1 /***************************************************************************
2 basic_op_sub.cpp - GDL sub (-) operators
3 -------------------
4 begin : July 22 2002
5 copyright : (C) 2002 by Marc Schellens
6 email : m_schellens@users.sf.net
7 ***************************************************************************/
8
9 /***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
22
23 #ifdef _OPENMP
24 #include <omp.h>
25 #endif
26
27 //#include "datatypes.hpp" // for friend declaration
28 #include "nullgdl.hpp"
29 #include "dinterpreter.hpp"
30
31 // needed with gcc-3.3.2
32 #include <cassert>
33
34 // Sub
35 // substraction: left=left-right
36 template<class Sp>
Sub(BaseGDL * r)37 BaseGDL* Data_<Sp>::Sub( BaseGDL* r)
38 {
39 Data_* right=static_cast<Data_*>(r);
40
41 ULong rEl=right->N_Elements();
42 ULong nEl=N_Elements();
43 assert( rEl);
44 assert( nEl);
45 // if( !rEl || !nEl) throw GDLException("Variable is undefined.");
46 if( nEl == 1)
47 {
48 (*this)[0] -= (*right)[0];
49 return this;
50 }
51 #ifdef USE_EIGEN
52
53 Eigen::Map<Eigen::Array<Ty,Eigen::Dynamic,1> ,Eigen::Aligned> mThis(&(*this)[0], nEl);
54 Eigen::Map<Eigen::Array<Ty,Eigen::Dynamic,1> ,Eigen::Aligned> mRight(&(*right)[0], nEl);
55 mThis -= mRight;
56 return this;
57 #else
58
59 if( nEl == rEl)
60 dd -= right->dd;
61 else
62 {
63 TRACEOMP( __FILE__, __LINE__)
64 #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl))
65 {
66 #pragma omp for
67 for( OMPInt i=0; i < nEl; ++i)
68 (*this)[i] -= (*right)[i];
69 }} //C delete right;
70 return this;
71 #endif
72
73 }
74 // inverse substraction: left=right-left
75 template<class Sp>
SubInv(BaseGDL * r)76 BaseGDL* Data_<Sp>::SubInv( BaseGDL* r)
77 {
78 Data_* right=static_cast<Data_*>(r);
79
80 ULong rEl=right->N_Elements();
81 ULong nEl=N_Elements();
82 assert( rEl);
83 assert( nEl);
84 // if( !rEl || !nEl) throw GDLException("Variable is undefined.");
85 /* if( nEl == rEl)
86 dd = right->dd - dd;
87 else*/
88 if( nEl == 1)
89 {
90 (*this)[0] = (*right)[0] - (*this)[0];
91 return this;
92 }
93 #ifdef USE_EIGEN
94
95 Eigen::Map<Eigen::Array<Ty,Eigen::Dynamic,1> ,Eigen::Aligned> mThis(&(*this)[0], nEl);
96 Eigen::Map<Eigen::Array<Ty,Eigen::Dynamic,1> ,Eigen::Aligned> mRight(&(*right)[0], nEl);
97 mThis = mRight - mThis;
98 return this;
99 #else
100 TRACEOMP( __FILE__, __LINE__)
101 #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl))
102 {
103 #pragma omp for
104 for( OMPInt i=0; i < nEl; ++i)
105 (*this)[i] = (*right)[i] - (*this)[i];
106 } //C delete right;
107 return this;
108 #endif
109
110 }
111 // invalid types
112 template<>
Sub(BaseGDL * r)113 BaseGDL* Data_<SpDString>::Sub( BaseGDL* r)
114 {
115 throw GDLException("Cannot apply operation to datatype STRING.",true,false);
116 return this;
117 }
118 template<>
SubInv(BaseGDL * r)119 BaseGDL* Data_<SpDString>::SubInv( BaseGDL* r)
120 {
121 throw GDLException("Cannot apply operation to datatype STRING.",true,false);
122 return this;
123 }
124 template<>
Sub(BaseGDL * r)125 BaseGDL* Data_<SpDPtr>::Sub( BaseGDL* r)
126 {
127 throw GDLException("Cannot apply operation to datatype PTR.",true,false);
128 return this;
129 }
130 template<>
SubInv(BaseGDL * r)131 BaseGDL* Data_<SpDPtr>::SubInv( BaseGDL* r)
132 {
133 throw GDLException("Cannot apply operation to datatype PTR.",true,false);
134 return this;
135 }
136 template<>
Sub(BaseGDL * r)137 BaseGDL* Data_<SpDObj>::Sub( BaseGDL* r)
138 {
139 // overload here
140 Data_* self;
141 DSubUD* plusOverload;
142
143 ProgNodeP callingNode = interpreter->GetRetTree();
144
145 if( !Scalar())
146 {
147 if( r->Type() == GDL_OBJ && r->Scalar())
148 {
149 self = static_cast<Data_*>( r);
150 plusOverload = static_cast<DSubUD*>(GDLInterpreter::GetObjHeapOperator( (*self)[0], OOMinus));
151 if( plusOverload == NULL)
152 {
153 throw GDLException( callingNode, "Cannot apply not overloaded operator to datatype OBJECT.", true, false);
154 }
155 }
156 else
157 {
158 throw GDLException( callingNode, "Cannot apply operation to non-scalar datatype OBJECT.", true, false);
159 }
160 }
161 else
162 {
163 // Scalar()
164 self = static_cast<Data_*>( this);
165 plusOverload = static_cast<DSubUD*>(GDLInterpreter::GetObjHeapOperator( (*self)[0], OOMinus));
166 if( plusOverload == NULL)
167 {
168 if( r->Type() == GDL_OBJ && r->Scalar())
169 {
170 self = static_cast<Data_*>( r);
171 plusOverload = static_cast<DSubUD*>(GDLInterpreter::GetObjHeapOperator( (*self)[0], OOMinus));
172 if( plusOverload == NULL)
173 {
174 throw GDLException(callingNode,"Cannot apply not overloaded operator to datatype OBJECT.",true, false);
175 }
176 }
177 else
178 {
179 throw GDLException( callingNode, "Cannot apply not overloaded operator to datatype OBJECT.", true, false);
180 }
181 }
182 }
183
184 assert( self->Scalar());
185 assert( plusOverload != NULL);
186
187 // hidden SELF is counted as well
188 int nParSub = plusOverload->NPar();
189 assert( nParSub >= 1); // SELF
190 if( nParSub < 3) // (SELF), LEFT, RIGHT
191 {
192 throw GDLException( callingNode, plusOverload->ObjectName() +
193 ": Incorrect number of arguments.",
194 false, false);
195 }
196 EnvUDT* newEnv;
197 Guard<BaseGDL> selfGuard;
198 BaseGDL* thisP;
199 // Dup() here is not optimal
200 // avoid at least for internal overload routines (which do/must not change SELF or r)
201 bool internalDSubUD = plusOverload->GetTree()->IsWrappedNode();
202 if( internalDSubUD)
203 {
204 thisP = this;
205 newEnv= new EnvUDT( callingNode, plusOverload, &self);
206 newEnv->SetNextParUnchecked( &thisP); // LEFT parameter, as reference to prevent cleanup in newEnv
207 newEnv->SetNextParUnchecked( &r); // RVALUE parameter, as reference to prevent cleanup in newEnv
208 }
209 else
210 {
211 self = self->Dup();
212 selfGuard.Init( self);
213 newEnv= new EnvUDT( callingNode, plusOverload, &self);
214 newEnv->SetNextParUnchecked( this->Dup()); // LEFT parameter, as value
215 newEnv->SetNextParUnchecked( r->Dup()); // RIGHT parameter, as value
216 }
217
218
219 // better than auto_ptr: auto_ptr wouldn't remove newEnv from the stack
220 StackGuard<EnvStackT> guard(interpreter->CallStack());
221
222 interpreter->CallStack().push_back( newEnv);
223
224 // make the call
225 BaseGDL* res=interpreter->call_fun(static_cast<DSubUD*>(newEnv->GetPro())->GetTree());
226
227 if( !internalDSubUD && self != selfGuard.Get())
228 {
229 // always put out warning first, in case of a later crash
230 Warning( "WARNING: " + plusOverload->ObjectName() +
231 ": Assignment to SELF detected (GDL session still ok).");
232 // assignment to SELF -> self was deleted and points to new variable
233 // which it owns
234 selfGuard.Release();
235 if( static_cast<BaseGDL*>(self) != NullGDL::GetSingleInstance())
236 selfGuard.Reset(self);
237 }
238 return res;
239 }
240 template<>
SubInv(BaseGDL * r)241 BaseGDL* Data_<SpDObj>::SubInv( BaseGDL* r)
242 {
243 if( r->Type() == GDL_OBJ && r->Scalar())
244 {
245 return r->Sub( this); // for right order of parameters
246 }
247
248 // overload here
249 Data_* self;
250 DSubUD* plusOverload;
251
252 ProgNodeP callingNode = interpreter->GetRetTree();
253
254 if( !Scalar())
255 {
256 throw GDLException( callingNode, "Cannot apply operation to non-scalar datatype OBJECT.", true, false);
257 }
258 else
259 {
260 // Scalar()
261 self = static_cast<Data_*>( this);
262 plusOverload = static_cast<DSubUD*>(GDLInterpreter::GetObjHeapOperator( (*self)[0], OOMinus));
263 if( plusOverload == NULL)
264 {
265 throw GDLException( callingNode, "Cannot apply not overloaded operator to datatype OBJECT.", true, false);
266 }
267 }
268
269 assert( self->Scalar());
270 assert( plusOverload != NULL);
271
272 // hidden SELF is counted as well
273 int nParSub = plusOverload->NPar();
274 assert( nParSub >= 1); // SELF
275 if( nParSub < 3) // (SELF), LEFT, RIGHT
276 {
277 throw GDLException( callingNode, plusOverload->ObjectName() +
278 ": Incorrect number of arguments.",
279 false, false);
280 }
281 EnvUDT* newEnv;
282 Guard<BaseGDL> selfGuard;
283 BaseGDL* thisP;
284 // Dup() here is not optimal
285 // avoid at least for internal overload routines (which do/must not change SELF or r)
286 bool internalDSubUD = plusOverload->GetTree()->IsWrappedNode();
287 if( internalDSubUD)
288 {
289 thisP = this;
290 newEnv= new EnvUDT( callingNode, plusOverload, &self);
291 // order different to Add
292 newEnv->SetNextParUnchecked( &r); // RVALUE parameter, as reference to prevent cleanup in newEnv
293 newEnv->SetNextParUnchecked( &thisP); // LEFT parameter, as reference to prevent cleanup in newEnv
294 }
295 else
296 {
297 self = self->Dup();
298 selfGuard.Init( self);
299 newEnv= new EnvUDT( callingNode, plusOverload, &self);
300 // order different to Add
301 newEnv->SetNextParUnchecked( r->Dup()); // RIGHT parameter, as value
302 newEnv->SetNextParUnchecked( this->Dup()); // LEFT parameter, as value
303 }
304
305
306 // better than auto_ptr: auto_ptr wouldn't remove newEnv from the stack
307 StackGuard<EnvStackT> guard(interpreter->CallStack());
308
309 interpreter->CallStack().push_back( newEnv);
310
311 // make the call
312 BaseGDL* res=interpreter->call_fun(static_cast<DSubUD*>(newEnv->GetPro())->GetTree());
313
314 if( !internalDSubUD && self != selfGuard.Get())
315 {
316 // always put out warning first, in case of a later crash
317 Warning( "WARNING: " + plusOverload->ObjectName() +
318 ": Assignment to SELF detected (GDL session still ok).");
319 // assignment to SELF -> self was deleted and points to new variable
320 // which it owns
321 selfGuard.Release();
322 if( static_cast<BaseGDL*>(self) != NullGDL::GetSingleInstance())
323 selfGuard.Reset(self);
324 }
325 return res;
326 }
327 template<class Sp>
SubS(BaseGDL * r)328 Data_<Sp>* Data_<Sp>::SubS( BaseGDL* r)
329 {
330 Data_* right=static_cast<Data_*>(r);
331
332 ULong nEl=N_Elements();
333 assert( nEl);
334 if( nEl == 1)
335 {
336 (*this)[0] -= (*right)[0];
337 return this;
338 }
339
340 Ty s = (*right)[0];
341 // right->Scalar(s);
342 // dd -= s;
343 #ifdef USE_EIGEN
344
345 Eigen::Map<Eigen::Array<Ty,Eigen::Dynamic,1> ,Eigen::Aligned> mThis(&(*this)[0], nEl);
346 mThis -= s;
347 return this;
348 #else
349 TRACEOMP( __FILE__, __LINE__)
350 #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl))
351 {
352 #pragma omp for
353 for( OMPInt i=0; i < nEl; ++i)
354 (*this)[i] -= s;
355 } //C delete right;
356 return this;
357 #endif
358
359 }
360 // inverse substraction: left=right-left
361 template<class Sp>
SubInvS(BaseGDL * r)362 Data_<Sp>* Data_<Sp>::SubInvS( BaseGDL* r)
363 {
364 Data_* right=static_cast<Data_*>(r);
365
366 ULong nEl=N_Elements();
367 assert( nEl);
368
369 if( nEl == 1)
370 {
371 (*this)[0] = (*right)[0] - (*this)[0];
372 return this;
373 }
374
375 Ty s = (*right)[0];
376 // right->Scalar(s);
377 // dd = s - dd;
378 #ifdef USE_EIGEN
379
380 Eigen::Map<Eigen::Array<Ty,Eigen::Dynamic,1> ,Eigen::Aligned> mThis(&(*this)[0], nEl);
381 mThis = s - mThis;
382 return this;
383 #else
384 TRACEOMP( __FILE__, __LINE__)
385 #pragma omp parallel if (nEl >= CpuTPOOL_MIN_ELTS && (CpuTPOOL_MAX_ELTS == 0 || CpuTPOOL_MAX_ELTS <= nEl))
386 {
387 #pragma omp for
388 for( OMPInt i=0; i < nEl; ++i)
389 (*this)[i] = s - (*this)[i];
390 } //C delete right;
391 return this;
392 #endif
393
394 }
395 // invalid types
396 template<>
SubS(BaseGDL * r)397 Data_<SpDString>* Data_<SpDString>::SubS( BaseGDL* r)
398 {
399 throw GDLException("Cannot apply operation to datatype STRING.",true,false);
400 return this;
401 }
402 template<>
SubInvS(BaseGDL * r)403 Data_<SpDString>* Data_<SpDString>::SubInvS( BaseGDL* r)
404 {
405 throw GDLException("Cannot apply operation to datatype STRING.",true,false);
406 return this;
407 }
408 template<>
SubS(BaseGDL * r)409 Data_<SpDPtr>* Data_<SpDPtr>::SubS( BaseGDL* r)
410 {
411 throw GDLException("Cannot apply operation to datatype PTR.",true,false);
412 return this;
413 }
414 template<>
SubInvS(BaseGDL * r)415 Data_<SpDPtr>* Data_<SpDPtr>::SubInvS( BaseGDL* r)
416 {
417 throw GDLException("Cannot apply operation to datatype PTR.",true,false);
418 return this;
419 }
420 template<>
SubS(BaseGDL * r)421 Data_<SpDObj>* Data_<SpDObj>::SubS( BaseGDL* r)
422 {
423 throw GDLException("Cannot apply operation to datatype OBJECT.",true,false);
424 return this;
425 }
426 template<>
SubInvS(BaseGDL * r)427 Data_<SpDObj>* Data_<SpDObj>::SubInvS( BaseGDL* r)
428 {
429 throw GDLException("Cannot apply operation to datatype OBJECT.",true,false);
430 return this;
431 }
432
433 #include "instantiate_templates.hpp"
434