[elementary_functions] linspace() c++ gateway gives tremendous speedup 85/20685/4
St├ęphane MOTTELET [Fri, 19 Oct 2018 21:48:38 +0000 (23:48 +0200)]
40x speedup for typical sizes:

Scilab 6.0.1:
--> tic;for i=1:100000;linspace(0,2*%pi,1000);end;toc()
 ans  =
   20.667936

Scilab master:
--> tic;for i=1:100000;linspace(0,2*%pi,1000);end;toc()
 ans  =
   0.476891

and linear interpolation between arrays of any dimensions, e.g.

--> linspace(rand(2,2),rand(2,2),5)
 ans  =

(:,:,1)

   0.8782165   0.5608486
   0.068374    0.6623569
(:,:,2)

   0.84025     0.5567008
   0.1009091   0.5547864
(:,:,3)

   0.8022836   0.552553
   0.1334442   0.4472159
(:,:,4)

   0.7643171   0.5484051
   0.1659793   0.3396453
(:,:,5)

   0.7263507   0.5442573
   0.1985144   0.2320748

Change-Id: I81362a2d858f1a465f4becc6ae8a29aea4dbda28

scilab/modules/elementary_functions/Makefile.am
scilab/modules/elementary_functions/Makefile.in
scilab/modules/elementary_functions/help/en_US/elementarymatrices/linspace.xml
scilab/modules/elementary_functions/includes/elem_func_gw.hxx
scilab/modules/elementary_functions/macros/%i_linspace.sci [moved from scilab/modules/elementary_functions/macros/linspace.sci with 72% similarity]
scilab/modules/elementary_functions/sci_gateway/cpp/elem_func_gw.cpp
scilab/modules/elementary_functions/sci_gateway/cpp/elem_func_gw/elem_func_gw.vcxproj
scilab/modules/elementary_functions/sci_gateway/cpp/sci_linspace.cpp [new file with mode: 0644]

index 69b4067..e429925 100644 (file)
@@ -336,10 +336,11 @@ GATEWAY_CXX_SOURCES =  \
     sci_gateway/cpp/sci_sign.cpp \
     sci_gateway/cpp/sci_sqrt.cpp \
     sci_gateway/cpp/sci_issquare.cpp \
-    sci_gateway/cpp/sci_isvector.cpp\
-    sci_gateway/cpp/sci_nearfloat.cpp\
-    sci_gateway/cpp/sci_permute.cpp\
-    sci_gateway/cpp/sci_bitstring.cpp
+    sci_gateway/cpp/sci_isvector.cpp \
+    sci_gateway/cpp/sci_nearfloat.cpp \
+    sci_gateway/cpp/sci_permute.cpp \
+    sci_gateway/cpp/sci_bitstring.cpp \
+    sci_gateway/cpp/sci_linspace.cpp
 
 EISPACK_SOURCES = src/fortran/eispack/balbak.f
 
index 9879ef8..021c9af 100644 (file)
@@ -413,7 +413,8 @@ am__objects_8 =  \
        sci_gateway/cpp/libscielementary_functions_la-sci_isvector.lo \
        sci_gateway/cpp/libscielementary_functions_la-sci_nearfloat.lo \
        sci_gateway/cpp/libscielementary_functions_la-sci_permute.lo \
-       sci_gateway/cpp/libscielementary_functions_la-sci_bitstring.lo
+       sci_gateway/cpp/libscielementary_functions_la-sci_bitstring.lo \
+       sci_gateway/cpp/libscielementary_functions_la-sci_linspace.lo
 am_libscielementary_functions_la_OBJECTS = $(am__objects_7) \
        $(am__objects_8)
 libscielementary_functions_la_OBJECTS =  \
@@ -474,6 +475,7 @@ am__depfiles_remade = sci_gateway/c/$(DEPDIR)/libscielementary_functions_la-sci_
        sci_gateway/cpp/$(DEPDIR)/libscielementary_functions_la-sci_issquare.Plo \
        sci_gateway/cpp/$(DEPDIR)/libscielementary_functions_la-sci_isvector.Plo \
        sci_gateway/cpp/$(DEPDIR)/libscielementary_functions_la-sci_kron.Plo \
