Geophysical Inversion and Modelling Library v1.5.4
Loading...
Searching...
No Matches
expressions.h
1/******************************************************************************
2 * Copyright (C) 2008-2024 by the GIMLi development team *
3 * Carsten Rücker carsten@resistivity.net *
4 * *
5 * Licensed under the Apache License, Version 2.0 (the "License"); *
6 * you may not use this file except in compliance with the License. *
7 * You may obtain a copy of the License at *
8 * *
9 * http://www.apache.org/licenses/LICENSE-2.0 *
10 * *
11 * Unless required by applicable law or agreed to in writing, software *
12 * distributed under the License is distributed on an "AS IS" BASIS, *
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
14 * See the License for the specific language governing permissions and *
15 * limitations under the License. *
16 * *
17 ******************************************************************************/
18
19#ifndef GIMLI_EXPRESSIONS__H
20#define GIMLI_EXPRESSIONS__H
21
22//** Idea taken from
23// @Article{Veldhuizen95b,
24// author = "Todd L. Veldhuizen",
25// title = "Expression templates",
26// journal = "C++ Report",
27// volume = "7",
28// number = "5",
29// pages = "26--31",
30// month = jun,
31// year = "1995",
32// note = "Reprinted in C++ Gems, ed. Stanley Lippman"
33// }
34
35#include <iostream>
36#include <cmath>
37
38namespace std{
39 // make std::less happy .. this wont work without this namespace
40 inline bool operator < (const std::complex< double > & a,
41 const std::complex< double > & b){
42 return a.real() < b.real() || (!(b.real() < a.real()) && a.imag() < b.imag());
43 }
44
45 inline bool operator > (const std::complex< double > & a,
46 const std::complex< double > & b){
47 return !(a < b);
48 }
49 inline bool operator >= (const std::complex< double > & a,
50 const std::complex< double > & b){
51 return (a > b) || (a==b);
52 }
53 inline bool operator <= (const std::complex< double > & a,
54 const std::complex< double > & b){
55 return (a < b) || (a==b);
56 }
57}
58
59namespace GIMLI{
60
61class ExprIdentity;
62template< class A > class Expr;
63template< class A > class ExprLiteral;
64
65struct XAxis__ {};
66struct YAxis__ {};
67struct ZAxis__ {};
68
69template <class T> struct Variable {
70};
71
72template<> struct Variable< XAxis__ > {
73 double operator()(const double x) const { return x; }
74 double operator()(const double x, const double y) const { return x; }
75 double operator()(const double x, const double y, const double z) const { return x; }
76};
77
78template<> struct Variable< YAxis__ > {
79 double operator()(const double x, const double y) const { return y; }
80 double operator()(const double x, const double y, const double z) const { return y; }
81};
82
83template<> struct Variable< ZAxis__ > {
84 double operator()(const double x, const double y, const double z) const { return z; }
85};
86
87typedef Expr< ExprIdentity > DPlaceholder;
88typedef Expr< ExprIdentity > IntPlaceholder;
89typedef Expr< ExprIdentity > Placeholder;
90typedef Expr< Variable<XAxis__> > VariableX;
91typedef Expr< Variable<YAxis__> > VariableY;
92typedef Expr< Variable<ZAxis__> > VariableZ;
93
94//**! Simple show the results of the expression
95template< class Ex > void show(Expr< Ex > expr, double start, double end, double step = 1.0){
96 for (double i = start; i < end; i += step) std::cout << expr(i) << std::endl;
97}
98
99template< class Ex > double sum(Expr< Ex > expr, double start, double end, double step){
100 double result = 0.0;
101 for (double i = start; i < end; i += step) result += expr(i);
102 return result;
103}
104
105template< class Ex > double sum(Expr< Ex > expr, double start, double end){
106 double result = 0.0;
107 for (double i = start; i < end; i += 1.0) result += expr(i);
108 return result;
109}
110#ifndef PI
111//** I redefine PI here, because vector.h should independ from alternative non std::headers, Ca
112#define PI 3.141592653589793238462643383279502884197169399375105820974944592308
113#define PI2 6.2831853071795864769252867665590057683942387987502116419498891846
114#define PI_2 1.5707963267948967384626433682795028841971193993751058209749445923
115#endif
116
117#define DEFINE_BINARY_OPERATOR__(OP, FUNCT) \
118struct OP { template < class T1, class T2 > inline T1 operator()(const T1 & a, const T2 & b) const { return a FUNCT b; } };\
119
120DEFINE_BINARY_OPERATOR__(PLUS, +)
121DEFINE_BINARY_OPERATOR__(MINUS, -)
122DEFINE_BINARY_OPERATOR__(MULT, *)
123DEFINE_BINARY_OPERATOR__(DIVID, /)
124
125#undef DEFINE_BINARY_OPERATOR__
126
127// inline bool isEqual(const Complex & a, const Complex & b) { return (a == b); }
128//inline bool isNonEqual(const double & a, const double & b) { return !isEqual(a, b); }
129//inline bool isNonEqual(const Complex & a, const Complex & b) { return (a != b); }
130template < class T > bool isEqual(const T & a, const T & b) { return a==b; }
131template < > inline bool isEqual(const double & a, const double & b) {
132 return (::fabs(a - b) < TOLERANCE); }
133template < > inline bool isEqual(const Complex & a, const Complex & b) {
134 return (::fabs(a.real() - b.real()) < TOLERANCE &&
135 ::fabs(a.imag() - b.imag()) < TOLERANCE); }
136template < class T > bool isNonEqual(const T & a, const T & b) { return !isEqual(a, b); }
137
138template < class T > bool isLesser(const T & a, const T & b) { return a < b; }
139template < class T > bool isGreater(const T & a, const T & b) { return a > b; }
140template < class T > bool isLesserEqual(const T & a, const T & b) { return a < b || isEqual(a, b); }
141template < class T > bool isGreaterEqual(const T & a, const T & b) { return a > b || isEqual(a, b); }
142
143
144#ifdef _MSC_VER
145template < class T > bool isInfNaN(const T & a){ return (isinf(a) || isnan(a)); }
146template < class T > bool isInf(const T & a){ return (isinf(a));}
147template < class T > bool isNaN(const T & a){ return (isnan(a));}
148inline bool isNaN(const Complex & a){ return (isnan(a.real()) || isnan(a.imag())); }
149inline bool isInf(const Complex & a){ return (isinf(a.real()) || isinf(a.imag())); }
150#else
151template < class T > bool isInfNaN(const T & a){ return (std::isinf(a) || std::isnan(a)); }
152template < class T > bool isInf(const T & a){ return (std::isinf(a));}
153template < class T > bool isNaN(const T & a){ return (std::isnan(a));}
154inline bool isNaN(const Complex & a){ return (std::isnan(a.real()) || std::isnan(a.imag())); }
155inline bool isInf(const Complex & a){ return (std::isinf(a.real()) || std::isinf(a.imag())); }
156#endif
157
158inline bool isInfNaN(const Complex & a){ return (isInfNaN(a.real()) || isInfNaN(a.imag())); }
159
160inline double abs(const double a) { return std::fabs(a); }
161inline double abs(const Complex & a) { return std::abs(a); }
162
163inline double conj(const double & a) { return a; }
164inline Complex conj(const Complex & a) { return std::conj(a); }
165
166inline Complex RINT(const Complex & a) { THROW_TO_IMPL; return Complex(0); }
167inline double RINT(const double & a) { return rint(a); }
168
169template < class T > T roundTo(const T & a, const T & tol){ return RINT(a / tol) * tol; }
170
171template < class T > T square(const T & a){ return a * a;}
172
173inline double cot(const double & a) { return 1.0 / std::tan(a); }
174inline double acot(const double & a) { return PI / 2.0 * std::atan(a); }
175inline double sign(const double & a) { return a > 0.0 ? 1.0 : (a < 0.0 ? -1.0 : 0.0); }
176inline double exp10(const double & a) { return std::pow(10.0, a); }
177
178
179// template < class T > inline T square(const T & a) { return a * a; }
180// template < class T > inline T cot(const T & a) { return 1.0 / std::tan(a); }
181// template < class T > inline T acot(const T & a) { return PI / 2.0 * std::atan(a); }
182#define DEFINE_UNARY_OPERATOR__(OP, FUNCT) \
183struct OP { template < class T > T operator()(const T & a) const { return FUNCT(a); } };\
184
185DEFINE_UNARY_OPERATOR__(ACOT, acot)
186DEFINE_UNARY_OPERATOR__(ABS_, std::fabs)
187DEFINE_UNARY_OPERATOR__(SIN , std::sin)
188DEFINE_UNARY_OPERATOR__(COS , std::cos)
189DEFINE_UNARY_OPERATOR__(COT , cot)
190DEFINE_UNARY_OPERATOR__(TAN , std::tan)
191DEFINE_UNARY_OPERATOR__(ATAN, std::atan)
192DEFINE_UNARY_OPERATOR__(TANH, std::tanh)
193DEFINE_UNARY_OPERATOR__(LOG , std::log)
194DEFINE_UNARY_OPERATOR__(LOG10, std::log10)
195DEFINE_UNARY_OPERATOR__(EXP , std::exp)
196DEFINE_UNARY_OPERATOR__(EXP10, exp10)
197DEFINE_UNARY_OPERATOR__(SQRT, std::sqrt)
198DEFINE_UNARY_OPERATOR__(SIGN, sign)
199DEFINE_UNARY_OPERATOR__(SQR, square)
200
201#undef DEFINE_UNARY_OPERATOR__
202
203#define DEFINE_UNARY_IF_FUNCTION__(OP, FUNCT) \
204struct OP { template < class T > bool operator()(const T & a) const { return FUNCT(a); } }; \
205
206DEFINE_UNARY_IF_FUNCTION__(ISINF, isInf)
207DEFINE_UNARY_IF_FUNCTION__(ISNAN, isNaN)
208DEFINE_UNARY_IF_FUNCTION__(ISINFNAN, isInfNaN)
209
210#undef DEFINE_UNARY_IF_FUNCTION__
211
214template< class A > class Expr {
215public:
216 Expr() : a_(A()){ }
217
218 Expr(const A & a) : a_(a){ }
219
220 template < class ValueType > inline ValueType operator()(const ValueType & x) const { return a_(x); }
221 template < class ValueType > inline ValueType operator()(const ValueType & x, const ValueType & y) const { return a_(x, y); }
222 template < class ValueType > inline ValueType operator()(const ValueType & x, const ValueType & y, const ValueType & z) const { return a_(x, y, z); }
223private:
224 A a_;
225};
226
227class ExprIdentity {
228public:
229 ExprIdentity(){ }
230
231 template < class ValueType > inline ValueType operator()(const ValueType & x) const { return x; }
232};
233
234template < class ValueType > class ExprLiteral {
235public:
236 ExprLiteral(const ValueType & value): value_(value){ }
237
238 inline ValueType operator()(const ValueType & x) const { return value_; }
239 inline ValueType operator()(const ValueType & x, const ValueType & y) const { return value_; }
240 inline ValueType operator()(const ValueType & x, const ValueType & y, const ValueType & z) const { return value_; }
241private:
242 ValueType value_;
243};
244
245template< class A, class Op > class UnaryExprOp {
246public:
247 UnaryExprOp(const A & a) : a_(a){ }
248 template < class ValueType > ValueType operator() (const ValueType & x) const {
249 return Op()(a_(x));
250 }
251 template < class ValueType > ValueType operator() (const ValueType & x, const ValueType & y) const {
252 return Op()(a_(x, y));
253 }
254 template < class ValueType > ValueType operator() (const ValueType & x, const ValueType & y, const ValueType & z) const {
255 return Op()(a_(x, y, z));
256 }
257private:
258 A a_;
259};
260
261template< class A, class B, class Op > class BinaryExprOp {
262public:
263 BinaryExprOp(const A & a, const B & b) : a_(a), b_(b){ }
264
265 template < class ValueType > ValueType operator() (const ValueType & x) const {
266 return Op()(a_(x), b_(x));
267 }
268 template < class ValueType > ValueType operator() (const ValueType & x, const ValueType & y) const {
269 return Op()(a_(x, y), b_(x, y));
270 }
271 template < class ValueType > ValueType operator() (const ValueType & x, const ValueType & y, const ValueType & z) const {
272 return Op()(a_(x, y, z), b_(x, y, z));
273 }
274private:
275 A a_;
276 B b_;
277};
278
279#define DEFINE_UNARY_EXPR_OPERATOR__(OP, FUNCT) \
280template< class A > Expr < UnaryExprOp < Expr< A >, FUNCT > >\
281 OP(const Expr< A > & a) { \
282 typedef UnaryExprOp< Expr< A >, FUNCT > ExprT; \
283 return Expr< ExprT >(ExprT(a));\
284}\
285
286DEFINE_UNARY_EXPR_OPERATOR__(abs, ABS_)
287DEFINE_UNARY_EXPR_OPERATOR__(acot, ACOT)
288DEFINE_UNARY_EXPR_OPERATOR__(atan, ATAN)
289DEFINE_UNARY_EXPR_OPERATOR__(cos, COS)
290DEFINE_UNARY_EXPR_OPERATOR__(cot, COT)
291DEFINE_UNARY_EXPR_OPERATOR__(exp, EXP)
292DEFINE_UNARY_EXPR_OPERATOR__(exp10, EXP10)
293DEFINE_UNARY_EXPR_OPERATOR__(fabs, ABS_)
294DEFINE_UNARY_EXPR_OPERATOR__(log, LOG)
295DEFINE_UNARY_EXPR_OPERATOR__(log10, LOG10)
296DEFINE_UNARY_EXPR_OPERATOR__(sign, SIGN)
297DEFINE_UNARY_EXPR_OPERATOR__(sin, SIN)
298DEFINE_UNARY_EXPR_OPERATOR__(sqrt, SQRT)
299DEFINE_UNARY_EXPR_OPERATOR__(square, SQR)
300DEFINE_UNARY_EXPR_OPERATOR__(tan, TAN)
301DEFINE_UNARY_EXPR_OPERATOR__(tanh, TANH)
302
303#undef DEFINE_UNARY_EXPR_OPERATOR__
304
305
306#define DEFINE_EXPR_OPERATOR__(OP, FUNCT) \
307template< class ValueType, class A > Expr < BinaryExprOp < ExprLiteral< ValueType >, Expr< A >, FUNCT > >\
308 operator OP (const ValueType & x, const Expr< A > & a) {\
309 typedef BinaryExprOp< ExprLiteral< ValueType >, Expr< A >, FUNCT > ExprT;\
310 return Expr< ExprT >(ExprT(ExprLiteral< ValueType >(x), a));\
311}\
312template< class ValueType, class A > Expr < BinaryExprOp < Expr< A >, ExprLiteral< ValueType >, FUNCT > >\
313 operator OP (const Expr< A > & a, const ValueType & x) {\
314 typedef BinaryExprOp< Expr< A >, ExprLiteral< ValueType >, FUNCT > ExprT;\
315 return Expr< ExprT >(ExprT(a, ExprLiteral< ValueType >(x)));\
316}\
317template < class A, class B > Expr< BinaryExprOp< Expr< A >, Expr< B >, FUNCT > >\
318 operator OP (const Expr< A > & a, const Expr< B > & b){\
319 typedef BinaryExprOp< Expr< A >, Expr< B >, FUNCT > ExprT;\
320 return Expr< ExprT >(ExprT(a, b));\
321}\
322
323DEFINE_EXPR_OPERATOR__(+, PLUS)
324DEFINE_EXPR_OPERATOR__(-, MINUS)
325DEFINE_EXPR_OPERATOR__(*, MULT)
326DEFINE_EXPR_OPERATOR__(/, DIVID)
327
328#undef DEFINE_EXPR_OPERATOR__
329
330} // namespace GIMLI
331
332#endif
Definition expressions.h:227
Definition expressions.h:234
Definition expressions.h:214
GIMLi main namespace for the Geophyiscal Inversion and Modelling Library.
Definition baseentity.h:24
RVector y(const R3Vector &rv)
Definition pos.cpp:114
RVector x(const R3Vector &rv)
Definition pos.cpp:107
RVector z(const R3Vector &rv)
Definition pos.cpp:120
Definition expressions.h:69
Definition expressions.h:65
Definition expressions.h:66
Definition expressions.h:67