changeset 9800:ef4c4186cb47

improve some mx_inline loops
author Jaroslav Hajek <highegg@gmail.com>
date Wed, 11 Nov 2009 10:59:27 +0100
parents cfd0aa788ae1
children 13868ea67c71
files liboctave/Array.h liboctave/CNDArray.cc liboctave/ChangeLog liboctave/dNDArray.cc liboctave/fCNDArray.cc liboctave/fNDArray.cc liboctave/mx-inlines.cc
diffstat 7 files changed, 101 insertions(+), 86 deletions(-) [+]
line wrap: on
line diff
--- a/liboctave/Array.h	Tue Nov 10 23:07:25 2009 -0500
+++ b/liboctave/Array.h	Wed Nov 11 10:59:27 2009 +0100
@@ -676,25 +676,6 @@
     return result;
   }
 
-  // This is non-breakable map, suitable for fast functions. Efficiency
-  // relies on compiler's ability to inline a function pointer. This seems
-  // to be OK with recent GCC.
-  template <class U>
-  Array<U>
-  fastmap (U (*fcn) (typename ref_param<T>::type)) const
-  {
-    octave_idx_type len = length ();
-
-    const T *m = data ();
-
-    Array<U> result (dims ());
-    U *p = result.fortran_vec ();
-
-    std::transform (m, m + len, p, fcn);
-
-    return result;
-  }
-
   template <class U> friend class Array;
 
 private:
--- a/liboctave/CNDArray.cc	Tue Nov 10 23:07:25 2009 -0500
+++ b/liboctave/CNDArray.cc	Wed Nov 11 10:59:27 2009 +0100
@@ -760,33 +760,31 @@
 NDArray
 ComplexNDArray::abs (void) const
 {
-  return NDArray (mx_inline_cabs_dup (data (), length ()),
-                  dims ());
+  return do_mx_unary_map<NDArray, ComplexNDArray, std::abs> (*this);
 }
 
 boolNDArray
 ComplexNDArray::isnan (void) const
 {
-  return Array<bool> (fastmap<bool> (xisnan));
+  return do_mx_unary_map<boolNDArray, ComplexNDArray, xisnan> (*this);
 }
 
 boolNDArray
 ComplexNDArray::isinf (void) const
 {
-  return Array<bool> (fastmap<bool> (xisinf));
+  return do_mx_unary_map<boolNDArray, ComplexNDArray, xisinf> (*this);
 }
 
 boolNDArray
 ComplexNDArray::isfinite (void) const
 {
-  return Array<bool> (fastmap<bool> (xfinite));
+  return do_mx_unary_map<boolNDArray, ComplexNDArray, xfinite> (*this);
 }
 
 ComplexNDArray
 conj (const ComplexNDArray& a)
 {
-  return ComplexNDArray (mx_inline_conj_dup (a.data (), a.length ()),
-                         a.dims ());
+  return do_mx_unary_map<ComplexNDArray, ComplexNDArray, std::conj> (a);
 }
 
 ComplexNDArray&
--- a/liboctave/ChangeLog	Tue Nov 10 23:07:25 2009 -0500
+++ b/liboctave/ChangeLog	Wed Nov 11 10:59:27 2009 +0100
@@ -1,3 +1,21 @@
+2009-11-11  Jaroslav Hajek  <highegg@gmail.com>
+
+	* mx-inlines.cc (mx_inline_map): New template loop.
+	(DEFMXMAPPER): New macro.
+	(DEFMXMAPPER2): Rename from DEFMXMAPPER.
+	(do_mx_unary_map): New applier.
+	(mx_inline_real, mx_inline_complex): New loops.
+	* dNDArray.cc (NDArray::abs, NDArray::isnan, NDArray::isinf,
+	NDArray::isfinite, real, imag): Use new constructs.
+	* fNDArray.cc (FloatNDArray::abs, FloatNDArray::isnan,
+	FloatNDArray::isinf, FloatNDArray::isfinite, real, imag): Ditto.
+	* CNDArray.cc (ComplexNDArray::abs, ComplexNDArray::isnan,
+	ComplexNDArray::isinf, ComplexNDArray::isfinite, conj): Use new
+	constructs.
+	* fCNDArray.cc (FloatComplexNDArray::abs, FloatComplexNDArray::isnan,
+	FloatComplexNDArray::isinf, FloatComplexNDArray::isfinite, conj): Use
+	new constructs.
+
 2009-11-10  John W. Eaton  <jwe@octave.org>
 
 	* mx-ops, sparse-mx-ops, vx-ops b/liboctave/vx-ops:
--- a/liboctave/dNDArray.cc	Tue Nov 10 23:07:25 2009 -0500
+++ b/liboctave/dNDArray.cc	Wed Nov 11 10:59:27 2009 +0100
@@ -849,15 +849,13 @@
 NDArray
 real (const ComplexNDArray& a)
 {
-  return NDArray (mx_inline_real_dup (a.data (), a.length ()),
-                  a.dims ());
+  return do_mx_unary_op<NDArray, ComplexNDArray> (a, mx_inline_real);
 }
 
 NDArray
 imag (const ComplexNDArray& a)
 {
-  return NDArray (mx_inline_imag_dup (a.data (), a.length ()),
-                  a.dims ());
+  return do_mx_unary_op<NDArray, ComplexNDArray> (a, mx_inline_imag);
 }
 
 NDArray&
@@ -877,26 +875,25 @@
 NDArray
 NDArray::abs (void) const
 {
-  return NDArray (mx_inline_fabs_dup (data (), length ()),
-                  dims ());
+  return do_mx_unary_map<NDArray, NDArray, std::abs> (*this);
 }
 
 boolNDArray
 NDArray::isnan (void) const
 {
-  return Array<bool> (fastmap<bool> (xisnan));
+  return do_mx_unary_map<boolNDArray, NDArray, xisnan> (*this);
 }
 
 boolNDArray
 NDArray::isinf (void) const
 {
-  return Array<bool> (fastmap<bool> (xisinf));
+  return do_mx_unary_map<boolNDArray, NDArray, xisinf> (*this);
 }
 
 boolNDArray
 NDArray::isfinite (void) const
 {
-  return Array<bool> (fastmap<bool> (xfinite));
+  return do_mx_unary_map<boolNDArray, NDArray, xfinite> (*this);
 }
 
 Matrix
--- a/liboctave/fCNDArray.cc	Tue Nov 10 23:07:25 2009 -0500
+++ b/liboctave/fCNDArray.cc	Wed Nov 11 10:59:27 2009 +0100
@@ -755,33 +755,31 @@
 FloatNDArray
 FloatComplexNDArray::abs (void) const
 {
-  return FloatNDArray (mx_inline_cabs_dup (data (), length ()),
-                       dims ());
+  return do_mx_unary_map<FloatNDArray, FloatComplexNDArray, std::abs> (*this);
 }
 
 boolNDArray
 FloatComplexNDArray::isnan (void) const
 {
-  return Array<bool> (fastmap<bool> (xisnan));
+  return do_mx_unary_map<boolNDArray, FloatComplexNDArray, xisnan> (*this);
 }
 
 boolNDArray
 FloatComplexNDArray::isinf (void) const
 {
-  return Array<bool> (fastmap<bool> (xisinf));
+  return do_mx_unary_map<boolNDArray, FloatComplexNDArray, xisinf> (*this);
 }
 
 boolNDArray
 FloatComplexNDArray::isfinite (void) const
 {
-  return Array<bool> (fastmap<bool> (xfinite));
+  return do_mx_unary_map<boolNDArray, FloatComplexNDArray, xfinite> (*this);
 }
 
 FloatComplexNDArray
 conj (const FloatComplexNDArray& a)
 {
-  return FloatComplexNDArray (mx_inline_conj_dup (a.data (), a.length ()),
-                              a.dims ());
+  return do_mx_unary_map<FloatComplexNDArray, FloatComplexNDArray, std::conj> (a);
 }
 
 FloatComplexNDArray&