+       sci_gateway/cpp/$(DEPDIR)/libscielementary_functions_la-sci_linspace.Plo \
        sci_gateway/cpp/$(DEPDIR)/libscielementary_functions_la-sci_log.Plo \
        sci_gateway/cpp/$(DEPDIR)/libscielementary_functions_la-sci_log1p.Plo \
        sci_gateway/cpp/$(DEPDIR)/libscielementary_functions_la-sci_matrix.Plo \
@@ -1264,10 +1266,11 @@ GATEWAY_CXX_SOURCES = \
     sci_gateway/cpp/sci_sign.cpp \
     sci_gateway/cpp/sci_sqrt.cpp \
     sci_gateway/cpp/sci_issquare.cpp \
-    sci_gateway/cpp/sci_isvector.cpp\
-    sci_gateway/cpp/sci_nearfloat.cpp\
-    sci_gateway/cpp/sci_permute.cpp\
-    sci_gateway/cpp/sci_bitstring.cpp
+    sci_gateway/cpp/sci_isvector.cpp \
+    sci_gateway/cpp/sci_nearfloat.cpp \
+    sci_gateway/cpp/sci_permute.cpp \
+    sci_gateway/cpp/sci_bitstring.cpp \
+    sci_gateway/cpp/sci_linspace.cpp
 
 EISPACK_SOURCES = src/fortran/eispack/balbak.f
 
@@ -2259,6 +2262,9 @@ sci_gateway/cpp/libscielementary_functions_la-sci_permute.lo:  \
 sci_gateway/cpp/libscielementary_functions_la-sci_bitstring.lo:  \
        sci_gateway/cpp/$(am__dirstamp) \
        sci_gateway/cpp/$(DEPDIR)/$(am__dirstamp)
+sci_gateway/cpp/libscielementary_functions_la-sci_linspace.lo:  \
+       sci_gateway/cpp/$(am__dirstamp) \
+       sci_gateway/cpp/$(DEPDIR)/$(am__dirstamp)
 
 libscielementary_functions.la: $(libscielementary_functions_la_OBJECTS) $(libscielementary_functions_la_DEPENDENCIES) $(EXTRA_libscielementary_functions_la_DEPENDENCIES) 
        $(AM_V_CXXLD)$(CXXLINK) $(am_libscielementary_functions_la_rpath) $(libscielementary_functions_la_OBJECTS) $(libscielementary_functions_la_LIBADD) $(LIBS)
@@ -2323,6 +2329,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@sci_gateway/cpp/$(DEPDIR)/libscielementary_functions_la-sci_issquare.Plo@am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@sci_gateway/cpp/$(DEPDIR)/libscielementary_functions_la-sci_isvector.Plo@am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@sci_gateway/cpp/$(DEPDIR)/libscielementary_functions_la-sci_kron.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@sci_gateway/cpp/$(DEPDIR)/libscielementary_functions_la-sci_linspace.Plo@am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@sci_gateway/cpp/$(DEPDIR)/libscielementary_functions_la-sci_log.Plo@am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@sci_gateway/cpp/$(DEPDIR)/libscielementary_functions_la-sci_log1p.Plo@am__quote@ # am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@sci_gateway/cpp/$(DEPDIR)/libscielementary_functions_la-sci_matrix.Plo@am__quote@ # am--include-marker
@@ -3252,6 +3259,13 @@ sci_gateway/cpp/libscielementary_functions_la-sci_bitstring.lo: sci_gateway/cpp/
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libscielementary_functions_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o sci_gateway/cpp/libscielementary_functions_la-sci_bitstring.lo `test -f 'sci_gateway/cpp/sci_bitstring.cpp' || echo '$(srcdir)/'`sci_gateway/cpp/sci_bitstring.cpp
 
