diff --git a/non_linear_algebra/doc.txt b/non_linear_algebra/doc.txt
new file mode 100644
index 0000000000000000000000000000000000000000..f951b578fe82e29638a9ca07fea1180fd7dadac8
--- /dev/null
+++ b/non_linear_algebra/doc.txt
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2020 Zakaria Kasmi <zkasmi@inf.fu-berlin.de> 
+ *               2020 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser
+ * General Public License v2.1. See the file LICENSE in the top level
+ * directory for more details.
+ */
+
+/**
+ * @defgroup    non_linear_algebra NON_LINEAR_ALGEBRA
+ *
+ * @brief       Non-linear algebra operations
+ *
+ * @details The non-linear algebra module contains functions to solve multi-variant nonlinear 
+ *          equations as wells algorithms solving problems of regression smoothing and curve 
+ *          fitting. This module also enables enables the optimization of an approximate solution
+ *          by using Non-linear Least Squares (NLS) methods such as modified Gauss--Newton (GN) or 
+ *          the Levenberg--Marquardt (LVM) algorithms.
+ *
+ * @author  Zakaria Kasmi
+ */
diff --git a/non_linear_algebra/optimization/doc.txt b/non_linear_algebra/optimization/doc.txt
new file mode 100644
index 0000000000000000000000000000000000000000..6586aab419a7339ea355847f69cb4507a60309c8
--- /dev/null
+++ b/non_linear_algebra/optimization/doc.txt
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2020 Zakaria Kasmi <zkasmi@inf.fu-berlin.de> 
+ *               2020 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser
+ * General Public License v2.1. See the file LICENSE in the top level
+ * directory for more details.
+ */
+
+/**
+ * @defgroup    optimization OPTIMIZATION
+ * @ingroup     non_linear_algebra
+ *
+ * @brief       Solving problems of regression smoothing and curve fitting. 
+ *          
+ * @details     This module also enables the optimization of an 
+ *              approximate solution by using Non-linear Least Squares 
+ *              (NLS) methods such as modified Gauss--Newton (GN) or 
+ *              the Levenberg--Marquardt (LVM) algorithms.
+ *
+ * @author      Zakaria Kasmi
+ */
diff --git a/non_linear_algebra/optimization/include/levenberg_marquardt.h b/non_linear_algebra/optimization/include/levenberg_marquardt.h
new file mode 100644
index 0000000000000000000000000000000000000000..7d162a9a65a46b72f9717eaf9c8217a2ec7d38a9
--- /dev/null
+++ b/non_linear_algebra/optimization/include/levenberg_marquardt.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2020 Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ *               2020 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser General
+ * Public License v2.1. See the file LICENSE in the top level directory for more
+ * details.
+ */
+
+/**
+ * @ingroup     optimization
+ * @{
+ *
+ * @file
+ * @brief       Implement the Levenberg--Marquardt (LVM) algorithm.
+ * @note        This function is generally implemented.
+ *
+ * @author      Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ * @author      Naouar Guerchali
+ *
+ * @}
+ */
+
+#ifndef LEVENBERG_MARQUARDT_H_
+#define LEVENBERG_MARQUARDT_H_
+
+#include <inttypes.h>
+
+#include "matrix.h"
+#include "vector.h"
+
+/**
+ * @brief   Implements the Levenberg--Marquardt (LVM) algorithm.
+ * @details The user should provide pointers to the error and Jacobian functions.
+ * @note    This function is generally implemented.
+ *
+ * @param[in] f_length                 length of the error functions vector.
+ * @param[in] n                        length of the start vector.
+ * @param[in] x0_vec[]                 start vector.
+ * @param[in] data_vec[]               data vector.
+ * @param[in] eps                      accuracy bound.
+ * @param[in] tau                      \f$ \tau \f$ factor.
+ * @param[in] beta0                    \f$ \beta_0 \f$ factor.
+ * @param[in] beta1                    \f$ \beta_1 \f$ factor.
+ * @param[in] max_iter_num             maximal iteration number of the LVM algorithm.
+ * @param[out] est_x_vec[]             estimated (optimized) vector.
+ * @param[in] (*get_f_error)           pointer to the error function.
+ * @param[in] (*get_jacobian)          pointer to the Jacobian matrix.
+ *
+ * @return  required iteration number.
+ *
+ */
+uint8_t opt_levenberg_marquardt(uint8_t f_length, uint8_t n,
+                                vector_t x0_vec[n],
+                                vector_t data_vec[f_length],
+                                matrix_t eps, matrix_t tau, matrix_t beta0,
+                                matrix_t beta1,
+                                uint8_t max_iter_num,
+                                vector_t est_x_vec[n],
+                                void (*get_f_error)(vector_t x0_vec[],
+                                                    vector_t data_vec[],
+                                                    vector_t f_vec[]),
+                                void (*get_jacobian)(vector_t x0_vec[],
+                                                     matrix_t J[][n])
+                                );
+
+/**
+ * @brief   Compute the initial value \f$ \mu_0 \f$ of the Levenberg--Marquardt (LVM) algorithm.
+ * @details The user should provide a pointer to the matrix
+ *          \f$ J_f^{T} J_{f} \f$.
+ *
+ * @param[in] n          column number of the matrix \f$J_f^T J_f\f$.
+ * @param[in] tau        \f$ \tau \f$ factor.
+ * @param[in] JTJ[][]    pointer to the matrix \f$J_f^T J_f\f$.
+ *
+ * @return  parameter \f$ \rho_{\mu} \f$
+ */
+matrix_t opt_levenberg_marquardt_get_mu0(uint8_t n, matrix_t tau,
+                                         matrix_t JTJ[][n]);
+
+#endif /* LEVENBERG_MARQUARDT_H_ */
diff --git a/non_linear_algebra/optimization/include/modified_gauss_newton.h b/non_linear_algebra/optimization/include/modified_gauss_newton.h
new file mode 100644
index 0000000000000000000000000000000000000000..4182f9128efb6832982561a03ef84ca74b837185
--- /dev/null
+++ b/non_linear_algebra/optimization/include/modified_gauss_newton.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2020 Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ *               2020 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser General
+ * Public License v2.1. See the file LICENSE in the top level directory for more
+ * details.
+ */
+
+/**
+ * @ingroup     optimization
+ * @{
+ *
+ * @file
+ * @brief       Implement the Gauss--Newton algorithm.
+ * @note        This function is generally implemented.
+ *
+ * @author      Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ * @author      Abdelmoumen Norrdine <a.norrdine@googlemail.com>
+ *
+ * @}
+ */
+
+#ifndef MODIFIED_GAUSS_NEWTON_H_
+#define MODIFIED_GAUSS_NEWTON_H_
+
+#include <inttypes.h>
+
+#include "matrix.h"
+#include "vector.h"
+
+/**
+ * @brief   Implements the modified Gauss--Newton algorithm.
+ * @details The user should provide pointers to the error and Jacobian functions.
+ * @note    This function is generally implemented.
+ *
+ * @param[in] f_length                 length of the error functions vector.
+ * @param[in] n                        length of the start vector.
+ * @param[in] x0_vec[]                 start vector.
+ * @param[in] data_vec[]               data vector.
+ * @param[in] eps                      accuracy bound.
+ * @param[in] fmin                     termination tolerance on the error function.
+ * @param[in] max_iter_num             maximal iteration number of the Gauss--Newton algorithm.
+ * @param[out] est_x_vec[]             estimated (optimized) vector.
+ * @param[in] (*get_f_error)           pointer to the error function.
+ * @param[in] (*get_jacobian)          pointer to the Jacobian matrix.
+ *
+ * @return  required iteration number.
+ *
+ */
+uint8_t modified_gauss_newton(uint8_t f_length, uint8_t n,
+                              vector_t x0_vec[n],
+                              vector_t data_vec[f_length],
+                              matrix_t eps, matrix_t fmin, uint8_t max_iter_num,
+                              vector_t est_x_vec[n],
+                              void (*get_f_error)(vector_t x0_vec[],
+                                                  vector_t data_vec[],
+                                                  vector_t f_vec[]),
+                              void (*get_jacobian)(vector_t x0_vec[],
+                                                   matrix_t J[][n])
+                              );
+
+#endif /* MODIFIED_GAUSS_NEWTON_H_ */
diff --git a/non_linear_algebra/optimization/levenberg_marquardt.c b/non_linear_algebra/optimization/levenberg_marquardt.c
new file mode 100644
index 0000000000000000000000000000000000000000..d1ce59df0521de8d2c176c0617ad51f90ffddb13
--- /dev/null
+++ b/non_linear_algebra/optimization/levenberg_marquardt.c
@@ -0,0 +1,239 @@
+/*
+ * Copyright (C) 2020 Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ *               2020 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser General
+ * Public License v2.1. See the file LICENSE in the top level directory for more
+ * details.
+ */
+
+/**
+ * @{
+ *
+ * @file
+ * @brief       Implement the Levenberg--Marquardt (LVM) algorithm.
+ * @note        This function is generally implemented.
+ *
+ * @author      Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ * @author      Naouar Guerchali
+ *
+ * @}
+ */
+
+#include <stdio.h>
+#include <math.h>
+#include <float.h>
+#include <inttypes.h>
+
+#include "levenberg_marquardt.h"
+#include "matrix.h"
+#include "vector.h"
+#include "solve.h"
+#include "utils.h"
+
+/**
+ * @brief    Implements the correction-function of the Levenberg--Marquardt (LVM) algorithm.
+ * @details  The user should provide pointers to the error and Jacobian functions.
+ *
+ * @note     This function is generally implemented.
+ *
+ * @param[in] f_length                 length of the error functions vector.
+ * @param[in] n                        length of the start vector.
+ * @param[in] x_vec[]                  start vector.
+ * @param[in] data_vec[]               data vector.
+ * @param[in] mu                       regularization parameter \f$ \mu \f$.
+ * @param[out] s[]                     correction vector.
+ * @param[in] (*get_f_error)           pointer to the error function that calculates the matrix
+ *                                     \f$ J_f^{T} J_{f} \f$.
+ * @param[in] (*get_jacobian)          pointer to the Jacobian matrix.
+ *
+ *
+ * @return  the parameter \f$ \rho_{\mu} \f$
+ */
+matrix_t opt_levenberg_marquardt_correction(uint8_t f_length, uint8_t n,
+                                            matrix_t x_vec[n],
+                                            matrix_t data_vec[f_length],
+                                            matrix_t mu,
+                                            matrix_t s[n],
+                                            void (*get_f_error)(
+                                                vector_t x_vec[],
+                                                vector_t data_vec[],
+                                                vector_t f_vec[]),
+                                            void (*get_jacobian)(
+                                                vector_t x_vec[],
+                                                matrix_t J[][n])
+                                            )
+{
+
+    matrix_t Fx[f_length];
+    matrix_t J[f_length][n];
+    vector_t f_vec[f_length];
+    matrix_t JTJ_mu2_I[n][n];
+    vector_t JTF[n];
+    matrix_t ro_mu = 0;
+    matrix_t Fx_square = 0;
+    matrix_t Fx_plus_s_square = 0;
+    matrix_t Fx_plus_J_mul_s_square = 0;
+    vector_t Fx_plus_J_mul_s[f_length];
+    vector_t F_x_plus_s[f_length];
+    vector_t x_plus_s[n];
+    matrix_t denom;
+
+    /*
+     * compute: -(J'J + mu^2*I)
+     */
+    //JT_J = J'*J
+    get_jacobian(x_vec, J);
+
+    //store J'J in JTJ_mu2_I
+    matrix_trans_mul_itself(f_length, n, J, JTJ_mu2_I);
+
+    //compute: J'J + mu^2*I
+    matrix_add_to_diag(n, JTJ_mu2_I, n, pow(mu, 2));
+
+    // -(J'*J+mu^2*eye(n)), is an (nxn) matrix
+    matrix_mul_scalar(n, n, JTJ_mu2_I, -1, JTJ_mu2_I);
+
+    //JT_f = J'*f
+    get_f_error(x_vec, data_vec, f_vec);
+    matrix_trans_mul_vec(f_length, n, J, f_length, f_vec, JTF);
+
+    //solve the equation: s = -(J'*J+mu^2*I)\(J'*Fx);
+    solve_householder(n, n, JTJ_mu2_I, JTF, s);
+
+    //f(x)
+    get_f_error(x_vec, data_vec, Fx);
+
+    //f(x)^2
+    Fx_square = vector_get_scalar_product(f_length, Fx, Fx);
+
+    //(x+s)
+    vector_add(n, x_vec, s, x_plus_s);
+
+    //f(x+s)
+    get_f_error(x_plus_s, data_vec, F_x_plus_s);
+
+    //f(x+s)^2
+    Fx_plus_s_square = vector_get_scalar_product(f_length, F_x_plus_s,
+                                                 F_x_plus_s);
+
+    //compute: J(x)*s
+    matrix_mul_vec(f_length, n, J, s, Fx_plus_J_mul_s);
+
+    //compute: f(x) + J(x)*s
+    vector_add(f_length, Fx, Fx_plus_J_mul_s, Fx_plus_J_mul_s);
+
+    //compute: ||f(x) + J(x)*s||^2
+    Fx_plus_J_mul_s_square = vector_get_scalar_product(f_length,
+                                                       Fx_plus_J_mul_s,
+                                                       Fx_plus_J_mul_s);
+
+    denom = Fx_square - Fx_plus_J_mul_s_square;
+    if (denom != 0) {
+        ro_mu = (Fx_square - Fx_plus_s_square) / denom;
+    }
+    else {
+        puts("ro_mu is infinite !!!");
+        ro_mu = FLT_MAX;
+    }
+
+    return ro_mu;
+}
+
+uint8_t opt_levenberg_marquardt(uint8_t f_length, uint8_t n,
+                                vector_t x0_vec[n],
+                                vector_t data_vec[f_length],
+                                matrix_t eps, matrix_t tau, matrix_t beta0,
+                                matrix_t beta1,
+                                uint8_t max_iter_num,
+                                vector_t est_x_vec[n],
+                                void (*get_f_error)(vector_t x0_vec[],
+                                                    vector_t data_vec[],
+                                                    vector_t f_vec[]),
+                                void (*get_jacobian)(vector_t x0_vec[],
+                                                     matrix_t J[][n])
+                                )
+{
+    matrix_t J[f_length][n];
+    vector_t JT_f[n];
+    matrix_t JTJ_mu2_I[n][n];
+    vector_t s[n];
+    vector_t f_vec[f_length];
+    matrix_t mu;
+    matrix_t ro_mu;
+    uint8_t it;
+
+    /*
+     * compute mu0 and -(J'J + mu0^2*I)
+     */
+    //JT_J = J'*J
+    get_jacobian(x0_vec, J);
+
+    //store J'J in JTJ_mu2_I
+    matrix_trans_mul_itself(f_length, n, J, JTJ_mu2_I);
+
+    // compute mu_0: mu = mu_0
+    mu = opt_levenberg_marquardt_get_mu0(n, tau, JTJ_mu2_I);
+
+    //compute: J'J + mu0^2*I
+    matrix_add_to_diag(n, JTJ_mu2_I, n, pow(mu, 2));
+
+    //-(J'*J+mu0^2*eye(n)) is a (n,n) matrix
+    matrix_mul_scalar(n, n, JTJ_mu2_I, -1, JTJ_mu2_I);
+
+    //compute JTF: JT_f = J'*f
+    get_f_error(x0_vec, data_vec, f_vec);
+    matrix_trans_mul_vec(f_length, n, J, f_length, f_vec, JT_f);
+
+    //solve the equation: s=-(J'*J+mu^2*eye(n))\(J'*F);
+    solve_householder(n, n, JTJ_mu2_I, JT_f, s);
+
+    vector_copy(n, x0_vec, est_x_vec);
+
+    it = 0;
+    while ((vector_get_norm2(n, s)
+            > eps * (1 + vector_get_norm2(n, est_x_vec)))
+           && (it < max_iter_num)) {   //norm(s,2)>eps*(1+norm(x,2))
+
+        ro_mu = opt_levenberg_marquardt_correction(f_length, n,
+                                                   est_x_vec, data_vec,
+                                                   mu, s, get_f_error,
+                                                   get_jacobian);
+
+        while (1) {
+            if (ro_mu <= beta0) {
+                mu = 2.0 * mu;
+                ro_mu = opt_levenberg_marquardt_correction(
+                    f_length, n,
+                    est_x_vec,
+                    data_vec, mu, s, get_f_error,
+                    get_jacobian);
+            }
+            else if (ro_mu >= beta1) {
+                mu = mu / 2.0;
+                break;
+            }
+            else {
+                break;
+            }
+        }
+        vector_add(n, est_x_vec, s, est_x_vec);
+        it = it + 1;
+    } //while
+
+    return it;
+}
+
+matrix_t opt_levenberg_marquardt_get_mu0(uint8_t n, matrix_t tau,
+                                         matrix_t JTJ[][n])
+{
+    matrix_t max_diag_JTJ = JTJ[0][0];
+
+    for (uint8_t i = 1; i < n; i++) {
+        if (JTJ[i][i] > max_diag_JTJ) {
+            max_diag_JTJ = JTJ[i][i];
+        }
+    }
+
+    return tau * max_diag_JTJ;
+}
diff --git a/non_linear_algebra/optimization/modified_gauss_newton.c b/non_linear_algebra/optimization/modified_gauss_newton.c
new file mode 100644
index 0000000000000000000000000000000000000000..37a40c10901fe81cfa7bdd6f640e82f514793f4c
--- /dev/null
+++ b/non_linear_algebra/optimization/modified_gauss_newton.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2020 Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ *               2020 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser General
+ * Public License v2.1. See the file LICENSE in the top level directory for more
+ * details.
+ */
+
+/**
+ * @{
+ *
+ * @file
+ * @brief       Implement the Gauss--Newton algorithm.
+ * @note        This function is generally implemented.
+ *
+ * @author      Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ * @author      Abdelmoumen Norrdine <a.norrdine@googlemail.com>
+ *
+ * @}
+ */
+
+#include <stdio.h>
+#include <math.h>
+
+#include "utils.h"
+#include "matrix.h"
+#include "vector.h"
+#include "moore_penrose_pseudo_inverse.h"
+
+//n is the size of x0 that is equal to the column number of J
+uint8_t modified_gauss_newton(uint8_t f_length, uint8_t n,
+                              vector_t x0_vec[n],
+                              vector_t data_vec[f_length],
+                              matrix_t eps, matrix_t fmin, uint8_t max_iter_num,
+                              vector_t est_x_vec[n],
+                              void (*get_f_error)(vector_t x0_vec[],
+                                                  vector_t data_vec[],
+                                                  vector_t f_vec[]),
+                              void (*get_jacobian)(vector_t x0_vec[],
+                                                   matrix_t J[][n])
+                              )
+
+{
+    matrix_t J[f_length][n];
+    matrix_t JT_J[n][n];
+    matrix_t JT_f[n];
+    vector_t f_vec[f_length];
+    matrix_t f_error;
+    matrix_t pinv_JTJ_mat[n][n];
+    vector_t correction_vec[n];
+    vector_t x_vec[n];
+    vector_t next_x_vec[n];
+    matrix_t max_error, min_error;
+    matrix_t step;
+    uint8_t iter_num;
+
+    get_f_error(x0_vec, data_vec, f_vec);
+    f_error = vector_get_norm2(f_length, f_vec);
+    max_error = f_error;
+    min_error = max_error;
+    step = eps;
+
+    vector_copy(n, x0_vec, x_vec);
+    vector_copy(n, x0_vec, est_x_vec);
+    iter_num = 0;
+
+    while ((step >= eps) && (iter_num < max_iter_num) && (f_error > fmin)) {
+        /*
+         * Compute then correction terms & next x_vec values
+         */
+        //JT_J = J'*J
+        get_jacobian(x_vec, J);
+        matrix_trans_mul_itself(f_length, n, J, JT_J);
+
+        //JT_f = J'*f
+        get_f_error(x_vec, data_vec, f_vec);
+        matrix_trans_mul_vec(f_length, n, J, f_length, f_vec, JT_f);
+
+        //solve: J'J*s = -J'*f
+        moore_penrose_get_pinv(n, n, JT_J, pinv_JTJ_mat);
+        //s = (J'J)\J'*f
+        matrix_mul_vec(n, n, pinv_JTJ_mat, JT_f, correction_vec);
+
+        // x = x - s
+        vector_sub(n, x_vec, correction_vec, next_x_vec);
+
+        //next step
+        step = vector_get_euclidean_distance(n, x_vec, next_x_vec);
+
+        // x_vec = next_x_vec
+        vector_copy(n, next_x_vec, x_vec);
+
+        //error vector
+        get_f_error(x_vec, data_vec, f_vec);
+
+        f_error = vector_get_norm2(f_length, f_vec);
+
+        if (min_error > f_error) {  //store the x_vec value with the minimum error in est_x_vec
+            vector_copy(n, x_vec, est_x_vec);
+            min_error = f_error;    // update min_error
+        }
+
+        max_error = utils_max(f_error, max_error); // update max_error
+        iter_num++;
+        if ((max_error - min_error) > 10) {
+            break;
+        }
+
+    } //while
+
+    return iter_num;
+}
diff --git a/non_linear_algebra/solve_non_linear_equations/damped_newton_raphson.c b/non_linear_algebra/solve_non_linear_equations/damped_newton_raphson.c
new file mode 100644
index 0000000000000000000000000000000000000000..6833629a510932da9ad7fe7b7075620c74071363
--- /dev/null
+++ b/non_linear_algebra/solve_non_linear_equations/damped_newton_raphson.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2020 Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ *               2020 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser General
+ * Public License v2.1. See the file LICENSE in the top level directory for more
+ * details.
+ */
+
+/**
+ * @{
+ *
+ * @file
+ * @brief       Implement the damped Newton--Raphson algorithm.
+ * @details     The damped Newton--Raphson algorithm enables to solve
+ *              multi-variant nonlinear equation systems.
+ *
+ * @author      Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ *
+ * @}
+ */
+
+#include <stdio.h>
+
+#include "moore_penrose_pseudo_inverse.h"
+#include "damped_newton_raphson.h"
+#include "vector.h"
+#include "matrix.h"
+
+//Multivariate Newton�s Method
+//n is the size of x0 that is equal to the column number of J
+uint8_t damped_newton_raphson(uint8_t f_length, uint8_t n, vector_t x0_arr[],
+                              double min_lamda, double eps, uint8_t max_it_num,
+                              vector_t est_x_arr[],
+                              void (*get_non_lin_sys)(vector_t x_arr[],
+                                                      vector_t f_vec[]),
+                              void (*get_jacobian)(vector_t x_arr[],
+                                                   matrix_t J[][n]))
+{
+    uint8_t iter_num;
+    double lamda;
+    double lamda_c;
+    double damped_norm_x;
+    double damped_norm_prev_x;
+    vector_t prev_x_arr[n];
+    vector_t delta_x[n];
+    vector_t lamda_mul_delta_x[n];
+
+    damped_norm_x = get_damped_norm(f_length, n, x0_arr, get_non_lin_sys,
+                                    get_jacobian);
+    iter_num = 0;
+    vector_copy(n, x0_arr, prev_x_arr);
+    while ((damped_norm_x >= eps) && (iter_num < max_it_num)) {
+
+        get_delta_x(f_length, n, prev_x_arr, get_non_lin_sys,
+                    get_jacobian, delta_x);
+        lamda = 1.0;
+
+        // x = x_k +lamda*s_k (lamda=1)
+        vector_add(n, prev_x_arr, delta_x, est_x_arr);
+
+        lamda_c = 1 - lamda / 4;
+        //|||f(x)|||_k
+        damped_norm_x = get_damped_norm(f_length, n, est_x_arr,
+                                        get_non_lin_sys, get_jacobian);
+
+        //|||f(prev_x)|||_k
+        damped_norm_prev_x = vector_get_norm2(n, delta_x);
+
+        while (damped_norm_x > (lamda_c * damped_norm_prev_x)) {
+            lamda = lamda / 2;
+            if (lamda >= min_lamda) {
+                //x = x_k +lamda*s_k
+                vector_scalar_mul(n, delta_x, lamda,
+                                  lamda_mul_delta_x);
+                vector_add(n, prev_x_arr, lamda_mul_delta_x,
+                           est_x_arr);
+            }
+            else {
+                break;
+            }
+            // |||f(x)|||_k
+            damped_norm_x = get_damped_norm(f_length, n, est_x_arr,
+                                            get_non_lin_sys, get_jacobian);
+
+        } //while
+
+        if (lamda <= min_lamda) {
+            break;
+        }
+
+        //update prev_x
+        vector_copy(n, est_x_arr, prev_x_arr);
+
+        // |||f(x)|||_k
+        damped_norm_x = get_damped_norm(f_length, n, est_x_arr,
+                                        get_non_lin_sys, get_jacobian);
+        iter_num++;
+    }
+
+    return iter_num;
+}
+
+double get_damped_norm(uint8_t m, uint8_t n, vector_t x_arr[],
+                       void (*get_non_lin_sys)(vector_t x_arr[],
+                                               vector_t f_vec[]),
+                       void (*get_jacobian)(vector_t x_arr[], matrix_t J[][n])
+                       )
+{
+    double damp_norm = 0.0;
+    vector_t delta_x_arr[n];
+
+    get_delta_x(m, n, x_arr, get_non_lin_sys, get_jacobian, delta_x_arr);
+    damp_norm = vector_get_norm2(n, delta_x_arr);
+
+    return damp_norm;
+}
+
+//Computes the correction vector.
+void get_delta_x(uint8_t m, uint8_t n, vector_t x_arr[],
+                 void (*get_non_lin_sys)(vector_t x_arr[], vector_t f_vec[]),
+                 void (*get_jacobian)(vector_t x_arr[], matrix_t J[][n]),
+                 vector_t delta_x_arr[])
+{
+    matrix_t J[m][n];
+    matrix_t pinv_J[n][m];
+    vector_t f_vec[m];
+
+    // compute the Jacobian matrix for the vector x_arr.
+    get_jacobian(x_arr, J);
+    // compute the inverse of J (J^-1)
+    moore_penrose_get_pinv(m, n, J, pinv_J);
+    // compute the value of f(x)
+    get_non_lin_sys(x_arr, f_vec);
+    //delta_x = J1^-1*f(x)
+    matrix_mul_vec(n, m, pinv_J, f_vec, delta_x_arr);
+    vector_in_place_scalar_mul(n, delta_x_arr, -1);
+}
diff --git a/non_linear_algebra/solve_non_linear_equations/doc.txt b/non_linear_algebra/solve_non_linear_equations/doc.txt
new file mode 100644
index 0000000000000000000000000000000000000000..a2d1bec0745f4226061e8e85eb858847bfddc43c
--- /dev/null
+++ b/non_linear_algebra/solve_non_linear_equations/doc.txt
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2020 Zakaria Kasmi <zkasmi@inf.fu-berlin.de> 
+ *               2020 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser
+ * General Public License v2.1. See the file LICENSE in the top level
+ * directory for more details.
+ */
+
+/**
+ * @defgroup    solve_non_linear_equations SOLVE_NON_LINEAR_EQUATIONS
+ * @ingroup     non_linear_algebra
+ *
+ * @brief       Enables to solve multi-variant nonlinear equation systems.
+ *
+ * @details     The multi-variant nonlinear equation systems are solved using 
+ *              damped or the Newton--Raphson algorithms.
+ *
+ * @author      Zakaria Kasmi
+ */
diff --git a/non_linear_algebra/solve_non_linear_equations/fsolve.c b/non_linear_algebra/solve_non_linear_equations/fsolve.c
new file mode 100644
index 0000000000000000000000000000000000000000..3b55379ec546270ac17b2aa8426d89086d739afe
--- /dev/null
+++ b/non_linear_algebra/solve_non_linear_equations/fsolve.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2020 Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ *               2020 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser General
+ * Public License v2.1. See the file LICENSE in the top level directory for more
+ * details.
+ */
+
+/**
+ * @{
+ *
+ * @file
+ * @brief       Solve multi-variant nonlinear equation systems.
+ * @details     The multi-variant nonlinear equation systems are solved using
+ *              damped or the Newton--Raphson algorithms.
+ *
+ * @author      Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ *
+ * @}
+ */
+
+#include "vector.h"
+#include "matrix.h"
+#include "fsolve.h"
+#include "newton_raphson.h"
+#include "damped_newton_raphson.h"
+
+uint8_t fsolve(uint8_t f_length, uint8_t x0_length, vector_t x0_arr[],
+               enum NON_LIN_ALGORITHM algo, vector_t est_x_arr[],
+               void (*get_non_lin_sys)(vector_t x_arr[], vector_t f_vec[]),
+               void (*get_jacobian)(vector_t x_arr[], matrix_t J[][x0_length]))
+{
+    double tol = 1e-9;
+    uint8_t max_it_num = 77;
+    uint8_t iter_num = 0;
+
+    switch (algo) {
+        case Newton_Raphson:
+            iter_num = newton_raphson(f_length, x0_length, x0_arr, tol,
+                                      max_it_num,
+                                      est_x_arr, get_non_lin_sys, get_jacobian);
+            break;
+
+        case Damped_Newton_Raphson:
+        {
+            double min_lamda = 4.8828125e-04;
+            iter_num = damped_newton_raphson(f_length, x0_length, x0_arr,
+                                             min_lamda,
+                                             tol, max_it_num, est_x_arr,
+                                             get_non_lin_sys, get_jacobian);
+            break;
+        }
+
+        default:
+            iter_num = newton_raphson(f_length, x0_length, x0_arr, tol,
+                                      max_it_num,
+                                      est_x_arr, get_non_lin_sys, get_jacobian);
+    }
+
+    return iter_num;
+}
diff --git a/non_linear_algebra/solve_non_linear_equations/include/damped_newton_raphson.h b/non_linear_algebra/solve_non_linear_equations/include/damped_newton_raphson.h
new file mode 100644
index 0000000000000000000000000000000000000000..1fd9806e2f0b4a3e1a63e72903b5ae4ff1c4f45d
--- /dev/null
+++ b/non_linear_algebra/solve_non_linear_equations/include/damped_newton_raphson.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2020 Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ *               2020 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser General
+ * Public License v2.1. See the file LICENSE in the top level directory for more
+ * details.
+ */
+
+/**
+ * @ingroup     solve_non_linear_equations
+ * @{
+ *
+ * @file
+ * @brief       Implement the damped Newton--Raphson algorithm.
+ * @details     The damped Newton--Raphson algorithm enables to solve
+ *              multi-variant nonlinear equation systems.
+ *
+ * @author      Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ *
+ * @}
+ */
+
+#ifndef DAMPED_NEWTON_RAPHSON_H_
+#define DAMPED_NEWTON_RAPHSON_H_
+
+#include "matrix.h"
+#include "vector.h"
+
+/**
+ * @brief   Implements the damped Newton--Raphson algorithm.
+ * @details The user should provide pointers to non-linear equation systems and Jacobian functions.
+ * @note    This function is generally implemented.
+ *
+ * @param[in] f_length                 length of the error functions vector.
+ * @param[in] n                        length of the start vector.
+ * @param[in] x0_arr[]                 start vector.
+ * @param[in] min_lamda                minimal damping factor.
+ * @param[in] eps                      accuracy bound.
+ * @param[in] max_it_num               maximal iteration number of the damped Newton--Raphson
+ *                                     algorithm.
+ * @param[out] est_x_arr[]             estimated (solution) vector.
+ * @param[in] (*get_non_lin_sys)       pointer to non-linear equation systems.
+ * @param[in] (*get_jacobian)          pointer to the Jacobian matrix.
+ *
+ * @return  required iteration number.
+ *
+ */
+uint8_t damped_newton_raphson(uint8_t f_length, uint8_t n, vector_t x0_arr[],
+                              double min_lamda, double eps, uint8_t max_it_num,
+                              vector_t est_x_arr[],
+                              void (*get_non_lin_sys)(vector_t x_arr[],
+                                                      vector_t f_vec[]),
+                              void (*get_jacobian)(vector_t x_arr[],
+                                                   matrix_t J[][n]));
+/**
+ * @brief   Compute the norm of the damped Newton--Raphson algorithm.
+ * @details The user should provide pointers to non-linear equation systems and Jacobian functions.
+ * @note    This function is generally implemented.
+ *
+ * @param[in] m                        number of the non-linear equations.
+ * @param[in] n                        length of the guess vector.
+ * @param[in] x_arr[]                  guess vector.
+ * @param[in] (*get_non_lin_sys)       pointer to non-linear equation systems.
+ * @param[in] (*get_jacobian)          pointer to the Jacobian matrix.
+ *
+ * @return  norm of the damped Newton--Raphson algorithm.
+ *
+ */
+double get_damped_norm(uint8_t m, uint8_t n, vector_t x_arr[],
+                       void (*get_non_lin_sys)(vector_t x_arr[],
+                                               vector_t f_vec[]),
+                       void (*get_jacobian)(vector_t x_arr[], matrix_t J[][n])
+                       );
+
+/**
+ * @brief   Compute the correction vector the damped Newton--Raphson algorithm.
+ * @details The user should provide pointers to non-linear equation systems and Jacobian functions.
+ * @note    This function is generally implemented.
+ *
+ * @param[in] m                        number of the non-linear equations.
+ * @param[in] n                        length of the guess vector.
+ * @param[in] x_arr[]                  guess vector.
+ * @param[in] (*get_non_lin_sys)       pointer to non-linear equation systems.
+ * @param[in] (*get_jacobian)          pointer to the Jacobian matrix.
+ * @param[in, out] delta_x_arr[]       the correction vector (term).
+ *
+ */
+void get_delta_x(uint8_t m, uint8_t n, vector_t x_arr[],
+                 void (*get_non_lin_sys)(vector_t x_arr[], vector_t f_vec[]),
+                 void (*get_jacobian)(vector_t x_arr[], matrix_t J[][n]),
+                 vector_t delta_x_arr[]);
+
+#endif /* DAMPED_NEWTON_RAPHSON_H_ */
diff --git a/non_linear_algebra/solve_non_linear_equations/include/fsolve.h b/non_linear_algebra/solve_non_linear_equations/include/fsolve.h
new file mode 100644
index 0000000000000000000000000000000000000000..35f27cb8b1b84f38aff9514f65c87e79a6159c1e
--- /dev/null
+++ b/non_linear_algebra/solve_non_linear_equations/include/fsolve.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2020 Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ *               2020 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser General
+ * Public License v2.1. See the file LICENSE in the top level directory for more
+ * details.
+ */
+
+/**
+ * @ingroup     solve_non_linear_equations
+ * @{
+ *
+ * @file
+ * @brief       Solve multi-variant nonlinear equation systems.
+ * @details     The multi-variant nonlinear equation systems are solved using
+ *              damped or the Newton--Raphson algorithms.
+ *
+ * @author      Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ *
+ * @}
+ */
+
+#ifndef FSOLVE_H_
+#define FSOLVE_H_
+
+/**
+ * Possible algorithms to solve multi-variant nonlinear equation systems.
+ */
+enum NON_LIN_ALGORITHM {
+    Newton_Raphson,         /**< Newton--Raphson algorithm */
+    Damped_Newton_Raphson   /**< Damped Newton--Raphson algorithm */
+};
+
+/**
+ * @brief   Solve systems of multi-variant nonlinear equations.
+ *  @details The user should provide pointers to non-linear equation systems and Jacobian functions.
+ *           The user can choose between the damped or the Newton--Raphson algorithms.
+ *
+ * @note    This function is generally implemented.
+ *
+ * @param[in] f_length                 length of the error functions vector.
+ * @param[in] x0_length                length of the start vector.
+ * @param[in] x0_arr[]                 start vector.
+ * @param[in] algo                     damped or the Newton--Raphson algorithm.
+ * @param[in, out] est_x_arr[]         estimated (solution) vector.
+ * @param[in] (*get_non_lin_sys)       pointer to non-linear equation systems.
+ * @param[in] (*get_jacobian)          pointer to the Jacobian matrix.
+ *
+ * @return  required iteration number.
+ *
+ */
+uint8_t fsolve(uint8_t f_length, uint8_t x0_length, vector_t x0_arr[],
+               enum NON_LIN_ALGORITHM algo, vector_t est_x_arr[],
+               void (*get_non_lin_sys)(vector_t x_arr[], vector_t f_vec[]),
+               void (*get_jacobian)(vector_t x_arr[], matrix_t J[][x0_length]));
+
+#endif /* FSOLVE_H_ */
diff --git a/non_linear_algebra/solve_non_linear_equations/include/newton_raphson.h b/non_linear_algebra/solve_non_linear_equations/include/newton_raphson.h
new file mode 100644
index 0000000000000000000000000000000000000000..2a5edf98fb7cec0e133cc11b329b6c7ad511d18d
--- /dev/null
+++ b/non_linear_algebra/solve_non_linear_equations/include/newton_raphson.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2020 Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ *               2020 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser General
+ * Public License v2.1. See the file LICENSE in the top level directory for more
+ * details.
+ */
+
+/**
+ * @ingroup     solve_non_linear_equations
+ * @{
+ *
+ * @file
+ * @brief       Implement the Newton--Raphson algorithm.
+ * @details     The Newton--Raphson algorithm enables to solve
+ *              multi-variant nonlinear equation systems.
+ *
+ * @author      Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ *
+ * @}
+ */
+#ifndef NEWTON_RAPHSON_H_
+#define NEWTON_RAPHSON_H_
+
+#include <inttypes.h>
+
+#include "vector.h"
+#include "matrix.h"
+
+/**
+ * @brief   Implements the Newton--Raphson algorithm.
+ * @details The user should provide pointers to non-linear equation systems and Jacobian functions.
+ * @note    This function is generally implemented.
+ *
+ * @param[in] f_length                 length of the error functions vector.
+ * @param[in] n                        length of the start vector.
+ * @param[in] x0_arr[]                 start vector.
+ * @param[in] eps                      accuracy bound.
+ * @param[in] max_it_num               maximal iteration number of the Newton--Raphson algorithm.
+ * @param[out] est_x_arr[]             estimated (solution) vector.
+ * @param[in] (*get_non_lin_sys)       pointer to non-linear equation systems.
+ * @param[in] (*get_jacobian)          pointer to the Jacobian matrix.
+ *
+ * @return  required iteration number.
+ *
+ */
+uint8_t newton_raphson(uint8_t f_length, uint8_t n, vector_t x0_arr[],
+                       double eps, uint8_t max_it_num, vector_t est_x_arr[],
+                       void (*get_non_lin_sys)(vector_t x_arr[], vector_t f_vec[]),
+                       void (*get_jacobian)(vector_t x_arr[], matrix_t J[][n]));
+
+#endif /* NEWTON_RAPHSON_H_ */
diff --git a/non_linear_algebra/solve_non_linear_equations/newton_raphson.c b/non_linear_algebra/solve_non_linear_equations/newton_raphson.c
new file mode 100644
index 0000000000000000000000000000000000000000..fd07c893755792ec9f7b6ca4c7bd6b698839c123
--- /dev/null
+++ b/non_linear_algebra/solve_non_linear_equations/newton_raphson.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2020 Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ *               2020 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser General
+ * Public License v2.1. See the file LICENSE in the top level directory for more
+ * details.
+ */
+
+/**
+ * @{
+ *
+ * @file
+ * @brief       Implement the Newton--Raphson algorithm.
+ * @details     The Newton--Raphson algorithm enables to solve
+ *              multi-variant nonlinear equation systems.
+ *
+ * @author      Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
+ *
+ * @}
+ */
+
+#include "vector.h"
+#include "matrix.h"
+#include "moore_penrose_pseudo_inverse.h"
+
+//n is the size of x0 that is equal to the column number of J
+uint8_t newton_raphson(uint8_t f_length, uint8_t n, vector_t x0_arr[],
+                       double eps, uint8_t max_it_num, vector_t est_x_arr[],
+                       void (*get_non_lin_sys)(vector_t x_arr[],
+                                               vector_t f_vec[]),
+                       void (*get_jacobian)(vector_t x_arr[], matrix_t J[][n]))
+{
+    uint8_t iter_num;
+    double step;
+    vector_t prev_x_arr[n];
+    matrix_t J[f_length][n];
+    matrix_t pinv_J[n][f_length];
+    vector_t delta_x[n];
+    vector_t f_vec[f_length];
+
+    vector_copy(n, x0_arr, prev_x_arr);
+    step = eps;
+    iter_num = 0;
+
+    while ((step >= eps) && (iter_num < max_it_num)) {
+        // compute the Jacobian matrix for the prev_x_arr.
+        get_jacobian(prev_x_arr, J);
+        // compute the inverse of J (J^-1)
+        moore_penrose_get_pinv(f_length, n, J, pinv_J);
+        // compute the value of f(x)
+        get_non_lin_sys(prev_x_arr, f_vec);
+        //delta_x = J1^-1*f(x)
+        matrix_mul_vec(n, f_length, pinv_J, f_vec, delta_x);
+        //improve x: x = x - delta_x
+        vector_sub(n, prev_x_arr, delta_x, est_x_arr);
+        //next step
+        step = vector_get_euclidean_distance(n, est_x_arr, prev_x_arr);
+        //update prev_x
+        vector_copy(n, est_x_arr, prev_x_arr);
+        iter_num++;
+    }
+
+    return iter_num;
+}