Mercurial > hg > octave-lyh
diff liboctave/mx-inlines.cc @ 9513:9f870f73ab7d
implement built-in diff
author | Jaroslav Hajek <highegg@gmail.com> |
---|---|
date | Tue, 11 Aug 2009 09:08:12 +0200 |
parents | e31d47f2c9bb |
children | 3d6a9aea2aea |
line wrap: on
line diff
--- a/liboctave/mx-inlines.cc +++ b/liboctave/mx-inlines.cc @@ -844,6 +844,114 @@ OP_CUMMINMAX_FCNN (mx_inline_cummin) OP_CUMMINMAX_FCNN (mx_inline_cummax) +template <class T> +void mx_inline_diff (const T *v, T *r, octave_idx_type n, + octave_idx_type order) +{ + switch (order) + { + case 1: + for (octave_idx_type i = 0; i < n-1; i++) + r[i] = v[i+1] - v[i]; + break; + case 2: + { + T lst; + if (n > 1) + lst = v[1] - v[0]; + for (octave_idx_type i = 0; i < n-2; i++) + { + T dif = v[i+2] - v[i+1]; + r[i] = dif - lst; + lst = dif; + } + } + break; + default: + { + OCTAVE_LOCAL_BUFFER (T, buf, n-1); + + for (octave_idx_type i = 0; i < n-1; i++) + buf[i] = v[i+1] - v[i]; + + for (octave_idx_type o = 2; o <= order; o++) + { + for (octave_idx_type i = 0; i < n-o; i++) + buf[i] = buf[i+1] - buf[i]; + } + + for (octave_idx_type i = 0; i < n-order; i++) + r[i] = buf[i]; + } + } +} + +template <class T> +void mx_inline_diff (const T *v, T *r, + octave_idx_type m, octave_idx_type n, + octave_idx_type order) +{ + switch (order) + { + case 1: + for (octave_idx_type i = 0; i < m*(n-1); i++) + r[i] = v[i+m] - v[i]; + break; + case 2: + for (octave_idx_type i = 0; i < n-2; i++) + { + for (octave_idx_type j = i*m; j < i*m+m; j++) + r[j] = (v[j+m+m] - v[j+m]) + (v[j+m] - v[j]); + } + break; + default: + { + OCTAVE_LOCAL_BUFFER (T, buf, n-1); + + for (octave_idx_type j = 0; j < m; j++) + { + for (octave_idx_type i = 0; i < n-1; i++) + buf[i] = v[i*m+j+m] - v[i*m+j]; + + for (octave_idx_type o = 2; o <= order; o++) + { + for (octave_idx_type i = 0; i < n-o; i++) + buf[i] = buf[i+1] - buf[i]; + } + + for (octave_idx_type i = 0; i < n-order; i++) + r[i*m+j] = buf[i]; + } + } + } +} + +template <class T> +inline void +mx_inline_diff (const T *v, T *r, + octave_idx_type l, octave_idx_type n, octave_idx_type u, + octave_idx_type order) +{ + if (! n) return; + if (l == 1) + { + for (octave_idx_type i = 0; i < u; i++) + { + mx_inline_diff (v, r, n, order); + v += n; r += n-order; + } + } + else + { + for (octave_idx_type i = 0; i < u; i++) + { + mx_inline_diff (v, r, l, n, order); + v += l*n; + r += l*(n-order); + } + } +} + // Assistant function inline void @@ -861,10 +969,8 @@ else { if (dim < 0) - { - // find first non-singleton dim - for (dim = 0; dims(dim) == 1 && dim < ndims - 1; dim++) ; - } + dim = dims.first_non_singleton (); + // calculate extent triplet. l = 1, n = dims(dim), u = 1; for (octave_idx_type i = 0; i < dim; i++) @@ -1003,6 +1109,40 @@ return ret; } +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 *, + octave_idx_type, octave_idx_type, octave_idx_type, + octave_idx_type)) +{ + octave_idx_type l, n, u; + if (order <= 0) + return src; + + dim_vector dims = src.dims (); + + get_extent_triplet (dims, dim, l, n, u); + if (dim >= dims.length ()) + dims.resize (dim+1, 1); + + if (dims(dim) <= order) + { + dims (dim) = 0; + return ArrayType (dims); + } + else + { + dims(dim) -= order; + } + + ArrayType ret (dims); + mx_diff_op (src.data (), ret.fortran_vec (), l, n, u, order); + + return ret; +} + #endif /*