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
bsxfun.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2007-2017 David Bateman
4 Copyright (C) 2009 VZLU Prague
5 
6 This file is part of Octave.
7 
8 Octave is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 3 of the License, or (at your
11 option) any later version.
12 
13 Octave is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with Octave; see the file COPYING. If not, see
20 <http://www.gnu.org/licenses/>.
21 
22 */
23 
24 #if defined (HAVE_CONFIG_H)
25 # include "config.h"
26 #endif
27 
28 #include <string>
29 #include <vector>
30 #include <list>
31 
32 #include "lo-mappers.h"
33 
34 #include "oct-map.h"
35 #include "defun.h"
36 #include "parse.h"
37 #include "variables.h"
38 #include "ov-colon.h"
39 #include "unwind-prot.h"
40 #include "ov-fcn-handle.h"
41 
42 // Optimized bsxfun operations
44 {
62 };
63 
64 const char *bsxfun_builtin_names[] =
65 {
66  "plus",
67  "minus",
68  "times",
69  "rdivide",
70  "max",
71  "min",
72  "eq",
73  "ne",
74  "lt",
75  "le",
76  "gt",
77  "ge",
78  "and",
79  "or",
80  "power"
81 };
82 
83 static bsxfun_builtin_op
85 {
86  for (int i = 0; i < bsxfun_num_builtin_ops; i++)
87  if (name == bsxfun_builtin_names[i])
88  return static_cast<bsxfun_builtin_op> (i);
90 }
91 
93  const octave_value&);
94 
95 // Static table of handlers.
97 
98 template <typename NDA, NDA (bsxfun_op) (const NDA&, const NDA&)>
99 static octave_value
101 {
102  NDA xa = octave_value_extract<NDA> (x);
103  NDA ya = octave_value_extract<NDA> (y);
104  return octave_value (bsxfun_op (xa, ya));
105 }
106 
107 template <typename NDA, boolNDArray (bsxfun_rel) (const NDA&, const NDA&)>
108 static octave_value
110 {
111  NDA xa = octave_value_extract<NDA> (x);
112  NDA ya = octave_value_extract<NDA> (y);
113  return octave_value (bsxfun_rel (xa, ya));
114 }
115 
116 // pow() needs a special handler for reals
117 // because of the potentially complex result.
118 template <typename NDA, typename CNDA>
119 static octave_value
121 {
122  NDA xa = octave_value_extract<NDA> (x);
123  NDA ya = octave_value_extract<NDA> (y);
124  if (! ya.all_integers () && xa.any_element_is_negative ())
125  return octave_value (bsxfun_pow (CNDA (xa), ya));
126  else
127  return octave_value (bsxfun_pow (xa, ya));
128 }
129 
130 static void maybe_fill_table (void)
131 {
132  static bool filled = false;
133  if (filled)
134  return;
135 
136 #define REGISTER_OP_HANDLER(OP, BTYP, NDA, FUNOP) \
137  bsxfun_handler_table[OP][BTYP] = bsxfun_forward_op<NDA, FUNOP>
138 
139 #define REGISTER_REL_HANDLER(REL, BTYP, NDA, FUNREL) \
140  bsxfun_handler_table[REL][BTYP] = bsxfun_forward_rel<NDA, FUNREL>
141 
142 #define REGISTER_STD_HANDLERS(BTYP, NDA) \
143  REGISTER_OP_HANDLER (bsxfun_builtin_plus, BTYP, NDA, bsxfun_add); \
144  REGISTER_OP_HANDLER (bsxfun_builtin_minus, BTYP, NDA, bsxfun_sub); \
145  REGISTER_OP_HANDLER (bsxfun_builtin_times, BTYP, NDA, bsxfun_mul); \
146  REGISTER_OP_HANDLER (bsxfun_builtin_divide, BTYP, NDA, bsxfun_div); \
147  REGISTER_OP_HANDLER (bsxfun_builtin_max, BTYP, NDA, bsxfun_max); \
148  REGISTER_OP_HANDLER (bsxfun_builtin_min, BTYP, NDA, bsxfun_min); \
149  REGISTER_REL_HANDLER (bsxfun_builtin_eq, BTYP, NDA, bsxfun_eq); \
150  REGISTER_REL_HANDLER (bsxfun_builtin_ne, BTYP, NDA, bsxfun_ne); \
151  REGISTER_REL_HANDLER (bsxfun_builtin_lt, BTYP, NDA, bsxfun_lt); \
152  REGISTER_REL_HANDLER (bsxfun_builtin_le, BTYP, NDA, bsxfun_le); \
153  REGISTER_REL_HANDLER (bsxfun_builtin_gt, BTYP, NDA, bsxfun_gt); \
154  REGISTER_REL_HANDLER (bsxfun_builtin_ge, BTYP, NDA, bsxfun_ge)
155 
168 
169  // For bools, we register and/or.
172 
173  // Register power handlers.
175  do_bsxfun_real_pow<NDArray, ComplexNDArray>;
177  do_bsxfun_real_pow<FloatNDArray, FloatComplexNDArray>;
178 
180  bsxfun_pow);
183 
184  // For chars, we want just relational handlers.
191 
192  filled = true;
193 }
194 
195 static octave_value
197  const octave_value& a, const octave_value& b)
198 {
200 
201  maybe_fill_table ();
202 
204  if (op != bsxfun_builtin_unknown)
205  {
206  builtin_type_t btyp_a = a.builtin_type ();
207  builtin_type_t btyp_b = b.builtin_type ();
208 
209  // Simplify single/double combinations.
210  if (btyp_a == btyp_float && btyp_b == btyp_double)
211  btyp_b = btyp_float;
212  else if (btyp_a == btyp_double && btyp_b == btyp_float)
213  btyp_a = btyp_float;
214  else if (btyp_a == btyp_float_complex && btyp_b == btyp_complex)
215  btyp_b = btyp_float_complex;
216  else if (btyp_a == btyp_complex && btyp_b == btyp_float_complex)
217  btyp_a = btyp_float_complex;
218 
219  if (btyp_a == btyp_b && btyp_a != btyp_unknown)
220  {
221  bsxfun_handler handler = bsxfun_handler_table[op][btyp_a];
222  if (handler)
223  retval = handler (a, b);
224  }
225  }
226 
227  return retval;
228 }
229 
230 static bool
232  const dim_vector& dva, const dim_vector& dvc,
234 {
235  octave_idx_type nd = dva.ndims ();
236 
237  if (i == 0)
238  {
239  idx(0) = octave_value (':');
240  for (octave_idx_type j = 1; j < nd; j++)
241  {
242  if (dva(j) == 1)
243  idx(j) = octave_value (1);
244  else
245  idx(j) = octave_value ((i % dvc(j)) + 1);
246 
247  i /= dvc(j);
248  }
249 
250  Ac = A;
251  Ac = Ac.single_subsref ("(", idx);
252  return true;
253  }
254  else
255  {
256  bool is_changed = false;
257  octave_idx_type k = i;
258  octave_idx_type k1 = i - 1;
259  for (octave_idx_type j = 1; j < nd; j++)
260  {
261  if (dva(j) != 1 && k % dvc(j) != k1 % dvc(j))
262  {
263  idx (j) = octave_value ((k % dvc(j)) + 1);
264  is_changed = true;
265  }
266 
267  k /= dvc(j);
268  k1 /= dvc(j);
269  }
270 
271  if (is_changed)
272  {
273  Ac = A;
274  Ac = Ac.single_subsref ("(", idx);
275  return true;
276  }
277  else
278  return false;
279  }
280 }
281 
282 #if 0
283 // FIXME: this function is not used; is it OK to delete it?
284 static void
286 {
287  octave_idx_type nd = dv.ndims ();
288 
289  if (i == 0)
290  {
291  for (octave_idx_type j = nd - 1; j > 0; j--)
292  idx(j) = octave_value (1.0);
293  idx(0) = octave_value (':');
294  }
295  else
296  {
297  for (octave_idx_type j = 1; j < nd; j++)
298  {
299  idx (j) = octave_value (i % dv(j) + 1);
300  i /= dv(j);
301  }
302  }
303 }
304 #endif
305 
306 static void
308 {
309  octave_idx_type nd = dv.ndims ();
310 
311  idx(0) = 0;
312  for (octave_idx_type j = 1; j < nd; j++)
313  {
314  idx(j) = i % dv(j);
315  i /= dv(j);
316  }
317 }
318 
319 DEFUN (bsxfun, args, ,
320  doc: /* -*- texinfo -*-
321 @deftypefn {} {} bsxfun (@var{f}, @var{A}, @var{B})
322 The binary singleton expansion function performs broadcasting,
323 that is, it applies a binary function @var{f} element-by-element to two
324 array arguments @var{A} and @var{B}, and expands as necessary
325 singleton dimensions in either input argument.
326 
327 @var{f} is a function handle, inline function, or string containing the name
328 of the function to evaluate. The function @var{f} must be capable of
329 accepting two column-vector arguments of equal length, or one column vector
330 argument and a scalar.
331 
332 The dimensions of @var{A} and @var{B} must be equal or singleton. The
333 singleton dimensions of the arrays will be expanded to the same
334 dimensionality as the other array.
335 @seealso{arrayfun, cellfun}
336 @end deftypefn */)
337 {
338  if (args.length () != 3)
339  print_usage ();
340 
341  octave_value func = args(0);
342  if (func.is_string ())
343  {
344  std::string name = func.string_value ();
345  func = symbol_table::find_function (name);
346  if (func.is_undefined ())
347  error ("bsxfun: invalid function name: %s", name.c_str ());
348  }
349  else if (! (args(0).is_function_handle () || args(0).is_inline_function ()))
350  error ("bsxfun: F must be a string or function handle");
351 
353 
354  const octave_value A = args(1);
355  const octave_value B = args(2);
356 
357  if (func.is_builtin_function ()
358  || (func.is_function_handle () && ! A.is_object () && ! B.is_object ()))
359  {
360  // This may break if the default behavior is overridden. But if you
361  // override arithmetic operators for builtin classes, you should expect
362  // mayhem anyway (constant folding etc). Querying is_overloaded() may
363  // not be exactly what we need here.
364  octave_function *fcn_val = func.function_value ();
365  if (fcn_val)
366  {
367  octave_value tmp = maybe_optimized_builtin (fcn_val->name (), A, B);
368  if (tmp.is_defined ())
369  retval(0) = tmp;
370  }
371  }
372 
373  if (retval.empty ())
374  {
375  dim_vector dva = A.dims ();
376  octave_idx_type nda = dva.ndims ();
377  dim_vector dvb = B.dims ();
378  octave_idx_type ndb = dvb.ndims ();
379  octave_idx_type nd = nda;
380 
381  if (nda > ndb)
382  dvb.resize (nda, 1);
383  else if (nda < ndb)
384  {
385  dva.resize (ndb, 1);
386  nd = ndb;
387  }
388 
389  for (octave_idx_type i = 0; i < nd; i++)
390  if (dva(i) != dvb(i) && dva(i) != 1 && dvb(i) != 1)
391  error ("bsxfun: dimensions of A and B must match");
392 
393  // Find the size of the output
394  dim_vector dvc;
395  dvc.resize (nd);
396 
397  for (octave_idx_type i = 0; i < nd; i++)
398  dvc(i) = (dva(i) < 1 ? dva(i)
399  : (dvb(i) < 1 ? dvb(i)
400  : (dva(i) > dvb(i)
401  ? dva(i) : dvb(i))));
402 
403  if (dva == dvb || dva.numel () == 1 || dvb.numel () == 1)
404  {
405  octave_value_list inputs (2);
406  inputs(0) = A;
407  inputs(1) = B;
408  retval = func.do_multi_index_op (1, inputs);
409  }
410  else if (dvc.numel () < 1)
411  {
412  octave_value_list inputs (2);
413  inputs(0) = A.resize (dvc);
414  inputs(1) = B.resize (dvc);
415  retval = func.do_multi_index_op (1, inputs);
416  }
417  else
418  {
419  octave_idx_type ncount = 1;
420  for (octave_idx_type i = 1; i < nd; i++)
421  ncount *= dvc(i);
422 
423 #define BSXDEF(T) \
424  T result_ ## T; \
425  bool have_ ## T = false;
426 
427  BSXDEF(NDArray);
440 
441  octave_value Ac;
442  octave_value_list idxA;
443  octave_value Bc;
444  octave_value_list idxB;
445  octave_value C;
446  octave_value_list inputs (2);
447  Array<int> ra_idx (dim_vector (dvc.ndims (), 1), 0);
448 
449  for (octave_idx_type i = 0; i < ncount; i++)
450  {
451  if (maybe_update_column (Ac, A, dva, dvc, i, idxA))
452  inputs(0) = Ac;
453 
454  if (maybe_update_column (Bc, B, dvb, dvc, i, idxB))
455  inputs(1) = Bc;
456 
457  octave_value_list tmp = func.do_multi_index_op (1, inputs);
458 
459 #define BSXINIT(T, CLS, EXTRACTOR) \
460  (result_type == CLS) \
461  { \
462  have_ ## T = true; \
463  result_ ## T = tmp(0). EXTRACTOR ## _array_value (); \
464  result_ ## T .resize (dvc); \
465  }
466 
467  if (i == 0)
468  {
469  if (! tmp(0).is_sparse_type ())
470  {
471  std::string result_type = tmp(0).class_name ();
472  if (result_type == "double")
473  {
474  if (tmp(0).is_real_type ())
475  {
476  have_NDArray = true;
477  result_NDArray = tmp(0).array_value ();
478  result_NDArray.resize (dvc);
479  }
480  else
481  {
482  have_ComplexNDArray = true;
483  result_ComplexNDArray =
484  tmp(0).complex_array_value ();
485  result_ComplexNDArray.resize (dvc);
486  }
487  }
488  else if (result_type == "single")
489  {
490  if (tmp(0).is_real_type ())
491  {
492  have_FloatNDArray = true;
493  result_FloatNDArray
494  = tmp(0).float_array_value ();
495  result_FloatNDArray.resize (dvc);
496  }
497  else
498  {
499  have_ComplexNDArray = true;
500  result_ComplexNDArray =
501  tmp(0).complex_array_value ();
502  result_ComplexNDArray.resize (dvc);
503  }
504  }
505  else if BSXINIT(boolNDArray, "logical", bool)
506  else if BSXINIT(int8NDArray, "int8", int8)
507  else if BSXINIT(int16NDArray, "int16", int16)
508  else if BSXINIT(int32NDArray, "int32", int32)
509  else if BSXINIT(int64NDArray, "int64", int64)
510  else if BSXINIT(uint8NDArray, "uint8", uint8)
511  else if BSXINIT(uint16NDArray, "uint16", uint16)
512  else if BSXINIT(uint32NDArray, "uint32", uint32)
513  else if BSXINIT(uint64NDArray, "uint64", uint64)
514  else
515  {
516  C = tmp(0);
517  C = C.resize (dvc);
518  }
519  }
520  else // Skip semi-fast path for sparse matrices
521  {
522  C = tmp (0);
523  C = C.resize (dvc);
524  }
525  }
526  else
527  {
528  update_index (ra_idx, dvc, i);
529 
530  if (have_FloatNDArray
531  || have_FloatComplexNDArray)
532  {
533  if (! tmp(0).is_float_type ())
534  {
535  if (have_FloatNDArray)
536  {
537  have_FloatNDArray = false;
538  C = result_FloatNDArray;
539  }
540  else
541  {
542  have_FloatComplexNDArray = false;
543  C = result_FloatComplexNDArray;
544  }
545  C = do_cat_op (C, tmp(0), ra_idx);
546  }
547  else if (tmp(0).is_double_type ())
548  {
549  if (tmp(0).is_complex_type ()
550  && have_FloatNDArray)
551  {
552  result_ComplexNDArray =
553  ComplexNDArray (result_FloatNDArray);
554  result_ComplexNDArray.insert
555  (tmp(0).complex_array_value (), ra_idx);
556  have_FloatComplexNDArray = false;
557  have_ComplexNDArray = true;
558  }
559  else
560  {
561  result_NDArray =
562  NDArray (result_FloatNDArray);
563  result_NDArray.insert
564  (tmp(0).array_value (), ra_idx);
565  have_FloatNDArray = false;
566  have_NDArray = true;
567  }
568  }
569  else if (tmp(0).is_real_type ())
570  result_FloatNDArray.insert
571  (tmp(0).float_array_value (), ra_idx);
572  else
573  {
574  result_FloatComplexNDArray =
575  FloatComplexNDArray (result_FloatNDArray);
576  result_FloatComplexNDArray.insert
577  (tmp(0).float_complex_array_value (),
578  ra_idx);
579  have_FloatNDArray = false;
580  have_FloatComplexNDArray = true;
581  }
582  }
583  else if (have_NDArray)
584  {
585  if (! tmp(0).is_float_type ())
586  {
587  have_NDArray = false;
588  C = result_NDArray;
589  C = do_cat_op (C, tmp(0), ra_idx);
590  }
591  else if (tmp(0).is_real_type ())
592  result_NDArray.insert (tmp(0).array_value (),
593  ra_idx);
594  else
595  {
596  result_ComplexNDArray =
597  ComplexNDArray (result_NDArray);
598  result_ComplexNDArray.insert
599  (tmp(0).complex_array_value (), ra_idx);
600  have_NDArray = false;
601  have_ComplexNDArray = true;
602  }
603  }
604 
605 #define BSXLOOP(T, CLS, EXTRACTOR) \
606  (have_ ## T) \
607  { \
608  if (tmp(0).class_name () != CLS) \
609  { \
610  have_ ## T = false; \
611  C = result_ ## T; \
612  C = do_cat_op (C, tmp(0), ra_idx); \
613  } \
614  else \
615  result_ ## T .insert (tmp(0). EXTRACTOR ## _array_value (), ra_idx); \
616  }
617 
618  else if BSXLOOP(ComplexNDArray, "double", complex)
619  else if BSXLOOP(boolNDArray, "logical", bool)
620  else if BSXLOOP(int8NDArray, "int8", int8)
621  else if BSXLOOP(int16NDArray, "int16", int16)
622  else if BSXLOOP(int32NDArray, "int32", int32)
623  else if BSXLOOP(int64NDArray, "int64", int64)
624  else if BSXLOOP(uint8NDArray, "uint8", uint8)
625  else if BSXLOOP(uint16NDArray, "uint16", uint16)
626  else if BSXLOOP(uint32NDArray, "uint32", uint32)
627  else if BSXLOOP(uint64NDArray, "uint64", uint64)
628  else
629  C = do_cat_op (C, tmp(0), ra_idx);
630  }
631  }
632 
633 #define BSXEND(T) \
634  (have_ ## T) \
635  retval(0) = result_ ## T;
636 
637  if BSXEND(NDArray)
638  else if BSXEND(ComplexNDArray)
639  else if BSXEND(FloatNDArray)
640  else if BSXEND(FloatComplexNDArray)
641  else if BSXEND(boolNDArray)
642  else if BSXEND(int8NDArray)
643  else if BSXEND(int16NDArray)
644  else if BSXEND(int32NDArray)
645  else if BSXEND(int64NDArray)
646  else if BSXEND(uint8NDArray)
647  else if BSXEND(uint16NDArray)
648  else if BSXEND(uint32NDArray)
649  else if BSXEND(uint64NDArray)
650  else
651  retval(0) = C;
652  }
653  }
654 
655  return retval;
656 }
657 
658 /*
659 
660 %!shared a, b, c, f
661 %! a = randn (4, 4);
662 %! b = mean (a, 1);
663 %! c = mean (a, 2);
664 %! f = @minus;
665 %!error (bsxfun (f))
666 %!error (bsxfun (f, a))
667 %!error (bsxfun (a, b))
668 %!error (bsxfun (a, b, c))
669 %!error (bsxfun (f, a, b, c))
670 %!error (bsxfun (f, ones (4, 0), ones (4, 4)))
671 %!assert (bsxfun (f, ones (4, 0), ones (4, 1)), zeros (4, 0))
672 %!assert (bsxfun (f, ones (1, 4), ones (4, 1)), zeros (4, 4))
673 %!assert (bsxfun (f, a, b), a - repmat (b, 4, 1))
674 %!assert (bsxfun (f, a, c), a - repmat (c, 1, 4))
675 %!assert (bsxfun ("minus", ones (1, 4), ones (4, 1)), zeros (4, 4))
676 
677 %!shared a, b, c, f
678 %! a = randn (4, 4);
679 %! a(1) *= 1i;
680 %! b = mean (a, 1);
681 %! c = mean (a, 2);
682 %! f = @minus;
683 %!error (bsxfun (f))
684 %!error (bsxfun (f, a))
685 %!error (bsxfun (a, b))
686 %!error (bsxfun (a, b, c))
687 %!error (bsxfun (f, a, b, c))
688 %!error (bsxfun (f, ones (4, 0), ones (4, 4)))
689 %!assert (bsxfun (f, ones (4, 0), ones (4, 1)), zeros (4, 0))
690 %!assert (bsxfun (f, ones (1, 4), ones (4, 1)), zeros (4, 4))
691 %!assert (bsxfun (f, a, b), a - repmat (b, 4, 1))
692 %!assert (bsxfun (f, a, c), a - repmat (c, 1, 4))
693 %!assert (bsxfun ("minus", ones (1, 4), ones (4, 1)), zeros (4, 4))
694 
695 %!shared a, b, c, f
696 %! a = randn (4, 4);
697 %! a(end) *= 1i;
698 %! b = mean (a, 1);
699 %! c = mean (a, 2);
700 %! f = @minus;
701 %!error (bsxfun (f))
702 %!error (bsxfun (f, a))
703 %!error (bsxfun (a, b))
704 %!error (bsxfun (a, b, c))
705 %!error (bsxfun (f, a, b, c))
706 %!error (bsxfun (f, ones (4, 0), ones (4, 4)))
707 %!assert (bsxfun (f, ones (4, 0), ones (4, 1)), zeros (4, 0))
708 %!assert (bsxfun (f, ones (1, 4), ones (4, 1)), zeros (4, 4))
709 %!assert (bsxfun (f, a, b), a - repmat (b, 4, 1))
710 %!assert (bsxfun (f, a, c), a - repmat (c, 1, 4))
711 %!assert (bsxfun ("minus", ones (1, 4), ones (4, 1)), zeros (4, 4))
712 
713 %!shared a, b, c, f
714 %! a = randn (4, 4);
715 %! b = a (1, :);
716 %! c = a (:, 1);
717 %! f = @(x, y) x == y;
718 %!error (bsxfun (f))
719 %!error (bsxfun (f, a))
720 %!error (bsxfun (a, b))
721 %!error (bsxfun (a, b, c))
722 %!error (bsxfun (f, a, b, c))
723 %!error (bsxfun (f, ones (4, 0), ones (4, 4)))
724 %!assert (bsxfun (f, ones (4, 0), ones (4, 1)), zeros (4, 0, "logical"))
725 %!assert (bsxfun (f, ones (1, 4), ones (4, 1)), ones (4, 4, "logical"))
726 %!assert (bsxfun (f, a, b), a == repmat (b, 4, 1))
727 %!assert (bsxfun (f, a, c), a == repmat (c, 1, 4))
728 
729 %!shared a, b, c, d, f
730 %! a = randn (4, 4, 4);
731 %! b = mean (a, 1);
732 %! c = mean (a, 2);
733 %! d = mean (a, 3);
734 %! f = @minus;
735 %!error (bsxfun (f, ones ([4, 0, 4]), ones ([4, 4, 4])))
736 %!assert (bsxfun (f, ones ([4, 0, 4]), ones ([4, 1, 4])), zeros ([4, 0, 4]))
737 %!assert (bsxfun (f, ones ([4, 4, 0]), ones ([4, 1, 1])), zeros ([4, 4, 0]))
738 %!assert (bsxfun (f, ones ([1, 4, 4]), ones ([4, 1, 4])), zeros ([4, 4, 4]))
739 %!assert (bsxfun (f, ones ([4, 4, 1]), ones ([4, 1, 4])), zeros ([4, 4, 4]))
740 %!assert (bsxfun (f, ones ([4, 1, 4]), ones ([1, 4, 4])), zeros ([4, 4, 4]))
741 %!assert (bsxfun (f, ones ([4, 1, 4]), ones ([1, 4, 1])), zeros ([4, 4, 4]))
742 %!assert (bsxfun (f, a, b), a - repmat (b, [4, 1, 1]))
743 %!assert (bsxfun (f, a, c), a - repmat (c, [1, 4, 1]))
744 %!assert (bsxfun (f, a, d), a - repmat (d, [1, 1, 4]))
745 %!assert (bsxfun ("minus", ones ([4, 0, 4]), ones ([4, 1, 4])), zeros ([4, 0, 4]))
746 
747 %% The test below is a very hard case to treat
748 %!assert (bsxfun (f, ones ([4, 1, 4, 1]), ones ([1, 4, 1, 4])), zeros ([4, 4, 4, 4]))
749 
750 %!shared a, b, aa, bb
751 %! a = randn (3, 1, 3);
752 %! aa = a(:, ones (1, 3), :, ones (1, 3));
753 %! b = randn (1, 3, 3, 3);
754 %! bb = b(ones (1, 3), :, :, :);
755 %!assert (bsxfun (@plus, a, b), aa + bb)
756 %!assert (bsxfun (@minus, a, b), aa - bb)
757 %!assert (bsxfun (@times, a, b), aa .* bb)
758 %!assert (bsxfun (@rdivide, a, b), aa ./ bb)
759 %!assert (bsxfun (@ldivide, a, b), aa .\ bb)
760 %!assert (bsxfun (@power, a, b), aa .^ bb)
761 %!assert (bsxfun (@power, abs (a), b), abs (aa) .^ bb)
762 %!assert (bsxfun (@eq, round (a), round (b)), round (aa) == round (bb))
763 %!assert (bsxfun (@ne, round (a), round (b)), round (aa) != round (bb))
764 %!assert (bsxfun (@lt, a, b), aa < bb)
765 %!assert (bsxfun (@le, a, b), aa <= bb)
766 %!assert (bsxfun (@gt, a, b), aa > bb)
767 %!assert (bsxfun (@ge, a, b), aa >= bb)
768 %!assert (bsxfun (@min, a, b), min (aa, bb))
769 %!assert (bsxfun (@max, a, b), max (aa, bb))
770 %!assert (bsxfun (@and, a > 0, b > 0), (aa > 0) & (bb > 0))
771 %!assert (bsxfun (@or, a > 0, b > 0), (aa > 0) | (bb > 0))
772 
773 %% Test automatic bsxfun
774 %
775 %!test
776 %! funs = {@plus, @minus, @times, @rdivide, @ldivide, @power, @max, @min, ...
777 %! @rem, @mod, @atan2, @hypot, @eq, @ne, @lt, @le, @gt, @ge, ...
778 %! @and, @or, @xor };
779 %!
780 %! float_types = {@single, @double};
781 %! int_types = {@int8, @int16, @int32, @int64, ...
782 %! @uint8, @uint16, @uint32, @uint64};
783 %!
784 %! x = rand (3) * 10-5;
785 %! y = rand (3,1) * 10-5;
786 %!
787 %! for i=1:length (funs)
788 %! for j = 1:length (float_types)
789 %! for k = 1:length (int_types)
790 %!
791 %! fun = funs{i};
792 %! f_type = float_types{j};
793 %! i_type = int_types{k};
794 %!
795 %! assert (bsxfun (fun, f_type (x), i_type (y)), ...
796 %! fun (f_type(x), i_type (y)));
797 %! assert (bsxfun (fun, f_type (y), i_type (x)), ...
798 %! fun (f_type(y), i_type (x)));
799 %!
800 %! assert (bsxfun (fun, i_type (x), i_type (y)), ...
801 %! fun (i_type (x), i_type (y)));
802 %! assert (bsxfun (fun, i_type (y), i_type (x)), ...
803 %! fun (i_type (y), i_type (x)));
804 %!
805 %! assert (bsxfun (fun, f_type (x), f_type (y)), ...
806 %! fun (f_type (x), f_type (y)));
807 %! assert (bsxfun (fun, f_type(y), f_type(x)), ...
808 %! fun (f_type (y), f_type (x)));
809 %! endfor
810 %! endfor
811 %! endfor
812 
813 ## Automatic broadcasting with zero length dimensions
814 %!assert <47085> ([1 2 3] .+ zeros (0, 3), zeros (0, 3))
815 %!assert <47085> (rand (3, 3, 1) .+ rand (3, 3, 0), zeros (3, 3, 0))
816 
817 ## In-place broadcasting with zero length dimensions
818 %!test <47085>
819 %! a = zeros (0, 3);
820 %! a .+= [1 2 3];
821 %! assert (a, zeros (0, 3));
822 
823 */
octave_value(* bsxfun_handler)(const octave_value &, const octave_value &)
Definition: bsxfun.cc:92
bool is_builtin_function(void) const
Definition: ov.h:723
bool is_object(void) const
Definition: ov.h:593
#define BSXEND(T)
#define C(a, b)
Definition: Faddeeva.cc:246
const octave_base_value const Array< octave_idx_type > & ra_idx
octave_value do_cat_op(const octave_value &v1, const octave_value &v2, const Array< octave_idx_type > &ra_idx)
Definition: ov.cc:2456
boolNDArray bsxfun_le(const charNDArray &x, const charNDArray &y)
Definition: chNDArray.cc:259
static octave_value bsxfun_forward_op(const octave_value &x, const octave_value &y)
Definition: bsxfun.cc:100
OCTINTERP_API void print_usage(void)
Definition: defun.cc:52
OCTAVE_EXPORT octave_value_list uint16
Definition: ov.cc:1258
bool is_defined(void) const
Definition: ov.h:536
for large enough k
Definition: lu.cc:606
static bsxfun_builtin_op bsxfun_builtin_lookup(const std::string &name)
Definition: bsxfun.cc:84
void resize(int n, int fill_value=0)
Definition: dim-vector.h:316
static octave_value do_bsxfun_real_pow(const octave_value &x, const octave_value &y)
Definition: bsxfun.cc:120
#define DEFUN(name, args_name, nargout_name, doc)
Definition: defun.h:46
void error(const char *fmt,...)
Definition: error.cc:570
std::string name(void) const
Definition: ov-fcn.h:163
octave_value resize(const dim_vector &dv, bool fill=false) const
Definition: ov.h:524
boolNDArray bsxfun_lt(const charNDArray &x, const charNDArray &y)
Definition: chNDArray.cc:259
static octave_value maybe_optimized_builtin(const std::string &name, const octave_value &a, const octave_value &b)
Definition: bsxfun.cc:196
builtin_type_t
Definition: ov-base.h:61
static octave_value find_function(const std::string &name, const octave_value_list &args=octave_value_list(), bool local_funcs=true)
Definition: symtab.cc:1276
#define BSXDEF(T)
bool is_function_handle(void) const
Definition: ov.h:702
octave_idx_type numel(int n=0) const
Number of elements that a matrix with this dimensions would have.
Definition: dim-vector.h:389
calling an anonymous function involves an overhead quite comparable to the overhead of an m file function Passing a handle to a built in function is because the interpreter is not involved in the internal loop For a
Definition: cellfun.cc:398
boolNDArray bsxfun_eq(const charNDArray &x, const charNDArray &y)
Definition: chNDArray.cc:259
JNIEnv void * args
Definition: ov-java.cc:67
octave_value single_subsref(const std::string &type, const octave_value_list &idx)
Definition: ov.cc:1430
octave_value_list do_multi_index_op(int nargout, const octave_value_list &idx)
Definition: ov.cc:1527
F77_RET_T const F77_INT F77_CMPLX const F77_INT F77_CMPLX * B
#define REGISTER_OP_HANDLER(OP, BTYP, NDA, FUNOP)
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
std::string string_value(bool force=false) const
Definition: ov.h:908
OCTAVE_EXPORT octave_value_list uint32
Definition: ov.cc:1258
bool is_string(void) const
Definition: ov.h:578
OCTAVE_EXPORT octave_value_list int16
Definition: ov.cc:1302
static void update_index(Array< int > &idx, const dim_vector &dv, octave_idx_type i)
Definition: bsxfun.cc:307
double tmp
Definition: data.cc:6300
#define REGISTER_REL_HANDLER(REL, BTYP, NDA, FUNREL)
octave_value retval
Definition: data.cc:6294
OCTAVE_EXPORT octave_value_list int32
Definition: ov.cc:1258
boolNDArray bsxfun_and(const boolNDArray &x, const boolNDArray &y)
Definition: boolNDArray.cc:169
dim_vector dims(void) const
Definition: ov.h:486
ComplexNDArray bsxfun_pow(const ComplexNDArray &x, const ComplexNDArray &y)
Definition: CNDArray.cc:900
boolNDArray bsxfun_ge(const charNDArray &x, const charNDArray &y)
Definition: chNDArray.cc:259
bsxfun_builtin_op
Definition: bsxfun.cc:43
octave_function * function_value(bool silent=false) const
Definition: ov.cc:1705
#define BSXLOOP(T, CLS, EXTRACTOR)
OCTAVE_EXPORT octave_value_list int64
Definition: ov.cc:1258
static bool maybe_update_column(octave_value &Ac, const octave_value &A, const dim_vector &dva, const dim_vector &dvc, octave_idx_type i, octave_value_list &idx)
Definition: bsxfun.cc:231
bool empty(void) const
Definition: ovl.h:98
=val(i)}if ode{val(i)}occurs in table i
Definition: lookup.cc:239
static octave_value bsxfun_forward_rel(const octave_value &x, const octave_value &y)
Definition: bsxfun.cc:109
static void maybe_fill_table(void)
Definition: bsxfun.cc:130
const char * bsxfun_builtin_names[]
Definition: bsxfun.cc:64
octave_idx_type ndims(void) const
Number of dimensions.
Definition: dim-vector.h:301
the element is set to zero In other the statement xample y
Definition: data.cc:5342
b
Definition: cellfun.cc:398
boolNDArray bsxfun_ne(const charNDArray &x, const charNDArray &y)
Definition: chNDArray.cc:259
bool is_undefined(void) const
Definition: ov.h:539
boolNDArray bsxfun_gt(const charNDArray &x, const charNDArray &y)
Definition: chNDArray.cc:259
bsxfun_handler bsxfun_handler_table[bsxfun_num_builtin_ops][btyp_num_types]
Definition: bsxfun.cc:96
#define REGISTER_STD_HANDLERS(BTYP, NDA)
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:87
If this string is the system will ring the terminal sometimes it is useful to be able to print the original representation of the string
Definition: utils.cc:854
builtin_type_t builtin_type(void) const
Definition: ov.h:619
dim_vector dv
Definition: sub2ind.cc:263
boolNDArray bsxfun_or(const boolNDArray &x, const boolNDArray &y)
Definition: boolNDArray.cc:170
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
return octave_value(v1.char_array_value().concat(v2.char_array_value(), ra_idx),((a1.is_sq_string()||a2.is_sq_string())? '\'': '"'))
#define BSXINIT(T, CLS, EXTRACTOR)
F77_RET_T const F77_INT F77_CMPLX * A