* Bug 15028 fixed: assert_checkalmostequal() did not accept polynomials
[scilab.git] / scilab / modules / development_tools / macros / assert / assert_checkalmostequal.sci
1 // Copyright (C) 2008 - 2009 - INRIA - Michael Baudin
2 // Copyright (C) 2009 - 2011 - DIGITEO - Michael Baudin
3 // Copyright (C) 2012 - Michael Baudin
4 // Copyright (C) 2017 - Samuel GOUGEON
5 //
6 // Copyright (C) 2012 - 2016 - Scilab Enterprises
7 //
8 // This file is hereby licensed under the terms of the GNU GPL v2.0,
9 // pursuant to article 5.3.4 of the CeCILL v.2.1.
10 // This file was originally licensed under the terms of the CeCILL v2.1,
11 // and continues to be available under such terms.
12 // For more information, see the COPYING file which you should have received
13 // along with this program.
14
15 function [flag,errmsg] = assert_checkalmostequal ( varargin )
16
17     function [kpinf , kninf , knan , kreg , xreg] = infnanindices ( x )
18         // Returns the indices where
19         //  * kpinf : x(kpinf) == +%inf,
20         //  * kninf : x(kninf) == -%inf,
21         //  * knan : x(knan) is a %nan
22         //  * kreg : x(kreg) is not an infinity, not a nan
23         //  * xreg = x(kreg)
24         // These 4 sets of indices have no intersection.
25         //
26         // Example :
27         // x = [1 2 3 -%inf %inf %nan %inf %nan -%inf 4 5 6]
28         // [kpinf , kninf , knan , kreg , xreg] = infnanindices ( x )
29         // xreg = [1 2 3 4 5 6]
30         // kreg = [1 2 3 10 11 12]
31         // knan = [6 8]
32         // kninf = [4 9]
33         // kpinf = [5 7]
34
35         kpinf = find(x==%inf)
36         kninf = find(x==-%inf)
37         knan = find(isnan(x))
38         kreg = find(abs(x)<>%inf & ~isnan(x))
39         xreg = x(kreg)
40     endfunction
41
42     function areequal = assert_arealmostequal ( computed , expected , reltol , abstol , comptype )
43         //
44         // Decompose the expected value into nan indices, inf indices and regular indices
45         // This allows to solve the following issue:
46         // if computed is %inf and expected is %inf, the difference is %nan,
47         // which makes the computations fail.
48         if ( computed == [] & expected == []) then
49             areequal = %t
50             return
51         end
52         [kcpinf , kcninf , kcnan , kcreg , creg] = infnanindices ( computed )
53         [kepinf , keninf , kenan , kereg , ereg] = infnanindices ( expected )
54         //
55         if ( comptype == "matrix" ) then
56             areclose = ( norm ( creg - ereg ) <= reltol * max(norm(ereg),norm(creg) ) + abstol )
57         else
58             if (creg==[]&ereg==[]) then
59                 areclose=%t
60             elseif (creg<>[]&ereg==[]) then
61                 areclose=%f
62             elseif (creg==[]&ereg<>[]) then
63                 areclose=%f
64             else
65                 entries = ( abs(creg-ereg) <= reltol * max(abs(ereg),abs(creg)) + abstol )
66                 // Compute the global condition from the entries conditions
67                 areclose = and(entries)
68             end
69         end
70         // The regular values must be almost equal and
71         // * the +%inf must be at the same place,
72         // * the -%inf must be at the same place,
73         // * the %nan must be at the same place.
74
75         areequal = ( areclose & and(kcpinf == kepinf) & and(kcninf == keninf) & and(kcnan == kenan) )
76     endfunction
77
78     function argin = assert_argindefault ( rhs , vararglist , ivar , default )
79         // Returns the value of the input argument #ivar.
80         // If this argument was not provided, or was equal to the
81         // empty matrix, returns the default value.
82         if ( rhs < ivar ) then
83             argin = default
84         else
85             if ( vararglist(ivar) <> [] ) then
86                 argin = vararglist(ivar)
87             else
88                 argin = default
89             end
90         end
91     endfunction
92     // ============================================================================================
93
94     //  Check that computed and expected are numerically close.
95
96     [lhs,rhs]=argn()
97     if ( and(rhs <> [2 3 4 5] ) ) then
98         errmsg = gettext("%s: Wrong number of input arguments: %d to %d expected.")
99         error(msprintf(errmsg, "assert_checkalmostequal" , 2 , 5 ))
100     end
101     //
102     // Get arguments
103     computed = varargin(1)
104     expected = varargin(2)
105     reltol = assert_argindefault ( rhs , varargin , 3 , sqrt(%eps) )
106     abstol = assert_argindefault ( rhs , varargin , 4 , 0 )
107     comptype = assert_argindefault ( rhs , varargin , 5 , "element" )
108     //
109     // Check types of variables
110     if ( and(typeof(computed) <> ["constant" "sparse" "polynomial"]) ) then
111         errmsg = gettext("%s: Wrong type for input argument #%d: Matrix expected.\n")
112         error(msprintf(errmsg, "assert_checkalmostequal", 1))
113     end
114     if ( and(typeof(expected) <> ["constant" "sparse" "polynomial"]) ) then
115         errmsg = gettext("%s: Wrong type for input argument #%d: Matrix expected.\n")
116         error(msprintf (errmsg, "assert_checkalmostequal" , 2 ))
117     end
118     if typeof(computed)=="polynomial" & typeof(expected)~="polynomial" then
119         errmsg = gettext("%s: Wrong type for input argument #%d: Polynomial expected.\n")
120         error(msprintf (errmsg, "assert_checkalmostequal" , 2 ))
121     end
122     if ( typeof(reltol) <> "constant" ) then
123         errmsg = gettext("%s: Wrong type for input argument #%d: Matrix expected.\n")
124         error(sprintf(errmsg, "assert_checkalmostequal", 3 ))
125     end
126     if ( typeof(abstol) <> "constant" ) then
127         errmsg = gettext("%s: Wrong type for input argument #%d: Matrix expected.\n")
128         error(sprintf(errmsg, "assert_checkalmostequal", 4 ))
129     end
130     if ( typeof(comptype) <> "string" ) then
131         errmsg = gettext("%s: Wrong type for input argument #%d: Matrix of strings expected.\n")
132         error(sprintf(errmsg, "assert_checkalmostequal", 5))
133     end
134     //
135     // Check sizes of variables
136     if ( size(reltol,"*") <> 1 ) then
137         errmsg = gettext("%s: Wrong size for input argument #%d: %d-by-%d matrix expected.\n")
138         error(msprintf(errmsg, "assert_checkalmostequal", 3, 1, 1))
139     end
140     if ( size(abstol,"*") <> 1 ) then
141         errmsg = gettext("%s: Wrong size for input argument #%d: %d-by-%d matrix expected.\n")
142         error(msprintf(errmsg, "assert_checkalmostequal", 4, 1, 1))
143     end
144     if ( size(comptype,"*") <> 1 ) then
145         errmsg = gettext("%s: Wrong size for input argument #%d: %d-by-%d matrix expected.\n")
146         error(msprintf(errmsg, "assert_checkalmostequal", 5, 1, 1))
147     end
148     //
149     // Check values of variables
150     if ( reltol < 0 ) then
151         errmsg = gettext("%s: Wrong value for input argument #%d: Must be > %d.\n")
152         error(msprintf(errmsg, "assert_checkalmostequal", 3, 0))
153     end
154     if ( abstol < 0 ) then
155         errmsg = gettext("%s: Wrong value for input argument #%d: Must be > %d.\n")
156         error(msprintf(errmsg, "assert_checkalmostequal", 4, 0))
157     end
158     if ( and ( comptype <> ["matrix" "element"] ) ) then
159         errmsg = gettext("%s: Wrong value for input argument #%d: Must be in the set  {%s}.\n")
160         error(msprintf(errmsg, "assert_checkalmostequal", 5, """matrix"",""element"""))
161     end
162     //
163     // Proceed...
164     ncom = size(computed)
165     nexp = size(expected)
166     if ( or(ncom <> nexp) ) then
167         errmsg = gettext("%s: Incompatible input arguments #%d and #%d: Same sizes expected.\n")
168         error(msprintf(errmsg, "assert_checkalmostequal", 1, 2))
169     end
170     if typeof(computed)=="polynomial" then
171         if or(degree(computed) <> degree(expected) ) then
172             errmsg = gettext("%s: Arguments #%d and #%d: Same degrees expected.\n")
173             error(msprintf(errmsg, "assert_checkalmostequal", 1, 2))
174         end
175         computed0 = computed;
176         expected0 = expected;
177         computed = coeff(computed(:));
178         expected = coeff(expected(:));
179     end
180     //
181     areequal_re = assert_arealmostequal ( real(computed) , real(expected) , reltol , abstol , comptype )
182     if ( areequal_re ) then
183         areequal = assert_arealmostequal ( imag(computed) , imag(expected) , reltol , abstol , comptype )
184     else
185         areequal = %f
186     end
187     //
188     if ( areequal ) then
189         flag = %t
190         errmsg = ""
191     else
192         flag = %f
193         if isdef("computed0","l") then
194             computed = computed0;
195             expected = expected0;
196         end
197         // Change the message if the matrix contains more than one value
198         if ( size(expected,"*") == 1 ) then
199             estr = string(expected)
200         else
201             estr = "[" + string(expected(1)) + " ...]"
202         end
203         if ( size(computed,"*") == 1 ) then
204             cstr = string(computed)
205         else
206             cstr = "[" + string(computed(1)) + " ...]"
207         end
208         relstr = string(reltol)
209         absstr = string(abstol)
210         errmsg = gettext("%s: Assertion failed: expected = %s while computed = %s")
211         errmsg = msprintf(errmsg, "assert_checkalmostequal", estr, cstr)
212         if ( lhs < 2 ) then
213             // If no output variable is given, generate an error
214             assert_generror ( errmsg )
215         end
216     end
217 endfunction