+sci_gateway/cpp/libscielementary_functions_la-sci_linspace.lo: sci_gateway/cpp/sci_linspace.cpp
+@am__fastdepCXX_TRUE@  $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libscielementary_functions_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT sci_gateway/cpp/libscielementary_functions_la-sci_linspace.lo -MD -MP -MF sci_gateway/cpp/$(DEPDIR)/libscielementary_functions_la-sci_linspace.Tpo -c -o sci_gateway/cpp/libscielementary_functions_la-sci_linspace.lo `test -f 'sci_gateway/cpp/sci_linspace.cpp' || echo '$(srcdir)/'`sci_gateway/cpp/sci_linspace.cpp
+@am__fastdepCXX_TRUE@  $(AM_V_at)$(am__mv) sci_gateway/cpp/$(DEPDIR)/libscielementary_functions_la-sci_linspace.Tpo sci_gateway/cpp/$(DEPDIR)/libscielementary_functions_la-sci_linspace.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     $(AM_V_CXX)source='sci_gateway/cpp/sci_linspace.cpp' object='sci_gateway/cpp/libscielementary_functions_la-sci_linspace.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libscielementary_functions_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o sci_gateway/cpp/libscielementary_functions_la-sci_linspace.lo `test -f 'sci_gateway/cpp/sci_linspace.cpp' || echo '$(srcdir)/'`sci_gateway/cpp/sci_linspace.cpp
+
 .f.o:
        $(AM_V_F77)$(F77COMPILE) -c -o $@ $<
 
@@ -3500,6 +3514,7 @@ distclean: distclean-am
        -rm -f sci_gateway/cpp/$(DEPDIR)/libscielementary_functions_la-sci_issquare.Plo
        -rm -f sci_gateway/cpp/$(DEPDIR)/libscielementary_functions_la-sci_isvector.Plo
        -rm -f sci_gateway/cpp/$(DEPDIR)/libscielementary_functions_la-sci_kron.Plo
+       -rm -f sci_gateway/cpp/$(DEPDIR)/libscielementary_functions_la-sci_linspace.Plo
        -rm -f sci_gateway/cpp/$(DEPDIR)/libscielementary_functions_la-sci_log.Plo
        -rm -f sci_gateway/cpp/$(DEPDIR)/libscielementary_functions_la-sci_log1p.Plo
        -rm -f sci_gateway/cpp/$(DEPDIR)/libscielementary_functions_la-sci_matrix.Plo
@@ -3661,6 +3676,7 @@ maintainer-clean: maintainer-clean-am
        -rm -f sci_gateway/cpp/$(DEPDIR)/libscielementary_functions_la-sci_issquare.Plo
        -rm -f sci_gateway/cpp/$(DEPDIR)/libscielementary_functions_la-sci_isvector.Plo
        -rm -f sci_gateway/cpp/$(DEPDIR)/libscielementary_functions_la-sci_kron.Plo
+       -rm -f sci_gateway/cpp/$(DEPDIR)/libscielementary_functions_la-sci_linspace.Plo
        -rm -f sci_gateway/cpp/$(DEPDIR)/libscielementary_functions_la-sci_log.Plo
        -rm -f sci_gateway/cpp/$(DEPDIR)/libscielementary_functions_la-sci_log1p.Plo
        -rm -f sci_gateway/cpp/$(DEPDIR)/libscielementary_functions_la-sci_matrix.Plo
index f493808..97d7c62 100644 (file)
@@ -172,6 +172,21 @@ x(:,1:$-1) - x(:,2:$)
  -13 -14 -13 -14 -13 -14 -13 -14 -14
   13  14  13  14  13  14  13  14  14
 ]]></screen>
+        <programlisting role="example"><![CDATA[
+// shape interpolation between a sphere and a cone
+[T,P]=meshgrid(linspace(0,2*%pi,32),linspace(-%pi/2,%pi/2,32));
+X=cos(T).*cos(P);
+Y=sin(T).*cos(P);
+
+Z=linspace(sin(P),cos(P)-1,100);
+
+h=uicontrol("style","slider","units","normalized",...
+"position",[0.2 0.03 0.6 0.05],"min",1,"max",100,...
+"callback",...
+"drawlater;delete(gca().children);mesh(X,Y,Z(:,:,h.value));isoview;drawnow")
+
+execstr(h.callback)
+ ]]></programlisting>
     </refsection>
     <refsection role="see also">
         <title>See also</title>
index 1df9b49..97880a8 100644 (file)
@@ -68,6 +68,7 @@ CPP_GATEWAY_PROTOTYPE(sci_int);
 CPP_GATEWAY_PROTOTYPE(sci_isequal);
 CPP_GATEWAY_PROTOTYPE(sci_isreal);
 CPP_GATEWAY_PROTOTYPE(sci_kron);