--- a/liboctave/fNDArray.cc	Tue Nov 10 23:07:25 2009 -0500
+++ b/liboctave/fNDArray.cc	Wed Nov 11 10:59:27 2009 +0100
@@ -807,15 +807,13 @@
 FloatNDArray
 real (const FloatComplexNDArray& a)
 {
-  return FloatNDArray (mx_inline_real_dup (a.data (), a.length ()),
-                       a.dims ());
+  return do_mx_unary_op<FloatNDArray, FloatComplexNDArray> (a, mx_inline_real);
 }
 
 FloatNDArray
 imag (const FloatComplexNDArray& a)
 {
-  return FloatNDArray (mx_inline_imag_dup (a.data (), a.length ()),
-                       a.dims ());
+  return do_mx_unary_op<FloatNDArray, FloatComplexNDArray> (a, mx_inline_imag);
 }
 
 FloatNDArray&
@@ -835,26 +833,25 @@
 FloatNDArray
 FloatNDArray::abs (void) const
 {
-  return FloatNDArray (mx_inline_fabs_dup (data (), length ()),
-                       dims ());
+  return do_mx_unary_map<FloatNDArray, FloatNDArray, std::abs> (*this);
 }
 
 boolNDArray
 FloatNDArray::isnan (void) const
 {
-  return Array<bool> (fastmap<bool> (xisnan));
+  return do_mx_unary_map<boolNDArray, FloatNDArray, xisnan> (*this);
 }
 
 boolNDArray
 FloatNDArray::isinf (void) const
 {
-  return Array<bool> (fastmap<bool> (xisinf));
+  return do_mx_unary_map<boolNDArray, FloatNDArray, xisinf> (*this);
 }
 
 boolNDArray
 FloatNDArray::isfinite (void) const
 {
-  return Array<bool> (fastmap<bool> (xfinite));
+  return do_mx_unary_map<boolNDArray, FloatNDArray, xfinite> (*this);
 }
 
 FloatMatrix
--- a/liboctave/mx-inlines.cc	Tue Nov 10 23:07:25 2009 -0500
+++ b/liboctave/mx-inlines.cc	Wed Nov 11 10:59:27 2009 +0100
@@ -197,8 +197,20 @@
 DEFMXANYNAN(Complex)
 DEFMXANYNAN(FloatComplex)
 
+#define DEFMXMAPPER(F, FUN) \
+template <class T> \
+inline void F (size_t n, T *r, const T *x) \
+{ for (size_t i = 0; i < n; i++) r[i] = FUN (x[i]); }
+
+template<class T>
+inline void mx_inline_real (size_t n, T *r, const std::complex<T>* x)
+{ for (size_t i = 0; i < n; i++) r[i] = x[i].real (); }
+template<class T>
+inline void mx_inline_imag (size_t n, T *r, const std::complex<T>* x)
+{ for (size_t i = 0; i < n; i++) r[i] = x[i].imag (); }
+
 // Pairwise minimums/maximums
-#define DEFMXMAPPER(F, FUN) \
+#define DEFMXMAPPER2(F, FUN) \
 template <class T> \
 inline void F (size_t n, T *r, const T *x, const T *y) \
 { for (size_t i = 0; i < n; i++) r[i] = FUN (x[i], y[i]); } \
@@ -209,35 +221,54 @@
 inline void F (size_t n, T *r, T x, const T *y) \
 { for (size_t i = 0; i < n; i++) r[i] = FUN (x, y[i]); }
 
-DEFMXMAPPER (mx_inline_xmin, xmin)
-DEFMXMAPPER (mx_inline_xmax, xmax)
+DEFMXMAPPER2 (mx_inline_xmin, xmin)
+DEFMXMAPPER2 (mx_inline_xmax, xmax)
 
-#define DEFMXLOCALMAPPER(F, FUN, T) \
-static void F (size_t n, T *r, const T *x, const T *y) \
-{ for (size_t i = 0; i < n; i++) r[i] = FUN (x[i], y[i]); } \
-static void F (size_t n, T *r, const T *x, T y) \
-{ for (size_t i = 0; i < n; i++) r[i] = FUN (x[i], y); } \
-static void F (size_t n, T *r, T x, const T *y) \
-{ for (size_t i = 0; i < n; i++) r[i] = FUN (x, y[i]); }
+// Arbitrary function appliers. The function is a template parameter to enable
+// inlining.
+template <class R, class X, R fun (X x)>
+inline void mx_inline_map (size_t n, R *r, const X *x)
+{ for (size_t i = 0; i < n; i++) r[i] = fun (x[i]); }
+
+template <class R, class X, R fun (const X& x)>
+inline void mx_inline_map (size_t n, R *r, const X *x)
+{ for (size_t i = 0; i < n; i++) r[i] = fun (x[i]); }
 
 // Appliers. Since these call the operation just once, we pass it as
 // a pointer, to allow the compiler reduce number of instances.
 
