1 /*
2 This file is part of CDO. CDO is a collection of Operators to manipulate and analyse Climate model Data.
3
4 Author: Uwe Schulzweida
5
6 */
7
8 #include "cdo_output.h"
9 #include "field.h"
10
11 template <typename T>
12 static void
fieldc_mul(size_t len,size_t nmiss,Varray<T> & v,const T missval,const double rconst)13 fieldc_mul(size_t len, size_t nmiss, Varray<T> &v, const T missval, const double rconst)
14 {
15 const auto missval1 = missval;
16 const auto missval2 = missval;
17
18 if (nmiss)
19 {
20 for (size_t i = 0; i < len; i++) v[i] = MULMN(v[i], rconst);
21 }
22 else
23 {
24 for (size_t i = 0; i < len; i++) v[i] *= rconst;
25 }
26 }
27
28 void
fieldc_mul(Field & field,const double rconst)29 fieldc_mul(Field &field, const double rconst)
30 {
31 if (field.memType == MemType::Float)
32 fieldc_mul(field.size, field.nmiss, field.vec_f, (float) field.missval, rconst);
33 else
34 fieldc_mul(field.size, field.nmiss, field.vec_d, field.missval, rconst);
35 }
36
37 template <typename T>
38 static size_t
fieldc_div(size_t len,size_t nmiss,Varray<T> & v,const T missval,const double rconst)39 fieldc_div(size_t len, size_t nmiss, Varray<T> &v, const T missval, const double rconst)
40 {
41 const auto missval1 = missval;
42 const auto missval2 = missval;
43
44 if (nmiss || IS_EQUAL(rconst, 0))
45 {
46 for (size_t i = 0; i < len; i++) v[i] = DIVMN(v[i], rconst);
47
48 if (IS_EQUAL(rconst, 0)) nmiss = len;
49 }
50 else
51 {
52 for (size_t i = 0; i < len; i++) v[i] /= rconst;
53 }
54
55 return nmiss;
56 }
57
58 void
fieldc_div(Field & field,const double rconst)59 fieldc_div(Field &field, const double rconst)
60 {
61 if (field.memType == MemType::Float)
62 field.nmiss = fieldc_div(field.size, field.nmiss, field.vec_f, (float) field.missval, rconst);
63 else
64 field.nmiss = fieldc_div(field.size, field.nmiss, field.vec_d, field.missval, rconst);
65 }
66
67 template <typename T>
68 static void
fieldc_add(size_t len,size_t nmiss,Varray<T> & v,const T missval,const double rconst)69 fieldc_add(size_t len, size_t nmiss, Varray<T> &v, const T missval, const double rconst)
70 {
71 const auto missval1 = missval;
72 const auto missval2 = missval;
73
74 if (nmiss)
75 {
76 for (size_t i = 0; i < len; i++) v[i] = ADDMN(v[i], rconst);
77 }
78 else
79 {
80 for (size_t i = 0; i < len; i++) v[i] += rconst;
81 }
82 }
83
84 void
fieldc_add(Field & field,const double rconst)85 fieldc_add(Field &field, const double rconst)
86 {
87 if (field.memType == MemType::Float)
88 fieldc_add(field.size, field.nmiss, field.vec_f, (float) field.missval, rconst);
89 else
90 fieldc_add(field.size, field.nmiss, field.vec_d, field.missval, rconst);
91 }
92
93 void
fieldc_sub(Field & field,const double rconst)94 fieldc_sub(Field &field, const double rconst)
95 {
96 fieldc_add(field, -rconst);
97 }
98
99 template <typename T>
100 static void
fieldc_min(size_t len,size_t nmiss,Varray<T> & v,const T missval,const T rconst)101 fieldc_min(size_t len, size_t nmiss, Varray<T> &v, const T missval, const T rconst)
102 {
103 const auto missval1 = missval;
104
105 if (nmiss)
106 {
107 for (size_t i = 0; i < len; i++)
108 if (DBL_IS_EQUAL(v[i], missval1) || v[i] > rconst) v[i] = rconst;
109 }
110 else
111 {
112 for (size_t i = 0; i < len; i++)
113 if (v[i] > rconst) v[i] = rconst;
114 }
115 }
116
117 void
fieldc_min(Field & field,const double rconst)118 fieldc_min(Field &field, const double rconst)
119 {
120 if (field.memType == MemType::Float)
121 fieldc_min(field.size, field.nmiss, field.vec_f, (float) field.missval, (float) rconst);
122 else
123 fieldc_min(field.size, field.nmiss, field.vec_d, field.missval, rconst);
124 }
125
126 template <typename T>
127 static void
fieldc_max(size_t len,size_t nmiss,Varray<T> & v,const T missval,const T rconst)128 fieldc_max(size_t len, size_t nmiss, Varray<T> &v, const T missval, const T rconst)
129 {
130 const auto missval1 = missval;
131
132 if (nmiss)
133 {
134 for (size_t i = 0; i < len; i++)
135 if (DBL_IS_EQUAL(v[i], missval1) || v[i] < rconst) v[i] = rconst;
136 }
137 else
138 {
139 for (size_t i = 0; i < len; i++)
140 if (v[i] < rconst) v[i] = rconst;
141 }
142 }
143
144 void
fieldc_max(Field & field,const double rconst)145 fieldc_max(Field &field, const double rconst)
146 {
147 if (field.memType == MemType::Float)
148 fieldc_max(field.size, field.nmiss, field.vec_f, (float) field.missval, (float) rconst);
149 else
150 fieldc_max(field.size, field.nmiss, field.vec_d, field.missval, rconst);
151 }
152
153 template <typename T>
154 static void
fieldc_mod(size_t len,size_t nmiss,Varray<T> & v,const T missval,const double divisor)155 fieldc_mod(size_t len, size_t nmiss, Varray<T> &v, const T missval, const double divisor)
156 {
157 (void)nmiss;
158 const auto missval1 = missval;
159
160 for (size_t i = 0; i < len; i++)
161 {
162 v[i] = DBL_IS_EQUAL(v[i], missval1) ? missval1 : std::fmod((double) v[i], divisor);
163 }
164 }
165
166 void
fieldc_mod(Field & field,const double divisor)167 fieldc_mod(Field &field, const double divisor)
168 {
169 if (field.memType == MemType::Float)
170 fieldc_mod(field.size, field.nmiss, field.vec_f, (float) field.missval, divisor);
171 else
172 fieldc_mod(field.size, field.nmiss, field.vec_d, field.missval, divisor);
173 }
174
175 void
fieldc_function(Field & field,const double rconst,const int function)176 fieldc_function(Field &field, const double rconst, const int function)
177 {
178 switch (function)
179 {
180 case FieldFunc_Add: fieldc_add(field, rconst); break;
181 case FieldFunc_Sub: fieldc_sub(field, rconst); break;
182 case FieldFunc_Mul: fieldc_mul(field, rconst); break;
183 case FieldFunc_Div: fieldc_div(field, rconst); break;
184 case FieldFunc_Min: fieldc_min(field, rconst); break;
185 case FieldFunc_Max: fieldc_max(field, rconst); break;
186 case FieldFunc_Mod: fieldc_mod(field, rconst); break;
187 default: cdo_abort("%s: function %d not implemented!", __func__, function);
188 }
189 }
190