diff liboctave/mx-inlines.cc @ 8777:724c0f46d9d4

implement cummin/cummax functions
author Jaroslav Hajek <highegg@gmail.com>
date Tue, 17 Feb 2009 11:26:29 +0100
parents d23c33ec6bd3
children ea76466605ba
line wrap: on
line diff
--- a/liboctave/mx-inlines.cc
+++ b/liboctave/mx-inlines.cc
@@ -2,6 +2,8 @@
 
 Copyright (C) 1993, 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2002,
               2003, 2004, 2005, 2006, 2007 John W. Eaton
+Copyright (C) 2009 Jaroslav Hajek
+Copyright (C) 2009 VZLU Prague
 
 This file is part of Octave.
 
@@ -656,6 +658,186 @@
 OP_MINMAX_FCNN (mx_inline_min)
 OP_MINMAX_FCNN (mx_inline_max)
 
+#define OP_CUMMINMAX_FCN(F, OP) \
+template <class T> \
+void F (const T *v, T *r, octave_idx_type n) \
+{ \
+  if (! n) return; \
+  T tmp = v[0]; \
+  octave_idx_type i = 1, j = 0; \
+  if (xisnan (tmp)) \
+    { \
+      for (; i < n && xisnan (v[i]); i++) ; \
+      for (; j < i; j++) r[j] = tmp; \
+      if (i < n) tmp = v[i]; \
+    } \
+  for (; i < n; i++) \
+    if (v[i] OP tmp) \
+      { \
+        for (; j < i; j++) r[j] = tmp; \
+        tmp = v[i]; \
+      } \
+  for (; j < i; j++) r[j] = tmp; \
+} \
+template <class T> \
+void F (const T *v, T *r, octave_idx_type *ri, octave_idx_type n) \
+{ \
+  if (! n) return; \
+  T tmp = v[0]; octave_idx_type tmpi = 0; \
+  octave_idx_type i = 1, j = 0; \
+  if (xisnan (tmp)) \
+    { \
+      for (; i < n && xisnan (v[i]); i++) ; \
+      for (; j < i; j++) { r[j] = tmp; ri[j] = tmpi; } \
+      if (i < n) { tmp = v[i]; tmpi = i; } \
+    } \
+  for (; i < n; i++) \
+    if (v[i] OP tmp) \
+      { \
+        for (; j < i; j++) { r[j] = tmp; ri[j] = tmpi; } \
+        tmp = v[i]; tmpi = i; \
+      } \
+  for (; j < i; j++) { r[j] = tmp; ri[j] = tmpi; } \
+}
+
+OP_CUMMINMAX_FCN (mx_inline_cummin, <)
+OP_CUMMINMAX_FCN (mx_inline_cummax, >)
+
+// Row reductions will be slightly complicated.  We will proceed with checks
+// for NaNs until we detect that no row will yield a NaN, in which case we
+// proceed to a faster code.
+
+#define OP_CUMMINMAX_FCN2(F, OP) \
+template <class T> \
+inline void \
+F (const T *v, T *r, octave_idx_type m, octave_idx_type n) \
+{ \
+  if (! n) return; \
+  bool nan = false; \
+  const T *r0; \
+  octave_idx_type j = 0; \
+  for (octave_idx_type i = 0; i < m; i++) \
+    {  \
+      r[i] = v[i]; \
+      if (xisnan (v[i])) nan = true;  \
+    } \
+  j++; v += m; r0 = r; r += m; \
+  while (nan && j < n) \
+    { \
+      nan = false; \
+      for (octave_idx_type i = 0; i < m; i++) \
+        {  \
+          if (xisnan (v[i])) \
+            { r[i] = r0[i]; nan = true; } \
+          else if (xisnan (r[i]) || v[i] OP r[i]) \
+            r[i] = v[i]; \
+        } \
+      j++; v += m; r0 = r; r += m; \
+    } \
+  while (j < n) \
+    { \
+      for (octave_idx_type i = 0; i < m; i++) \
+        if (v[i] OP r[i]) \
+          r[i] = v[i]; \
+        else \
+          r[i] = r0[i]; \
+      j++; v += m; r0 = r; r += m; \
+    } \
+} \
+template <class T> \
+inline void \
+F (const T *v, T *r, octave_idx_type *ri, \
+   octave_idx_type m, octave_idx_type n) \
+{ \
+  if (! n) return; \
+  bool nan = false; \
+  const T *r0; const octave_idx_type *r0i; \
+  octave_idx_type j = 0; \
+  for (octave_idx_type i = 0; i < m; i++) \
+    {  \
+      r[i] = v[i]; ri[i] = 0; \
+      if (xisnan (v[i])) nan = true;  \
+    } \
+  j++; v += m; r0 = r; r += m; r0i = ri; ri += m;  \
+  while (nan && j < n) \
+    { \
+      nan = false; \
+      for (octave_idx_type i = 0; i < m; i++) \
+        {  \
+          if (xisnan (v[i])) \
+            { r[i] = r0[i]; ri[i] = r0i[i]; nan = true; } \
+          else if (xisnan (r[i]) || v[i] OP r[i]) \
+            { r[i] = v[i]; ri[i] = j; }\
+        } \
+      j++; v += m; r0 = r; r += m; r0i = ri; ri += m;  \
+    } \
+  while (j < n) \
+    { \
+      for (octave_idx_type i = 0; i < m; i++) \
+        if (v[i] OP r[i]) \
+          { r[i] = v[i]; ri[i] = j; } \
+        else \
+          { r[i] = r0[i]; ri[i] = r0i[i]; } \
+      j++; v += m; r0 = r; r += m; r0i = ri; ri += m;  \
+    } \
+}
+
+OP_CUMMINMAX_FCN2 (mx_inline_cummin, <)
+OP_CUMMINMAX_FCN2 (mx_inline_cummax, >)
+
+#define OP_CUMMINMAX_FCNN(F) \
+template <class T> \
+inline void \
+F (const T *v, T *r, octave_idx_type l, \
+   octave_idx_type n, octave_idx_type u) \
+{ \
+  if (! n) return; \
+  if (l == 1) \
+    { \
+      for (octave_idx_type i = 0; i < u; i++) \
+        { \
+          F (v, r, n); \
+          v += n; r += n; \
+        } \
+    } \
+  else \
+    { \
+      for (octave_idx_type i = 0; i < u; i++) \
+        { \
+          F (v, r, l, n); \
+          v += l*n; \
+          r += l*n; \
+        } \
+    } \
+} \
+template <class T> \
+inline void \
+F (const T *v, T *r, octave_idx_type *ri, \
+   octave_idx_type l, octave_idx_type n, octave_idx_type u) \
+{ \
+  if (! n) return; \
+  if (l == 1) \
+    { \
+      for (octave_idx_type i = 0; i < u; i++) \
+        { \
+          F (v, r, ri, n); \
+          v += n; r += n; ri += n; \
+        } \
+    } \
+  else \
+    { \
+      for (octave_idx_type i = 0; i < u; i++) \
+        { \
+          F (v, r, ri, l, n); \
+          v += l*n; \
+          r += l*n; ri += l*n; \
+        } \
+    } \
+}
+
+OP_CUMMINMAX_FCNN (mx_inline_cummin)
+OP_CUMMINMAX_FCNN (mx_inline_cummax)
+
 // Assistant function
 
 inline void
@@ -777,6 +959,44 @@
   return ret;
 }
 
+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 *,
+                                             octave_idx_type, octave_idx_type, octave_idx_type))
+{
+  octave_idx_type l, n, u;
+  dim_vector dims = src.dims ();
+  get_extent_triplet (dims, dim, l, n, u);
+
+  ArrayType ret (dims);
+  mx_cumminmax_op (src.data (), ret.fortran_vec (), l, n, u);
+
+  return ret;
+}
+
+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 *,
+                                             octave_idx_type *,
+                                             octave_idx_type, octave_idx_type, octave_idx_type))
+{
+  octave_idx_type l, n, u;
+  dim_vector dims = src.dims ();
+  get_extent_triplet (dims, dim, l, n, u);
+
+  ArrayType ret (dims);
+  if (idx.dims () != dims) idx = Array<octave_idx_type> (dims);
+
+  mx_cumminmax_op (src.data (), ret.fortran_vec (), idx.fortran_vec (),
+                   l, n, u);
+
+  return ret;
+}
+
 #endif
 
 /*