TECA
The Toolkit for Extreme Climate Analysis
teca_variant_array_operator.h
Go to the documentation of this file.
1 #ifndef teca_variant_array_operator
2 #define teca_variant_array_operator
3 
4 /// @file
5 
6 #include "teca_variant_array.h"
7 #include "teca_type_select.h"
8 
9 /// Codes dealing with run time specified operations on teca_variant_arrays
11 {
12 /// @cond
13 namespace internal
14 {
15 // --------------------------------------------------------------------------
16 template <typename nt_arg1, typename nt_arg2, typename nt_arg3,
17  typename operator_t, typename type_select_t =
19 p_teca_variant_array apply(unsigned long n,
20  const nt_arg1 *parg1, const nt_arg2 *parg2, const nt_arg3 *parg3,
21  const operator_t &op)
22 {
23  using nt_out = typename type_select_t::type;
24 
27 
28  nt_out *pout = out->get();
29 
30  for (unsigned long i = 0; i < n; ++i)
31  pout[i] = static_cast<nt_out>(op(parg1[i], parg2[i], parg3[i]));
32 
33  return out;
34 }
35 
36 // --------------------------------------------------------------------------
37 template <typename nt_larg, typename nt_rarg, typename operator_t,
38  typename type_select_t = typename teca_type_select::elevate<nt_larg, nt_rarg>>
39 p_teca_variant_array apply(unsigned long n,
40  const nt_larg *plarg, const nt_rarg *prarg, const operator_t &op)
41 {
42  using nt_out = typename type_select_t::type;
43 
46 
47  nt_out *pout = out->get();
48 
49  for (unsigned long i = 0; i < n; ++i)
50  pout[i] = static_cast<nt_out>(op(plarg[i], prarg[i]));
51 
52  return out;
53 }
54 
55 // --------------------------------------------------------------------------
56 template <typename nt_arg, typename operator_t>
57 p_teca_variant_array apply(unsigned long n,
58  const nt_arg *parg, const operator_t &op)
59 {
62 
63  nt_arg *pout = out->get();
64 
65  for (unsigned long i = 0; i < n; ++i)
66  pout[i] = static_cast<nt_arg>(op(parg[i]));
67 
68  return out;
69 }
70 };
71 /// @endcond
72 
73 // --------------------------------------------------------------------------
74 template <typename operator_t>
77  const operator_t &op)
78 {
80  arg1.get(), _1,
81  const NT_1 *parg1 = std::static_pointer_cast<TT_1>(arg1)->get();
83  arg2.get(), _2,
84  const NT_2 *parg2 = std::static_pointer_cast<TT_2>(arg2)->get();
86  arg2.get(), _3,
87  const NT_3 *parg3 = std::static_pointer_cast<TT_3>(arg3)->get();
88  return internal::apply(arg1->size(), parg1, parg2, parg3, op);
89  )
90  )
91  )
92  TECA_ERROR("failed to apply " << operator_t::name() << ". unsupported type.")
93  return nullptr;
94 }
95 
96 // --------------------------------------------------------------------------
97 template <typename operator_t>
99  const const_p_teca_variant_array &rarg, const operator_t &op)
100 {
102  larg.get(), _LEFT,
103  const NT_LEFT *plarg = std::static_pointer_cast<TT_LEFT>(larg)->get();
105  rarg.get(), _RIGHT,
106  const NT_RIGHT *prarg = std::static_pointer_cast<TT_RIGHT>(rarg)->get();
107  return internal::apply(larg->size(), plarg, prarg, op);
108  )
109  )
110  TECA_ERROR("failed to apply " << operator_t::name() << ". unsupported type.")
111  return nullptr;
112 }
113 
114 // --------------------------------------------------------------------------
115 template <typename operator_t>
117  const const_p_teca_variant_array &rarg, const operator_t &op)
118 {
120  larg.get(), _LEFT,
121  const NT_LEFT *plarg = std::static_pointer_cast<TT_LEFT>(larg)->get();
123  rarg.get(), _RIGHT,
124  const NT_RIGHT *prarg = std::static_pointer_cast<TT_RIGHT>(rarg)->get();
125  return internal::apply(larg->size(), plarg, prarg, op);
126  )
127  )
128  TECA_ERROR("failed to apply " << operator_t::name() << ". unsupported type.")
129  return nullptr;
130 }
131 
132 // --------------------------------------------------------------------------
133 template <typename operator_t>
135  const operator_t &op)
136 {
138  arg.get(),
139  const NT *parg = std::static_pointer_cast<TT>(arg)->get();
140  return internal::apply(arg->size(), parg, op);
141  )
142  TECA_ERROR("failed to apply " << operator_t::name() << ". unsupported type.")
143  return nullptr;
144 }
145 
147 {
148 template<typename nt_arg1, typename nt_arg2, typename nt_arg3,
149 typename nt_out = typename teca_type_select::elevate<nt_arg2, nt_arg3>::type>
150 nt_out operator()(const nt_arg1 &arg1, const nt_arg2 &arg2, const nt_arg3 &arg3) const
151 { return (arg1 ? static_cast<nt_out>(arg2) : static_cast<nt_out>(arg3)); }
152 static constexpr const char *name(){ return "ternary_condition"; }
153 };
154 
155 #define binary_operator(_name, _op) \
156 struct _name \
157 { \
158 template<typename nt_larg, typename nt_rarg, \
159 typename nt_out = typename teca_type_select::elevate<nt_larg, nt_rarg>::type> \
160 nt_out operator()(const nt_larg &larg, const nt_rarg &rarg) const \
161 { return static_cast<nt_out>(larg) _op static_cast<nt_out>(rarg); } \
162 static constexpr const char *name(){ return #_op; } \
163 };
164 
165 binary_operator(add, +)
166 binary_operator(subtract, -)
167 binary_operator(multiply, *)
168 binary_operator(divide, /)
169 binary_operator(modulo, %)
170 binary_operator(logical_and, &&)
171 binary_operator(logical_or, ||)
172 binary_operator(less, <)
173 binary_operator(less_equal, <=)
174 binary_operator(greater, >)
175 binary_operator(greater_equal, >=)
176 binary_operator(equal, ==)
177 binary_operator(not_equal, !=)
178 
179 #define binary_operator_fun(_name, _op) \
180 struct _name \
181 { \
182 template<typename nt_larg, typename nt_rarg, \
183 typename nt_out = typename teca_type_select::elevate<nt_larg, nt_rarg>::type> \
184 nt_out operator()(const nt_larg &larg, const nt_rarg &rarg) const \
185 { return _op(static_cast<nt_out>(larg), static_cast<nt_out>(rarg)); } \
186 static constexpr const char *name(){ return #_op; } \
187 };
188 
189 binary_operator_fun(power, std::pow)
190 
191 #define unary_operator(_name, _op) \
192 struct _name \
193 { \
194 template<typename nt_arg> \
195 nt_arg operator()(const nt_arg &arg) const \
196 { return static_cast<nt_arg>(_op arg); } \
197 static constexpr const char *name(){ return #_op; } \
198 };
199 
200 unary_operator(logical_not, !)
201 
202 struct resolver
203 {
204  static int invoke(const char *op, p_teca_variant_array &r,
206  const const_p_teca_variant_array &a3)
207  {
208  switch (*op)
209  {
210  case '?': r = apply(a1, a2, a3, ternary_condition()); return 0;
211  }
212  r = nullptr;
213  TECA_ERROR("binary operation " << op << " is not implemented")
214  return -1;
215  }
216  static int invoke(const char *op, p_teca_variant_array &r,
218  {
219  switch (*op)
220  {
221  case '=': r = apply(a1, a2, equal()); return 0;
222  case '!': r = apply(a1, a2, not_equal()); return 0;
223  case '<':
224  if (op[1] == '=') r = apply(a1, a2, less_equal());
225  else r = apply(a1, a2, less());
226  return 0;
227  case '>':
228  if (op[1] == '=') r = apply(a1, a2, greater_equal());
229  else r = apply(a1, a2, greater());
230  return 0;
231  case '&': r = apply(a1, a2, logical_and()); return 0;
232  case '|': r = apply(a1, a2, logical_or()); return 0;
233  case '+': r = apply(a1, a2, add()); return 0;
234  case '-': r = apply(a1, a2, subtract()); return 0;
235  case '*':
236  if (op[1] == '*') r = apply(a1, a2, power());
237  else r = apply(a1, a2, multiply());
238  return 0;
239  case '/': r = apply(a1, a2, divide()); return 0;
240  case '%': r = apply_i(a1, a2, modulo()); return 0;
241 
242  }
243  r = nullptr;
244  TECA_ERROR("binary operation " << op << " is not implemented")
245  return -1;
246  }
247 
248  static int invoke(const char *op, p_teca_variant_array &r,
249  const const_p_teca_variant_array &a1)
250  {
251  switch (*op)
252  {
253  case '!':
254  r = teca_variant_array_operator::apply(a1, logical_not());
255  return 0;
256  break;
257  }
258  r = nullptr;
259  TECA_ERROR("unary operation " << op << " is not implemented")
260  return -1;
261  }
262 
263 };
264 };
265 
266 #endif
teca_variant_array.h
teca_variant_array_operator::logical_or
Definition: teca_variant_array_operator.h:171
teca_variant_array_impl
The concrete implementation of our type agnostic container for contiguous arrays.
Definition: teca_variant_array.h:23
teca_variant_array_operator::subtract
Definition: teca_variant_array_operator.h:166
teca_variant_array_operator::greater_equal
Definition: teca_variant_array_operator.h:175
teca_variant_array_operator::resolver
Definition: teca_variant_array_operator.h:202
NESTED_TEMPLATE_DISPATCH
#define NESTED_TEMPLATE_DISPATCH(t, p, i, body)
Definition: teca_variant_array.h:276
teca_variant_array_operator
Codes dealing with run time specified operations on teca_variant_arrays.
Definition: teca_variant_array_operator.h:10
teca_type_select::elevate
Select the higher precision type.
Definition: teca_type_select.h:18
teca_variant_array_operator::less
Definition: teca_variant_array_operator.h:172
teca_coordinate_util::equal
bool equal(T a, T b, T relTol=equal_tt< T >::relTol(), T absTol=equal_tt< T >::absTol(), typename std::enable_if< std::is_floating_point< T >::value >::type *=0)
Definition: teca_coordinate_util.h:61
teca_variant_array_impl::get
T & get(unsigned long i)
Get the ith value.
Definition: teca_variant_array.h:565
teca_variant_array_operator::logical_and
Definition: teca_variant_array_operator.h:170
teca_variant_array_operator::less_equal
Definition: teca_variant_array_operator.h:173
teca_variant_array_operator::equal
Definition: teca_variant_array_operator.h:176
const_p_teca_variant_array
std::shared_ptr< const teca_variant_array > const_p_teca_variant_array
Definition: teca_variant_array.h:22
teca_variant_array_operator::not_equal
Definition: teca_variant_array_operator.h:177
TEMPLATE_DISPATCH
#define TEMPLATE_DISPATCH(t, p, body)
Definition: teca_variant_array.h:231
teca_variant_array_impl::New
static std::shared_ptr< teca_variant_array_impl< T > > New()
Definition: teca_variant_array.h:525
NESTED_TEMPLATE_DISPATCH_I
#define NESTED_TEMPLATE_DISPATCH_I(t, p, i, body)
Definition: teca_variant_array.h:255
teca_type_select.h
teca_variant_array_operator::logical_not
Definition: teca_variant_array_operator.h:200
teca_variant_array_operator::multiply
Definition: teca_variant_array_operator.h:167
p_teca_variant_array_impl
std::shared_ptr< teca_variant_array_impl< T > > p_teca_variant_array_impl
Definition: teca_variant_array.h:23
p_teca_variant_array
std::shared_ptr< teca_variant_array > p_teca_variant_array
Definition: teca_variant_array.h:22
teca_variant_array_operator::power
Definition: teca_variant_array_operator.h:189
teca_variant_array_operator::divide
Definition: teca_variant_array_operator.h:168
teca_variant_array_operator::modulo
Definition: teca_variant_array_operator.h:169
teca_variant_array_operator::add
Definition: teca_variant_array_operator.h:165
teca_variant_array_operator::ternary_condition
Definition: teca_variant_array_operator.h:146
TECA_ERROR
#define TECA_ERROR(_msg)
Constructs an error message and sends it to the stderr stream.
Definition: teca_common.h:138
teca_variant_array_operator::greater
Definition: teca_variant_array_operator.h:174