[sparse] now sparse([]) is sparse
[scilab.git] / scilab / modules / elementary_functions / macros / resize_matrix.sci
1 // Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
2 // Copyright (C) 2013, 2016, 2017 - Samuel GOUGEON
3 //
4 // Copyright (C) 2012 - 2016 - Scilab Enterprises
5 //
6 // This file is hereby licensed under the terms of the GNU GPL v2.0,
7 // pursuant to article 5.3.4 of the CeCILL v.2.1.
8 // This file was originally licensed under the terms of the CeCILL v2.1,
9 // and continues to be available under such terms.
10 // For more information, see the COPYING file which you should have received
11 // along with this program.
12
13
14 function mat = resize_matrix(mat, varargin)
15
16     // Syntax:
17     //     resize_matrix(M, nRows, nCols )
18     //     resize_matrix(M, [nRows nCols] )
19     //     resize_matrix(M, newSizes )
20     //     resize_matrix(M, .. , resType )
21     //     resize_matrix(M, .. , resType, padding )
22     //     resize_matrix(M, .. ,   ""   , padding )
23
24     [lhs, rhs] = argn(0)
25
26     // EXAMPLES
27     // --------
28     if rhs == 0 then
29         M = grand(4, 3, "uin", -9, 9)
30         disp(_("RESIZING a matrix of DECIMALS:"))
31         disp("M = ")
32         disp(M)
33         com = [ "resize_matrix(M, 3, 4)"
34         "resize_matrix(M, [3 4 2])"
35         "resize_matrix(M, [3 4 2], """", %i)"
36         "resize_matrix(M, [3 4 2], ""string"", %i)"
37         ]
38         for c = com'
39             disp(c)
40             execstr("disp("+c+")")
41         end
42
43         halt(ascii(10)+_("Type <Enter> to see an example with polynomials:"))
44         x = poly(0, "x")
45         P = (1-x)^grand(4, 2, "uin", 0, 3)
46         disp("P = ")
47         disp(P)
48         com = [ "resize_matrix(P, 3, 3)"
49         "resize_matrix(P, [3 3 2])"
50         "resize_matrix(P, [3 3 2],"""", %z)"
51         ]
52         for c = com'
53             disp(c)
54             execstr("disp("+c+")")
55         end
56         disp(_("The unknown variable of added values is forced to the P''s one"))
57         disp(_("Polynomials can''t be converted"))
58
59         halt(ascii(10)+_("Type <Enter> to see an example with character strings:"))
60         T = string(grand(4, 3, 2, "unf", 0, 1)*100)
61         disp("T = ")
62         disp(T)
63         com = [ "resize_matrix(T, 2, 5)"
64         "resize_matrix(T, [2 5], ""constant"")"
65         "resize_matrix(T, [2 5], """", ""abc"")"
66         "resize_matrix(T, [2 5], ""int16"", ""-1e4"")"
67         ]
68         for c = com'
69             disp(c)
70             execstr("disp("+c+")")
71         end
72         warning(msprintf(_("Hypermatrices of character strings can''t be converted.\n")))
73
74         mat = []
75         return
76     end
77
78     // INITIALIZATIONS
79     // ---------------
80     // if needed, default padding will be defined later:
81     padding = []
82     // Default type of the result:
83     resType = typeof(mat)
84
85     // ARGUMENTS ANALYSIS & CHECKING
86     // -----------------------------
87     if rhs==1 | rhs > 5 then
88         msg = _("%s: Wrong number of input argument(s): %d to %d expected.\n")
89         error(msprintf(msg, "resize_matrix", 2, 5))
90     end
91
92     if ~(or(type(mat)~=[15 16 17]) ..
93         & or(type(mat(:))==[1 2 4 5 6 8 10]))
94         msg = _("%s: Wrong type of input argument #%d: ""%s"" not supported.\n")
95         error(msprintf(msg, "resize_matrix", 1, typeof(mat(:))))
96     end
97
98     arg = varargin(1)
99     nextvarg = 2
100     if ~isscalar(arg) then
101         newsizes = arg
102     else
103         if rhs>2 then
104             varg2 = varargin(2)
105             if type(varg2)~=1 | ~isscalar(varg2) then
106                 msg = _("%s: Wrong input argument #%d: An integer value expected.\n")
107                 error(msprintf(msg, "resize_matrix", 2))
108             end
109             nextvarg = 3
110         else
111             varg2 = 1
112         end
113         newsizes = [ arg varg2 ]
114     end
115
116     if or(type(mat) == [15 16]) & size(size(newsizes), "*") <> 1  then
117         msg = _("%s: Wrong sizes requested, cannot convert list to matrix.\n")
118         error(msprintf(msg, "resize_matrix"))
119     end
120
121
122     if  size(varargin)>=nextvarg then
123         // Type of output
124         resType = varargin(nextvarg)
125         if typeof(resType)~="string"
126             resType = typeof(mat(:))
127         elseif resType=="" then
128             resType = typeof(mat(:))
129             nextvarg = nextvarg + 1
130         else
131             nextvarg = nextvarg + 1
132         end
133         // Padding pattern
134         if size(varargin)>=nextvarg then
135             padding = varargin(nextvarg)
136             err = %f
137             tpad = type(padding)
138             if tpad~=type(mat(:)) then  // TRYING to CONVERT the given PADDING
139                 if or(type(mat(:))==[1 5 8]) then    // numbers
140                     if or(tpad==[4 6])      // boolean
141                         padding = bool2s(tpad)
142                     elseif tpad==10         // string
143                         padding = strtod(padding)
144                         err = isnan(padding)
145                     elseif or(tpad==[2 9]) | tpad>10
146                         err = %t
147                     end
148                 elseif type(mat(:))==2  // polynomials
149                     if or(tpad==[1 5 8]) then   // decimals or encoded integers
150                         padding = double(padding)
151                     elseif or(tpad==[4 6])      // booleans
152                         padding = bool2s(padding)
153                     else
154                         err = %t
155                     end
156                 elseif or(type(mat(:))==[4 6])  // booleans
157                     if or(tpad==[1 5 8]) then       // numbers
158                         padding = (padding~=0)
159                     elseif tpad==10
160                         padding = (padding~="")     // string
161                     else
162                         err = %t
163                     end
164                 else
165                     err = %t
166                 end
167                 if err then
168                     msg = _("%s: Wrong type for input argument #%d: cannot convert the padding value to the input matrix type.\n")
169                     error(msprintf(msg, "resize_matrix", nextvarg+1))
170                 end
171             else
172                 padding = varargin(nextvarg)
173                 if type(padding)==2 then
174                     // the padding's unknown is forced to the mat's one
175                     padding = varn(padding, varn(mat(1)))
176                 end
177             end
178         end
179     end
180
181     // FORMATTING SIZES VECTORS
182     // ------------------------
183     // if the vector of new sizes is shorter than ndims(mat), it is padded with ones
184     oldsizes = size(mat)
185     newsizes = int(real(newsizes(:)'))
186     newsizes = [ newsizes  ones(1, length(oldsizes)-length(newsizes)) ]
187     oldsizes = [ oldsizes  ones(1, length(newsizes)-length(oldsizes)) ]
188     imax = length(newsizes)
189
190     // TRIMMING
191     // --------
192     if or(newsizes==0) then
193         mat(:) = []
194         return
195     end
196     k = (newsizes>0 & newsizes<oldsizes)
197     if or(k) then
198         strcommand = ""
199         for i=1:imax
200             if k(i) then
201                 strcommand = strcommand + msprintf("1:%d",newsizes(i))
202             else
203                 strcommand = strcommand + ":"
204             end
205             if i<imax then
206                 strcommand = strcommand + ","
207             end
208         end
209         execstr("mat = mat("+strcommand+")")
210     end
211
212     // PADDING
213     // -------
214     k = (newsizes>0 & newsizes>oldsizes)
215     if or(k) then
216         if padding==[] then
217             // Padding with default: needs just to set the upper bounds
218             // setting defaults
219             if or(type(mat(:))==[1 2 5 8]) // decimals, polynomials, decimal sparse, encoded integers
220                 padding = "0"
221             elseif or(type(mat(:))==[4 6]) // booleans, boolean sparse
222                 padding = "%f"
223             elseif type(mat(:))==10        // text
224                 padding = """"""
225             end
226             // padding:
227             strcommand = ""
228             for i=1:imax
229                 if k(i) then
230                     strcommand = strcommand + msprintf("%d",newsizes(i))
231                 else
232                     strcommand = strcommand + "1"
233                 end
234                 if i<imax then
235                     strcommand = strcommand + ","
236                 end
237             end
238             execstr("mat("+strcommand+")="+padding)
239         else    // Explicit padding
240             Pad = padding
241             padding = "Pad"
242             for i=1:imax
243                 if k(i) then
244                     s = zeros(1,imax)
245                     s(i) = i
246                     s = strcat(string(s),",")
247                     s = strsubst(s,"0",":")
248                     padRange = string(oldsizes(i)+1)+":"+string(newsizes(i))
249                     s = strsubst(s, string(i), padRange)
250                     execstr("mat("+s+") = "+padding)
251                 end
252             end
253         end
254     end
255
256     // CASTING : converting the type of the result
257     // -------
258     type_0 = typeof(mat(:))
259     if resType~=type_0
260         if type_0=="polynomial"
261             msg = _("%s: conversion of polynomials is not supported\n")
262             error(msprintf(msg, "resize_matrix"))
263         elseif resType=="string"
264             mat = string(mat)
265         elseif or(resType==["int8" "int16" "int32" "int64" "uint8" "uint16" "uint32" "uint64"])
266             if type_0=="string"
267                 mat = strtod(mat)       // strings => decimals
268             end
269             // encoded integers, reals, complexes, booleans  => #int#
270             if type(mat(:))==1 & ~isreal(mat)
271                 mat = abs(mat)  // taking the module of complexes
272             end
273             execstr("mat = "+resType+"(mat)")
274         elseif resType=="constant"
275             if type_0=="string" then
276                 mat = strtod(mat)
277             else // encoded integers, booleans => decimals
278                 mat = double(mat)
279             end
280         elseif resType=="boolean"
281             if type_0=="string" then
282                 mat = (mat~="")
283             else
284                 mat = (mat~=0)
285             end
286         else
287             msg = _("%s: conversion into ""%s"" is not supported\n")
288             error(msprintf(msg, "resize_matrix", resType))
289         end
290     end
291 endfunction