* Bug #15117 fixed - Optimization: fix imbricated optimizers calls 51/19251/8
Paul Bignier [Mon, 10 Apr 2017 12:49:03 +0000 (14:49 +0200)]
  test_run optimization bug_15117
  test_run optimization bug_15117 mode_nwni_profiling

Change-Id: I56767debaec42b1bfbfe44031059b3a3485c1dad

scilab/CHANGES.md
scilab/modules/optimization/includes/optimizationfunctions.hxx
scilab/modules/optimization/sci_gateway/cpp/sci_fsolve.cpp
scilab/modules/optimization/sci_gateway/cpp/sci_lsqrsolve.cpp
scilab/modules/optimization/src/cpp/optimizationfunctions.cpp
scilab/modules/optimization/tests/nonreg_tests/bug_15117.tst [new file with mode: 0644]

index d776000..7dc4475 100644 (file)
@@ -370,6 +370,7 @@ the [development mailing list](dev@lists.scilab.org) for a particular toolbox.
 * [#15060](http://bugzilla.scilab.org/show_bug.cgi?id=15060): `fplot3d` did not draw because of an addition with an empty matrix which now returns an empty matrix.
 * [#15072](http://bugzilla.scilab.org/show_bug.cgi?id=15072): The context was stored as a root diagram attribute instead of being stored on each Superblock layer.
 * [#15079](http://bugzilla.scilab.org/show_bug.cgi?id=15079): When all children of a graphic handle have not the same number of sub-children, any vectorized extraction or insertion in subchildren failed.
+* [#15117](http://bugzilla.scilab.org/show_bug.cgi?id=15117): Imbricated optim/leastsq/lsqrsolve/fsolve calls either crashed or returned errors
 
 
 ### Bugs fixed in 6.0.0:
index 5bf1709..120ec44 100644 (file)
@@ -16,6 +16,7 @@
 #ifndef __OPTIMIZATIONS_HXX__
 #define __OPTIMIZATIONS_HXX__
 
+#include <vector>
 #include <map>
 #include "dynlib_optimization.h"
 #include "string.hxx"
@@ -111,7 +112,7 @@ class OPTIMIZATION_IMPEXP Optimization
 {
     // differential equation functions
 private :
-    static OptimizationFunctions* m_OptimizationFunctions;
+    static std::vector<OptimizationFunctions*> m_OptimizationFunctions;
 
 public :
     static void addOptimizationFunctions(OptimizationFunctions* _opFunction);
index 7303a52..dd9555c 100644 (file)
@@ -33,8 +33,6 @@ extern "C"
 
 types::Function::ReturnValue sci_fsolve(types::typed_list &in, int _iRetCount, types::typed_list &out)
 {
-    OptimizationFunctions* opFunctionsManager = NULL;
-
     types::Double* pDblX    = NULL;
     types::Double* pDblV    = NULL;
     types::Double* pDblTol  = NULL;
@@ -80,26 +78,27 @@ types::Function::ReturnValue sci_fsolve(types::typed_list &in, int _iRetCount, t
     iSizeX = pDblX->getSize();
 
     // get function
-    opFunctionsManager = new OptimizationFunctions(L"fsolve");
-    Optimization::addOptimizationFunctions(opFunctionsManager);
-    opFunctionsManager->setXRows(pDblX->getRows());
-    opFunctionsManager->setXCols(pDblX->getCols());
+    OptimizationFunctions opFunctionsManager(L"fsolve");
+    Optimization::addOptimizationFunctions(&opFunctionsManager);
+    opFunctionsManager.setXRows(pDblX->getRows());
+    opFunctionsManager.setXCols(pDblX->getCols());
 
     if (in[1]->isCallable())
     {
         types::Callable* pCall = in[1]->getAs<types::Callable>();
-        opFunctionsManager->setFsolveFctFunction(pCall);
+        opFunctionsManager.setFsolveFctFunction(pCall);
     }
     else if (in[1]->isString())
     {
         types::String* pStr = in[1]->getAs<types::String>();
         char* pst = wide_string_to_UTF8(pStr->get(0));
-        bool bOK = opFunctionsManager->setFsolveFctFunction(pStr);
+        bool bOK = opFunctionsManager.setFsolveFctFunction(pStr);
 
         if (bOK == false)
         {
             Scierror(50, _("%s: Subroutine not found: %s\n"), "fsolve", pst);
             FREE(pst);
+            Optimization::removeOptimizationFunctions();
             return types::Function::Error;
         }
 
@@ -111,6 +110,7 @@ types::Function::ReturnValue sci_fsolve(types::typed_list &in, int _iRetCount, t
         if (pList->getSize() == 0)
         {
             Scierror(50, _("%s: Argument #%d: Subroutine not found in list: %s\n"), "fsolve", 2, "(string empty)");
+            Optimization::removeOptimizationFunctions();
             return types::Function::Error;
         }
 
@@ -118,12 +118,13 @@ types::Function::ReturnValue sci_fsolve(types::typed_list &in, int _iRetCount, t
         {
             types::String* pStr = pList->get(0)->getAs<types::String>();
             char* pst = wide_string_to_UTF8(pStr->get(0));
-            bool bOK = opFunctionsManager->setFsolveFctFunction(pStr);
+            bool bOK = opFunctionsManager.setFsolveFctFunction(pStr);
 
             if (bOK == false)
             {
                 Scierror(50, _("%s: Subroutine not found: %s\n"), "fsolve", pst);
                 FREE(pst);
+                Optimization::removeOptimizationFunctions();
                 return types::Function::Error;
             }
 
@@ -132,21 +133,23 @@ types::Function::ReturnValue sci_fsolve(types::typed_list &in, int _iRetCount, t
         else if (pList->get(0)->isCallable())
         {
             types::Callable* pCall = pList->get(0)->getAs<types::Callable>();
-            opFunctionsManager->setFsolveFctFunction(pCall);
+            opFunctionsManager.setFsolveFctFunction(pCall);
             for (int iter = 1; iter < pList->getSize(); iter++)
             {
-                opFunctionsManager->setFsolveFctArgs(pList->get(iter)->getAs<types::InternalType>());
+                opFunctionsManager.setFsolveFctArgs(pList->get(iter)->getAs<types::InternalType>());
             }
         }
         else
         {
             Scierror(999, _("%s: Wrong type for input argument #%d: The first argument in the list must be a string or a function.\n"), "fsolve", 2);
+            Optimization::removeOptimizationFunctions();
             return types::Function::Error;
         }
     }
     else
     {
         Scierror(999, _("%s: Wrong type for input argument #%d: A matrix or a function expected.\n"), "fsolve", 2);
+        Optimization::removeOptimizationFunctions();
         return types::Function::Error;
     }
 
@@ -155,7 +158,7 @@ types::Function::ReturnValue sci_fsolve(types::typed_list &in, int _iRetCount, t
         if (in[2]->isCallable())
         {
             types::Callable* pCall = in[2]->getAs<types::Callable>();
-            opFunctionsManager->setFsolveJacFunction(pCall);
+            opFunctionsManager.setFsolveJacFunction(pCall);
 
             bJac = true;
         }
@@ -163,12 +166,13 @@ types::Function::ReturnValue sci_fsolve(types::typed_list &in, int _iRetCount, t
         {
             types::String* pStr = in[2]->getAs<types::String>();
             char* pst = wide_string_to_UTF8(pStr->get(0));
-            bool bOK = opFunctionsManager->setFsolveJacFunction(pStr);
+            bool bOK = opFunctionsManager.setFsolveJacFunction(pStr);
 
             if (bOK == false)
             {
                 Scierror(50, _("%s: Subroutine not found: %s\n"), "fsolve", pst);
                 FREE(pst);
+                Optimization::removeOptimizationFunctions();
                 return types::Function::Error;
             }
 
@@ -181,6 +185,7 @@ types::Function::ReturnValue sci_fsolve(types::typed_list &in, int _iRetCount, t
             if (pList->getSize() == 0)
             {
                 Scierror(50, _("%s: Argument #%d: Subroutine not found in list: %s\n"), "fsolve", 3, "(string empty)");
+                Optimization::removeOptimizationFunctions();
                 return types::Function::Error;
             }
 
@@ -188,12 +193,13 @@ types::Function::ReturnValue sci_fsolve(types::typed_list &in, int _iRetCount, t
             {
                 types::String* pStr = pList->get(0)->getAs<types::String>();
                 char* pst = wide_string_to_UTF8(pStr->get(0));
-                bool bOK = opFunctionsManager->setFsolveJacFunction(pStr);
+                bool bOK = opFunctionsManager.setFsolveJacFunction(pStr);
 
                 if (bOK == false)
                 {
                     Scierror(50, _("%s: Subroutine not found: %s\n"), "fsolve", pst);
                     FREE(pst);
+                    Optimization::removeOptimizationFunctions();
                     return types::Function::Error;
                 }
 
@@ -203,10 +209,10 @@ types::Function::ReturnValue sci_fsolve(types::typed_list &in, int _iRetCount, t
             else if (pList->get(0)->isCallable())
             {
                 types::Callable* pCall = pList->get(0)->getAs<types::Callable>();
-                opFunctionsManager->setFsolveJacFunction(pCall);
+                opFunctionsManager.setFsolveJacFunction(pCall);
                 for (int iter = 1; iter < pList->getSize(); iter++)
                 {
-                    opFunctionsManager->setFsolveJacArgs(pList->get(iter)->getAs<types::InternalType>());
+                    opFunctionsManager.setFsolveJacArgs(pList->get(iter)->getAs<types::InternalType>());
                 }
 
                 bJac = true;
@@ -214,6 +220,7 @@ types::Function::ReturnValue sci_fsolve(types::typed_list &in, int _iRetCount, t
             else
             {
                 Scierror(999, _("%s: Wrong type for input argument #%d: The first argument in the list must be a string or a function.\n"), "fsolve", 3);
+                Optimization::removeOptimizationFunctions();
                 return types::Function::Error;
             }
         }
@@ -227,6 +234,7 @@ types::Function::ReturnValue sci_fsolve(types::typed_list &in, int _iRetCount, t
             if (pDblTol->isScalar() == false)
             {
                 Scierror(999, _("%s: Wrong type for input argument #%d: A scalar expected.\n"), "fsolve", 4);
+                Optimization::removeOptimizationFunctions();
                 return types::Function::Error;
             }
 
@@ -235,6 +243,7 @@ types::Function::ReturnValue sci_fsolve(types::typed_list &in, int _iRetCount, t
         else
         {
             Scierror(999, _("%s: Wrong type for input argument #%d: A real expected.\n"), "fsolve", 4);
+            Optimization::removeOptimizationFunctions();
             return types::Function::Error;
         }
     }
@@ -282,9 +291,12 @@ types::Function::ReturnValue sci_fsolve(types::typed_list &in, int _iRetCount, t
             delete[] pdblJac;
         }
 
+        Optimization::removeOptimizationFunctions();
         return types::Function::Error;
     }
 
+    Optimization::removeOptimizationFunctions();
+
     delete[] pdblWork;
     if (pdblJac)
     {
@@ -318,4 +330,3 @@ types::Function::ReturnValue sci_fsolve(types::typed_list &in, int _iRetCount, t
 
     return types::Function::OK;
 }
-
index 356d01c..248149b 100644 (file)
@@ -33,8 +33,6 @@ extern "C"
 
 types::Function::ReturnValue sci_lsqrsolve(types::typed_list &in, int _iRetCount, types::typed_list &out)
 {
-    OptimizationFunctions* opFunctionsManager = NULL;
-
     types::Double* pDblX    = NULL;
     types::Double* pDblM    = NULL;
     types::Double* pDblV    = NULL;
@@ -92,26 +90,27 @@ types::Function::ReturnValue sci_lsqrsolve(types::typed_list &in, int _iRetCount
     iSizeX = pDblX->getSize();
 
     // get function
-    opFunctionsManager = new OptimizationFunctions(L"lsqrsolve");
-    Optimization::addOptimizationFunctions(opFunctionsManager);
-    opFunctionsManager->setXRows(pDblX->getRows());
-    opFunctionsManager->setXCols(pDblX->getCols());
+    OptimizationFunctions opFunctionsManager(L"lsqrsolve");
+    Optimization::addOptimizationFunctions(&opFunctionsManager);
+    opFunctionsManager.setXRows(pDblX->getRows());
+    opFunctionsManager.setXCols(pDblX->getCols());
 
     if (in[1]->isCallable())
     {
         types::Callable* pCall = in[1]->getAs<types::Callable>();
-        opFunctionsManager->setFsolveFctFunction(pCall);
+        opFunctionsManager.setFsolveFctFunction(pCall);
     }
     else if (in[1]->isString())
     {
         types::String* pStr = in[1]->getAs<types::String>();
         char* pst = wide_string_to_UTF8(pStr->get(0));
-        bool bOK = opFunctionsManager->setFsolveFctFunction(pStr);
+        bool bOK = opFunctionsManager.setFsolveFctFunction(pStr);
 
         if (bOK == false)
         {
             Scierror(50, _("%s: Subroutine not found: %s\n"), "lsqrsolve", pst);
             FREE(pst);
+            Optimization::removeOptimizationFunctions();
             return types::Function::Error;
         }
 
@@ -123,6 +122,7 @@ types::Function::ReturnValue sci_lsqrsolve(types::typed_list &in, int _iRetCount
         if (pList->getSize() == 0)
         {
             Scierror(50, _("%s: Argument #%d: Subroutine not found in list: %s\n"), "lsqrsolve", 2, "(string empty)");
+            Optimization::removeOptimizationFunctions();
             return types::Function::Error;
         }
 
@@ -130,12 +130,13 @@ types::Function::ReturnValue sci_lsqrsolve(types::typed_list &in, int _iRetCount
         {
             types::String* pStr = pList->get(0)->getAs<types::String>();
             char* pst = wide_string_to_UTF8(pStr->get(0));
-            bool bOK = opFunctionsManager->setFsolveFctFunction(pStr);
+            bool bOK = opFunctionsManager.setFsolveFctFunction(pStr);
 
             if (bOK == false)
             {
                 Scierror(50, _("%s: Subroutine not found: %s\n"), "lsqrsolve", pst);
                 FREE(pst);
+                Optimization::removeOptimizationFunctions();
                 return types::Function::Error;
             }
 
@@ -144,21 +145,23 @@ types::Function::ReturnValue sci_lsqrsolve(types::typed_list &in, int _iRetCount
         else if (pList->get(0)->isCallable())
         {
             types::Callable* pCall = pList->get(0)->getAs<types::Callable>();
-            opFunctionsManager->setFsolveFctFunction(pCall);
+            opFunctionsManager.setFsolveFctFunction(pCall);
             for (int iter = 1; iter < pList->getSize(); iter++)
             {
-                opFunctionsManager->setFsolveFctArgs(pList->get(iter)->getAs<types::InternalType>());
+                opFunctionsManager.setFsolveFctArgs(pList->get(iter)->getAs<types::InternalType>());
             }
         }
         else
         {
             Scierror(999, _("%s: Wrong type for input argument #%d: The first argument in the list must be a string or a function.\n"), "lsqrsolve", 2);
+            Optimization::removeOptimizationFunctions();
             return types::Function::Error;
         }
     }
     else
     {
         Scierror(999, _("%s: Wrong type for input argument #%d: A matrix or a function expected.\n"), "lsqrsolve", 2);
+        Optimization::removeOptimizationFunctions();
         return types::Function::Error;
     }
 
@@ -166,6 +169,7 @@ types::Function::ReturnValue sci_lsqrsolve(types::typed_list &in, int _iRetCount
     if (in[2]->isDouble() == false)
     {
         Scierror(999, _("%s: Wrong type for input argument #%d: A real Scalar expected.\n"), "lsqrsolve", 3);
+        Optimization::removeOptimizationFunctions();
         return types::Function::Error;
     }
 
@@ -174,6 +178,7 @@ types::Function::ReturnValue sci_lsqrsolve(types::typed_list &in, int _iRetCount
     if (pDblM->isComplex() || pDblM->isScalar() == false)
     {
         Scierror(999, _("%s: Wrong type for input argument #%d: A real Scalar expected.\n"), "lsqrsolve", 3);
+        Optimization::removeOptimizationFunctions();
         return types::Function::Error;
     }
 
@@ -182,6 +187,7 @@ types::Function::ReturnValue sci_lsqrsolve(types::typed_list &in, int _iRetCount
     if (iM < iSizeX)
     {
         Scierror(999, _("%s: Wrong value for input argument #%d: At most %d expected.\n"), "lsqrsolve", 3, iM);
+        Optimization::removeOptimizationFunctions();
         return types::Function::Error;
     }
 
@@ -193,7 +199,7 @@ types::Function::ReturnValue sci_lsqrsolve(types::typed_list &in, int _iRetCount
         if (in[iPos]->isCallable())
         {
             types::Callable* pCall = in[iPos]->getAs<types::Callable>();
-            opFunctionsManager->setFsolveJacFunction(pCall);
+            opFunctionsManager.setFsolveJacFunction(pCall);
 
             bJac = true;
             iPos++;
@@ -202,12 +208,13 @@ types::Function::ReturnValue sci_lsqrsolve(types::typed_list &in, int _iRetCount
         {
             types::String* pStr = in[iPos]->getAs<types::String>();
             char* pst = wide_string_to_UTF8(pStr->get(0));
-            bool bOK = opFunctionsManager->setFsolveJacFunction(pStr);
+            bool bOK = opFunctionsManager.setFsolveJacFunction(pStr);
 
             if (bOK == false)
             {
                 Scierror(50, _("%s: Subroutine not found: %s\n"), "lsqrsolve", pst);
                 FREE(pst);
+                Optimization::removeOptimizationFunctions();
                 return types::Function::Error;
             }
 
@@ -221,6 +228,7 @@ types::Function::ReturnValue sci_lsqrsolve(types::typed_list &in, int _iRetCount
             if (pList->getSize() == 0)
             {
                 Scierror(50, _("%s: Argument #%d: Subroutine not found in list: %s\n"), "lsqrsolve", 4, "(string empty)");
+                Optimization::removeOptimizationFunctions();
                 return types::Function::Error;
             }
 
@@ -228,12 +236,13 @@ types::Function::ReturnValue sci_lsqrsolve(types::typed_list &in, int _iRetCount
             {
                 types::String* pStr = pList->get(0)->getAs<types::String>();
                 char* pst = wide_string_to_UTF8(pStr->get(0));
-                bool bOK = opFunctionsManager->setFsolveJacFunction(pStr);
+                bool bOK = opFunctionsManager.setFsolveJacFunction(pStr);
 
                 if (bOK == false)
                 {
                     Scierror(50, _("%s: Subroutine not found: %s\n"), "lsqrsolve", pst);
                     FREE(pst);
+                    Optimization::removeOptimizationFunctions();
                     return types::Function::Error;
                 }
 
@@ -244,10 +253,10 @@ types::Function::ReturnValue sci_lsqrsolve(types::typed_list &in, int _iRetCount
             else if (pList->get(0)->isCallable())
             {
                 types::Callable* pCall = pList->get(0)->getAs<types::Callable>();
-                opFunctionsManager->setFsolveJacFunction(pCall);
+                opFunctionsManager.setFsolveJacFunction(pCall);
                 for (int iter = 1; iter < pList->getSize(); iter++)
                 {
-                    opFunctionsManager->setFsolveJacArgs(pList->get(iter)->getAs<types::InternalType>());
+                    opFunctionsManager.setFsolveJacArgs(pList->get(iter)->getAs<types::InternalType>());
                 }
 
                 bJac = true;
@@ -256,6 +265,7 @@ types::Function::ReturnValue sci_lsqrsolve(types::typed_list &in, int _iRetCount
             else
             {
                 Scierror(999, _("%s: Wrong type for input argument #%d: The first argument in the list must be a string or a function.\n"), "lsqrsolve", 4);
+                Optimization::removeOptimizationFunctions();
                 return types::Function::Error;
             }
         }
@@ -264,6 +274,7 @@ types::Function::ReturnValue sci_lsqrsolve(types::typed_list &in, int _iRetCount
     if (bJac == false && in.size() > 5)
     {
         Scierror(77, _("%s: Wrong number of input argument(s): %d to %d expected.\n"), "lsqrsolve", 3, 5);
+        Optimization::removeOptimizationFunctions();
         return types::Function::Error;
     }
 
@@ -276,6 +287,7 @@ types::Function::ReturnValue sci_lsqrsolve(types::typed_list &in, int _iRetCount
             if (pDblStop->getRows() != 1 || pDblStop->getCols() != 6)
             {
                 Scierror(999, _("%s: Wrong size for input argument #%d: A vector of size %d x %d expected.\n"), "lsqrsolve", iPos + 1, 1, 6);
+                Optimization::removeOptimizationFunctions();
                 return types::Function::Error;
             }
 
@@ -289,12 +301,14 @@ types::Function::ReturnValue sci_lsqrsolve(types::typed_list &in, int _iRetCount
             if (dFtol < 0 || dXtol < 0 || dGtol < 0 || iMaxfev <= 0 || dFactor <= 0)
             {
                 Scierror(999, _("%s: Wrong value for input argument #%d.\n"), "lsqrsolve", iPos + 1, 1, 6);
+                Optimization::removeOptimizationFunctions();
                 return types::Function::Error;
             }
         }
         else
         {
             Scierror(999, _("%s: Wrong type for input argument #%d: A vector expected.\n"), "lsqrsolve", iPos + 1);
+            Optimization::removeOptimizationFunctions();
             return types::Function::Error;
         }
 
@@ -309,6 +323,7 @@ types::Function::ReturnValue sci_lsqrsolve(types::typed_list &in, int _iRetCount
             if (pDblDiag->getSize() != iSizeX)
             {
                 Scierror(999, _("%s: Wrong size for input argument #%d: A vector of size %d expected.\n"), "lsqrsolve", iPos + 1, iSizeX);
+                Optimization::removeOptimizationFunctions();
                 return types::Function::Error;
             }
 
@@ -319,6 +334,7 @@ types::Function::ReturnValue sci_lsqrsolve(types::typed_list &in, int _iRetCount
                 if (pdblDiag[i] <= 0)
                 {
                     Scierror(999, _("%s: Wrong value for input argument #%d: A strictly positive vector expected.\n"), "lsqrsolve", iPos + 1);
+                    Optimization::removeOptimizationFunctions();
                     return types::Function::Error;
                 }
             }
@@ -328,6 +344,7 @@ types::Function::ReturnValue sci_lsqrsolve(types::typed_list &in, int _iRetCount
         else
         {
             Scierror(999, _("%s: Wrong type for input argument #%d: A vector expected.\n"), "lsqrsolve", iPos + 1);
+            Optimization::removeOptimizationFunctions();
             return types::Function::Error;
         }
     }
@@ -386,9 +403,12 @@ types::Function::ReturnValue sci_lsqrsolve(types::typed_list &in, int _iRetCount
             delete[] pdblDiag;
         }
 
+        Optimization::removeOptimizationFunctions();
         return types::Function::Error;
     }
 
+    Optimization::removeOptimizationFunctions();
+
     delete[] piPvt;
     delete[] pDblQtf;
     delete[] pdblWork1;
@@ -446,4 +466,3 @@ types::Function::ReturnValue sci_lsqrsolve(types::typed_list &in, int _iRetCount
 
     return types::Function::OK;
 }
-
index 5506512..8bbb01c 100644 (file)
@@ -13,6 +13,7 @@
  *
  */
 /*--------------------------------------------------------------------------*/
+#include <vector>
 #include "string.hxx"
 #include "double.hxx"
 #include "optimizationfunctions.hxx"
@@ -31,22 +32,22 @@ extern "C"
 ** \{
 */
 
-OptimizationFunctions* Optimization::m_OptimizationFunctions;
+std::vector<OptimizationFunctions*> Optimization::m_OptimizationFunctions;
 
 using namespace types;
 void Optimization::addOptimizationFunctions(OptimizationFunctions* _opFunction)
 {
-    m_OptimizationFunctions = _opFunction;
+    m_OptimizationFunctions.push_back(_opFunction);
 }
 
 void Optimization::removeOptimizationFunctions()
 {
-    m_OptimizationFunctions = NULL;
+    m_OptimizationFunctions.pop_back();
 }
 
 OptimizationFunctions* Optimization::getOptimizationFunctions()
 {
-    return m_OptimizationFunctions;
+    return m_OptimizationFunctions.back();
 }
 
 /*
@@ -473,6 +474,14 @@ void OptimizationFunctions::callCostfMacro(int *ind, int *n, double *x, double *
         throw ast::InternalError(errorMsg);
     }
 
+    if (pDblOut->getSize() != *n)
+    {
+        char* pstrName = wide_string_to_UTF8(m_pCallOptimCostfFunction->getName().c_str());
+        sprintf(errorMsg, _("%s: Wrong size for output argument #%d: %d element(s) expected.\n"), pstrName, 2, *n);
+        FREE(pstrName);
+        throw ast::InternalError(errorMsg);
+    }
+
     C2F(dcopy)(n, pDblOut->get(), &one, g, &one);
 
     out[1]->DecreaseRef();
@@ -884,4 +893,3 @@ void OptimizationFunctions::callLsqrsolveJacMacro(int *m, int *n, double *x, dou
         delete out[0];
     }
 }
-
diff --git a/scilab/modules/optimization/tests/nonreg_tests/bug_15117.tst b/scilab/modules/optimization/tests/nonreg_tests/bug_15117.tst
new file mode 100644 (file)
index 0000000..86ef079
--- /dev/null
@@ -0,0 +1,73 @@
+// =============================================================================
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) 2017 - ESI Group - Paul Bignier
+//
+//  This file is distributed under the same license as the Scilab package.
+// =============================================================================
+//
+// <-- NO CHECK REF -->
+// <-- CLI SHELL MODE -->
+//
+// <-- Non-regression test for bug 15117 -->
+//
+// <-- Bugzilla URL -->
+// http://bugzilla.scilab.org/show_bug.cgi?id=15117
+//
+// <-- Short Description -->
+// Imbricated optim/leastsq/lsqrsolve/fsolve calls either crashed or returned errors
+
+
+xmes = [-0.25  -0.5  -0.75  -1  -1.25  -1.5]';
+bb = [1:6]';
+
+// Exemple bidon fsolve
+function xres = fonc(a, b)
+    deff("y = fsol1(x)","y = a*x+b")
+    xres = fsolve(0, fsol1)
+endfunction
+
+// Pour appel leastsq
+function e = evalopti(X)
+    aa = X
+    xres = []
+    for i=1:6
+        xres = [xres; fonc(aa,bb(i))]
+    end
+    e = xmes-xres
+endfunction
+
+// Pour appel lsqrsolve
+function e = evaloptim(X, m)
+    e = evalopti(X)
+endfunction
+
+// Même problème réécrit pour appel datafit
+Y = xmes';
+X = bb';
+Z = [Y; X];
+// Pour appel datafit
+function e = G(p, z)
+    y = z(1, :)
+    x = z(2, :)
+    e = y-fonc(p, x)
+endfunction
+
+
+/////////// Lancement optimisation
+
+x0 = 100;
+
+// leastsq
+iprint = 2;
+[fopt, xopt] = leastsq(iprint, evalopti, x0);
+assert_checkequal([fopt xopt], [0 4]);
+
+// lsqrsolve
+[xsol, v] = lsqrsolve(x0, evaloptim, 6);
+assert_checkequal(xsol, 4);
+assert_checkequal(v, zeros(6, 1));
+
+// datafit
+p0 = x0;
+[p, err] = datafit(G, Z, p0);
+assert_checkalmostequal([p err], [4 0], [], 1e-9);