+CPP_GATEWAY_PROTOTYPE(sci_linspace);
 CPP_GATEWAY_PROTOTYPE(sci_log);
 CPP_GATEWAY_PROTOTYPE(sci_log1p);
 CPP_GATEWAY_PROTOTYPE(sci_matrix);
@@ -12,7 +12,7 @@
 // For more information, see the COPYING file which you should have received
 // along with this program.
 
-function y = linspace(d1, d2, n)
+function y = %i_linspace(d1, d2, n)
     // Linearly spaced vector.
     // linspace(x1, x2) generates a row vector of 100 linearly
     // equally spaced points between x1 and x2.
@@ -88,39 +88,39 @@ function y = linspace(d1, d2, n)
 endfunction
 // -----------------
 function y = linspace_integers_64(d1,d2,n)
-        s = d2>=d1
-        span = zeros(d1)
-        if typeof(d1)=="int64"  then
-            span = uint64(span)
-        end
-        span(s) = d2(s) - d1(s)
-        span(~s) = d1(~s) - d2(~s)
-        step = span/(n-1)
-        y = iconvert(zeros(size(d1,1),n), inttype(d1))
-        if or(s)  // d2 > d1
-            y(s,:) = d1(s)*ones(1,n) + step(s)*(0:n-1)
-        end
-        if or(~s)
-            y(~s,:) = d1(~s)*ones(1,n) - step(~s)*(0:n-1)
-        end
-        y(:,$) = d2
-        // Computing the balancing corrections
-            // We computes actual intervals
-        if typeof(d1)=="uint64" then
-            i = int64(zeros(size(d1,1),n-1))
-            i(s, :) = y(s, 2:$)    -  y(s, 1:$-1)
-            i(~s,:) = y(~s, 1:$-1) -  y(~s, 2:$)
-        else // int64
-            i = diff(y,1,2);
-        end
-            // diff wrt the 1st interval's width
-        e = i - i(:,1) * ones(1,n-1)
+    s = d2>=d1
+    span = zeros(d1)
+    if typeof(d1)=="int64"  then
+        span = uint64(span)
+    end
+    span(s) = d2(s) - d1(s)
+    span(~s) = d1(~s) - d2(~s)
+    step = span/(n-1)
+    y = iconvert(zeros(size(d1,1),n), inttype(d1))
+    if or(s)  // d2 > d1
+        y(s,:) = d1(s)*ones(1,n) + step(s)*(0:n-1)
+    end
+    if or(~s)
+        y(~s,:) = d1(~s)*ones(1,n) - step(~s)*(0:n-1)
+    end
+    y(:,$) = d2
+    // Computing the balancing corrections
+    // We computes actual intervals
+    if typeof(d1)=="uint64" then
+        i = int64(zeros(size(d1,1),n-1))
+        i(s, :) = y(s, 2:$)    -  y(s, 1:$-1)
+        i(~s,:) = y(~s, 1:$-1) -  y(~s, 2:$)
+    else // int64
+        i = diff(y,1,2);
+    end
+    // diff wrt the 1st interval's width
+    e = i - i(:,1) * ones(1,n-1)
 
-            // Computing corrections
-        S = mean(double(e), 'c') * ones(1,n-1)
-        cumE = cumsum(e, 'c')
-        cumS = cumsum(S, 'c')
-        delta = cumS - cumE
-        // Applying the corrections
-        y(:,2:$) = y(:,2:$) + delta
+    // Computing corrections
+    S = mean(double(e), "c") * ones(1,n-1)
+    cumE = cumsum(e, "c")
+    cumS = cumsum(S, "c")
+    delta = cumS - cumE
+    // Applying the corrections
+    y(:,2:$) = y(:,2:$) + delta
 endfunction
index d5ab0e3..878ef95 100644 (file)
@@ -61,6 +61,7 @@ int ElemFuncModule::Load()
     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"isreal", &sci_isreal, MODULE_NAME));
     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"isequal", &sci_isequal, MODULE_NAME));
     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"kron", &sci_kron, MODULE_NAME));
