1 /*
2 XLiFE++ is an extended library of finite elements written in C++
3 Copyright (C) 2014 Lunéville, Eric; Kielbasiewicz, Nicolas; Lafranche, Yvon; Nguyen, Manh-Ha; Chambeyron, Colin
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17 /*!
18 \file Value.cpp
19 \author E. Lunéville
20 \since 04 mar 2012
21 \date 04 may 2012
22
23 \brief Implementation of xlifepp::Value class members and related functions
24 */
25
26 #include "Value.hpp"
27
28 namespace xlifepp
29 {
30
31 //------------------------------------------------------------------------------------
32 // Value member functions
33 //------------------------------------------------------------------------------------
34
35 // copy constructor (full copy)
Value(const Value & v)36 Value::Value(const Value& v)
37 : type_(v.type_), struct_(v.struct_), conjugate_(v.conjugate_), transpose_(v.transpose_) {copyValue(v);}
38
copyValue(const Value & v)39 void Value::copyValue(const Value& v)
40 {
41 value_p = 0;
42 if(v.value_p != 0)
43 {
44 switch(struct_)
45 {
46 case _scalar:
47 switch(type_)
48 {
49 case _real: value_p = reinterpret_cast<void*>(new real_t(*reinterpret_cast<real_t*>(v.value_p))); return;
50 case _complex: value_p = reinterpret_cast<void*>(new complex_t(*reinterpret_cast<complex_t*>(v.value_p))); return;
51 default: return;
52 }
53 break;
54 case _vector:
55 switch(type_)
56 {
57 case _real: value_p = reinterpret_cast<void*>(new Vector<real_t>(*reinterpret_cast<Vector<real_t>*>(v.value_p))); return;
58 case _complex: value_p = reinterpret_cast<void*>(new Vector<complex_t>(*reinterpret_cast<Vector<complex_t>*>(v.value_p))); return;
59 default: return;
60 }
61 case _matrix:
62 switch(type_)
63 {
64 case _real: value_p = reinterpret_cast<void*>(new Matrix<real_t>(*reinterpret_cast<Matrix<real_t>*>(v.value_p))); return;
65 case _complex: value_p = reinterpret_cast<void*>(new Matrix<complex_t>(*reinterpret_cast<Matrix<complex_t>*>(v.value_p))); return;
66 default: return;
67 }
68 case _vectorofvector:
69 switch(type_)
70 {
71 case _real: value_p = reinterpret_cast<void*>(new Vector<Vector<real_t> >(*reinterpret_cast<Vector<Vector<real_t> >*>(v.value_p))); return;
72 case _complex: value_p = reinterpret_cast<void*>(new Vector<Vector<complex_t> >(*reinterpret_cast<Vector<Vector<complex_t> >*>(v.value_p))); return;
73 default: return;
74 }
75 case _vectorofmatrix:
76 switch(type_)
77 {
78 case _real: value_p = reinterpret_cast<void*>(new Vector<Matrix<real_t> >(*reinterpret_cast<Vector<Matrix<real_t> >*>(v.value_p))); return;
79 case _complex: value_p = reinterpret_cast<void*>(new Vector<Matrix<complex_t> >(*reinterpret_cast<Vector<Matrix<complex_t> >*>(v.value_p))); return;
80 default: return;
81 }
82 case _matrixofmatrix:
83 switch(type_)
84 {
85 case _real: value_p = reinterpret_cast<void*>(new Matrix<Matrix<real_t> >(*reinterpret_cast<Matrix<Matrix<real_t> >*>(v.value_p))); return;
86 case _complex: value_p = reinterpret_cast<void*>(new Matrix<Matrix<complex_t> >(*reinterpret_cast<Matrix<Matrix<complex_t> >*>(v.value_p))); return;
87 default: return;
88 }
89 default: return;
90 }
91 }
92 }
93
operator =(const Value & v)94 Value& Value::operator=(const Value& v)
95 {
96 if(this == &v) return *this;
97 clearValue();
98 type_ = v.type_;
99 struct_ = v.struct_;
100 conjugate_ = v.conjugate_;
101 transpose_ = v.transpose_;
102 copyValue(v);
103 return *this;
104 }
105
106 // constructors only for supported types
107 // the input values (given by users) are copied !
Value(const real_t & v)108 Value::Value(const real_t& v)
109 : type_(_real), struct_(_scalar), conjugate_(false), transpose_(false)
110 {
111 value_p = reinterpret_cast<void*>(new real_t(v));
112 }
113
Value(const Vector<real_t> & v)114 Value::Value(const Vector<real_t>& v)
115 : type_(_real), struct_(_vector), conjugate_(false), transpose_(false)
116 {
117 value_p = reinterpret_cast<void*>(new Vector<real_t>(v));
118 }
119
Value(const Matrix<real_t> & v)120 Value::Value(const Matrix<real_t>& v)
121 : type_(_real), struct_(_matrix), conjugate_(false), transpose_(false)
122 {
123 value_p = reinterpret_cast<void*>(new Matrix<real_t>(v));
124 }
125
Value(const Vector<Vector<real_t>> & v)126 Value::Value(const Vector<Vector<real_t> >& v)
127 : type_(_real), struct_(_vectorofvector), conjugate_(false), transpose_(false)
128 {
129 value_p = reinterpret_cast<void*>(new Vector<Vector<real_t> >(v));
130 }
131
Value(const Vector<Matrix<real_t>> & v)132 Value::Value(const Vector<Matrix<real_t> >& v)
133 : type_(_real), struct_(_vectorofmatrix), conjugate_(false), transpose_(false)
134 {
135 value_p = reinterpret_cast<void*>(new Vector<Matrix<real_t> >(v));
136 }
137
Value(const Matrix<Matrix<real_t>> & v)138 Value::Value(const Matrix<Matrix<real_t> >& v)
139 : type_(_real), struct_(_matrixofmatrix), conjugate_(false), transpose_(false)
140 {
141 value_p = reinterpret_cast<void*>(new Matrix<Matrix<real_t> >(v));
142 }
143
Value(const complex_t & v)144 Value::Value(const complex_t& v)
145 : type_(_complex), struct_(_scalar), conjugate_(false), transpose_(false)
146 {
147 value_p = reinterpret_cast<void*>(new complex_t(v));
148 }
149
Value(const Vector<complex_t> & v)150 Value::Value(const Vector<complex_t>& v)
151 : type_(_complex), struct_(_vector), conjugate_(false), transpose_(false)
152 {
153 value_p = reinterpret_cast<void*>(new Vector<complex_t>(v));
154 }
155
Value(const Matrix<complex_t> & v)156 Value::Value(const Matrix<complex_t>& v)
157 : type_(_complex), struct_(_matrix), conjugate_(false), transpose_(false)
158 {
159 value_p = reinterpret_cast<void*>(new Matrix<complex_t>(v));
160 }
161
Value(const Vector<Vector<complex_t>> & v)162 Value::Value(const Vector<Vector<complex_t> >& v)
163 : type_(_complex), struct_(_vectorofvector), conjugate_(false), transpose_(false)
164 {
165 value_p = reinterpret_cast<void*>(new Vector<Vector<complex_t> >(v));
166 }
167
Value(const Vector<Matrix<complex_t>> & v)168 Value::Value(const Vector<Matrix<complex_t> >& v)
169 : type_(_complex), struct_(_vectorofmatrix), conjugate_(false), transpose_(false)
170 {
171 value_p = reinterpret_cast<void*>(new Vector<Matrix<complex_t> >(v));
172 }
173
Value(const Matrix<Matrix<complex_t>> & v)174 Value::Value(const Matrix<Matrix<complex_t> >& v)
175 : type_(_complex), struct_(_matrixofmatrix), conjugate_(false), transpose_(false)
176 {
177 value_p = reinterpret_cast<void*>(new Matrix<Matrix<complex_t> >(v));
178 }
179
~Value()180 Value::~Value()
181 {
182 clearValue();
183 }
184
clearValue()185 void Value::clearValue()
186 {
187 if(value_p != 0)
188 {
189 switch(struct_)
190 {
191 case _scalar:
192 switch(type_)
193 {
194 case _real:
195 delete reinterpret_cast<real_t*>(value_p);
196 break;
197 case _complex:
198 delete reinterpret_cast<complex_t*>(value_p);
199 break;
200 default:
201 break;
202 }
203 break;
204 case _vector:
205 switch(type_)
206 {
207 case _real:
208 delete reinterpret_cast<Vector<real_t>* >(value_p);
209 break;
210 case _complex:
211 delete reinterpret_cast<Vector<complex_t>* >(value_p);
212 break;
213 default:
214 break;
215 }
216 break;
217 case _matrix:
218 switch(type_)
219 {
220 case _real:
221 delete reinterpret_cast<Matrix<real_t>* >(value_p);
222 break;
223 case _complex:
224 delete reinterpret_cast<Matrix<complex_t>* >(value_p);
225 break;
226 default:
227 break;
228 }
229 break;
230 case _vectorofvector:
231 switch(type_)
232 {
233 case _real:
234 delete reinterpret_cast<Vector<Vector<real_t> >* >(value_p);
235 break;
236 case _complex:
237 delete reinterpret_cast<Vector<Vector<complex_t> >* >(value_p);
238 break;
239 default:
240 break;
241 }
242 break;
243 case _vectorofmatrix:
244 switch(type_)
245 {
246 case _real:
247 delete reinterpret_cast<Vector<Matrix<real_t> >* >(value_p);
248 break;
249 case _complex:
250 delete reinterpret_cast<Vector<Matrix<complex_t> >* >(value_p);
251 break;
252 default:
253 break;
254 }
255 break;
256 case _matrixofmatrix:
257 switch(type_)
258 {
259 case _real:
260 delete reinterpret_cast<Matrix<Matrix<real_t> >* >(value_p);
261 break;
262 case _complex:
263 delete reinterpret_cast<Matrix<Matrix<complex_t> >* >(value_p);
264 break;
265 default:
266 break;
267 }
268 break;
269 default:
270 break;
271 }
272 }
273 }
274
275 //return dimensions of value as a pair of dimensions, (1,1) in scalar case
dims() const276 dimPair Value::dims() const
277 {
278 switch(struct_)
279 {
280 case _vector:
281 switch(type_)
282 {
283 case _real: return dimPair(reinterpret_cast<Vector<real_t>* >(value_p)->size(),1);
284 default: return dimPair(reinterpret_cast<Vector<complex_t>* >(value_p)->size(),1);
285 }
286 break;
287 case _matrix:
288 switch(type_)
289 {
290 case _real: return reinterpret_cast<Matrix<real_t>* >(value_p)->dims();
291 default : return reinterpret_cast<Matrix<real_t>* >(value_p)->dims();
292 }
293 break;
294 case _vectorofvector:
295 switch(type_)
296 {
297 case _real: return dimPair(reinterpret_cast<Vector<Vector<real_t> >* >(value_p)->size(),1);
298 default: return dimPair(reinterpret_cast<Vector<Vector<complex_t> >* >(value_p)->size(),1);
299 }
300 break;
301 case _vectorofmatrix:
302 switch(type_)
303 {
304 case _real: return dimPair(reinterpret_cast<Vector<Matrix<real_t> >* >(value_p)->size(),1);
305 default: return dimPair(reinterpret_cast<Vector<Matrix<complex_t> >* >(value_p)->size(),1);
306 }
307 break;
308 case _matrixofmatrix:
309 switch(type_)
310 {
311 case _real:return reinterpret_cast<Matrix<Matrix<real_t> >* >(value_p)->dims();
312 default: return reinterpret_cast<Matrix<Matrix<complex_t> >* >(value_p)->dims();
313 }
314 break;
315 default:
316 break;
317 }
318 return dimPair(1,1);
319 }
320
321 // initialization of RTI names of value types
322 // real_t, Vector<real_t>, Matrix<real_t>, complex_t, Vector<complex_t>, Matrix<complex_t>
valueTypeRTINamesInit()323 void Value::valueTypeRTINamesInit()
324 {
325 Value v;
326 theValueTypeRTInames.insert(mapPair(string_t(typeid(v).name()), structPair(_real, _scalar)));
327 real_t r;
328 theValueTypeRTInames.insert(mapPair(string_t(typeid(r).name()), structPair(_real, _scalar)));
329 Vector<real_t> vr;
330 theValueTypeRTInames.insert(mapPair(string_t(typeid(vr).name()), structPair(_real, _vector)));
331 Matrix<real_t> mr;
332 theValueTypeRTInames.insert(mapPair(string_t(typeid(mr).name()), structPair(_real, _matrix)));
333 Vector<Vector<real_t> > vvr;
334 theValueTypeRTInames.insert(mapPair(string_t(typeid(vvr).name()), structPair(_real, _vectorofvector)));
335 Vector<Matrix<real_t> > vmr;
336 theValueTypeRTInames.insert(mapPair(string_t(typeid(vmr).name()), structPair(_real, _vectorofmatrix)));
337 Matrix<Matrix<real_t> > mmr;
338 theValueTypeRTInames.insert(mapPair(string_t(typeid(mmr).name()), structPair(_real, _matrixofmatrix)));
339 complex_t c;
340 theValueTypeRTInames.insert(mapPair(string_t(typeid(c).name()), structPair(_complex, _scalar)));
341 Vector<complex_t> vc;
342 theValueTypeRTInames.insert(mapPair(string_t(typeid(vc).name()), structPair(_complex, _vector)));
343 Matrix<complex_t> mc;
344 theValueTypeRTInames.insert(mapPair(string_t(typeid(mc).name()), structPair(_complex, _matrix)));
345 Vector<Vector<complex_t> > vvc;
346 theValueTypeRTInames.insert(mapPair(string_t(typeid(vvc).name()), structPair(_complex, _vectorofvector)));
347 Vector<Matrix<complex_t> > vmc;
348 theValueTypeRTInames.insert(mapPair(string_t(typeid(vmc).name()), structPair(_complex, _vectorofmatrix)));
349 Matrix<Matrix<complex_t> > mmc;
350 theValueTypeRTInames.insert(mapPair(string_t(typeid(mmc).name()), structPair(_complex, _matrixofmatrix)));
351 }
352
353 // print utility
printValueTypeRTINames(std::ostream & os)354 void Value::printValueTypeRTINames(std::ostream& os) //! print RTI names
355 {
356 std::map<string_t, structPair>::iterator it;
357 os << message("value_RTInames") << "\n";
358 for(it = theValueTypeRTInames.begin(); it != theValueTypeRTInames.end(); it++)
359 {
360 os << it->first << " -> (" << words("value", (it->second).first) << "," << words("structure", (it->second).second) << ")\n";
361 }
362
363 }
364
print(std::ostream & os) const365 void Value::print(std::ostream& os) const
366 {
367 if(theVerboseLevel > 0)
368 { os << "Value of type (" << words("value", type_) << "," << words("structure", struct_) << ")"; }
369 if(theVerboseLevel == 0)
370 {
371 os << std::endl;
372 return;
373 }
374 os << " =";
375
376 switch(struct_)
377 {
378 case _scalar:
379 {
380 if(type_ == _real) { os << value<real_t>(); }
381 else { os << value<complex_t>(); }
382 break;
383 }
384 case _vector :
385 {
386 if(type_ == _real) { os << value<Vector<real_t> >(); }
387 else { os << value<Vector<complex_t> >(); }
388 break;
389 }
390 case _matrix :
391 {
392 if(type_ == _real) { os << value<Matrix<real_t> >(); }
393 else { os << value<Matrix<complex_t> >(); }
394 break;
395 }
396 case _vectorofvector :
397 {
398 if(type_ == _real) { os << value<Vector<Vector<real_t> > >(); }
399 else { os << value<Vector<Vector<complex_t> > >(); }
400 break;
401 }
402 case _vectorofmatrix :
403 {
404 if(type_ == _real) { os << value<Vector<Matrix<real_t> > >(); }
405 else { os << value<Vector<Matrix<complex_t> > >(); }
406 break;
407 }
408 case _matrixofmatrix :
409 {
410 if(type_ == _real) { os << value<Matrix<Matrix<real_t> > >(); }
411 else { os << value<Matrix<Matrix<complex_t> > >(); }
412 break;
413 }
414 default : os << "undefined value";
415 }
416 os << "\n";
417 }
418
operator <<(std::ostream & os,const Value & val)419 std::ostream& operator<<(std::ostream& os, const Value& val)
420 {
421 val.print(os);
422 return os;
423 }
424
opposite()425 void Value::opposite()
426 {
427 if(value_p != 0) return; //nothing done
428 switch(struct_)
429 {
430 case _scalar:
431 {
432 if(type_ == _real)
433 {real_t& val = value<real_t>(); val = -val; return;}
434 complex_t& val = value<complex_t>(); val = -val; return;
435 }
436 case _vector :
437 {
438 if(type_ == _real)
439 {Vector<real_t>& val = value<Vector<real_t> >(); val = -val; return;}
440 Vector<complex_t>& val = value<Vector<complex_t> >(); val = -val; return;
441 }
442 case _matrix :
443 {
444 if(type_ == _real)
445 {Matrix<real_t>& val = value<Matrix<real_t> >(); val = -val; return;}
446 Matrix<complex_t>& val = value<Matrix<complex_t> >(); val = -val; return;
447 }
448 case _vectorofvector :
449 {
450 if(type_ == _real)
451 {Vector<Vector<real_t> >& val = value<Vector<Vector<real_t> > >(); val = -val; return;}
452 Vector<Vector<complex_t> >& val = value<Vector<Vector<complex_t> > >(); val = -val; return;
453 }
454 case _vectorofmatrix :
455 {
456 if(type_ == _real)
457 {Vector<Matrix<real_t> >& val = value<Vector<Matrix<real_t> > >(); val = -val; return;}
458 Vector<Matrix<complex_t> >& val = value<Vector<Matrix<complex_t> > >(); val = -val; return;
459 }
460 case _matrixofmatrix :
461 {
462 if(type_ == _real)
463 {Matrix<Matrix<real_t> >& val = value<Matrix<Matrix<real_t> > >(); val = -val; return;}
464 Matrix<Matrix<complex_t> >& val = value<Matrix<Matrix<complex_t> > >(); val = -val; return;
465 }
466 default : break; //nothing done
467 }
468 }
469
470 //! set to true or false the temporary conjugate flag
conj(Value & v)471 Value& conj(Value& v)
472 {
473 v.conjugate_ = !v.conjugate_;
474 return v;
475 }
476
477 //! set to true or false the temporary transpose flag
trans(Value & v)478 Value& trans(Value& v)
479 {
480 v.transpose_ = !v.transpose_;
481 return v;
482 }
483
484 //! set to true or false the temporary conjugate/transpose flag
adj(Value & v)485 Value& adj(Value& v)
486 {
487 v.transpose_ = !v.transpose_;
488 v.conjugate_ = !v.conjugate_;
489 return v;
490 }
491
operator -(const Value & v)492 Value operator-(const Value& v) //opposite of a value
493 {
494 Value w(v);
495 w.opposite();
496 return w;
497 }
498
499 //compare values
operator ==(const Value & v1,const Value & v2)500 bool operator==(const Value& v1, const Value& v2)
501 {
502 if(v1.valueType() != v2.valueType()) return false;
503 if(v1.strucType() != v2.strucType()) return false;
504 switch(v1.strucType())
505 {
506 case _scalar:
507 {
508 if(v1.valueType() == _real) return v1.value<real_t>() == v2.value<real_t>();
509 return v1.value<complex_t>() == v2.value<complex_t>();
510 }
511 case _vector :
512 {
513 if(v1.valueType() == _real) return v1.value<Vector<real_t> >() == v2.value<Vector<real_t> >();
514 return v1.value<Vector<complex_t> >() == v2.value<Vector<complex_t> >();
515 }
516 case _matrix :
517 {
518 if(v1.valueType() == _real) return v1.value<Matrix<real_t> >() == v2.value<Matrix<real_t> >();
519 return v1.value<Matrix<complex_t> >() == v2.value<Matrix<complex_t> >();
520 }
521 case _vectorofvector :
522 {
523 if(v1.valueType() == _real) return v1.value<Vector<Vector<real_t> > >() == v2.value<Vector<Vector<real_t> > >();
524 return v1.value<Vector<Vector<complex_t> > >() == v2.value<Vector<Vector<complex_t> > >();
525 }
526 case _vectorofmatrix :
527 {
528 if(v1.valueType() == _real) return v1.value<Vector<Matrix<real_t> > >() == v2.value<Vector<Matrix<real_t> > >();
529 return v1.value<Vector<Matrix<complex_t> > >() == v2.value<Vector<Matrix<complex_t> > >();
530 }
531 case _matrixofmatrix :
532 {
533 if(v1.valueType() == _real) return v1.value<Matrix<Matrix<real_t> > >() == v2.value<Matrix<Matrix<real_t> > >();
534 return v1.value<Matrix<Matrix<complex_t> > >() == v2.value<Matrix<Matrix<complex_t> > >();
535 }
536 default : break; //nothing done
537 }
538 return true;
539 }
540
operator !=(const Value & v1,const Value & v2)541 bool operator!=(const Value& v1, const Value& v2)
542 {
543 return !(v1 == v2);
544 }
545
546 //specialisation of value evaluation
value() const547 template<> real_t Value::value<real_t>() const
548 {
549 if(struct_==_scalar && type_ ==_real) return *(reinterpret_cast<real_t*>(value_p));
550 where("Value::value<Real>");
551 error("value_wrongtype",words("structure",struct_),words("value",type_),words("structure",_scalar),words("value",_real));
552 return 0;
553 }
554
value() const555 template<> complex_t Value::value<complex_t>() const
556 {
557 if(struct_==_scalar)
558 {
559 if(type_==_real) return complex_t(*(reinterpret_cast<real_t*>(value_p)));
560 else return *(reinterpret_cast<complex_t*>(value_p));
561 }
562 where("Value::value<Complex>");
563 error("value_wrongtype",words("structure",struct_),words("value",type_),words("structure",_scalar),words("value",_complex));
564 return 0;
565 }
566
value() const567 template<> Vector<real_t> Value::value<Vector<real_t> >() const
568 {
569 if(struct_==_vector && type_ ==_real) return *(reinterpret_cast<Vector<real_t>* >(value_p));
570 where("Value::value<Vector<Real> >");
571 error("value_wrongtype",words("structure",struct_),words("value",type_),words("structure",_vector),words("value",_real));
572 return 0;
573 }
574
value() const575 template<> Vector<complex_t> Value::value<Vector<complex_t> >() const
576 {
577 if(struct_==_vector)
578 {
579 if(type_==_real) return cmplx(*(reinterpret_cast<Vector<real_t>* >(value_p)));
580 else return *(reinterpret_cast<Vector<complex_t> *>(value_p));
581 }
582 where("Value::value<Vector<Complex> >");
583 error("value_wrongtype",words("structure",struct_),words("value",type_),words("structure",_vector),words("value",_complex));
584 return 0;
585 }
586
value() const587 template<> Matrix<real_t> Value::value<Matrix<real_t> >() const
588 {
589 if(struct_==_matrix && type_ ==_real) return *(reinterpret_cast<Matrix<real_t>* >(value_p));
590 where("Value::value<Matrix<Real> >");
591 error("value_wrongtype",words("structure",struct_),words("value",type_),words("structure",_matrix),words("value",_real));
592 return 0;
593 }
594
value() const595 template<> Matrix<complex_t> Value::value<Matrix<complex_t> >() const
596 {
597 if(struct_==_matrix)
598 {
599 if(type_==_real) return cmplx(*(reinterpret_cast<Matrix<real_t>* >(value_p)));
600 else return *(reinterpret_cast<Matrix<complex_t> *>(value_p));
601 }
602 where("Value::value<Matrix<Complex> >");
603 error("value_wrongtype",words("structure",struct_),words("value",type_),words("structure",_matrix),words("value",_complex));
604 return 0;
605 }
606 //not done for Vector<Vector<T> >and Matrix<Matrix<T> >
607
608 } // end of namespace xlifepp
609