All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
operators.h
1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 // names, trademarks, service marks, or product names of the Licensor
11 // and its affiliates, except as required to comply with Section 4(c) of
12 // the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 // http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 #ifndef VT_OPERATORS_H
25 #define VT_OPERATORS_H
26 
27 #include "pxr/pxr.h"
28 #include "pxr/base/vt/api.h"
29 
30 #include <boost/utility/enable_if.hpp>
31 #include <boost/type_traits/is_same.hpp>
32 
33 //
34 // Operators.h
35 //
36 // Define macros to make it easier to create and wrap operators that work
37 // with multiple types. In general, we want most operators to allow
38 // array OP array
39 // array OP scalar
40 // scalar OP array
41 // array OP tuple
42 // tuple OP array
43 // array OP list
44 // list OP array
45 //
46 // where the operators work element-by-element. For arrays, this means they
47 // need to be the same size and shape. For tuples and lists, this means
48 // the array shape is ignored, and the array and tuple/list need to contain the
49 // same number of elements. For scalars, this means the same scalar value is
50 // used for every array element. Naturally we require that the types held in
51 // the array, tuple, list, and scalar are all the same (i.e no multiplying
52 // a VtDoubleArray by a GfVec3d).
53 //
54 // However, we do have special cases for
55 // array OP double
56 // double OP array
57 // for some OPs, for cases where you may want to do element-by-element
58 // operations with a double when the array type is *not* double (e.g. Vec3d).
59 // This is done in Core/Anim, for example, for spline calculations on the
60 // underlying data type.
61 //
62 // We define macros because this is so repetitive, and because they need to be
63 // defined in different places (the array operators on the class, the array and
64 // scalar operators as free functions, and the tuple/list operators in the
65 // Python wrapping of course). Having them here allows us to put them all
66 // in one place for better editability.
67 
68 // -------------------------------------------------------------------------
69 // C++ operator definitions
70 // -------------------------------------------------------------------------
71 // These will be callable from C++, and define operations between arrays
72 // and between arrays and scalars.
73 
74 PXR_NAMESPACE_OPEN_SCOPE
75 
76 // Operations on arrays
77 // These go into the class definition for VtArray
78 #define VTOPERATOR_CPPARRAY(op) \
79  VtArray operator op (VtArray const &other) const { \
80  /* accept empty vecs */ \
81  if ((size()!=0 && other.size()!=0) && \
82  (size() != other.size())) { \
83  TF_CODING_ERROR("Non-conforming inputs for operator %s",#op); \
84  return VtArray(); \
85  } \
86  /* promote empty vecs to vecs of zeros */ \
87  const bool thisEmpty = size() == 0, \
88  otherEmpty = other.size() == 0; \
89  VtArray ret(thisEmpty ? other.size() : size()); \
90  ElementType zero = VtZero<ElementType>(); \
91  for (size_t i = 0, n = ret.size(); i != n; ++i) { \
92  ret[i] = (thisEmpty ? zero : (*this)[i]) op \
93  (otherEmpty ? zero : other[i]); \
94  } \
95  return ret; \
96  }
97 
98 #define VTOPERATOR_CPPARRAY_UNARY(op) \
99  VtArray operator op () const { \
100  VtArray ret(size()); \
101  for (size_t i = 0, sz = ret.size(); i != sz; ++i) { \
102  ret[i] = op (*this)[i]; \
103  } \
104  return ret; \
105  }
106 
107 // Operations on scalars and arrays
108 // These are free functions defined in Array.h
109 #define VTOPERATOR_CPPSCALAR_TYPE(op,arraytype,scalartype,rettype) \
110  template<typename arraytype> \
111  VtArray<ElemType> \
112  operator op (scalartype const &scalar, \
113  VtArray<arraytype> const &vec) { \
114  VtArray<rettype> ret(vec.size()); \
115  for (size_t i = 0; i<vec.size(); ++i) { \
116  ret[i] = scalar op vec[i]; \
117  } \
118  return ret; \
119  } \
120  template<typename arraytype> \
121  VtArray<ElemType> \
122  operator op (VtArray<arraytype> const &vec, \
123  scalartype const &scalar) { \
124  VtArray<rettype> ret(vec.size()); \
125  for (size_t i = 0; i<vec.size(); ++i) { \
126  ret[i] = vec[i] op scalar; \
127  } \
128  return ret; \
129  }
130 
131 #define VTOPERATOR_CPPSCALAR(op) \
132  VTOPERATOR_CPPSCALAR_TYPE(op,ElemType,ElemType,ElemType)
133 
134 // define special-case operators on arrays and doubles - except if the array
135 // holds doubles, in which case we already defined the operator (with
136 // VTOPERATOR_CPPSCALAR above) so we can't do it again!
137 #define VTOPERATOR_CPPSCALAR_DOUBLE(op) \
138  template<typename ElemType> \
139  typename boost::disable_if<boost::is_same<ElemType, double>, \
140  VtArray<ElemType> >::type \
141  operator op (double const &scalar, \
142  VtArray<ElemType> const &vec) { \
143  VtArray<ElemType> ret(vec.size()); \
144  for (size_t i = 0; i<vec.size(); ++i) { \
145  ret[i] = scalar op vec[i]; \
146  } \
147  return ret; \
148  } \
149  template<typename ElemType> \
150  typename boost::disable_if<boost::is_same<ElemType, double>, \
151  VtArray<ElemType> >::type \
152  operator op (VtArray<ElemType> const &vec, \
153  double const &scalar) { \
154  VtArray<ElemType> ret(vec.size()); \
155  for (size_t i = 0; i<vec.size(); ++i) { \
156  ret[i] = vec[i] op scalar; \
157  } \
158  return ret; \
159  }
160 
161 struct Vt_ShapeData;
162 
163 PXR_NAMESPACE_CLOSE_SCOPE
164 
165 #endif // VT_OPERATORS_H