ndarray
NumPy-friendly multidimensional arrays in C++
Loading...
Searching...
No Matches
operators.h
Go to the documentation of this file.
1// -*- c++ -*-
2/*
3 * Copyright (c) 2010-2012, Jim Bosch
4 * All rights reserved.
5 *
6 * ndarray is distributed under a simple BSD-like license;
7 * see the LICENSE file that should be present in the root
8 * of the source distribution, or alternately available at:
9 * https://github.com/ndarray/ndarray
10 */
11
12#ifndef NDARRAY_operators_h_INCLUDED
13#define NDARRAY_operators_h_INCLUDED
14
19#include "ndarray/Array.h"
20#include <boost/call_traits.hpp>
21#include <boost/utility/enable_if.hpp>
22
25#include "ndarray/types.h"
26
27namespace ndarray {
28
30namespace detail {
31
38template <typename A, typename B>
39struct PromotingBinaryFunction {
40 typedef A ElementA;
41 typedef B ElementB;
42 typedef A first_argument_type;
43 typedef B second_argument_type;
44 typedef typename boost::call_traits<A>::param_type ParamA;
45 typedef typename boost::call_traits<B>::param_type ParamB;
46 typedef typename Promote<A,B>::Type result_type;
47};
48
55template <typename A, typename B>
56struct BinaryPredicate {
57 typedef A ElementA;
58 typedef B ElementB;
59 typedef A first_argument_type;
60 typedef B second_argument_type;
61 typedef typename boost::call_traits<A>::param_type ParamA;
62 typedef typename boost::call_traits<B>::param_type ParamB;
63 typedef bool result_type;
64};
65
66// Local helper classes to avoid using the Boost ones,
67// which inherit from boost::unary_function and boost::binary_function
68// Boost might use the std implementations underneath,
69// which are removed in the C++17 standard, but are still supported by some compilers
70// in C++20
71
72template <class Operation>
73struct binary_traits
74{
75 typedef Operation function_type;
76 typedef const function_type & param_type;
77 typedef typename Operation::result_type result_type;
78 typedef typename Operation::first_argument_type first_argument_type;
79 typedef typename Operation::second_argument_type second_argument_type;
80};
81
82template<class Operation>
83class _binder1st {
84public:
85 using result_type = typename binary_traits<Operation>::result_type;
86
87 _binder1st(typename binary_traits<Operation>::param_type x,
88 typename boost::call_traits<typename binary_traits<Operation>::first_argument_type>::param_type y)
89 :
90 op(x), value(y) {}
91
92 typename binary_traits<Operation>::result_type
93 operator()(
94 typename boost::call_traits<typename binary_traits<Operation>::second_argument_type>::param_type x) const {
95 return op(value, x);
96 }
97
98protected:
99 typename binary_traits<Operation>::function_type op;
100 typename binary_traits<Operation>::first_argument_type value;
101};
102
103template<class Operation>
104class _binder2nd {
105public:
106 using result_type = typename binary_traits<Operation>::result_type;
107
108 _binder2nd(typename binary_traits<Operation>::param_type x,
109 typename boost::call_traits<typename binary_traits<Operation>::second_argument_type>::param_type y)
110 :
111 op(x), value(y) {}
112
113 typename binary_traits<Operation>::result_type
114 operator()(
115 typename boost::call_traits<typename binary_traits<Operation>::first_argument_type>::param_type x) const {
116 return op(x, value);
117 }
118
119protected:
120 typename binary_traits<Operation>::function_type op;
121 typename binary_traits<Operation>::second_argument_type value;
122};
123
130template <typename Derived>
131struct AdaptableFunctionTag {
132
133 template <typename OperandB, typename A>
134 struct ScalarExpr {
135 typedef typename Derived::template ScalarFunction<
136 A, typename ExpressionTraits<OperandB>::Element
137 > BinaryFunction;
138 typedef _binder1st<BinaryFunction> Bound;
139 static Bound bind(A const & scalar) {
140 return Bound(BinaryFunction(),scalar);
141 }
142 };
143
144 template <typename OperandA, typename B>
145 struct ExprScalar {
146 typedef typename Derived::template ScalarFunction<
147 typename ExpressionTraits<OperandA>::Element, B
148 > BinaryFunction;
149 typedef _binder2nd<BinaryFunction> Bound;
150 static Bound bind(B const & scalar) {
151 return Bound(BinaryFunction(),scalar);
152 }
153 };
154
155 template <typename OperandA, typename OperandB>
156 struct ExprExpr {
157 typedef typename Derived::template ScalarFunction<
158 typename ExpressionTraits<OperandA>::Element,
159 typename ExpressionTraits<OperandB>::Element
160 > BinaryFunction;
161 };
162
163};
164
170template <typename T>
171struct BitwiseNot {
172 typedef T argument_type;
173 typedef T result_type;
174
175 result_type operator()(argument_type arg) const { return ~arg; }
176};
177
178
179 struct PlusTag : public AdaptableFunctionTag<PlusTag> {
180 template <typename A, typename B>
181 struct ScalarFunction : public PromotingBinaryFunction<A,B> {
182 typename PromotingBinaryFunction<A,B>::result_type operator()(
183 typename PromotingBinaryFunction<A,B>::ParamA a,
184 typename PromotingBinaryFunction<A,B>::ParamB b
185 ) const {
186 return a + b;
187 }
188 };
189 };
190
191 struct MinusTag : public AdaptableFunctionTag<MinusTag> {
192 template <typename A, typename B>
193 struct ScalarFunction : public PromotingBinaryFunction<A,B> {
194 typename PromotingBinaryFunction<A,B>::result_type operator()(
195 typename PromotingBinaryFunction<A,B>::ParamA a,
196 typename PromotingBinaryFunction<A,B>::ParamB b
197 ) const {
198 return a - b;
199 }
200 };
201 };
202
203 struct MultipliesTag : public AdaptableFunctionTag<MultipliesTag> {
204 template <typename A, typename B>
205 struct ScalarFunction : public PromotingBinaryFunction<A,B> {
206 typename PromotingBinaryFunction<A,B>::result_type operator()(
207 typename PromotingBinaryFunction<A,B>::ParamA a,
208 typename PromotingBinaryFunction<A,B>::ParamB b
209 ) const {
210 return a * b;
211 }
212 };
213 };
214
215 struct DividesTag : public AdaptableFunctionTag<DividesTag> {
216 template <typename A, typename B>
217 struct ScalarFunction : public PromotingBinaryFunction<A,B> {
218 typename PromotingBinaryFunction<A,B>::result_type operator()(
219 typename PromotingBinaryFunction<A,B>::ParamA a,
220 typename PromotingBinaryFunction<A,B>::ParamB b
221 ) const {
222 return a / b;
223 }
224 };
225 };
226
227 struct ModulusTag : public AdaptableFunctionTag<ModulusTag> {
228 template <typename A, typename B>
229 struct ScalarFunction : public PromotingBinaryFunction<A,B> {
230 typename PromotingBinaryFunction<A,B>::result_type operator()(
231 typename PromotingBinaryFunction<A,B>::ParamA a,
232 typename PromotingBinaryFunction<A,B>::ParamB b
233 ) const {
234 return a % b;
235 }
236 };
237 };
238
239 struct BitwiseXorTag : public AdaptableFunctionTag<BitwiseXorTag> {
240 template <typename A, typename B>
241 struct ScalarFunction : public PromotingBinaryFunction<A,B> {
242 typename PromotingBinaryFunction<A,B>::result_type operator()(
243 typename PromotingBinaryFunction<A,B>::ParamA a,
244 typename PromotingBinaryFunction<A,B>::ParamB b
245 ) const {
246 return a ^ b;
247 }
248 };
249 };
250
251 struct BitwiseOrTag : public AdaptableFunctionTag<BitwiseOrTag> {
252 template <typename A, typename B>
253 struct ScalarFunction : public PromotingBinaryFunction<A,B> {
254 typename PromotingBinaryFunction<A,B>::result_type operator()(
255 typename PromotingBinaryFunction<A,B>::ParamA a,
256 typename PromotingBinaryFunction<A,B>::ParamB b
257 ) const {
258 return a | b;
259 }
260 };
261 };
262
263 struct BitwiseAndTag : public AdaptableFunctionTag<BitwiseAndTag> {
264 template <typename A, typename B>
265 struct ScalarFunction : public PromotingBinaryFunction<A,B> {
266 typename PromotingBinaryFunction<A,B>::result_type operator()(
267 typename PromotingBinaryFunction<A,B>::ParamA a,
268 typename PromotingBinaryFunction<A,B>::ParamB b
269 ) const {
270 return a & b;
271 }
272 };
273 };
274
275 struct BitwiseLeftShiftTag : public AdaptableFunctionTag<BitwiseLeftShiftTag> {
276 template <typename A, typename B>
277 struct ScalarFunction : public PromotingBinaryFunction<A,B> {
278 typename PromotingBinaryFunction<A,B>::result_type operator()(
279 typename PromotingBinaryFunction<A,B>::ParamA a,
280 typename PromotingBinaryFunction<A,B>::ParamB b
281 ) const {
282 return a << b;
283 }
284 };
285 };
286
287 struct BitwiseRightShiftTag : public AdaptableFunctionTag<BitwiseRightShiftTag> {
288 template <typename A, typename B>
289 struct ScalarFunction : public PromotingBinaryFunction<A,B> {
290 typename PromotingBinaryFunction<A,B>::result_type operator()(
291 typename PromotingBinaryFunction<A,B>::ParamA a,
292 typename PromotingBinaryFunction<A,B>::ParamB b
293 ) const {
294 return a >> b;
295 }
296 };
297 };
298
299
300 struct EqualToTag : public AdaptableFunctionTag<EqualToTag> {
301 template <typename A, typename B>
302 struct ScalarFunction : public BinaryPredicate<A,B> {
303 typename BinaryPredicate<A,B>::result_type operator()(
304 typename BinaryPredicate<A,B>::ParamA a,
305 typename BinaryPredicate<A,B>::ParamB b
306 ) const {
307 return a == b;
308 }
309 };
310 };
311
312 struct NotEqualToTag : public AdaptableFunctionTag<NotEqualToTag> {
313 template <typename A, typename B>
314 struct ScalarFunction : public BinaryPredicate<A,B> {
315 typename BinaryPredicate<A,B>::result_type operator()(
316 typename BinaryPredicate<A,B>::ParamA a,
317 typename BinaryPredicate<A,B>::ParamB b
318 ) const {
319 return a != b;
320 }
321 };
322 };
323
324 struct LessTag : public AdaptableFunctionTag<LessTag> {
325 template <typename A, typename B>
326 struct ScalarFunction : public BinaryPredicate<A,B> {
327 typename BinaryPredicate<A,B>::result_type operator()(
328 typename BinaryPredicate<A,B>::ParamA a,
329 typename BinaryPredicate<A,B>::ParamB b
330 ) const {
331 return a < b;
332 }
333 };
334 };
335
336 struct GreaterTag : public AdaptableFunctionTag<GreaterTag> {
337 template <typename A, typename B>
338 struct ScalarFunction : public BinaryPredicate<A,B> {
339 typename BinaryPredicate<A,B>::result_type operator()(
340 typename BinaryPredicate<A,B>::ParamA a,
341 typename BinaryPredicate<A,B>::ParamB b
342 ) const {
343 return a > b;
344 }
345 };
346 };
347
348 struct LessEqualTag : public AdaptableFunctionTag<LessEqualTag> {
349 template <typename A, typename B>
350 struct ScalarFunction : public BinaryPredicate<A,B> {
351 typename BinaryPredicate<A,B>::result_type operator()(
352 typename BinaryPredicate<A,B>::ParamA a,
353 typename BinaryPredicate<A,B>::ParamB b
354 ) const {
355 return a <= b;
356 }
357 };
358 };
359
360 struct GreaterEqualTag : public AdaptableFunctionTag<GreaterEqualTag> {
361 template <typename A, typename B>
362 struct ScalarFunction : public BinaryPredicate<A,B> {
363 typename BinaryPredicate<A,B>::result_type operator()(
364 typename BinaryPredicate<A,B>::ParamA a,
365 typename BinaryPredicate<A,B>::ParamB b
366 ) const {
367 return a >= b;
368 }
369 };
370 };
371
372 struct LogicalAnd : public AdaptableFunctionTag<LogicalAnd> {
373 template <typename A, typename B>
374 struct ScalarFunction : public BinaryPredicate<A,B> {
375 typename BinaryPredicate<A,B>::result_type operator()(
376 typename BinaryPredicate<A,B>::ParamA a,
377 typename BinaryPredicate<A,B>::ParamB b
378 ) const {
379 return a && b;
380 }
381 };
382 };
383
384 struct LogicalOr : public AdaptableFunctionTag<LogicalOr> {
385 template <typename A, typename B>
386 struct ScalarFunction : public BinaryPredicate<A,B> {
387 typename BinaryPredicate<A,B>::result_type operator()(
388 typename BinaryPredicate<A,B>::ParamA a,
389 typename BinaryPredicate<A,B>::ParamB b
390 ) const {
391 return a || b;
392 }
393 };
394 };
395
396} // namespace detail
398
401
402 template <typename Operand, typename Scalar>
403#ifndef DOXYGEN
404 typename boost::enable_if<
405 typename ExpressionTraits<Scalar>::IsScalar,
406 detail::UnaryOpExpression< Operand, typename detail::PlusTag::template ExprScalar<Operand,Scalar>::Bound >
407 >::type
408#else
409 <unspecified-expression-type>
410#endif
411 operator+(ExpressionBase<Operand> const & operand, Scalar const & scalar) {
412 return vectorize(detail::PlusTag::template ExprScalar<Operand,Scalar>::bind(scalar),operand);
413 }
414
415 template <typename Operand, typename Scalar>
416#ifndef DOXYGEN
417 typename boost::enable_if<
418 typename ExpressionTraits<Scalar>::IsScalar,
419 detail::UnaryOpExpression< Operand, typename detail::PlusTag::template ScalarExpr<Operand,Scalar>::Bound >
420 >::type
421#else
422 <unspecified-expression-type>
423#endif
424 operator+(Scalar const & scalar, ExpressionBase<Operand> const & operand) {
425 return vectorize(detail::PlusTag::template ScalarExpr<Operand,Scalar>::bind(scalar),operand);
426 }
427
428 template <typename Operand1, typename Operand2>
429#ifndef DOXYGEN
430 detail::BinaryOpExpression<
431 Operand1, Operand2,
432 typename detail::PlusTag::template ExprExpr<Operand1,Operand2>::BinaryFunction
433 >
434#else
435 <unspecified-expression-type>
436#endif
437 operator+(ExpressionBase<Operand1> const & operand1, ExpressionBase<Operand2> const & operand2) {
438 return vectorize(
439 typename detail::PlusTag::template ExprExpr<Operand1,Operand2>::BinaryFunction(),
440 operand1,
441 operand2
442 );
443 }
444
445 template <typename Operand, typename Scalar>
446#ifndef DOXYGEN
447 typename boost::enable_if<
448 typename ExpressionTraits<Scalar>::IsScalar,
449 detail::UnaryOpExpression< Operand, typename detail::MinusTag::template ExprScalar<Operand,Scalar>::Bound >
450 >::type
451#else
452 <unspecified-expression-type>
453#endif
454 operator-(ExpressionBase<Operand> const & operand, Scalar const & scalar) {
455 return vectorize(detail::MinusTag::template ExprScalar<Operand,Scalar>::bind(scalar),operand);
456 }
457
458 template <typename Operand, typename Scalar>
459#ifndef DOXYGEN
460 typename boost::enable_if<
461 typename ExpressionTraits<Scalar>::IsScalar,
462 detail::UnaryOpExpression< Operand, typename detail::MinusTag::template ScalarExpr<Operand,Scalar>::Bound >
463 >::type
464#else
465 <unspecified-expression-type>
466#endif
467 operator-(Scalar const & scalar, ExpressionBase<Operand> const & operand) {
468 return vectorize(detail::MinusTag::template ScalarExpr<Operand,Scalar>::bind(scalar),operand);
469 }
470
471 template <typename Operand1, typename Operand2>
472#ifndef DOXYGEN
473 detail::BinaryOpExpression<
474 Operand1, Operand2,
475 typename detail::MinusTag::template ExprExpr<Operand1,Operand2>::BinaryFunction
476 >
477#else
478 <unspecified-expression-type>
479#endif
480 operator-(ExpressionBase<Operand1> const & operand1, ExpressionBase<Operand2> const & operand2) {
481 return vectorize(
482 typename detail::MinusTag::template ExprExpr<Operand1,Operand2>::BinaryFunction(),
483 operand1,
484 operand2
485 );
486 }
487
488 template <typename Operand, typename Scalar>
489#ifndef DOXYGEN
490 typename boost::enable_if<
491 typename ExpressionTraits<Scalar>::IsScalar,
492 detail::UnaryOpExpression< Operand, typename detail::MultipliesTag::template ExprScalar<Operand,Scalar>::Bound >
493 >::type
494#else
495 <unspecified-expression-type>
496#endif
497 operator*(ExpressionBase<Operand> const & operand, Scalar const & scalar) {
498 return vectorize(detail::MultipliesTag::template ExprScalar<Operand,Scalar>::bind(scalar),operand);
499 }
500
501 template <typename Operand, typename Scalar>
502#ifndef DOXYGEN
503 typename boost::enable_if<
504 typename ExpressionTraits<Scalar>::IsScalar,
505 detail::UnaryOpExpression< Operand, typename detail::MultipliesTag::template ScalarExpr<Operand,Scalar>::Bound >
506 >::type
507#else
508 <unspecified-expression-type>
509#endif
510 operator*(Scalar const & scalar, ExpressionBase<Operand> const & operand) {
511 return vectorize(detail::MultipliesTag::template ScalarExpr<Operand,Scalar>::bind(scalar),operand);
512 }
513
514 template <typename Operand1, typename Operand2>
515#ifndef DOXYGEN
516 detail::BinaryOpExpression<
517 Operand1, Operand2,
518 typename detail::MultipliesTag::template ExprExpr<Operand1,Operand2>::BinaryFunction
519 >
520#else
521 <unspecified-expression-type>
522#endif
523 operator*(ExpressionBase<Operand1> const & operand1, ExpressionBase<Operand2> const & operand2) {
524 return vectorize(
525 typename detail::MultipliesTag::template ExprExpr<Operand1,Operand2>::BinaryFunction(),
526 operand1,
527 operand2
528 );
529 }
530
531 template <typename Operand, typename Scalar>
532#ifndef DOXYGEN
533 typename boost::enable_if<
534 typename ExpressionTraits<Scalar>::IsScalar,
535 detail::UnaryOpExpression< Operand, typename detail::DividesTag::template ExprScalar<Operand,Scalar>::Bound >
536 >::type
537#else
538 <unspecified-expression-type>
539#endif
540 operator/(ExpressionBase<Operand> const & operand, Scalar const & scalar) {
541 return vectorize(detail::DividesTag::template ExprScalar<Operand,Scalar>::bind(scalar),operand);
542 }
543
544 template <typename Operand, typename Scalar>
545#ifndef DOXYGEN
546 typename boost::enable_if<
547 typename ExpressionTraits<Scalar>::IsScalar,
548 detail::UnaryOpExpression< Operand, typename detail::DividesTag::template ScalarExpr<Operand,Scalar>::Bound >
549 >::type
550#else
551 <unspecified-expression-type>
552#endif
553 operator/(Scalar const & scalar, ExpressionBase<Operand> const & operand) {
554 return vectorize(detail::DividesTag::template ScalarExpr<Operand,Scalar>::bind(scalar),operand);
555 }
556
557 template <typename Operand1, typename Operand2>
558#ifndef DOXYGEN
559 detail::BinaryOpExpression<
560 Operand1, Operand2,
561 typename detail::DividesTag::template ExprExpr<Operand1,Operand2>::BinaryFunction
562 >
563#else
564 <unspecified-expression-type>
565#endif
566 operator/(ExpressionBase<Operand1> const & operand1, ExpressionBase<Operand2> const & operand2) {
567 return vectorize(
568 typename detail::DividesTag::template ExprExpr<Operand1,Operand2>::BinaryFunction(),
569 operand1,
570 operand2
571 );
572 }
573
574 template <typename Operand, typename Scalar>
575#ifndef DOXYGEN
576 typename boost::enable_if<
577 typename ExpressionTraits<Scalar>::IsScalar,
578 detail::UnaryOpExpression< Operand, typename detail::ModulusTag::template ExprScalar<Operand,Scalar>::Bound >
579 >::type
580#else
581 <unspecified-expression-type>
582#endif
583 operator%(ExpressionBase<Operand> const & operand, Scalar const & scalar) {
584 return vectorize(detail::ModulusTag::template ExprScalar<Operand,Scalar>::bind(scalar),operand);
585 }
586
587 template <typename Operand, typename Scalar>
588#ifndef DOXYGEN
589 typename boost::enable_if<
590 typename ExpressionTraits<Scalar>::IsScalar,
591 detail::UnaryOpExpression< Operand, typename detail::ModulusTag::template ScalarExpr<Operand,Scalar>::Bound >
592 >::type
593#else
594 <unspecified-expression-type>
595#endif
596 operator%(Scalar const & scalar, ExpressionBase<Operand> const & operand) {
597 return vectorize(detail::ModulusTag::template ScalarExpr<Operand,Scalar>::bind(scalar),operand);
598 }
599
600 template <typename Operand1, typename Operand2>
601#ifndef DOXYGEN
602 detail::BinaryOpExpression<
603 Operand1, Operand2,
604 typename detail::ModulusTag::template ExprExpr<Operand1,Operand2>::BinaryFunction
605 >
606#else
607 <unspecified-expression-type>
608#endif
609 operator%(ExpressionBase<Operand1> const & operand1, ExpressionBase<Operand2> const & operand2) {
610 return vectorize(
611 typename detail::ModulusTag::template ExprExpr<Operand1,Operand2>::BinaryFunction(),
612 operand1,
613 operand2
614 );
615 }
616
617 template <typename Operand, typename Scalar>
618#ifndef DOXYGEN
619 typename boost::enable_if<
620 typename ExpressionTraits<Scalar>::IsScalar,
621 detail::UnaryOpExpression< Operand, typename detail::BitwiseXorTag::template ExprScalar<Operand,Scalar>::Bound >
622 >::type
623#else
624 <unspecified-expression-type>
625#endif
626 operator^(ExpressionBase<Operand> const & operand, Scalar const & scalar) {
627 return vectorize(detail::BitwiseXorTag::template ExprScalar<Operand,Scalar>::bind(scalar),operand);
628 }
629
630 template <typename Operand, typename Scalar>
631#ifndef DOXYGEN
632 typename boost::enable_if<
633 typename ExpressionTraits<Scalar>::IsScalar,
634 detail::UnaryOpExpression< Operand, typename detail::BitwiseXorTag::template ScalarExpr<Operand,Scalar>::Bound >
635 >::type
636#else
637 <unspecified-expression-type>
638#endif
639 operator^(Scalar const & scalar, ExpressionBase<Operand> const & operand) {
640 return vectorize(detail::BitwiseXorTag::template ScalarExpr<Operand,Scalar>::bind(scalar),operand);
641 }
642
643 template <typename Operand1, typename Operand2>
644#ifndef DOXYGEN
645 detail::BinaryOpExpression<
646 Operand1, Operand2,
647 typename detail::BitwiseXorTag::template ExprExpr<Operand1,Operand2>::BinaryFunction
648 >
649#else
650 <unspecified-expression-type>
651#endif
652 operator^(ExpressionBase<Operand1> const & operand1, ExpressionBase<Operand2> const & operand2) {
653 return vectorize(
654 typename detail::BitwiseXorTag::template ExprExpr<Operand1,Operand2>::BinaryFunction(),
655 operand1,
656 operand2
657 );
658 }
659
660 template <typename Operand, typename Scalar>
661#ifndef DOXYGEN
662 typename boost::enable_if<
663 typename ExpressionTraits<Scalar>::IsScalar,
664 detail::UnaryOpExpression< Operand, typename detail::BitwiseOrTag::template ExprScalar<Operand,Scalar>::Bound >
665 >::type
666#else
667 <unspecified-expression-type>
668#endif
669 operator|(ExpressionBase<Operand> const & operand, Scalar const & scalar) {
670 return vectorize(detail::BitwiseOrTag::template ExprScalar<Operand,Scalar>::bind(scalar),operand);
671 }
672
673 template <typename Operand, typename Scalar>
674#ifndef DOXYGEN
675 typename boost::enable_if<
676 typename ExpressionTraits<Scalar>::IsScalar,
677 detail::UnaryOpExpression< Operand, typename detail::BitwiseOrTag::template ScalarExpr<Operand,Scalar>::Bound >
678 >::type
679#else
680 <unspecified-expression-type>
681#endif
682 operator|(Scalar const & scalar, ExpressionBase<Operand> const & operand) {
683 return vectorize(detail::BitwiseOrTag::template ScalarExpr<Operand,Scalar>::bind(scalar),operand);
684 }
685
686 template <typename Operand1, typename Operand2>
687#ifndef DOXYGEN
688 detail::BinaryOpExpression<
689 Operand1, Operand2,
690 typename detail::BitwiseOrTag::template ExprExpr<Operand1,Operand2>::BinaryFunction
691 >
692#else
693 <unspecified-expression-type>
694#endif
695 operator|(ExpressionBase<Operand1> const & operand1, ExpressionBase<Operand2> const & operand2) {
696 return vectorize(
697 typename detail::BitwiseOrTag::template ExprExpr<Operand1,Operand2>::BinaryFunction(),
698 operand1,
699 operand2
700 );
701 }
702
703 template <typename Operand, typename Scalar>
704#ifndef DOXYGEN
705 typename boost::enable_if<
706 typename ExpressionTraits<Scalar>::IsScalar,
707 detail::UnaryOpExpression< Operand, typename detail::BitwiseAndTag::template ExprScalar<Operand,Scalar>::Bound >
708 >::type
709#else
710 <unspecified-expression-type>
711#endif
712 operator&(ExpressionBase<Operand> const & operand, Scalar const & scalar) {
713 return vectorize(detail::BitwiseAndTag::template ExprScalar<Operand,Scalar>::bind(scalar),operand);
714 }
715
716 template <typename Operand, typename Scalar>
717#ifndef DOXYGEN
718 typename boost::enable_if<
719 typename ExpressionTraits<Scalar>::IsScalar,
720 detail::UnaryOpExpression< Operand, typename detail::BitwiseAndTag::template ScalarExpr<Operand,Scalar>::Bound >
721 >::type
722#else
723 <unspecified-expression-type>
724#endif
725 operator&(Scalar const & scalar, ExpressionBase<Operand> const & operand) {
726 return vectorize(detail::BitwiseAndTag::template ScalarExpr<Operand,Scalar>::bind(scalar),operand);
727 }
728
729 template <typename Operand1, typename Operand2>
730#ifndef DOXYGEN
731 detail::BinaryOpExpression<
732 Operand1, Operand2,
733 typename detail::BitwiseAndTag::template ExprExpr<Operand1,Operand2>::BinaryFunction
734 >
735#else
736 <unspecified-expression-type>
737#endif
738 operator&(ExpressionBase<Operand1> const & operand1, ExpressionBase<Operand2> const & operand2) {
739 return vectorize(
740 typename detail::BitwiseAndTag::template ExprExpr<Operand1,Operand2>::BinaryFunction(),
741 operand1,
742 operand2
743 );
744 }
745
746 template <typename Operand, typename Scalar>
747#ifndef DOXYGEN
748 typename boost::enable_if<
749 typename ExpressionTraits<Scalar>::IsScalar,
750 detail::UnaryOpExpression< Operand, typename detail::BitwiseLeftShiftTag::template ExprScalar<Operand,Scalar>::Bound >
751 >::type
752#else
753 <unspecified-expression-type>
754#endif
755 operator<<(ExpressionBase<Operand> const & operand, Scalar const & scalar) {
756 return vectorize(detail::BitwiseLeftShiftTag::template ExprScalar<Operand,Scalar>::bind(scalar),operand);
757 }
758
759 template <typename Operand, typename Scalar>
760#ifndef DOXYGEN
761 typename boost::enable_if<
762 typename ExpressionTraits<Scalar>::IsScalar,
763 detail::UnaryOpExpression< Operand, typename detail::BitwiseLeftShiftTag::template ScalarExpr<Operand,Scalar>::Bound >
764 >::type
765#else
766 <unspecified-expression-type>
767#endif
768 operator<<(Scalar const & scalar, ExpressionBase<Operand> const & operand) {
769 return vectorize(detail::BitwiseLeftShiftTag::template ScalarExpr<Operand,Scalar>::bind(scalar),operand);
770 }
771
772 template <typename Operand1, typename Operand2>
773#ifndef DOXYGEN
774 detail::BinaryOpExpression<
775 Operand1, Operand2,
776 typename detail::BitwiseLeftShiftTag::template ExprExpr<Operand1,Operand2>::BinaryFunction
777 >
778#else
779 <unspecified-expression-type>
780#endif
781 operator<<(ExpressionBase<Operand1> const & operand1, ExpressionBase<Operand2> const & operand2) {
782 return vectorize(
783 typename detail::BitwiseLeftShiftTag::template ExprExpr<Operand1,Operand2>::BinaryFunction(),
784 operand1,
785 operand2
786 );
787 }
788
789 template <typename Operand, typename Scalar>
790#ifndef DOXYGEN
791 typename boost::enable_if<
792 typename ExpressionTraits<Scalar>::IsScalar,
793 detail::UnaryOpExpression< Operand, typename detail::BitwiseRightShiftTag::template ExprScalar<Operand,Scalar>::Bound >
794 >::type
795#else
796 <unspecified-expression-type>
797#endif
798 operator>>(ExpressionBase<Operand> const & operand, Scalar const & scalar) {
799 return vectorize(detail::BitwiseRightShiftTag::template ExprScalar<Operand,Scalar>::bind(scalar),operand);
800 }
801
802 template <typename Operand, typename Scalar>
803#ifndef DOXYGEN
804 typename boost::enable_if<
805 typename ExpressionTraits<Scalar>::IsScalar,
806 detail::UnaryOpExpression< Operand, typename detail::BitwiseRightShiftTag::template ScalarExpr<Operand,Scalar>::Bound >
807 >::type
808#else
809 <unspecified-expression-type>
810#endif
811 operator>>(Scalar const & scalar, ExpressionBase<Operand> const & operand) {
812 return vectorize(detail::BitwiseRightShiftTag::template ScalarExpr<Operand,Scalar>::bind(scalar),operand);
813 }
814
815 template <typename Operand1, typename Operand2>
816#ifndef DOXYGEN
817 detail::BinaryOpExpression<
818 Operand1, Operand2,
819 typename detail::BitwiseRightShiftTag::template ExprExpr<Operand1,Operand2>::BinaryFunction
820 >
821#else
822 <unspecified-expression-type>
823#endif
824 operator>>(ExpressionBase<Operand1> const & operand1, ExpressionBase<Operand2> const & operand2) {
825 return vectorize(
826 typename detail::BitwiseRightShiftTag::template ExprExpr<Operand1,Operand2>::BinaryFunction(),
827 operand1,
828 operand2
829 );
830 }
831
832
833 template <typename Operand, typename Scalar>
834#ifndef DOXYGEN
835 typename boost::enable_if<
836 typename ExpressionTraits<Scalar>::IsScalar,
837 detail::UnaryOpExpression< Operand, typename detail::EqualToTag::template ExprScalar<Operand,Scalar>::Bound >
838 >::type
839#else
840 <unspecified-expression-type>
841#endif
842 equal(ExpressionBase<Operand> const & operand, Scalar const & scalar) {
843 return vectorize(detail::EqualToTag::template ExprScalar<Operand,Scalar>::bind(scalar),operand);
844 }
845
846 template <typename Operand, typename Scalar>
847#ifndef DOXYGEN
848 typename boost::enable_if<
849 typename ExpressionTraits<Scalar>::IsScalar,
850 detail::UnaryOpExpression< Operand, typename detail::EqualToTag::template ScalarExpr<Operand,Scalar>::Bound >
851 >::type
852#else
853 <unspecified-expression-type>
854#endif
855 equal(Scalar const & scalar, ExpressionBase<Operand> const & operand) {
856 return vectorize(detail::EqualToTag::template ScalarExpr<Operand,Scalar>::bind(scalar),operand);
857 }
858
859 template <typename Operand1, typename Operand2>
860#ifndef DOXYGEN
861 detail::BinaryOpExpression<
862 Operand1, Operand2,
863 typename detail::EqualToTag::template ExprExpr<Operand1,Operand2>::BinaryFunction
864 >
865#else
866 <unspecified-expression-type>
867#endif
868 equal(ExpressionBase<Operand1> const & operand1, ExpressionBase<Operand2> const & operand2) {
869 return vectorize(
870 typename detail::EqualToTag::template ExprExpr<Operand1,Operand2>::BinaryFunction(),
871 operand1,
872 operand2
873 );
874 }
875
876 template <typename Operand, typename Scalar>
877#ifndef DOXYGEN
878 typename boost::enable_if<
879 typename ExpressionTraits<Scalar>::IsScalar,
880 detail::UnaryOpExpression< Operand, typename detail::NotEqualToTag::template ExprScalar<Operand,Scalar>::Bound >
881 >::type
882#else
883 <unspecified-expression-type>
884#endif
885 not_equal(ExpressionBase<Operand> const & operand, Scalar const & scalar) {
886 return vectorize(detail::NotEqualToTag::template ExprScalar<Operand,Scalar>::bind(scalar),operand);
887 }
888
889 template <typename Operand, typename Scalar>
890#ifndef DOXYGEN
891 typename boost::enable_if<
892 typename ExpressionTraits<Scalar>::IsScalar,
893 detail::UnaryOpExpression< Operand, typename detail::NotEqualToTag::template ScalarExpr<Operand,Scalar>::Bound >
894 >::type
895#else
896 <unspecified-expression-type>
897#endif
898 not_equal(Scalar const & scalar, ExpressionBase<Operand> const & operand) {
899 return vectorize(detail::NotEqualToTag::template ScalarExpr<Operand,Scalar>::bind(scalar),operand);
900 }
901
902 template <typename Operand1, typename Operand2>
903#ifndef DOXYGEN
904 detail::BinaryOpExpression<
905 Operand1, Operand2,
906 typename detail::NotEqualToTag::template ExprExpr<Operand1,Operand2>::BinaryFunction
907 >
908#else
909 <unspecified-expression-type>
910#endif
911 not_equal(ExpressionBase<Operand1> const & operand1, ExpressionBase<Operand2> const & operand2) {
912 return vectorize(
913 typename detail::NotEqualToTag::template ExprExpr<Operand1,Operand2>::BinaryFunction(),
914 operand1,
915 operand2
916 );
917 }
918
919 template <typename Operand, typename Scalar>
920#ifndef DOXYGEN
921 typename boost::enable_if<
922 typename ExpressionTraits<Scalar>::IsScalar,
923 detail::UnaryOpExpression< Operand, typename detail::LessTag::template ExprScalar<Operand,Scalar>::Bound >
924 >::type
925#else
926 <unspecified-expression-type>
927#endif
928 less(ExpressionBase<Operand> const & operand, Scalar const & scalar) {
929 return vectorize(detail::LessTag::template ExprScalar<Operand,Scalar>::bind(scalar),operand);
930 }
931
932 template <typename Operand, typename Scalar>
933#ifndef DOXYGEN
934 typename boost::enable_if<
935 typename ExpressionTraits<Scalar>::IsScalar,
936 detail::UnaryOpExpression< Operand, typename detail::LessTag::template ScalarExpr<Operand,Scalar>::Bound >
937 >::type
938#else
939 <unspecified-expression-type>
940#endif
941 less(Scalar const & scalar, ExpressionBase<Operand> const & operand) {
942 return vectorize(detail::LessTag::template ScalarExpr<Operand,Scalar>::bind(scalar),operand);
943 }
944
945 template <typename Operand1, typename Operand2>
946#ifndef DOXYGEN
947 detail::BinaryOpExpression<
948 Operand1, Operand2,
949 typename detail::LessTag::template ExprExpr<Operand1,Operand2>::BinaryFunction
950 >
951#else
952 <unspecified-expression-type>
953#endif
954 less(ExpressionBase<Operand1> const & operand1, ExpressionBase<Operand2> const & operand2) {
955 return vectorize(
956 typename detail::LessTag::template ExprExpr<Operand1,Operand2>::BinaryFunction(),
957 operand1,
958 operand2
959 );
960 }
961
962 template <typename Operand, typename Scalar>
963#ifndef DOXYGEN
964 typename boost::enable_if<
965 typename ExpressionTraits<Scalar>::IsScalar,
966 detail::UnaryOpExpression< Operand, typename detail::GreaterTag::template ExprScalar<Operand,Scalar>::Bound >
967 >::type
968#else
969 <unspecified-expression-type>
970#endif
971 greater(ExpressionBase<Operand> const & operand, Scalar const & scalar) {
972 return vectorize(detail::GreaterTag::template ExprScalar<Operand,Scalar>::bind(scalar),operand);
973 }
974
975 template <typename Operand, typename Scalar>
976#ifndef DOXYGEN
977 typename boost::enable_if<
978 typename ExpressionTraits<Scalar>::IsScalar,
979 detail::UnaryOpExpression< Operand, typename detail::GreaterTag::template ScalarExpr<Operand,Scalar>::Bound >
980 >::type
981#else
982 <unspecified-expression-type>
983#endif
984 greater(Scalar const & scalar, ExpressionBase<Operand> const & operand) {
985 return vectorize(detail::GreaterTag::template ScalarExpr<Operand,Scalar>::bind(scalar),operand);
986 }
987
988 template <typename Operand1, typename Operand2>
989#ifndef DOXYGEN
990 detail::BinaryOpExpression<
991 Operand1, Operand2,
992 typename detail::GreaterTag::template ExprExpr<Operand1,Operand2>::BinaryFunction
993 >
994#else
995 <unspecified-expression-type>
996#endif
997 greater(ExpressionBase<Operand1> const & operand1, ExpressionBase<Operand2> const & operand2) {
998 return vectorize(
999 typename detail::GreaterTag::template ExprExpr<Operand1,Operand2>::BinaryFunction(),
1000 operand1,
1001 operand2
1002 );
1003 }
1004
1005 template <typename Operand, typename Scalar>
1006#ifndef DOXYGEN
1007 typename boost::enable_if<
1008 typename ExpressionTraits<Scalar>::IsScalar,
1009 detail::UnaryOpExpression< Operand, typename detail::LessEqualTag::template ExprScalar<Operand,Scalar>::Bound >
1010 >::type
1011#else
1012 <unspecified-expression-type>
1013#endif
1014 less_equal(ExpressionBase<Operand> const & operand, Scalar const & scalar) {
1015 return vectorize(detail::LessEqualTag::template ExprScalar<Operand,Scalar>::bind(scalar),operand);
1016 }
1017
1018 template <typename Operand, typename Scalar>
1019#ifndef DOXYGEN
1020 typename boost::enable_if<
1021 typename ExpressionTraits<Scalar>::IsScalar,
1022 detail::UnaryOpExpression< Operand, typename detail::LessEqualTag::template ScalarExpr<Operand,Scalar>::Bound >
1023 >::type
1024#else
1025 <unspecified-expression-type>
1026#endif
1027 less_equal(Scalar const & scalar, ExpressionBase<Operand> const & operand) {
1028 return vectorize(detail::LessEqualTag::template ScalarExpr<Operand,Scalar>::bind(scalar),operand);
1029 }
1030
1031 template <typename Operand1, typename Operand2>
1032#ifndef DOXYGEN
1033 detail::BinaryOpExpression<
1034 Operand1, Operand2,
1035 typename detail::LessEqualTag::template ExprExpr<Operand1,Operand2>::BinaryFunction
1036 >
1037#else
1038 <unspecified-expression-type>
1039#endif
1040 less_equal(ExpressionBase<Operand1> const & operand1, ExpressionBase<Operand2> const & operand2) {
1041 return vectorize(
1042 typename detail::LessEqualTag::template ExprExpr<Operand1,Operand2>::BinaryFunction(),
1043 operand1,
1044 operand2
1045 );
1046 }
1047
1048 template <typename Operand, typename Scalar>
1049#ifndef DOXYGEN
1050 typename boost::enable_if<
1051 typename ExpressionTraits<Scalar>::IsScalar,
1052 detail::UnaryOpExpression< Operand, typename detail::GreaterEqualTag::template ExprScalar<Operand,Scalar>::Bound >
1053 >::type
1054#else
1055 <unspecified-expression-type>
1056#endif
1057 great_equal(ExpressionBase<Operand> const & operand, Scalar const & scalar) {
1058 return vectorize(detail::GreaterEqualTag::template ExprScalar<Operand,Scalar>::bind(scalar),operand);
1059 }
1060
1061 template <typename Operand, typename Scalar>
1062#ifndef DOXYGEN
1063 typename boost::enable_if<
1064 typename ExpressionTraits<Scalar>::IsScalar,
1065 detail::UnaryOpExpression< Operand, typename detail::GreaterEqualTag::template ScalarExpr<Operand,Scalar>::Bound >
1066 >::type
1067#else
1068 <unspecified-expression-type>
1069#endif
1070 great_equal(Scalar const & scalar, ExpressionBase<Operand> const & operand) {
1071 return vectorize(detail::GreaterEqualTag::template ScalarExpr<Operand,Scalar>::bind(scalar),operand);
1072 }
1073
1074 template <typename Operand1, typename Operand2>
1075#ifndef DOXYGEN
1076 detail::BinaryOpExpression<
1077 Operand1, Operand2,
1078 typename detail::GreaterEqualTag::template ExprExpr<Operand1,Operand2>::BinaryFunction
1079 >
1080#else
1081 <unspecified-expression-type>
1082#endif
1083 great_equal(ExpressionBase<Operand1> const & operand1, ExpressionBase<Operand2> const & operand2) {
1084 return vectorize(
1085 typename detail::GreaterEqualTag::template ExprExpr<Operand1,Operand2>::BinaryFunction(),
1086 operand1,
1087 operand2
1088 );
1089 }
1090
1091 template <typename Operand, typename Scalar>
1092#ifndef DOXYGEN
1093 typename boost::enable_if<
1094 typename ExpressionTraits<Scalar>::IsScalar,
1095 detail::UnaryOpExpression< Operand, typename detail::LogicalAnd::template ExprScalar<Operand,Scalar>::Bound >
1096 >::type
1097#else
1098 <unspecified-expression-type>
1099#endif
1100 logical_and(ExpressionBase<Operand> const & operand, Scalar const & scalar) {
1101 return vectorize(detail::LogicalAnd::template ExprScalar<Operand,Scalar>::bind(scalar),operand);
1102 }
1103
1104 template <typename Operand, typename Scalar>
1105#ifndef DOXYGEN
1106 typename boost::enable_if<
1107 typename ExpressionTraits<Scalar>::IsScalar,
1108 detail::UnaryOpExpression< Operand, typename detail::LogicalAnd::template ScalarExpr<Operand,Scalar>::Bound >
1109 >::type
1110#else
1111 <unspecified-expression-type>
1112#endif
1113 logical_and(Scalar const & scalar, ExpressionBase<Operand> const & operand) {
1114 return vectorize(detail::LogicalAnd::template ScalarExpr<Operand,Scalar>::bind(scalar),operand);
1115 }
1116
1117 template <typename Operand1, typename Operand2>
1118#ifndef DOXYGEN
1119 detail::BinaryOpExpression<
1120 Operand1, Operand2,
1121 typename detail::LogicalAnd::template ExprExpr<Operand1,Operand2>::BinaryFunction
1122 >
1123#else
1124 <unspecified-expression-type>
1125#endif
1126 logical_and(ExpressionBase<Operand1> const & operand1, ExpressionBase<Operand2> const & operand2) {
1127 return vectorize(
1128 typename detail::LogicalAnd::template ExprExpr<Operand1,Operand2>::BinaryFunction(),
1129 operand1,
1130 operand2
1131 );
1132 }
1133
1134 template <typename Operand, typename Scalar>
1135#ifndef DOXYGEN
1136 typename boost::enable_if<
1137 typename ExpressionTraits<Scalar>::IsScalar,
1138 detail::UnaryOpExpression< Operand, typename detail::LogicalOr::template ExprScalar<Operand,Scalar>::Bound >
1139 >::type
1140#else
1141 <unspecified-expression-type>
1142#endif
1143 logical_or(ExpressionBase<Operand> const & operand, Scalar const & scalar) {
1144 return vectorize(detail::LogicalOr::template ExprScalar<Operand,Scalar>::bind(scalar),operand);
1145 }
1146
1147 template <typename Operand, typename Scalar>
1148#ifndef DOXYGEN
1149 typename boost::enable_if<
1150 typename ExpressionTraits<Scalar>::IsScalar,
1151 detail::UnaryOpExpression< Operand, typename detail::LogicalOr::template ScalarExpr<Operand,Scalar>::Bound >
1152 >::type
1153#else
1154 <unspecified-expression-type>
1155#endif
1156 logical_or(Scalar const & scalar, ExpressionBase<Operand> const & operand) {
1157 return vectorize(detail::LogicalOr::template ScalarExpr<Operand,Scalar>::bind(scalar),operand);
1158 }
1159
1160 template <typename Operand1, typename Operand2>
1161#ifndef DOXYGEN
1162 detail::BinaryOpExpression<
1163 Operand1, Operand2,
1164 typename detail::LogicalOr::template ExprExpr<Operand1,Operand2>::BinaryFunction
1165 >
1166#else
1167 <unspecified-expression-type>
1168#endif
1169 logical_or(ExpressionBase<Operand1> const & operand1, ExpressionBase<Operand2> const & operand2) {
1170 return vectorize(
1171 typename detail::LogicalOr::template ExprExpr<Operand1,Operand2>::BinaryFunction(),
1172 operand1,
1173 operand2
1174 );
1175 }
1176
1177
1178 template <typename Operand>
1179#ifndef DOXYGEN
1180 detail::UnaryOpExpression< Operand, std::negate<typename ExpressionTraits<Operand>::Element> >
1181#else
1182 <unspecified-expression-type>
1183#endif
1184 operator-(ExpressionBase<Operand> const & operand) {
1185 return vectorize(std::negate<typename ExpressionTraits<Operand>::Element>(),operand);
1186 }
1187
1188 template <typename Operand>
1189#ifndef DOXYGEN
1190 detail::UnaryOpExpression< Operand, std::logical_not<typename ExpressionTraits<Operand>::Element> >
1191#else
1192 <unspecified-expression-type>
1193#endif
1194 logical_not(ExpressionBase<Operand> const & operand) {
1195 return vectorize(std::logical_not<typename ExpressionTraits<Operand>::Element>(),operand);
1196 }
1197
1198 template <typename Operand>
1199#ifndef DOXYGEN
1200 detail::UnaryOpExpression< Operand, detail::BitwiseNot<typename ExpressionTraits<Operand>::Element> >
1201#else
1202 <unspecified-expression-type>
1203#endif
1204 operator~(ExpressionBase<Operand> const & operand) {
1205 return vectorize(detail::BitwiseNot<typename ExpressionTraits<Operand>::Element>(),operand);
1206 }
1208
1209template <typename Scalar>
1210inline typename boost::enable_if<typename ExpressionTraits<Scalar>::IsScalar, bool>::type
1211any(Scalar const & scalar) {
1212 return bool(scalar);
1213}
1214
1220template <typename Derived>
1221inline bool
1222any(ExpressionBase<Derived> const & expr) {
1223 typename Derived::Iterator const i_end = expr.end();
1224 for (typename Derived::Iterator i = expr.begin(); i != i_end; ++i) {
1225 if (any(*i)) return true;
1226 }
1227 return false;
1228}
1229
1230template <typename Scalar>
1231inline typename boost::enable_if<typename ExpressionTraits<Scalar>::IsScalar, bool>::type
1232all(Scalar const & scalar) {
1233 return bool(scalar);
1234}
1235
1241template <typename Derived>
1242inline bool
1243all(ExpressionBase<Derived> const & expr) {
1244 typename Derived::Iterator const i_end = expr.end();
1245 for (typename Derived::Iterator i = expr.begin(); i != i_end; ++i) {
1246 if (!all(*i)) return false;
1247 }
1248 return true;
1249}
1250
1251template <typename Scalar1, typename Scalar2>
1252inline typename boost::enable_if<
1253 boost::mpl::and_<
1254 typename ExpressionTraits<Scalar1>::IsScalar,
1255 typename ExpressionTraits<Scalar2>::IsScalar
1256 >,
1257 bool
1258>::type
1259allclose(Scalar1 const & scalar1, Scalar2 const & scalar2, double tol=1E-8) {
1260 ApproximatelyEqual<Scalar1,Scalar2> func(tol);
1261 return func(scalar1, scalar2);
1262}
1263
1264template <typename Scalar, typename Derived>
1265inline typename boost::enable_if<typename ExpressionTraits<Scalar>::IsScalar,bool>::type
1266allclose(Scalar const & scalar, ExpressionBase<Derived> const & expr, double tol=1E-8) {
1267 ApproximatelyEqual<Scalar,typename Derived::Element> func(tol);
1268 typename Derived::Iterator const i_end = expr.end();
1269 for (typename Derived::Iterator i = expr.begin(); i != i_end; ++i) {
1270 if (!allclose(scalar, *i, tol)) return false;
1271 }
1272 return true;
1273}
1274
1275template <typename Scalar, typename Derived>
1276inline typename boost::enable_if<typename ExpressionTraits<Scalar>::IsScalar,bool>::type
1277allclose(ExpressionBase<Derived> const & expr, Scalar const & scalar, double tol=1E-8) {
1278 return allclose(scalar, expr, tol);
1279}
1280
1281template <typename Derived1, typename Derived2>
1282inline bool
1283allclose(ExpressionBase<Derived1> const & expr1, ExpressionBase<Derived2> const & expr2, double tol=1E-8) {
1284 typename Derived1::Iterator const i_end = expr1.end();
1285 typename Derived1::Iterator i = expr1.begin();
1286 typename Derived2::Iterator j = expr2.begin();
1287 for (; i != i_end; ++i, ++j) {
1288 if (!allclose(*i, *j, tol)) return false;
1289 }
1290 return true;
1291}
1292
1293
1294template <typename Scalar>
1295inline typename boost::enable_if<typename ExpressionTraits<Scalar>::IsScalar, Scalar>::type
1296sum(Scalar const & scalar) { return scalar; }
1297
1298
1304template <typename Derived>
1305inline typename Derived::Element
1306sum(ExpressionBase<Derived> const & expr) {
1307 typename Derived::Iterator const i_end = expr.end();
1308 typename Derived::Element total = static_cast<typename Derived::Element>(0);
1309 for (typename Derived::Iterator i = expr.begin(); i != i_end; ++i) {
1310 total += sum(*i);
1311 }
1312 return total;
1313}
1314
1315
1316} // namespace ndarray
1317
1318#endif // !NDARRAY_operators_h_INCLUDED
Definitions for Array.
Lazy binary expression templates.
Lazy unary expression templates.
CRTP base class for all multidimensional expressions.
Definition ExpressionBase.h:40
Iterator end() const
Return an Iterator to one past the end of the expression.
Definition ExpressionBase.h:70
Iterator begin() const
Return an Iterator to the beginning of the expression.
Definition ExpressionBase.h:67
std::ostream & operator<<(std::ostream &os, ExpressionBase< Derived > const &expr)
Stream output for ExpressionBase using default-constructed FormatOptions.
Definition formatting.h:72
boost::enable_if< typenameExpressionTraits< Scalar >::IsScalar, typenameUnaryFunction::result_type >::type vectorize(UnaryFunction const &functor, Scalar const &scalar)
Apply a non-mutating unary function object to a scalar.
Definition vectorize.h:73
Numeric type traits.