00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #if !defined (octave_mx_inlines_h)
00026 #define octave_mx_inlines_h 1
00027
00028 #include <cstddef>
00029 #include <cmath>
00030 #include <memory>
00031
00032 #include "quit.h"
00033
00034 #include "oct-cmplx.h"
00035 #include "oct-locbuf.h"
00036 #include "oct-inttypes.h"
00037 #include "Array.h"
00038 #include "Array-util.h"
00039
00040 #include "bsxfun.h"
00041
00042
00043
00044 template <class R, class S>
00045 inline void mx_inline_fill (size_t n, R *r, S s) throw ()
00046 { for (size_t i = 0; i < n; i++) r[i] = s; }
00047
00048 #define DEFMXUNOP(F, OP) \
00049 template <class R, class X> \
00050 inline void F (size_t n, R *r, const X *x) throw () \
00051 { for (size_t i = 0; i < n; i++) r[i] = OP x[i]; }
00052
00053 DEFMXUNOP (mx_inline_uminus, -)
00054
00055 #define DEFMXUNOPEQ(F, OP) \
00056 template <class R> \
00057 inline void F (size_t n, R *r) throw () \
00058 { for (size_t i = 0; i < n; i++) r[i] = OP r[i]; }
00059
00060 DEFMXUNOPEQ (mx_inline_uminus2, -)
00061
00062 #define DEFMXUNBOOLOP(F, OP) \
00063 template <class X> \
00064 inline void F (size_t n, bool *r, const X *x) throw () \
00065 { const X zero = X(); for (size_t i = 0; i < n; i++) r[i] = x[i] OP zero; }
00066
00067 DEFMXUNBOOLOP (mx_inline_iszero, ==)
00068 DEFMXUNBOOLOP (mx_inline_notzero, !=)
00069
00070 #define DEFMXBINOP(F, OP) \
00071 template <class R, class X, class Y> \
00072 inline void F (size_t n, R *r, const X *x, const Y *y) throw () \
00073 { for (size_t i = 0; i < n; i++) r[i] = x[i] OP y[i]; } \
00074 template <class R, class X, class Y> \
00075 inline void F (size_t n, R *r, const X *x, Y y) throw () \
00076 { for (size_t i = 0; i < n; i++) r[i] = x[i] OP y; } \
00077 template <class R, class X, class Y> \
00078 inline void F (size_t n, R *r, X x, const Y *y) throw () \
00079 { for (size_t i = 0; i < n; i++) r[i] = x OP y[i]; }
00080
00081 DEFMXBINOP (mx_inline_add, +)
00082 DEFMXBINOP (mx_inline_sub, -)
00083 DEFMXBINOP (mx_inline_mul, *)
00084 DEFMXBINOP (mx_inline_div, /)
00085
00086 #define DEFMXBINOPEQ(F, OP) \
00087 template <class R, class X> \
00088 inline void F (size_t n, R *r, const X *x) throw () \
00089 { for (size_t i = 0; i < n; i++) r[i] OP x[i]; } \
00090 template <class R, class X> \
00091 inline void F (size_t n, R *r, X x) throw () \
00092 { for (size_t i = 0; i < n; i++) r[i] OP x; }
00093
00094 DEFMXBINOPEQ (mx_inline_add2, +=)
00095 DEFMXBINOPEQ (mx_inline_sub2, -=)
00096 DEFMXBINOPEQ (mx_inline_mul2, *=)
00097 DEFMXBINOPEQ (mx_inline_div2, /=)
00098
00099 #define DEFMXCMPOP(F, OP) \
00100 template <class X, class Y> \
00101 inline void F (size_t n, bool *r, const X *x, const Y *y) throw () \
00102 { for (size_t i = 0; i < n; i++) r[i] = x[i] OP y[i]; } \
00103 template <class X, class Y> \
00104 inline void F (size_t n, bool *r, const X *x, Y y) throw () \
00105 { for (size_t i = 0; i < n; i++) r[i] = x[i] OP y; } \
00106 template <class X, class Y> \
00107 inline void F (size_t n, bool *r, X x, const Y *y) throw () \
00108 { for (size_t i = 0; i < n; i++) r[i] = x OP y[i]; }
00109
00110 DEFMXCMPOP (mx_inline_lt, <)
00111 DEFMXCMPOP (mx_inline_le, <=)
00112 DEFMXCMPOP (mx_inline_gt, >)
00113 DEFMXCMPOP (mx_inline_ge, >=)
00114 DEFMXCMPOP (mx_inline_eq, ==)
00115 DEFMXCMPOP (mx_inline_ne, !=)
00116
00117
00118 template <class T> inline bool logical_value (T x) { return x; }
00119 template <class T> inline bool logical_value (const std::complex<T>& x)
00120 { return x.real () != 0 || x.imag () != 0; }
00121 template <class T> inline bool logical_value (const octave_int<T>& x)
00122 { return x.value (); }
00123
00124 template <class X>
00125 void mx_inline_not (size_t n, bool *r, const X* x) throw ()
00126 {
00127 for (size_t i = 0; i < n; i++)
00128 r[i] = ! logical_value (x[i]);
00129 }
00130
00131 inline void mx_inline_not2 (size_t n, bool *r) throw ()
00132 {
00133 for (size_t i = 0; i < n; i++) r[i] = ! r[i];
00134 }
00135
00136 #define DEFMXBOOLOP(F, NOT1, OP, NOT2) \
00137 template <class X, class Y> \
00138 inline void F (size_t n, bool *r, const X *x, const Y *y) throw () \
00139 { \
00140 for (size_t i = 0; i < n; i++) \
00141 r[i] = (NOT1 logical_value (x[i])) OP (NOT2 logical_value (y[i])); \
00142 } \
00143 template <class X, class Y> \
00144 inline void F (size_t n, bool *r, const X *x, Y y) throw () \
00145 { \
00146 const bool yy = (NOT2 logical_value (y)); \
00147 for (size_t i = 0; i < n; i++) \
00148 r[i] = (NOT1 logical_value (x[i])) OP yy; \
00149 } \
00150 template <class X, class Y> \
00151 inline void F (size_t n, bool *r, X x, const Y *y) throw () \
00152 { \
00153 const bool xx = (NOT1 logical_value (x)); \
00154 for (size_t i = 0; i < n; i++) \
00155 r[i] = xx OP (NOT2 logical_value (y[i])); \
00156 }
00157
00158 DEFMXBOOLOP (mx_inline_and, , &, )
00159 DEFMXBOOLOP (mx_inline_or, , |, )
00160 DEFMXBOOLOP (mx_inline_not_and, !, &, )
00161 DEFMXBOOLOP (mx_inline_not_or, !, |, )
00162 DEFMXBOOLOP (mx_inline_and_not, , &, !)
00163 DEFMXBOOLOP (mx_inline_or_not, , |, !)
00164
00165 #define DEFMXBOOLOPEQ(F, OP) \
00166 template <class X> \
00167 inline void F (size_t n, bool *r, const X *x) throw () \
00168 { \
00169 for (size_t i = 0; i < n; i++) \
00170 r[i] OP logical_value (x[i]); \
00171 } \
00172 template <class X> \
00173 inline void F (size_t n, bool *r, X x) throw () \
00174 { for (size_t i = 0; i < n; i++) r[i] OP x; }
00175
00176 DEFMXBOOLOPEQ (mx_inline_and2, &=)
00177 DEFMXBOOLOPEQ (mx_inline_or2, |=)
00178
00179 template <class T>
00180 inline bool
00181 mx_inline_any_nan (size_t n, const T* x) throw ()
00182 {
00183 for (size_t i = 0; i < n; i++)
00184 {
00185 if (xisnan (x[i]))
00186 return true;
00187 }
00188
00189 return false;
00190 }
00191
00192 template <class T>
00193 inline bool
00194 mx_inline_all_finite (size_t n, const T* x) throw ()
00195 {
00196 for (size_t i = 0; i < n; i++)
00197 {
00198 if (! xfinite (x[i]))
00199 return false;
00200 }
00201
00202 return true;
00203 }
00204
00205 template <class T>
00206 inline bool
00207 mx_inline_any_negative (size_t n, const T* x) throw ()
00208 {
00209 for (size_t i = 0; i < n; i++)
00210 {
00211 if (x[i] < 0)
00212 return true;
00213 }
00214
00215 return false;
00216 }
00217
00218 template <class T>
00219 inline bool
00220 mx_inline_any_positive (size_t n, const T* x) throw ()
00221 {
00222 for (size_t i = 0; i < n; i++)
00223 {
00224 if (x[i] > 0)
00225 return true;
00226 }
00227
00228 return false;
00229 }
00230
00231 template<class T>
00232 inline bool
00233 mx_inline_all_real (size_t n, const std::complex<T>* x) throw ()
00234 {
00235 for (size_t i = 0; i < n; i++)
00236 {
00237 if (x[i].imag () != 0)
00238 return false;
00239 }
00240
00241 return true;
00242 }
00243
00244 #define DEFMXMAPPER(F, FUN) \
00245 template <class T> \
00246 inline void F (size_t n, T *r, const T *x) throw () \
00247 { for (size_t i = 0; i < n; i++) r[i] = FUN (x[i]); }
00248
00249 template<class T>
00250 inline void mx_inline_real (size_t n, T *r, const std::complex<T>* x) throw ()
00251 { for (size_t i = 0; i < n; i++) r[i] = x[i].real (); }
00252 template<class T>
00253 inline void mx_inline_imag (size_t n, T *r, const std::complex<T>* x) throw ()
00254 { for (size_t i = 0; i < n; i++) r[i] = x[i].imag (); }
00255
00256
00257 #define DEFMXMAPPER2(F, FUN) \
00258 template <class T> \
00259 inline void F (size_t n, T *r, const T *x, const T *y) throw () \
00260 { for (size_t i = 0; i < n; i++) r[i] = FUN (x[i], y[i]); } \
00261 template <class T> \
00262 inline void F (size_t n, T *r, const T *x, T y) throw () \
00263 { for (size_t i = 0; i < n; i++) r[i] = FUN (x[i], y); } \
00264 template <class T> \
00265 inline void F (size_t n, T *r, T x, const T *y) throw () \
00266 { for (size_t i = 0; i < n; i++) r[i] = FUN (x, y[i]); }
00267
00268 DEFMXMAPPER2 (mx_inline_xmin, xmin)
00269 DEFMXMAPPER2 (mx_inline_xmax, xmax)
00270
00271
00272 #define DEFMINMAXSPEC(T, F, OP) \
00273 template <> \
00274 inline void F<T> (size_t n, T *r, const T *x, T y) throw () \
00275 { \
00276 if (xisnan (y)) \
00277 std::memcpy (r, x, n * sizeof (T)); \
00278 else \
00279 for (size_t i = 0; i < n; i++) r[i] = (x[i] OP y) ? x[i] : y; \
00280 } \
00281 template <> \
00282 inline void F<T> (size_t n, T *r, T x, const T *y) throw () \
00283 { \
00284 if (xisnan (x)) \
00285 std::memcpy (r, y, n * sizeof (T)); \
00286 else \
00287 for (size_t i = 0; i < n; i++) r[i] = (y[i] OP x) ? y[i] : x; \
00288 }
00289
00290 DEFMINMAXSPEC (double, mx_inline_xmin, <=)
00291 DEFMINMAXSPEC (double, mx_inline_xmax, >=)
00292 DEFMINMAXSPEC (float, mx_inline_xmin, <=)
00293 DEFMINMAXSPEC (float, mx_inline_xmax, >=)
00294
00295
00296 #define DEFMXMAPPER2X(F, FUN) \
00297 template <class R, class X, class Y> \
00298 inline void F (size_t n, R *r, const X *x, const Y *y) throw () \
00299 { for (size_t i = 0; i < n; i++) r[i] = FUN (x[i], y[i]); } \
00300 template <class R, class X, class Y> \
00301 inline void F (size_t n, R *r, const X *x, Y y) throw () \
00302 { for (size_t i = 0; i < n; i++) r[i] = FUN (x[i], y); } \
00303 template <class R, class X, class Y> \
00304 inline void F (size_t n, R *r, X x, const Y *y) throw () \
00305 { for (size_t i = 0; i < n; i++) r[i] = FUN (x, y[i]); }
00306
00307
00308
00309 using std::pow;
00310 DEFMXMAPPER2X (mx_inline_pow, pow)
00311
00312
00313
00314 template <class R, class X, R fun (X x)>
00315 inline void mx_inline_map (size_t n, R *r, const X *x) throw ()
00316 { for (size_t i = 0; i < n; i++) r[i] = fun (x[i]); }
00317
00318 template <class R, class X, R fun (const X& x)>
00319 inline void mx_inline_map (size_t n, R *r, const X *x) throw ()
00320 { for (size_t i = 0; i < n; i++) r[i] = fun (x[i]); }
00321
00322
00323
00324
00325 template <class R, class X>
00326 inline Array<R>
00327 do_mx_unary_op (const Array<X>& x,
00328 void (*op) (size_t, R *, const X *) throw ())
00329 {
00330 Array<R> r (x.dims ());
00331 op (r.numel (), r.fortran_vec (), x.data ());
00332 return r;
00333 }
00334
00335
00336
00337 template <class R, class X, R fun (X)>
00338 inline Array<R>
00339 do_mx_unary_map (const Array<X>& x)
00340 {
00341 return do_mx_unary_op<R, X> (x, mx_inline_map<R, X, fun>);
00342 }
00343
00344 template <class R, class X, R fun (const X&)>
00345 inline Array<R>
00346 do_mx_unary_map (const Array<X>& x)
00347 {
00348 return do_mx_unary_op<R, X> (x, mx_inline_map<R, X, fun>);
00349 }
00350
00351 template <class R>
00352 inline Array<R>&
00353 do_mx_inplace_op (Array<R>& r,
00354 void (*op) (size_t, R *) throw ())
00355 {
00356 op (r.numel (), r.fortran_vec ());
00357 return r;
00358 }
00359
00360 template <class R, class X, class Y>
00361 inline Array<R>
00362 do_mm_binary_op (const Array<X>& x, const Array<Y>& y,
00363 void (*op) (size_t, R *, const X *, const Y *) throw (),
00364 void (*op1) (size_t, R *, X, const Y *) throw (),
00365 void (*op2) (size_t, R *, const X *, Y) throw (),
00366 const char *opname)
00367 {
00368 dim_vector dx = x.dims (), dy = y.dims ();
00369 if (dx == dy)
00370 {
00371 Array<R> r (dx);
00372 op (r.length (), r.fortran_vec (), x.data (), y.data ());
00373 return r;
00374 }
00375 else if (is_valid_bsxfun (opname, dx, dy))
00376 {
00377 return do_bsxfun_op (x, y, op, op1, op2);
00378 }
00379 else
00380 {
00381 gripe_nonconformant (opname, dx, dy);
00382 return Array<R> ();
00383 }
00384 }
00385
00386 template <class R, class X, class Y>
00387 inline Array<R>
00388 do_ms_binary_op (const Array<X>& x, const Y& y,
00389 void (*op) (size_t, R *, const X *, Y) throw ())
00390 {
00391 Array<R> r (x.dims ());
00392 op (r.length (), r.fortran_vec (), x.data (), y);
00393 return r;
00394 }
00395
00396 template <class R, class X, class Y>
00397 inline Array<R>
00398 do_sm_binary_op (const X& x, const Array<Y>& y,
00399 void (*op) (size_t, R *, X, const Y *) throw ())
00400 {
00401 Array<R> r (y.dims ());
00402 op (r.length (), r.fortran_vec (), x, y.data ());
00403 return r;
00404 }
00405
00406 template <class R, class X>
00407 inline Array<R>&
00408 do_mm_inplace_op (Array<R>& r, const Array<X>& x,
00409 void (*op) (size_t, R *, const X *) throw (),
00410 void (*op1) (size_t, R *, X) throw (),
00411 const char *opname)
00412 {
00413 dim_vector dr = r.dims (), dx = x.dims ();
00414 if (dr == dx)
00415 {
00416 op (r.length (), r.fortran_vec (), x.data ());
00417 }
00418 else if (is_valid_inplace_bsxfun (opname, dr, dx))
00419 {
00420 do_inplace_bsxfun_op (r, x, op, op1);
00421 }
00422 else
00423 gripe_nonconformant (opname, dr, dx);
00424 return r;
00425 }
00426
00427 template <class R, class X>
00428 inline Array<R>&
00429 do_ms_inplace_op (Array<R>& r, const X& x,
00430 void (*op) (size_t, R *, X) throw ())
00431 {
00432 op (r.length (), r.fortran_vec (), x);
00433 return r;
00434 }
00435
00436 template <class T1, class T2>
00437 inline bool
00438 mx_inline_equal (size_t n, const T1 *x, const T2 *y) throw ()
00439 {
00440 for (size_t i = 0; i < n; i++)
00441 if (x[i] != y[i])
00442 return false;
00443 return true;
00444 }
00445
00446 template <class T>
00447 inline bool
00448 do_mx_check (const Array<T>& a,
00449 bool (*op) (size_t, const T *) throw ())
00450 {
00451 return op (a.numel (), a.data ());
00452 }
00453
00454
00455
00456 template <class T>
00457 inline T cabsq (const std::complex<T>& c)
00458 { return c.real () * c.real () + c.imag () * c.imag (); }
00459
00460
00461 template <class T>
00462 inline bool xis_true (T x) { return x; }
00463 template <class T>
00464 inline bool xis_false (T x) { return ! x; }
00465
00466 template <class T>
00467 inline bool xis_true (const octave_int<T>& x) { return x.value (); }
00468 template <class T>
00469 inline bool xis_false (const octave_int<T>& x) { return ! x.value (); }
00470
00471 inline bool xis_true (double x) { return ! xisnan (x) && x != 0.0; }
00472 inline bool xis_false (double x) { return x == 0.0; }
00473 inline bool xis_true (float x) { return ! xisnan (x) && x != 0.0f; }
00474 inline bool xis_false (float x) { return x == 0.0f; }
00475
00476 inline bool xis_true (const Complex& x) { return ! xisnan (x) && x != 0.0; }
00477 inline bool xis_false (const Complex& x) { return x == 0.0; }
00478 inline bool xis_true (const FloatComplex& x) { return ! xisnan (x) && x != 0.0f; }
00479 inline bool xis_false (const FloatComplex& x) { return x == 0.0f; }
00480
00481 #define OP_RED_SUM(ac, el) ac += el
00482 #define OP_RED_PROD(ac, el) ac *= el
00483 #define OP_RED_SUMSQ(ac, el) ac += el*el
00484 #define OP_RED_SUMSQC(ac, el) ac += cabsq (el)
00485
00486 inline void op_dble_sum(double& ac, float el)
00487 { ac += el; }
00488 inline void op_dble_sum(Complex& ac, const FloatComplex& el)
00489 { ac += el; }
00490 template <class T>
00491 inline void op_dble_sum(double& ac, const octave_int<T>& el)
00492 { ac += el.double_value (); }
00493
00494
00495 #define OP_RED_ANYC(ac, el) if (xis_true (el)) { ac = true; break; } else continue
00496 #define OP_RED_ALLC(ac, el) if (xis_false (el)) { ac = false; break; } else continue
00497
00498 #define OP_RED_FCN(F, TSRC, TRES, OP, ZERO) \
00499 template <class T> \
00500 inline TRES \
00501 F (const TSRC* v, octave_idx_type n) \
00502 { \
00503 TRES ac = ZERO; \
00504 for (octave_idx_type i = 0; i < n; i++) \
00505 OP(ac, v[i]); \
00506 return ac; \
00507 }
00508
00509 #define PROMOTE_DOUBLE(T) typename subst_template_param<std::complex, T, double>::type
00510
00511 OP_RED_FCN (mx_inline_sum, T, T, OP_RED_SUM, 0)
00512 OP_RED_FCN (mx_inline_dsum, T, PROMOTE_DOUBLE(T), op_dble_sum, 0.0)
00513 OP_RED_FCN (mx_inline_count, bool, T, OP_RED_SUM, 0)
00514 OP_RED_FCN (mx_inline_prod, T, T, OP_RED_PROD, 1)
00515 OP_RED_FCN (mx_inline_sumsq, T, T, OP_RED_SUMSQ, 0)
00516 OP_RED_FCN (mx_inline_sumsq, std::complex<T>, T, OP_RED_SUMSQC, 0)
00517 OP_RED_FCN (mx_inline_any, T, bool, OP_RED_ANYC, false)
00518 OP_RED_FCN (mx_inline_all, T, bool, OP_RED_ALLC, true)
00519
00520
00521 #define OP_RED_FCN2(F, TSRC, TRES, OP, ZERO) \
00522 template <class T> \
00523 inline void \
00524 F (const TSRC* v, TRES *r, octave_idx_type m, octave_idx_type n) \
00525 { \
00526 for (octave_idx_type i = 0; i < m; i++) \
00527 r[i] = ZERO; \
00528 for (octave_idx_type j = 0; j < n; j++) \
00529 { \
00530 for (octave_idx_type i = 0; i < m; i++) \
00531 OP(r[i], v[i]); \
00532 v += m; \
00533 } \
00534 }
00535
00536 OP_RED_FCN2 (mx_inline_sum, T, T, OP_RED_SUM, 0)
00537 OP_RED_FCN2 (mx_inline_dsum, T, PROMOTE_DOUBLE(T), op_dble_sum, 0.0)
00538 OP_RED_FCN2 (mx_inline_count, bool, T, OP_RED_SUM, 0)
00539 OP_RED_FCN2 (mx_inline_prod, T, T, OP_RED_PROD, 1)
00540 OP_RED_FCN2 (mx_inline_sumsq, T, T, OP_RED_SUMSQ, 0)
00541 OP_RED_FCN2 (mx_inline_sumsq, std::complex<T>, T, OP_RED_SUMSQC, 0)
00542
00543 #define OP_RED_ANYR(ac, el) ac |= xis_true (el)
00544 #define OP_RED_ALLR(ac, el) ac &= xis_true (el)
00545
00546 OP_RED_FCN2 (mx_inline_any_r, T, bool, OP_RED_ANYR, false)
00547 OP_RED_FCN2 (mx_inline_all_r, T, bool, OP_RED_ALLR, true)
00548
00549
00550
00551
00552
00553 #define OP_ROW_SHORT_CIRCUIT(F, PRED, ZERO) \
00554 template <class T> \
00555 inline void \
00556 F (const T* v, bool *r, octave_idx_type m, octave_idx_type n) \
00557 { \
00558 if (n <= 8) \
00559 return F ## _r (v, r, m, n); \
00560 \
00561 \
00562 OCTAVE_LOCAL_BUFFER (octave_idx_type, iact, m); \
00563 for (octave_idx_type i = 0; i < m; i++) iact[i] = i; \
00564 octave_idx_type nact = m; \
00565 for (octave_idx_type j = 0; j < n; j++) \
00566 { \
00567 octave_idx_type k = 0; \
00568 for (octave_idx_type i = 0; i < nact; i++) \
00569 { \
00570 octave_idx_type ia = iact[i]; \
00571 if (! PRED (v[ia])) \
00572 iact[k++] = ia; \
00573 } \
00574 nact = k; \
00575 v += m; \
00576 } \
00577 for (octave_idx_type i = 0; i < m; i++) r[i] = ! ZERO; \
00578 for (octave_idx_type i = 0; i < nact; i++) r[iact[i]] = ZERO; \
00579 }
00580
00581 OP_ROW_SHORT_CIRCUIT (mx_inline_any, xis_true, false)
00582 OP_ROW_SHORT_CIRCUIT (mx_inline_all, xis_false, true)
00583
00584 #define OP_RED_FCNN(F, TSRC, TRES) \
00585 template <class T> \
00586 inline void \
00587 F (const TSRC *v, TRES *r, octave_idx_type l, \
00588 octave_idx_type n, octave_idx_type u) \
00589 { \
00590 if (l == 1) \
00591 { \
00592 for (octave_idx_type i = 0; i < u; i++) \
00593 { \
00594 r[i] = F<T> (v, n); \
00595 v += n; \
00596 } \
00597 } \
00598 else \
00599 { \
00600 for (octave_idx_type i = 0; i < u; i++) \
00601 { \
00602 F (v, r, l, n); \
00603 v += l*n; \
00604 r += l; \
00605 } \
00606 } \
00607 }
00608
00609 OP_RED_FCNN (mx_inline_sum, T, T)
00610 OP_RED_FCNN (mx_inline_dsum, T, PROMOTE_DOUBLE(T))
00611 OP_RED_FCNN (mx_inline_count, bool, T)
00612 OP_RED_FCNN (mx_inline_prod, T, T)
00613 OP_RED_FCNN (mx_inline_sumsq, T, T)
00614 OP_RED_FCNN (mx_inline_sumsq, std::complex<T>, T)
00615 OP_RED_FCNN (mx_inline_any, T, bool)
00616 OP_RED_FCNN (mx_inline_all, T, bool)
00617
00618 #define OP_CUM_FCN(F, TSRC, TRES, OP) \
00619 template <class T> \
00620 inline void \
00621 F (const TSRC *v, TRES *r, octave_idx_type n) \
00622 { \
00623 if (n) \
00624 { \
00625 TRES t = r[0] = v[0]; \
00626 for (octave_idx_type i = 1; i < n; i++) \
00627 r[i] = t = t OP v[i]; \
00628 } \
00629 }
00630
00631 OP_CUM_FCN (mx_inline_cumsum, T, T, +)
00632 OP_CUM_FCN (mx_inline_cumprod, T, T, *)
00633 OP_CUM_FCN (mx_inline_cumcount, bool, T, +)
00634
00635 #define OP_CUM_FCN2(F, TSRC, TRES, OP) \
00636 template <class T> \
00637 inline void \
00638 F (const TSRC *v, TRES *r, octave_idx_type m, octave_idx_type n) \
00639 { \
00640 if (n) \
00641 { \
00642 for (octave_idx_type i = 0; i < m; i++) \
00643 r[i] = v[i]; \
00644 const T *r0 = r; \
00645 for (octave_idx_type j = 1; j < n; j++) \
00646 { \
00647 r += m; v += m; \
00648 for (octave_idx_type i = 0; i < m; i++) \
00649 r[i] = r0[i] OP v[i]; \
00650 r0 += m; \
00651 } \
00652 } \
00653 }
00654
00655 OP_CUM_FCN2 (mx_inline_cumsum, T, T, +)
00656 OP_CUM_FCN2 (mx_inline_cumprod, T, T, *)
00657 OP_CUM_FCN2 (mx_inline_cumcount, bool, T, +)
00658
00659 #define OP_CUM_FCNN(F, TSRC, TRES) \
00660 template <class T> \
00661 inline void \
00662 F (const TSRC *v, TRES *r, octave_idx_type l, \
00663 octave_idx_type n, octave_idx_type u) \
00664 { \
00665 if (l == 1) \
00666 { \
00667 for (octave_idx_type i = 0; i < u; i++) \
00668 { \
00669 F (v, r, n); \
00670 v += n; r += n; \
00671 } \
00672 } \
00673 else \
00674 { \
00675 for (octave_idx_type i = 0; i < u; i++) \
00676 { \
00677 F (v, r, l, n); \
00678 v += l*n; \
00679 r += l*n; \
00680 } \
00681 } \
00682 }
00683
00684 OP_CUM_FCNN (mx_inline_cumsum, T, T)
00685 OP_CUM_FCNN (mx_inline_cumprod, T, T)
00686 OP_CUM_FCNN (mx_inline_cumcount, bool, T)
00687
00688 #define OP_MINMAX_FCN(F, OP) \
00689 template <class T> \
00690 void F (const T *v, T *r, octave_idx_type n) \
00691 { \
00692 if (! n) return; \
00693 T tmp = v[0]; \
00694 octave_idx_type i = 1; \
00695 if (xisnan (tmp)) \
00696 { \
00697 for (; i < n && xisnan (v[i]); i++) ; \
00698 if (i < n) tmp = v[i]; \
00699 } \
00700 for (; i < n; i++) \
00701 if (v[i] OP tmp) tmp = v[i]; \
00702 *r = tmp; \
00703 } \
00704 template <class T> \
00705 void F (const T *v, T *r, octave_idx_type *ri, octave_idx_type n) \
00706 { \
00707 if (! n) return; \
00708 T tmp = v[0]; \
00709 octave_idx_type tmpi = 0; \
00710 octave_idx_type i = 1; \
00711 if (xisnan (tmp)) \
00712 { \
00713 for (; i < n && xisnan (v[i]); i++) ; \
00714 if (i < n) { tmp = v[i]; tmpi = i; } \
00715 } \
00716 for (; i < n; i++) \
00717 if (v[i] OP tmp) { tmp = v[i]; tmpi = i; }\
00718 *r = tmp; \
00719 *ri = tmpi; \
00720 }
00721
00722 OP_MINMAX_FCN (mx_inline_min, <)
00723 OP_MINMAX_FCN (mx_inline_max, >)
00724
00725
00726
00727
00728
00729 #define OP_MINMAX_FCN2(F, OP) \
00730 template <class T> \
00731 inline void \
00732 F (const T *v, T *r, octave_idx_type m, octave_idx_type n) \
00733 { \
00734 if (! n) return; \
00735 bool nan = false; \
00736 octave_idx_type j = 0; \
00737 for (octave_idx_type i = 0; i < m; i++) \
00738 { \
00739 r[i] = v[i]; \
00740 if (xisnan (v[i])) nan = true; \
00741 } \
00742 j++; v += m; \
00743 while (nan && j < n) \
00744 { \
00745 nan = false; \
00746 for (octave_idx_type i = 0; i < m; i++) \
00747 { \
00748 if (xisnan (v[i])) \
00749 nan = true; \
00750 else if (xisnan (r[i]) || v[i] OP r[i]) \
00751 r[i] = v[i]; \
00752 } \
00753 j++; v += m; \
00754 } \
00755 while (j < n) \
00756 { \
00757 for (octave_idx_type i = 0; i < m; i++) \
00758 if (v[i] OP r[i]) r[i] = v[i]; \
00759 j++; v += m; \
00760 } \
00761 } \
00762 template <class T> \
00763 inline void \
00764 F (const T *v, T *r, octave_idx_type *ri, \
00765 octave_idx_type m, octave_idx_type n) \
00766 { \
00767 if (! n) return; \
00768 bool nan = false; \
00769 octave_idx_type j = 0; \
00770 for (octave_idx_type i = 0; i < m; i++) \
00771 { \
00772 r[i] = v[i]; ri[i] = j; \
00773 if (xisnan (v[i])) nan = true; \
00774 } \
00775 j++; v += m; \
00776 while (nan && j < n) \
00777 { \
00778 nan = false; \
00779 for (octave_idx_type i = 0; i < m; i++) \
00780 { \
00781 if (xisnan (v[i])) \
00782 nan = true; \
00783 else if (xisnan (r[i]) || v[i] OP r[i]) \
00784 { r[i] = v[i]; ri[i] = j; } \
00785 } \
00786 j++; v += m; \
00787 } \
00788 while (j < n) \
00789 { \
00790 for (octave_idx_type i = 0; i < m; i++) \
00791 if (v[i] OP r[i]) \
00792 { r[i] = v[i]; ri[i] = j; } \
00793 j++; v += m; \
00794 } \
00795 }
00796
00797 OP_MINMAX_FCN2 (mx_inline_min, <)
00798 OP_MINMAX_FCN2 (mx_inline_max, >)
00799
00800 #define OP_MINMAX_FCNN(F) \
00801 template <class T> \
00802 inline void \
00803 F (const T *v, T *r, octave_idx_type l, \
00804 octave_idx_type n, octave_idx_type u) \
00805 { \
00806 if (! n) return; \
00807 if (l == 1) \
00808 { \
00809 for (octave_idx_type i = 0; i < u; i++) \
00810 { \
00811 F (v, r, n); \
00812 v += n; r++; \
00813 } \
00814 } \
00815 else \
00816 { \
00817 for (octave_idx_type i = 0; i < u; i++) \
00818 { \
00819 F (v, r, l, n); \
00820 v += l*n; \
00821 r += l; \
00822 } \
00823 } \
00824 } \
00825 template <class T> \
00826 inline void \
00827 F (const T *v, T *r, octave_idx_type *ri, \
00828 octave_idx_type l, octave_idx_type n, octave_idx_type u) \
00829 { \
00830 if (! n) return; \
00831 if (l == 1) \
00832 { \
00833 for (octave_idx_type i = 0; i < u; i++) \
00834 { \
00835 F (v, r, ri, n); \
00836 v += n; r++; ri++; \
00837 } \
00838 } \
00839 else \
00840 { \
00841 for (octave_idx_type i = 0; i < u; i++) \
00842 { \
00843 F (v, r, ri, l, n); \
00844 v += l*n; \
00845 r += l; ri += l; \
00846 } \
00847 } \
00848 }
00849
00850 OP_MINMAX_FCNN (mx_inline_min)
00851 OP_MINMAX_FCNN (mx_inline_max)
00852
00853 #define OP_CUMMINMAX_FCN(F, OP) \
00854 template <class T> \
00855 void F (const T *v, T *r, octave_idx_type n) \
00856 { \
00857 if (! n) return; \
00858 T tmp = v[0]; \
00859 octave_idx_type i = 1, j = 0; \
00860 if (xisnan (tmp)) \
00861 { \
00862 for (; i < n && xisnan (v[i]); i++) ; \
00863 for (; j < i; j++) r[j] = tmp; \
00864 if (i < n) tmp = v[i]; \
00865 } \
00866 for (; i < n; i++) \
00867 if (v[i] OP tmp) \
00868 { \
00869 for (; j < i; j++) r[j] = tmp; \
00870 tmp = v[i]; \
00871 } \
00872 for (; j < i; j++) r[j] = tmp; \
00873 } \
00874 template <class T> \
00875 void F (const T *v, T *r, octave_idx_type *ri, octave_idx_type n) \
00876 { \
00877 if (! n) return; \
00878 T tmp = v[0]; octave_idx_type tmpi = 0; \
00879 octave_idx_type i = 1, j = 0; \
00880 if (xisnan (tmp)) \
00881 { \
00882 for (; i < n && xisnan (v[i]); i++) ; \
00883 for (; j < i; j++) { r[j] = tmp; ri[j] = tmpi; } \
00884 if (i < n) { tmp = v[i]; tmpi = i; } \
00885 } \
00886 for (; i < n; i++) \
00887 if (v[i] OP tmp) \
00888 { \
00889 for (; j < i; j++) { r[j] = tmp; ri[j] = tmpi; } \
00890 tmp = v[i]; tmpi = i; \
00891 } \
00892 for (; j < i; j++) { r[j] = tmp; ri[j] = tmpi; } \
00893 }
00894
00895 OP_CUMMINMAX_FCN (mx_inline_cummin, <)
00896 OP_CUMMINMAX_FCN (mx_inline_cummax, >)
00897
00898
00899
00900
00901
00902 #define OP_CUMMINMAX_FCN2(F, OP) \
00903 template <class T> \
00904 inline void \
00905 F (const T *v, T *r, octave_idx_type m, octave_idx_type n) \
00906 { \
00907 if (! n) return; \
00908 bool nan = false; \
00909 const T *r0; \
00910 octave_idx_type j = 0; \
00911 for (octave_idx_type i = 0; i < m; i++) \
00912 { \
00913 r[i] = v[i]; \
00914 if (xisnan (v[i])) nan = true; \
00915 } \
00916 j++; v += m; r0 = r; r += m; \
00917 while (nan && j < n) \
00918 { \
00919 nan = false; \
00920 for (octave_idx_type i = 0; i < m; i++) \
00921 { \
00922 if (xisnan (v[i])) \
00923 { r[i] = r0[i]; nan = true; } \
00924 else if (xisnan (r0[i]) || v[i] OP r0[i]) \
00925 r[i] = v[i]; \
00926 } \
00927 j++; v += m; r0 = r; r += m; \
00928 } \
00929 while (j < n) \
00930 { \
00931 for (octave_idx_type i = 0; i < m; i++) \
00932 if (v[i] OP r0[i]) \
00933 r[i] = v[i]; \
00934 else \
00935 r[i] = r0[i]; \
00936 j++; v += m; r0 = r; r += m; \
00937 } \
00938 } \
00939 template <class T> \
00940 inline void \
00941 F (const T *v, T *r, octave_idx_type *ri, \
00942 octave_idx_type m, octave_idx_type n) \
00943 { \
00944 if (! n) return; \
00945 bool nan = false; \
00946 const T *r0; const octave_idx_type *r0i; \
00947 octave_idx_type j = 0; \
00948 for (octave_idx_type i = 0; i < m; i++) \
00949 { \
00950 r[i] = v[i]; ri[i] = 0; \
00951 if (xisnan (v[i])) nan = true; \
00952 } \
00953 j++; v += m; r0 = r; r += m; r0i = ri; ri += m; \
00954 while (nan && j < n) \
00955 { \
00956 nan = false; \
00957 for (octave_idx_type i = 0; i < m; i++) \
00958 { \
00959 if (xisnan (v[i])) \
00960 { r[i] = r0[i]; ri[i] = r0i[i]; nan = true; } \
00961 else if (xisnan (r0[i]) || v[i] OP r0[i]) \
00962 { r[i] = v[i]; ri[i] = j; }\
00963 } \
00964 j++; v += m; r0 = r; r += m; r0i = ri; ri += m; \
00965 } \
00966 while (j < n) \
00967 { \
00968 for (octave_idx_type i = 0; i < m; i++) \
00969 if (v[i] OP r0[i]) \
00970 { r[i] = v[i]; ri[i] = j; } \
00971 else \
00972 { r[i] = r0[i]; ri[i] = r0i[i]; } \
00973 j++; v += m; r0 = r; r += m; r0i = ri; ri += m; \
00974 } \
00975 }
00976
00977 OP_CUMMINMAX_FCN2 (mx_inline_cummin, <)
00978 OP_CUMMINMAX_FCN2 (mx_inline_cummax, >)
00979
00980 #define OP_CUMMINMAX_FCNN(F) \
00981 template <class T> \
00982 inline void \
00983 F (const T *v, T *r, octave_idx_type l, \
00984 octave_idx_type n, octave_idx_type u) \
00985 { \
00986 if (! n) return; \
00987 if (l == 1) \
00988 { \
00989 for (octave_idx_type i = 0; i < u; i++) \
00990 { \
00991 F (v, r, n); \
00992 v += n; r += n; \
00993 } \
00994 } \
00995 else \
00996 { \
00997 for (octave_idx_type i = 0; i < u; i++) \
00998 { \
00999 F (v, r, l, n); \
01000 v += l*n; \
01001 r += l*n; \
01002 } \
01003 } \
01004 } \
01005 template <class T> \
01006 inline void \
01007 F (const T *v, T *r, octave_idx_type *ri, \
01008 octave_idx_type l, octave_idx_type n, octave_idx_type u) \
01009 { \
01010 if (! n) return; \
01011 if (l == 1) \
01012 { \
01013 for (octave_idx_type i = 0; i < u; i++) \
01014 { \
01015 F (v, r, ri, n); \
01016 v += n; r += n; ri += n; \
01017 } \
01018 } \
01019 else \
01020 { \
01021 for (octave_idx_type i = 0; i < u; i++) \
01022 { \
01023 F (v, r, ri, l, n); \
01024 v += l*n; \
01025 r += l*n; ri += l*n; \
01026 } \
01027 } \
01028 }
01029
01030 OP_CUMMINMAX_FCNN (mx_inline_cummin)
01031 OP_CUMMINMAX_FCNN (mx_inline_cummax)
01032
01033 template <class T>
01034 void mx_inline_diff (const T *v, T *r, octave_idx_type n,
01035 octave_idx_type order)
01036 {
01037 switch (order)
01038 {
01039 case 1:
01040 for (octave_idx_type i = 0; i < n-1; i++)
01041 r[i] = v[i+1] - v[i];
01042 break;
01043 case 2:
01044 if (n > 1)
01045 {
01046 T lst = v[1] - v[0];
01047 for (octave_idx_type i = 0; i < n-2; i++)
01048 {
01049 T dif = v[i+2] - v[i+1];
01050 r[i] = dif - lst;
01051 lst = dif;
01052 }
01053 }
01054 break;
01055 default:
01056 {
01057 OCTAVE_LOCAL_BUFFER (T, buf, n-1);
01058
01059 for (octave_idx_type i = 0; i < n-1; i++)
01060 buf[i] = v[i+1] - v[i];
01061
01062 for (octave_idx_type o = 2; o <= order; o++)
01063 {
01064 for (octave_idx_type i = 0; i < n-o; i++)
01065 buf[i] = buf[i+1] - buf[i];
01066 }
01067
01068 for (octave_idx_type i = 0; i < n-order; i++)
01069 r[i] = buf[i];
01070 }
01071 }
01072 }
01073
01074 template <class T>
01075 void mx_inline_diff (const T *v, T *r,
01076 octave_idx_type m, octave_idx_type n,
01077 octave_idx_type order)
01078 {
01079 switch (order)
01080 {
01081 case 1:
01082 for (octave_idx_type i = 0; i < m*(n-1); i++)
01083 r[i] = v[i+m] - v[i];
01084 break;
01085 case 2:
01086 for (octave_idx_type i = 0; i < n-2; i++)
01087 {
01088 for (octave_idx_type j = i*m; j < i*m+m; j++)
01089 r[j] = (v[j+m+m] - v[j+m]) - (v[j+m] - v[j]);
01090 }
01091 break;
01092 default:
01093 {
01094 OCTAVE_LOCAL_BUFFER (T, buf, n-1);
01095
01096 for (octave_idx_type j = 0; j < m; j++)
01097 {
01098 for (octave_idx_type i = 0; i < n-1; i++)
01099 buf[i] = v[i*m+j+m] - v[i*m+j];
01100
01101 for (octave_idx_type o = 2; o <= order; o++)
01102 {
01103 for (octave_idx_type i = 0; i < n-o; i++)
01104 buf[i] = buf[i+1] - buf[i];
01105 }
01106
01107 for (octave_idx_type i = 0; i < n-order; i++)
01108 r[i*m+j] = buf[i];
01109 }
01110 }
01111 }
01112 }
01113
01114 template <class T>
01115 inline void
01116 mx_inline_diff (const T *v, T *r,
01117 octave_idx_type l, octave_idx_type n, octave_idx_type u,
01118 octave_idx_type order)
01119 {
01120 if (! n) return;
01121 if (l == 1)
01122 {
01123 for (octave_idx_type i = 0; i < u; i++)
01124 {
01125 mx_inline_diff (v, r, n, order);
01126 v += n; r += n-order;
01127 }
01128 }
01129 else
01130 {
01131 for (octave_idx_type i = 0; i < u; i++)
01132 {
01133 mx_inline_diff (v, r, l, n, order);
01134 v += l*n;
01135 r += l*(n-order);
01136 }
01137 }
01138 }
01139
01140
01141
01142 inline void
01143 get_extent_triplet (const dim_vector& dims, int& dim,
01144 octave_idx_type& l, octave_idx_type& n,
01145 octave_idx_type& u)
01146 {
01147 octave_idx_type ndims = dims.length ();
01148 if (dim >= ndims)
01149 {
01150 l = dims.numel ();
01151 n = 1;
01152 u = 1;
01153 }
01154 else
01155 {
01156 if (dim < 0)
01157 dim = dims.first_non_singleton ();
01158
01159
01160 l = 1, n = dims(dim), u = 1;
01161 for (octave_idx_type i = 0; i < dim; i++)
01162 l *= dims (i);
01163 for (octave_idx_type i = dim + 1; i < ndims; i++)
01164 u *= dims (i);
01165 }
01166 }
01167
01168
01169
01170
01171
01172 template <class R, class T>
01173 inline Array<R>
01174 do_mx_red_op (const Array<T>& src, int dim,
01175 void (*mx_red_op) (const T *, R *, octave_idx_type,
01176 octave_idx_type, octave_idx_type))
01177 {
01178 octave_idx_type l, n, u;
01179 dim_vector dims = src.dims ();
01180
01181 if (dims.length () == 2 && dims(0) == 0 && dims(1) == 0)
01182 dims (1) = 1;
01183
01184 get_extent_triplet (dims, dim, l, n, u);
01185
01186
01187 if (dim < dims.length ()) dims(dim) = 1;
01188 dims.chop_trailing_singletons ();
01189
01190 Array<R> ret (dims);
01191 mx_red_op (src.data (), ret.fortran_vec (), l, n, u);
01192
01193 return ret;
01194 }
01195
01196 template <class R, class T>
01197 inline Array<R>
01198 do_mx_cum_op (const Array<T>& src, int dim,
01199 void (*mx_cum_op) (const T *, R *, octave_idx_type,
01200 octave_idx_type, octave_idx_type))
01201 {
01202 octave_idx_type l, n, u;
01203 dim_vector dims = src.dims ();
01204 get_extent_triplet (dims, dim, l, n, u);
01205
01206
01207 Array<R> ret (dims);
01208 mx_cum_op (src.data (), ret.fortran_vec (), l, n, u);
01209
01210 return ret;
01211 }
01212
01213 template <class R>
01214 inline Array<R>
01215 do_mx_minmax_op (const Array<R>& src, int dim,
01216 void (*mx_minmax_op) (const R *, R *, octave_idx_type,
01217 octave_idx_type, octave_idx_type))
01218 {
01219 octave_idx_type l, n, u;
01220 dim_vector dims = src.dims ();
01221 get_extent_triplet (dims, dim, l, n, u);
01222
01223
01224 if (dim < dims.length () && dims(dim) != 0) dims(dim) = 1;
01225 dims.chop_trailing_singletons ();
01226
01227 Array<R> ret (dims);
01228 mx_minmax_op (src.data (), ret.fortran_vec (), l, n, u);
01229
01230 return ret;
01231 }
01232
01233 template <class R>
01234 inline Array<R>
01235 do_mx_minmax_op (const Array<R>& src, Array<octave_idx_type>& idx, int dim,
01236 void (*mx_minmax_op) (const R *, R *, octave_idx_type *,
01237 octave_idx_type, octave_idx_type, octave_idx_type))
01238 {
01239 octave_idx_type l, n, u;
01240 dim_vector dims = src.dims ();
01241 get_extent_triplet (dims, dim, l, n, u);
01242
01243
01244 if (dim < dims.length () && dims(dim) != 0) dims(dim) = 1;
01245 dims.chop_trailing_singletons ();
01246
01247 Array<R> ret (dims);
01248 if (idx.dims () != dims) idx = Array<octave_idx_type> (dims);
01249
01250 mx_minmax_op (src.data (), ret.fortran_vec (), idx.fortran_vec (),
01251 l, n, u);
01252
01253 return ret;
01254 }
01255
01256 template <class R>
01257 inline Array<R>
01258 do_mx_cumminmax_op (const Array<R>& src, int dim,
01259 void (*mx_cumminmax_op) (const R *, R *, octave_idx_type,
01260 octave_idx_type, octave_idx_type))
01261 {
01262 octave_idx_type l, n, u;
01263 dim_vector dims = src.dims ();
01264 get_extent_triplet (dims, dim, l, n, u);
01265
01266 Array<R> ret (dims);
01267 mx_cumminmax_op (src.data (), ret.fortran_vec (), l, n, u);
01268
01269 return ret;
01270 }
01271
01272 template <class R>
01273 inline Array<R>
01274 do_mx_cumminmax_op (const Array<R>& src, Array<octave_idx_type>& idx, int dim,
01275 void (*mx_cumminmax_op) (const R *, R *, octave_idx_type *,
01276 octave_idx_type, octave_idx_type, octave_idx_type))
01277 {
01278 octave_idx_type l, n, u;
01279 dim_vector dims = src.dims ();
01280 get_extent_triplet (dims, dim, l, n, u);
01281
01282 Array<R> ret (dims);
01283 if (idx.dims () != dims) idx = Array<octave_idx_type> (dims);
01284
01285 mx_cumminmax_op (src.data (), ret.fortran_vec (), idx.fortran_vec (),
01286 l, n, u);
01287
01288 return ret;
01289 }
01290
01291 template <class R>
01292 inline Array<R>
01293 do_mx_diff_op (const Array<R>& src, int dim, octave_idx_type order,
01294 void (*mx_diff_op) (const R *, R *,
01295 octave_idx_type, octave_idx_type, octave_idx_type,
01296 octave_idx_type))
01297 {
01298 octave_idx_type l, n, u;
01299 if (order <= 0)
01300 return src;
01301
01302 dim_vector dims = src.dims ();
01303
01304 get_extent_triplet (dims, dim, l, n, u);
01305 if (dim >= dims.length ())
01306 dims.resize (dim+1, 1);
01307
01308 if (dims(dim) <= order)
01309 {
01310 dims (dim) = 0;
01311 return Array<R> (dims);
01312 }
01313 else
01314 {
01315 dims(dim) -= order;
01316 }
01317
01318 Array<R> ret (dims);
01319 mx_diff_op (src.data (), ret.fortran_vec (), l, n, u, order);
01320
01321 return ret;
01322 }
01323
01324
01325
01326
01327
01328
01329 template <class T>
01330 inline void twosum_accum (T& s, T& e,
01331 const T& x)
01332 {
01333 T s1 = s + x, t = s1 - s, e1 = (s - (s1 - t)) + (x - t);
01334 s = s1;
01335 e += e1;
01336 }
01337
01338 template <class T>
01339 inline T
01340 mx_inline_xsum (const T *v, octave_idx_type n)
01341 {
01342 T s = 0, e = 0;
01343 for (octave_idx_type i = 0; i < n; i++)
01344 twosum_accum (s, e, v[i]);
01345
01346 return s + e;
01347 }
01348
01349 template <class T>
01350 inline void
01351 mx_inline_xsum (const T *v, T *r,
01352 octave_idx_type m, octave_idx_type n)
01353 {
01354 OCTAVE_LOCAL_BUFFER (T, e, m);
01355 for (octave_idx_type i = 0; i < m; i++)
01356 e[i] = r[i] = T ();
01357
01358 for (octave_idx_type j = 0; j < n; j++)
01359 {
01360 for (octave_idx_type i = 0; i < m; i++)
01361 twosum_accum (r[i], e[i], v[i]);
01362
01363 v += m;
01364 }
01365
01366 for (octave_idx_type i = 0; i < m; i++)
01367 r[i] += e[i];
01368 }
01369
01370 OP_RED_FCNN (mx_inline_xsum, T, T)
01371
01372 #endif