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