diff --git a/contrib/lbfgs/solvers.cpp b/contrib/lbfgs/solvers.cpp
new file mode 100755
index 0000000000000000000000000000000000000000..595486b309f676d0fd0c3d51cfe3d2b8e1564ca1
--- /dev/null
+++ b/contrib/lbfgs/solvers.cpp
@@ -0,0 +1,5665 @@
+/*************************************************************************
+Copyright (c) Sergey Bochkanov (ALGLIB project).
+
+>>> SOURCE LICENSE >>>
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation (www.fsf.org); either version 2 of the
+License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+A copy of the GNU General Public License is available at
+http://www.fsf.org/licensing/licenses
+>>> END OF LICENSE >>>
+*************************************************************************/
+#include "stdafx.h"
+#include "solvers.h"
+
+// disable some irrelevant warnings
+#if (AE_COMPILER==AE_MSVC)
+#pragma warning(disable:4100)
+#pragma warning(disable:4127)
+#pragma warning(disable:4702)
+#pragma warning(disable:4996)
+#endif
+using namespace std;
+
+/////////////////////////////////////////////////////////////////////////
+//
+// THIS SECTION CONTAINS IMPLEMENTATION OF C++ INTERFACE
+//
+/////////////////////////////////////////////////////////////////////////
+namespace alglib
+{
+
+
+/*************************************************************************
+
+*************************************************************************/
+_densesolverreport_owner::_densesolverreport_owner()
+{
+    p_struct = (alglib_impl::densesolverreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::densesolverreport), NULL);
+    if( p_struct==NULL )
+        throw ap_error("ALGLIB: malloc error");
+    if( !alglib_impl::_densesolverreport_init(p_struct, NULL, ae_false) )
+        throw ap_error("ALGLIB: malloc error");
+}
+
+_densesolverreport_owner::_densesolverreport_owner(const _densesolverreport_owner &rhs)
+{
+    p_struct = (alglib_impl::densesolverreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::densesolverreport), NULL);
+    if( p_struct==NULL )
+        throw ap_error("ALGLIB: malloc error");
+    if( !alglib_impl::_densesolverreport_init_copy(p_struct, const_cast<alglib_impl::densesolverreport*>(rhs.p_struct), NULL, ae_false) )
+        throw ap_error("ALGLIB: malloc error");
+}
+
+_densesolverreport_owner& _densesolverreport_owner::operator=(const _densesolverreport_owner &rhs)
+{
+    if( this==&rhs )
+        return *this;
+    alglib_impl::_densesolverreport_clear(p_struct);
+    if( !alglib_impl::_densesolverreport_init_copy(p_struct, const_cast<alglib_impl::densesolverreport*>(rhs.p_struct), NULL, ae_false) )
+        throw ap_error("ALGLIB: malloc error");
+    return *this;
+}
+
+_densesolverreport_owner::~_densesolverreport_owner()
+{
+    alglib_impl::_densesolverreport_clear(p_struct);
+    ae_free(p_struct);
+}
+
+alglib_impl::densesolverreport* _densesolverreport_owner::c_ptr()
+{
+    return p_struct;
+}
+
+alglib_impl::densesolverreport* _densesolverreport_owner::c_ptr() const
+{
+    return const_cast<alglib_impl::densesolverreport*>(p_struct);
+}
+densesolverreport::densesolverreport() : _densesolverreport_owner() ,r1(p_struct->r1),rinf(p_struct->rinf)
+{
+}
+
+densesolverreport::densesolverreport(const densesolverreport &rhs):_densesolverreport_owner(rhs) ,r1(p_struct->r1),rinf(p_struct->rinf)
+{
+}
+
+densesolverreport& densesolverreport::operator=(const densesolverreport &rhs)
+{
+    if( this==&rhs )
+        return *this;
+    _densesolverreport_owner::operator=(rhs);
+    return *this;
+}
+
+densesolverreport::~densesolverreport()
+{
+}
+
+
+/*************************************************************************
+
+*************************************************************************/
+_densesolverlsreport_owner::_densesolverlsreport_owner()
+{
+    p_struct = (alglib_impl::densesolverlsreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::densesolverlsreport), NULL);
+    if( p_struct==NULL )
+        throw ap_error("ALGLIB: malloc error");
+    if( !alglib_impl::_densesolverlsreport_init(p_struct, NULL, ae_false) )
+        throw ap_error("ALGLIB: malloc error");
+}
+
+_densesolverlsreport_owner::_densesolverlsreport_owner(const _densesolverlsreport_owner &rhs)
+{
+    p_struct = (alglib_impl::densesolverlsreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::densesolverlsreport), NULL);
+    if( p_struct==NULL )
+        throw ap_error("ALGLIB: malloc error");
+    if( !alglib_impl::_densesolverlsreport_init_copy(p_struct, const_cast<alglib_impl::densesolverlsreport*>(rhs.p_struct), NULL, ae_false) )
+        throw ap_error("ALGLIB: malloc error");
+}
+
+_densesolverlsreport_owner& _densesolverlsreport_owner::operator=(const _densesolverlsreport_owner &rhs)
+{
+    if( this==&rhs )
+        return *this;
+    alglib_impl::_densesolverlsreport_clear(p_struct);
+    if( !alglib_impl::_densesolverlsreport_init_copy(p_struct, const_cast<alglib_impl::densesolverlsreport*>(rhs.p_struct), NULL, ae_false) )
+        throw ap_error("ALGLIB: malloc error");
+    return *this;
+}
+
+_densesolverlsreport_owner::~_densesolverlsreport_owner()
+{
+    alglib_impl::_densesolverlsreport_clear(p_struct);
+    ae_free(p_struct);
+}
+
+alglib_impl::densesolverlsreport* _densesolverlsreport_owner::c_ptr()
+{
+    return p_struct;
+}
+
+alglib_impl::densesolverlsreport* _densesolverlsreport_owner::c_ptr() const
+{
+    return const_cast<alglib_impl::densesolverlsreport*>(p_struct);
+}
+densesolverlsreport::densesolverlsreport() : _densesolverlsreport_owner() ,r2(p_struct->r2),cx(&p_struct->cx),n(p_struct->n),k(p_struct->k)
+{
+}
+
+densesolverlsreport::densesolverlsreport(const densesolverlsreport &rhs):_densesolverlsreport_owner(rhs) ,r2(p_struct->r2),cx(&p_struct->cx),n(p_struct->n),k(p_struct->k)
+{
+}
+
+densesolverlsreport& densesolverlsreport::operator=(const densesolverlsreport &rhs)
+{
+    if( this==&rhs )
+        return *this;
+    _densesolverlsreport_owner::operator=(rhs);
+    return *this;
+}
+
+densesolverlsreport::~densesolverlsreport()
+{
+}
+
+/*************************************************************************
+Dense solver.
+
+This  subroutine  solves  a  system  A*x=b,  where A is NxN non-denegerate
+real matrix, x and b are vectors.
+
+Algorithm features:
+* automatic detection of degenerate cases
+* condition number estimation
+* iterative refinement
+* O(N^3) complexity
+
+INPUT PARAMETERS
+    A       -   array[0..N-1,0..N-1], system matrix
+    N       -   size of A
+    B       -   array[0..N-1], right part
+
+OUTPUT PARAMETERS
+    Info    -   return code:
+                * -3    A is singular, or VERY close to singular.
+                        X is filled by zeros in such cases.
+                * -1    N<=0 was passed
+                *  1    task is solved (but matrix A may be ill-conditioned,
+                        check R1/RInf parameters for condition numbers).
+    Rep     -   solver report, see below for more info
+    X       -   array[0..N-1], it contains:
+                * solution of A*x=b if A is non-singular (well-conditioned
+                  or ill-conditioned, but not very close to singular)
+                * zeros,  if  A  is  singular  or  VERY  close to singular
+                  (in this case Info=-3).
+
+SOLVER REPORT
+
+Subroutine sets following fields of the Rep structure:
+* R1        reciprocal of condition number: 1/cond(A), 1-norm.
+* RInf      reciprocal of condition number: 1/cond(A), inf-norm.
+
+  -- ALGLIB --
+     Copyright 27.01.2010 by Bochkanov Sergey
+*************************************************************************/
+void rmatrixsolve(const real_2d_array &a, const ae_int_t n, const real_1d_array &b, ae_int_t &info, densesolverreport &rep, real_1d_array &x)
+{
+    alglib_impl::ae_state _alglib_env_state;
+    alglib_impl::ae_state_init(&_alglib_env_state);
+    try
+    {
+        alglib_impl::rmatrixsolve(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, const_cast<alglib_impl::ae_vector*>(b.c_ptr()), &info, const_cast<alglib_impl::densesolverreport*>(rep.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), &_alglib_env_state);
+        alglib_impl::ae_state_clear(&_alglib_env_state);
+        return;
+    }
+    catch(alglib_impl::ae_error_type)
+    {
+        throw ap_error(_alglib_env_state.error_msg);
+    }
+    catch(...)
+    {
+        throw;
+    }
+}
+
+/*************************************************************************
+Dense solver.
+
+Similar to RMatrixSolve() but solves task with multiple right parts (where
+b and x are NxM matrices).
+
+Algorithm features:
+* automatic detection of degenerate cases
+* condition number estimation
+* optional iterative refinement
+* O(N^3+M*N^2) complexity
+
+INPUT PARAMETERS
+    A       -   array[0..N-1,0..N-1], system matrix
+    N       -   size of A
+    B       -   array[0..N-1,0..M-1], right part
+    M       -   right part size
+    RFS     -   iterative refinement switch:
+                * True - refinement is used.
+                  Less performance, more precision.
+                * False - refinement is not used.
+                  More performance, less precision.
+
+OUTPUT PARAMETERS
+    Info    -   same as in RMatrixSolve
+    Rep     -   same as in RMatrixSolve
+    X       -   same as in RMatrixSolve
+
+  -- ALGLIB --
+     Copyright 27.01.2010 by Bochkanov Sergey
+*************************************************************************/
+void rmatrixsolvem(const real_2d_array &a, const ae_int_t n, const real_2d_array &b, const ae_int_t m, const bool rfs, ae_int_t &info, densesolverreport &rep, real_2d_array &x)
+{
+    alglib_impl::ae_state _alglib_env_state;
+    alglib_impl::ae_state_init(&_alglib_env_state);
+    try
+    {
+        alglib_impl::rmatrixsolvem(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, const_cast<alglib_impl::ae_matrix*>(b.c_ptr()), m, rfs, &info, const_cast<alglib_impl::densesolverreport*>(rep.c_ptr()), const_cast<alglib_impl::ae_matrix*>(x.c_ptr()), &_alglib_env_state);
+        alglib_impl::ae_state_clear(&_alglib_env_state);
+        return;
+    }
+    catch(alglib_impl::ae_error_type)
+    {
+        throw ap_error(_alglib_env_state.error_msg);
+    }
+    catch(...)
+    {
+        throw;
+    }
+}
+
+/*************************************************************************
+Dense solver.
+
+This  subroutine  solves  a  system  A*X=B,  where A is NxN non-denegerate
+real matrix given by its LU decomposition, X and B are NxM real matrices.
+
+Algorithm features:
+* automatic detection of degenerate cases
+* O(N^2) complexity
+* condition number estimation
+
+No iterative refinement  is provided because exact form of original matrix
+is not known to subroutine. Use RMatrixSolve or RMatrixMixedSolve  if  you
+need iterative refinement.
+
+INPUT PARAMETERS
+    LUA     -   array[0..N-1,0..N-1], LU decomposition, RMatrixLU result
+    P       -   array[0..N-1], pivots array, RMatrixLU result
+    N       -   size of A
+    B       -   array[0..N-1], right part
+
+OUTPUT PARAMETERS
+    Info    -   same as in RMatrixSolve
+    Rep     -   same as in RMatrixSolve
+    X       -   same as in RMatrixSolve
+
+  -- ALGLIB --
+     Copyright 27.01.2010 by Bochkanov Sergey
+*************************************************************************/
+void rmatrixlusolve(const real_2d_array &lua, const integer_1d_array &p, const ae_int_t n, const real_1d_array &b, ae_int_t &info, densesolverreport &rep, real_1d_array &x)
+{
+    alglib_impl::ae_state _alglib_env_state;
+    alglib_impl::ae_state_init(&_alglib_env_state);
+    try
+    {
+        alglib_impl::rmatrixlusolve(const_cast<alglib_impl::ae_matrix*>(lua.c_ptr()), const_cast<alglib_impl::ae_vector*>(p.c_ptr()), n, const_cast<alglib_impl::ae_vector*>(b.c_ptr()), &info, const_cast<alglib_impl::densesolverreport*>(rep.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), &_alglib_env_state);
+        alglib_impl::ae_state_clear(&_alglib_env_state);
+        return;
+    }
+    catch(alglib_impl::ae_error_type)
+    {
+        throw ap_error(_alglib_env_state.error_msg);
+    }
+    catch(...)
+    {
+        throw;
+    }
+}
+
+/*************************************************************************
+Dense solver.
+
+Similar to RMatrixLUSolve() but solves task with multiple right parts
+(where b and x are NxM matrices).
+
+Algorithm features:
+* automatic detection of degenerate cases
+* O(M*N^2) complexity
+* condition number estimation
+
+No iterative refinement  is provided because exact form of original matrix
+is not known to subroutine. Use RMatrixSolve or RMatrixMixedSolve  if  you
+need iterative refinement.
+
+INPUT PARAMETERS
+    LUA     -   array[0..N-1,0..N-1], LU decomposition, RMatrixLU result
+    P       -   array[0..N-1], pivots array, RMatrixLU result
+    N       -   size of A
+    B       -   array[0..N-1,0..M-1], right part
+    M       -   right part size
+
+OUTPUT PARAMETERS
+    Info    -   same as in RMatrixSolve
+    Rep     -   same as in RMatrixSolve
+    X       -   same as in RMatrixSolve
+
+  -- ALGLIB --
+     Copyright 27.01.2010 by Bochkanov Sergey
+*************************************************************************/
+void rmatrixlusolvem(const real_2d_array &lua, const integer_1d_array &p, const ae_int_t n, const real_2d_array &b, const ae_int_t m, ae_int_t &info, densesolverreport &rep, real_2d_array &x)
+{
+    alglib_impl::ae_state _alglib_env_state;
+    alglib_impl::ae_state_init(&_alglib_env_state);
+    try
+    {
+        alglib_impl::rmatrixlusolvem(const_cast<alglib_impl::ae_matrix*>(lua.c_ptr()), const_cast<alglib_impl::ae_vector*>(p.c_ptr()), n, const_cast<alglib_impl::ae_matrix*>(b.c_ptr()), m, &info, const_cast<alglib_impl::densesolverreport*>(rep.c_ptr()), const_cast<alglib_impl::ae_matrix*>(x.c_ptr()), &_alglib_env_state);
+        alglib_impl::ae_state_clear(&_alglib_env_state);
+        return;
+    }
+    catch(alglib_impl::ae_error_type)
+    {
+        throw ap_error(_alglib_env_state.error_msg);
+    }
+    catch(...)
+    {
+        throw;
+    }
+}
+
+/*************************************************************************
+Dense solver.
+
+This  subroutine  solves  a  system  A*x=b,  where BOTH ORIGINAL A AND ITS
+LU DECOMPOSITION ARE KNOWN. You can use it if for some  reasons  you  have
+both A and its LU decomposition.
+
+Algorithm features:
+* automatic detection of degenerate cases
+* condition number estimation
+* iterative refinement
+* O(N^2) complexity
+
+INPUT PARAMETERS
+    A       -   array[0..N-1,0..N-1], system matrix
+    LUA     -   array[0..N-1,0..N-1], LU decomposition, RMatrixLU result
+    P       -   array[0..N-1], pivots array, RMatrixLU result
+    N       -   size of A
+    B       -   array[0..N-1], right part
+
+OUTPUT PARAMETERS
+    Info    -   same as in RMatrixSolveM
+    Rep     -   same as in RMatrixSolveM
+    X       -   same as in RMatrixSolveM
+
+  -- ALGLIB --
+     Copyright 27.01.2010 by Bochkanov Sergey
+*************************************************************************/
+void rmatrixmixedsolve(const real_2d_array &a, const real_2d_array &lua, const integer_1d_array &p, const ae_int_t n, const real_1d_array &b, ae_int_t &info, densesolverreport &rep, real_1d_array &x)
+{
+    alglib_impl::ae_state _alglib_env_state;
+    alglib_impl::ae_state_init(&_alglib_env_state);
+    try
+    {
+        alglib_impl::rmatrixmixedsolve(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), const_cast<alglib_impl::ae_matrix*>(lua.c_ptr()), const_cast<alglib_impl::ae_vector*>(p.c_ptr()), n, const_cast<alglib_impl::ae_vector*>(b.c_ptr()), &info, const_cast<alglib_impl::densesolverreport*>(rep.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), &_alglib_env_state);
+        alglib_impl::ae_state_clear(&_alglib_env_state);
+        return;
+    }
+    catch(alglib_impl::ae_error_type)
+    {
+        throw ap_error(_alglib_env_state.error_msg);
+    }
+    catch(...)
+    {
+        throw;
+    }
+}
+
+/*************************************************************************
+Dense solver.
+
+Similar to RMatrixMixedSolve() but  solves task with multiple right  parts
+(where b and x are NxM matrices).
+
+Algorithm features:
+* automatic detection of degenerate cases
+* condition number estimation
+* iterative refinement
+* O(M*N^2) complexity
+
+INPUT PARAMETERS
+    A       -   array[0..N-1,0..N-1], system matrix
+    LUA     -   array[0..N-1,0..N-1], LU decomposition, RMatrixLU result
+    P       -   array[0..N-1], pivots array, RMatrixLU result
+    N       -   size of A
+    B       -   array[0..N-1,0..M-1], right part
+    M       -   right part size
+
+OUTPUT PARAMETERS
+    Info    -   same as in RMatrixSolveM
+    Rep     -   same as in RMatrixSolveM
+    X       -   same as in RMatrixSolveM
+
+  -- ALGLIB --
+     Copyright 27.01.2010 by Bochkanov Sergey
+*************************************************************************/
+void rmatrixmixedsolvem(const real_2d_array &a, const real_2d_array &lua, const integer_1d_array &p, const ae_int_t n, const real_2d_array &b, const ae_int_t m, ae_int_t &info, densesolverreport &rep, real_2d_array &x)
+{
+    alglib_impl::ae_state _alglib_env_state;
+    alglib_impl::ae_state_init(&_alglib_env_state);
+    try
+    {
+        alglib_impl::rmatrixmixedsolvem(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), const_cast<alglib_impl::ae_matrix*>(lua.c_ptr()), const_cast<alglib_impl::ae_vector*>(p.c_ptr()), n, const_cast<alglib_impl::ae_matrix*>(b.c_ptr()), m, &info, const_cast<alglib_impl::densesolverreport*>(rep.c_ptr()), const_cast<alglib_impl::ae_matrix*>(x.c_ptr()), &_alglib_env_state);
+        alglib_impl::ae_state_clear(&_alglib_env_state);
+        return;
+    }
+    catch(alglib_impl::ae_error_type)
+    {
+        throw ap_error(_alglib_env_state.error_msg);
+    }
+    catch(...)
+    {
+        throw;
+    }
+}
+
+/*************************************************************************
+Dense solver. Same as RMatrixSolveM(), but for complex matrices.
+
+Algorithm features:
+* automatic detection of degenerate cases
+* condition number estimation
+* iterative refinement
+* O(N^3+M*N^2) complexity
+
+INPUT PARAMETERS
+    A       -   array[0..N-1,0..N-1], system matrix
+    N       -   size of A
+    B       -   array[0..N-1,0..M-1], right part
+    M       -   right part size
+    RFS     -   iterative refinement switch:
+                * True - refinement is used.
+                  Less performance, more precision.
+                * False - refinement is not used.
+                  More performance, less precision.
+
+OUTPUT PARAMETERS
+    Info    -   same as in RMatrixSolve
+    Rep     -   same as in RMatrixSolve
+    X       -   same as in RMatrixSolve
+
+  -- ALGLIB --
+     Copyright 27.01.2010 by Bochkanov Sergey
+*************************************************************************/
+void cmatrixsolvem(const complex_2d_array &a, const ae_int_t n, const complex_2d_array &b, const ae_int_t m, const bool rfs, ae_int_t &info, densesolverreport &rep, complex_2d_array &x)
+{
+    alglib_impl::ae_state _alglib_env_state;
+    alglib_impl::ae_state_init(&_alglib_env_state);
+    try
+    {
+        alglib_impl::cmatrixsolvem(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, const_cast<alglib_impl::ae_matrix*>(b.c_ptr()), m, rfs, &info, const_cast<alglib_impl::densesolverreport*>(rep.c_ptr()), const_cast<alglib_impl::ae_matrix*>(x.c_ptr()), &_alglib_env_state);
+        alglib_impl::ae_state_clear(&_alglib_env_state);
+        return;
+    }
+    catch(alglib_impl::ae_error_type)
+    {
+        throw ap_error(_alglib_env_state.error_msg);
+    }
+    catch(...)
+    {
+        throw;
+    }
+}
+
+/*************************************************************************
+Dense solver. Same as RMatrixSolve(), but for complex matrices.
+
+Algorithm features:
+* automatic detection of degenerate cases
+* condition number estimation
+* iterative refinement
+* O(N^3) complexity
+
+INPUT PARAMETERS
+    A       -   array[0..N-1,0..N-1], system matrix
+    N       -   size of A
+    B       -   array[0..N-1], right part
+
+OUTPUT PARAMETERS
+    Info    -   same as in RMatrixSolve
+    Rep     -   same as in RMatrixSolve
+    X       -   same as in RMatrixSolve
+
+  -- ALGLIB --
+     Copyright 27.01.2010 by Bochkanov Sergey
+*************************************************************************/
+void cmatrixsolve(const complex_2d_array &a, const ae_int_t n, const complex_1d_array &b, ae_int_t &info, densesolverreport &rep, complex_1d_array &x)
+{
+    alglib_impl::ae_state _alglib_env_state;
+    alglib_impl::ae_state_init(&_alglib_env_state);
+    try
+    {
+        alglib_impl::cmatrixsolve(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, const_cast<alglib_impl::ae_vector*>(b.c_ptr()), &info, const_cast<alglib_impl::densesolverreport*>(rep.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), &_alglib_env_state);
+        alglib_impl::ae_state_clear(&_alglib_env_state);
+        return;
+    }
+    catch(alglib_impl::ae_error_type)
+    {
+        throw ap_error(_alglib_env_state.error_msg);
+    }
+    catch(...)
+    {
+        throw;
+    }
+}
+
+/*************************************************************************
+Dense solver. Same as RMatrixLUSolveM(), but for complex matrices.
+
+Algorithm features:
+* automatic detection of degenerate cases
+* O(M*N^2) complexity
+* condition number estimation
+
+No iterative refinement  is provided because exact form of original matrix
+is not known to subroutine. Use CMatrixSolve or CMatrixMixedSolve  if  you
+need iterative refinement.
+
+INPUT PARAMETERS
+    LUA     -   array[0..N-1,0..N-1], LU decomposition, RMatrixLU result
+    P       -   array[0..N-1], pivots array, RMatrixLU result
+    N       -   size of A
+    B       -   array[0..N-1,0..M-1], right part
+    M       -   right part size
+
+OUTPUT PARAMETERS
+    Info    -   same as in RMatrixSolve
+    Rep     -   same as in RMatrixSolve
+    X       -   same as in RMatrixSolve
+
+  -- ALGLIB --
+     Copyright 27.01.2010 by Bochkanov Sergey
+*************************************************************************/
+void cmatrixlusolvem(const complex_2d_array &lua, const integer_1d_array &p, const ae_int_t n, const complex_2d_array &b, const ae_int_t m, ae_int_t &info, densesolverreport &rep, complex_2d_array &x)
+{
+    alglib_impl::ae_state _alglib_env_state;
+    alglib_impl::ae_state_init(&_alglib_env_state);
+    try
+    {
+        alglib_impl::cmatrixlusolvem(const_cast<alglib_impl::ae_matrix*>(lua.c_ptr()), const_cast<alglib_impl::ae_vector*>(p.c_ptr()), n, const_cast<alglib_impl::ae_matrix*>(b.c_ptr()), m, &info, const_cast<alglib_impl::densesolverreport*>(rep.c_ptr()), const_cast<alglib_impl::ae_matrix*>(x.c_ptr()), &_alglib_env_state);
+        alglib_impl::ae_state_clear(&_alglib_env_state);
+        return;
+    }
+    catch(alglib_impl::ae_error_type)
+    {
+        throw ap_error(_alglib_env_state.error_msg);
+    }
+    catch(...)
+    {
+        throw;
+    }
+}
+
+/*************************************************************************
+Dense solver. Same as RMatrixLUSolve(), but for complex matrices.
+
+Algorithm features:
+* automatic detection of degenerate cases
+* O(N^2) complexity
+* condition number estimation
+
+No iterative refinement is provided because exact form of original matrix
+is not known to subroutine. Use CMatrixSolve or CMatrixMixedSolve  if  you
+need iterative refinement.
+
+INPUT PARAMETERS
+    LUA     -   array[0..N-1,0..N-1], LU decomposition, CMatrixLU result
+    P       -   array[0..N-1], pivots array, CMatrixLU result
+    N       -   size of A
+    B       -   array[0..N-1], right part
+
+OUTPUT PARAMETERS
+    Info    -   same as in RMatrixSolve
+    Rep     -   same as in RMatrixSolve
+    X       -   same as in RMatrixSolve
+
+  -- ALGLIB --
+     Copyright 27.01.2010 by Bochkanov Sergey
+*************************************************************************/
+void cmatrixlusolve(const complex_2d_array &lua, const integer_1d_array &p, const ae_int_t n, const complex_1d_array &b, ae_int_t &info, densesolverreport &rep, complex_1d_array &x)
+{
+    alglib_impl::ae_state _alglib_env_state;
+    alglib_impl::ae_state_init(&_alglib_env_state);
+    try
+    {
+        alglib_impl::cmatrixlusolve(const_cast<alglib_impl::ae_matrix*>(lua.c_ptr()), const_cast<alglib_impl::ae_vector*>(p.c_ptr()), n, const_cast<alglib_impl::ae_vector*>(b.c_ptr()), &info, const_cast<alglib_impl::densesolverreport*>(rep.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), &_alglib_env_state);
+        alglib_impl::ae_state_clear(&_alglib_env_state);
+        return;
+    }
+    catch(alglib_impl::ae_error_type)
+    {
+        throw ap_error(_alglib_env_state.error_msg);
+    }
+    catch(...)
+    {
+        throw;
+    }
+}
+
+/*************************************************************************
+Dense solver. Same as RMatrixMixedSolveM(), but for complex matrices.
+
+Algorithm features:
+* automatic detection of degenerate cases
+* condition number estimation
+* iterative refinement
+* O(M*N^2) complexity
+
+INPUT PARAMETERS
+    A       -   array[0..N-1,0..N-1], system matrix
+    LUA     -   array[0..N-1,0..N-1], LU decomposition, CMatrixLU result
+    P       -   array[0..N-1], pivots array, CMatrixLU result
+    N       -   size of A
+    B       -   array[0..N-1,0..M-1], right part
+    M       -   right part size
+
+OUTPUT PARAMETERS
+    Info    -   same as in RMatrixSolveM
+    Rep     -   same as in RMatrixSolveM
+    X       -   same as in RMatrixSolveM
+
+  -- ALGLIB --
+     Copyright 27.01.2010 by Bochkanov Sergey
+*************************************************************************/
+void cmatrixmixedsolvem(const complex_2d_array &a, const complex_2d_array &lua, const integer_1d_array &p, const ae_int_t n, const complex_2d_array &b, const ae_int_t m, ae_int_t &info, densesolverreport &rep, complex_2d_array &x)
+{
+    alglib_impl::ae_state _alglib_env_state;
+    alglib_impl::ae_state_init(&_alglib_env_state);
+    try
+    {
+        alglib_impl::cmatrixmixedsolvem(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), const_cast<alglib_impl::ae_matrix*>(lua.c_ptr()), const_cast<alglib_impl::ae_vector*>(p.c_ptr()), n, const_cast<alglib_impl::ae_matrix*>(b.c_ptr()), m, &info, const_cast<alglib_impl::densesolverreport*>(rep.c_ptr()), const_cast<alglib_impl::ae_matrix*>(x.c_ptr()), &_alglib_env_state);
+        alglib_impl::ae_state_clear(&_alglib_env_state);
+        return;
+    }
+    catch(alglib_impl::ae_error_type)
+    {
+        throw ap_error(_alglib_env_state.error_msg);
+    }
+    catch(...)
+    {
+        throw;
+    }
+}
+
+/*************************************************************************
+Dense solver. Same as RMatrixMixedSolve(), but for complex matrices.
+
+Algorithm features:
+* automatic detection of degenerate cases
+* condition number estimation
+* iterative refinement
+* O(N^2) complexity
+
+INPUT PARAMETERS
+    A       -   array[0..N-1,0..N-1], system matrix
+    LUA     -   array[0..N-1,0..N-1], LU decomposition, CMatrixLU result
+    P       -   array[0..N-1], pivots array, CMatrixLU result
+    N       -   size of A
+    B       -   array[0..N-1], right part
+
+OUTPUT PARAMETERS
+    Info    -   same as in RMatrixSolveM
+    Rep     -   same as in RMatrixSolveM
+    X       -   same as in RMatrixSolveM
+
+  -- ALGLIB --
+     Copyright 27.01.2010 by Bochkanov Sergey
+*************************************************************************/
+void cmatrixmixedsolve(const complex_2d_array &a, const complex_2d_array &lua, const integer_1d_array &p, const ae_int_t n, const complex_1d_array &b, ae_int_t &info, densesolverreport &rep, complex_1d_array &x)
+{
+    alglib_impl::ae_state _alglib_env_state;
+    alglib_impl::ae_state_init(&_alglib_env_state);
+    try
+    {
+        alglib_impl::cmatrixmixedsolve(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), const_cast<alglib_impl::ae_matrix*>(lua.c_ptr()), const_cast<alglib_impl::ae_vector*>(p.c_ptr()), n, const_cast<alglib_impl::ae_vector*>(b.c_ptr()), &info, const_cast<alglib_impl::densesolverreport*>(rep.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), &_alglib_env_state);
+        alglib_impl::ae_state_clear(&_alglib_env_state);
+        return;
+    }
+    catch(alglib_impl::ae_error_type)
+    {
+        throw ap_error(_alglib_env_state.error_msg);
+    }
+    catch(...)
+    {
+        throw;
+    }
+}
+
+/*************************************************************************
+Dense solver. Same as RMatrixSolveM(), but for symmetric positive definite
+matrices.
+
+Algorithm features:
+* automatic detection of degenerate cases
+* condition number estimation
+* O(N^3+M*N^2) complexity
+* matrix is represented by its upper or lower triangle
+
+No iterative refinement is provided because such partial representation of
+matrix does not allow efficient calculation of extra-precise  matrix-vector
+products for large matrices. Use RMatrixSolve or RMatrixMixedSolve  if  you
+need iterative refinement.
+
+INPUT PARAMETERS
+    A       -   array[0..N-1,0..N-1], system matrix
+    N       -   size of A
+    IsUpper -   what half of A is provided
+    B       -   array[0..N-1,0..M-1], right part
+    M       -   right part size
+
+OUTPUT PARAMETERS
+    Info    -   same as in RMatrixSolve.
+                Returns -3 for non-SPD matrices.
+    Rep     -   same as in RMatrixSolve
+    X       -   same as in RMatrixSolve
+
+  -- ALGLIB --
+     Copyright 27.01.2010 by Bochkanov Sergey
+*************************************************************************/
+void spdmatrixsolvem(const real_2d_array &a, const ae_int_t n, const bool isupper, const real_2d_array &b, const ae_int_t m, ae_int_t &info, densesolverreport &rep, real_2d_array &x)
+{
+    alglib_impl::ae_state _alglib_env_state;
+    alglib_impl::ae_state_init(&_alglib_env_state);
+    try
+    {
+        alglib_impl::spdmatrixsolvem(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, isupper, const_cast<alglib_impl::ae_matrix*>(b.c_ptr()), m, &info, const_cast<alglib_impl::densesolverreport*>(rep.c_ptr()), const_cast<alglib_impl::ae_matrix*>(x.c_ptr()), &_alglib_env_state);
+        alglib_impl::ae_state_clear(&_alglib_env_state);
+        return;
+    }
+    catch(alglib_impl::ae_error_type)
+    {
+        throw ap_error(_alglib_env_state.error_msg);
+    }
+    catch(...)
+    {
+        throw;
+    }
+}
+
+/*************************************************************************
+Dense solver. Same as RMatrixSolve(), but for SPD matrices.
+
+Algorithm features:
+* automatic detection of degenerate cases
+* condition number estimation
+* O(N^3) complexity
+* matrix is represented by its upper or lower triangle
+
+No iterative refinement is provided because such partial representation of
+matrix does not allow efficient calculation of extra-precise  matrix-vector
+products for large matrices. Use RMatrixSolve or RMatrixMixedSolve  if  you
+need iterative refinement.
+
+INPUT PARAMETERS
+    A       -   array[0..N-1,0..N-1], system matrix
+    N       -   size of A
+    IsUpper -   what half of A is provided
+    B       -   array[0..N-1], right part
+
+OUTPUT PARAMETERS
+    Info    -   same as in RMatrixSolve
+                Returns -3 for non-SPD matrices.
+    Rep     -   same as in RMatrixSolve
+    X       -   same as in RMatrixSolve
+
+  -- ALGLIB --
+     Copyright 27.01.2010 by Bochkanov Sergey
+*************************************************************************/
+void spdmatrixsolve(const real_2d_array &a, const ae_int_t n, const bool isupper, const real_1d_array &b, ae_int_t &info, densesolverreport &rep, real_1d_array &x)
+{
+    alglib_impl::ae_state _alglib_env_state;
+    alglib_impl::ae_state_init(&_alglib_env_state);
+    try
+    {
+        alglib_impl::spdmatrixsolve(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, isupper, const_cast<alglib_impl::ae_vector*>(b.c_ptr()), &info, const_cast<alglib_impl::densesolverreport*>(rep.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), &_alglib_env_state);
+        alglib_impl::ae_state_clear(&_alglib_env_state);
+        return;
+    }
+    catch(alglib_impl::ae_error_type)
+    {
+        throw ap_error(_alglib_env_state.error_msg);
+    }
+    catch(...)
+    {
+        throw;
+    }
+}
+
+/*************************************************************************
+Dense solver. Same as RMatrixLUSolveM(), but for SPD matrices  represented
+by their Cholesky decomposition.
+
+Algorithm features:
+* automatic detection of degenerate cases
+* O(M*N^2) complexity
+* condition number estimation
+* matrix is represented by its upper or lower triangle
+
+No iterative refinement is provided because such partial representation of
+matrix does not allow efficient calculation of extra-precise  matrix-vector
+products for large matrices. Use RMatrixSolve or RMatrixMixedSolve  if  you
+need iterative refinement.
+
+INPUT PARAMETERS
+    CHA     -   array[0..N-1,0..N-1], Cholesky decomposition,
+                SPDMatrixCholesky result
+    N       -   size of CHA
+    IsUpper -   what half of CHA is provided
+    B       -   array[0..N-1,0..M-1], right part
+    M       -   right part size
+
+OUTPUT PARAMETERS
+    Info    -   same as in RMatrixSolve
+    Rep     -   same as in RMatrixSolve
+    X       -   same as in RMatrixSolve
+
+  -- ALGLIB --
+     Copyright 27.01.2010 by Bochkanov Sergey
+*************************************************************************/
+void spdmatrixcholeskysolvem(const real_2d_array &cha, const ae_int_t n, const bool isupper, const real_2d_array &b, const ae_int_t m, ae_int_t &info, densesolverreport &rep, real_2d_array &x)
+{
+    alglib_impl::ae_state _alglib_env_state;
+    alglib_impl::ae_state_init(&_alglib_env_state);
+    try
+    {
+        alglib_impl::spdmatrixcholeskysolvem(const_cast<alglib_impl::ae_matrix*>(cha.c_ptr()), n, isupper, const_cast<alglib_impl::ae_matrix*>(b.c_ptr()), m, &info, const_cast<alglib_impl::densesolverreport*>(rep.c_ptr()), const_cast<alglib_impl::ae_matrix*>(x.c_ptr()), &_alglib_env_state);
+        alglib_impl::ae_state_clear(&_alglib_env_state);
+        return;
+    }
+    catch(alglib_impl::ae_error_type)
+    {
+        throw ap_error(_alglib_env_state.error_msg);
+    }
+    catch(...)
+    {
+        throw;
+    }
+}
+
+/*************************************************************************
+Dense solver. Same as RMatrixLUSolve(), but for  SPD matrices  represented
+by their Cholesky decomposition.
+
+Algorithm features:
+* automatic detection of degenerate cases
+* O(N^2) complexity
+* condition number estimation
+* matrix is represented by its upper or lower triangle
+
+No iterative refinement is provided because such partial representation of
+matrix does not allow efficient calculation of extra-precise  matrix-vector
+products for large matrices. Use RMatrixSolve or RMatrixMixedSolve  if  you
+need iterative refinement.
+
+INPUT PARAMETERS
+    CHA     -   array[0..N-1,0..N-1], Cholesky decomposition,
+                SPDMatrixCholesky result
+    N       -   size of A
+    IsUpper -   what half of CHA is provided
+    B       -   array[0..N-1], right part
+
+OUTPUT PARAMETERS
+    Info    -   same as in RMatrixSolve
+    Rep     -   same as in RMatrixSolve
+    X       -   same as in RMatrixSolve
+
+  -- ALGLIB --
+     Copyright 27.01.2010 by Bochkanov Sergey
+*************************************************************************/
+void spdmatrixcholeskysolve(const real_2d_array &cha, const ae_int_t n, const bool isupper, const real_1d_array &b, ae_int_t &info, densesolverreport &rep, real_1d_array &x)
+{
+    alglib_impl::ae_state _alglib_env_state;
+    alglib_impl::ae_state_init(&_alglib_env_state);
+    try
+    {
+        alglib_impl::spdmatrixcholeskysolve(const_cast<alglib_impl::ae_matrix*>(cha.c_ptr()), n, isupper, const_cast<alglib_impl::ae_vector*>(b.c_ptr()), &info, const_cast<alglib_impl::densesolverreport*>(rep.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), &_alglib_env_state);
+        alglib_impl::ae_state_clear(&_alglib_env_state);
+        return;
+    }
+    catch(alglib_impl::ae_error_type)
+    {
+        throw ap_error(_alglib_env_state.error_msg);
+    }
+    catch(...)
+    {
+        throw;
+    }
+}
+
+/*************************************************************************
+Dense solver. Same as RMatrixSolveM(), but for Hermitian positive definite
+matrices.
+
+Algorithm features:
+* automatic detection of degenerate cases
+* condition number estimation
+* O(N^3+M*N^2) complexity
+* matrix is represented by its upper or lower triangle
+
+No iterative refinement is provided because such partial representation of
+matrix does not allow efficient calculation of extra-precise  matrix-vector
+products for large matrices. Use RMatrixSolve or RMatrixMixedSolve  if  you
+need iterative refinement.
+
+INPUT PARAMETERS
+    A       -   array[0..N-1,0..N-1], system matrix
+    N       -   size of A
+    IsUpper -   what half of A is provided
+    B       -   array[0..N-1,0..M-1], right part
+    M       -   right part size
+
+OUTPUT PARAMETERS
+    Info    -   same as in RMatrixSolve.
+                Returns -3 for non-HPD matrices.
+    Rep     -   same as in RMatrixSolve
+    X       -   same as in RMatrixSolve
+
+  -- ALGLIB --
+     Copyright 27.01.2010 by Bochkanov Sergey
+*************************************************************************/
+void hpdmatrixsolvem(const complex_2d_array &a, const ae_int_t n, const bool isupper, const complex_2d_array &b, const ae_int_t m, ae_int_t &info, densesolverreport &rep, complex_2d_array &x)
+{
+    alglib_impl::ae_state _alglib_env_state;
+    alglib_impl::ae_state_init(&_alglib_env_state);
+    try
+    {
+        alglib_impl::hpdmatrixsolvem(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, isupper, const_cast<alglib_impl::ae_matrix*>(b.c_ptr()), m, &info, const_cast<alglib_impl::densesolverreport*>(rep.c_ptr()), const_cast<alglib_impl::ae_matrix*>(x.c_ptr()), &_alglib_env_state);
+        alglib_impl::ae_state_clear(&_alglib_env_state);
+        return;
+    }
+    catch(alglib_impl::ae_error_type)
+    {
+        throw ap_error(_alglib_env_state.error_msg);
+    }
+    catch(...)
+    {
+        throw;
+    }
+}
+
+/*************************************************************************
+Dense solver. Same as RMatrixSolve(),  but for Hermitian positive definite
+matrices.
+
+Algorithm features:
+* automatic detection of degenerate cases
+* condition number estimation
+* O(N^3) complexity
+* matrix is represented by its upper or lower triangle
+
+No iterative refinement is provided because such partial representation of
+matrix does not allow efficient calculation of extra-precise  matrix-vector
+products for large matrices. Use RMatrixSolve or RMatrixMixedSolve  if  you
+need iterative refinement.
+
+INPUT PARAMETERS
+    A       -   array[0..N-1,0..N-1], system matrix
+    N       -   size of A
+    IsUpper -   what half of A is provided
+    B       -   array[0..N-1], right part
+
+OUTPUT PARAMETERS
+    Info    -   same as in RMatrixSolve
+                Returns -3 for non-HPD matrices.
+    Rep     -   same as in RMatrixSolve
+    X       -   same as in RMatrixSolve
+
+  -- ALGLIB --
+     Copyright 27.01.2010 by Bochkanov Sergey
+*************************************************************************/
+void hpdmatrixsolve(const complex_2d_array &a, const ae_int_t n, const bool isupper, const complex_1d_array &b, ae_int_t &info, densesolverreport &rep, complex_1d_array &x)
+{
+    alglib_impl::ae_state _alglib_env_state;
+    alglib_impl::ae_state_init(&_alglib_env_state);
+    try
+    {
+        alglib_impl::hpdmatrixsolve(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), n, isupper, const_cast<alglib_impl::ae_vector*>(b.c_ptr()), &info, const_cast<alglib_impl::densesolverreport*>(rep.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), &_alglib_env_state);
+        alglib_impl::ae_state_clear(&_alglib_env_state);
+        return;
+    }
+    catch(alglib_impl::ae_error_type)
+    {
+        throw ap_error(_alglib_env_state.error_msg);
+    }
+    catch(...)
+    {
+        throw;
+    }
+}
+
+/*************************************************************************
+Dense solver. Same as RMatrixLUSolveM(), but for HPD matrices  represented
+by their Cholesky decomposition.
+
+Algorithm features:
+* automatic detection of degenerate cases
+* O(M*N^2) complexity
+* condition number estimation
+* matrix is represented by its upper or lower triangle
+
+No iterative refinement is provided because such partial representation of
+matrix does not allow efficient calculation of extra-precise  matrix-vector
+products for large matrices. Use RMatrixSolve or RMatrixMixedSolve  if  you
+need iterative refinement.
+
+INPUT PARAMETERS
+    CHA     -   array[0..N-1,0..N-1], Cholesky decomposition,
+                HPDMatrixCholesky result
+    N       -   size of CHA
+    IsUpper -   what half of CHA is provided
+    B       -   array[0..N-1,0..M-1], right part
+    M       -   right part size
+
+OUTPUT PARAMETERS
+    Info    -   same as in RMatrixSolve
+    Rep     -   same as in RMatrixSolve
+    X       -   same as in RMatrixSolve
+
+  -- ALGLIB --
+     Copyright 27.01.2010 by Bochkanov Sergey
+*************************************************************************/
+void hpdmatrixcholeskysolvem(const complex_2d_array &cha, const ae_int_t n, const bool isupper, const complex_2d_array &b, const ae_int_t m, ae_int_t &info, densesolverreport &rep, complex_2d_array &x)
+{
+    alglib_impl::ae_state _alglib_env_state;
+    alglib_impl::ae_state_init(&_alglib_env_state);
+    try
+    {
+        alglib_impl::hpdmatrixcholeskysolvem(const_cast<alglib_impl::ae_matrix*>(cha.c_ptr()), n, isupper, const_cast<alglib_impl::ae_matrix*>(b.c_ptr()), m, &info, const_cast<alglib_impl::densesolverreport*>(rep.c_ptr()), const_cast<alglib_impl::ae_matrix*>(x.c_ptr()), &_alglib_env_state);
+        alglib_impl::ae_state_clear(&_alglib_env_state);
+        return;
+    }
+    catch(alglib_impl::ae_error_type)
+    {
+        throw ap_error(_alglib_env_state.error_msg);
+    }
+    catch(...)
+    {
+        throw;
+    }
+}
+
+/*************************************************************************
+Dense solver. Same as RMatrixLUSolve(), but for  HPD matrices  represented
+by their Cholesky decomposition.
+
+Algorithm features:
+* automatic detection of degenerate cases
+* O(N^2) complexity
+* condition number estimation
+* matrix is represented by its upper or lower triangle
+
+No iterative refinement is provided because such partial representation of
+matrix does not allow efficient calculation of extra-precise  matrix-vector
+products for large matrices. Use RMatrixSolve or RMatrixMixedSolve  if  you
+need iterative refinement.
+
+INPUT PARAMETERS
+    CHA     -   array[0..N-1,0..N-1], Cholesky decomposition,
+                SPDMatrixCholesky result
+    N       -   size of A
+    IsUpper -   what half of CHA is provided
+    B       -   array[0..N-1], right part
+
+OUTPUT PARAMETERS
+    Info    -   same as in RMatrixSolve
+    Rep     -   same as in RMatrixSolve
+    X       -   same as in RMatrixSolve
+
+  -- ALGLIB --
+     Copyright 27.01.2010 by Bochkanov Sergey
+*************************************************************************/
+void hpdmatrixcholeskysolve(const complex_2d_array &cha, const ae_int_t n, const bool isupper, const complex_1d_array &b, ae_int_t &info, densesolverreport &rep, complex_1d_array &x)
+{
+    alglib_impl::ae_state _alglib_env_state;
+    alglib_impl::ae_state_init(&_alglib_env_state);
+    try
+    {
+        alglib_impl::hpdmatrixcholeskysolve(const_cast<alglib_impl::ae_matrix*>(cha.c_ptr()), n, isupper, const_cast<alglib_impl::ae_vector*>(b.c_ptr()), &info, const_cast<alglib_impl::densesolverreport*>(rep.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), &_alglib_env_state);
+        alglib_impl::ae_state_clear(&_alglib_env_state);
+        return;
+    }
+    catch(alglib_impl::ae_error_type)
+    {
+        throw ap_error(_alglib_env_state.error_msg);
+    }
+    catch(...)
+    {
+        throw;
+    }
+}
+
+/*************************************************************************
+Dense solver.
+
+This subroutine finds solution of the linear system A*X=B with non-square,
+possibly degenerate A.  System  is  solved in the least squares sense, and
+general least squares solution  X = X0 + CX*y  which  minimizes |A*X-B| is
+returned. If A is non-degenerate, solution in the  usual sense is returned
+
+Algorithm features:
+* automatic detection of degenerate cases
+* iterative refinement
+* O(N^3) complexity
+
+INPUT PARAMETERS
+    A       -   array[0..NRows-1,0..NCols-1], system matrix
+    NRows   -   vertical size of A
+    NCols   -   horizontal size of A
+    B       -   array[0..NCols-1], right part
+    Threshold-  a number in [0,1]. Singular values  beyond  Threshold  are
+                considered  zero.  Set  it to 0.0, if you don't understand
+                what it means, so the solver will choose good value on its
+                own.
+
+OUTPUT PARAMETERS
+    Info    -   return code:
+                * -4    SVD subroutine failed
+                * -1    if NRows<=0 or NCols<=0 or Threshold<0 was passed
+                *  1    if task is solved
+    Rep     -   solver report, see below for more info
+    X       -   array[0..N-1,0..M-1], it contains:
+                * solution of A*X=B if A is non-singular (well-conditioned
+                  or ill-conditioned, but not very close to singular)
+                * zeros,  if  A  is  singular  or  VERY  close to singular
+                  (in this case Info=-3).
+
+SOLVER REPORT
+
+Subroutine sets following fields of the Rep structure:
+* R2        reciprocal of condition number: 1/cond(A), 2-norm.
+* N         = NCols
+* K         dim(Null(A))
+* CX        array[0..N-1,0..K-1], kernel of A.
+            Columns of CX store such vectors that A*CX[i]=0.
+
+  -- ALGLIB --
+     Copyright 24.08.2009 by Bochkanov Sergey
+*************************************************************************/
+void rmatrixsolvels(const real_2d_array &a, const ae_int_t nrows, const ae_int_t ncols, const real_1d_array &b, const double threshold, ae_int_t &info, densesolverlsreport &rep, real_1d_array &x)
+{
+    alglib_impl::ae_state _alglib_env_state;
+    alglib_impl::ae_state_init(&_alglib_env_state);
+    try
+    {
+        alglib_impl::rmatrixsolvels(const_cast<alglib_impl::ae_matrix*>(a.c_ptr()), nrows, ncols, const_cast<alglib_impl::ae_vector*>(b.c_ptr()), threshold, &info, const_cast<alglib_impl::densesolverlsreport*>(rep.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), &_alglib_env_state);
+        alglib_impl::ae_state_clear(&_alglib_env_state);
+        return;
+    }
+    catch(alglib_impl::ae_error_type)
+    {
+        throw ap_error(_alglib_env_state.error_msg);
+    }
+    catch(...)
+    {
+        throw;
+    }
+}
+
+/*************************************************************************
+
+*************************************************************************/
+_nleqstate_owner::_nleqstate_owner()
+{
+    p_struct = (alglib_impl::nleqstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::nleqstate), NULL);
+    if( p_struct==NULL )
+        throw ap_error("ALGLIB: malloc error");
+    if( !alglib_impl::_nleqstate_init(p_struct, NULL, ae_false) )
+        throw ap_error("ALGLIB: malloc error");
+}
+
+_nleqstate_owner::_nleqstate_owner(const _nleqstate_owner &rhs)
+{
+    p_struct = (alglib_impl::nleqstate*)alglib_impl::ae_malloc(sizeof(alglib_impl::nleqstate), NULL);
+    if( p_struct==NULL )
+        throw ap_error("ALGLIB: malloc error");
+    if( !alglib_impl::_nleqstate_init_copy(p_struct, const_cast<alglib_impl::nleqstate*>(rhs.p_struct), NULL, ae_false) )
+        throw ap_error("ALGLIB: malloc error");
+}
+
+_nleqstate_owner& _nleqstate_owner::operator=(const _nleqstate_owner &rhs)
+{
+    if( this==&rhs )
+        return *this;
+    alglib_impl::_nleqstate_clear(p_struct);
+    if( !alglib_impl::_nleqstate_init_copy(p_struct, const_cast<alglib_impl::nleqstate*>(rhs.p_struct), NULL, ae_false) )
+        throw ap_error("ALGLIB: malloc error");
+    return *this;
+}
+
+_nleqstate_owner::~_nleqstate_owner()
+{
+    alglib_impl::_nleqstate_clear(p_struct);
+    ae_free(p_struct);
+}
+
+alglib_impl::nleqstate* _nleqstate_owner::c_ptr()
+{
+    return p_struct;
+}
+
+alglib_impl::nleqstate* _nleqstate_owner::c_ptr() const
+{
+    return const_cast<alglib_impl::nleqstate*>(p_struct);
+}
+nleqstate::nleqstate() : _nleqstate_owner() ,needf(p_struct->needf),needfij(p_struct->needfij),xupdated(p_struct->xupdated),f(p_struct->f),fi(&p_struct->fi),j(&p_struct->j),x(&p_struct->x)
+{
+}
+
+nleqstate::nleqstate(const nleqstate &rhs):_nleqstate_owner(rhs) ,needf(p_struct->needf),needfij(p_struct->needfij),xupdated(p_struct->xupdated),f(p_struct->f),fi(&p_struct->fi),j(&p_struct->j),x(&p_struct->x)
+{
+}
+
+nleqstate& nleqstate::operator=(const nleqstate &rhs)
+{
+    if( this==&rhs )
+        return *this;
+    _nleqstate_owner::operator=(rhs);
+    return *this;
+}
+
+nleqstate::~nleqstate()
+{
+}
+
+
+/*************************************************************************
+
+*************************************************************************/
+_nleqreport_owner::_nleqreport_owner()
+{
+    p_struct = (alglib_impl::nleqreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::nleqreport), NULL);
+    if( p_struct==NULL )
+        throw ap_error("ALGLIB: malloc error");
+    if( !alglib_impl::_nleqreport_init(p_struct, NULL, ae_false) )
+        throw ap_error("ALGLIB: malloc error");
+}
+
+_nleqreport_owner::_nleqreport_owner(const _nleqreport_owner &rhs)
+{
+    p_struct = (alglib_impl::nleqreport*)alglib_impl::ae_malloc(sizeof(alglib_impl::nleqreport), NULL);
+    if( p_struct==NULL )
+        throw ap_error("ALGLIB: malloc error");
+    if( !alglib_impl::_nleqreport_init_copy(p_struct, const_cast<alglib_impl::nleqreport*>(rhs.p_struct), NULL, ae_false) )
+        throw ap_error("ALGLIB: malloc error");
+}
+
+_nleqreport_owner& _nleqreport_owner::operator=(const _nleqreport_owner &rhs)
+{
+    if( this==&rhs )
+        return *this;
+    alglib_impl::_nleqreport_clear(p_struct);
+    if( !alglib_impl::_nleqreport_init_copy(p_struct, const_cast<alglib_impl::nleqreport*>(rhs.p_struct), NULL, ae_false) )
+        throw ap_error("ALGLIB: malloc error");
+    return *this;
+}
+
+_nleqreport_owner::~_nleqreport_owner()
+{
+    alglib_impl::_nleqreport_clear(p_struct);
+    ae_free(p_struct);
+}
+
+alglib_impl::nleqreport* _nleqreport_owner::c_ptr()
+{
+    return p_struct;
+}
+
+alglib_impl::nleqreport* _nleqreport_owner::c_ptr() const
+{
+    return const_cast<alglib_impl::nleqreport*>(p_struct);
+}
+nleqreport::nleqreport() : _nleqreport_owner() ,iterationscount(p_struct->iterationscount),nfunc(p_struct->nfunc),njac(p_struct->njac),terminationtype(p_struct->terminationtype)
+{
+}
+
+nleqreport::nleqreport(const nleqreport &rhs):_nleqreport_owner(rhs) ,iterationscount(p_struct->iterationscount),nfunc(p_struct->nfunc),njac(p_struct->njac),terminationtype(p_struct->terminationtype)
+{
+}
+
+nleqreport& nleqreport::operator=(const nleqreport &rhs)
+{
+    if( this==&rhs )
+        return *this;
+    _nleqreport_owner::operator=(rhs);
+    return *this;
+}
+
+nleqreport::~nleqreport()
+{
+}
+
+/*************************************************************************
+                LEVENBERG-MARQUARDT-LIKE NONLINEAR SOLVER
+
+DESCRIPTION:
+This algorithm solves system of nonlinear equations
+    F[0](x[0], ..., x[n-1])   = 0
+    F[1](x[0], ..., x[n-1])   = 0
+    ...
+    F[M-1](x[0], ..., x[n-1]) = 0
+with M/N do not necessarily coincide.  Algorithm  converges  quadratically
+under following conditions:
+    * the solution set XS is nonempty
+    * for some xs in XS there exist such neighbourhood N(xs) that:
+      * vector function F(x) and its Jacobian J(x) are continuously
+        differentiable on N
+      * ||F(x)|| provides local error bound on N, i.e. there  exists  such
+        c1, that ||F(x)||>c1*distance(x,XS)
+Note that these conditions are much more weaker than usual non-singularity
+conditions. For example, algorithm will converge for any  affine  function
+F (whether its Jacobian singular or not).
+
+
+REQUIREMENTS:
+Algorithm will request following information during its operation:
+* function vector F[] and Jacobian matrix at given point X
+* value of merit function f(x)=F[0]^2(x)+...+F[M-1]^2(x) at given point X
+
+
+USAGE:
+1. User initializes algorithm state with NLEQCreateLM() call
+2. User tunes solver parameters with  NLEQSetCond(),  NLEQSetStpMax()  and
+   other functions
+3. User  calls  NLEQSolve()  function  which  takes  algorithm  state  and
+   pointers (delegates, etc.) to callback functions which calculate  merit
+   function value and Jacobian.
+4. User calls NLEQResults() to get solution
+5. Optionally, user may call NLEQRestartFrom() to  solve  another  problem
+   with same parameters (N/M) but another starting  point  and/or  another
+   function vector. NLEQRestartFrom() allows to reuse already  initialized
+   structure.
+
+
+INPUT PARAMETERS:
+    N       -   space dimension, N>1:
+                * if provided, only leading N elements of X are used
+                * if not provided, determined automatically from size of X
+    M       -   system size
+    X       -   starting point
+
+
+OUTPUT PARAMETERS:
+    State   -   structure which stores algorithm state
+
+
+NOTES:
+1. you may tune stopping conditions with NLEQSetCond() function
+2. if target function contains exp() or other fast growing functions,  and
+   optimization algorithm makes too large steps which leads  to  overflow,
+   use NLEQSetStpMax() function to bound algorithm's steps.
+3. this  algorithm  is  a  slightly  modified implementation of the method
+   described  in  'Levenberg-Marquardt  method  for constrained  nonlinear
+   equations with strong local convergence properties' by Christian Kanzow
+   Nobuo Yamashita and Masao Fukushima and further  developed  in  'On the
+   convergence of a New Levenberg-Marquardt Method'  by  Jin-yan  Fan  and
+   Ya-Xiang Yuan.
+
+
+  -- ALGLIB --
+     Copyright 20.08.2009 by Bochkanov Sergey
+*************************************************************************/
+void nleqcreatelm(const ae_int_t n, const ae_int_t m, const real_1d_array &x, nleqstate &state)
+{
+    alglib_impl::ae_state _alglib_env_state;
+    alglib_impl::ae_state_init(&_alglib_env_state);
+    try
+    {
+        alglib_impl::nleqcreatelm(n, m, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::nleqstate*>(state.c_ptr()), &_alglib_env_state);
+        alglib_impl::ae_state_clear(&_alglib_env_state);
+        return;
+    }
+    catch(alglib_impl::ae_error_type)
+    {
+        throw ap_error(_alglib_env_state.error_msg);
+    }
+    catch(...)
+    {
+        throw;
+    }
+}
+
+/*************************************************************************
+                LEVENBERG-MARQUARDT-LIKE NONLINEAR SOLVER
+
+DESCRIPTION:
+This algorithm solves system of nonlinear equations
+    F[0](x[0], ..., x[n-1])   = 0
+    F[1](x[0], ..., x[n-1])   = 0
+    ...
+    F[M-1](x[0], ..., x[n-1]) = 0
+with M/N do not necessarily coincide.  Algorithm  converges  quadratically
+under following conditions:
+    * the solution set XS is nonempty
+    * for some xs in XS there exist such neighbourhood N(xs) that:
+      * vector function F(x) and its Jacobian J(x) are continuously
+        differentiable on N
+      * ||F(x)|| provides local error bound on N, i.e. there  exists  such
+        c1, that ||F(x)||>c1*distance(x,XS)
+Note that these conditions are much more weaker than usual non-singularity
+conditions. For example, algorithm will converge for any  affine  function
+F (whether its Jacobian singular or not).
+
+
+REQUIREMENTS:
+Algorithm will request following information during its operation:
+* function vector F[] and Jacobian matrix at given point X
+* value of merit function f(x)=F[0]^2(x)+...+F[M-1]^2(x) at given point X
+
+
+USAGE:
+1. User initializes algorithm state with NLEQCreateLM() call
+2. User tunes solver parameters with  NLEQSetCond(),  NLEQSetStpMax()  and
+   other functions
+3. User  calls  NLEQSolve()  function  which  takes  algorithm  state  and
+   pointers (delegates, etc.) to callback functions which calculate  merit
+   function value and Jacobian.
+4. User calls NLEQResults() to get solution
+5. Optionally, user may call NLEQRestartFrom() to  solve  another  problem
+   with same parameters (N/M) but another starting  point  and/or  another
+   function vector. NLEQRestartFrom() allows to reuse already  initialized
+   structure.
+
+
+INPUT PARAMETERS:
+    N       -   space dimension, N>1:
+                * if provided, only leading N elements of X are used
+                * if not provided, determined automatically from size of X
+    M       -   system size
+    X       -   starting point
+
+
+OUTPUT PARAMETERS:
+    State   -   structure which stores algorithm state
+
+
+NOTES:
+1. you may tune stopping conditions with NLEQSetCond() function
+2. if target function contains exp() or other fast growing functions,  and
+   optimization algorithm makes too large steps which leads  to  overflow,
+   use NLEQSetStpMax() function to bound algorithm's steps.
+3. this  algorithm  is  a  slightly  modified implementation of the method
+   described  in  'Levenberg-Marquardt  method  for constrained  nonlinear
+   equations with strong local convergence properties' by Christian Kanzow
+   Nobuo Yamashita and Masao Fukushima and further  developed  in  'On the
+   convergence of a New Levenberg-Marquardt Method'  by  Jin-yan  Fan  and
+   Ya-Xiang Yuan.
+
+
+  -- ALGLIB --
+     Copyright 20.08.2009 by Bochkanov Sergey
+*************************************************************************/
+void nleqcreatelm(const ae_int_t m, const real_1d_array &x, nleqstate &state)
+{
+    alglib_impl::ae_state _alglib_env_state;    
+    ae_int_t n;
+
+    n = x.length();
+    alglib_impl::ae_state_init(&_alglib_env_state);
+    try
+    {
+        alglib_impl::nleqcreatelm(n, m, const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::nleqstate*>(state.c_ptr()), &_alglib_env_state);
+
+        alglib_impl::ae_state_clear(&_alglib_env_state);
+        return;
+    }
+    catch(alglib_impl::ae_error_type)
+    {
+        throw ap_error(_alglib_env_state.error_msg);
+    }
+    catch(...)
+    {
+        throw;
+    }
+}
+
+/*************************************************************************
+This function sets stopping conditions for the nonlinear solver
+
+INPUT PARAMETERS:
+    State   -   structure which stores algorithm state
+    EpsF    -   >=0
+                The subroutine finishes  its work if on k+1-th iteration
+                the condition ||F||<=EpsF is satisfied
+    MaxIts  -   maximum number of iterations. If MaxIts=0, the  number  of
+                iterations is unlimited.
+
+Passing EpsF=0 and MaxIts=0 simultaneously will lead to  automatic
+stopping criterion selection (small EpsF).
+
+NOTES:
+
+  -- ALGLIB --
+     Copyright 20.08.2010 by Bochkanov Sergey
+*************************************************************************/
+void nleqsetcond(const nleqstate &state, const double epsf, const ae_int_t maxits)
+{
+    alglib_impl::ae_state _alglib_env_state;
+    alglib_impl::ae_state_init(&_alglib_env_state);
+    try
+    {
+        alglib_impl::nleqsetcond(const_cast<alglib_impl::nleqstate*>(state.c_ptr()), epsf, maxits, &_alglib_env_state);
+        alglib_impl::ae_state_clear(&_alglib_env_state);
+        return;
+    }
+    catch(alglib_impl::ae_error_type)
+    {
+        throw ap_error(_alglib_env_state.error_msg);
+    }
+    catch(...)
+    {
+        throw;
+    }
+}
+
+/*************************************************************************
+This function turns on/off reporting.
+
+INPUT PARAMETERS:
+    State   -   structure which stores algorithm state
+    NeedXRep-   whether iteration reports are needed or not
+
+If NeedXRep is True, algorithm will call rep() callback function if  it is
+provided to NLEQSolve().
+
+  -- ALGLIB --
+     Copyright 20.08.2010 by Bochkanov Sergey
+*************************************************************************/
+void nleqsetxrep(const nleqstate &state, const bool needxrep)
+{
+    alglib_impl::ae_state _alglib_env_state;
+    alglib_impl::ae_state_init(&_alglib_env_state);
+    try
+    {
+        alglib_impl::nleqsetxrep(const_cast<alglib_impl::nleqstate*>(state.c_ptr()), needxrep, &_alglib_env_state);
+        alglib_impl::ae_state_clear(&_alglib_env_state);
+        return;
+    }
+    catch(alglib_impl::ae_error_type)
+    {
+        throw ap_error(_alglib_env_state.error_msg);
+    }
+    catch(...)
+    {
+        throw;
+    }
+}
+
+/*************************************************************************
+This function sets maximum step length
+
+INPUT PARAMETERS:
+    State   -   structure which stores algorithm state
+    StpMax  -   maximum step length, >=0. Set StpMax to 0.0,  if you don't
+                want to limit step length.
+
+Use this subroutine when target function  contains  exp()  or  other  fast
+growing functions, and algorithm makes  too  large  steps  which  lead  to
+overflow. This function allows us to reject steps that are too large  (and
+therefore expose us to the possible overflow) without actually calculating
+function value at the x+stp*d.
+
+  -- ALGLIB --
+     Copyright 20.08.2010 by Bochkanov Sergey
+*************************************************************************/
+void nleqsetstpmax(const nleqstate &state, const double stpmax)
+{
+    alglib_impl::ae_state _alglib_env_state;
+    alglib_impl::ae_state_init(&_alglib_env_state);
+    try
+    {
+        alglib_impl::nleqsetstpmax(const_cast<alglib_impl::nleqstate*>(state.c_ptr()), stpmax, &_alglib_env_state);
+        alglib_impl::ae_state_clear(&_alglib_env_state);
+        return;
+    }
+    catch(alglib_impl::ae_error_type)
+    {
+        throw ap_error(_alglib_env_state.error_msg);
+    }
+    catch(...)
+    {
+        throw;
+    }
+}
+
+/*************************************************************************
+This function provides reverse communication interface
+Reverse communication interface is not documented or recommended to use.
+See below for functions which provide better documented API
+*************************************************************************/
+bool nleqiteration(const nleqstate &state)
+{
+    alglib_impl::ae_state _alglib_env_state;
+    alglib_impl::ae_state_init(&_alglib_env_state);
+    try
+    {
+        ae_bool result = alglib_impl::nleqiteration(const_cast<alglib_impl::nleqstate*>(state.c_ptr()), &_alglib_env_state);
+        alglib_impl::ae_state_clear(&_alglib_env_state);
+        return *(reinterpret_cast<bool*>(&result));
+    }
+    catch(alglib_impl::ae_error_type)
+    {
+        throw ap_error(_alglib_env_state.error_msg);
+    }
+    catch(...)
+    {
+        throw;
+    }
+}
+
+
+void nleqsolve(nleqstate &state,
+    void (*func)(const real_1d_array &x, double &func, void *ptr),
+    void  (*jac)(const real_1d_array &x, real_1d_array &fi, real_2d_array &jac, void *ptr),
+    void  (*rep)(const real_1d_array &x, double func, void *ptr), 
+    void *ptr)
+{
+    alglib_impl::ae_state _alglib_env_state;
+    if( func==NULL )
+        throw ap_error("ALGLIB: error in 'nleqsolve()' (func is NULL)");
+    if( jac==NULL )
+        throw ap_error("ALGLIB: error in 'nleqsolve()' (jac is NULL)");
+    alglib_impl::ae_state_init(&_alglib_env_state);
+    try
+    {
+        while( alglib_impl::nleqiteration(state.c_ptr(), &_alglib_env_state) )
+        {
+            if( state.needf )
+            {
+                func(state.x, state.f, ptr);
+                continue;
+            }
+            if( state.needfij )
+            {
+                jac(state.x, state.fi, state.j, ptr);
+                continue;
+            }
+            if( state.xupdated )
+            {
+                if( rep!=NULL )
+                    rep(state.x, state.f, ptr);
+                continue;
+            }
+            throw ap_error("ALGLIB: error in 'nleqsolve' (some derivatives were not provided?)");
+        }
+        alglib_impl::ae_state_clear(&_alglib_env_state);
+    }
+    catch(alglib_impl::ae_error_type)
+    {
+        throw ap_error(_alglib_env_state.error_msg);
+    }
+    catch(...)
+    {
+        throw;
+    }
+}
+
+
+
+/*************************************************************************
+NLEQ solver results
+
+INPUT PARAMETERS:
+    State   -   algorithm state.
+
+OUTPUT PARAMETERS:
+    X       -   array[0..N-1], solution
+    Rep     -   optimization report:
+                * Rep.TerminationType completetion code:
+                    * -4    ERROR:  algorithm   has   converged   to   the
+                            stationary point Xf which is local minimum  of
+                            f=F[0]^2+...+F[m-1]^2, but is not solution  of
+                            nonlinear system.
+                    *  1    sqrt(f)<=EpsF.
+                    *  5    MaxIts steps was taken
+                    *  7    stopping conditions are too stringent,
+                            further improvement is impossible
+                * Rep.IterationsCount contains iterations count
+                * NFEV countains number of function calculations
+                * ActiveConstraints contains number of active constraints
+
+  -- ALGLIB --
+     Copyright 20.08.2009 by Bochkanov Sergey
+*************************************************************************/
+void nleqresults(const nleqstate &state, real_1d_array &x, nleqreport &rep)
+{
+    alglib_impl::ae_state _alglib_env_state;
+    alglib_impl::ae_state_init(&_alglib_env_state);
+    try
+    {
+        alglib_impl::nleqresults(const_cast<alglib_impl::nleqstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::nleqreport*>(rep.c_ptr()), &_alglib_env_state);
+        alglib_impl::ae_state_clear(&_alglib_env_state);
+        return;
+    }
+    catch(alglib_impl::ae_error_type)
+    {
+        throw ap_error(_alglib_env_state.error_msg);
+    }
+    catch(...)
+    {
+        throw;
+    }
+}
+
+/*************************************************************************
+NLEQ solver results
+
+Buffered implementation of NLEQResults(), which uses pre-allocated  buffer
+to store X[]. If buffer size is  too  small,  it  resizes  buffer.  It  is
+intended to be used in the inner cycles of performance critical algorithms
+where array reallocation penalty is too large to be ignored.
+
+  -- ALGLIB --
+     Copyright 20.08.2009 by Bochkanov Sergey
+*************************************************************************/
+void nleqresultsbuf(const nleqstate &state, real_1d_array &x, nleqreport &rep)
+{
+    alglib_impl::ae_state _alglib_env_state;
+    alglib_impl::ae_state_init(&_alglib_env_state);
+    try
+    {
+        alglib_impl::nleqresultsbuf(const_cast<alglib_impl::nleqstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), const_cast<alglib_impl::nleqreport*>(rep.c_ptr()), &_alglib_env_state);
+        alglib_impl::ae_state_clear(&_alglib_env_state);
+        return;
+    }
+    catch(alglib_impl::ae_error_type)
+    {
+        throw ap_error(_alglib_env_state.error_msg);
+    }
+    catch(...)
+    {
+        throw;
+    }
+}
+
+/*************************************************************************
+This  subroutine  restarts  CG  algorithm from new point. All optimization
+parameters are left unchanged.
+
+This  function  allows  to  solve multiple  optimization  problems  (which
+must have same number of dimensions) without object reallocation penalty.
+
+INPUT PARAMETERS:
+    State   -   structure used for reverse communication previously
+                allocated with MinCGCreate call.
+    X       -   new starting point.
+    BndL    -   new lower bounds
+    BndU    -   new upper bounds
+
+  -- ALGLIB --
+     Copyright 30.07.2010 by Bochkanov Sergey
+*************************************************************************/
+void nleqrestartfrom(const nleqstate &state, const real_1d_array &x)
+{
+    alglib_impl::ae_state _alglib_env_state;
+    alglib_impl::ae_state_init(&_alglib_env_state);
+    try
+    {
+        alglib_impl::nleqrestartfrom(const_cast<alglib_impl::nleqstate*>(state.c_ptr()), const_cast<alglib_impl::ae_vector*>(x.c_ptr()), &_alglib_env_state);
+        alglib_impl::ae_state_clear(&_alglib_env_state);
+        return;
+    }
+    catch(alglib_impl::ae_error_type)
+    {
+        throw ap_error(_alglib_env_state.error_msg);
+    }
+    catch(...)
+    {
+        throw;
+    }
+}
+}
+
+/////////////////////////////////////////////////////////////////////////
+//
+// THIS SECTION CONTAINS IMPLEMENTATION OF COMPUTATIONAL CORE
+//
+/////////////////////////////////////////////////////////////////////////
+namespace alglib_impl
+{
+static void densesolver_rmatrixlusolveinternal(/* Real    */ ae_matrix* lua,
+     /* Integer */ ae_vector* p,
+     double scalea,
+     ae_int_t n,
+     /* Real    */ ae_matrix* a,
+     ae_bool havea,
+     /* Real    */ ae_matrix* b,
+     ae_int_t m,
+     ae_int_t* info,
+     densesolverreport* rep,
+     /* Real    */ ae_matrix* x,
+     ae_state *_state);
+static void densesolver_spdmatrixcholeskysolveinternal(/* Real    */ ae_matrix* cha,
+     double sqrtscalea,
+     ae_int_t n,
+     ae_bool isupper,
+     /* Real    */ ae_matrix* a,
+     ae_bool havea,
+     /* Real    */ ae_matrix* b,
+     ae_int_t m,
+     ae_int_t* info,
+     densesolverreport* rep,
+     /* Real    */ ae_matrix* x,
+     ae_state *_state);
+static void densesolver_cmatrixlusolveinternal(/* Complex */ ae_matrix* lua,
+     /* Integer */ ae_vector* p,
+     double scalea,
+     ae_int_t n,
+     /* Complex */ ae_matrix* a,
+     ae_bool havea,
+     /* Complex */ ae_matrix* b,
+     ae_int_t m,
+     ae_int_t* info,
+     densesolverreport* rep,
+     /* Complex */ ae_matrix* x,
+     ae_state *_state);
+static void densesolver_hpdmatrixcholeskysolveinternal(/* Complex */ ae_matrix* cha,
+     double sqrtscalea,
+     ae_int_t n,
+     ae_bool isupper,
+     /* Complex */ ae_matrix* a,
+     ae_bool havea,
+     /* Complex */ ae_matrix* b,
+     ae_int_t m,
+     ae_int_t* info,
+     densesolverreport* rep,
+     /* Complex */ ae_matrix* x,
+     ae_state *_state);
+static ae_int_t densesolver_densesolverrfsmax(ae_int_t n,
+     double r1,
+     double rinf,
+     ae_state *_state);
+static ae_int_t densesolver_densesolverrfsmaxv2(ae_int_t n,
+     double r2,
+     ae_state *_state);
+static void densesolver_rbasiclusolve(/* Real    */ ae_matrix* lua,
+     /* Integer */ ae_vector* p,
+     double scalea,
+     ae_int_t n,
+     /* Real    */ ae_vector* xb,
+     /* Real    */ ae_vector* tmp,
+     ae_state *_state);
+static void densesolver_spdbasiccholeskysolve(/* Real    */ ae_matrix* cha,
+     double sqrtscalea,
+     ae_int_t n,
+     ae_bool isupper,
+     /* Real    */ ae_vector* xb,
+     /* Real    */ ae_vector* tmp,
+     ae_state *_state);
+static void densesolver_cbasiclusolve(/* Complex */ ae_matrix* lua,
+     /* Integer */ ae_vector* p,
+     double scalea,
+     ae_int_t n,
+     /* Complex */ ae_vector* xb,
+     /* Complex */ ae_vector* tmp,
+     ae_state *_state);
+static void densesolver_hpdbasiccholeskysolve(/* Complex */ ae_matrix* cha,
+     double sqrtscalea,
+     ae_int_t n,
+     ae_bool isupper,
+     /* Complex */ ae_vector* xb,
+     /* Complex */ ae_vector* tmp,
+     ae_state *_state);
+
+
+static ae_int_t nleq_armijomaxfev = 20;
+static void nleq_clearrequestfields(nleqstate* state, ae_state *_state);
+static ae_bool nleq_increaselambda(double* lambdav,
+     double* nu,
+     double lambdaup,
+     ae_state *_state);
+static void nleq_decreaselambda(double* lambdav,
+     double* nu,
+     double lambdadown,
+     ae_state *_state);
+
+
+
+
+
+/*************************************************************************
+Dense solver.
+
+This  subroutine  solves  a  system  A*x=b,  where A is NxN non-denegerate
+real matrix, x and b are vectors.
+
+Algorithm features:
+* automatic detection of degenerate cases
+* condition number estimation
+* iterative refinement
+* O(N^3) complexity
+
+INPUT PARAMETERS
+    A       -   array[0..N-1,0..N-1], system matrix
+    N       -   size of A
+    B       -   array[0..N-1], right part
+
+OUTPUT PARAMETERS
+    Info    -   return code:
+                * -3    A is singular, or VERY close to singular.
+                        X is filled by zeros in such cases.
+                * -1    N<=0 was passed
+                *  1    task is solved (but matrix A may be ill-conditioned,
+                        check R1/RInf parameters for condition numbers).
+    Rep     -   solver report, see below for more info
+    X       -   array[0..N-1], it contains:
+                * solution of A*x=b if A is non-singular (well-conditioned
+                  or ill-conditioned, but not very close to singular)
+                * zeros,  if  A  is  singular  or  VERY  close to singular
+                  (in this case Info=-3).
+
+SOLVER REPORT
+
+Subroutine sets following fields of the Rep structure:
+* R1        reciprocal of condition number: 1/cond(A), 1-norm.
+* RInf      reciprocal of condition number: 1/cond(A), inf-norm.
+
+  -- ALGLIB --
+     Copyright 27.01.2010 by Bochkanov Sergey
+*************************************************************************/
+void rmatrixsolve(/* Real    */ ae_matrix* a,
+     ae_int_t n,
+     /* Real    */ ae_vector* b,
+     ae_int_t* info,
+     densesolverreport* rep,
+     /* Real    */ ae_vector* x,
+     ae_state *_state)
+{
+    ae_frame _frame_block;
+    ae_matrix bm;
+    ae_matrix xm;
+
+    ae_frame_make(_state, &_frame_block);
+    *info = 0;
+    _densesolverreport_clear(rep);
+    ae_vector_clear(x);
+    ae_matrix_init(&bm, 0, 0, DT_REAL, _state, ae_true);
+    ae_matrix_init(&xm, 0, 0, DT_REAL, _state, ae_true);
+
+    if( n<=0 )
+    {
+        *info = -1;
+        ae_frame_leave(_state);
+        return;
+    }
+    ae_matrix_set_length(&bm, n, 1, _state);
+    ae_v_move(&bm.ptr.pp_double[0][0], bm.stride, &b->ptr.p_double[0], 1, ae_v_len(0,n-1));
+    rmatrixsolvem(a, n, &bm, 1, ae_true, info, rep, &xm, _state);
+    ae_vector_set_length(x, n, _state);
+    ae_v_move(&x->ptr.p_double[0], 1, &xm.ptr.pp_double[0][0], xm.stride, ae_v_len(0,n-1));
+    ae_frame_leave(_state);
+}
+
+
+/*************************************************************************
+Dense solver.
+
+Similar to RMatrixSolve() but solves task with multiple right parts (where
+b and x are NxM matrices).
+
+Algorithm features:
+* automatic detection of degenerate cases
+* condition number estimation
+* optional iterative refinement
+* O(N^3+M*N^2) complexity
+
+INPUT PARAMETERS
+    A       -   array[0..N-1,0..N-1], system matrix
+    N       -   size of A
+    B       -   array[0..N-1,0..M-1], right part
+    M       -   right part size
+    RFS     -   iterative refinement switch:
+                * True - refinement is used.
+                  Less performance, more precision.
+                * False - refinement is not used.
+                  More performance, less precision.
+
+OUTPUT PARAMETERS
+    Info    -   same as in RMatrixSolve
+    Rep     -   same as in RMatrixSolve
+    X       -   same as in RMatrixSolve
+
+  -- ALGLIB --
+     Copyright 27.01.2010 by Bochkanov Sergey
+*************************************************************************/
+void rmatrixsolvem(/* Real    */ ae_matrix* a,
+     ae_int_t n,
+     /* Real    */ ae_matrix* b,
+     ae_int_t m,
+     ae_bool rfs,
+     ae_int_t* info,
+     densesolverreport* rep,
+     /* Real    */ ae_matrix* x,
+     ae_state *_state)
+{
+    ae_frame _frame_block;
+    ae_matrix da;
+    ae_matrix emptya;
+    ae_vector p;
+    double scalea;
+    ae_int_t i;
+    ae_int_t j;
+
+    ae_frame_make(_state, &_frame_block);
+    *info = 0;
+    _densesolverreport_clear(rep);
+    ae_matrix_clear(x);
+    ae_matrix_init(&da, 0, 0, DT_REAL, _state, ae_true);
+    ae_matrix_init(&emptya, 0, 0, DT_REAL, _state, ae_true);
+    ae_vector_init(&p, 0, DT_INT, _state, ae_true);
+
+    
+    /*
+     * prepare: check inputs, allocate space...
+     */
+    if( n<=0||m<=0 )
+    {
+        *info = -1;
+        ae_frame_leave(_state);
+        return;
+    }
+    ae_matrix_set_length(&da, n, n, _state);
+    
+    /*
+     * 1. scale matrix, max(|A[i,j]|)
+     * 2. factorize scaled matrix
+     * 3. solve
+     */
+    scalea = 0;
+    for(i=0; i<=n-1; i++)
+    {
+        for(j=0; j<=n-1; j++)
+        {
+            scalea = ae_maxreal(scalea, ae_fabs(a->ptr.pp_double[i][j], _state), _state);
+        }
+    }
+    if( ae_fp_eq(scalea,0) )
+    {
+        scalea = 1;
+    }
+    scalea = 1/scalea;
+    for(i=0; i<=n-1; i++)
+    {
+        ae_v_move(&da.ptr.pp_double[i][0], 1, &a->ptr.pp_double[i][0], 1, ae_v_len(0,n-1));
+    }
+    rmatrixlu(&da, n, n, &p, _state);
+    if( rfs )
+    {
+        densesolver_rmatrixlusolveinternal(&da, &p, scalea, n, a, ae_true, b, m, info, rep, x, _state);
+    }
+    else
+    {
+        densesolver_rmatrixlusolveinternal(&da, &p, scalea, n, &emptya, ae_false, b, m, info, rep, x, _state);
+    }
+    ae_frame_leave(_state);
+}
+
+
+/*************************************************************************
+Dense solver.
+
+This  subroutine  solves  a  system  A*X=B,  where A is NxN non-denegerate
+real matrix given by its LU decomposition, X and B are NxM real matrices.
+
+Algorithm features:
+* automatic detection of degenerate cases
+* O(N^2) complexity
+* condition number estimation
+
+No iterative refinement  is provided because exact form of original matrix
+is not known to subroutine. Use RMatrixSolve or RMatrixMixedSolve  if  you
+need iterative refinement.
+
+INPUT PARAMETERS
+    LUA     -   array[0..N-1,0..N-1], LU decomposition, RMatrixLU result
+    P       -   array[0..N-1], pivots array, RMatrixLU result
+    N       -   size of A
+    B       -   array[0..N-1], right part
+
+OUTPUT PARAMETERS
+    Info    -   same as in RMatrixSolve
+    Rep     -   same as in RMatrixSolve
+    X       -   same as in RMatrixSolve
+    
+  -- ALGLIB --
+     Copyright 27.01.2010 by Bochkanov Sergey
+*************************************************************************/
+void rmatrixlusolve(/* Real    */ ae_matrix* lua,
+     /* Integer */ ae_vector* p,
+     ae_int_t n,
+     /* Real    */ ae_vector* b,
+     ae_int_t* info,
+     densesolverreport* rep,
+     /* Real    */ ae_vector* x,
+     ae_state *_state)
+{
+    ae_frame _frame_block;
+    ae_matrix bm;
+    ae_matrix xm;
+
+    ae_frame_make(_state, &_frame_block);
+    *info = 0;
+    _densesolverreport_clear(rep);
+    ae_vector_clear(x);
+    ae_matrix_init(&bm, 0, 0, DT_REAL, _state, ae_true);
+    ae_matrix_init(&xm, 0, 0, DT_REAL, _state, ae_true);
+
+    if( n<=0 )
+    {
+        *info = -1;
+        ae_frame_leave(_state);
+        return;
+    }
+    ae_matrix_set_length(&bm, n, 1, _state);
+    ae_v_move(&bm.ptr.pp_double[0][0], bm.stride, &b->ptr.p_double[0], 1, ae_v_len(0,n-1));
+    rmatrixlusolvem(lua, p, n, &bm, 1, info, rep, &xm, _state);
+    ae_vector_set_length(x, n, _state);
+    ae_v_move(&x->ptr.p_double[0], 1, &xm.ptr.pp_double[0][0], xm.stride, ae_v_len(0,n-1));
+    ae_frame_leave(_state);
+}
+
+
+/*************************************************************************
+Dense solver.
+
+Similar to RMatrixLUSolve() but solves task with multiple right parts
+(where b and x are NxM matrices).
+
+Algorithm features:
+* automatic detection of degenerate cases
+* O(M*N^2) complexity
+* condition number estimation
+
+No iterative refinement  is provided because exact form of original matrix
+is not known to subroutine. Use RMatrixSolve or RMatrixMixedSolve  if  you
+need iterative refinement.
+
+INPUT PARAMETERS
+    LUA     -   array[0..N-1,0..N-1], LU decomposition, RMatrixLU result
+    P       -   array[0..N-1], pivots array, RMatrixLU result
+    N       -   size of A
+    B       -   array[0..N-1,0..M-1], right part
+    M       -   right part size
+
+OUTPUT PARAMETERS
+    Info    -   same as in RMatrixSolve
+    Rep     -   same as in RMatrixSolve
+    X       -   same as in RMatrixSolve
+
+  -- ALGLIB --
+     Copyright 27.01.2010 by Bochkanov Sergey
+*************************************************************************/
+void rmatrixlusolvem(/* Real    */ ae_matrix* lua,
+     /* Integer */ ae_vector* p,
+     ae_int_t n,
+     /* Real    */ ae_matrix* b,
+     ae_int_t m,
+     ae_int_t* info,
+     densesolverreport* rep,
+     /* Real    */ ae_matrix* x,
+     ae_state *_state)
+{
+    ae_frame _frame_block;
+    ae_matrix emptya;
+    ae_int_t i;
+    ae_int_t j;
+    double scalea;
+
+    ae_frame_make(_state, &_frame_block);
+    *info = 0;
+    _densesolverreport_clear(rep);
+    ae_matrix_clear(x);
+    ae_matrix_init(&emptya, 0, 0, DT_REAL, _state, ae_true);
+
+    
+    /*
+     * prepare: check inputs, allocate space...
+     */
+    if( n<=0||m<=0 )
+    {
+        *info = -1;
+        ae_frame_leave(_state);
+        return;
+    }
+    
+    /*
+     * 1. scale matrix, max(|U[i,j]|)
+     *    we assume that LU is in its normal form, i.e. |L[i,j]|<=1
+     * 2. solve
+     */
+    scalea = 0;
+    for(i=0; i<=n-1; i++)
+    {
+        for(j=i; j<=n-1; j++)
+        {
+            scalea = ae_maxreal(scalea, ae_fabs(lua->ptr.pp_double[i][j], _state), _state);
+        }
+    }
+    if( ae_fp_eq(scalea,0) )
+    {
+        scalea = 1;
+    }
+    scalea = 1/scalea;
+    densesolver_rmatrixlusolveinternal(lua, p, scalea, n, &emptya, ae_false, b, m, info, rep, x, _state);
+    ae_frame_leave(_state);
+}
+
+
+/*************************************************************************
+Dense solver.
+
+This  subroutine  solves  a  system  A*x=b,  where BOTH ORIGINAL A AND ITS
+LU DECOMPOSITION ARE KNOWN. You can use it if for some  reasons  you  have
+both A and its LU decomposition.
+
+Algorithm features:
+* automatic detection of degenerate cases
+* condition number estimation
+* iterative refinement
+* O(N^2) complexity
+
+INPUT PARAMETERS
+    A       -   array[0..N-1,0..N-1], system matrix
+    LUA     -   array[0..N-1,0..N-1], LU decomposition, RMatrixLU result
+    P       -   array[0..N-1], pivots array, RMatrixLU result
+    N       -   size of A
+    B       -   array[0..N-1], right part
+
+OUTPUT PARAMETERS
+    Info    -   same as in RMatrixSolveM
+    Rep     -   same as in RMatrixSolveM
+    X       -   same as in RMatrixSolveM
+
+  -- ALGLIB --
+     Copyright 27.01.2010 by Bochkanov Sergey
+*************************************************************************/
+void rmatrixmixedsolve(/* Real    */ ae_matrix* a,
+     /* Real    */ ae_matrix* lua,
+     /* Integer */ ae_vector* p,
+     ae_int_t n,
+     /* Real    */ ae_vector* b,
+     ae_int_t* info,
+     densesolverreport* rep,
+     /* Real    */ ae_vector* x,
+     ae_state *_state)
+{
+    ae_frame _frame_block;
+    ae_matrix bm;
+    ae_matrix xm;
+
+    ae_frame_make(_state, &_frame_block);
+    *info = 0;
+    _densesolverreport_clear(rep);
+    ae_vector_clear(x);
+    ae_matrix_init(&bm, 0, 0, DT_REAL, _state, ae_true);
+    ae_matrix_init(&xm, 0, 0, DT_REAL, _state, ae_true);
+
+    if( n<=0 )
+    {
+        *info = -1;
+        ae_frame_leave(_state);
+        return;
+    }
+    ae_matrix_set_length(&bm, n, 1, _state);
+    ae_v_move(&bm.ptr.pp_double[0][0], bm.stride, &b->ptr.p_double[0], 1, ae_v_len(0,n-1));
+    rmatrixmixedsolvem(a, lua, p, n, &bm, 1, info, rep, &xm, _state);
+    ae_vector_set_length(x, n, _state);
+    ae_v_move(&x->ptr.p_double[0], 1, &xm.ptr.pp_double[0][0], xm.stride, ae_v_len(0,n-1));
+    ae_frame_leave(_state);
+}
+
+
+/*************************************************************************
+Dense solver.
+
+Similar to RMatrixMixedSolve() but  solves task with multiple right  parts
+(where b and x are NxM matrices).
+
+Algorithm features:
+* automatic detection of degenerate cases
+* condition number estimation
+* iterative refinement
+* O(M*N^2) complexity
+
+INPUT PARAMETERS
+    A       -   array[0..N-1,0..N-1], system matrix
+    LUA     -   array[0..N-1,0..N-1], LU decomposition, RMatrixLU result
+    P       -   array[0..N-1], pivots array, RMatrixLU result
+    N       -   size of A
+    B       -   array[0..N-1,0..M-1], right part
+    M       -   right part size
+
+OUTPUT PARAMETERS
+    Info    -   same as in RMatrixSolveM
+    Rep     -   same as in RMatrixSolveM
+    X       -   same as in RMatrixSolveM
+
+  -- ALGLIB --
+     Copyright 27.01.2010 by Bochkanov Sergey
+*************************************************************************/
+void rmatrixmixedsolvem(/* Real    */ ae_matrix* a,
+     /* Real    */ ae_matrix* lua,
+     /* Integer */ ae_vector* p,
+     ae_int_t n,
+     /* Real    */ ae_matrix* b,
+     ae_int_t m,
+     ae_int_t* info,
+     densesolverreport* rep,
+     /* Real    */ ae_matrix* x,
+     ae_state *_state)
+{
+    double scalea;
+    ae_int_t i;
+    ae_int_t j;
+
+    *info = 0;
+    _densesolverreport_clear(rep);
+    ae_matrix_clear(x);
+
+    
+    /*
+     * prepare: check inputs, allocate space...
+     */
+    if( n<=0||m<=0 )
+    {
+        *info = -1;
+        return;
+    }
+    
+    /*
+     * 1. scale matrix, max(|A[i,j]|)
+     * 2. factorize scaled matrix
+     * 3. solve
+     */
+    scalea = 0;
+    for(i=0; i<=n-1; i++)
+    {
+        for(j=0; j<=n-1; j++)
+        {
+            scalea = ae_maxreal(scalea, ae_fabs(a->ptr.pp_double[i][j], _state), _state);
+        }
+    }
+    if( ae_fp_eq(scalea,0) )
+    {
+        scalea = 1;
+    }
+    scalea = 1/scalea;
+    densesolver_rmatrixlusolveinternal(lua, p, scalea, n, a, ae_true, b, m, info, rep, x, _state);
+}
+
+
+/*************************************************************************
+Dense solver. Same as RMatrixSolveM(), but for complex matrices.
+
+Algorithm features:
+* automatic detection of degenerate cases
+* condition number estimation
+* iterative refinement
+* O(N^3+M*N^2) complexity
+
+INPUT PARAMETERS
+    A       -   array[0..N-1,0..N-1], system matrix
+    N       -   size of A
+    B       -   array[0..N-1,0..M-1], right part
+    M       -   right part size
+    RFS     -   iterative refinement switch:
+                * True - refinement is used.
+                  Less performance, more precision.
+                * False - refinement is not used.
+                  More performance, less precision.
+
+OUTPUT PARAMETERS
+    Info    -   same as in RMatrixSolve
+    Rep     -   same as in RMatrixSolve
+    X       -   same as in RMatrixSolve
+
+  -- ALGLIB --
+     Copyright 27.01.2010 by Bochkanov Sergey
+*************************************************************************/
+void cmatrixsolvem(/* Complex */ ae_matrix* a,
+     ae_int_t n,
+     /* Complex */ ae_matrix* b,
+     ae_int_t m,
+     ae_bool rfs,
+     ae_int_t* info,
+     densesolverreport* rep,
+     /* Complex */ ae_matrix* x,
+     ae_state *_state)
+{
+    ae_frame _frame_block;
+    ae_matrix da;
+    ae_matrix emptya;
+    ae_vector p;
+    double scalea;
+    ae_int_t i;
+    ae_int_t j;
+
+    ae_frame_make(_state, &_frame_block);
+    *info = 0;
+    _densesolverreport_clear(rep);
+    ae_matrix_clear(x);
+    ae_matrix_init(&da, 0, 0, DT_COMPLEX, _state, ae_true);
+    ae_matrix_init(&emptya, 0, 0, DT_COMPLEX, _state, ae_true);
+    ae_vector_init(&p, 0, DT_INT, _state, ae_true);
+
+    
+    /*
+     * prepare: check inputs, allocate space...
+     */
+    if( n<=0||m<=0 )
+    {
+        *info = -1;
+        ae_frame_leave(_state);
+        return;
+    }
+    ae_matrix_set_length(&da, n, n, _state);
+    
+    /*
+     * 1. scale matrix, max(|A[i,j]|)
+     * 2. factorize scaled matrix
+     * 3. solve
+     */
+    scalea = 0;
+    for(i=0; i<=n-1; i++)
+    {
+        for(j=0; j<=n-1; j++)
+        {
+            scalea = ae_maxreal(scalea, ae_c_abs(a->ptr.pp_complex[i][j], _state), _state);
+        }
+    }
+    if( ae_fp_eq(scalea,0) )
+    {
+        scalea = 1;
+    }
+    scalea = 1/scalea;
+    for(i=0; i<=n-1; i++)
+    {
+        ae_v_cmove(&da.ptr.pp_complex[i][0], 1, &a->ptr.pp_complex[i][0], 1, "N", ae_v_len(0,n-1));
+    }
+    cmatrixlu(&da, n, n, &p, _state);
+    if( rfs )
+    {
+        densesolver_cmatrixlusolveinternal(&da, &p, scalea, n, a, ae_true, b, m, info, rep, x, _state);
+    }
+    else
+    {
+        densesolver_cmatrixlusolveinternal(&da, &p, scalea, n, &emptya, ae_false, b, m, info, rep, x, _state);
+    }
+    ae_frame_leave(_state);
+}
+
+
+/*************************************************************************
+Dense solver. Same as RMatrixSolve(), but for complex matrices.
+
+Algorithm features:
+* automatic detection of degenerate cases
+* condition number estimation
+* iterative refinement
+* O(N^3) complexity
+
+INPUT PARAMETERS
+    A       -   array[0..N-1,0..N-1], system matrix
+    N       -   size of A
+    B       -   array[0..N-1], right part
+
+OUTPUT PARAMETERS
+    Info    -   same as in RMatrixSolve
+    Rep     -   same as in RMatrixSolve
+    X       -   same as in RMatrixSolve
+
+  -- ALGLIB --
+     Copyright 27.01.2010 by Bochkanov Sergey
+*************************************************************************/
+void cmatrixsolve(/* Complex */ ae_matrix* a,
+     ae_int_t n,
+     /* Complex */ ae_vector* b,
+     ae_int_t* info,
+     densesolverreport* rep,
+     /* Complex */ ae_vector* x,
+     ae_state *_state)
+{
+    ae_frame _frame_block;
+    ae_matrix bm;
+    ae_matrix xm;
+
+    ae_frame_make(_state, &_frame_block);
+    *info = 0;
+    _densesolverreport_clear(rep);
+    ae_vector_clear(x);
+    ae_matrix_init(&bm, 0, 0, DT_COMPLEX, _state, ae_true);
+    ae_matrix_init(&xm, 0, 0, DT_COMPLEX, _state, ae_true);
+
+    if( n<=0 )
+    {
+        *info = -1;
+        ae_frame_leave(_state);
+        return;
+    }
+    ae_matrix_set_length(&bm, n, 1, _state);
+    ae_v_cmove(&bm.ptr.pp_complex[0][0], bm.stride, &b->ptr.p_complex[0], 1, "N", ae_v_len(0,n-1));
+    cmatrixsolvem(a, n, &bm, 1, ae_true, info, rep, &xm, _state);
+    ae_vector_set_length(x, n, _state);
+    ae_v_cmove(&x->ptr.p_complex[0], 1, &xm.ptr.pp_complex[0][0], xm.stride, "N", ae_v_len(0,n-1));
+    ae_frame_leave(_state);
+}
+
+
+/*************************************************************************
+Dense solver. Same as RMatrixLUSolveM(), but for complex matrices.
+
+Algorithm features:
+* automatic detection of degenerate cases
+* O(M*N^2) complexity
+* condition number estimation
+
+No iterative refinement  is provided because exact form of original matrix
+is not known to subroutine. Use CMatrixSolve or CMatrixMixedSolve  if  you
+need iterative refinement.
+
+INPUT PARAMETERS
+    LUA     -   array[0..N-1,0..N-1], LU decomposition, RMatrixLU result
+    P       -   array[0..N-1], pivots array, RMatrixLU result
+    N       -   size of A
+    B       -   array[0..N-1,0..M-1], right part
+    M       -   right part size
+
+OUTPUT PARAMETERS
+    Info    -   same as in RMatrixSolve
+    Rep     -   same as in RMatrixSolve
+    X       -   same as in RMatrixSolve
+
+  -- ALGLIB --
+     Copyright 27.01.2010 by Bochkanov Sergey
+*************************************************************************/
+void cmatrixlusolvem(/* Complex */ ae_matrix* lua,
+     /* Integer */ ae_vector* p,
+     ae_int_t n,
+     /* Complex */ ae_matrix* b,
+     ae_int_t m,
+     ae_int_t* info,
+     densesolverreport* rep,
+     /* Complex */ ae_matrix* x,
+     ae_state *_state)
+{
+    ae_frame _frame_block;
+    ae_matrix emptya;
+    ae_int_t i;
+    ae_int_t j;
+    double scalea;
+
+    ae_frame_make(_state, &_frame_block);
+    *info = 0;
+    _densesolverreport_clear(rep);
+    ae_matrix_clear(x);
+    ae_matrix_init(&emptya, 0, 0, DT_COMPLEX, _state, ae_true);
+
+    
+    /*
+     * prepare: check inputs, allocate space...
+     */
+    if( n<=0||m<=0 )
+    {
+        *info = -1;
+        ae_frame_leave(_state);
+        return;
+    }
+    
+    /*
+     * 1. scale matrix, max(|U[i,j]|)
+     *    we assume that LU is in its normal form, i.e. |L[i,j]|<=1
+     * 2. solve
+     */
+    scalea = 0;
+    for(i=0; i<=n-1; i++)
+    {
+        for(j=i; j<=n-1; j++)
+        {
+            scalea = ae_maxreal(scalea, ae_c_abs(lua->ptr.pp_complex[i][j], _state), _state);
+        }
+    }
+    if( ae_fp_eq(scalea,0) )
+    {
+        scalea = 1;
+    }
+    scalea = 1/scalea;
+    densesolver_cmatrixlusolveinternal(lua, p, scalea, n, &emptya, ae_false, b, m, info, rep, x, _state);
+    ae_frame_leave(_state);
+}
+
+
+/*************************************************************************
+Dense solver. Same as RMatrixLUSolve(), but for complex matrices.
+
+Algorithm features:
+* automatic detection of degenerate cases
+* O(N^2) complexity
+* condition number estimation
+
+No iterative refinement is provided because exact form of original matrix
+is not known to subroutine. Use CMatrixSolve or CMatrixMixedSolve  if  you
+need iterative refinement.
+
+INPUT PARAMETERS
+    LUA     -   array[0..N-1,0..N-1], LU decomposition, CMatrixLU result
+    P       -   array[0..N-1], pivots array, CMatrixLU result
+    N       -   size of A
+    B       -   array[0..N-1], right part
+
+OUTPUT PARAMETERS
+    Info    -   same as in RMatrixSolve
+    Rep     -   same as in RMatrixSolve
+    X       -   same as in RMatrixSolve
+
+  -- ALGLIB --
+     Copyright 27.01.2010 by Bochkanov Sergey
+*************************************************************************/
+void cmatrixlusolve(/* Complex */ ae_matrix* lua,
+     /* Integer */ ae_vector* p,
+     ae_int_t n,
+     /* Complex */ ae_vector* b,
+     ae_int_t* info,
+     densesolverreport* rep,
+     /* Complex */ ae_vector* x,
+     ae_state *_state)
+{
+    ae_frame _frame_block;
+    ae_matrix bm;
+    ae_matrix xm;
+
+    ae_frame_make(_state, &_frame_block);
+    *info = 0;
+    _densesolverreport_clear(rep);
+    ae_vector_clear(x);
+    ae_matrix_init(&bm, 0, 0, DT_COMPLEX, _state, ae_true);
+    ae_matrix_init(&xm, 0, 0, DT_COMPLEX, _state, ae_true);
+
+    if( n<=0 )
+    {
+        *info = -1;
+        ae_frame_leave(_state);
+        return;
+    }
+    ae_matrix_set_length(&bm, n, 1, _state);
+    ae_v_cmove(&bm.ptr.pp_complex[0][0], bm.stride, &b->ptr.p_complex[0], 1, "N", ae_v_len(0,n-1));
+    cmatrixlusolvem(lua, p, n, &bm, 1, info, rep, &xm, _state);
+    ae_vector_set_length(x, n, _state);
+    ae_v_cmove(&x->ptr.p_complex[0], 1, &xm.ptr.pp_complex[0][0], xm.stride, "N", ae_v_len(0,n-1));
+    ae_frame_leave(_state);
+}
+
+
+/*************************************************************************
+Dense solver. Same as RMatrixMixedSolveM(), but for complex matrices.
+
+Algorithm features:
+* automatic detection of degenerate cases
+* condition number estimation
+* iterative refinement
+* O(M*N^2) complexity
+
+INPUT PARAMETERS
+    A       -   array[0..N-1,0..N-1], system matrix
+    LUA     -   array[0..N-1,0..N-1], LU decomposition, CMatrixLU result
+    P       -   array[0..N-1], pivots array, CMatrixLU result
+    N       -   size of A
+    B       -   array[0..N-1,0..M-1], right part
+    M       -   right part size
+
+OUTPUT PARAMETERS
+    Info    -   same as in RMatrixSolveM
+    Rep     -   same as in RMatrixSolveM
+    X       -   same as in RMatrixSolveM
+
+  -- ALGLIB --
+     Copyright 27.01.2010 by Bochkanov Sergey
+*************************************************************************/
+void cmatrixmixedsolvem(/* Complex */ ae_matrix* a,
+     /* Complex */ ae_matrix* lua,
+     /* Integer */ ae_vector* p,
+     ae_int_t n,
+     /* Complex */ ae_matrix* b,
+     ae_int_t m,
+     ae_int_t* info,
+     densesolverreport* rep,
+     /* Complex */ ae_matrix* x,
+     ae_state *_state)
+{
+    double scalea;
+    ae_int_t i;
+    ae_int_t j;
+
+    *info = 0;
+    _densesolverreport_clear(rep);
+    ae_matrix_clear(x);
+
+    
+    /*
+     * prepare: check inputs, allocate space...
+     */
+    if( n<=0||m<=0 )
+    {
+        *info = -1;
+        return;
+    }
+    
+    /*
+     * 1. scale matrix, max(|A[i,j]|)
+     * 2. factorize scaled matrix
+     * 3. solve
+     */
+    scalea = 0;
+    for(i=0; i<=n-1; i++)
+    {
+        for(j=0; j<=n-1; j++)
+        {
+            scalea = ae_maxreal(scalea, ae_c_abs(a->ptr.pp_complex[i][j], _state), _state);
+        }
+    }
+    if( ae_fp_eq(scalea,0) )
+    {
+        scalea = 1;
+    }
+    scalea = 1/scalea;
+    densesolver_cmatrixlusolveinternal(lua, p, scalea, n, a, ae_true, b, m, info, rep, x, _state);
+}
+
+
+/*************************************************************************
+Dense solver. Same as RMatrixMixedSolve(), but for complex matrices.
+
+Algorithm features:
+* automatic detection of degenerate cases
+* condition number estimation
+* iterative refinement
+* O(N^2) complexity
+
+INPUT PARAMETERS
+    A       -   array[0..N-1,0..N-1], system matrix
+    LUA     -   array[0..N-1,0..N-1], LU decomposition, CMatrixLU result
+    P       -   array[0..N-1], pivots array, CMatrixLU result
+    N       -   size of A
+    B       -   array[0..N-1], right part
+
+OUTPUT PARAMETERS
+    Info    -   same as in RMatrixSolveM
+    Rep     -   same as in RMatrixSolveM
+    X       -   same as in RMatrixSolveM
+
+  -- ALGLIB --
+     Copyright 27.01.2010 by Bochkanov Sergey
+*************************************************************************/
+void cmatrixmixedsolve(/* Complex */ ae_matrix* a,
+     /* Complex */ ae_matrix* lua,
+     /* Integer */ ae_vector* p,
+     ae_int_t n,
+     /* Complex */ ae_vector* b,
+     ae_int_t* info,
+     densesolverreport* rep,
+     /* Complex */ ae_vector* x,
+     ae_state *_state)
+{
+    ae_frame _frame_block;
+    ae_matrix bm;
+    ae_matrix xm;
+
+    ae_frame_make(_state, &_frame_block);
+    *info = 0;
+    _densesolverreport_clear(rep);
+    ae_vector_clear(x);
+    ae_matrix_init(&bm, 0, 0, DT_COMPLEX, _state, ae_true);
+    ae_matrix_init(&xm, 0, 0, DT_COMPLEX, _state, ae_true);
+
+    if( n<=0 )
+    {
+        *info = -1;
+        ae_frame_leave(_state);
+        return;
+    }
+    ae_matrix_set_length(&bm, n, 1, _state);
+    ae_v_cmove(&bm.ptr.pp_complex[0][0], bm.stride, &b->ptr.p_complex[0], 1, "N", ae_v_len(0,n-1));
+    cmatrixmixedsolvem(a, lua, p, n, &bm, 1, info, rep, &xm, _state);
+    ae_vector_set_length(x, n, _state);
+    ae_v_cmove(&x->ptr.p_complex[0], 1, &xm.ptr.pp_complex[0][0], xm.stride, "N", ae_v_len(0,n-1));
+    ae_frame_leave(_state);
+}
+
+
+/*************************************************************************
+Dense solver. Same as RMatrixSolveM(), but for symmetric positive definite
+matrices.
+
+Algorithm features:
+* automatic detection of degenerate cases
+* condition number estimation
+* O(N^3+M*N^2) complexity
+* matrix is represented by its upper or lower triangle
+
+No iterative refinement is provided because such partial representation of
+matrix does not allow efficient calculation of extra-precise  matrix-vector
+products for large matrices. Use RMatrixSolve or RMatrixMixedSolve  if  you
+need iterative refinement.
+
+INPUT PARAMETERS
+    A       -   array[0..N-1,0..N-1], system matrix
+    N       -   size of A
+    IsUpper -   what half of A is provided
+    B       -   array[0..N-1,0..M-1], right part
+    M       -   right part size
+
+OUTPUT PARAMETERS
+    Info    -   same as in RMatrixSolve.
+                Returns -3 for non-SPD matrices.
+    Rep     -   same as in RMatrixSolve
+    X       -   same as in RMatrixSolve
+
+  -- ALGLIB --
+     Copyright 27.01.2010 by Bochkanov Sergey
+*************************************************************************/
+void spdmatrixsolvem(/* Real    */ ae_matrix* a,
+     ae_int_t n,
+     ae_bool isupper,
+     /* Real    */ ae_matrix* b,
+     ae_int_t m,
+     ae_int_t* info,
+     densesolverreport* rep,
+     /* Real    */ ae_matrix* x,
+     ae_state *_state)
+{
+    ae_frame _frame_block;
+    ae_matrix da;
+    double sqrtscalea;
+    ae_int_t i;
+    ae_int_t j;
+    ae_int_t j1;
+    ae_int_t j2;
+
+    ae_frame_make(_state, &_frame_block);
+    *info = 0;
+    _densesolverreport_clear(rep);
+    ae_matrix_clear(x);
+    ae_matrix_init(&da, 0, 0, DT_REAL, _state, ae_true);
+
+    
+    /*
+     * prepare: check inputs, allocate space...
+     */
+    if( n<=0||m<=0 )
+    {
+        *info = -1;
+        ae_frame_leave(_state);
+        return;
+    }
+    ae_matrix_set_length(&da, n, n, _state);
+    
+    /*
+     * 1. scale matrix, max(|A[i,j]|)
+     * 2. factorize scaled matrix
+     * 3. solve
+     */
+    sqrtscalea = 0;
+    for(i=0; i<=n-1; i++)
+    {
+        if( isupper )
+        {
+            j1 = i;
+            j2 = n-1;
+        }
+        else
+        {
+            j1 = 0;
+            j2 = i;
+        }
+        for(j=j1; j<=j2; j++)
+        {
+            sqrtscalea = ae_maxreal(sqrtscalea, ae_fabs(a->ptr.pp_double[i][j], _state), _state);
+        }
+    }
+    if( ae_fp_eq(sqrtscalea,0) )
+    {
+        sqrtscalea = 1;
+    }
+    sqrtscalea = 1/sqrtscalea;
+    sqrtscalea = ae_sqrt(sqrtscalea, _state);
+    for(i=0; i<=n-1; i++)
+    {
+        if( isupper )
+        {
+            j1 = i;
+            j2 = n-1;
+        }
+        else
+        {
+            j1 = 0;
+            j2 = i;
+        }
+        ae_v_move(&da.ptr.pp_double[i][j1], 1, &a->ptr.pp_double[i][j1], 1, ae_v_len(j1,j2));
+    }
+    if( !spdmatrixcholesky(&da, n, isupper, _state) )
+    {
+        ae_matrix_set_length(x, n, m, _state);
+        for(i=0; i<=n-1; i++)
+        {
+            for(j=0; j<=m-1; j++)
+            {
+                x->ptr.pp_double[i][j] = 0;
+            }
+        }
+        rep->r1 = 0;
+        rep->rinf = 0;
+        *info = -3;
+        ae_frame_leave(_state);
+        return;
+    }
+    *info = 1;
+    densesolver_spdmatrixcholeskysolveinternal(&da, sqrtscalea, n, isupper, a, ae_true, b, m, info, rep, x, _state);
+    ae_frame_leave(_state);
+}
+
+
+/*************************************************************************
+Dense solver. Same as RMatrixSolve(), but for SPD matrices.
+
+Algorithm features:
+* automatic detection of degenerate cases
+* condition number estimation
+* O(N^3) complexity
+* matrix is represented by its upper or lower triangle
+
+No iterative refinement is provided because such partial representation of
+matrix does not allow efficient calculation of extra-precise  matrix-vector
+products for large matrices. Use RMatrixSolve or RMatrixMixedSolve  if  you
+need iterative refinement.
+
+INPUT PARAMETERS
+    A       -   array[0..N-1,0..N-1], system matrix
+    N       -   size of A
+    IsUpper -   what half of A is provided
+    B       -   array[0..N-1], right part
+
+OUTPUT PARAMETERS
+    Info    -   same as in RMatrixSolve
+                Returns -3 for non-SPD matrices.
+    Rep     -   same as in RMatrixSolve
+    X       -   same as in RMatrixSolve
+
+  -- ALGLIB --
+     Copyright 27.01.2010 by Bochkanov Sergey
+*************************************************************************/
+void spdmatrixsolve(/* Real    */ ae_matrix* a,
+     ae_int_t n,
+     ae_bool isupper,
+     /* Real    */ ae_vector* b,
+     ae_int_t* info,
+     densesolverreport* rep,
+     /* Real    */ ae_vector* x,
+     ae_state *_state)
+{
+    ae_frame _frame_block;
+    ae_matrix bm;
+    ae_matrix xm;
+
+    ae_frame_make(_state, &_frame_block);
+    *info = 0;
+    _densesolverreport_clear(rep);
+    ae_vector_clear(x);
+    ae_matrix_init(&bm, 0, 0, DT_REAL, _state, ae_true);
+    ae_matrix_init(&xm, 0, 0, DT_REAL, _state, ae_true);
+
+    if( n<=0 )
+    {
+        *info = -1;
+        ae_frame_leave(_state);
+        return;
+    }
+    ae_matrix_set_length(&bm, n, 1, _state);
+    ae_v_move(&bm.ptr.pp_double[0][0], bm.stride, &b->ptr.p_double[0], 1, ae_v_len(0,n-1));
+    spdmatrixsolvem(a, n, isupper, &bm, 1, info, rep, &xm, _state);
+    ae_vector_set_length(x, n, _state);
+    ae_v_move(&x->ptr.p_double[0], 1, &xm.ptr.pp_double[0][0], xm.stride, ae_v_len(0,n-1));
+    ae_frame_leave(_state);
+}
+
+
+/*************************************************************************
+Dense solver. Same as RMatrixLUSolveM(), but for SPD matrices  represented
+by their Cholesky decomposition.
+
+Algorithm features:
+* automatic detection of degenerate cases
+* O(M*N^2) complexity
+* condition number estimation
+* matrix is represented by its upper or lower triangle
+
+No iterative refinement is provided because such partial representation of
+matrix does not allow efficient calculation of extra-precise  matrix-vector
+products for large matrices. Use RMatrixSolve or RMatrixMixedSolve  if  you
+need iterative refinement.
+
+INPUT PARAMETERS
+    CHA     -   array[0..N-1,0..N-1], Cholesky decomposition,
+                SPDMatrixCholesky result
+    N       -   size of CHA
+    IsUpper -   what half of CHA is provided
+    B       -   array[0..N-1,0..M-1], right part
+    M       -   right part size
+
+OUTPUT PARAMETERS
+    Info    -   same as in RMatrixSolve
+    Rep     -   same as in RMatrixSolve
+    X       -   same as in RMatrixSolve
+
+  -- ALGLIB --
+     Copyright 27.01.2010 by Bochkanov Sergey
+*************************************************************************/
+void spdmatrixcholeskysolvem(/* Real    */ ae_matrix* cha,
+     ae_int_t n,
+     ae_bool isupper,
+     /* Real    */ ae_matrix* b,
+     ae_int_t m,
+     ae_int_t* info,
+     densesolverreport* rep,
+     /* Real    */ ae_matrix* x,
+     ae_state *_state)
+{
+    ae_frame _frame_block;
+    ae_matrix emptya;
+    double sqrtscalea;
+    ae_int_t i;
+    ae_int_t j;
+    ae_int_t j1;
+    ae_int_t j2;
+
+    ae_frame_make(_state, &_frame_block);
+    *info = 0;
+    _densesolverreport_clear(rep);
+    ae_matrix_clear(x);
+    ae_matrix_init(&emptya, 0, 0, DT_REAL, _state, ae_true);
+
+    
+    /*
+     * prepare: check inputs, allocate space...
+     */
+    if( n<=0||m<=0 )
+    {
+        *info = -1;
+        ae_frame_leave(_state);
+        return;
+    }
+    
+    /*
+     * 1. scale matrix, max(|U[i,j]|)
+     * 2. factorize scaled matrix
+     * 3. solve
+     */
+    sqrtscalea = 0;
+    for(i=0; i<=n-1; i++)
+    {
+        if( isupper )
+        {
+            j1 = i;
+            j2 = n-1;
+        }
+        else
+        {
+            j1 = 0;
+            j2 = i;
+        }
+        for(j=j1; j<=j2; j++)
+        {
+            sqrtscalea = ae_maxreal(sqrtscalea, ae_fabs(cha->ptr.pp_double[i][j], _state), _state);
+        }
+    }
+    if( ae_fp_eq(sqrtscalea,0) )
+    {
+        sqrtscalea = 1;
+    }
+    sqrtscalea = 1/sqrtscalea;
+    densesolver_spdmatrixcholeskysolveinternal(cha, sqrtscalea, n, isupper, &emptya, ae_false, b, m, info, rep, x, _state);
+    ae_frame_leave(_state);
+}
+
+
+/*************************************************************************
+Dense solver. Same as RMatrixLUSolve(), but for  SPD matrices  represented
+by their Cholesky decomposition.
+
+Algorithm features:
+* automatic detection of degenerate cases
+* O(N^2) complexity
+* condition number estimation
+* matrix is represented by its upper or lower triangle
+
+No iterative refinement is provided because such partial representation of
+matrix does not allow efficient calculation of extra-precise  matrix-vector
+products for large matrices. Use RMatrixSolve or RMatrixMixedSolve  if  you
+need iterative refinement.
+
+INPUT PARAMETERS
+    CHA     -   array[0..N-1,0..N-1], Cholesky decomposition,
+                SPDMatrixCholesky result
+    N       -   size of A
+    IsUpper -   what half of CHA is provided
+    B       -   array[0..N-1], right part
+
+OUTPUT PARAMETERS
+    Info    -   same as in RMatrixSolve
+    Rep     -   same as in RMatrixSolve
+    X       -   same as in RMatrixSolve
+
+  -- ALGLIB --
+     Copyright 27.01.2010 by Bochkanov Sergey
+*************************************************************************/
+void spdmatrixcholeskysolve(/* Real    */ ae_matrix* cha,
+     ae_int_t n,
+     ae_bool isupper,
+     /* Real    */ ae_vector* b,
+     ae_int_t* info,
+     densesolverreport* rep,
+     /* Real    */ ae_vector* x,
+     ae_state *_state)
+{
+    ae_frame _frame_block;
+    ae_matrix bm;
+    ae_matrix xm;
+
+    ae_frame_make(_state, &_frame_block);
+    *info = 0;
+    _densesolverreport_clear(rep);
+    ae_vector_clear(x);
+    ae_matrix_init(&bm, 0, 0, DT_REAL, _state, ae_true);
+    ae_matrix_init(&xm, 0, 0, DT_REAL, _state, ae_true);
+
+    if( n<=0 )
+    {
+        *info = -1;
+        ae_frame_leave(_state);
+        return;
+    }
+    ae_matrix_set_length(&bm, n, 1, _state);
+    ae_v_move(&bm.ptr.pp_double[0][0], bm.stride, &b->ptr.p_double[0], 1, ae_v_len(0,n-1));
+    spdmatrixcholeskysolvem(cha, n, isupper, &bm, 1, info, rep, &xm, _state);
+    ae_vector_set_length(x, n, _state);
+    ae_v_move(&x->ptr.p_double[0], 1, &xm.ptr.pp_double[0][0], xm.stride, ae_v_len(0,n-1));
+    ae_frame_leave(_state);
+}
+
+
+/*************************************************************************
+Dense solver. Same as RMatrixSolveM(), but for Hermitian positive definite
+matrices.
+
+Algorithm features:
+* automatic detection of degenerate cases
+* condition number estimation
+* O(N^3+M*N^2) complexity
+* matrix is represented by its upper or lower triangle
+
+No iterative refinement is provided because such partial representation of
+matrix does not allow efficient calculation of extra-precise  matrix-vector
+products for large matrices. Use RMatrixSolve or RMatrixMixedSolve  if  you
+need iterative refinement.
+
+INPUT PARAMETERS
+    A       -   array[0..N-1,0..N-1], system matrix
+    N       -   size of A
+    IsUpper -   what half of A is provided
+    B       -   array[0..N-1,0..M-1], right part
+    M       -   right part size
+
+OUTPUT PARAMETERS
+    Info    -   same as in RMatrixSolve.
+                Returns -3 for non-HPD matrices.
+    Rep     -   same as in RMatrixSolve
+    X       -   same as in RMatrixSolve
+
+  -- ALGLIB --
+     Copyright 27.01.2010 by Bochkanov Sergey
+*************************************************************************/
+void hpdmatrixsolvem(/* Complex */ ae_matrix* a,
+     ae_int_t n,
+     ae_bool isupper,
+     /* Complex */ ae_matrix* b,
+     ae_int_t m,
+     ae_int_t* info,
+     densesolverreport* rep,
+     /* Complex */ ae_matrix* x,
+     ae_state *_state)
+{
+    ae_frame _frame_block;
+    ae_matrix da;
+    double sqrtscalea;
+    ae_int_t i;
+    ae_int_t j;
+    ae_int_t j1;
+    ae_int_t j2;
+
+    ae_frame_make(_state, &_frame_block);
+    *info = 0;
+    _densesolverreport_clear(rep);
+    ae_matrix_clear(x);
+    ae_matrix_init(&da, 0, 0, DT_COMPLEX, _state, ae_true);
+
+    
+    /*
+     * prepare: check inputs, allocate space...
+     */
+    if( n<=0||m<=0 )
+    {
+        *info = -1;
+        ae_frame_leave(_state);
+        return;
+    }
+    ae_matrix_set_length(&da, n, n, _state);
+    
+    /*
+     * 1. scale matrix, max(|A[i,j]|)
+     * 2. factorize scaled matrix
+     * 3. solve
+     */
+    sqrtscalea = 0;
+    for(i=0; i<=n-1; i++)
+    {
+        if( isupper )
+        {
+            j1 = i;
+            j2 = n-1;
+        }
+        else
+        {
+            j1 = 0;
+            j2 = i;
+        }
+        for(j=j1; j<=j2; j++)
+        {
+            sqrtscalea = ae_maxreal(sqrtscalea, ae_c_abs(a->ptr.pp_complex[i][j], _state), _state);
+        }
+    }
+    if( ae_fp_eq(sqrtscalea,0) )
+    {
+        sqrtscalea = 1;
+    }
+    sqrtscalea = 1/sqrtscalea;
+    sqrtscalea = ae_sqrt(sqrtscalea, _state);
+    for(i=0; i<=n-1; i++)
+    {
+        if( isupper )
+        {
+            j1 = i;
+            j2 = n-1;
+        }
+        else
+        {
+            j1 = 0;
+            j2 = i;
+        }
+        ae_v_cmove(&da.ptr.pp_complex[i][j1], 1, &a->ptr.pp_complex[i][j1], 1, "N", ae_v_len(j1,j2));
+    }
+    if( !hpdmatrixcholesky(&da, n, isupper, _state) )
+    {
+        ae_matrix_set_length(x, n, m, _state);
+        for(i=0; i<=n-1; i++)
+        {
+            for(j=0; j<=m-1; j++)
+            {
+                x->ptr.pp_complex[i][j] = ae_complex_from_d(0);
+            }
+        }
+        rep->r1 = 0;
+        rep->rinf = 0;
+        *info = -3;
+        ae_frame_leave(_state);
+        return;
+    }
+    *info = 1;
+    densesolver_hpdmatrixcholeskysolveinternal(&da, sqrtscalea, n, isupper, a, ae_true, b, m, info, rep, x, _state);
+    ae_frame_leave(_state);
+}
+
+
+/*************************************************************************
+Dense solver. Same as RMatrixSolve(),  but for Hermitian positive definite
+matrices.
+
+Algorithm features:
+* automatic detection of degenerate cases
+* condition number estimation
+* O(N^3) complexity
+* matrix is represented by its upper or lower triangle
+
+No iterative refinement is provided because such partial representation of
+matrix does not allow efficient calculation of extra-precise  matrix-vector
+products for large matrices. Use RMatrixSolve or RMatrixMixedSolve  if  you
+need iterative refinement.
+
+INPUT PARAMETERS
+    A       -   array[0..N-1,0..N-1], system matrix
+    N       -   size of A
+    IsUpper -   what half of A is provided
+    B       -   array[0..N-1], right part
+
+OUTPUT PARAMETERS
+    Info    -   same as in RMatrixSolve
+                Returns -3 for non-HPD matrices.
+    Rep     -   same as in RMatrixSolve
+    X       -   same as in RMatrixSolve
+
+  -- ALGLIB --
+     Copyright 27.01.2010 by Bochkanov Sergey
+*************************************************************************/
+void hpdmatrixsolve(/* Complex */ ae_matrix* a,
+     ae_int_t n,
+     ae_bool isupper,
+     /* Complex */ ae_vector* b,
+     ae_int_t* info,
+     densesolverreport* rep,
+     /* Complex */ ae_vector* x,
+     ae_state *_state)
+{
+    ae_frame _frame_block;
+    ae_matrix bm;
+    ae_matrix xm;
+
+    ae_frame_make(_state, &_frame_block);
+    *info = 0;
+    _densesolverreport_clear(rep);
+    ae_vector_clear(x);
+    ae_matrix_init(&bm, 0, 0, DT_COMPLEX, _state, ae_true);
+    ae_matrix_init(&xm, 0, 0, DT_COMPLEX, _state, ae_true);
+
+    if( n<=0 )
+    {
+        *info = -1;
+        ae_frame_leave(_state);
+        return;
+    }
+    ae_matrix_set_length(&bm, n, 1, _state);
+    ae_v_cmove(&bm.ptr.pp_complex[0][0], bm.stride, &b->ptr.p_complex[0], 1, "N", ae_v_len(0,n-1));
+    hpdmatrixsolvem(a, n, isupper, &bm, 1, info, rep, &xm, _state);
+    ae_vector_set_length(x, n, _state);
+    ae_v_cmove(&x->ptr.p_complex[0], 1, &xm.ptr.pp_complex[0][0], xm.stride, "N", ae_v_len(0,n-1));
+    ae_frame_leave(_state);
+}
+
+
+/*************************************************************************
+Dense solver. Same as RMatrixLUSolveM(), but for HPD matrices  represented
+by their Cholesky decomposition.
+
+Algorithm features:
+* automatic detection of degenerate cases
+* O(M*N^2) complexity
+* condition number estimation
+* matrix is represented by its upper or lower triangle
+
+No iterative refinement is provided because such partial representation of
+matrix does not allow efficient calculation of extra-precise  matrix-vector
+products for large matrices. Use RMatrixSolve or RMatrixMixedSolve  if  you
+need iterative refinement.
+
+INPUT PARAMETERS
+    CHA     -   array[0..N-1,0..N-1], Cholesky decomposition,
+                HPDMatrixCholesky result
+    N       -   size of CHA
+    IsUpper -   what half of CHA is provided
+    B       -   array[0..N-1,0..M-1], right part
+    M       -   right part size
+
+OUTPUT PARAMETERS
+    Info    -   same as in RMatrixSolve
+    Rep     -   same as in RMatrixSolve
+    X       -   same as in RMatrixSolve
+
+  -- ALGLIB --
+     Copyright 27.01.2010 by Bochkanov Sergey
+*************************************************************************/
+void hpdmatrixcholeskysolvem(/* Complex */ ae_matrix* cha,
+     ae_int_t n,
+     ae_bool isupper,
+     /* Complex */ ae_matrix* b,
+     ae_int_t m,
+     ae_int_t* info,
+     densesolverreport* rep,
+     /* Complex */ ae_matrix* x,
+     ae_state *_state)
+{
+    ae_frame _frame_block;
+    ae_matrix emptya;
+    double sqrtscalea;
+    ae_int_t i;
+    ae_int_t j;
+    ae_int_t j1;
+    ae_int_t j2;
+
+    ae_frame_make(_state, &_frame_block);
+    *info = 0;
+    _densesolverreport_clear(rep);
+    ae_matrix_clear(x);
+    ae_matrix_init(&emptya, 0, 0, DT_COMPLEX, _state, ae_true);
+
+    
+    /*
+     * prepare: check inputs, allocate space...
+     */
+    if( n<=0||m<=0 )
+    {
+        *info = -1;
+        ae_frame_leave(_state);
+        return;
+    }
+    
+    /*
+     * 1. scale matrix, max(|U[i,j]|)
+     * 2. factorize scaled matrix
+     * 3. solve
+     */
+    sqrtscalea = 0;
+    for(i=0; i<=n-1; i++)
+    {
+        if( isupper )
+        {
+            j1 = i;
+            j2 = n-1;
+        }
+        else
+        {
+            j1 = 0;
+            j2 = i;
+        }
+        for(j=j1; j<=j2; j++)
+        {
+            sqrtscalea = ae_maxreal(sqrtscalea, ae_c_abs(cha->ptr.pp_complex[i][j], _state), _state);
+        }
+    }
+    if( ae_fp_eq(sqrtscalea,0) )
+    {
+        sqrtscalea = 1;
+    }
+    sqrtscalea = 1/sqrtscalea;
+    densesolver_hpdmatrixcholeskysolveinternal(cha, sqrtscalea, n, isupper, &emptya, ae_false, b, m, info, rep, x, _state);
+    ae_frame_leave(_state);
+}
+
+
+/*************************************************************************
+Dense solver. Same as RMatrixLUSolve(), but for  HPD matrices  represented
+by their Cholesky decomposition.
+
+Algorithm features:
+* automatic detection of degenerate cases
+* O(N^2) complexity
+* condition number estimation
+* matrix is represented by its upper or lower triangle
+
+No iterative refinement is provided because such partial representation of
+matrix does not allow efficient calculation of extra-precise  matrix-vector
+products for large matrices. Use RMatrixSolve or RMatrixMixedSolve  if  you
+need iterative refinement.
+
+INPUT PARAMETERS
+    CHA     -   array[0..N-1,0..N-1], Cholesky decomposition,
+                SPDMatrixCholesky result
+    N       -   size of A
+    IsUpper -   what half of CHA is provided
+    B       -   array[0..N-1], right part
+
+OUTPUT PARAMETERS
+    Info    -   same as in RMatrixSolve
+    Rep     -   same as in RMatrixSolve
+    X       -   same as in RMatrixSolve
+
+  -- ALGLIB --
+     Copyright 27.01.2010 by Bochkanov Sergey
+*************************************************************************/
+void hpdmatrixcholeskysolve(/* Complex */ ae_matrix* cha,
+     ae_int_t n,
+     ae_bool isupper,
+     /* Complex */ ae_vector* b,
+     ae_int_t* info,
+     densesolverreport* rep,
+     /* Complex */ ae_vector* x,
+     ae_state *_state)
+{
+    ae_frame _frame_block;
+    ae_matrix bm;
+    ae_matrix xm;
+
+    ae_frame_make(_state, &_frame_block);
+    *info = 0;
+    _densesolverreport_clear(rep);
+    ae_vector_clear(x);
+    ae_matrix_init(&bm, 0, 0, DT_COMPLEX, _state, ae_true);
+    ae_matrix_init(&xm, 0, 0, DT_COMPLEX, _state, ae_true);
+
+    if( n<=0 )
+    {
+        *info = -1;
+        ae_frame_leave(_state);
+        return;
+    }
+    ae_matrix_set_length(&bm, n, 1, _state);
+    ae_v_cmove(&bm.ptr.pp_complex[0][0], bm.stride, &b->ptr.p_complex[0], 1, "N", ae_v_len(0,n-1));
+    hpdmatrixcholeskysolvem(cha, n, isupper, &bm, 1, info, rep, &xm, _state);
+    ae_vector_set_length(x, n, _state);
+    ae_v_cmove(&x->ptr.p_complex[0], 1, &xm.ptr.pp_complex[0][0], xm.stride, "N", ae_v_len(0,n-1));
+    ae_frame_leave(_state);
+}
+
+
+/*************************************************************************
+Dense solver.
+
+This subroutine finds solution of the linear system A*X=B with non-square,
+possibly degenerate A.  System  is  solved in the least squares sense, and
+general least squares solution  X = X0 + CX*y  which  minimizes |A*X-B| is
+returned. If A is non-degenerate, solution in the  usual sense is returned
+
+Algorithm features:
+* automatic detection of degenerate cases
+* iterative refinement
+* O(N^3) complexity
+
+INPUT PARAMETERS
+    A       -   array[0..NRows-1,0..NCols-1], system matrix
+    NRows   -   vertical size of A
+    NCols   -   horizontal size of A
+    B       -   array[0..NCols-1], right part
+    Threshold-  a number in [0,1]. Singular values  beyond  Threshold  are
+                considered  zero.  Set  it to 0.0, if you don't understand
+                what it means, so the solver will choose good value on its
+                own.
+                
+OUTPUT PARAMETERS
+    Info    -   return code:
+                * -4    SVD subroutine failed
+                * -1    if NRows<=0 or NCols<=0 or Threshold<0 was passed
+                *  1    if task is solved
+    Rep     -   solver report, see below for more info
+    X       -   array[0..N-1,0..M-1], it contains:
+                * solution of A*X=B if A is non-singular (well-conditioned
+                  or ill-conditioned, but not very close to singular)
+                * zeros,  if  A  is  singular  or  VERY  close to singular
+                  (in this case Info=-3).
+
+SOLVER REPORT
+
+Subroutine sets following fields of the Rep structure:
+* R2        reciprocal of condition number: 1/cond(A), 2-norm.
+* N         = NCols
+* K         dim(Null(A))
+* CX        array[0..N-1,0..K-1], kernel of A.
+            Columns of CX store such vectors that A*CX[i]=0.
+
+  -- ALGLIB --
+     Copyright 24.08.2009 by Bochkanov Sergey
+*************************************************************************/
+void rmatrixsolvels(/* Real    */ ae_matrix* a,
+     ae_int_t nrows,
+     ae_int_t ncols,
+     /* Real    */ ae_vector* b,
+     double threshold,
+     ae_int_t* info,
+     densesolverlsreport* rep,
+     /* Real    */ ae_vector* x,
+     ae_state *_state)
+{
+    ae_frame _frame_block;
+    ae_vector sv;
+    ae_matrix u;
+    ae_matrix vt;
+    ae_vector rp;
+    ae_vector utb;
+    ae_vector sutb;
+    ae_vector tmp;
+    ae_vector ta;
+    ae_vector tx;
+    ae_vector buf;
+    ae_vector w;
+    ae_int_t i;
+    ae_int_t j;
+    ae_int_t nsv;
+    ae_int_t kernelidx;
+    double v;
+    double verr;
+    ae_bool svdfailed;
+    ae_bool zeroa;
+    ae_int_t rfs;
+    ae_int_t nrfs;
+    ae_bool terminatenexttime;
+    ae_bool smallerr;
+
+    ae_frame_make(_state, &_frame_block);
+    *info = 0;
+    _densesolverlsreport_clear(rep);
+    ae_vector_clear(x);
+    ae_vector_init(&sv, 0, DT_REAL, _state, ae_true);
+    ae_matrix_init(&u, 0, 0, DT_REAL, _state, ae_true);
+    ae_matrix_init(&vt, 0, 0, DT_REAL, _state, ae_true);
+    ae_vector_init(&rp, 0, DT_REAL, _state, ae_true);
+    ae_vector_init(&utb, 0, DT_REAL, _state, ae_true);
+    ae_vector_init(&sutb, 0, DT_REAL, _state, ae_true);
+    ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true);
+    ae_vector_init(&ta, 0, DT_REAL, _state, ae_true);
+    ae_vector_init(&tx, 0, DT_REAL, _state, ae_true);
+    ae_vector_init(&buf, 0, DT_REAL, _state, ae_true);
+    ae_vector_init(&w, 0, DT_REAL, _state, ae_true);
+
+    if( (nrows<=0||ncols<=0)||ae_fp_less(threshold,0) )
+    {
+        *info = -1;
+        ae_frame_leave(_state);
+        return;
+    }
+    if( ae_fp_eq(threshold,0) )
+    {
+        threshold = 1000*ae_machineepsilon;
+    }
+    
+    /*
+     * Factorize A first
+     */
+    svdfailed = !rmatrixsvd(a, nrows, ncols, 1, 2, 2, &sv, &u, &vt, _state);
+    zeroa = ae_fp_eq(sv.ptr.p_double[0],0);
+    if( svdfailed||zeroa )
+    {
+        if( svdfailed )
+        {
+            *info = -4;
+        }
+        else
+        {
+            *info = 1;
+        }
+        ae_vector_set_length(x, ncols, _state);
+        for(i=0; i<=ncols-1; i++)
+        {
+            x->ptr.p_double[i] = 0;
+        }
+        rep->n = ncols;
+        rep->k = ncols;
+        ae_matrix_set_length(&rep->cx, ncols, ncols, _state);
+        for(i=0; i<=ncols-1; i++)
+        {
+            for(j=0; j<=ncols-1; j++)
+            {
+                if( i==j )
+                {
+                    rep->cx.ptr.pp_double[i][j] = 1;
+                }
+                else
+                {
+                    rep->cx.ptr.pp_double[i][j] = 0;
+                }
+            }
+        }
+        rep->r2 = 0;
+        ae_frame_leave(_state);
+        return;
+    }
+    nsv = ae_minint(ncols, nrows, _state);
+    if( nsv==ncols )
+    {
+        rep->r2 = sv.ptr.p_double[nsv-1]/sv.ptr.p_double[0];
+    }
+    else
+    {
+        rep->r2 = 0;
+    }
+    rep->n = ncols;
+    *info = 1;
+    
+    /*
+     * Iterative refinement of xc combined with solution:
+     * 1. xc = 0
+     * 2. calculate r = bc-A*xc using extra-precise dot product
+     * 3. solve A*y = r
+     * 4. update x:=x+r
+     * 5. goto 2
+     *
+     * This cycle is executed until one of two things happens:
+     * 1. maximum number of iterations reached
+     * 2. last iteration decreased error to the lower limit
+     */
+    ae_vector_set_length(&utb, nsv, _state);
+    ae_vector_set_length(&sutb, nsv, _state);
+    ae_vector_set_length(x, ncols, _state);
+    ae_vector_set_length(&tmp, ncols, _state);
+    ae_vector_set_length(&ta, ncols+1, _state);
+    ae_vector_set_length(&tx, ncols+1, _state);
+    ae_vector_set_length(&buf, ncols+1, _state);
+    for(i=0; i<=ncols-1; i++)
+    {
+        x->ptr.p_double[i] = 0;
+    }
+    kernelidx = nsv;
+    for(i=0; i<=nsv-1; i++)
+    {
+        if( ae_fp_less_eq(sv.ptr.p_double[i],threshold*sv.ptr.p_double[0]) )
+        {
+            kernelidx = i;
+            break;
+        }
+    }
+    rep->k = ncols-kernelidx;
+    nrfs = densesolver_densesolverrfsmaxv2(ncols, rep->r2, _state);
+    terminatenexttime = ae_false;
+    ae_vector_set_length(&rp, nrows, _state);
+    for(rfs=0; rfs<=nrfs; rfs++)
+    {
+        if( terminatenexttime )
+        {
+            break;
+        }
+        
+        /*
+         * calculate right part
+         */
+        if( rfs==0 )
+        {
+            ae_v_move(&rp.ptr.p_double[0], 1, &b->ptr.p_double[0], 1, ae_v_len(0,nrows-1));
+        }
+        else
+        {
+            smallerr = ae_true;
+            for(i=0; i<=nrows-1; i++)
+            {
+                ae_v_move(&ta.ptr.p_double[0], 1, &a->ptr.pp_double[i][0], 1, ae_v_len(0,ncols-1));
+                ta.ptr.p_double[ncols] = -1;
+                ae_v_move(&tx.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,ncols-1));
+                tx.ptr.p_double[ncols] = b->ptr.p_double[i];
+                xdot(&ta, &tx, ncols+1, &buf, &v, &verr, _state);
+                rp.ptr.p_double[i] = -v;
+                smallerr = smallerr&&ae_fp_less(ae_fabs(v, _state),4*verr);
+            }
+            if( smallerr )
+            {
+                terminatenexttime = ae_true;
+            }
+        }
+        
+        /*
+         * solve A*dx = rp
+         */
+        for(i=0; i<=ncols-1; i++)
+        {
+            tmp.ptr.p_double[i] = 0;
+        }
+        for(i=0; i<=nsv-1; i++)
+        {
+            utb.ptr.p_double[i] = 0;
+        }
+        for(i=0; i<=nrows-1; i++)
+        {
+            v = rp.ptr.p_double[i];
+            ae_v_addd(&utb.ptr.p_double[0], 1, &u.ptr.pp_double[i][0], 1, ae_v_len(0,nsv-1), v);
+        }
+        for(i=0; i<=nsv-1; i++)
+        {
+            if( i<kernelidx )
+            {
+                sutb.ptr.p_double[i] = utb.ptr.p_double[i]/sv.ptr.p_double[i];
+            }
+            else
+            {
+                sutb.ptr.p_double[i] = 0;
+            }
+        }
+        for(i=0; i<=nsv-1; i++)
+        {
+            v = sutb.ptr.p_double[i];
+            ae_v_addd(&tmp.ptr.p_double[0], 1, &vt.ptr.pp_double[i][0], 1, ae_v_len(0,ncols-1), v);
+        }
+        
+        /*
+         * update x:  x:=x+dx
+         */
+        ae_v_add(&x->ptr.p_double[0], 1, &tmp.ptr.p_double[0], 1, ae_v_len(0,ncols-1));
+    }
+    
+    /*
+     * fill CX
+     */
+    if( rep->k>0 )
+    {
+        ae_matrix_set_length(&rep->cx, ncols, rep->k, _state);
+        for(i=0; i<=rep->k-1; i++)
+        {
+            ae_v_move(&rep->cx.ptr.pp_double[0][i], rep->cx.stride, &vt.ptr.pp_double[kernelidx+i][0], 1, ae_v_len(0,ncols-1));
+        }
+    }
+    ae_frame_leave(_state);
+}
+
+
+/*************************************************************************
+Internal LU solver
+
+  -- ALGLIB --
+     Copyright 27.01.2010 by Bochkanov Sergey
+*************************************************************************/
+static void densesolver_rmatrixlusolveinternal(/* Real    */ ae_matrix* lua,
+     /* Integer */ ae_vector* p,
+     double scalea,
+     ae_int_t n,
+     /* Real    */ ae_matrix* a,
+     ae_bool havea,
+     /* Real    */ ae_matrix* b,
+     ae_int_t m,
+     ae_int_t* info,
+     densesolverreport* rep,
+     /* Real    */ ae_matrix* x,
+     ae_state *_state)
+{
+    ae_frame _frame_block;
+    ae_int_t i;
+    ae_int_t j;
+    ae_int_t k;
+    ae_int_t rfs;
+    ae_int_t nrfs;
+    ae_vector xc;
+    ae_vector y;
+    ae_vector bc;
+    ae_vector xa;
+    ae_vector xb;
+    ae_vector tx;
+    double v;
+    double verr;
+    double mxb;
+    double scaleright;
+    ae_bool smallerr;
+    ae_bool terminatenexttime;
+
+    ae_frame_make(_state, &_frame_block);
+    *info = 0;
+    _densesolverreport_clear(rep);
+    ae_matrix_clear(x);
+    ae_vector_init(&xc, 0, DT_REAL, _state, ae_true);
+    ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
+    ae_vector_init(&bc, 0, DT_REAL, _state, ae_true);
+    ae_vector_init(&xa, 0, DT_REAL, _state, ae_true);
+    ae_vector_init(&xb, 0, DT_REAL, _state, ae_true);
+    ae_vector_init(&tx, 0, DT_REAL, _state, ae_true);
+
+    ae_assert(ae_fp_greater(scalea,0), "Assertion failed", _state);
+    
+    /*
+     * prepare: check inputs, allocate space...
+     */
+    if( n<=0||m<=0 )
+    {
+        *info = -1;
+        ae_frame_leave(_state);
+        return;
+    }
+    for(i=0; i<=n-1; i++)
+    {
+        if( p->ptr.p_int[i]>n-1||p->ptr.p_int[i]<i )
+        {
+            *info = -1;
+            ae_frame_leave(_state);
+            return;
+        }
+    }
+    ae_matrix_set_length(x, n, m, _state);
+    ae_vector_set_length(&y, n, _state);
+    ae_vector_set_length(&xc, n, _state);
+    ae_vector_set_length(&bc, n, _state);
+    ae_vector_set_length(&tx, n+1, _state);
+    ae_vector_set_length(&xa, n+1, _state);
+    ae_vector_set_length(&xb, n+1, _state);
+    
+    /*
+     * estimate condition number, test for near singularity
+     */
+    rep->r1 = rmatrixlurcond1(lua, n, _state);
+    rep->rinf = rmatrixlurcondinf(lua, n, _state);
+    if( ae_fp_less(rep->r1,rcondthreshold(_state))||ae_fp_less(rep->rinf,rcondthreshold(_state)) )
+    {
+        for(i=0; i<=n-1; i++)
+        {
+            for(j=0; j<=m-1; j++)
+            {
+                x->ptr.pp_double[i][j] = 0;
+            }
+        }
+        rep->r1 = 0;
+        rep->rinf = 0;
+        *info = -3;
+        ae_frame_leave(_state);
+        return;
+    }
+    *info = 1;
+    
+    /*
+     * solve
+     */
+    for(k=0; k<=m-1; k++)
+    {
+        
+        /*
+         * copy B to contiguous storage
+         */
+        ae_v_move(&bc.ptr.p_double[0], 1, &b->ptr.pp_double[0][k], b->stride, ae_v_len(0,n-1));
+        
+        /*
+         * Scale right part:
+         * * MX stores max(|Bi|)
+         * * ScaleRight stores actual scaling applied to B when solving systems
+         *   it is chosen to make |scaleRight*b| close to 1.
+         */
+        mxb = 0;
+        for(i=0; i<=n-1; i++)
+        {
+            mxb = ae_maxreal(mxb, ae_fabs(bc.ptr.p_double[i], _state), _state);
+        }
+        if( ae_fp_eq(mxb,0) )
+        {
+            mxb = 1;
+        }
+        scaleright = 1/mxb;
+        
+        /*
+         * First, non-iterative part of solution process.
+         * We use separate code for this task because
+         * XDot is quite slow and we want to save time.
+         */
+        ae_v_moved(&xc.ptr.p_double[0], 1, &bc.ptr.p_double[0], 1, ae_v_len(0,n-1), scaleright);
+        densesolver_rbasiclusolve(lua, p, scalea, n, &xc, &tx, _state);
+        
+        /*
+         * Iterative refinement of xc:
+         * * calculate r = bc-A*xc using extra-precise dot product
+         * * solve A*y = r
+         * * update x:=x+r
+         *
+         * This cycle is executed until one of two things happens:
+         * 1. maximum number of iterations reached
+         * 2. last iteration decreased error to the lower limit
+         */
+        if( havea )
+        {
+            nrfs = densesolver_densesolverrfsmax(n, rep->r1, rep->rinf, _state);
+            terminatenexttime = ae_false;
+            for(rfs=0; rfs<=nrfs-1; rfs++)
+            {
+                if( terminatenexttime )
+                {
+                    break;
+                }
+                
+                /*
+                 * generate right part
+                 */
+                smallerr = ae_true;
+                ae_v_move(&xb.ptr.p_double[0], 1, &xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
+                for(i=0; i<=n-1; i++)
+                {
+                    ae_v_moved(&xa.ptr.p_double[0], 1, &a->ptr.pp_double[i][0], 1, ae_v_len(0,n-1), scalea);
+                    xa.ptr.p_double[n] = -1;
+                    xb.ptr.p_double[n] = scaleright*bc.ptr.p_double[i];
+                    xdot(&xa, &xb, n+1, &tx, &v, &verr, _state);
+                    y.ptr.p_double[i] = -v;
+                    smallerr = smallerr&&ae_fp_less(ae_fabs(v, _state),4*verr);
+                }
+                if( smallerr )
+                {
+                    terminatenexttime = ae_true;
+                }
+                
+                /*
+                 * solve and update
+                 */
+                densesolver_rbasiclusolve(lua, p, scalea, n, &y, &tx, _state);
+                ae_v_add(&xc.ptr.p_double[0], 1, &y.ptr.p_double[0], 1, ae_v_len(0,n-1));
+            }
+        }
+        
+        /*
+         * Store xc.
+         * Post-scale result.
+         */
+        v = scalea*mxb;
+        ae_v_moved(&x->ptr.pp_double[0][k], x->stride, &xc.ptr.p_double[0], 1, ae_v_len(0,n-1), v);
+    }
+    ae_frame_leave(_state);
+}
+
+
+/*************************************************************************
+Internal Cholesky solver
+
+  -- ALGLIB --
+     Copyright 27.01.2010 by Bochkanov Sergey
+*************************************************************************/
+static void densesolver_spdmatrixcholeskysolveinternal(/* Real    */ ae_matrix* cha,
+     double sqrtscalea,
+     ae_int_t n,
+     ae_bool isupper,
+     /* Real    */ ae_matrix* a,
+     ae_bool havea,
+     /* Real    */ ae_matrix* b,
+     ae_int_t m,
+     ae_int_t* info,
+     densesolverreport* rep,
+     /* Real    */ ae_matrix* x,
+     ae_state *_state)
+{
+    ae_frame _frame_block;
+    ae_int_t i;
+    ae_int_t j;
+    ae_int_t k;
+    ae_vector xc;
+    ae_vector y;
+    ae_vector bc;
+    ae_vector xa;
+    ae_vector xb;
+    ae_vector tx;
+    double v;
+    double mxb;
+    double scaleright;
+
+    ae_frame_make(_state, &_frame_block);
+    *info = 0;
+    _densesolverreport_clear(rep);
+    ae_matrix_clear(x);
+    ae_vector_init(&xc, 0, DT_REAL, _state, ae_true);
+    ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
+    ae_vector_init(&bc, 0, DT_REAL, _state, ae_true);
+    ae_vector_init(&xa, 0, DT_REAL, _state, ae_true);
+    ae_vector_init(&xb, 0, DT_REAL, _state, ae_true);
+    ae_vector_init(&tx, 0, DT_REAL, _state, ae_true);
+
+    ae_assert(ae_fp_greater(sqrtscalea,0), "Assertion failed", _state);
+    
+    /*
+     * prepare: check inputs, allocate space...
+     */
+    if( n<=0||m<=0 )
+    {
+        *info = -1;
+        ae_frame_leave(_state);
+        return;
+    }
+    ae_matrix_set_length(x, n, m, _state);
+    ae_vector_set_length(&y, n, _state);
+    ae_vector_set_length(&xc, n, _state);
+    ae_vector_set_length(&bc, n, _state);
+    ae_vector_set_length(&tx, n+1, _state);
+    ae_vector_set_length(&xa, n+1, _state);
+    ae_vector_set_length(&xb, n+1, _state);
+    
+    /*
+     * estimate condition number, test for near singularity
+     */
+    rep->r1 = spdmatrixcholeskyrcond(cha, n, isupper, _state);
+    rep->rinf = rep->r1;
+    if( ae_fp_less(rep->r1,rcondthreshold(_state)) )
+    {
+        for(i=0; i<=n-1; i++)
+        {
+            for(j=0; j<=m-1; j++)
+            {
+                x->ptr.pp_double[i][j] = 0;
+            }
+        }
+        rep->r1 = 0;
+        rep->rinf = 0;
+        *info = -3;
+        ae_frame_leave(_state);
+        return;
+    }
+    *info = 1;
+    
+    /*
+     * solve
+     */
+    for(k=0; k<=m-1; k++)
+    {
+        
+        /*
+         * copy B to contiguous storage
+         */
+        ae_v_move(&bc.ptr.p_double[0], 1, &b->ptr.pp_double[0][k], b->stride, ae_v_len(0,n-1));
+        
+        /*
+         * Scale right part:
+         * * MX stores max(|Bi|)
+         * * ScaleRight stores actual scaling applied to B when solving systems
+         *   it is chosen to make |scaleRight*b| close to 1.
+         */
+        mxb = 0;
+        for(i=0; i<=n-1; i++)
+        {
+            mxb = ae_maxreal(mxb, ae_fabs(bc.ptr.p_double[i], _state), _state);
+        }
+        if( ae_fp_eq(mxb,0) )
+        {
+            mxb = 1;
+        }
+        scaleright = 1/mxb;
+        
+        /*
+         * First, non-iterative part of solution process.
+         * We use separate code for this task because
+         * XDot is quite slow and we want to save time.
+         */
+        ae_v_moved(&xc.ptr.p_double[0], 1, &bc.ptr.p_double[0], 1, ae_v_len(0,n-1), scaleright);
+        densesolver_spdbasiccholeskysolve(cha, sqrtscalea, n, isupper, &xc, &tx, _state);
+        
+        /*
+         * Store xc.
+         * Post-scale result.
+         */
+        v = ae_sqr(sqrtscalea, _state)*mxb;
+        ae_v_moved(&x->ptr.pp_double[0][k], x->stride, &xc.ptr.p_double[0], 1, ae_v_len(0,n-1), v);
+    }
+    ae_frame_leave(_state);
+}
+
+
+/*************************************************************************
+Internal LU solver
+
+  -- ALGLIB --
+     Copyright 27.01.2010 by Bochkanov Sergey
+*************************************************************************/
+static void densesolver_cmatrixlusolveinternal(/* Complex */ ae_matrix* lua,
+     /* Integer */ ae_vector* p,
+     double scalea,
+     ae_int_t n,
+     /* Complex */ ae_matrix* a,
+     ae_bool havea,
+     /* Complex */ ae_matrix* b,
+     ae_int_t m,
+     ae_int_t* info,
+     densesolverreport* rep,
+     /* Complex */ ae_matrix* x,
+     ae_state *_state)
+{
+    ae_frame _frame_block;
+    ae_int_t i;
+    ae_int_t j;
+    ae_int_t k;
+    ae_int_t rfs;
+    ae_int_t nrfs;
+    ae_vector xc;
+    ae_vector y;
+    ae_vector bc;
+    ae_vector xa;
+    ae_vector xb;
+    ae_vector tx;
+    ae_vector tmpbuf;
+    ae_complex v;
+    double verr;
+    double mxb;
+    double scaleright;
+    ae_bool smallerr;
+    ae_bool terminatenexttime;
+
+    ae_frame_make(_state, &_frame_block);
+    *info = 0;
+    _densesolverreport_clear(rep);
+    ae_matrix_clear(x);
+    ae_vector_init(&xc, 0, DT_COMPLEX, _state, ae_true);
+    ae_vector_init(&y, 0, DT_COMPLEX, _state, ae_true);
+    ae_vector_init(&bc, 0, DT_COMPLEX, _state, ae_true);
+    ae_vector_init(&xa, 0, DT_COMPLEX, _state, ae_true);
+    ae_vector_init(&xb, 0, DT_COMPLEX, _state, ae_true);
+    ae_vector_init(&tx, 0, DT_COMPLEX, _state, ae_true);
+    ae_vector_init(&tmpbuf, 0, DT_REAL, _state, ae_true);
+
+    ae_assert(ae_fp_greater(scalea,0), "Assertion failed", _state);
+    
+    /*
+     * prepare: check inputs, allocate space...
+     */
+    if( n<=0||m<=0 )
+    {
+        *info = -1;
+        ae_frame_leave(_state);
+        return;
+    }
+    for(i=0; i<=n-1; i++)
+    {
+        if( p->ptr.p_int[i]>n-1||p->ptr.p_int[i]<i )
+        {
+            *info = -1;
+            ae_frame_leave(_state);
+            return;
+        }
+    }
+    ae_matrix_set_length(x, n, m, _state);
+    ae_vector_set_length(&y, n, _state);
+    ae_vector_set_length(&xc, n, _state);
+    ae_vector_set_length(&bc, n, _state);
+    ae_vector_set_length(&tx, n, _state);
+    ae_vector_set_length(&xa, n+1, _state);
+    ae_vector_set_length(&xb, n+1, _state);
+    ae_vector_set_length(&tmpbuf, 2*n+2, _state);
+    
+    /*
+     * estimate condition number, test for near singularity
+     */
+    rep->r1 = cmatrixlurcond1(lua, n, _state);
+    rep->rinf = cmatrixlurcondinf(lua, n, _state);
+    if( ae_fp_less(rep->r1,rcondthreshold(_state))||ae_fp_less(rep->rinf,rcondthreshold(_state)) )
+    {
+        for(i=0; i<=n-1; i++)
+        {
+            for(j=0; j<=m-1; j++)
+            {
+                x->ptr.pp_complex[i][j] = ae_complex_from_d(0);
+            }
+        }
+        rep->r1 = 0;
+        rep->rinf = 0;
+        *info = -3;
+        ae_frame_leave(_state);
+        return;
+    }
+    *info = 1;
+    
+    /*
+     * solve
+     */
+    for(k=0; k<=m-1; k++)
+    {
+        
+        /*
+         * copy B to contiguous storage
+         */
+        ae_v_cmove(&bc.ptr.p_complex[0], 1, &b->ptr.pp_complex[0][k], b->stride, "N", ae_v_len(0,n-1));
+        
+        /*
+         * Scale right part:
+         * * MX stores max(|Bi|)
+         * * ScaleRight stores actual scaling applied to B when solving systems
+         *   it is chosen to make |scaleRight*b| close to 1.
+         */
+        mxb = 0;
+        for(i=0; i<=n-1; i++)
+        {
+            mxb = ae_maxreal(mxb, ae_c_abs(bc.ptr.p_complex[i], _state), _state);
+        }
+        if( ae_fp_eq(mxb,0) )
+        {
+            mxb = 1;
+        }
+        scaleright = 1/mxb;
+        
+        /*
+         * First, non-iterative part of solution process.
+         * We use separate code for this task because
+         * XDot is quite slow and we want to save time.
+         */
+        ae_v_cmoved(&xc.ptr.p_complex[0], 1, &bc.ptr.p_complex[0], 1, "N", ae_v_len(0,n-1), scaleright);
+        densesolver_cbasiclusolve(lua, p, scalea, n, &xc, &tx, _state);
+        
+        /*
+         * Iterative refinement of xc:
+         * * calculate r = bc-A*xc using extra-precise dot product
+         * * solve A*y = r
+         * * update x:=x+r
+         *
+         * This cycle is executed until one of two things happens:
+         * 1. maximum number of iterations reached
+         * 2. last iteration decreased error to the lower limit
+         */
+        if( havea )
+        {
+            nrfs = densesolver_densesolverrfsmax(n, rep->r1, rep->rinf, _state);
+            terminatenexttime = ae_false;
+            for(rfs=0; rfs<=nrfs-1; rfs++)
+            {
+                if( terminatenexttime )
+                {
+                    break;
+                }
+                
+                /*
+                 * generate right part
+                 */
+                smallerr = ae_true;
+                ae_v_cmove(&xb.ptr.p_complex[0], 1, &xc.ptr.p_complex[0], 1, "N", ae_v_len(0,n-1));
+                for(i=0; i<=n-1; i++)
+                {
+                    ae_v_cmoved(&xa.ptr.p_complex[0], 1, &a->ptr.pp_complex[i][0], 1, "N", ae_v_len(0,n-1), scalea);
+                    xa.ptr.p_complex[n] = ae_complex_from_d(-1);
+                    xb.ptr.p_complex[n] = ae_c_mul_d(bc.ptr.p_complex[i],scaleright);
+                    xcdot(&xa, &xb, n+1, &tmpbuf, &v, &verr, _state);
+                    y.ptr.p_complex[i] = ae_c_neg(v);
+                    smallerr = smallerr&&ae_fp_less(ae_c_abs(v, _state),4*verr);
+                }
+                if( smallerr )
+                {
+                    terminatenexttime = ae_true;
+                }
+                
+                /*
+                 * solve and update
+                 */
+                densesolver_cbasiclusolve(lua, p, scalea, n, &y, &tx, _state);
+                ae_v_cadd(&xc.ptr.p_complex[0], 1, &y.ptr.p_complex[0], 1, "N", ae_v_len(0,n-1));
+            }
+        }
+        
+        /*
+         * Store xc.
+         * Post-scale result.
+         */
+        v = ae_complex_from_d(scalea*mxb);
+        ae_v_cmovec(&x->ptr.pp_complex[0][k], x->stride, &xc.ptr.p_complex[0], 1, "N", ae_v_len(0,n-1), v);
+    }
+    ae_frame_leave(_state);
+}
+
+
+/*************************************************************************
+Internal Cholesky solver
+
+  -- ALGLIB --
+     Copyright 27.01.2010 by Bochkanov Sergey
+*************************************************************************/
+static void densesolver_hpdmatrixcholeskysolveinternal(/* Complex */ ae_matrix* cha,
+     double sqrtscalea,
+     ae_int_t n,
+     ae_bool isupper,
+     /* Complex */ ae_matrix* a,
+     ae_bool havea,
+     /* Complex */ ae_matrix* b,
+     ae_int_t m,
+     ae_int_t* info,
+     densesolverreport* rep,
+     /* Complex */ ae_matrix* x,
+     ae_state *_state)
+{
+    ae_frame _frame_block;
+    ae_int_t i;
+    ae_int_t j;
+    ae_int_t k;
+    ae_vector xc;
+    ae_vector y;
+    ae_vector bc;
+    ae_vector xa;
+    ae_vector xb;
+    ae_vector tx;
+    double v;
+    double mxb;
+    double scaleright;
+
+    ae_frame_make(_state, &_frame_block);
+    *info = 0;
+    _densesolverreport_clear(rep);
+    ae_matrix_clear(x);
+    ae_vector_init(&xc, 0, DT_COMPLEX, _state, ae_true);
+    ae_vector_init(&y, 0, DT_COMPLEX, _state, ae_true);
+    ae_vector_init(&bc, 0, DT_COMPLEX, _state, ae_true);
+    ae_vector_init(&xa, 0, DT_COMPLEX, _state, ae_true);
+    ae_vector_init(&xb, 0, DT_COMPLEX, _state, ae_true);
+    ae_vector_init(&tx, 0, DT_COMPLEX, _state, ae_true);
+
+    ae_assert(ae_fp_greater(sqrtscalea,0), "Assertion failed", _state);
+    
+    /*
+     * prepare: check inputs, allocate space...
+     */
+    if( n<=0||m<=0 )
+    {
+        *info = -1;
+        ae_frame_leave(_state);
+        return;
+    }
+    ae_matrix_set_length(x, n, m, _state);
+    ae_vector_set_length(&y, n, _state);
+    ae_vector_set_length(&xc, n, _state);
+    ae_vector_set_length(&bc, n, _state);
+    ae_vector_set_length(&tx, n+1, _state);
+    ae_vector_set_length(&xa, n+1, _state);
+    ae_vector_set_length(&xb, n+1, _state);
+    
+    /*
+     * estimate condition number, test for near singularity
+     */
+    rep->r1 = hpdmatrixcholeskyrcond(cha, n, isupper, _state);
+    rep->rinf = rep->r1;
+    if( ae_fp_less(rep->r1,rcondthreshold(_state)) )
+    {
+        for(i=0; i<=n-1; i++)
+        {
+            for(j=0; j<=m-1; j++)
+            {
+                x->ptr.pp_complex[i][j] = ae_complex_from_d(0);
+            }
+        }
+        rep->r1 = 0;
+        rep->rinf = 0;
+        *info = -3;
+        ae_frame_leave(_state);
+        return;
+    }
+    *info = 1;
+    
+    /*
+     * solve
+     */
+    for(k=0; k<=m-1; k++)
+    {
+        
+        /*
+         * copy B to contiguous storage
+         */
+        ae_v_cmove(&bc.ptr.p_complex[0], 1, &b->ptr.pp_complex[0][k], b->stride, "N", ae_v_len(0,n-1));
+        
+        /*
+         * Scale right part:
+         * * MX stores max(|Bi|)
+         * * ScaleRight stores actual scaling applied to B when solving systems
+         *   it is chosen to make |scaleRight*b| close to 1.
+         */
+        mxb = 0;
+        for(i=0; i<=n-1; i++)
+        {
+            mxb = ae_maxreal(mxb, ae_c_abs(bc.ptr.p_complex[i], _state), _state);
+        }
+        if( ae_fp_eq(mxb,0) )
+        {
+            mxb = 1;
+        }
+        scaleright = 1/mxb;
+        
+        /*
+         * First, non-iterative part of solution process.
+         * We use separate code for this task because
+         * XDot is quite slow and we want to save time.
+         */
+        ae_v_cmoved(&xc.ptr.p_complex[0], 1, &bc.ptr.p_complex[0], 1, "N", ae_v_len(0,n-1), scaleright);
+        densesolver_hpdbasiccholeskysolve(cha, sqrtscalea, n, isupper, &xc, &tx, _state);
+        
+        /*
+         * Store xc.
+         * Post-scale result.
+         */
+        v = ae_sqr(sqrtscalea, _state)*mxb;
+        ae_v_cmoved(&x->ptr.pp_complex[0][k], x->stride, &xc.ptr.p_complex[0], 1, "N", ae_v_len(0,n-1), v);
+    }
+    ae_frame_leave(_state);
+}
+
+
+/*************************************************************************
+Internal subroutine.
+Returns maximum count of RFS iterations as function of:
+1. machine epsilon
+2. task size.
+3. condition number
+
+  -- ALGLIB --
+     Copyright 27.01.2010 by Bochkanov Sergey
+*************************************************************************/
+static ae_int_t densesolver_densesolverrfsmax(ae_int_t n,
+     double r1,
+     double rinf,
+     ae_state *_state)
+{
+    ae_int_t result;
+
+
+    result = 5;
+    return result;
+}
+
+
+/*************************************************************************
+Internal subroutine.
+Returns maximum count of RFS iterations as function of:
+1. machine epsilon
+2. task size.
+3. norm-2 condition number
+
+  -- ALGLIB --
+     Copyright 27.01.2010 by Bochkanov Sergey
+*************************************************************************/
+static ae_int_t densesolver_densesolverrfsmaxv2(ae_int_t n,
+     double r2,
+     ae_state *_state)
+{
+    ae_int_t result;
+
+
+    result = densesolver_densesolverrfsmax(n, 0, 0, _state);
+    return result;
+}
+
+
+/*************************************************************************
+Basic LU solver for ScaleA*PLU*x = y.
+
+This subroutine assumes that:
+* L is well-scaled, and it is U which needs scaling by ScaleA.
+* A=PLU is well-conditioned, so no zero divisions or overflow may occur
+
+  -- ALGLIB --
+     Copyright 27.01.2010 by Bochkanov Sergey
+*************************************************************************/
+static void densesolver_rbasiclusolve(/* Real    */ ae_matrix* lua,
+     /* Integer */ ae_vector* p,
+     double scalea,
+     ae_int_t n,
+     /* Real    */ ae_vector* xb,
+     /* Real    */ ae_vector* tmp,
+     ae_state *_state)
+{
+    ae_int_t i;
+    double v;
+
+
+    for(i=0; i<=n-1; i++)
+    {
+        if( p->ptr.p_int[i]!=i )
+        {
+            v = xb->ptr.p_double[i];
+            xb->ptr.p_double[i] = xb->ptr.p_double[p->ptr.p_int[i]];
+            xb->ptr.p_double[p->ptr.p_int[i]] = v;
+        }
+    }
+    for(i=1; i<=n-1; i++)
+    {
+        v = ae_v_dotproduct(&lua->ptr.pp_double[i][0], 1, &xb->ptr.p_double[0], 1, ae_v_len(0,i-1));
+        xb->ptr.p_double[i] = xb->ptr.p_double[i]-v;
+    }
+    xb->ptr.p_double[n-1] = xb->ptr.p_double[n-1]/(scalea*lua->ptr.pp_double[n-1][n-1]);
+    for(i=n-2; i>=0; i--)
+    {
+        ae_v_moved(&tmp->ptr.p_double[i+1], 1, &lua->ptr.pp_double[i][i+1], 1, ae_v_len(i+1,n-1), scalea);
+        v = ae_v_dotproduct(&tmp->ptr.p_double[i+1], 1, &xb->ptr.p_double[i+1], 1, ae_v_len(i+1,n-1));
+        xb->ptr.p_double[i] = (xb->ptr.p_double[i]-v)/(scalea*lua->ptr.pp_double[i][i]);
+    }
+}
+
+
+/*************************************************************************
+Basic Cholesky solver for ScaleA*Cholesky(A)'*x = y.
+
+This subroutine assumes that:
+* A*ScaleA is well scaled
+* A is well-conditioned, so no zero divisions or overflow may occur
+
+  -- ALGLIB --
+     Copyright 27.01.2010 by Bochkanov Sergey
+*************************************************************************/
+static void densesolver_spdbasiccholeskysolve(/* Real    */ ae_matrix* cha,
+     double sqrtscalea,
+     ae_int_t n,
+     ae_bool isupper,
+     /* Real    */ ae_vector* xb,
+     /* Real    */ ae_vector* tmp,
+     ae_state *_state)
+{
+    ae_int_t i;
+    double v;
+
+
+    
+    /*
+     * A = L*L' or A=U'*U
+     */
+    if( isupper )
+    {
+        
+        /*
+         * Solve U'*y=b first.
+         */
+        for(i=0; i<=n-1; i++)
+        {
+            xb->ptr.p_double[i] = xb->ptr.p_double[i]/(sqrtscalea*cha->ptr.pp_double[i][i]);
+            if( i<n-1 )
+            {
+                v = xb->ptr.p_double[i];
+                ae_v_moved(&tmp->ptr.p_double[i+1], 1, &cha->ptr.pp_double[i][i+1], 1, ae_v_len(i+1,n-1), sqrtscalea);
+                ae_v_subd(&xb->ptr.p_double[i+1], 1, &tmp->ptr.p_double[i+1], 1, ae_v_len(i+1,n-1), v);
+            }
+        }
+        
+        /*
+         * Solve U*x=y then.
+         */
+        for(i=n-1; i>=0; i--)
+        {
+            if( i<n-1 )
+            {
+                ae_v_moved(&tmp->ptr.p_double[i+1], 1, &cha->ptr.pp_double[i][i+1], 1, ae_v_len(i+1,n-1), sqrtscalea);
+                v = ae_v_dotproduct(&tmp->ptr.p_double[i+1], 1, &xb->ptr.p_double[i+1], 1, ae_v_len(i+1,n-1));
+                xb->ptr.p_double[i] = xb->ptr.p_double[i]-v;
+            }
+            xb->ptr.p_double[i] = xb->ptr.p_double[i]/(sqrtscalea*cha->ptr.pp_double[i][i]);
+        }
+    }
+    else
+    {
+        
+        /*
+         * Solve L*y=b first
+         */
+        for(i=0; i<=n-1; i++)
+        {
+            if( i>0 )
+            {
+                ae_v_moved(&tmp->ptr.p_double[0], 1, &cha->ptr.pp_double[i][0], 1, ae_v_len(0,i-1), sqrtscalea);
+                v = ae_v_dotproduct(&tmp->ptr.p_double[0], 1, &xb->ptr.p_double[0], 1, ae_v_len(0,i-1));
+                xb->ptr.p_double[i] = xb->ptr.p_double[i]-v;
+            }
+            xb->ptr.p_double[i] = xb->ptr.p_double[i]/(sqrtscalea*cha->ptr.pp_double[i][i]);
+        }
+        
+        /*
+         * Solve L'*x=y then.
+         */
+        for(i=n-1; i>=0; i--)
+        {
+            xb->ptr.p_double[i] = xb->ptr.p_double[i]/(sqrtscalea*cha->ptr.pp_double[i][i]);
+            if( i>0 )
+            {
+                v = xb->ptr.p_double[i];
+                ae_v_moved(&tmp->ptr.p_double[0], 1, &cha->ptr.pp_double[i][0], 1, ae_v_len(0,i-1), sqrtscalea);
+                ae_v_subd(&xb->ptr.p_double[0], 1, &tmp->ptr.p_double[0], 1, ae_v_len(0,i-1), v);
+            }
+        }
+    }
+}
+
+
+/*************************************************************************
+Basic LU solver for ScaleA*PLU*x = y.
+
+This subroutine assumes that:
+* L is well-scaled, and it is U which needs scaling by ScaleA.
+* A=PLU is well-conditioned, so no zero divisions or overflow may occur
+
+  -- ALGLIB --
+     Copyright 27.01.2010 by Bochkanov Sergey
+*************************************************************************/
+static void densesolver_cbasiclusolve(/* Complex */ ae_matrix* lua,
+     /* Integer */ ae_vector* p,
+     double scalea,
+     ae_int_t n,
+     /* Complex */ ae_vector* xb,
+     /* Complex */ ae_vector* tmp,
+     ae_state *_state)
+{
+    ae_int_t i;
+    ae_complex v;
+
+
+    for(i=0; i<=n-1; i++)
+    {
+        if( p->ptr.p_int[i]!=i )
+        {
+            v = xb->ptr.p_complex[i];
+            xb->ptr.p_complex[i] = xb->ptr.p_complex[p->ptr.p_int[i]];
+            xb->ptr.p_complex[p->ptr.p_int[i]] = v;
+        }
+    }
+    for(i=1; i<=n-1; i++)
+    {
+        v = ae_v_cdotproduct(&lua->ptr.pp_complex[i][0], 1, "N", &xb->ptr.p_complex[0], 1, "N", ae_v_len(0,i-1));
+        xb->ptr.p_complex[i] = ae_c_sub(xb->ptr.p_complex[i],v);
+    }
+    xb->ptr.p_complex[n-1] = ae_c_div(xb->ptr.p_complex[n-1],ae_c_mul_d(lua->ptr.pp_complex[n-1][n-1],scalea));
+    for(i=n-2; i>=0; i--)
+    {
+        ae_v_cmoved(&tmp->ptr.p_complex[i+1], 1, &lua->ptr.pp_complex[i][i+1], 1, "N", ae_v_len(i+1,n-1), scalea);
+        v = ae_v_cdotproduct(&tmp->ptr.p_complex[i+1], 1, "N", &xb->ptr.p_complex[i+1], 1, "N", ae_v_len(i+1,n-1));
+        xb->ptr.p_complex[i] = ae_c_div(ae_c_sub(xb->ptr.p_complex[i],v),ae_c_mul_d(lua->ptr.pp_complex[i][i],scalea));
+    }
+}
+
+
+/*************************************************************************
+Basic Cholesky solver for ScaleA*Cholesky(A)'*x = y.
+
+This subroutine assumes that:
+* A*ScaleA is well scaled
+* A is well-conditioned, so no zero divisions or overflow may occur
+
+  -- ALGLIB --
+     Copyright 27.01.2010 by Bochkanov Sergey
+*************************************************************************/
+static void densesolver_hpdbasiccholeskysolve(/* Complex */ ae_matrix* cha,
+     double sqrtscalea,
+     ae_int_t n,
+     ae_bool isupper,
+     /* Complex */ ae_vector* xb,
+     /* Complex */ ae_vector* tmp,
+     ae_state *_state)
+{
+    ae_int_t i;
+    ae_complex v;
+
+
+    
+    /*
+     * A = L*L' or A=U'*U
+     */
+    if( isupper )
+    {
+        
+        /*
+         * Solve U'*y=b first.
+         */
+        for(i=0; i<=n-1; i++)
+        {
+            xb->ptr.p_complex[i] = ae_c_div(xb->ptr.p_complex[i],ae_c_mul_d(ae_c_conj(cha->ptr.pp_complex[i][i], _state),sqrtscalea));
+            if( i<n-1 )
+            {
+                v = xb->ptr.p_complex[i];
+                ae_v_cmoved(&tmp->ptr.p_complex[i+1], 1, &cha->ptr.pp_complex[i][i+1], 1, "Conj", ae_v_len(i+1,n-1), sqrtscalea);
+                ae_v_csubc(&xb->ptr.p_complex[i+1], 1, &tmp->ptr.p_complex[i+1], 1, "N", ae_v_len(i+1,n-1), v);
+            }
+        }
+        
+        /*
+         * Solve U*x=y then.
+         */
+        for(i=n-1; i>=0; i--)
+        {
+            if( i<n-1 )
+            {
+                ae_v_cmoved(&tmp->ptr.p_complex[i+1], 1, &cha->ptr.pp_complex[i][i+1], 1, "N", ae_v_len(i+1,n-1), sqrtscalea);
+                v = ae_v_cdotproduct(&tmp->ptr.p_complex[i+1], 1, "N", &xb->ptr.p_complex[i+1], 1, "N", ae_v_len(i+1,n-1));
+                xb->ptr.p_complex[i] = ae_c_sub(xb->ptr.p_complex[i],v);
+            }
+            xb->ptr.p_complex[i] = ae_c_div(xb->ptr.p_complex[i],ae_c_mul_d(cha->ptr.pp_complex[i][i],sqrtscalea));
+        }
+    }
+    else
+    {
+        
+        /*
+         * Solve L*y=b first
+         */
+        for(i=0; i<=n-1; i++)
+        {
+            if( i>0 )
+            {
+                ae_v_cmoved(&tmp->ptr.p_complex[0], 1, &cha->ptr.pp_complex[i][0], 1, "N", ae_v_len(0,i-1), sqrtscalea);
+                v = ae_v_cdotproduct(&tmp->ptr.p_complex[0], 1, "N", &xb->ptr.p_complex[0], 1, "N", ae_v_len(0,i-1));
+                xb->ptr.p_complex[i] = ae_c_sub(xb->ptr.p_complex[i],v);
+            }
+            xb->ptr.p_complex[i] = ae_c_div(xb->ptr.p_complex[i],ae_c_mul_d(cha->ptr.pp_complex[i][i],sqrtscalea));
+        }
+        
+        /*
+         * Solve L'*x=y then.
+         */
+        for(i=n-1; i>=0; i--)
+        {
+            xb->ptr.p_complex[i] = ae_c_div(xb->ptr.p_complex[i],ae_c_mul_d(ae_c_conj(cha->ptr.pp_complex[i][i], _state),sqrtscalea));
+            if( i>0 )
+            {
+                v = xb->ptr.p_complex[i];
+                ae_v_cmoved(&tmp->ptr.p_complex[0], 1, &cha->ptr.pp_complex[i][0], 1, "Conj", ae_v_len(0,i-1), sqrtscalea);
+                ae_v_csubc(&xb->ptr.p_complex[0], 1, &tmp->ptr.p_complex[0], 1, "N", ae_v_len(0,i-1), v);
+            }
+        }
+    }
+}
+
+
+ae_bool _densesolverreport_init(densesolverreport* p, ae_state *_state, ae_bool make_automatic)
+{
+    return ae_true;
+}
+
+
+ae_bool _densesolverreport_init_copy(densesolverreport* dst, densesolverreport* src, ae_state *_state, ae_bool make_automatic)
+{
+    dst->r1 = src->r1;
+    dst->rinf = src->rinf;
+    return ae_true;
+}
+
+
+void _densesolverreport_clear(densesolverreport* p)
+{
+}
+
+
+ae_bool _densesolverlsreport_init(densesolverlsreport* p, ae_state *_state, ae_bool make_automatic)
+{
+    if( !ae_matrix_init(&p->cx, 0, 0, DT_REAL, _state, make_automatic) )
+        return ae_false;
+    return ae_true;
+}
+
+
+ae_bool _densesolverlsreport_init_copy(densesolverlsreport* dst, densesolverlsreport* src, ae_state *_state, ae_bool make_automatic)
+{
+    dst->r2 = src->r2;
+    if( !ae_matrix_init_copy(&dst->cx, &src->cx, _state, make_automatic) )
+        return ae_false;
+    dst->n = src->n;
+    dst->k = src->k;
+    return ae_true;
+}
+
+
+void _densesolverlsreport_clear(densesolverlsreport* p)
+{
+    ae_matrix_clear(&p->cx);
+}
+
+
+
+
+/*************************************************************************
+                LEVENBERG-MARQUARDT-LIKE NONLINEAR SOLVER
+
+DESCRIPTION:
+This algorithm solves system of nonlinear equations
+    F[0](x[0], ..., x[n-1])   = 0
+    F[1](x[0], ..., x[n-1])   = 0
+    ...
+    F[M-1](x[0], ..., x[n-1]) = 0
+with M/N do not necessarily coincide.  Algorithm  converges  quadratically
+under following conditions:
+    * the solution set XS is nonempty
+    * for some xs in XS there exist such neighbourhood N(xs) that:
+      * vector function F(x) and its Jacobian J(x) are continuously
+        differentiable on N
+      * ||F(x)|| provides local error bound on N, i.e. there  exists  such
+        c1, that ||F(x)||>c1*distance(x,XS)
+Note that these conditions are much more weaker than usual non-singularity
+conditions. For example, algorithm will converge for any  affine  function
+F (whether its Jacobian singular or not).
+
+
+REQUIREMENTS:
+Algorithm will request following information during its operation:
+* function vector F[] and Jacobian matrix at given point X
+* value of merit function f(x)=F[0]^2(x)+...+F[M-1]^2(x) at given point X
+
+
+USAGE:
+1. User initializes algorithm state with NLEQCreateLM() call
+2. User tunes solver parameters with  NLEQSetCond(),  NLEQSetStpMax()  and
+   other functions
+3. User  calls  NLEQSolve()  function  which  takes  algorithm  state  and
+   pointers (delegates, etc.) to callback functions which calculate  merit
+   function value and Jacobian.
+4. User calls NLEQResults() to get solution
+5. Optionally, user may call NLEQRestartFrom() to  solve  another  problem
+   with same parameters (N/M) but another starting  point  and/or  another
+   function vector. NLEQRestartFrom() allows to reuse already  initialized
+   structure.
+
+
+INPUT PARAMETERS:
+    N       -   space dimension, N>1:
+                * if provided, only leading N elements of X are used
+                * if not provided, determined automatically from size of X
+    M       -   system size
+    X       -   starting point
+
+
+OUTPUT PARAMETERS:
+    State   -   structure which stores algorithm state
+
+
+NOTES:
+1. you may tune stopping conditions with NLEQSetCond() function
+2. if target function contains exp() or other fast growing functions,  and
+   optimization algorithm makes too large steps which leads  to  overflow,
+   use NLEQSetStpMax() function to bound algorithm's steps.
+3. this  algorithm  is  a  slightly  modified implementation of the method
+   described  in  'Levenberg-Marquardt  method  for constrained  nonlinear
+   equations with strong local convergence properties' by Christian Kanzow
+   Nobuo Yamashita and Masao Fukushima and further  developed  in  'On the
+   convergence of a New Levenberg-Marquardt Method'  by  Jin-yan  Fan  and
+   Ya-Xiang Yuan.
+
+
+  -- ALGLIB --
+     Copyright 20.08.2009 by Bochkanov Sergey
+*************************************************************************/
+void nleqcreatelm(ae_int_t n,
+     ae_int_t m,
+     /* Real    */ ae_vector* x,
+     nleqstate* state,
+     ae_state *_state)
+{
+
+    _nleqstate_clear(state);
+
+    ae_assert(n>=1, "NLEQCreateLM: N<1!", _state);
+    ae_assert(m>=1, "NLEQCreateLM: M<1!", _state);
+    ae_assert(x->cnt>=n, "NLEQCreateLM: Length(X)<N!", _state);
+    ae_assert(isfinitevector(x, n, _state), "NLEQCreateLM: X contains infinite or NaN values!", _state);
+    
+    /*
+     * Initialize
+     */
+    state->n = n;
+    state->m = m;
+    nleqsetcond(state, 0, 0, _state);
+    nleqsetxrep(state, ae_false, _state);
+    nleqsetstpmax(state, 0, _state);
+    ae_vector_set_length(&state->x, n, _state);
+    ae_vector_set_length(&state->xbase, n, _state);
+    ae_matrix_set_length(&state->j, m, n, _state);
+    ae_vector_set_length(&state->fi, m, _state);
+    ae_vector_set_length(&state->rightpart, n, _state);
+    ae_vector_set_length(&state->candstep, n, _state);
+    nleqrestartfrom(state, x, _state);
+}
+
+
+/*************************************************************************
+This function sets stopping conditions for the nonlinear solver
+
+INPUT PARAMETERS:
+    State   -   structure which stores algorithm state
+    EpsF    -   >=0
+                The subroutine finishes  its work if on k+1-th iteration
+                the condition ||F||<=EpsF is satisfied
+    MaxIts  -   maximum number of iterations. If MaxIts=0, the  number  of
+                iterations is unlimited.
+
+Passing EpsF=0 and MaxIts=0 simultaneously will lead to  automatic
+stopping criterion selection (small EpsF).
+
+NOTES:
+
+  -- ALGLIB --
+     Copyright 20.08.2010 by Bochkanov Sergey
+*************************************************************************/
+void nleqsetcond(nleqstate* state,
+     double epsf,
+     ae_int_t maxits,
+     ae_state *_state)
+{
+
+
+    ae_assert(ae_isfinite(epsf, _state), "NLEQSetCond: EpsF is not finite number!", _state);
+    ae_assert(ae_fp_greater_eq(epsf,0), "NLEQSetCond: negative EpsF!", _state);
+    ae_assert(maxits>=0, "NLEQSetCond: negative MaxIts!", _state);
+    if( ae_fp_eq(epsf,0)&&maxits==0 )
+    {
+        epsf = 1.0E-6;
+    }
+    state->epsf = epsf;
+    state->maxits = maxits;
+}
+
+
+/*************************************************************************
+This function turns on/off reporting.
+
+INPUT PARAMETERS:
+    State   -   structure which stores algorithm state
+    NeedXRep-   whether iteration reports are needed or not
+
+If NeedXRep is True, algorithm will call rep() callback function if  it is
+provided to NLEQSolve().
+
+  -- ALGLIB --
+     Copyright 20.08.2010 by Bochkanov Sergey
+*************************************************************************/
+void nleqsetxrep(nleqstate* state, ae_bool needxrep, ae_state *_state)
+{
+
+
+    state->xrep = needxrep;
+}
+
+
+/*************************************************************************
+This function sets maximum step length
+
+INPUT PARAMETERS:
+    State   -   structure which stores algorithm state
+    StpMax  -   maximum step length, >=0. Set StpMax to 0.0,  if you don't
+                want to limit step length.
+
+Use this subroutine when target function  contains  exp()  or  other  fast
+growing functions, and algorithm makes  too  large  steps  which  lead  to
+overflow. This function allows us to reject steps that are too large  (and
+therefore expose us to the possible overflow) without actually calculating
+function value at the x+stp*d.
+
+  -- ALGLIB --
+     Copyright 20.08.2010 by Bochkanov Sergey
+*************************************************************************/
+void nleqsetstpmax(nleqstate* state, double stpmax, ae_state *_state)
+{
+
+
+    ae_assert(ae_isfinite(stpmax, _state), "NLEQSetStpMax: StpMax is not finite!", _state);
+    ae_assert(ae_fp_greater_eq(stpmax,0), "NLEQSetStpMax: StpMax<0!", _state);
+    state->stpmax = stpmax;
+}
+
+
+/*************************************************************************
+
+  -- ALGLIB --
+     Copyright 20.03.2009 by Bochkanov Sergey
+*************************************************************************/
+ae_bool nleqiteration(nleqstate* state, ae_state *_state)
+{
+    ae_int_t n;
+    ae_int_t m;
+    ae_int_t i;
+    double lambdaup;
+    double lambdadown;
+    double lambdav;
+    double rho;
+    double mu;
+    double stepnorm;
+    ae_bool b;
+    ae_bool result;
+
+
+    
+    /*
+     * Reverse communication preparations
+     * I know it looks ugly, but it works the same way
+     * anywhere from C++ to Python.
+     *
+     * This code initializes locals by:
+     * * random values determined during code
+     *   generation - on first subroutine call
+     * * values from previous call - on subsequent calls
+     */
+    if( state->rstate.stage>=0 )
+    {
+        n = state->rstate.ia.ptr.p_int[0];
+        m = state->rstate.ia.ptr.p_int[1];
+        i = state->rstate.ia.ptr.p_int[2];
+        b = state->rstate.ba.ptr.p_bool[0];
+        lambdaup = state->rstate.ra.ptr.p_double[0];
+        lambdadown = state->rstate.ra.ptr.p_double[1];
+        lambdav = state->rstate.ra.ptr.p_double[2];
+        rho = state->rstate.ra.ptr.p_double[3];
+        mu = state->rstate.ra.ptr.p_double[4];
+        stepnorm = state->rstate.ra.ptr.p_double[5];
+    }
+    else
+    {
+        n = -983;
+        m = -989;
+        i = -834;
+        b = ae_false;
+        lambdaup = -287;
+        lambdadown = 364;
+        lambdav = 214;
+        rho = -338;
+        mu = -686;
+        stepnorm = 912;
+    }
+    if( state->rstate.stage==0 )
+    {
+        goto lbl_0;
+    }
+    if( state->rstate.stage==1 )
+    {
+        goto lbl_1;
+    }
+    if( state->rstate.stage==2 )
+    {
+        goto lbl_2;
+    }
+    if( state->rstate.stage==3 )
+    {
+        goto lbl_3;
+    }
+    if( state->rstate.stage==4 )
+    {
+        goto lbl_4;
+    }
+    
+    /*
+     * Routine body
+     */
+    
+    /*
+     * Prepare
+     */
+    n = state->n;
+    m = state->m;
+    state->repterminationtype = 0;
+    state->repiterationscount = 0;
+    state->repnfunc = 0;
+    state->repnjac = 0;
+    
+    /*
+     * Calculate F/G, initialize algorithm
+     */
+    nleq_clearrequestfields(state, _state);
+    state->needf = ae_true;
+    state->rstate.stage = 0;
+    goto lbl_rcomm;
+lbl_0:
+    state->needf = ae_false;
+    state->repnfunc = state->repnfunc+1;
+    ae_v_move(&state->xbase.ptr.p_double[0], 1, &state->x.ptr.p_double[0], 1, ae_v_len(0,n-1));
+    state->fbase = state->f;
+    state->fprev = ae_maxrealnumber;
+    if( !state->xrep )
+    {
+        goto lbl_5;
+    }
+    
+    /*
+     * progress report
+     */
+    nleq_clearrequestfields(state, _state);
+    state->xupdated = ae_true;
+    state->rstate.stage = 1;
+    goto lbl_rcomm;
+lbl_1:
+    state->xupdated = ae_false;
+lbl_5:
+    if( ae_fp_less_eq(state->f,ae_sqr(state->epsf, _state)) )
+    {
+        state->repterminationtype = 1;
+        result = ae_false;
+        return result;
+    }
+    
+    /*
+     * Main cycle
+     */
+    lambdaup = 10;
+    lambdadown = 0.3;
+    lambdav = 0.001;
+    rho = 1;
+lbl_7:
+    if( ae_false )
+    {
+        goto lbl_8;
+    }
+    
+    /*
+     * Get Jacobian;
+     * before we get to this point we already have State.XBase filled
+     * with current point and State.FBase filled with function value
+     * at XBase
+     */
+    nleq_clearrequestfields(state, _state);
+    state->needfij = ae_true;
+    ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
+    state->rstate.stage = 2;
+    goto lbl_rcomm;
+lbl_2:
+    state->needfij = ae_false;
+    state->repnfunc = state->repnfunc+1;
+    state->repnjac = state->repnjac+1;
+    rmatrixmv(n, m, &state->j, 0, 0, 1, &state->fi, 0, &state->rightpart, 0, _state);
+    ae_v_muld(&state->rightpart.ptr.p_double[0], 1, ae_v_len(0,n-1), -1);
+    
+    /*
+     * Inner cycle: find good lambda
+     */
+lbl_9:
+    if( ae_false )
+    {
+        goto lbl_10;
+    }
+    
+    /*
+     * Solve (J^T*J + (Lambda+Mu)*I)*y = J^T*F
+     * to get step d=-y where:
+     * * Mu=||F|| - is damping parameter for nonlinear system
+     * * Lambda   - is additional Levenberg-Marquardt parameter
+     *              for better convergence when far away from minimum
+     */
+    for(i=0; i<=n-1; i++)
+    {
+        state->candstep.ptr.p_double[i] = 0;
+    }
+    fblssolvecgx(&state->j, m, n, lambdav, &state->rightpart, &state->candstep, &state->cgbuf, _state);
+    
+    /*
+     * Normalize step (it must be no more than StpMax)
+     */
+    stepnorm = 0;
+    for(i=0; i<=n-1; i++)
+    {
+        if( ae_fp_neq(state->candstep.ptr.p_double[i],0) )
+        {
+            stepnorm = 1;
+            break;
+        }
+    }
+    linminnormalized(&state->candstep, &stepnorm, n, _state);
+    if( ae_fp_neq(state->stpmax,0) )
+    {
+        stepnorm = ae_minreal(stepnorm, state->stpmax, _state);
+    }
+    
+    /*
+     * Test new step - is it good enough?
+     * * if not, Lambda is increased and we try again.
+     * * if step is good, we decrease Lambda and move on.
+     *
+     * We can break this cycle on two occasions:
+     * * step is so small that x+step==x (in floating point arithmetics)
+     * * lambda is so large
+     */
+    ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
+    ae_v_addd(&state->x.ptr.p_double[0], 1, &state->candstep.ptr.p_double[0], 1, ae_v_len(0,n-1), stepnorm);
+    b = ae_true;
+    for(i=0; i<=n-1; i++)
+    {
+        if( ae_fp_neq(state->x.ptr.p_double[i],state->xbase.ptr.p_double[i]) )
+        {
+            b = ae_false;
+            break;
+        }
+    }
+    if( b )
+    {
+        
+        /*
+         * Step is too small, force zero step and break
+         */
+        stepnorm = 0;
+        ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
+        state->f = state->fbase;
+        goto lbl_10;
+    }
+    nleq_clearrequestfields(state, _state);
+    state->needf = ae_true;
+    state->rstate.stage = 3;
+    goto lbl_rcomm;
+lbl_3:
+    state->needf = ae_false;
+    state->repnfunc = state->repnfunc+1;
+    if( ae_fp_less(state->f,state->fbase) )
+    {
+        
+        /*
+         * function value decreased, move on
+         */
+        nleq_decreaselambda(&lambdav, &rho, lambdadown, _state);
+        goto lbl_10;
+    }
+    if( !nleq_increaselambda(&lambdav, &rho, lambdaup, _state) )
+    {
+        
+        /*
+         * Lambda is too large (near overflow), force zero step and break
+         */
+        stepnorm = 0;
+        ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
+        state->f = state->fbase;
+        goto lbl_10;
+    }
+    goto lbl_9;
+lbl_10:
+    
+    /*
+     * Accept step:
+     * * new position
+     * * new function value
+     */
+    state->fbase = state->f;
+    ae_v_addd(&state->xbase.ptr.p_double[0], 1, &state->candstep.ptr.p_double[0], 1, ae_v_len(0,n-1), stepnorm);
+    state->repiterationscount = state->repiterationscount+1;
+    
+    /*
+     * Report new iteration
+     */
+    if( !state->xrep )
+    {
+        goto lbl_11;
+    }
+    nleq_clearrequestfields(state, _state);
+    state->xupdated = ae_true;
+    state->f = state->fbase;
+    ae_v_move(&state->x.ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,n-1));
+    state->rstate.stage = 4;
+    goto lbl_rcomm;
+lbl_4:
+    state->xupdated = ae_false;
+lbl_11:
+    
+    /*
+     * Test stopping conditions on F, step (zero/non-zero) and MaxIts;
+     * If one of the conditions is met, RepTerminationType is changed.
+     */
+    if( ae_fp_less_eq(ae_sqrt(state->f, _state),state->epsf) )
+    {
+        state->repterminationtype = 1;
+    }
+    if( ae_fp_eq(stepnorm,0)&&state->repterminationtype==0 )
+    {
+        state->repterminationtype = -4;
+    }
+    if( state->repiterationscount>=state->maxits&&state->maxits>0 )
+    {
+        state->repterminationtype = 5;
+    }
+    if( state->repterminationtype!=0 )
+    {
+        goto lbl_8;
+    }
+    
+    /*
+     * Now, iteration is finally over
+     */
+    goto lbl_7;
+lbl_8:
+    result = ae_false;
+    return result;
+    
+    /*
+     * Saving state
+     */
+lbl_rcomm:
+    result = ae_true;
+    state->rstate.ia.ptr.p_int[0] = n;
+    state->rstate.ia.ptr.p_int[1] = m;
+    state->rstate.ia.ptr.p_int[2] = i;
+    state->rstate.ba.ptr.p_bool[0] = b;
+    state->rstate.ra.ptr.p_double[0] = lambdaup;
+    state->rstate.ra.ptr.p_double[1] = lambdadown;
+    state->rstate.ra.ptr.p_double[2] = lambdav;
+    state->rstate.ra.ptr.p_double[3] = rho;
+    state->rstate.ra.ptr.p_double[4] = mu;
+    state->rstate.ra.ptr.p_double[5] = stepnorm;
+    return result;
+}
+
+
+/*************************************************************************
+NLEQ solver results
+
+INPUT PARAMETERS:
+    State   -   algorithm state.
+
+OUTPUT PARAMETERS:
+    X       -   array[0..N-1], solution
+    Rep     -   optimization report:
+                * Rep.TerminationType completetion code:
+                    * -4    ERROR:  algorithm   has   converged   to   the
+                            stationary point Xf which is local minimum  of
+                            f=F[0]^2+...+F[m-1]^2, but is not solution  of
+                            nonlinear system.
+                    *  1    sqrt(f)<=EpsF.
+                    *  5    MaxIts steps was taken
+                    *  7    stopping conditions are too stringent,
+                            further improvement is impossible
+                * Rep.IterationsCount contains iterations count
+                * NFEV countains number of function calculations
+                * ActiveConstraints contains number of active constraints
+
+  -- ALGLIB --
+     Copyright 20.08.2009 by Bochkanov Sergey
+*************************************************************************/
+void nleqresults(nleqstate* state,
+     /* Real    */ ae_vector* x,
+     nleqreport* rep,
+     ae_state *_state)
+{
+
+    ae_vector_clear(x);
+    _nleqreport_clear(rep);
+
+    nleqresultsbuf(state, x, rep, _state);
+}
+
+
+/*************************************************************************
+NLEQ solver results
+
+Buffered implementation of NLEQResults(), which uses pre-allocated  buffer
+to store X[]. If buffer size is  too  small,  it  resizes  buffer.  It  is
+intended to be used in the inner cycles of performance critical algorithms
+where array reallocation penalty is too large to be ignored.
+
+  -- ALGLIB --
+     Copyright 20.08.2009 by Bochkanov Sergey
+*************************************************************************/
+void nleqresultsbuf(nleqstate* state,
+     /* Real    */ ae_vector* x,
+     nleqreport* rep,
+     ae_state *_state)
+{
+
+
+    if( x->cnt<state->n )
+    {
+        ae_vector_set_length(x, state->n, _state);
+    }
+    ae_v_move(&x->ptr.p_double[0], 1, &state->xbase.ptr.p_double[0], 1, ae_v_len(0,state->n-1));
+    rep->iterationscount = state->repiterationscount;
+    rep->nfunc = state->repnfunc;
+    rep->njac = state->repnjac;
+    rep->terminationtype = state->repterminationtype;
+}
+
+
+/*************************************************************************
+This  subroutine  restarts  CG  algorithm from new point. All optimization
+parameters are left unchanged.
+
+This  function  allows  to  solve multiple  optimization  problems  (which
+must have same number of dimensions) without object reallocation penalty.
+
+INPUT PARAMETERS:
+    State   -   structure used for reverse communication previously
+                allocated with MinCGCreate call.
+    X       -   new starting point.
+    BndL    -   new lower bounds
+    BndU    -   new upper bounds
+
+  -- ALGLIB --
+     Copyright 30.07.2010 by Bochkanov Sergey
+*************************************************************************/
+void nleqrestartfrom(nleqstate* state,
+     /* Real    */ ae_vector* x,
+     ae_state *_state)
+{
+
+
+    ae_assert(x->cnt>=state->n, "NLEQRestartFrom: Length(X)<N!", _state);
+    ae_assert(isfinitevector(x, state->n, _state), "NLEQRestartFrom: X contains infinite or NaN values!", _state);
+    ae_v_move(&state->x.ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,state->n-1));
+    ae_vector_set_length(&state->rstate.ia, 2+1, _state);
+    ae_vector_set_length(&state->rstate.ba, 0+1, _state);
+    ae_vector_set_length(&state->rstate.ra, 5+1, _state);
+    state->rstate.stage = -1;
+    nleq_clearrequestfields(state, _state);
+}
+
+
+/*************************************************************************
+Clears request fileds (to be sure that we don't forgot to clear something)
+*************************************************************************/
+static void nleq_clearrequestfields(nleqstate* state, ae_state *_state)
+{
+
+
+    state->needf = ae_false;
+    state->needfij = ae_false;
+    state->xupdated = ae_false;
+}
+
+
+/*************************************************************************
+Increases lambda, returns False when there is a danger of overflow
+*************************************************************************/
+static ae_bool nleq_increaselambda(double* lambdav,
+     double* nu,
+     double lambdaup,
+     ae_state *_state)
+{
+    double lnlambda;
+    double lnnu;
+    double lnlambdaup;
+    double lnmax;
+    ae_bool result;
+
+
+    result = ae_false;
+    lnlambda = ae_log(*lambdav, _state);
+    lnlambdaup = ae_log(lambdaup, _state);
+    lnnu = ae_log(*nu, _state);
+    lnmax = 0.5*ae_log(ae_maxrealnumber, _state);
+    if( ae_fp_greater(lnlambda+lnlambdaup+lnnu,lnmax) )
+    {
+        return result;
+    }
+    if( ae_fp_greater(lnnu+ae_log(2, _state),lnmax) )
+    {
+        return result;
+    }
+    *lambdav = *lambdav*lambdaup*(*nu);
+    *nu = *nu*2;
+    result = ae_true;
+    return result;
+}
+
+
+/*************************************************************************
+Decreases lambda, but leaves it unchanged when there is danger of underflow.
+*************************************************************************/
+static void nleq_decreaselambda(double* lambdav,
+     double* nu,
+     double lambdadown,
+     ae_state *_state)
+{
+
+
+    *nu = 1;
+    if( ae_fp_less(ae_log(*lambdav, _state)+ae_log(lambdadown, _state),ae_log(ae_minrealnumber, _state)) )
+    {
+        *lambdav = ae_minrealnumber;
+    }
+    else
+    {
+        *lambdav = *lambdav*lambdadown;
+    }
+}
+
+
+ae_bool _nleqstate_init(nleqstate* p, ae_state *_state, ae_bool make_automatic)
+{
+    if( !ae_vector_init(&p->x, 0, DT_REAL, _state, make_automatic) )
+        return ae_false;
+    if( !ae_vector_init(&p->fi, 0, DT_REAL, _state, make_automatic) )
+        return ae_false;
+    if( !ae_matrix_init(&p->j, 0, 0, DT_REAL, _state, make_automatic) )
+        return ae_false;
+    if( !_rcommstate_init(&p->rstate, _state, make_automatic) )
+        return ae_false;
+    if( !ae_vector_init(&p->xbase, 0, DT_REAL, _state, make_automatic) )
+        return ae_false;
+    if( !ae_vector_init(&p->candstep, 0, DT_REAL, _state, make_automatic) )
+        return ae_false;
+    if( !ae_vector_init(&p->rightpart, 0, DT_REAL, _state, make_automatic) )
+        return ae_false;
+    if( !ae_vector_init(&p->cgbuf, 0, DT_REAL, _state, make_automatic) )
+        return ae_false;
+    return ae_true;
+}
+
+
+ae_bool _nleqstate_init_copy(nleqstate* dst, nleqstate* src, ae_state *_state, ae_bool make_automatic)
+{
+    dst->n = src->n;
+    dst->m = src->m;
+    dst->epsf = src->epsf;
+    dst->maxits = src->maxits;
+    dst->xrep = src->xrep;
+    dst->stpmax = src->stpmax;
+    if( !ae_vector_init_copy(&dst->x, &src->x, _state, make_automatic) )
+        return ae_false;
+    dst->f = src->f;
+    if( !ae_vector_init_copy(&dst->fi, &src->fi, _state, make_automatic) )
+        return ae_false;
+    if( !ae_matrix_init_copy(&dst->j, &src->j, _state, make_automatic) )
+        return ae_false;
+    dst->needf = src->needf;
+    dst->needfij = src->needfij;
+    dst->xupdated = src->xupdated;
+    if( !_rcommstate_init_copy(&dst->rstate, &src->rstate, _state, make_automatic) )
+        return ae_false;
+    dst->repiterationscount = src->repiterationscount;
+    dst->repnfunc = src->repnfunc;
+    dst->repnjac = src->repnjac;
+    dst->repterminationtype = src->repterminationtype;
+    if( !ae_vector_init_copy(&dst->xbase, &src->xbase, _state, make_automatic) )
+        return ae_false;
+    dst->fbase = src->fbase;
+    dst->fprev = src->fprev;
+    if( !ae_vector_init_copy(&dst->candstep, &src->candstep, _state, make_automatic) )
+        return ae_false;
+    if( !ae_vector_init_copy(&dst->rightpart, &src->rightpart, _state, make_automatic) )
+        return ae_false;
+    if( !ae_vector_init_copy(&dst->cgbuf, &src->cgbuf, _state, make_automatic) )
+        return ae_false;
+    return ae_true;
+}
+
+
+void _nleqstate_clear(nleqstate* p)
+{
+    ae_vector_clear(&p->x);
+    ae_vector_clear(&p->fi);
+    ae_matrix_clear(&p->j);
+    _rcommstate_clear(&p->rstate);
+    ae_vector_clear(&p->xbase);
+    ae_vector_clear(&p->candstep);
+    ae_vector_clear(&p->rightpart);
+    ae_vector_clear(&p->cgbuf);
+}
+
+
+ae_bool _nleqreport_init(nleqreport* p, ae_state *_state, ae_bool make_automatic)
+{
+    return ae_true;
+}
+
+
+ae_bool _nleqreport_init_copy(nleqreport* dst, nleqreport* src, ae_state *_state, ae_bool make_automatic)
+{
+    dst->iterationscount = src->iterationscount;
+    dst->nfunc = src->nfunc;
+    dst->njac = src->njac;
+    dst->terminationtype = src->terminationtype;
+    return ae_true;
+}
+
+
+void _nleqreport_clear(nleqreport* p)
+{
+}
+
+
+
+}
+