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  auto spout = out->get_cpu_accessible();
29  nt_out *pout = spout.get();
30 
31  for (unsigned long i = 0; i < n; ++i)
32  pout[i] = static_cast<nt_out>(op(parg1[i], parg2[i], parg3[i]));
33 
34  return out;
35 }
36 
37 // --------------------------------------------------------------------------
38 template <typename nt_larg, typename nt_rarg, typename operator_t,
39  typename type_select_t = typename teca_type_select::elevate<nt_larg, nt_rarg>>
40 p_teca_variant_array apply(unsigned long n,
41  const nt_larg *plarg, const nt_rarg *prarg, const operator_t &op)
42 {
43  using nt_out = typename type_select_t::type;
44 
47 
48  auto spout = out->get_cpu_accessible();
49  nt_out *pout = spout.get();
50 
51  for (unsigned long i = 0; i < n; ++i)
52  pout[i] = static_cast<nt_out>(op(plarg[i], prarg[i]));
53 
54  return out;
55 }
56 
57 // --------------------------------------------------------------------------
58 template <typename nt_arg, typename operator_t>
59 p_teca_variant_array apply(unsigned long n,
60  const nt_arg *parg, const operator_t &op)
61 {
64 
65  auto spout = out->get_cpu_accessible();
66  nt_arg *pout = spout.get();
67 
68  for (unsigned long i = 0; i < n; ++i)
69  pout[i] = static_cast<nt_arg>(op(parg[i]));
70 
71  return out;
72 }
73 };
74 /// @endcond
75 
76 // --------------------------------------------------------------------------
77 template <typename operator_t>
80  const operator_t &op)
81 {
83  arg1.get(), _1,
84  auto sparg1 = static_cast<TT_1*>(arg1.get())->get_cpu_accessible();
85  auto parg1 = sparg1.get();
87  arg2.get(), _2,
88  auto sparg2 = static_cast<TT_2*>(arg2.get())->get_cpu_accessible();
89  auto parg2 = sparg2.get();
91  arg2.get(), _3,
92  auto sparg3 = static_cast<TT_3*>(arg3.get())->get_cpu_accessible();
93  auto parg3 = sparg3.get();
94  return internal::apply(arg1->size(), parg1, parg2, parg3, op);
95  )
96  )
97  )
98  TECA_ERROR("failed to apply " << operator_t::name() << ". unsupported type.")
99  return nullptr;
100 }
101 
102 // --------------------------------------------------------------------------
103 template <typename operator_t>
105  const const_p_teca_variant_array &rarg, const operator_t &op)
106 {
108  larg.get(), _LEFT,
109  auto splarg = static_cast<TT_LEFT*>(larg.get())->get_cpu_accessible();
110  auto plarg = splarg.get();
112  rarg.get(), _RIGHT,
113  auto sprarg = static_cast<TT_RIGHT*>(rarg.get())->get_cpu_accessible();
114  auto prarg = sprarg.get();
115  return internal::apply(larg->size(), plarg, prarg, op);
116  )
117  )
118  TECA_ERROR("failed to apply " << operator_t::name() << ". unsupported type.")
119  return nullptr;
120 }
121 
122 // --------------------------------------------------------------------------
123 template <typename operator_t>
125  const const_p_teca_variant_array &rarg, const operator_t &op)
126 {
128  larg.get(), _LEFT,
129  auto splarg = static_cast<TT_LEFT*>(larg.get())->get_cpu_accessible();
130  auto plarg = splarg.get();
132  rarg.get(), _RIGHT,
133  auto sprarg = static_cast<TT_RIGHT*>(rarg.get())->get_cpu_accessible();
134  auto prarg = sprarg.get();
135  return internal::apply(larg->size(), plarg, prarg, op);
136  )
137  )
138  TECA_ERROR("failed to apply " << operator_t::name() << ". unsupported type.")
139  return nullptr;
140 }
141 
142 // --------------------------------------------------------------------------
143 template <typename operator_t>
145  const operator_t &op)
146 {
148  arg.get(),
149  auto sparg = static_cast<TT*>(arg.get())->get_cpu_accessible();
150  auto parg = sparg.get();
151  return internal::apply(arg->size(), parg, op);
152  )
153  TECA_ERROR("failed to apply " << operator_t::name() << ". unsupported type.")
154  return nullptr;
155 }
156 
158 {
159 template<typename nt_arg1, typename nt_arg2, typename nt_arg3,
160 typename nt_out = typename teca_type_select::elevate<nt_arg2, nt_arg3>::type>
161 nt_out operator()(const nt_arg1 &arg1, const nt_arg2 &arg2, const nt_arg3 &arg3) const
162 { return (arg1 ? static_cast<nt_out>(arg2) : static_cast<nt_out>(arg3)); }
163 static constexpr const char *name(){ return "ternary_condition"; }
164 };
165 
166 #define binary_operator(_name, _op) \
167 struct _name \
168 { \
169 template<typename nt_larg, typename nt_rarg, \
170 typename nt_out = typename teca_type_select::elevate<nt_larg, nt_rarg>::type> \
171 nt_out operator()(const nt_larg &larg, const nt_rarg &rarg) const \
172 { return static_cast<nt_out>(larg) _op static_cast<nt_out>(rarg); } \
173 static constexpr const char *name(){ return #_op; } \
174 };
175 
176 binary_operator(add, +)
177 binary_operator(subtract, -)
178 binary_operator(multiply, *)
179 binary_operator(divide, /)
180 binary_operator(modulo, %)
181 binary_operator(logical_and, &&)
182 binary_operator(logical_or, ||)
183 binary_operator(less, <)
184 binary_operator(less_equal, <=)
185 binary_operator(greater, >)
186 binary_operator(greater_equal, >=)
187 binary_operator(equal, ==)
188 binary_operator(not_equal, !=)
189 
190 #define binary_operator_fun(_name, _op) \
191 struct _name \
192 { \
193 template<typename nt_larg, typename nt_rarg, \
194 typename nt_out = typename teca_type_select::elevate<nt_larg, nt_rarg>::type> \
195 nt_out operator()(const nt_larg &larg, const nt_rarg &rarg) const \
196 { return _op(static_cast<nt_out>(larg), static_cast<nt_out>(rarg)); } \
197 static constexpr const char *name(){ return #_op; } \
198 };
199 
200 binary_operator_fun(power, std::pow)
201 
202 #define unary_operator(_name, _op) \
203 struct _name \
204 { \
205 template<typename nt_arg> \
206 nt_arg operator()(const nt_arg &arg) const \
207 { return static_cast<nt_arg>(_op arg); } \
208 static constexpr const char *name(){ return #_op; } \
209 };
210 
211 unary_operator(logical_not, !)
212 
213 struct resolver
214 {
215  static int invoke(const char *op, p_teca_variant_array &r,
217  const const_p_teca_variant_array &a3)
218  {
219  switch (*op)
220  {
221  case '?': r = apply(a1, a2, a3, ternary_condition()); return 0;
222  }
223  r = nullptr;
224  TECA_ERROR("binary operation " << op << " is not implemented")
225  return -1;
226  }
227  static int invoke(const char *op, p_teca_variant_array &r,
229  {
230  switch (*op)
231  {
232  case '=': r = apply(a1, a2, equal()); return 0;
233  case '!': r = apply(a1, a2, not_equal()); return 0;
234  case '<':
235  if (op[1] == '=') r = apply(a1, a2, less_equal());
236  else r = apply(a1, a2, less());
237  return 0;
238  case '>':
239  if (op[1] == '=') r = apply(a1, a2, greater_equal());
240  else r = apply(a1, a2, greater());
241  return 0;
242  case '&': r = apply(a1, a2, logical_and()); return 0;
243  case '|': r = apply(a1, a2, logical_or()); return 0;
244  case '+': r = apply(a1, a2, add()); return 0;
245  case '-': r = apply(a1, a2, subtract()); return 0;
246  case '*':
247  if (op[1] == '*') r = apply(a1, a2, power());
248  else r = apply(a1, a2, multiply());
249  return 0;
250  case '/': r = apply(a1, a2, divide()); return 0;
251  case '%': r = apply_i(a1, a2, modulo()); return 0;
252 
253  }
254  r = nullptr;
255  TECA_ERROR("binary operation " << op << " is not implemented")
256  return -1;
257  }
258 
259  static int invoke(const char *op, p_teca_variant_array &r,
260  const const_p_teca_variant_array &a1)
261  {
262  switch (*op)
263  {
264  case '!':
265  r = teca_variant_array_operator::apply(a1, logical_not());
266  return 0;
267  break;
268  }
269  r = nullptr;
270  TECA_ERROR("unary operation " << op << " is not implemented")
271  return -1;
272  }
273 
274 };
275 };
276 
277 #endif
teca_variant_array.h
teca_variant_array_impl::get
void get(size_t i, U &val) const
Definition: teca_variant_array_impl.h:444
teca_variant_array_operator::logical_or
Definition: teca_variant_array_operator.h:182
teca_variant_array_impl
The concrete implementation of our type agnostic container for contiguous arrays.
Definition: teca_variant_array_impl.h:39
teca_variant_array_operator::subtract
Definition: teca_variant_array_operator.h:177
teca_variant_array_operator::greater_equal
Definition: teca_variant_array_operator.h:186
teca_variant_array_operator::resolver
Definition: teca_variant_array_operator.h:213
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:20
teca_variant_array_operator::less
Definition: teca_variant_array_operator.h:183
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:70
NESTED_TEMPLATE_DISPATCH
#define NESTED_TEMPLATE_DISPATCH(t, p, i, body)
Definition: teca_variant_array_impl.h:276
NESTED_TEMPLATE_DISPATCH_I
#define NESTED_TEMPLATE_DISPATCH_I(t, p, i, body)
Definition: teca_variant_array_impl.h:255
teca_variant_array_operator::logical_and
Definition: teca_variant_array_operator.h:181
teca_variant_array_operator::less_equal
Definition: teca_variant_array_operator.h:184
teca_variant_array_operator::equal
Definition: teca_variant_array_operator.h:187
const_p_teca_variant_array
std::shared_ptr< const teca_variant_array > const_p_teca_variant_array
Definition: teca_variant_array.h:27
teca_variant_array_operator::not_equal
Definition: teca_variant_array_operator.h:188
teca_type_select.h
teca_variant_array_operator::logical_not
Definition: teca_variant_array_operator.h:211
teca_variant_array_operator::multiply
Definition: teca_variant_array_operator.h:178
p_teca_variant_array
std::shared_ptr< teca_variant_array > p_teca_variant_array
Definition: teca_variant_array.h:27
teca_variant_array_operator::power
Definition: teca_variant_array_operator.h:200
teca_variant_array_operator::divide
Definition: teca_variant_array_operator.h:179
teca_variant_array_operator::modulo
Definition: teca_variant_array_operator.h:180
teca_variant_array_operator::add
Definition: teca_variant_array_operator.h:176
teca_variant_array_operator::ternary_condition
Definition: teca_variant_array_operator.h:157
p_teca_variant_array_impl
std::shared_ptr< teca_variant_array_impl< T > > p_teca_variant_array_impl
Definition: teca_variant_array_impl.h:39
TECA_ERROR
#define TECA_ERROR(_msg)
Constructs an error message and sends it to the stderr stream.
Definition: teca_common.h:146
teca_variant_array_operator::greater
Definition: teca_variant_array_operator.h:185
TEMPLATE_DISPATCH
#define TEMPLATE_DISPATCH(t, p, body)
Definition: teca_variant_array_impl.h:209
teca_variant_array_impl::New
static std::shared_ptr< teca_variant_array_impl< T > > New()
Definition: teca_variant_array_impl.h:326