comparison libinterp/corefcn/pow2.cc @ 30719:a885bdb22374

maint: tweaks to cset a7c4fb821d64 (pow2). * pow2.cc: Add #include for "lo-array-errwarn.h" to get access to octave::err_nonconformant error function. Replace calls to error() with calls to octave::err_nonconformant() for mismatched input dimensions. Rename warning to "Octave:pow2:imaginary-ignored". Add BIST tests for input validation. * warning_ids.m: Add new ID "Octave:pow2:imaginary-only"
author Rik <rik@octave.org>
date Sun, 06 Feb 2022 15:47:43 -0800
parents 555676697eef
children e88a07dec498
comparison
equal deleted inserted replaced
30718:95ee9b9605cc 30719:a885bdb22374
26 #if defined (HAVE_CONFIG_H) 26 #if defined (HAVE_CONFIG_H)
27 # include "config.h" 27 # include "config.h"
28 #endif 28 #endif
29 29
30 #include <cmath> 30 #include <cmath>
31
32 #include "lo-array-errwarn.h"
31 33
32 #include "defun.h" 34 #include "defun.h"
33 #include "error.h" 35 #include "error.h"
34 #include "errwarn.h" 36 #include "errwarn.h"
35 37
44 if (f.numel () == e.numel () || e.numel () == 1) 46 if (f.numel () == e.numel () || e.numel () == 1)
45 y = Array<T> (f.dims ()); 47 y = Array<T> (f.dims ());
46 else if (f.numel () == 1) 48 else if (f.numel () == 1)
47 y = Array<T> (e.dims ()); 49 y = Array<T> (e.dims ());
48 else 50 else
49 error ("pow2: Input dimensions must agree."); 51 octave::err_nonconformant ("pow2", f.dims (), e.dims ());
50 52
51 octave_idx_type f_inc = (f.numel () == 1) ? 0 : 1; 53 octave_idx_type f_inc = (f.numel () == 1) ? 0 : 1;
52 octave_idx_type e_inc = (e.numel () == 1) ? 0 : 1; 54 octave_idx_type e_inc = (e.numel () == 1) ? 0 : 1;
53 55
54 for (octave_idx_type i = 0; i < y.numel (); i++) 56 for (octave_idx_type i = 0; i < y.numel (); i++)
77 int ee = static_cast<int> (e.xelem (f.ridx (i), col - 1)); 79 int ee = static_cast<int> (e.xelem (f.ridx (i), col - 1));
78 y.data (i) = std::ldexp (f.data (i), ee); 80 y.data (i) = std::ldexp (f.data (i), ee);
79 } 81 }
80 } 82 }
81 else 83 else
82 error ("pow2: Input dimensions must agree."); 84 octave::err_nonconformant ("pow2", f.dims (), e.dims ());
83 } 85 }
84 86
85 OCTAVE_NAMESPACE_BEGIN 87 OCTAVE_NAMESPACE_BEGIN
86 88
87 DEFUN (pow2, args, , 89 DEFUN (pow2, args, ,
164 166
165 if (! args(1).isfloat ()) 167 if (! args(1).isfloat ())
166 err_wrong_type_arg ("pow2", args(1)); 168 err_wrong_type_arg ("pow2", args(1));
167 169
168 if (args(0).iscomplex () || args(1).iscomplex ()) 170 if (args(0).iscomplex () || args(1).iscomplex ())
169 warning_with_id ("Octave:pow2:only-real", 171 warning_with_id ("Octave:pow2:imaginary-ignored",
170 "pow2: Imaginary part is ignored."); 172 "pow2: imaginary part is ignored");
171 173
172 // Note: Matlab R2021a errors on `pow2 (sparse (f), single (e))`, 174 // Note: Matlab R2021a errors on `pow2 (sparse (f), single (e))`,
173 // but sparsity in f determines output and can significantly 175 // but sparsity in f determines output and can significantly
174 // reduce computation, e.g. `N=1e5; pow2(speye(N),sparse(N,N))`. 176 // reduce computation, e.g. `N=1e5; pow2(speye(N),sparse(N,N))`.
175 if (args(0).issparse ()) 177 if (args(0).issparse ())
250 %!test 252 %!test
251 %! fcns = {@double, @single, @complex, @sparse}; 253 %! fcns = {@double, @single, @complex, @sparse};
252 %! f = [2 2]; 254 %! f = [2 2];
253 %! e = [2 2]; 255 %! e = [2 2];
254 %! z = [8 8]; 256 %! z = [8 8];
255 %! warning ("off", "Octave:pow2:only-real", "local"); 257 %! warning ("off", "Octave:pow2:imaginary-ignored", "local");
256 %! for i = 1:numel (fcns) 258 %! for i = 1:numel (fcns)
257 %! fcn = fcns{i}; 259 %! fcn = fcns{i};
258 %! assert (pow2 (fcn (f), fcn (e)), real (fcn (z))); 260 %! assert (pow2 (fcn (f), fcn (e)), real (fcn (z)));
259 %! endfor 261 %! endfor
260 262
268 ## Only real part is taken into account. 270 ## Only real part is taken into account.
269 %!test 271 %!test
270 %! f = [1+1i, 1]; 272 %! f = [1+1i, 1];
271 %! e = 2; 273 %! e = 2;
272 %! z = [4, 4]; 274 %! z = [4, 4];
273 %! warning ("off", "Octave:pow2:only-real", "local"); 275 %! warning ("off", "Octave:pow2:imaginary-ignored", "local");
274 %! assert (pow2 (f, e), z); 276 %! assert (pow2 (f, e), z);
275 277
276 %!test 278 %!test
277 %! f = 1; 279 %! f = 1;
278 %! e = [1+1i, 1]; 280 %! e = [1+1i, 1];
279 %! z = [2, 2]; 281 %! z = [2, 2];
280 %! warning ("off", "Octave:pow2:only-real", "local"); 282 %! warning ("off", "Octave:pow2:imaginary-ignored", "local");
281 %! assert (pow2 (f, e), z); 283 %! assert (pow2 (f, e), z);
282 284
283 %!test 285 %!test
284 %! f = [1/2, pi/4, -3/4, 1/2, 1-eps()/2, 1/2]; 286 %! f = [1/2, pi/4, -3/4, 1/2, 1-eps()/2, 1/2];
285 %! e = [1, 2, 2, -51, 1024, -1021]; 287 %! e = [1, 2, 2, -51, 1024, -1021];
309 %! N = 1e3; 311 %! N = 1e3;
310 %! assert (pow2 (speye (N), sparse (N,N)), speye (N)); 312 %! assert (pow2 (speye (N), sparse (N,N)), speye (N));
311 %! assert (pow2 (sparse (0), speye (N)), sparse(N,N)); 313 %! assert (pow2 (sparse (0), speye (N)), sparse(N,N));
312 314
313 %!error <Invalid call> pow2 () 315 %!error <Invalid call> pow2 ()
316 %!error <Invalid call> pow2 (1,2,3)
317 %!error <wrong type argument> pow2 (int8 (1))
318 %!error <wrong type argument> pow2 (2, int8 (1))
319 %!warning <imaginary part is ignored> pow2 (i, 2);
320 %!warning <imaginary part is ignored> pow2 (2, i);
321 %!error <pow2: nonconformant arguments> pow2 ([1,2], [3,4,5])
322 %!error <pow2: nonconformant arguments> pow2 (sparse ([1,2]), sparse ([3,4,5]))
314 */ 323 */
315 324
316 OCTAVE_NAMESPACE_END 325 OCTAVE_NAMESPACE_END