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