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
oct-binmap.h
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2010-2017 VZLU Prague
4 
5 This file is part of Octave.
6 
7 Octave is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <http://www.gnu.org/licenses/>.
20 
21 */
22 
23 #if ! defined (octave_oct_binmap_h)
24 #define octave_oct_binmap_h 1
25 
26 #include "octave-config.h"
27 
28 #include "Array.h"
29 #include "Sparse.h"
30 #include "Array-util.h"
31 
32 #include "bsxfun.h"
33 
34 // This source file implements a general binary maping function for arrays.
35 // The syntax is binmap<type> (a, b, f,[name]).
36 // type denotes the expected return type of the operation.
37 // a, b, should be one of the 6 combinations:
38 //
39 // Array-Array
40 // Array-scalar
41 // scalar-Array
42 // Sparse-Sparse
43 // Sparse-scalar
44 // scalar-Sparse
45 //
46 // If both operands are nonscalar, name must be supplied. It is used
47 // as the base for error message when operands are nonconforming.
48 //
49 // The operation needs not be homogeneous, i.e., a, b and the result
50 // may be of distinct types. f can have any of the four signatures:
51 //
52 // U f (T, R)
53 // U f (const T&, R)
54 // U f (T, const R&)
55 // U f (const T&, const R&)
56 //
57 // Additionally, f can be an arbitrary functor object.
58 //
59 // octave_quit() is called at appropriate places, hence the operation
60 // is breakable.
61 
62 // The following template wrappers are provided for automatic bsxfun
63 // calls (see the function signature for do_bsxfun_op).
64 
65 template <typename R, typename X, typename Y, typename F>
67 {
68 private:
69  static F f;
70 
71 public:
72  static void
73  set_f (const F& f_in)
74  {
75  f = f_in;
76  }
77 
78  static void
79  op_mm (size_t n, R* r, const X* x , const Y* y)
80  {
81  for (size_t i = 0; i < n; i++)
82  r[i] = f (x[i], y[i]);
83  }
84 
85  static void
86  op_sm (size_t n, R* r, X x, const Y* y)
87  {
88  for (size_t i = 0; i < n; i++)
89  r[i] = f (x, y[i]);
90  }
91 
92  static void
93  op_ms (size_t n , R* r, const X* x, Y y)
94  {
95  for (size_t i = 0; i < n; i++)
96  r[i] = f (x[i], y);
97  }
98 };
99 
100 // Static init
101 template <typename R, typename X, typename Y, typename F>
103 
104 // scalar-Array
105 template <typename U, typename T, typename R, typename F>
106 Array<U>
107 binmap (const T& x, const Array<R>& ya, F fcn)
108 {
109  octave_idx_type len = ya.numel ();
110 
111  const R *y = ya.data ();
112 
113  Array<U> result (ya.dims ());
114  U *p = result.fortran_vec ();
115 
117  for (i = 0; i < len - 3; i += 4)
118  {
119  octave_quit ();
120 
121  p[i] = fcn (x, y[i]);
122  p[i+1] = fcn (x, y[i+1]);
123  p[i+2] = fcn (x, y[i+2]);
124  p[i+3] = fcn (x, y[i+3]);
125  }
126 
127  octave_quit ();
128 
129  for (; i < len; i++)
130  p[i] = fcn (x, y[i]);
131 
132  return result;
133 }
134 
135 // Array-scalar
136 template <typename U, typename T, typename R, typename F>
137 Array<U>
138 binmap (const Array<T>& xa, const R& y, F fcn)
139 {
140  octave_idx_type len = xa.numel ();
141 
142  const R *x = xa.data ();
143 
144  Array<U> result (xa.dims ());
145  U *p = result.fortran_vec ();
146 
148  for (i = 0; i < len - 3; i += 4)
149  {
150  octave_quit ();
151 
152  p[i] = fcn (x[i], y);
153  p[i+1] = fcn (x[i+1], y);
154  p[i+2] = fcn (x[i+2], y);
155  p[i+3] = fcn (x[i+3], y);
156  }
157 
158  octave_quit ();
159 
160  for (; i < len; i++)
161  p[i] = fcn (x[i], y);
162 
163  return result;
164 }
165 
166 // Array-Array (treats singletons as scalars)
167 template <typename U, typename T, typename R, typename F>
168 Array<U>
169 binmap (const Array<T>& xa, const Array<R>& ya, F fcn, const char *name)
170 {
171  dim_vector xad = xa.dims ();
172  dim_vector yad = ya.dims ();
173  if (xa.numel () == 1)
174  return binmap<U, T, R, F> (xa(0), ya, fcn);
175  else if (ya.numel () == 1)
176  return binmap<U, T, R, F> (xa, ya(0), fcn);
177  else if (xad != yad)
178  {
179  if (! is_valid_bsxfun (name, xad, yad))
180  octave::err_nonconformant (name, xad, yad);
181 
183  return do_bsxfun_op (xa, ya,
187  }
188 
189  octave_idx_type len = xa.numel ();
190 
191  const T *x = xa.data ();
192  const T *y = ya.data ();
193 
194  Array<U> result (xa.dims ());
195  U *p = result.fortran_vec ();
196 
198  for (i = 0; i < len - 3; i += 4)
199  {
200  octave_quit ();
201 
202  p[i] = fcn (x[i], y[i]);
203  p[i+1] = fcn (x[i+1], y[i+1]);
204  p[i+2] = fcn (x[i+2], y[i+2]);
205  p[i+3] = fcn (x[i+3], y[i+3]);
206  }
207 
208  octave_quit ();
209 
210  for (; i < len; i++)
211  p[i] = fcn (x[i], y[i]);
212 
213  return result;
214 }
215 
216 // scalar-Sparse
217 template <typename U, typename T, typename R, typename F>
218 Sparse<U>
219 binmap (const T& x, const Sparse<R>& ys, F fcn)
220 {
221  R yzero = R ();
222  U fz = fcn (x, yzero);
223 
224  if (fz == U ()) // Sparsity preserving fcn
225  {
226  octave_idx_type nz = ys.nnz ();
227  Sparse<U> retval (ys.rows (), ys.cols (), nz);
228  std::copy (ys.ridx (), ys.ridx () + nz, retval.ridx ());
229  std::copy (ys.cidx (), ys.cidx () + ys.cols () + 1, retval.cidx ());
230 
231  for (octave_idx_type i = 0; i < nz; i++)
232  {
233  octave_quit ();
234  // FIXME: Could keep track of whether fcn call results in a 0.
235  // If no zeroes are created could skip maybe_compress()
236  retval.xdata (i) = fcn (x, ys.data (i));
237  }
238 
239  octave_quit ();
240  retval.maybe_compress (true);
241  return retval;
242  }
243  else
244  return Sparse<U> (binmap<U, T, R, F> (x, ys.array_value (), fcn));
245 }
246 
247 // Sparse-scalar
248 template <typename U, typename T, typename R, typename F>
249 Sparse<U>
250 binmap (const Sparse<T>& xs, const R& y, F fcn)
251 {
252  T xzero = T ();
253  U fz = fcn (xzero, y);
254 
255  if (fz == U ()) // Sparsity preserving fcn
256  {
257  octave_idx_type nz = xs.nnz ();
258  Sparse<U> retval (xs.rows (), xs.cols (), nz);
259  std::copy (xs.ridx (), xs.ridx () + nz, retval.ridx ());
260  std::copy (xs.cidx (), xs.cidx () + xs.cols () + 1, retval.cidx ());
261 
262  for (octave_idx_type i = 0; i < nz; i++)
263  {
264  octave_quit ();
265  // FIXME: Could keep track of whether fcn call results in a 0.
266  // If no zeroes are created could skip maybe_compress()
267  retval.xdata (i) = fcn (xs.data (i), y);
268  }
269 
270  octave_quit ();
271  retval.maybe_compress (true);
272  return retval;
273  }
274  else
275  return Sparse<U> (binmap<U, T, R, F> (xs.array_value (), y, fcn));
276 }
277 
278 // Sparse-Sparse (treats singletons as scalars)
279 template <typename U, typename T, typename R, typename F>
280 Sparse<U>
281 binmap (const Sparse<T>& xs, const Sparse<R>& ys, F fcn, const char *name)
282 {
283  if (xs.rows () == 1 && xs.cols () == 1)
284  return binmap<U, T, R, F> (xs(0,0), ys, fcn);
285  else if (ys.rows () == 1 && ys.cols () == 1)
286  return binmap<U, T, R, F> (xs, ys(0,0), fcn);
287  else if (xs.dims () != ys.dims ())
288  octave::err_nonconformant (name, xs.dims (), ys.dims ());
289 
290  T xzero = T ();
291  R yzero = R ();
292  U fz = fcn (xzero, yzero);
293 
294  if (fz == U ())
295  {
296  // Sparsity-preserving function. Do it efficiently.
297  octave_idx_type nr = xs.rows ();
298  octave_idx_type nc = xs.cols ();
299  Sparse<T> retval (nr, nc, xs.nnz () + ys.nnz ());
300 
301  octave_idx_type nz = 0;
302  for (octave_idx_type j = 0; j < nc; j++)
303  {
304  octave_quit ();
305 
306  octave_idx_type jx = xs.cidx (j);
307  octave_idx_type jx_max = xs.cidx (j+1);
308  bool jx_lt_max = jx < jx_max;
309 
310  octave_idx_type jy = ys.cidx (j);
311  octave_idx_type jy_max = ys.cidx (j+1);
312  bool jy_lt_max = jy < jy_max;
313 
314  while (jx_lt_max || jy_lt_max)
315  {
316  if (! jy_lt_max
317  || (jx_lt_max && (xs.ridx (jx) < ys.ridx (jy))))
318  {
319  retval.xridx (nz) = xs.ridx (jx);
320  retval.xdata (nz) = fcn (xs.data (jx), yzero);
321  jx++;
322  jx_lt_max = jx < jx_max;
323  }
324  else if (! jx_lt_max
325  || (jy_lt_max && (ys.ridx (jy) < xs.ridx (jx))))
326  {
327  retval.xridx (nz) = ys.ridx (jy);
328  retval.xdata (nz) = fcn (xzero, ys.data (jy));
329  jy++;
330  jy_lt_max = jy < jy_max;
331  }
332  else
333  {
334  retval.xridx (nz) = xs.ridx (jx);
335  retval.xdata (nz) = fcn (xs.data (jx), ys.data (jy));
336  jx++;
337  jx_lt_max = jx < jx_max;
338  jy++;
339  jy_lt_max = jy < jy_max;
340  }
341  nz++;
342  }
343  retval.xcidx (j+1) = nz;
344  }
345 
346  retval.maybe_compress (true);
347  return retval;
348  }
349  else
350  return Sparse<U> (binmap<U, T, R, F> (xs.array_value (), ys.array_value (),
351  fcn, name));
352 }
353 
354 // Overloads for function pointers.
355 
356 // Signature (T, R)
357 
358 template <typename U, typename T, typename R>
359 inline Array<U>
360 binmap (const Array<T>& xa, const Array<R>& ya, U (*fcn) (T, R),
361  const char *name)
362 { return binmap<U, T, R, U (*) (T, R)> (xa, ya, fcn, name); }
363 
364 template <typename U, typename T, typename R>
365 inline Array<U>
366 binmap (const T& x, const Array<R>& ya, U (*fcn) (T, R))
367 { return binmap<U, T, R, U (*) (T, R)> (x, ya, fcn); }
368 
369 template <typename U, typename T, typename R>
370 inline Array<U>
371 binmap (const Array<T>& xa, const R& y, U (*fcn) (T, R))
372 { return binmap<U, T, R, U (*) (T, R)> (xa, y, fcn); }
373 
374 template <typename U, typename T, typename R>
375 inline Sparse<U>
376 binmap (const Sparse<T>& xa, const Sparse<R>& ya, U (*fcn) (T, R),
377  const char *name)
378 { return binmap<U, T, R, U (*) (T, R)> (xa, ya, fcn, name); }
379 
380 template <typename U, typename T, typename R>
381 inline Sparse<U>
382 binmap (const T& x, const Sparse<R>& ya, U (*fcn) (T, R))
383 { return binmap<U, T, R, U (*) (T, R)> (x, ya, fcn); }
384 
385 template <typename U, typename T, typename R>
386 inline Sparse<U>
387 binmap (const Sparse<T>& xa, const R& y, U (*fcn) (T, R))
388 { return binmap<U, T, R, U (*) (T, R)> (xa, y, fcn); }
389 
390 // Signature (const T&, const R&)
391 
392 template <typename U, typename T, typename R>
393 inline Array<U>
394 binmap (const Array<T>& xa, const Array<R>& ya, U (*fcn) (const T&, const R&),
395  const char *name)
396 { return binmap<U, T, R, U (*) (const T&, const R&)> (xa, ya, fcn, name); }
397 
398 template <typename U, typename T, typename R>
399 inline Array<U>
400 binmap (const T& x, const Array<R>& ya, U (*fcn) (const T&, const R&))
401 { return binmap<U, T, R, U (*) (const T&, const R&)> (x, ya, fcn); }
402 
403 template <typename U, typename T, typename R>
404 inline Array<U>
405 binmap (const Array<T>& xa, const R& y, U (*fcn) (const T&, const R&))
406 { return binmap<U, T, R, U (*) (const T&, const R&)> (xa, y, fcn); }
407 
408 template <typename U, typename T, typename R>
409 inline Sparse<U>
410 binmap (const Sparse<T>& xa, const Sparse<R>& ya, U (*fcn) (const T&, const R&),
411  const char *name)
412 { return binmap<U, T, R, U (*) (const T&, const R&)> (xa, ya, fcn, name); }
413 
414 template <typename U, typename T, typename R>
415 inline Sparse<U>
416 binmap (const T& x, const Sparse<R>& ya, U (*fcn) (const T&, const R&))
417 { return binmap<U, T, R, U (*) (const T&, const R&)> (x, ya, fcn); }
418 
419 template <typename U, typename T, typename R>
420 inline Sparse<U>
421 binmap (const Sparse<T>& xa, const R& y, U (*fcn) (const T&, const R&))
422 { return binmap<U, T, R, U (*) (const T&, const R&)> (xa, y, fcn); }
423 
424 // Signature (const T&, R)
425 
426 template <typename U, typename T, typename R>
427 inline Array<U>
428 binmap (const Array<T>& xa, const Array<R>& ya, U (*fcn) (const T&, R),
429  const char *name)
430 { return binmap<U, T, R, U (*) (const T&, R)> (xa, ya, fcn, name); }
431 
432 template <typename U, typename T, typename R>
433 inline Array<U>
434 binmap (const T& x, const Array<R>& ya, U (*fcn) (const T&, R))
435 { return binmap<U, T, R, U (*) (const T&, R)> (x, ya, fcn); }
436 
437 template <typename U, typename T, typename R>
438 inline Array<U>
439 binmap (const Array<T>& xa, const R& y, U (*fcn) (const T&, R))
440 { return binmap<U, T, R, U (*) (const T&, R)> (xa, y, fcn); }
441 
442 template <typename U, typename T, typename R>
443 inline Sparse<U>
444 binmap (const Sparse<T>& xa, const Sparse<R>& ya, U (*fcn) (const T&, R),
445  const char *name)
446 { return binmap<U, T, R, U (*) (const T&, R)> (xa, ya, fcn, name); }
447 
448 template <typename U, typename T, typename R>
449 inline Sparse<U>
450 binmap (const T& x, const Sparse<R>& ya, U (*fcn) (const T&, R))
451 { return binmap<U, T, R, U (*) (const T&, R)> (x, ya, fcn); }
452 
453 template <typename U, typename T, typename R>
454 inline Sparse<U>
455 binmap (const Sparse<T>& xa, const R& y, U (*fcn) (const T&, R))
456 { return binmap<U, T, R, U (*) (const T&, R)> (xa, y, fcn); }
457 
458 // Signature (T, const R&)
459 
460 template <typename U, typename T, typename R>
461 inline Array<U>
462 binmap (const Array<T>& xa, const Array<R>& ya, U (*fcn) (T, const R&),
463  const char *name)
464 { return binmap<U, T, R, U (*) (T, const R&)> (xa, ya, fcn, name); }
465 
466 template <typename U, typename T, typename R>
467 inline Array<U>
468 binmap (const T& x, const Array<R>& ya, U (*fcn) (T, const R&))
469 { return binmap<U, T, R, U (*) (T, const R&)> (x, ya, fcn); }
470 
471 template <typename U, typename T, typename R>
472 inline Array<U>
473 binmap (const Array<T>& xa, const R& y, U (*fcn) (T, const R&))
474 { return binmap<U, T, R, U (*) (T, const R&)> (xa, y, fcn); }
475 
476 template <typename U, typename T, typename R>
477 inline Sparse<U>
478 binmap (const Sparse<T>& xa, const Sparse<R>& ya, U (*fcn) (T, const R&),
479  const char *name)
480 { return binmap<U, T, R, U (*) (T, const R&)> (xa, ya, fcn, name); }
481 
482 template <typename U, typename T, typename R>
483 inline Sparse<U>
484 binmap (const T& x, const Sparse<R>& ya, U (*fcn) (T, const R&))
485 { return binmap<U, T, R, U (*) (T, const R&)> (x, ya, fcn); }
486 
487 template <typename U, typename T, typename R>
488 inline Sparse<U>
489 binmap (const Sparse<T>& xa, const R& y, U (*fcn) (T, const R&))
490 { return binmap<U, T, R, U (*) (T, const R&)> (xa, y, fcn); }
491 
492 #endif
octave_idx_type cols(void) const
Definition: Sparse.h:272
T * data(void)
Definition: Sparse.h:521
octave_idx_type rows(void) const
Definition: Sparse.h:271
dim_vector dims(void) const
Definition: Sparse.h:291
octave_idx_type numel(void) const
Number of elements in the array.
Definition: Array.h:363
static void set_f(const F &f_in)
Definition: oct-binmap.h:73
octave_idx_type * cidx(void)
Definition: Sparse.h:543
static void op_sm(size_t n, R *r, X x, const Y *y)
Definition: oct-binmap.h:86
octave_function * fcn
Definition: ov-class.cc:1743
octave_idx_type nnz(void) const
Actual number of nonzero terms.
Definition: Sparse.h:253
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
const dim_vector & dims(void) const
Return a const-reference so that dims ()(i) works efficiently.
Definition: Array.h:439
OCTAVE_EXPORT octave_value_list any number nd example oindent prints the prompt xample Pick a any number!nd example oindent and waits for the user to enter a value The string entered by the user is evaluated as an so it may be a literal a variable name
Definition: input.cc:871
const T * data(void) const
Definition: Array.h:582
void err_nonconformant(const char *op, octave_idx_type op1_len, octave_idx_type op2_len)
octave_value retval
Definition: data.cc:6294
With real return the complex result
Definition: data.cc:3375
Array< U > binmap(const T &x, const Array< R > &ya, F fcn)
Definition: oct-binmap.h:107
N Dimensional Array with copy-on-write semantics.
Definition: Array.h:126
static void op_mm(size_t n, R *r, const X *x, const Y *y)
Definition: oct-binmap.h:79
octave_idx_type * ridx(void)
Definition: Sparse.h:530
=val(i)}if ode{val(i)}occurs in table i
Definition: lookup.cc:239
p
Definition: lu.cc:138
the element is set to zero In other the statement xample y
Definition: data.cc:5342
bool is_valid_bsxfun(const std::string &name, const dim_vector &dx, const dim_vector &dy)
Definition: bsxfun.h:38
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:87
static void op_ms(size_t n, R *r, const X *x, Y y)
Definition: oct-binmap.h:93
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
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
Array< T > array_value(void) const
Definition: Sparse.cc:2675
void F(const TSRC *v, TRES *r, octave_idx_type m, octave_idx_type n)
Definition: mx-inlines.cc:719
static F f
Definition: oct-binmap.h:69