+    symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"linspace", &sci_linspace, MODULE_NAME));
     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"log", &sci_log, MODULE_NAME));
     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"log1p", &sci_log1p, MODULE_NAME));
     symbol::Context::getInstance()->addFunction(types::Function::createFunction(L"matrix", &sci_matrix, MODULE_NAME));
index 1a8b8b2..adddfa1 100644 (file)
@@ -241,6 +241,7 @@ lib /DEF:"$(ProjectDir)elementary_functions_Import.def" /SUBSYSTEM:WINDOWS /MACH
     <ClCompile Include="..\sci_isequal.cpp" />
     <ClCompile Include="..\sci_isreal.cpp" />
     <ClCompile Include="..\sci_kron.cpp" />
+    <ClCompile Include="..\sci_linspace.cpp" />
     <ClCompile Include="..\sci_log.cpp" />
     <ClCompile Include="..\sci_log1p.cpp" />
     <ClCompile Include="..\sci_matrix.cpp" />
@@ -331,4 +332,4 @@ lib /DEF:"$(ProjectDir)elementary_functions_Import.def" /SUBSYSTEM:WINDOWS /MACH
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
   </ImportGroup>
-</Project>
\ No newline at end of file
+</Project>
diff --git a/scilab/modules/elementary_functions/sci_gateway/cpp/sci_linspace.cpp b/scilab/modules/elementary_functions/sci_gateway/cpp/sci_linspace.cpp
new file mode 100644 (file)
index 0000000..5b104c4
--- /dev/null
@@ -0,0 +1,198 @@
+/*
+ *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+ *  Copyright (C) 2018- St├ęphane MOTTELET
+ *
+ * This file is hereby licensed under the terms of the GNU GPL v2.0,
+ * For more information, see the COPYING file which you should have received
+ * along with this program.
+ *
+ */
+
+#include "double.hxx"
+#include "function.hxx"
+#include "int.hxx"
+#include "overload.hxx"
+
+extern "C"
+{
+#include "Scierror.h"
+#include "localization.h"
+}
+
+bool fillRange(double* pdblOut, double* pdblMin, double* pdblMax, int iRows, int iCols);
+
+/* ==================================================================== */
+types::Function::ReturnValue sci_linspace(types::typed_list &in, int _iRetCount, types::typed_list &out)
+{
+    int iCols = 100;
+    types::Double* pDblOut;
+
+    if (in.size() != 2 & in.size() != 3)
+    {
+        Scierror(77, _("%s: Wrong number of input argument(s): %d to %d expected.\n"), "linspace", 2,3);
+        return types::Function::Error;
+    }
+
+    if (_iRetCount > 1)
+    {
+        Scierror(78, _("%s: Wrong number of output argument(s): %d expected."), "linspace", 1);
+        return types::Function::Error;
+    }
+
+    types::Double* pDbl[2];
+    for (int i=0; i<2; i++)
+    {
+        if (in[i]->isDouble())
+        {
+            pDbl[i] = in[i]->getAs<types::Double>();
+        }
+        else
+        {
+            // other types -> overload
+            std::wstring wstFuncName = L"%" + in[i]->getShortTypeStr() + L"_linspace";
+            return Overload::call(wstFuncName, in, _iRetCount, out);
+        }
+    }
+
+    // Check dimensions are the same
+    int  iDims0  = pDbl[0]->getDims();
+    int* piDims0 = pDbl[0]->getDimsArray();
+    int  iDims1  = pDbl[1]->getDims();
+    int* piDims1 = pDbl[1]->getDimsArray();
+    if (iDims0 != iDims1)
+    {
+        Scierror(999, _("%s: Arguments %d and %d must have same dimensions.\n"), "linspace",1,2);
+        return types::Function::Error;
+    }
+    for (int i = 0; i < iDims0; i++)
+    {
+        if (piDims0[i] != piDims1[i])
+        {
+            Scierror(999, _("%s: Arguments %d and %d must have same dimensions.\n"), "linspace",1,2);
+            return types::Function::Error;
+        }
+    }
+
+    if (in.size() == 3)
+    {
+        if (in[2]->isDouble() && in[2]->getAs<types::Double>()->isComplex() == false
+            && in[2]->getAs<types::Double>()->getSize() == 1)
+        {
+            double dblCols = in[2]->getAs<types::Double>()->get(0);
+            if (std::floor(dblCols) != dblCols)
+            {
+                Scierror(999, _("%s: Argument #%d: An integer value expected.\n"), "linspace",3);
+                return types::Function::Error;
+            }
+            if (dblCols <= 0)
+            {
+                // empty matrix case
+                out.push_back(types::Double::Empty());
+                return types::Function::OK;
+            }
+            iCols = (int) dblCols;
+        }
+        else
+        {
+            Scierror(999, _("%s: Argument #%d: An integer value expected.\n"), "linspace",3);
+            return types::Function::Error;
+        }
+    }
+
+    // yet another empty matrix case
+    if (pDbl[0]->getSize() == 0)
+    {
+        out.push_back(types::Double::Empty());
+        return types::Function::OK;
+    }
+
+    // generation is done by considering array as a column vector
+    int iRows =  pDbl[0]->getSize();
+    // pDblOut is resized later
+    pDblOut = new types::Double(iRows,iCols);
+
+    if (!fillRange(pDblOut->get(), pDbl[0]->get(), pDbl[1]->get(), iRows, iCols))
+    {
+        // if Infs or NaNs
+        pDblOut->killMe();
+        return types::Function::Error;
+    }
+
+    if (pDbl[0]->isComplex() || pDbl[1]->isComplex())
+    {
+        int iReal;
+        for (iReal = 0; iReal < 2; iReal++) {
+            if (!pDbl[iReal]->isComplex())
+            {
+                pDbl[iReal] = pDbl[iReal]->clone();
+                pDbl[iReal]->setComplex(true);
+                break;
+            }
+        }
+        // Complexify pDblOut
+        pDblOut->setComplex(true);
+        bool status = fillRange(pDblOut->getImg(), pDbl[0]->getImg(), pDbl[1]->getImg(), iRows, iCols);
+        if (iReal < 2)
+        {
+              pDbl[iReal]->killMe();
+        }
+        if (status != true) // if Infs or NaNs
+        {
+            pDblOut->killMe();
+            return types::Function::Error;
+        }
+    }
+
+    int *piNewDims = new int[iDims0+1];
+    // keep the first dimension unchanged
+    piNewDims[0] = piDims0[0];
+    int iDim = 1;
+    for (int i=1; i<iDims0; i++)
+    {
+        // squeeze subsequent single dimensions
+        if (piDims0[i]>1)
+        {
+            piNewDims[iDim++] = piDims0[i];
+        }
+    }
+    // add the suplementary dimension
+    piNewDims[iDim++] = iCols;
+    // reshape the matrix:
+    pDblOut->reshape(piNewDims, iDim);
+    out.push_back(pDblOut);
+
+    return types::Function::OK;
+}
+
+bool fillRange(double* pdblOut, double* pdblMin, double* pdblMax, int iRows, int iCols)
+{
+    double* step = new double[iRows];
+    for (int j = 0, k = (iCols-1)*iRows; j < iRows; j++)
+    {
+        step[j] = (pdblMax[j]-pdblMin[j])/(iCols-1);
+        // checking Infs and NaNs
+        int indInfOrNan = std::isinf(pdblMin[j]) || std::isnan(pdblMin[j]) ? 1 : 0;
+        indInfOrNan = indInfOrNan == 0 ? (std::isinf(pdblMax[j]) || std::isnan(pdblMax[j]) ? 2 : 0) : indInfOrNan;
+        if (indInfOrNan > 0)
+        {
+            delete[] step;
+            Scierror(999, _("%s: Argument #%d: %%nan and %%inf values are forbidden.\n"), "linspace",indInfOrNan);
+            return false;
+        }
+        // last column is enforced (http://bugzilla.scilab.org/10966)
+        pdblOut[k++] = pdblMax[j];
+    }
+    // doing the linear range generation
+    for (int i = 0; i<iCols-1; i++)
+    {
+        for (int j = 0; j < iRows; j++)
+        {
+              *(pdblOut++) = pdblMin[j]+i*step[j];
+        }
+    }
+    delete[] step;
+
+    return true;
+}
+
+