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