GNU Octave  4.4.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
mx-inlines.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1993-2018 John W. Eaton
4 Copyright (C) 2009 Jaroslav Hajek
5 Copyright (C) 2009 VZLU Prague
6 
7 This file is part of Octave.
8 
9 Octave is free software: you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13 
14 Octave is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with Octave; see the file COPYING. If not, see
21 <https://www.gnu.org/licenses/>.
22 
23 */
24 
25 #if ! defined (octave_mx_inlines_h)
26 #define octave_mx_inlines_h 1
27 
28 // This file should *not* include config.h. It is only included in other C++
29 // source files that should have included config.h before including this file.
30 
31 #include <cstddef>
32 #include <cmath>
33 
34 #include <algorithm>
35 
36 #include "Array-util.h"
37 #include "Array.h"
38 #include "bsxfun.h"
39 #include "oct-cmplx.h"
40 #include "oct-inttypes.h"
41 #include "oct-locbuf.h"
42 
43 // Provides some commonly repeated, basic loop templates.
44 
45 template <typename R, typename S>
46 inline void mx_inline_fill (size_t n, R *r, S s)
47 {
48  for (size_t i = 0; i < n; i++)
49  r[i] = s;
50 }
51 
52 template <typename R, typename X>
53 inline void
54 mx_inline_uminus (size_t n, R *r, const X *x)
55 {
56  for (size_t i = 0; i < n; i++)
57  r[i] = -x[i];
58 }
59 
60 template <typename R>
61 inline void
62 mx_inline_uminus2 (size_t n, R *r)
63 {
64  for (size_t i = 0; i < n; i++)
65  r[i] = -r[i];
66 }
67 
68 template <typename X>
69 inline void
70 mx_inline_iszero (size_t n, bool *r, const X *x)
71 {
72  const X zero = X ();
73  for (size_t i = 0; i < n; i++)
74  r[i] = x[i] == zero;
75 }
76 
77 template <typename X>
78 inline void
79 mx_inline_notzero (size_t n, bool *r, const X *x)
80 {
81  const X zero = X ();
82  for (size_t i = 0; i < n; i++)
83  r[i] = x[i] != zero;
84 }
85 
86 #define DEFMXBINOP(F, OP) \
87  template <typename R, typename X, typename Y> \
88  inline void F (size_t n, R *r, const X *x, const Y *y) \
89  { \
90  for (size_t i = 0; i < n; i++) \
91  r[i] = x[i] OP y[i]; \
92  } \
93  template <typename R, typename X, typename Y> \
94  inline void F (size_t n, R *r, const X *x, Y y) \
95  { \
96  for (size_t i = 0; i < n; i++) \
97  r[i] = x[i] OP y; \
98  } \
99  template <typename R, typename X, typename Y> \
100  inline void F (size_t n, R *r, X x, const Y *y) \
101  { \
102  for (size_t i = 0; i < n; i++) \
103  r[i] = x OP y[i]; \
104  }
105 
110 
111 #define DEFMXBINOPEQ(F, OP) \
112  template <typename R, typename X> \
113  inline void F (size_t n, R *r, const X *x) \
114  { \
115  for (size_t i = 0; i < n; i++) \
116  r[i] OP x[i]; \
117  } \
118  template <typename R, typename X> \
119  inline void F (size_t n, R *r, X x) \
120  { \
121  for (size_t i = 0; i < n; i++) \
122  r[i] OP x; \
123  }
124 
129 
130 #define DEFMXCMPOP(F, OP) \
131  template <typename X, typename Y> \
132  inline void F (size_t n, bool *r, const X *x, const Y *y) \
133  { \
134  for (size_t i = 0; i < n; i++) \
135  r[i] = x[i] OP y[i]; \
136  } \
137  template <typename X, typename Y> \
138  inline void F (size_t n, bool *r, const X *x, Y y) \
139  { \
140  for (size_t i = 0; i < n; i++) \
141  r[i] = x[i] OP y; \
142  } \
143  template <typename X, typename Y> \
144  inline void F (size_t n, bool *r, X x, const Y *y) \
145  { \
146  for (size_t i = 0; i < n; i++) \
147  r[i] = x OP y[i]; \
148  }
149 
156 
157 // Convert to logical value, for logical op purposes.
158 template <typename T>
159 inline bool
161 {
162  return x;
163 }
164 
165 template <typename T>
166 inline bool
167 logical_value (const std::complex<T>& x)
168 {
169  return x.real () != 0 || x.imag () != 0;
170 }
171 
172 template <typename T>
173 inline bool
175 {
176  return x.value ();
177 }
178 
179 template <typename X>
180 void mx_inline_not (size_t n, bool *r, const X *x)
181 {
182  for (size_t i = 0; i < n; i++)
183  r[i] = ! logical_value (x[i]);
184 }
185 
186 inline void mx_inline_not2 (size_t n, bool *r)
187 {
188  for (size_t i = 0; i < n; i++)
189  r[i] = ! r[i];
190 }
191 
192 #define DEFMXBOOLOP(F, NOT1, OP, NOT2) \
193  template <typename X, typename Y> \
194  inline void F (size_t n, bool *r, const X *x, const Y *y) \
195  { \
196  for (size_t i = 0; i < n; i++) \
197  r[i] = ((NOT1 logical_value (x[i])) \
198  OP (NOT2 logical_value (y[i]))); \
199  } \
200  template <typename X, typename Y> \
201  inline void F (size_t n, bool *r, const X *x, Y y) \
202  { \
203  const bool yy = (NOT2 logical_value (y)); \
204  for (size_t i = 0; i < n; i++) \
205  r[i] = (NOT1 logical_value (x[i])) OP yy; \
206  } \
207  template <typename X, typename Y> \
208  inline void F (size_t n, bool *r, X x, const Y *y) \
209  { \
210  const bool xx = (NOT1 logical_value (x)); \
211  for (size_t i = 0; i < n; i++) \
212  r[i] = xx OP (NOT2 logical_value (y[i])); \
213  }
214 
221 
222 template <typename X>
223 inline void
224 mx_inline_and2 (size_t n, bool *r, const X *x)
225 {
226  for (size_t i = 0; i < n; i++)
227  r[i] &= logical_value (x[i]);
228 }
229 
230 template <typename X>
231 inline void
232 mx_inline_and2 (size_t n, bool *r, X x)
233 {
234  for (size_t i = 0; i < n; i++)
235  r[i] &= x;
236 }
237 
238 template <typename X>
239 inline void
240 mx_inline_or2 (size_t n, bool *r, const X *x)
241 {
242  for (size_t i = 0; i < n; i++)
243  r[i] |= logical_value (x[i]);
244 }
245 
246 template <typename X>
247 inline void
248 mx_inline_or2 (size_t n, bool *r, X x)
249 {
250  for (size_t i = 0; i < n; i++)
251  r[i] |= x;
252 }
253 
254 template <typename T>
255 inline bool
256 mx_inline_any_nan (size_t n, const T *x)
257 {
258  for (size_t i = 0; i < n; i++)
259  {
260  if (octave::math::isnan (x[i]))
261  return true;
262  }
263 
264  return false;
265 }
266 
267 template <typename T>
268 inline bool
269 mx_inline_all_finite (size_t n, const T *x)
270 {
271  for (size_t i = 0; i < n; i++)
272  {
273  if (! octave::math::isfinite (x[i]))
274  return false;
275  }
276 
277  return true;
278 }
279 
280 template <typename T>
281 inline bool
282 mx_inline_any_negative (size_t n, const T *x)
283 {
284  for (size_t i = 0; i < n; i++)
285  {
286  if (x[i] < 0)
287  return true;
288  }
289 
290  return false;
291 }
292 
293 template <typename T>
294 inline bool
295 mx_inline_any_positive (size_t n, const T *x)
296 {
297  for (size_t i = 0; i < n; i++)
298  {
299  if (x[i] > 0)
300  return true;
301  }
302 
303  return false;
304 }
305 
306 template <typename T>
307 inline bool
308 mx_inline_all_real (size_t n, const std::complex<T>* x)
309 {
310  for (size_t i = 0; i < n; i++)
311  {
312  if (x[i].imag () != 0)
313  return false;
314  }
315 
316  return true;
317 }
318 
319 template <typename T>
320 inline void mx_inline_real (size_t n, T *r, const std::complex<T>* x)
321 {
322  for (size_t i = 0; i < n; i++)
323  r[i] = x[i].real ();
324 }
325 
326 template <typename T>
327 inline void mx_inline_imag (size_t n, T *r, const std::complex<T>* x)
328 {
329  for (size_t i = 0; i < n; i++)
330  r[i] = x[i].imag ();
331 }
332 
333 template <typename T>
334 inline void
335 mx_inline_xmin (size_t n, T *r, const T *x, const T *y)
336 {
337  for (size_t i = 0; i < n; i++)
338  r[i] = octave::math::min (x[i], y[i]);
339 }
340 
341 template <typename T>
342 inline void
343 mx_inline_xmin (size_t n, T *r, const T *x, T y)
344 {
345  for (size_t i = 0; i < n; i++)
346  r[i] = octave::math::min (x[i], y);
347 }
348 
349 template <typename T>
350 inline void
351 mx_inline_xmin (size_t n, T *r, T x, const T *y)
352 {
353  for (size_t i = 0; i < n; i++)
354  r[i] = octave::math::min (x, y[i]);
355 }
356 
357 template <typename T>
358 inline void
359 mx_inline_xmax (size_t n, T *r, const T *x, const T *y)
360 {
361  for (size_t i = 0; i < n; i++)
362  r[i] = octave::math::max (x[i], y[i]);
363 }
364 
365 template <typename T>
366 inline void
367 mx_inline_xmax (size_t n, T *r, const T *x, T y)
368 {
369  for (size_t i = 0; i < n; i++)
370  r[i] = octave::math::max (x[i], y);
371 }
372 
373 template <typename T>
374 inline void
375 mx_inline_xmax (size_t n, T *r, T x, const T *y)
376 {
377  for (size_t i = 0; i < n; i++)
378  r[i] = octave::math::max (x, y[i]);
379 }
380 
381 // Specialize array-scalar max/min
382 #define DEFMINMAXSPEC(T, F, OP) \
383  template <> \
384  inline void F<T> (size_t n, T *r, const T *x, T y) \
385  { \
386  if (octave::math::isnan (y)) \
387  std::memcpy (r, x, n * sizeof (T)); \
388  else \
389  for (size_t i = 0; i < n; i++) \
390  r[i] = (x[i] OP y ? x[i] : y); \
391  } \
392  template <> \
393  inline void F<T> (size_t n, T *r, T x, const T *y) \
394  { \
395  if (octave::math::isnan (x)) \
396  std::memcpy (r, y, n * sizeof (T)); \
397  else \
398  for (size_t i = 0; i < n; i++) \
399  r[i] = (y[i] OP x ? y[i] : x); \
400  }
401 
406 
407 // FIXME: Is this comment correct anymore? It seems like std::pow is chosen.
408 // Let the compiler decide which pow to use, whichever best matches the
409 // arguments provided.
410 
411 template <typename R, typename X, typename Y>
412 inline void
413 mx_inline_pow (size_t n, R *r, const X *x, const Y *y)
414 {
415  using std::pow;
416 
417  for (size_t i = 0; i < n; i++)
418  r[i] = pow (x[i], y[i]);
419 }
420 
421 template <typename R, typename X, typename Y>
422 inline void
423 mx_inline_pow (size_t n, R *r, const X *x, Y y)
424 {
425  using std::pow;
426 
427  for (size_t i = 0; i < n; i++)
428  r[i] = pow (x[i], y);
429 }
430 
431 template <typename R, typename X, typename Y>
432 inline void
433 mx_inline_pow (size_t n, R *r, X x, const Y *y)
434 {
435  using std::pow;
436 
437  for (size_t i = 0; i < n; i++)
438  r[i] = pow (x, y[i]);
439 }
440 
441 // Arbitrary function appliers.
442 // The function is a template parameter to enable inlining.
443 template <typename R, typename X, R fun (X x)>
444 inline void mx_inline_map (size_t n, R *r, const X *x)
445 {
446  for (size_t i = 0; i < n; i++)
447  r[i] = fun (x[i]);
448 }
449 
450 template <typename R, typename X, R fun (const X& x)>
451 inline void mx_inline_map (size_t n, R *r, const X *x)
452 {
453  for (size_t i = 0; i < n; i++)
454  r[i] = fun (x[i]);
455 }
456 
457 // Appliers. Since these call the operation just once, we pass it as
458 // a pointer, to allow the compiler reduce number of instances.
459 
460 template <typename R, typename X>
461 inline Array<R>
463  void (*op) (size_t, R *, const X *))
464 {
465  Array<R> r (x.dims ());
466  op (r.numel (), r.fortran_vec (), x.data ());
467  return r;
468 }
469 
470 // Shortcuts for applying mx_inline_map.
471 
472 template <typename R, typename X, R fun (X)>
473 inline Array<R>
475 {
476  return do_mx_unary_op<R, X> (x, mx_inline_map<R, X, fun>);
477 }
478 
479 template <typename R, typename X, R fun (const X&)>
480 inline Array<R>
481 do_mx_unary_map (const Array<X>& x)
482 {
483  return do_mx_unary_op<R, X> (x, mx_inline_map<R, X, fun>);
484 }
485 
486 template <typename R>
487 inline Array<R>&
489  void (*op) (size_t, R *))
490 {
491  op (r.numel (), r.fortran_vec ());
492  return r;
493 }
494 
495 template <typename R, typename X, typename Y>
496 inline Array<R>
498  void (*op) (size_t, R *, const X *, const Y *),
499  void (*op1) (size_t, R *, X, const Y *),
500  void (*op2) (size_t, R *, const X *, Y),
501  const char *opname)
502 {
503  dim_vector dx = x.dims ();
504  dim_vector dy = y.dims ();
505  if (dx == dy)
506  {
507  Array<R> r (dx);
508  op (r.numel (), r.fortran_vec (), x.data (), y.data ());
509  return r;
510  }
511  else if (is_valid_bsxfun (opname, dx, dy))
512  {
513  return do_bsxfun_op (x, y, op, op1, op2);
514  }
515  else
516  octave::err_nonconformant (opname, dx, dy);
517 }
518 
519 template <typename R, typename X, typename Y>
520 inline Array<R>
521 do_ms_binary_op (const Array<X>& x, const Y& y,
522  void (*op) (size_t, R *, const X *, Y))
523 {
524  Array<R> r (x.dims ());
525  op (r.numel (), r.fortran_vec (), x.data (), y);
526  return r;
527 }
528 
529 template <typename R, typename X, typename Y>
530 inline Array<R>
531 do_sm_binary_op (const X& x, const Array<Y>& y,
532  void (*op) (size_t, R *, X, const Y *))
533 {
534  Array<R> r (y.dims ());
535  op (r.numel (), r.fortran_vec (), x, y.data ());
536  return r;
537 }
538 
539 template <typename R, typename X>
540 inline Array<R>&
542  void (*op) (size_t, R *, const X *) ,
543  void (*op1) (size_t, R *, X) ,
544  const char *opname)
545 {
546  dim_vector dr = r.dims ();
547  dim_vector dx = x.dims ();
548  if (dr == dx)
549  op (r.numel (), r.fortran_vec (), x.data ());
550  else if (is_valid_inplace_bsxfun (opname, dr, dx))
551  do_inplace_bsxfun_op (r, x, op, op1);
552  else
553  octave::err_nonconformant (opname, dr, dx);
554 
555  return r;
556 }
557 
558 template <typename R, typename X>
559 inline Array<R>&
561  void (*op) (size_t, R *, X))
562 {
563  op (r.numel (), r.fortran_vec (), x);
564  return r;
565 }
566 
567 template <typename T1, typename T2>
568 inline bool
569 mx_inline_equal (size_t n, const T1 *x, const T2 *y)
570 {
571  for (size_t i = 0; i < n; i++)
572  if (x[i] != y[i])
573  return false;
574  return true;
575 }
576 
577 template <typename T>
578 inline bool
580  bool (*op) (size_t, const T *))
581 {
582  return op (a.numel (), a.data ());
583 }
584 
585 // NOTE: we don't use std::norm because it typically does some heavyweight
586 // magic to avoid underflows, which we don't need here.
587 template <typename T>
588 inline T cabsq (const std::complex<T>& c)
589 {
590  return c.real () * c.real () + c.imag () * c.imag ();
591 }
592 
593 // default. works for integers and bool.
594 template <typename T>
595 inline bool
597 {
598  return x;
599 }
600 
601 template <typename T>
602 inline bool
604 {
605  return ! x;
606 }
607 
608 // for octave_ints
609 template <typename T>
610 inline bool
612 {
613  return x.value ();
614 }
615 
616 template <typename T>
617 inline bool
619 {
620  return ! x.value ();
621 }
622 
623 // for reals, we want to ignore NaNs.
624 inline bool
625 xis_true (double x)
626 {
627  return ! octave::math::isnan (x) && x != 0.0;
628 }
629 
630 inline bool
631 xis_false (double x)
632 {
633  return x == 0.0;
634 }
635 
636 inline bool
637 xis_true (float x)
638 {
639  return ! octave::math::isnan (x) && x != 0.0f;
640 }
641 
642 inline bool
643 xis_false (float x)
644 {
645  return x == 0.0f;
646 }
647 
648 // Ditto for complex.
649 inline bool
651 {
652  return ! octave::math::isnan (x) && x != 0.0;
653 }
654 
655 inline bool
657 {
658  return x == 0.0;
659 }
660 
661 inline bool
663 {
664  return ! octave::math::isnan (x) && x != 0.0f;
665 }
666 
667 inline bool
669 {
670  return x == 0.0f;
671 }
672 
673 #define OP_RED_SUM(ac, el) ac += el
674 #define OP_RED_PROD(ac, el) ac *= el
675 #define OP_RED_SUMSQ(ac, el) ac += el*el
676 #define OP_RED_SUMSQC(ac, el) ac += cabsq (el)
677 
678 inline void
679 op_dble_prod (double& ac, float el)
680 {
681  ac *= el;
682 }
683 
684 // FIXME: guaranteed?
685 inline void
687 {
688  ac *= el;
689 }
690 
691 template <typename T>
692 inline void
693 op_dble_prod (double& ac, const octave_int<T>& el)
694 {
695  ac *= el.double_value ();
696 }
697 
698 inline void
699 op_dble_sum (double& ac, float el)
700 {
701  ac += el;
702 }
703 
704 // FIXME: guaranteed?
705 inline void
707 {
708  ac += el;
709 }
710 
711 template <typename T>
712 inline void
713 op_dble_sum (double& ac, const octave_int<T>& el)
714 {
715  ac += el.double_value ();
716 }
717 
718 // The following two implement a simple short-circuiting.
719 #define OP_RED_ANYC(ac, el) \
720  if (xis_true (el)) \
721  { \
722  ac = true; \
723  break; \
724  } \
725  else \
726  continue
727 
728 #define OP_RED_ALLC(ac, el) \
729  if (xis_false (el)) \
730  { \
731  ac = false; \
732  break; \
733  } \
734  else \
735  continue
736 
737 #define OP_RED_FCN(F, TSRC, TRES, OP, ZERO) \
738  template <typename T> \
739  inline TRES \
740  F (const TSRC *v, octave_idx_type n) \
741  { \
742  TRES ac = ZERO; \
743  for (octave_idx_type i = 0; i < n; i++) \
744  OP(ac, v[i]); \
745  return ac; \
746  }
747 
748 #define PROMOTE_DOUBLE(T) \
749  typename subst_template_param<std::complex, T, double>::type
750 
757 OP_RED_FCN (mx_inline_sumsq, std::complex<T>, T, OP_RED_SUMSQC, 0)
759 OP_RED_FCN (mx_inline_all, T, bool, OP_RED_ALLC, true)
760 
761 #define OP_RED_FCN2(F, TSRC, TRES, OP, ZERO) \
762  template <typename T> \
763  inline void \
764  F (const TSRC *v, TRES *r, octave_idx_type m, octave_idx_type n) \
765  { \
766  for (octave_idx_type i = 0; i < m; i++) \
767  r[i] = ZERO; \
768  for (octave_idx_type j = 0; j < n; j++) \
769  { \
770  for (octave_idx_type i = 0; i < m; i++) \
771  OP(r[i], v[i]); \
772  v += m; \
773  } \
774  }
775 
776 OP_RED_FCN2 (mx_inline_sum, T, T, OP_RED_SUM, 0)
777 OP_RED_FCN2 (mx_inline_dsum, T, PROMOTE_DOUBLE(T), op_dble_sum, 0.0)
778 OP_RED_FCN2 (mx_inline_count, bool, T, OP_RED_SUM, 0)
779 OP_RED_FCN2 (mx_inline_prod, T, T, OP_RED_PROD, 1)
780 OP_RED_FCN2 (mx_inline_dprod, T, PROMOTE_DOUBLE(T), op_dble_prod, 0.0)
781 OP_RED_FCN2 (mx_inline_sumsq, T, T, OP_RED_SUMSQ, 0)
782 OP_RED_FCN2 (mx_inline_sumsq, std::complex<T>, T, OP_RED_SUMSQC, 0)
783 
784 #define OP_RED_ANYR(ac, el) ac |= xis_true (el)
785 #define OP_RED_ALLR(ac, el) ac &= xis_true (el)
786 
787 OP_RED_FCN2 (mx_inline_any_r, T, bool, OP_RED_ANYR, false)
788 OP_RED_FCN2 (mx_inline_all_r, T, bool, OP_RED_ALLR, true)
789 
790 // Using the general code for any/all would sacrifice short-circuiting.
791 // OTOH, going by rows would sacrifice cache-coherence. The following
792 // algorithm will achieve both, at the cost of a temporary octave_idx_type
793 // array.
794 
795 #define OP_ROW_SHORT_CIRCUIT(F, PRED, ZERO) \
796  template <typename T> \
797  inline void \
798  F (const T *v, bool *r, octave_idx_type m, octave_idx_type n) \
799  { \
800  if (n <= 8) \
801  return F ## _r (v, r, m, n); \
802  \
803  /* FIXME: it may be sub-optimal to allocate the buffer here. */ \
804  OCTAVE_LOCAL_BUFFER (octave_idx_type, iact, m); \
805  for (octave_idx_type i = 0; i < m; i++) iact[i] = i; \
806  octave_idx_type nact = m; \
807  for (octave_idx_type j = 0; j < n; j++) \
808  { \
809  octave_idx_type k = 0; \
810  for (octave_idx_type i = 0; i < nact; i++) \
811  { \
812  octave_idx_type ia = iact[i]; \
813  if (! PRED (v[ia])) \
814  iact[k++] = ia; \
815  } \
816  nact = k; \
817  v += m; \
818  } \
819  for (octave_idx_type i = 0; i < m; i++) r[i] = ! ZERO; \
820  for (octave_idx_type i = 0; i < nact; i++) r[iact[i]] = ZERO; \
821  }
822 
825 
826 #define OP_RED_FCNN(F, TSRC, TRES) \
827  template <typename T> \
828  inline void \
829  F (const TSRC *v, TRES *r, octave_idx_type l, \
830  octave_idx_type n, octave_idx_type u) \
831  { \
832  if (l == 1) \
833  { \
834  for (octave_idx_type i = 0; i < u; i++) \
835  { \
836  r[i] = F<T> (v, n); \
837  v += n; \
838  } \
839  } \
840  else \
841  { \
842  for (octave_idx_type i = 0; i < u; i++) \
843  { \
844  F (v, r, l, n); \
845  v += l*n; \
846  r += l; \
847  } \
848  } \
849  }
850 
853 OP_RED_FCNN (mx_inline_count, bool, T)
857 OP_RED_FCNN (mx_inline_sumsq, std::complex<T>, T)
860 
861 #define OP_CUM_FCN(F, TSRC, TRES, OP) \
862  template <typename T> \
863  inline void \
864  F (const TSRC *v, TRES *r, octave_idx_type n) \
865  { \
866  if (n) \
867  { \
868  TRES t = r[0] = v[0]; \
869  for (octave_idx_type i = 1; i < n; i++) \
870  r[i] = t = t OP v[i]; \
871  } \
872  }
873 
874 OP_CUM_FCN (mx_inline_cumsum, T, T, +)
875 OP_CUM_FCN (mx_inline_cumprod, T, T, *)
876 OP_CUM_FCN (mx_inline_cumcount, bool, T, +)
877 
878 #define OP_CUM_FCN2(F, TSRC, TRES, OP) \
879  template <typename T> \
880  inline void \
881  F (const TSRC *v, TRES *r, octave_idx_type m, octave_idx_type n) \
882  { \
883  if (n) \
884  { \
885  for (octave_idx_type i = 0; i < m; i++) \
886  r[i] = v[i]; \
887  const T *r0 = r; \
888  for (octave_idx_type j = 1; j < n; j++) \
889  { \
890  r += m; v += m; \
891  for (octave_idx_type i = 0; i < m; i++) \
892  r[i] = r0[i] OP v[i]; \
893  r0 += m; \
894  } \
895  } \
896  }
897 
898 OP_CUM_FCN2 (mx_inline_cumsum, T, T, +)
900 OP_CUM_FCN2 (mx_inline_cumcount, bool, T, +)
901 
902 #define OP_CUM_FCNN(F, TSRC, TRES) \
903  template <typename T> \
904  inline void \
905  F (const TSRC *v, TRES *r, octave_idx_type l, \
906  octave_idx_type n, octave_idx_type u) \
907  { \
908  if (l == 1) \
909  { \
910  for (octave_idx_type i = 0; i < u; i++) \
911  { \
912  F (v, r, n); \
913  v += n; \
914  r += n; \
915  } \
916  } \
917  else \
918  { \
919  for (octave_idx_type i = 0; i < u; i++) \
920  { \
921  F (v, r, l, n); \
922  v += l*n; \
923  r += l*n; \
924  } \
925  } \
926  }
927 
931 
932 #define OP_MINMAX_FCN(F, OP) \
933  template <typename T> \
934  void F (const T *v, T *r, octave_idx_type n) \
935  { \
936  if (! n) \
937  return; \
938  T tmp = v[0]; \
939  octave_idx_type i = 1; \
940  if (octave::math::isnan (tmp)) \
941  { \
942  for (; i < n && octave::math::isnan (v[i]); i++) ; \
943  if (i < n) \
944  tmp = v[i]; \
945  } \
946  for (; i < n; i++) \
947  if (v[i] OP tmp) \
948  tmp = v[i]; \
949  *r = tmp; \
950  } \
951  template <typename T> \
952  void F (const T *v, T *r, octave_idx_type *ri, octave_idx_type n) \
953  { \
954  if (! n) \
955  return; \
956  T tmp = v[0]; \
957  octave_idx_type tmpi = 0; \
958  octave_idx_type i = 1; \
959  if (octave::math::isnan (tmp)) \
960  { \
961  for (; i < n && octave::math::isnan (v[i]); i++) ; \
962  if (i < n) \
963  { \
964  tmp = v[i]; \
965  tmpi = i; \
966  } \
967  } \
968  for (; i < n; i++) \
969  if (v[i] OP tmp) \
970  { \
971  tmp = v[i]; \
972  tmpi = i; \
973  } \
974  *r = tmp; \
975  *ri = tmpi; \
976  }
977 
980 
981 // Row reductions will be slightly complicated. We will proceed with checks
982 // for NaNs until we detect that no row will yield a NaN, in which case we
983 // proceed to a faster code.
984 
985 #define OP_MINMAX_FCN2(F, OP) \
986  template <typename T> \
987  inline void \
988  F (const T *v, T *r, octave_idx_type m, octave_idx_type n) \
989  { \
990  if (! n) \
991  return; \
992  bool nan = false; \
993  octave_idx_type j = 0; \
994  for (octave_idx_type i = 0; i < m; i++) \
995  { \
996  r[i] = v[i]; \
997  if (octave::math::isnan (v[i])) \
998  nan = true; \
999  } \
1000  j++; \
1001  v += m; \
1002  while (nan && j < n) \
1003  { \
1004  nan = false; \
1005  for (octave_idx_type i = 0; i < m; i++) \
1006  { \
1007  if (octave::math::isnan (v[i])) \
1008  nan = true; \
1009  else if (octave::math::isnan (r[i]) || v[i] OP r[i]) \
1010  r[i] = v[i]; \
1011  } \
1012  j++; \
1013  v += m; \
1014  } \
1015  while (j < n) \
1016  { \
1017  for (octave_idx_type i = 0; i < m; i++) \
1018  if (v[i] OP r[i]) \
1019  r[i] = v[i]; \
1020  j++; \
1021  v += m; \
1022  } \
1023  } \
1024  template <typename T> \
1025  inline void \
1026  F (const T *v, T *r, octave_idx_type *ri, \
1027  octave_idx_type m, octave_idx_type n) \
1028  { \
1029  if (! n) \
1030  return; \
1031  bool nan = false; \
1032  octave_idx_type j = 0; \
1033  for (octave_idx_type i = 0; i < m; i++) \
1034  { \
1035  r[i] = v[i]; \
1036  ri[i] = j; \
1037  if (octave::math::isnan (v[i])) \
1038  nan = true; \
1039  } \
1040  j++; \
1041  v += m; \
1042  while (nan && j < n) \
1043  { \
1044  nan = false; \
1045  for (octave_idx_type i = 0; i < m; i++) \
1046  { \
1047  if (octave::math::isnan (v[i])) \
1048  nan = true; \
1049  else if (octave::math::isnan (r[i]) || v[i] OP r[i]) \
1050  { \
1051  r[i] = v[i]; \
1052  ri[i] = j; \
1053  } \
1054  } \
1055  j++; \
1056  v += m; \
1057  } \
1058  while (j < n) \
1059  { \
1060  for (octave_idx_type i = 0; i < m; i++) \
1061  if (v[i] OP r[i]) \
1062  { \
1063  r[i] = v[i]; \
1064  ri[i] = j; \
1065  } \
1066  j++; \
1067  v += m; \
1068  } \
1069  }
1070 
1073 
1074 #define OP_MINMAX_FCNN(F) \
1075  template <typename T> \
1076  inline void \
1077  F (const T *v, T *r, octave_idx_type l, \
1078  octave_idx_type n, octave_idx_type u) \
1079  { \
1080  if (! n) \
1081  return; \
1082  if (l == 1) \
1083  { \
1084  for (octave_idx_type i = 0; i < u; i++) \
1085  { \
1086  F (v, r, n); \
1087  v += n; \
1088  r++; \
1089  } \
1090  } \
1091  else \
1092  { \
1093  for (octave_idx_type i = 0; i < u; i++) \
1094  { \
1095  F (v, r, l, n); \
1096  v += l*n; \
1097  r += l; \
1098  } \
1099  } \
1100  } \
1101  template <typename T> \
1102  inline void \
1103  F (const T *v, T *r, octave_idx_type *ri, \
1104  octave_idx_type l, octave_idx_type n, octave_idx_type u) \
1105  { \
1106  if (! n) return; \
1107  if (l == 1) \
1108  { \
1109  for (octave_idx_type i = 0; i < u; i++) \
1110  { \
1111  F (v, r, ri, n); \
1112  v += n; \
1113  r++; \
1114  ri++; \
1115  } \
1116  } \
1117  else \
1118  { \
1119  for (octave_idx_type i = 0; i < u; i++) \
1120  { \
1121  F (v, r, ri, l, n); \
1122  v += l*n; \
1123  r += l; \
1124  ri += l; \
1125  } \
1126  } \
1127  }
1128 
1131 
1132 #define OP_CUMMINMAX_FCN(F, OP) \
1133  template <typename T> \
1134  void F (const T *v, T *r, octave_idx_type n) \
1135  { \
1136  if (! n) \
1137  return; \
1138  T tmp = v[0]; \
1139  octave_idx_type i = 1; \
1140  octave_idx_type j = 0; \
1141  if (octave::math::isnan (tmp)) \
1142  { \
1143  for (; i < n && octave::math::isnan (v[i]); i++) ; \
1144  for (; j < i; j++) \
1145  r[j] = tmp; \
1146  if (i < n) \
1147  tmp = v[i]; \
1148  } \
1149  for (; i < n; i++) \
1150  if (v[i] OP tmp) \
1151  { \
1152  for (; j < i; j++) \
1153  r[j] = tmp; \
1154  tmp = v[i]; \
1155  } \
1156  for (; j < i; j++) \
1157  r[j] = tmp; \
1158  } \
1159  template <typename T> \
1160  void F (const T *v, T *r, octave_idx_type *ri, octave_idx_type n) \
1161  { \
1162  if (! n) \
1163  return; \
1164  T tmp = v[0]; \
1165  octave_idx_type tmpi = 0; \
1166  octave_idx_type i = 1; \
1167  octave_idx_type j = 0; \
1168  if (octave::math::isnan (tmp)) \
1169  { \
1170  for (; i < n && octave::math::isnan (v[i]); i++) ; \
1171  for (; j < i; j++) \
1172  { \
1173  r[j] = tmp; \
1174  ri[j] = tmpi; \
1175  } \
1176  if (i < n) \
1177  { \
1178  tmp = v[i]; \
1179  tmpi = i; \
1180  } \
1181  } \
1182  for (; i < n; i++) \
1183  if (v[i] OP tmp) \
1184  { \
1185  for (; j < i; j++) \
1186  { \
1187  r[j] = tmp; \
1188  ri[j] = tmpi; \
1189  } \
1190  tmp = v[i]; \
1191  tmpi = i; \
1192  } \
1193  for (; j < i; j++) \
1194  { \
1195  r[j] = tmp; \
1196  ri[j] = tmpi; \
1197  } \
1198  }
1199 
1202 
1203 // Row reductions will be slightly complicated. We will proceed with checks
1204 // for NaNs until we detect that no row will yield a NaN, in which case we
1205 // proceed to a faster code.
1206 
1207 #define OP_CUMMINMAX_FCN2(F, OP) \
1208  template <typename T> \
1209  inline void \
1210  F (const T *v, T *r, octave_idx_type m, octave_idx_type n) \
1211  { \
1212  if (! n) \
1213  return; \
1214  bool nan = false; \
1215  const T *r0; \
1216  octave_idx_type j = 0; \
1217  for (octave_idx_type i = 0; i < m; i++) \
1218  { \
1219  r[i] = v[i]; \
1220  if (octave::math::isnan (v[i])) \
1221  nan = true; \
1222  } \
1223  j++; \
1224  v += m; \
1225  r0 = r; \
1226  r += m; \
1227  while (nan && j < n) \
1228  { \
1229  nan = false; \
1230  for (octave_idx_type i = 0; i < m; i++) \
1231  { \
1232  if (octave::math::isnan (v[i])) \
1233  { \
1234  r[i] = r0[i]; \
1235  nan = true; \
1236  } \
1237  else if (octave::math::isnan (r0[i]) || v[i] OP r0[i]) \
1238  r[i] = v[i]; \
1239  else \
1240  r[i] = r0[i]; \
1241  } \
1242  j++; \
1243  v += m; \
1244  r0 = r; \
1245  r += m; \
1246  } \
1247  while (j < n) \
1248  { \
1249  for (octave_idx_type i = 0; i < m; i++) \
1250  if (v[i] OP r0[i]) \
1251  r[i] = v[i]; \
1252  else \
1253  r[i] = r0[i]; \
1254  j++; \
1255  v += m; \
1256  r0 = r; \
1257  r += m; \
1258  } \
1259  } \
1260  template <typename T> \
1261  inline void \
1262  F (const T *v, T *r, octave_idx_type *ri, \
1263  octave_idx_type m, octave_idx_type n) \
1264  { \
1265  if (! n) \
1266  return; \
1267  bool nan = false; \
1268  const T *r0; \
1269  const octave_idx_type *r0i; \
1270  octave_idx_type j = 0; \
1271  for (octave_idx_type i = 0; i < m; i++) \
1272  { \
1273  r[i] = v[i]; ri[i] = 0; \
1274  if (octave::math::isnan (v[i])) \
1275  nan = true; \
1276  } \
1277  j++; \
1278  v += m; \
1279  r0 = r; \
1280  r += m; \
1281  r0i = ri; \
1282  ri += m; \
1283  while (nan && j < n) \
1284  { \
1285  nan = false; \
1286  for (octave_idx_type i = 0; i < m; i++) \
1287  { \
1288  if (octave::math::isnan (v[i])) \
1289  { \
1290  r[i] = r0[i]; \
1291  ri[i] = r0i[i]; \
1292  nan = true; \
1293  } \
1294  else if (octave::math::isnan (r0[i]) || v[i] OP r0[i]) \
1295  { \
1296  r[i] = v[i]; \
1297  ri[i] = j; \
1298  } \
1299  else \
1300  { \
1301  r[i] = r0[i]; \
1302  ri[i] = r0i[i]; \
1303  } \
1304  } \
1305  j++; \
1306  v += m; \
1307  r0 = r; \
1308  r += m; \
1309  r0i = ri; \
1310  ri += m; \
1311  } \
1312  while (j < n) \
1313  { \
1314  for (octave_idx_type i = 0; i < m; i++) \
1315  if (v[i] OP r0[i]) \
1316  { \
1317  r[i] = v[i]; \
1318  ri[i] = j; \
1319  } \
1320  else \
1321  { \
1322  r[i] = r0[i]; \
1323  ri[i] = r0i[i]; \
1324  } \
1325  j++; \
1326  v += m; \
1327  r0 = r; \
1328  r += m; \
1329  r0i = ri; \
1330  ri += m; \
1331  } \
1332  }
1333 
1336 
1337 #define OP_CUMMINMAX_FCNN(F) \
1338  template <typename T> \
1339  inline void \
1340  F (const T *v, T *r, octave_idx_type l, \
1341  octave_idx_type n, octave_idx_type u) \
1342  { \
1343  if (! n) \
1344  return; \
1345  if (l == 1) \
1346  { \
1347  for (octave_idx_type i = 0; i < u; i++) \
1348  { \
1349  F (v, r, n); \
1350  v += n; \
1351  r += n; \
1352  } \
1353  } \
1354  else \
1355  { \
1356  for (octave_idx_type i = 0; i < u; i++) \
1357  { \
1358  F (v, r, l, n); \
1359  v += l*n; \
1360  r += l*n; \
1361  } \
1362  } \
1363  } \
1364  template <typename T> \
1365  inline void \
1366  F (const T *v, T *r, octave_idx_type *ri, \
1367  octave_idx_type l, octave_idx_type n, octave_idx_type u) \
1368  { \
1369  if (! n) \
1370  return; \
1371  if (l == 1) \
1372  { \
1373  for (octave_idx_type i = 0; i < u; i++) \
1374  { \
1375  F (v, r, ri, n); \
1376  v += n; \
1377  r += n; \
1378  ri += n; \
1379  } \
1380  } \
1381  else \
1382  { \
1383  for (octave_idx_type i = 0; i < u; i++) \
1384  { \
1385  F (v, r, ri, l, n); \
1386  v += l*n; \
1387  r += l*n; \
1388  ri += l*n; \
1389  } \
1390  } \
1391  }
1392 
1395 
1396 template <typename T>
1397 void mx_inline_diff (const T *v, T *r, octave_idx_type n,
1398  octave_idx_type order)
1399 {
1400  switch (order)
1401  {
1402  case 1:
1403  for (octave_idx_type i = 0; i < n-1; i++)
1404  r[i] = v[i+1] - v[i];
1405  break;
1406  case 2:
1407  if (n > 1)
1408  {
1409  T lst = v[1] - v[0];
1410  for (octave_idx_type i = 0; i < n-2; i++)
1411  {
1412  T dif = v[i+2] - v[i+1];
1413  r[i] = dif - lst;
1414  lst = dif;
1415  }
1416  }
1417  break;
1418  default:
1419  {
1420  OCTAVE_LOCAL_BUFFER (T, buf, n-1);
1422  for (octave_idx_type i = 0; i < n-1; i++)
1423  buf[i] = v[i+1] - v[i];
1424 
1425  for (octave_idx_type o = 2; o <= order; o++)
1426  {
1427  for (octave_idx_type i = 0; i < n-o; i++)
1428  buf[i] = buf[i+1] - buf[i];
1429  }
1430 
1431  for (octave_idx_type i = 0; i < n-order; i++)
1432  r[i] = buf[i];
1433  }
1434  }
1435 }
1436 
1437 template <typename T>
1438 void mx_inline_diff (const T *v, T *r,
1440  octave_idx_type order)
1441 {
1442  switch (order)
1443  {
1444  case 1:
1445  for (octave_idx_type i = 0; i < m*(n-1); i++)
1446  r[i] = v[i+m] - v[i];
1447  break;
1448  case 2:
1449  for (octave_idx_type i = 0; i < n-2; i++)
1450  {
1451  for (octave_idx_type j = i*m; j < i*m+m; j++)
1452  r[j] = (v[j+m+m] - v[j+m]) - (v[j+m] - v[j]);
1453  }
1454  break;
1455  default:
1456  {
1457  OCTAVE_LOCAL_BUFFER (T, buf, n-1);
1458 
1459  for (octave_idx_type j = 0; j < m; j++)
1460  {
1461  for (octave_idx_type i = 0; i < n-1; i++)
1462  buf[i] = v[i*m+j+m] - v[i*m+j];
1463 
1464  for (octave_idx_type o = 2; o <= order; o++)
1465  {
1466  for (octave_idx_type i = 0; i < n-o; i++)
1467  buf[i] = buf[i+1] - buf[i];
1468  }
1469 
1470  for (octave_idx_type i = 0; i < n-order; i++)
1471  r[i*m+j] = buf[i];
1472  }
1473  }
1474  }
1475 }
1476 
1477 template <typename T>
1478 inline void
1479 mx_inline_diff (const T *v, T *r,
1481  octave_idx_type order)
1482 {
1483  if (! n) return;
1484  if (l == 1)
1485  {
1486  for (octave_idx_type i = 0; i < u; i++)
1487  {
1488  mx_inline_diff (v, r, n, order);
1489  v += n; r += n-order;
1490  }
1491  }
1492  else
1493  {
1494  for (octave_idx_type i = 0; i < u; i++)
1495  {
1496  mx_inline_diff (v, r, l, n, order);
1497  v += l*n;
1498  r += l*(n-order);
1499  }
1500  }
1501 }
1502 
1503 // Assistant function
1504 
1505 inline void
1506 get_extent_triplet (const dim_vector& dims, int& dim,
1508  octave_idx_type& u)
1509 {
1510  octave_idx_type ndims = dims.ndims ();
1511  if (dim >= ndims)
1512  {
1513  l = dims.numel ();
1514  n = 1;
1515  u = 1;
1516  }
1517  else
1518  {
1519  if (dim < 0)
1520  dim = dims.first_non_singleton ();
1521 
1522  // calculate extent triplet.
1523  l = 1, n = dims(dim), u = 1;
1524  for (octave_idx_type i = 0; i < dim; i++)
1525  l *= dims(i);
1526  for (octave_idx_type i = dim + 1; i < ndims; i++)
1527  u *= dims(i);
1528  }
1529 }
1530 
1531 // Appliers.
1532 // FIXME: is this the best design? C++ gives a lot of options here...
1533 // maybe it can be done without an explicit parameter?
1534 
1535 template <typename R, typename T>
1536 inline Array<R>
1537 do_mx_red_op (const Array<T>& src, int dim,
1538  void (*mx_red_op) (const T *, R *, octave_idx_type,
1540 {
1541  octave_idx_type l, n, u;
1542  dim_vector dims = src.dims ();
1543  // M*b inconsistency: sum ([]) = 0 etc.
1544  if (dims.ndims () == 2 && dims(0) == 0 && dims(1) == 0)
1545  dims(1) = 1;
1546 
1547  get_extent_triplet (dims, dim, l, n, u);
1548 
1549  // Reduction operation reduces the array size.
1550  if (dim < dims.ndims ()) dims(dim) = 1;
1551  dims.chop_trailing_singletons ();
1552 
1553  Array<R> ret (dims);
1554  mx_red_op (src.data (), ret.fortran_vec (), l, n, u);
1555 
1556  return ret;
1557 }
1558 
1559 template <typename R, typename T>
1560 inline Array<R>
1561 do_mx_cum_op (const Array<T>& src, int dim,
1562  void (*mx_cum_op) (const T *, R *, octave_idx_type,
1564 {
1565  octave_idx_type l, n, u;
1566  dim_vector dims = src.dims ();
1567  get_extent_triplet (dims, dim, l, n, u);
1568 
1569  // Cumulative operation doesn't reduce the array size.
1570  Array<R> ret (dims);
1571  mx_cum_op (src.data (), ret.fortran_vec (), l, n, u);
1572 
1573  return ret;
1574 }
1575 
1576 template <typename R>
1577 inline Array<R>
1578 do_mx_minmax_op (const Array<R>& src, int dim,
1579  void (*mx_minmax_op) (const R *, R *, octave_idx_type,
1582  octave_idx_type l, n, u;
1583  dim_vector dims = src.dims ();
1584  get_extent_triplet (dims, dim, l, n, u);
1585 
1586  // If the dimension is zero, we don't do anything.
1587  if (dim < dims.ndims () && dims(dim) != 0) dims(dim) = 1;
1588  dims.chop_trailing_singletons ();
1589 
1590  Array<R> ret (dims);
1591  mx_minmax_op (src.data (), ret.fortran_vec (), l, n, u);
1592 
1593  return ret;
1594 }
1595 
1596 template <typename R>
1597 inline Array<R>
1598 do_mx_minmax_op (const Array<R>& src, Array<octave_idx_type>& idx, int dim,
1599  void (*mx_minmax_op) (const R *, R *, octave_idx_type *,
1601 {
1602  octave_idx_type l, n, u;
1603  dim_vector dims = src.dims ();
1604  get_extent_triplet (dims, dim, l, n, u);
1605 
1606  // If the dimension is zero, we don't do anything.
1607  if (dim < dims.ndims () && dims(dim) != 0) dims(dim) = 1;
1608  dims.chop_trailing_singletons ();
1609 
1610  Array<R> ret (dims);
1611  if (idx.dims () != dims) idx = Array<octave_idx_type> (dims);
1612 
1613  mx_minmax_op (src.data (), ret.fortran_vec (), idx.fortran_vec (),
1614  l, n, u);
1615 
1616  return ret;
1617 }
1618 
1619 template <typename R>
1620 inline Array<R>
1621 do_mx_cumminmax_op (const Array<R>& src, int dim,
1622  void (*mx_cumminmax_op) (const R *, R *, octave_idx_type,
1624 {
1625  octave_idx_type l, n, u;
1626  dim_vector dims = src.dims ();
1627  get_extent_triplet (dims, dim, l, n, u);
1628 
1629  Array<R> ret (dims);
1630  mx_cumminmax_op (src.data (), ret.fortran_vec (), l, n, u);
1631 
1632  return ret;
1633 }
1634 
1635 template <typename R>
1636 inline Array<R>
1637 do_mx_cumminmax_op (const Array<R>& src, Array<octave_idx_type>& idx, int dim,
1638  void (*mx_cumminmax_op) (const R *, R *, octave_idx_type *,
1640 {
1641  octave_idx_type l, n, u;
1642  dim_vector dims = src.dims ();
1643  get_extent_triplet (dims, dim, l, n, u);
1644 
1645  Array<R> ret (dims);
1646  if (idx.dims () != dims) idx = Array<octave_idx_type> (dims);
1647 
1648  mx_cumminmax_op (src.data (), ret.fortran_vec (), idx.fortran_vec (),
1649  l, n, u);
1650 
1651  return ret;
1652 }
1653 
1654 template <typename R>
1655 inline Array<R>
1656 do_mx_diff_op (const Array<R>& src, int dim, octave_idx_type order,
1657  void (*mx_diff_op) (const R *, R *,
1660 {
1661  octave_idx_type l, n, u;
1662  if (order <= 0)
1663  return src;
1664 
1665  dim_vector dims = src.dims ();
1666 
1667  get_extent_triplet (dims, dim, l, n, u);
1668  if (dim >= dims.ndims ())
1669  dims.resize (dim+1, 1);
1670 
1671  if (dims(dim) <= order)
1672  {
1673  dims(dim) = 0;
1674  return Array<R> (dims);
1675  }
1676  else
1677  {
1678  dims(dim) -= order;
1679  }
1680 
1681  Array<R> ret (dims);
1682  mx_diff_op (src.data (), ret.fortran_vec (), l, n, u, order);
1683 
1684  return ret;
1685 }
1686 
1687 // Fast extra-precise summation. According to
1688 // T. Ogita, S. M. Rump, S. Oishi:
1689 // Accurate Sum And Dot Product,
1690 // SIAM J. Sci. Computing, Vol. 26, 2005
1691 
1692 template <typename T>
1693 inline void twosum_accum (T& s, T& e,
1694  const T& x)
1695 {
1696  T s1 = s + x;
1697  T t = s1 - s;
1698  T e1 = (s - (s1 - t)) + (x - t);
1699  s = s1;
1700  e += e1;
1701 }
1702 
1703 template <typename T>
1704 inline T
1705 mx_inline_xsum (const T *v, octave_idx_type n)
1706 {
1707  T s, e;
1708  s = e = 0;
1709  for (octave_idx_type i = 0; i < n; i++)
1710  twosum_accum (s, e, v[i]);
1711 
1712  return s + e;
1713 }
1714 
1715 template <typename T>
1716 inline void
1717 mx_inline_xsum (const T *v, T *r,
1720  OCTAVE_LOCAL_BUFFER (T, e, m);
1721  for (octave_idx_type i = 0; i < m; i++)
1722  e[i] = r[i] = T ();
1723 
1724  for (octave_idx_type j = 0; j < n; j++)
1725  {
1726  for (octave_idx_type i = 0; i < m; i++)
1727  twosum_accum (r[i], e[i], v[i]);
1728 
1729  v += m;
1730  }
1731 
1732  for (octave_idx_type i = 0; i < m; i++)
1733  r[i] += e[i];
1734 }
1735 
1737 
1738 #endif
void mx_inline_or_not(size_t n, bool *r, const X *x, const Y *y)
Definition: mx-inlines.cc:220
T mx_inline_xsum(const T *v, octave_idx_type n)
Definition: mx-inlines.cc:1688
void mx_inline_mul2(size_t n, R *r, const X *x)
Definition: mx-inlines.cc:127
void op_dble_prod(double &ac, float el)
Definition: mx-inlines.cc:679
bool xis_false(T x)
Definition: mx-inlines.cc:603
#define PROMOTE_DOUBLE(T)
Definition: mx-inlines.cc:748
void mx_inline_add2(size_t n, R *r, const X *x)
Definition: mx-inlines.cc:125
#define DEFMINMAXSPEC(T, F, OP)
Definition: mx-inlines.cc:382
void mx_inline_or2(size_t n, bool *r, const X *x)
Definition: mx-inlines.cc:240
Array< R > & do_mm_inplace_op(Array< R > &r, const Array< X > &x, void(*op)(size_t, R *, const X *), void(*op1)(size_t, R *, X), const char *opname)
Definition: mx-inlines.cc:541
Array< R > do_sm_binary_op(const X &x, const Array< Y > &y, void(*op)(size_t, R *, X, const Y *))
Definition: mx-inlines.cc:531
void mx_inline_sub2(size_t n, R *r, const X *x)
Definition: mx-inlines.cc:126
void mx_inline_cummax(const T *v, T *r, octave_idx_type n)
Definition: mx-inlines.cc:1184
#define OP_MINMAX_FCN(F, OP)
Definition: mx-inlines.cc:915
void mx_inline_notzero(size_t n, bool *r, const X *x)
Definition: mx-inlines.cc:79
bool is_valid_bsxfun(const std::string &name, const dim_vector &xdv, const dim_vector &ydv)
Definition: bsxfun.h:38
void mx_inline_le(size_t n, bool *r, const X *x, const Y *y)
Definition: mx-inlines.cc:151
const T * data(void) const
Definition: Array.h:582
void mx_inline_fill(size_t n, R *r, S s)
Definition: mx-inlines.cc:46
void mx_inline_uminus2(size_t n, R *r)
Definition: mx-inlines.cc:62
bool logical_value(T x)
Definition: mx-inlines.cc:160
#define OP_CUM_FCN2(F, TSRC, TRES, OP)
Definition: mx-inlines.cc:861
Array< R > do_mx_diff_op(const Array< R > &src, int dim, octave_idx_type order, void(*mx_diff_op)(const R *, R *, octave_idx_type, octave_idx_type, octave_idx_type, octave_idx_type))
Definition: mx-inlines.cc:1639
OCTAVE_EXPORT octave_value_list or N dimensional array whose elements are all equal to the IEEE symbol zero divided by zero($0/0$)
T cabsq(const std::complex< T > &c)
Definition: mx-inlines.cc:588
#define DEFMXBOOLOP(F, NOT1, OP, NOT2)
Definition: mx-inlines.cc:192
bool is_valid_inplace_bsxfun(const std::string &name, const dim_vector &rdv, const dim_vector &xdv)
Definition: bsxfun.h:62
void mx_inline_real(size_t n, T *r, const std::complex< T > *x)
Definition: mx-inlines.cc:320
bool mx_inline_all_finite(size_t n, const T *x)
Definition: mx-inlines.cc:269
T max(T x, T y)
Definition: lo-mappers.h:383
const T * fortran_vec(void) const
Definition: Array.h:584
bool isnan(bool)
Definition: lo-mappers.h:187
void mx_inline_cumcount(const bool *v, T *r, octave_idx_type n)
Definition: mx-inlines.cc:859
STL namespace.
const dim_vector & dims(void) const
Return a const-reference so that dims ()(i) works efficiently.
Definition: Array.h:442
void mx_inline_map(size_t n, R *r, const X *x)
Definition: mx-inlines.cc:444
bool xis_true(T x)
Definition: mx-inlines.cc:596
u
Definition: lu.cc:138
void mx_inline_ne(size_t n, bool *r, const X *x, const Y *y)
Definition: mx-inlines.cc:155
OCTAVE_EXPORT octave_value_list return the number of command line arguments passed to Octave If called with the optional argument the function t
Definition: ov-usr-fcn.cc:997
T mx_inline_sumsq(const T *v, octave_idx_type n)
Definition: mx-inlines.cc:753
bool mx_inline_any_negative(size_t n, const T *x)
Definition: mx-inlines.cc:282
void mx_inline_max(const T *v, T *r, octave_idx_type n)
Definition: mx-inlines.cc:962
nd example oindent opens the file binary numeric values will be read assuming they are stored in IEEE format with the least significant bit and then converted to the native representation Opening a file that is already open simply opens it again and returns a separate file id It is not an error to open a file several though writing to the same file through several different file ids may produce unexpected results The possible values of text mode reading and writing automatically converts linefeeds to the appropriate line end character for the you may append a you must also open the file in binary mode The parameter conversions are currently only supported for and permissions will be set to and then everything is written in a single operation This is very efficient and improves performance c
Definition: file-io.cc:587
s
Definition: file-io.cc:2729
void mx_inline_eq(size_t n, bool *r, const X *x, const Y *y)
Definition: mx-inlines.cc:154
Array< R > & do_ms_inplace_op(Array< R > &r, const X &x, void(*op)(size_t, R *, X))
Definition: mx-inlines.cc:560
#define OP_RED_ALLC(ac, el)
Definition: mx-inlines.cc:728
i e
Definition: data.cc:2591
bool mx_inline_any(const T *v, octave_idx_type n)
Definition: mx-inlines.cc:753
static void dif(octave_idx_type nt, double *root, double *dif1, double *dif2, double *dif3)
Definition: CollocWt.cc:59
void mx_inline_mul(size_t n, R *r, const X *x, const Y *y)
Definition: mx-inlines.cc:108
void mx_inline_imag(size_t n, T *r, const std::complex< T > *x)
Definition: mx-inlines.cc:327
void mx_inline_xmin(size_t n, T *r, const T *x, const T *y)
Definition: mx-inlines.cc:335
calling an anonymous function involves an overhead quite comparable to the overhead of an m file function Passing a handle to a built in function is because the interpreter is not involved in the internal loop For a
Definition: cellfun.cc:400
#define OP_CUMMINMAX_FCN2(F, OP)
Definition: mx-inlines.cc:1190
#define DEFMXCMPOP(F, OP)
Definition: mx-inlines.cc:130
bool mx_inline_all_real(size_t n, const std::complex< T > *x)
Definition: mx-inlines.cc:308
void mx_inline_sub(size_t n, R *r, const X *x, const Y *y)
Definition: mx-inlines.cc:107
void mx_inline_uminus(size_t n, R *r, const X *x)
Definition: mx-inlines.cc:54
#define OP_RED_SUMSQC(ac, el)
Definition: mx-inlines.cc:676
void mx_inline_and2(size_t n, bool *r, const X *x)
Definition: mx-inlines.cc:224
subst_template_param< std::complex, T, double >::type mx_inline_dprod(const T *v, octave_idx_type n)
Definition: mx-inlines.cc:752
Array< R > do_mm_binary_op(const Array< X > &x, const Array< Y > &y, void(*op)(size_t, R *, const X *, const Y *), void(*op1)(size_t, R *, X, const Y *), void(*op2)(size_t, R *, const X *, Y), const char *opname)
Definition: mx-inlines.cc:497
Array< R > & do_mx_inplace_op(Array< R > &r, void(*op)(size_t, R *))
Definition: mx-inlines.cc:488
#define OP_CUMMINMAX_FCNN(F)
Definition: mx-inlines.cc:1320
#define OP_ROW_SHORT_CIRCUIT(F, PRED, ZERO)
Definition: mx-inlines.cc:778
octave_int< T > pow(const octave_int< T > &a, const octave_int< T > &b)
#define OP_RED_ANYC(ac, el)
Definition: mx-inlines.cc:719
void err_nonconformant(const char *op, octave_idx_type op1_len, octave_idx_type op2_len)
is false
Definition: cellfun.cc:400
bool mx_inline_any_positive(size_t n, const T *x)
Definition: mx-inlines.cc:295
void mx_inline_ge(size_t n, bool *r, const X *x, const Y *y)
Definition: mx-inlines.cc:153
void mx_inline_cummin(const T *v, T *r, octave_idx_type n)
Definition: mx-inlines.cc:1183
void mx_inline_pow(size_t n, R *r, const X *x, const Y *y)
Definition: mx-inlines.cc:413
void mx_inline_all_r(const T *v, bool *r, octave_idx_type m, octave_idx_type n)
Definition: mx-inlines.cc:773
the exceeded dimensions are set to if fewer subscripts than dimensions are the exceeding dimensions are merged into the final requested dimension For consider the following dims
Definition: sub2ind.cc:255
Array< R > do_mx_red_op(const Array< T > &src, int dim, void(*mx_red_op)(const T *, R *, octave_idx_type, octave_idx_type, octave_idx_type))
Definition: mx-inlines.cc:1520
bool mx_inline_any_nan(size_t n, const T *x)
Definition: mx-inlines.cc:256
subst_template_param< std::complex, T, double >::type mx_inline_dsum(const T *v, octave_idx_type n)
Definition: mx-inlines.cc:751
#define OP_RED_ALLR(ac, el)
Definition: mx-inlines.cc:771
#define OP_MINMAX_FCNN(F)
Definition: mx-inlines.cc:1057
#define OP_CUMMINMAX_FCN(F, OP)
Definition: mx-inlines.cc:1115
void do_inplace_bsxfun_op(Array< R > &r, const Array< X > &x, void(*op_vv)(size_t, R *, const X *), void(*op_vs)(size_t, R *, X))
Definition: bsxfun-defs.cc:140
#define OP_CUM_FCN(F, TSRC, TRES, OP)
Definition: mx-inlines.cc:844
T min(T x, T y)
Definition: lo-mappers.h:376
T mx_inline_sum(const T *v, octave_idx_type n)
Definition: mx-inlines.cc:751
void mx_inline_gt(size_t n, bool *r, const X *x, const Y *y)
Definition: mx-inlines.cc:152
Array< R > do_mx_cum_op(const Array< T > &src, int dim, void(*mx_cum_op)(const T *, R *, octave_idx_type, octave_idx_type, octave_idx_type))
Definition: mx-inlines.cc:1544
N Dimensional Array with copy-on-write semantics.
Definition: Array.h:125
void mx_inline_not_or(size_t n, bool *r, const X *x, const Y *y)
Definition: mx-inlines.cc:218
void mx_inline_cumprod(const T *v, T *r, octave_idx_type n)
Definition: mx-inlines.cc:858
void mx_inline_and(size_t n, bool *r, const X *x, const Y *y)
Definition: mx-inlines.cc:215
void mx_inline_not_and(size_t n, bool *r, const X *x, const Y *y)
Definition: mx-inlines.cc:217
void mx_inline_cumsum(const T *v, T *r, octave_idx_type n)
Definition: mx-inlines.cc:857
void mx_inline_iszero(size_t n, bool *r, const X *x)
Definition: mx-inlines.cc:70
#define DEFMXBINOPEQ(F, OP)
Definition: mx-inlines.cc:111
#define OP_RED_SUMSQ(ac, el)
Definition: mx-inlines.cc:675
double double_value(void) const
Definition: oct-inttypes.h:782
void mx_inline_or(size_t n, bool *r, const X *x, const Y *y)
Definition: mx-inlines.cc:216
Array< R > do_mx_unary_map(const Array< X > &x)
Definition: mx-inlines.cc:474
bool isfinite(double x)
Definition: lo-mappers.h:201
void get_extent_triplet(const dim_vector &dims, int &dim, octave_idx_type &l, octave_idx_type &n, octave_idx_type &u)
Definition: mx-inlines.cc:1489
Array< R > do_mx_cumminmax_op(const Array< R > &src, int dim, void(*mx_cumminmax_op)(const R *, R *, octave_idx_type, octave_idx_type, octave_idx_type))
Definition: mx-inlines.cc:1604
the element is set to zero In other the statement xample y
Definition: data.cc:5264
#define OCTAVE_LOCAL_BUFFER(T, buf, size)
Definition: oct-locbuf.h:41
Array< R > do_mx_minmax_op(const Array< R > &src, int dim, void(*mx_minmax_op)(const R *, R *, octave_idx_type, octave_idx_type, octave_idx_type))
Definition: mx-inlines.cc:1561
ColumnVector imag(const ComplexColumnVector &a)
Definition: dColVector.cc:141
for i
Definition: data.cc:5264
void mx_inline_add(size_t n, R *r, const X *x, const Y *y)
Definition: mx-inlines.cc:106
void mx_inline_any_r(const T *v, bool *r, octave_idx_type m, octave_idx_type n)
Definition: mx-inlines.cc:773
std::complex< float > FloatComplex
Definition: oct-cmplx.h:32
void mx_inline_and_not(size_t n, bool *r, const X *x, const Y *y)
Definition: mx-inlines.cc:219
void mx_inline_div(size_t n, R *r, const X *x, const Y *y)
Definition: mx-inlines.cc:109
#define OP_RED_FCNN(F, TSRC, TRES)
Definition: mx-inlines.cc:809
#define OP_RED_FCN(F, TSRC, TRES, OP, ZERO)
Definition: mx-inlines.cc:737
bool mx_inline_all(const T *v, octave_idx_type n)
Definition: mx-inlines.cc:753
#define OP_RED_SUM(ac, el)
Definition: mx-inlines.cc:673
std::complex< double > Complex
Definition: oct-cmplx.h:31
void mx_inline_div2(size_t n, R *r, const X *x)
Definition: mx-inlines.cc:128
#define DEFMXBINOP(F, OP)
Definition: mx-inlines.cc:86
void mx_inline_not(size_t n, bool *r, const X *x)
Definition: mx-inlines.cc:180
#define OP_CUM_FCNN(F, TSRC, TRES)
Definition: mx-inlines.cc:885
octave_idx_type numel(void) const
Number of elements in the array.
Definition: Array.h:366
ColumnVector real(const ComplexColumnVector &a)
Definition: dColVector.cc:135
void mx_inline_lt(size_t n, bool *r, const X *x, const Y *y)
Definition: mx-inlines.cc:150
bool mx_inline_equal(size_t n, const T1 *x, const T2 *y)
Definition: mx-inlines.cc:569
#define OP_MINMAX_FCN2(F, OP)
Definition: mx-inlines.cc:968
void op_dble_sum(double &ac, float el)
Definition: mx-inlines.cc:699
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:87
#define OP_RED_PROD(ac, el)
Definition: mx-inlines.cc:674
bool do_mx_check(const Array< T > &a, bool(*op)(size_t, const T *))
Definition: mx-inlines.cc:579
void mx_inline_not2(size_t n, bool *r)
Definition: mx-inlines.cc:186
T mx_inline_prod(const T *v, octave_idx_type n)
Definition: mx-inlines.cc:752
Array< R > do_ms_binary_op(const Array< X > &x, const Y &y, void(*op)(size_t, R *, const X *, Y))
Definition: mx-inlines.cc:521
Array< R > do_mx_unary_op(const Array< X > &x, void(*op)(size_t, R *, const X *))
Definition: mx-inlines.cc:462
void twosum_accum(T &s, T &e, const T &x)
Definition: mx-inlines.cc:1676
F77_RET_T const F77_REAL const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE &F77_RET_T const F77_DBLE F77_DBLE &F77_RET_T const F77_REAL F77_REAL &F77_RET_T const F77_DBLE * x
void mx_inline_diff(const T *v, T *r, octave_idx_type n, octave_idx_type order)
Definition: mx-inlines.cc:1380
void mx_inline_xmax(size_t n, T *r, const T *x, const T *y)
Definition: mx-inlines.cc:359
Array< R > do_bsxfun_op(const Array< X > &x, const Array< Y > &y, void(*op_vv)(size_t, R *, const X *, const Y *), void(*op_sv)(size_t, R *, X, const Y *), void(*op_vs)(size_t, R *, const X *, Y))
Definition: bsxfun-defs.cc:39
T mx_inline_count(const bool *v, octave_idx_type n)
Definition: mx-inlines.cc:752
void mx_inline_min(const T *v, T *r, octave_idx_type n)
Definition: mx-inlines.cc:961