* Bug 15260 fixed: sci2exp broken for all cells structs and hypermats 12/19412/3
Samuel GOUGEON [Thu, 31 Aug 2017 23:32:22 +0000 (01:32 +0200)]
  http://bugzilla.scilab.org/15260

  This commit fixes the issue for cells, hypermats and simple structs.
  The bug http://bugzilla.scilab.org/15264 must be priorly fixed to fix
  the case of arrays of structures.
  We should not wait for it (there are more than 900 occurences of
  sci2exp() in Scilab .sci files, that are potentially impacted by this
  bug and that wait). A complementary fix will be commited later.

Change-Id: I902727617b022ed6dbb07d854d67bf37af8c1099

scilab/CHANGES.md
scilab/modules/string/macros/sci2exp.sci
scilab/modules/string/tests/nonreg_tests/bug_15260.tst [new file with mode: 0644]

index 25323c0..8d8de6c 100644 (file)
@@ -406,6 +406,7 @@ the [development mailing list](dev@lists.scilab.org) for a particular toolbox.
 * [#15205](http://bugzilla.scilab.org/show_bug.cgi?id=15205): `get_scicos_version` returned the previous version.
 * [#15207](http://bugzilla.scilab.org/show_bug.cgi?id=15207): `xcos(scs_m)` did not work for sub-systems.
 * [#15236](http://bugzilla.scilab.org/show_bug.cgi?id=15236): The `isglobal` help page was inaccurate. Examples were erroneous.
+* [#15260](http://bugzilla.scilab.org/show_bug.cgi?id=15260): `sci2exp` was broken for cells, structures, and all types of hypermatrix.
 * [#15266](http://bugzilla.scilab.org/show_bug.cgi?id=15266): Wrong default out_mode in `linear_interpn`.
 
 ### Bugs fixed in 6.0.0:
index ca83c57..77d50de 100644 (file)
@@ -1,8 +1,7 @@
 // Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
 // Copyright (C) INRIA -
-// Copyright (C) 2016 - Samuel GOUGEON
-//
 // Copyright (C) 2012 - 2016 - Scilab Enterprises
+// Copyright (C) 2016, 2017 - Samuel GOUGEON
 //
 // This file is hereby licensed under the terms of the GNU GPL v2.0,
 // pursuant to article 5.3.4 of the CeCILL v.2.1.
@@ -51,7 +50,14 @@ function t=sci2exp(a,nom,lmax)
             [lmax,nom]=(nom,lmax)
         end
     end
+    // For an hypermatrix, we concatenate all components in a single row:
+    hyperMat = or(type(a)==[1 2 4 8 10]) & ndims(a)>2;
+    if hyperMat
+        s = size(a);
+        a = matrix(a,1,-1);
+    end
     dots="..";
+
     select type(a)
     case 1 then
         t=mat2exp(a,lmax)
@@ -84,23 +90,49 @@ function t=sci2exp(a,nom,lmax)
         strfun(1)=str;
         strfun($)=[];
         t=strfun;
-        t(1)=part(t(1),10:length(t(1)))
-        t($)=[]
-        t=sci2exp(t,lmax)
-        t(1)="createfun("+t(1)
-        t($)=t($)+")"
+        t(1) = part(t(1),10:length(t(1)))
+        t($) = [];
+        t = sci2exp(t, lmax);
+        t(1) = "createfun(" + t(1);
+        t($) = t($) + ")";
     case 15 then
-        t=list2exp(a,lmax)
+        t = list2exp(a, lmax);
     case 16 then
-        t=tlist2exp(a,lmax)
-    case 17 then
-        t=mlist2exp(a,lmax)
+        t = tlist2exp(a, lmax);
+    case 17 then            // cells, struct, mlists
+        if typeof(a)=="st" & length(a)==1
+            t = scalarstruct2exp(a, lmax);
+        else
+            t = mlist2exp(a, lmax);
+        end
+    case 128 then
+        t = mlist2exp(user2mlist(a), lmax);
     case 129 then
-        t=imp2exp(a,lmax)
+        t = imp2exp(a, lmax);
     else
         //  execstr('t='+typeof(a)+'2exp(a,lmax)')
-        error(msprintf(gettext("%s: This feature has not been implemented: Variable translation of type %s.\n"),"sci2exp",string(type(a))));
-    end,
+        msg = _("%s: This feature has not been implemented: Variable translation of type %s.\n");
+        error(msprintf(msg, "sci2exp", string(type(a))));
+    end
+    // Post-processing:
+    if hyperMat then
+        s = strcat(msprintf("%d\n",s(:)), ",");  // Literal list of sizes
+        if lmax>0
+            if length(t(1)) > (lmax-8)
+                t = ["matrix(.."; t];
+            else
+                t(1) = "matrix("+t(1);
+            end
+            if length(t($)) > (lmax-length(s)-5)
+                t($) = t($)+",..";
+                t = [t ; "["+s+"])"];
+            else
+                t($) = t($)+", ["+s+"])";
+            end
+        else
+            t = "matrix(" + t + ", ["+s+"])";
+        end
+    end
     if named&and(type(a)<>13) then
         t(1)=nom+" = "+t(1)
     end
@@ -334,12 +366,40 @@ function t=pol2exp(a,lmax)
     end
 endfunction
 
-function t = glist2exp(listType, l,lmax)
+function t = glist2exp(listType, l, lmax)
     [lhs,rhs] = argn(0)
     if rhs<3 then lmax = 0, end
     dots = "."+".";
-    t = listType+"("
-    for k = 1:length(l)
+    isCell = typeof(l)=="ce";
+    if isCell then
+        s = size(l);
+        s = strcat(msprintf("%d\n",s(:)),",");  // Literal list of sizes
+        t = "makecell(";
+        if lmax>0 & (length(t) > (lmax-length(s)-4))
+            t = [t + dots; "["+s+"],.. "];
+        else
+            t = t + "["+s+"], ";
+        end
+        // ND-transposition needed due to makecell() special indexing:
+        if ndims(l)<3
+            l = l'
+        else
+            i = 1:ndims(l);
+            i([1 2]) = [2 1];
+            l = permute(l, i);
+        end
+        //
+        l = l{:};
+        L = length(l);
+    else
+        t = listType + "("
+        if listType=="list" then
+            L = length(l)
+        else
+             L = size(getfield(1,l),"*");
+        end
+    end
+    for k = 1:L
         sep = ",", if k==1 then sep = "", end
         clear lk
         if listType ~= "mlist"
@@ -348,21 +408,9 @@ function t = glist2exp(listType, l,lmax)
             lk = getfield(k,l)
         end
         if ~isdef("lk","local")
-            t1=""
+            t1 = ""
         else
-            if type(lk)==9 then
-                t1 = h2exp(lk,lmax)
-            elseif type(lk)==15 then
-                t1 = list2exp(lk,lmax)
-            elseif type(lk)==16 then
-                t1 = tlist2exp(lk,lmax)
-            elseif type(lk)==17 then
-                t1 = mlist2exp(lk,lmax)
-            elseif type(lk)==128 then
-                t1 = mlist2exp(user2mlist(lk),lmax)
-            else
-                t1 = sci2exp(lk,lmax)
-            end
+            t1 = sci2exp(lk, lmax)
         end
         if size(t1,"*")==1&(lmax==0|max(length(t1))+length(t($))<lmax) then
             t($) = t($)+sep+t1
@@ -384,6 +432,41 @@ function t = mlist2exp(l, lmax)
     t = glist2exp("mlist", l, lmax)
 endfunction
 
+function t = scalarstruct2exp(l, lmax)
+    if argn(2)<2 then lmax = 0, end
+    dots = "."+".";
+    t = "struct(";
+    fields = fieldnames(l);
+    n = size(fields,"*");
+    for i = 1:n
+        if ~lmax | lmax>(12+length(fields(i)))
+            t($) = t($) + """"+fields(i)+""",";
+        else
+            t($) = t($) + " " + dots;
+            t = [t; """"+fields(i)+""","];
+        end
+        clear lk
+        lk = l(fields(i));
+        if ~isdef("lk","local")
+            t1 = "";
+        else
+            t1 = sci2exp(lk, lmax)
+        end
+        if i<n then
+            tmp = ", ";
+        else
+            tmp = "";
+        end
+        if size(t1,"*")==1&(lmax==0|max(length(t1))+length(t($))<lmax) then
+            t($) = t($) + t1 + tmp;
+        else
+            t($) = t($) + " ..";
+            t = [t; t1 + tmp]
+        end
+    end
+    t($) = t($)+")"
+endfunction
+
 function t=log2exp(a,lmax)
     $;
     if rhs<2 then lmax = 0, end
@@ -501,7 +584,6 @@ function t=h2exp(a,lmax) //Only for figure and uicontrol
     end
     [lhs,rhs]=argn(0);
 
-
     f1="''parent'', ";
     f2="''children'', ";
     f3="''BackgroundColor'', ";
@@ -764,18 +846,17 @@ function t=h2exp(a,lmax) //Only for figure and uicontrol
             t(1:$-1)=t(1:$-1)+dots;
         end
     else
-        error(msprintf(gettext("%s: This feature has not been implemented: Variable translation of type %s.\n"),"sci2exp",string(a.type)));
+        msg = _("%s: This feature has not been implemented: Variable translation of type %s.\n")
+        error(msprintf(msg,"sci2exp",string(a.type)));
     end
 
 endfunction
 
 function ml = user2mlist(u)
-
     fn = getfield(1, u);
     ml = mlist(fn);
 
-    for k=1:size(fn,"*")
-        ml(k) = eval("u."+fn(k));
+    for k = 1:size(fn,"*")
+        ml(k) = u(fn(k));
     end
-
 endfunction
diff --git a/scilab/modules/string/tests/nonreg_tests/bug_15260.tst b/scilab/modules/string/tests/nonreg_tests/bug_15260.tst
new file mode 100644 (file)
index 0000000..8501538
--- /dev/null
@@ -0,0 +1,81 @@
+// =============================================================================
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) 2017 - Samuel GOUGEON
+//
+//  This file is distributed under the same license as the Scilab package.
+// =============================================================================
+//
+// <-- CLI SHELL MODE -->
+// <-- NO CHECK REF -->
+// <-- Non-regression test for bug 15260 -->
+//
+// <-- Bugzilla URL -->
+// http://bugzilla.scilab.org/15260
+//
+// <-- Short Description -->
+// sci2exp() was broken for all types of hypermatrix, simple structure or
+//  arrays of structures, and simple cell or arrays of cells.
+
+// Hypermatrix of booleans
+b = rand(4,5,3,2)<0.5;
+tb = sci2exp(b);
+assert_checkequal(evstr(tb), b);
+
+// Hypermatrix of encoded integers
+i = int8(rand(4,5,3,2)*100);
+ti = sci2exp(i);
+assert_checkequal(evstr(ti), i);
+
+// Hypermatrix of complex numbers
+c = rand(4,5,3,2) + rand(4,5,3,2)*%i;
+tc = sci2exp(c);
+assert_checkalmostequal(evstr(tc), c, 1e-7, 1e-7);
+
+// Hypermatrix of complex polynomials
+p = (rand(4,5,3) + rand(4,5,3)*%i - %z).^fix(rand(4,5,3)*4);
+tp = sci2exp(p);
+z = %z;
+rp = evstr(tp);
+r = clean(rp-p, 1e-7);
+assert_checkequal(sum(abs(r)),0*%z);
+
+// Hypermatrix of strings
+s = string(rand(4,5,3,2)*100);
+ts = sci2exp(s);
+assert_checkequal(evstr(ts), s);
+
+// Array of cells
+c = {1,%t,"A",%z,%i,0,list(2,"B"),"B",%f,3.1415,"abc",list(%i,"cat")};
+c = matrix(c, [2 3 1 2]);
+tc = sci2exp(c);
+z = %z;
+rc = evstr(tc);
+assert_checkequal(rc,c);
+
+// Scalar structure:
+s = struct("r",1.234-5.6*%i,"b",%f,"t","Hello","i",int8([123 -76]),"l",list(4,,%i));
+ss = sci2exp(s);
+ssref = "struct(""r"",1.234-%i*5.6, ""b"",%f, ""t"",""Hello"", ""i"",int8([123,-76]), ""l"",list(4,,%i))";
+assert_checkequal(ss, ssref);
+assert_checkequal(evstr(ss), s);
+
+// Array of structures
+// =======================================================================
+// There is no longer any way to generate nand initialize from scratch any
+//  non-scalar array of structures.
+// =======================================================================
+// This part shall be rewritten when struct(dims,field1,listOfValues1, ..)
+// will have been implemented (= bug http://bugzilla.scilab.org/15264 fixed)
+clear s
+s.r = 1.2345;
+s(1,2).r = %i;
+s(2,2).r = 1-%i;
+s(2,1).r = 2.345;
+s.t = "A";
+s(1,2).t = "C";
+s(2,2).t = "D";
+s(2,1).t = "B";
+tmpref = mlist(["st","dims","r","t"],int32([2,2]),list(1.2345,2.345,%i,1-%i),list("A","B","C","D"));
+ssref = "mlist([""st"",""dims"",""r"",""t""],int32([2,2]),list(1.2345,2.345,%i,1-%i),list(""A"",""B"",""C"",""D""))";
+assert_checkequal(sci2exp(s), ssref);
+assert_checkequal(evstr(sci2exp(s)), tmpref);