+#define AELEMT(ARRAY) typename ARRAY::element_type
 template <class RNDA, class XNDA>
 inline RNDA 
 do_mx_unary_op (const XNDA& x,
-                void (*op) (size_t, typename RNDA::element_type *,
-                            const typename XNDA::element_type *))
+                void (*op) (size_t, AELEMT(RNDA) *,
+                            const AELEMT(XNDA) *))
 {
   RNDA r (x.dims ());
   op (r.length (), r.fortran_vec (), x.data ());
   return r;
 }
 
+// Shortcuts for applying mx_inline_map.
+
+template <class RNDA, class XNDA, AELEMT(RNDA) fun (AELEMT(XNDA))>
+inline RNDA 
+do_mx_unary_map (const XNDA& x)
+{
+  return do_mx_unary_op<RNDA, XNDA> (x, mx_inline_map<AELEMT(RNDA), AELEMT(XNDA), fun>);
+}
+
+template <class RNDA, class XNDA, AELEMT(RNDA) fun (const AELEMT(XNDA)&)>
+inline RNDA 
+do_mx_unary_map (const XNDA& x)
+{
+  return do_mx_unary_op<RNDA, XNDA> (x, mx_inline_map<AELEMT(RNDA), AELEMT(XNDA), fun>);
+}
+
 template <class RNDA>
 inline RNDA&
 do_mx_inplace_op (RNDA& r,
-                  void (*op) (size_t, typename RNDA::element_type *))
+                  void (*op) (size_t, AELEMT(RNDA) *))
 {
   op (r.numel (), r.fortran_vec ());
   return r;
@@ -247,9 +278,9 @@
 template <class RNDA, class XNDA, class YNDA>
 inline RNDA 
 do_mm_binary_op (const XNDA& x, const YNDA& y,
-                 void (*op) (size_t, typename RNDA::element_type *,
-                             const typename XNDA::element_type *,
-                             const typename YNDA::element_type *),
+                 void (*op) (size_t, AELEMT(RNDA) *,
+                             const AELEMT(XNDA) *,
+                             const AELEMT(YNDA) *),
                  const char *opname)
 {
   dim_vector dx = x.dims (), dy = y.dims ();
@@ -269,8 +300,8 @@
 template <class RNDA, class XNDA, class YS>
 inline RNDA 
 do_ms_binary_op (const XNDA& x, const YS& y,
-                 void (*op) (size_t, typename RNDA::element_type *,
-                             const typename XNDA::element_type *, YS))
+                 void (*op) (size_t, AELEMT(RNDA) *,
+                             const AELEMT(XNDA) *, YS))
 {
   RNDA r (x.dims ());
   op (r.length (), r.fortran_vec (), x.data (), y);
@@ -280,8 +311,8 @@
 template <class RNDA, class XS, class YNDA>
 inline RNDA 
 do_sm_binary_op (const XS& x, const YNDA& y,
-                 void (*op) (size_t, typename RNDA::element_type *, XS,
-                             const typename YNDA::element_type *))
+                 void (*op) (size_t, AELEMT(RNDA) *, XS,
+                             const AELEMT(YNDA) *))
 {
   RNDA r (y.dims ());
   op (r.length (), r.fortran_vec (), x, y.data ());
@@ -291,8 +322,8 @@
 template <class RNDA, class XNDA>
 inline RNDA& 
 do_mm_inplace_op (RNDA& r, const XNDA& x,
-                  void (*op) (size_t, typename RNDA::element_type *,
-                              const typename XNDA::element_type *),
+                  void (*op) (size_t, AELEMT(RNDA) *,
+                              const AELEMT(XNDA) *),
                   const char *opname)
 {
   dim_vector dr = r.dims (), dx = x.dims ();
@@ -306,7 +337,7 @@
 template <class RNDA, class XS>
 inline RNDA& 
 do_ms_inplace_op (RNDA& r, const XS& x,
-                  void (*op) (size_t, typename RNDA::element_type *, XS))
+                  void (*op) (size_t, AELEMT(RNDA) *, XS))
 {
   op (r.length (), r.fortran_vec (), x);
   return r;
@@ -1084,7 +1115,7 @@
 template <class ArrayType, class T>
 inline ArrayType
 do_mx_red_op (const Array<T>& src, int dim,
-              void (*mx_red_op) (const T *, typename ArrayType::element_type *,
+              void (*mx_red_op) (const T *, AELEMT(ArrayType) *,
                                  octave_idx_type, octave_idx_type, octave_idx_type))
 {
   octave_idx_type l, n, u;
@@ -1108,7 +1139,7 @@
 template <class ArrayType, class T>
 inline ArrayType
 do_mx_cum_op (const Array<T>& src, int dim,
-              void (*mx_cum_op) (const T *, typename ArrayType::element_type *,
+              void (*mx_cum_op) (const T *, AELEMT(ArrayType) *,
                                  octave_idx_type, octave_idx_type, octave_idx_type))
 {
   octave_idx_type l, n, u;
@@ -1125,8 +1156,7 @@
 template <class ArrayType>
 inline ArrayType
 do_mx_minmax_op (const ArrayType& src, int dim,
-                 void (*mx_minmax_op) (const typename ArrayType::element_type *, 
-                                       typename ArrayType::element_type *,
+                 void (*mx_minmax_op) (const AELEMT(ArrayType) *, AELEMT(ArrayType) *,
                                        octave_idx_type, octave_idx_type, octave_idx_type))
 {
   octave_idx_type l, n, u;
@@ -1146,8 +1176,7 @@
 template <class ArrayType>
 inline ArrayType
 do_mx_minmax_op (const ArrayType& src, Array<octave_idx_type>& idx, int dim,
-                 void (*mx_minmax_op) (const typename ArrayType::element_type *, 
-                                       typename ArrayType::element_type *,
+                 void (*mx_minmax_op) (const AELEMT(ArrayType) *, AELEMT(ArrayType) *,
                                        octave_idx_type *,
                                        octave_idx_type, octave_idx_type, octave_idx_type))
 {
@@ -1171,8 +1200,7 @@
 template <class ArrayType>
 inline ArrayType
 do_mx_cumminmax_op (const ArrayType& src, int dim,
-                    void (*mx_cumminmax_op) (const typename ArrayType::element_type *, 
-                                             typename ArrayType::element_type *,
+                    void (*mx_cumminmax_op) (const AELEMT(ArrayType) *, AELEMT(ArrayType) *,
                                              octave_idx_type, octave_idx_type, octave_idx_type))
 {
   octave_idx_type l, n, u;
@@ -1188,8 +1216,7 @@
 template <class ArrayType>
 inline ArrayType
 do_mx_cumminmax_op (const ArrayType& src, Array<octave_idx_type>& idx, int dim,
-                    void (*mx_cumminmax_op) (const typename ArrayType::element_type *, 
-                                             typename ArrayType::element_type *,
+                    void (*mx_cumminmax_op) (const AELEMT(ArrayType) *, AELEMT(ArrayType) *,
                                              octave_idx_type *,
                                              octave_idx_type, octave_idx_type, octave_idx_type))
 {
@@ -1209,8 +1236,7 @@
 template <class ArrayType>
 inline ArrayType
 do_mx_diff_op (const ArrayType& src, int dim, octave_idx_type order,
-               void (*mx_diff_op) (const typename ArrayType::element_type *, 
-                                   typename ArrayType::element_type *,
+               void (*mx_diff_op) (const AELEMT(ArrayType) *, AELEMT(ArrayType) *,
                                    octave_idx_type, octave_idx_type, octave_idx_type,
                                    octave_idx_type))
 {