GNU Octave  4.0.0
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-2015 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 "Array.h"
27 #include "Sparse.h"
28 #include "Array-util.h"
29 
30 #include "bsxfun.h"
31 
32 // This source file implements a general binary maping function for
33 // arrays. The syntax is binmap<type> (a, b, f,[name]). type denotes
34 // the expected return type of the operation. a, b, should be one of
35 // the 6 combinations:
36 //
37 // Array-Array
38 // Array-scalar
39 // scalar-Array
40 // Sparse-Sparse
41 // Sparse-scalar
42 // scalar-Sparse
43 //
44 // If both operands are nonscalar, name must be supplied. It is used
45 // as the base for error message when operands are nonconforming.
46 //
47 // The operation needs not be homogeneous, i.e. a, b and the result
48 // may be of distinct types. f can have any of the four signatures:
49 //
50 // U f (T, R)
51 // U f (const T&, R)
52 // U f (T, const R&)
53 // U f (const T&, const R&)
54 //
55 // Additionally, f can be an arbitrary functor object.
56 //
57 // octave_quit() is called at appropriate places, hence the operation
58 // is breakable.
59 
60 // The following template wrappers are provided for automatic bsxfun
61 // calls (see the function signature for do_bsxfun_op).
62 
63 template<typename R, typename X, typename Y, typename F>
65 {
66 private:
67  static F f;
68 
69 public:
70  static void
71  set_f (const F& f_in)
72  {
73  f = f_in;
74  }
75 
76  static void
77  op_mm (size_t n, R* r, const X* x , const Y* y)
78  {
79  for (size_t i = 0; i < n; i++)
80  r[i] = f (x[i], y[i]);
81  }
82 
83  static void
84  op_sm (size_t n, R* r, X x, const Y* y)
85  {
86  for (size_t i = 0; i < n; i++)
87  r[i] = f (x, y[i]);
88  }
89 
90  static void
91  op_ms (size_t n , R* r, const X* x, Y y)
92  {
93  for (size_t i = 0; i < n; i++)
94  r[i] = f (x[i], y);
95  }
96 };
97 
98 // Static init
99 template<typename R, typename X, typename Y, typename F>
101 
102 
103 // scalar-Array
104 template <class U, class T, class R, class F>
105 Array<U>
106 binmap (const T& x, const Array<R>& ya, F fcn)
107 {
108  octave_idx_type len = ya.numel ();
109 
110  const R *y = ya.data ();
111 
112  Array<U> result (ya.dims ());
113  U *p = result.fortran_vec ();
114 
115  octave_idx_type i;
116  for (i = 0; i < len - 3; i += 4)
117  {
118  octave_quit ();
119 
120  p[i] = fcn (x, y[i]);
121  p[i+1] = fcn (x, y[i+1]);
122  p[i+2] = fcn (x, y[i+2]);
123  p[i+3] = fcn (x, y[i+3]);
124  }
125 
126  octave_quit ();
127 
128  for (; i < len; i++)
129  p[i] = fcn (x, y[i]);
130 
131  return result;
132 }
133 
134 // Array-scalar
135 template <class U, class T, class R, class F>
136 Array<U>
137 binmap (const Array<T>& xa, const R& y, F fcn)
138 {
139  octave_idx_type len = xa.numel ();
140 
141  const R *x = xa.data ();
142 
143  Array<U> result (xa.dims ());
144  U *p = result.fortran_vec ();
145 
146  octave_idx_type i;
147  for (i = 0; i < len - 3; i += 4)
148  {
149  octave_quit ();
150 
151  p[i] = fcn (x[i], y);
152  p[i+1] = fcn (x[i+1], y);
153  p[i+2] = fcn (x[i+2], y);
154  p[i+3] = fcn (x[i+3], y);
155  }
156 
157  octave_quit ();
158 
159  for (; i < len; i++)
160  p[i] = fcn (x[i], y);
161 
162  return result;
163 }
164 
165 // Array-Array (treats singletons as scalars)
166 template <class U, class T, class R, class F>
167 Array<U>
168 binmap (const Array<T>& xa, const Array<R>& ya, F fcn, const char *name)
169 {
170  dim_vector xad = xa.dims ();
171  dim_vector yad = ya.dims ();
172  if (xa.numel () == 1)
173  return binmap<U, T, R, F> (xa(0), ya, fcn);
174  else if (ya.numel () == 1)
175  return binmap<U, T, R, F> (xa, ya(0), fcn);
176  else if (xad != yad)
177  {
178  if (is_valid_bsxfun (name, xad, yad))
179  {
181  return do_bsxfun_op (xa, ya,
185  }
186  else
187  gripe_nonconformant (name, xad, yad);
188  }
189 
190  octave_idx_type len = xa.numel ();
191 
192  const T *x = xa.data ();
193  const T *y = ya.data ();
194 
195  Array<U> result (xa.dims ());
196  U *p = result.fortran_vec ();
197 
198  octave_idx_type i;
199  for (i = 0; i < len - 3; i += 4)
200  {
201  octave_quit ();
202 
203  p[i] = fcn (x[i], y[i]);
204  p[i+1] = fcn (x[i+1], y[i+1]);
205  p[i+2] = fcn (x[i+2], y[i+2]);
206  p[i+3] = fcn (x[i+3], y[i+3]);
207  }
208 
209  octave_quit ();
210 
211  for (; i < len; i++)
212  p[i] = fcn (x[i], y[i]);
213 
214  return result;
215 }
216 
217 // scalar-Sparse
218 template <class U, class T, class R, class F>
219 Sparse<U>
220 binmap (const T& x, const Sparse<R>& ys, F fcn)
221 {
222  R yzero = R ();
223  U fz = fcn (x, yzero);
224 
225  if (fz == U ()) // Sparsity preserving fcn
226  {
227  octave_idx_type nz = ys.nnz ();
228  Sparse<U> retval (ys.rows (), ys.cols (), nz);
229  std::copy (ys.ridx (), ys.ridx () + nz, retval.ridx ());
230  std::copy (ys.cidx (), ys.cidx () + ys.cols () + 1, retval.cidx ());
231 
232  for (octave_idx_type i = 0; i < nz; i++)
233  {
234  octave_quit ();
235  // FIXME: Could keep track of whether fcn call results in a 0.
236  // If no zeroes are created could skip maybe_compress()
237  retval.xdata (i) = fcn (x, ys.data (i));
238  }
239 
240  octave_quit ();
241  retval.maybe_compress (true);
242  return retval;
243  }
244  else
245  return Sparse<U> (binmap<U, T, R, F> (x, ys.array_value (), fcn));
246 }
247 
248 // Sparse-scalar
249 template <class U, class T, class R, class F>
250 Sparse<U>
251 binmap (const Sparse<T>& xs, const R& y, F fcn)
252 {
253  T xzero = T ();
254  U fz = fcn (xzero, y);
255 
256  if (fz == U ()) // Sparsity preserving fcn
257  {
258  octave_idx_type nz = xs.nnz ();
259  Sparse<U> retval (xs.rows (), xs.cols (), nz);
260  std::copy (xs.ridx (), xs.ridx () + nz, retval.ridx ());
261  std::copy (xs.cidx (), xs.cidx () + xs.cols () + 1, retval.cidx ());
262 
263  for (octave_idx_type i = 0; i < nz; i++)
264  {
265  octave_quit ();
266  // FIXME: Could keep track of whether fcn call results in a 0.
267  // If no zeroes are created could skip maybe_compress()
268  retval.xdata (i) = fcn (xs.data (i), y);
269  }
270 
271  octave_quit ();
272  retval.maybe_compress (true);
273  return retval;
274  }
275  else
276  return Sparse<U> (binmap<U, T, R, F> (xs.array_value (), y, fcn));
277 }
278 
279 // Sparse-Sparse (treats singletons as scalars)
280 template <class U, class T, class R, class F>
281 Sparse<U>
282 binmap (const Sparse<T>& xs, const Sparse<R>& ys, F fcn, const char *name)
283 {
284  if (xs.rows () == 1 && xs.cols () == 1)
285  return binmap<U, T, R, F> (xs(0,0), ys, fcn);
286  else if (ys.rows () == 1 && ys.cols () == 1)
287  return binmap<U, T, R, F> (xs, ys(0,0), fcn);
288  else if (xs.dims () != ys.dims ())
289  gripe_nonconformant (name, xs.dims (), ys.dims ());
290 
291  T xzero = T ();
292  R yzero = R ();
293  U fz = fcn (xzero, yzero);
294 
295  if (fz == U ())
296  {
297  // Sparsity-preserving function. Do it efficiently.
298  octave_idx_type nr = xs.rows ();
299  octave_idx_type nc = xs.cols ();
300  Sparse<T> retval (nr, nc, xs.nnz () + ys.nnz ());
301 
302  octave_idx_type nz = 0;
303  for (octave_idx_type j = 0; j < nc; j++)
304  {
305  octave_quit ();
306 
307  octave_idx_type jx = xs.cidx (j);
308  octave_idx_type jx_max = xs.cidx (j+1);
309  bool jx_lt_max = jx < jx_max;
310 
311  octave_idx_type jy = ys.cidx (j);
312  octave_idx_type jy_max = ys.cidx (j+1);
313  bool jy_lt_max = jy < jy_max;
314 
315  while (jx_lt_max || jy_lt_max)
316  {
317  if (! jy_lt_max
318  || (jx_lt_max && (xs.ridx (jx) < ys.ridx (jy))))
319  {
320  retval.xridx (nz) = xs.ridx (jx);
321  retval.xdata (nz) = fcn (xs.data (jx), yzero);
322  jx++;
323  jx_lt_max = jx < jx_max;
324  }
325  else if (! jx_lt_max
326  || (jy_lt_max && (ys.ridx (jy) < xs.ridx (jx))))
327  {
328  retval.xridx (nz) = ys.ridx (jy);
329  retval.xdata (nz) = fcn (xzero, ys.data (jy));
330  jy++;
331  jy_lt_max = jy < jy_max;
332  }
333  else
334  {
335  retval.xridx (nz) = xs.ridx (jx);
336  retval.xdata (nz) = fcn (xs.data (jx), ys.data (jy));
337  jx++;
338  jx_lt_max = jx < jx_max;
339  jy++;
340  jy_lt_max = jy < jy_max;
341  }
342  nz++;
343  }
344  retval.xcidx (j+1) = nz;
345  }
346 
347  retval.maybe_compress (true);
348  return retval;
349  }
350  else
351  return Sparse<U> (binmap<U, T, R, F> (xs.array_value (), ys.array_value (),
352  fcn, name));
353 }
354 
355 // Overloads for function pointers.
356 
357 // Signature (T, R)
358 
359 template <class U, class T, class R>
360 inline Array<U>
361 binmap (const Array<T>& xa, const Array<R>& ya, U (*fcn) (T, R),
362  const char *name)
363 { return binmap<U, T, R, U (*) (T, R)> (xa, ya, fcn, name); }
364 
365 template <class U, class T, class R>
366 inline Array<U>
367 binmap (const T& x, const Array<R>& ya, U (*fcn) (T, R))
368 { return binmap<U, T, R, U (*) (T, R)> (x, ya, fcn); }
369 
370 template <class U, class T, class R>
371 inline Array<U>
372 binmap (const Array<T>& xa, const R& y, U (*fcn) (T, R))
373 { return binmap<U, T, R, U (*) (T, R)> (xa, y, fcn); }
374 
375 template <class U, class T, class R>
376 inline Sparse<U>
377 binmap (const Sparse<T>& xa, const Sparse<R>& ya, U (*fcn) (T, R),
378  const char *name)
379 { return binmap<U, T, R, U (*) (T, R)> (xa, ya, fcn, name); }
380 
381 template <class U, class T, class R>
382 inline Sparse<U>
383 binmap (const T& x, const Sparse<R>& ya, U (*fcn) (T, R))
384 { return binmap<U, T, R, U (*) (T, R)> (x, ya, fcn); }
385 
386 template <class U, class T, class R>
387 inline Sparse<U>
388 binmap (const Sparse<T>& xa, const R& y, U (*fcn) (T, R))
389 { return binmap<U, T, R, U (*) (T, R)> (xa, y, fcn); }
390 
391 // Signature (const T&, const R&)
392 
393 template <class U, class T, class R>
394 inline Array<U>
395 binmap (const Array<T>& xa, const Array<R>& ya, U (*fcn) (const T&, const R&),
396  const char *name)
397 { return binmap<U, T, R, U (*) (const T&, const R&)> (xa, ya, fcn, name); }
398 
399 template <class U, class T, class R>
400 inline Array<U>
401 binmap (const T& x, const Array<R>& ya, U (*fcn) (const T&, const R&))
402 { return binmap<U, T, R, U (*) (const T&, const R&)> (x, ya, fcn); }
403 
404 template <class U, class T, class R>
405 inline Array<U>
406 binmap (const Array<T>& xa, const R& y, U (*fcn) (const T&, const R&))
407 { return binmap<U, T, R, U (*) (const T&, const R&)> (xa, y, fcn); }
408 
409 template <class U, class T, class R>
410 inline Sparse<U>
411 binmap (const Sparse<T>& xa, const Sparse<R>& ya, U (*fcn) (const T&, const R&),
412  const char *name)
413 { return binmap<U, T, R, U (*) (const T&, const R&)> (xa, ya, fcn, name); }
414 
415 template <class U, class T, class R>
416 inline Sparse<U>
417 binmap (const T& x, const Sparse<R>& ya, U (*fcn) (const T&, const R&))
418 { return binmap<U, T, R, U (*) (const T&, const R&)> (x, ya, fcn); }
419 
420 template <class U, class T, class R>
421 inline Sparse<U>
422 binmap (const Sparse<T>& xa, const R& y, U (*fcn) (const T&, const R&))
423 { return binmap<U, T, R, U (*) (const T&, const R&)> (xa, y, fcn); }
424 
425 // Signature (const T&, R)
426 
427 template <class U, class T, class R>
428 inline Array<U>
429 binmap (const Array<T>& xa, const Array<R>& ya, U (*fcn) (const T&, R),
430  const char *name)
431 { return binmap<U, T, R, U (*) (const T&, R)> (xa, ya, fcn, name); }
432 
433 template <class U, class T, class R>
434 inline Array<U>
435 binmap (const T& x, const Array<R>& ya, U (*fcn) (const T&, R))
436 { return binmap<U, T, R, U (*) (const T&, R)> (x, ya, fcn); }
437 
438 template <class U, class T, class R>
439 inline Array<U>
440 binmap (const Array<T>& xa, const R& y, U (*fcn) (const T&, R))
441 { return binmap<U, T, R, U (*) (const T&, R)> (xa, y, fcn); }
442 
443 template <class U, class T, class R>
444 inline Sparse<U>
445 binmap (const Sparse<T>& xa, const Sparse<R>& ya, U (*fcn) (const T&, R),
446  const char *name)
447 { return binmap<U, T, R, U (*) (const T&, R)> (xa, ya, fcn, name); }
448 
449 template <class U, class T, class R>
450 inline Sparse<U>
451 binmap (const T& x, const Sparse<R>& ya, U (*fcn) (const T&, R))
452 { return binmap<U, T, R, U (*) (const T&, R)> (x, ya, fcn); }
453 
454 template <class U, class T, class R>
455 inline Sparse<U>
456 binmap (const Sparse<T>& xa, const R& y, U (*fcn) (const T&, R))
457 { return binmap<U, T, R, U (*) (const T&, R)> (xa, y, fcn); }
458 
459 // Signature (T, const R&)
460 
461 template <class U, class T, class R>
462 inline Array<U>
463 binmap (const Array<T>& xa, const Array<R>& ya, U (*fcn) (T, const R&),
464  const char *name)
465 { return binmap<U, T, R, U (*) (T, const R&)> (xa, ya, fcn, name); }
466 
467 template <class U, class T, class R>
468 inline Array<U>
469 binmap (const T& x, const Array<R>& ya, U (*fcn) (T, const R&))
470 { return binmap<U, T, R, U (*) (T, const R&)> (x, ya, fcn); }
471 
472 template <class U, class T, class R>
473 inline Array<U>
474 binmap (const Array<T>& xa, const R& y, U (*fcn) (T, const R&))
475 { return binmap<U, T, R, U (*) (T, const R&)> (xa, y, fcn); }
476 
477 template <class U, class T, class R>
478 inline Sparse<U>
479 binmap (const Sparse<T>& xa, const Sparse<R>& ya, U (*fcn) (T, const R&),
480  const char *name)
481 { return binmap<U, T, R, U (*) (T, const R&)> (xa, ya, fcn, name); }
482 
483 template <class U, class T, class R>
484 inline Sparse<U>
485 binmap (const T& x, const Sparse<R>& ya, U (*fcn) (T, const R&))
486 { return binmap<U, T, R, U (*) (T, const R&)> (x, ya, fcn); }
487 
488 template <class U, class T, class R>
489 inline Sparse<U>
490 binmap (const Sparse<T>& xa, const R& y, U (*fcn) (T, const R&))
491 { return binmap<U, T, R, U (*) (T, const R&)> (xa, y, fcn); }
492 
493 #endif
octave_idx_type cols(void) const
Definition: Sparse.h:264
void gripe_nonconformant(const char *op, octave_idx_type op1_len, octave_idx_type op2_len)
T * data(void)
Definition: Sparse.h:509
octave_idx_type rows(void) const
Definition: Sparse.h:263
dim_vector dims(void) const
Definition: Sparse.h:283
octave_idx_type numel(void) const
Number of elements in the array.
Definition: Array.h:275
octave_idx_type * xcidx(void)
Definition: Sparse.h:537
static void set_f(const F &f_in)
Definition: oct-binmap.h:71
octave_idx_type * cidx(void)
Definition: Sparse.h:531
static void op_sm(size_t n, R *r, X x, const Y *y)
Definition: oct-binmap.h:84
octave_idx_type nnz(void) const
Definition: Sparse.h:248
const dim_vector & dims(void) const
Return a const-reference so that dims ()(i) works efficiently.
Definition: Array.h:337
Sparse< T > maybe_compress(bool remove_zeros=false)
Definition: Sparse.h:469
const T * data(void) const
Definition: Array.h:479
Array< U > binmap(const T &x, const Array< R > &ya, F fcn)
Definition: oct-binmap.h:106
Handles the reference counting for all the derived classes.
Definition: Array.h:45
static void op_mm(size_t n, R *r, const X *x, const Y *y)
Definition: oct-binmap.h:77
octave_idx_type * ridx(void)
Definition: Sparse.h:518
bool is_valid_bsxfun(const std::string &name, const dim_vector &dx, const dim_vector &dy)
Definition: bsxfun.h:36
const T * fortran_vec(void) const
Definition: Array.h:481
static void op_ms(size_t n, R *r, const X *x, Y y)
Definition: oct-binmap.h:91
F77_RET_T const double * 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:38
Array< T > array_value(void) const
Definition: Sparse.cc:2685
void F(const TSRC *v, TRES *r, octave_idx_type m, octave_idx_type n)
Definition: mx-inlines.cc:527
static F f
Definition: oct-binmap.h:67