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