1 /** \file
2     \brief Definition of functions for complex valued operations.
3 
4 <pre>
5                __________                                 ____  ___
6     _____  __ _\______   \_____ _______  ______ __________\   \/  /
7    /     \|  |  \     ___/\__  \\_  __ \/  ___// __ \_  __ \     /
8   |  Y Y  \  |  /    |     / __ \|  | \/\___ \\  ___/|  | \/     \
9   |__|_|  /____/|____|    (____  /__|  /____  >\___  >__| /___/\  \
10         \/                     \/           \/     \/           \_/
11                                        Copyright (C) 2016 Ingo Berg
12                                        All rights reserved.
13 
14   muParserX - A C++ math parser library with array and string support
15   Copyright (c) 2016, Ingo Berg
16   All rights reserved.
17 
18   Redistribution and use in source and binary forms, with or without
19   modification, are permitted provided that the following conditions are met:
20 
21    * Redistributions of source code must retain the above copyright notice,
22      this list of conditions and the following disclaimer.
23    * Redistributions in binary form must reproduce the above copyright notice,
24      this list of conditions and the following disclaimer in the documentation
25      and/or other materials provided with the distribution.
26 
27   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
28   ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
29   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
30   IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
31   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
32   NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
34   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36   POSSIBILITY OF SUCH DAMAGE.
37 </pre>
38 */
39 #include "mpFuncCmplx.h"
40 
41 //--- Standard includes ----------------------------------------------------
42 #include <cmath>
43 #include <cassert>
44 #include <complex>
45 #include <iostream>
46 
47 //--- Parser framework -----------------------------------------------------
48 #include "mpValue.h"
49 #include "mpError.h"
50 
51 
52 MUP_NAMESPACE_START
53 
54   //-----------------------------------------------------------------------
55   //
56   //  class FunCmplxReal
57   //
58   //-----------------------------------------------------------------------
59 
FunCmplxReal()60   FunCmplxReal::FunCmplxReal()
61     :ICallback(cmFUNC, _T("real"), 1)
62   {}
63 
64   //-----------------------------------------------------------------------
~FunCmplxReal()65   FunCmplxReal::~FunCmplxReal()
66   {}
67 
68   //-----------------------------------------------------------------------
Eval(ptr_val_type & ret,const ptr_val_type * a_pArg,int)69   void FunCmplxReal::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
70   {
71     float_type v = a_pArg[0]->GetFloat();
72     *ret = v;
73   }
74 
75   //-----------------------------------------------------------------------
GetDesc() const76   const char_type* FunCmplxReal::GetDesc() const
77   {
78     return _T("real(x) - Returns the real part of the complex number x.");
79   }
80 
81   //-----------------------------------------------------------------------
Clone() const82   IToken* FunCmplxReal::Clone() const
83   {
84     return new FunCmplxReal(*this);
85   }
86 
87   //-----------------------------------------------------------------------
88   //
89   //  class FunCmplxImag
90   //
91   //-----------------------------------------------------------------------
92 
FunCmplxImag()93   FunCmplxImag::FunCmplxImag()
94     :ICallback(cmFUNC, _T("imag"), 1)
95   {}
96 
97   //-----------------------------------------------------------------------
Eval(ptr_val_type & ret,const ptr_val_type * a_pArg,int)98   void FunCmplxImag::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
99   {
100     float_type v = a_pArg[0]->GetImag();
101     *ret = v;
102   }
103 
104   //-----------------------------------------------------------------------
GetDesc() const105   const char_type* FunCmplxImag::GetDesc() const
106   {
107     return _T("imag(x) - Returns the imaginary part of the complex number x.");
108   }
109 
110   //-----------------------------------------------------------------------
Clone() const111   IToken* FunCmplxImag::Clone() const
112   {
113     return new FunCmplxImag(*this);
114   }
115 
116   //-----------------------------------------------------------------------
117   //
118   //  class FunCmplxConj
119   //
120   //-----------------------------------------------------------------------
121 
FunCmplxConj()122   FunCmplxConj::FunCmplxConj()
123     :ICallback(cmFUNC, _T("conj"), 1)
124   {}
125 
126   //-----------------------------------------------------------------------
Eval(ptr_val_type & ret,const ptr_val_type * a_pArg,int)127   void FunCmplxConj::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
128   {
129     *ret = cmplx_type(a_pArg[0]->GetFloat(), -a_pArg[0]->GetImag());
130   }
131 
132   //-----------------------------------------------------------------------
GetDesc() const133   const char_type* FunCmplxConj::GetDesc() const
134   {
135     return _T("conj(x) - Returns the complex conjugate of the complex number x.");
136   }
137 
138   //-----------------------------------------------------------------------
Clone() const139   IToken* FunCmplxConj::Clone() const
140   {
141     return new FunCmplxConj(*this);
142   }
143 
144   //-----------------------------------------------------------------------
145   //
146   //  class FunCmplxArg
147   //
148   //-----------------------------------------------------------------------
149 
FunCmplxArg()150   FunCmplxArg::FunCmplxArg()
151     :ICallback(cmFUNC, _T("arg"), 1)
152   {}
153 
154   //-----------------------------------------------------------------------
Eval(ptr_val_type & ret,const ptr_val_type * a_pArg,int)155   void FunCmplxArg::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
156   {
157     cmplx_type v(a_pArg[0]->GetFloat(), a_pArg[0]->GetImag());
158     *ret = std::arg(v);
159   }
160 
161   //-----------------------------------------------------------------------
GetDesc() const162   const char_type* FunCmplxArg::GetDesc() const
163   {
164     return _T("arg(x) - Returns the phase angle (or angular component) of the complex number x, expressed in radians.");
165   }
166 
167   //-----------------------------------------------------------------------
Clone() const168   IToken* FunCmplxArg::Clone() const
169   {
170     return new FunCmplxArg(*this);
171   }
172 
173   //-----------------------------------------------------------------------
174   //
175   //  class FunCmplxNorm
176   //
177   //-----------------------------------------------------------------------
178 
FunCmplxNorm()179   FunCmplxNorm::FunCmplxNorm()
180     :ICallback(cmFUNC, _T("norm"), 1)
181   {}
182 
183   //-----------------------------------------------------------------------
Eval(ptr_val_type & ret,const ptr_val_type * a_pArg,int)184   void FunCmplxNorm::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
185   {
186     cmplx_type v(a_pArg[0]->GetFloat(), a_pArg[0]->GetImag());
187     *ret = std::norm(v);
188   }
189 
190   //-----------------------------------------------------------------------
GetDesc() const191   const char_type* FunCmplxNorm::GetDesc() const
192   {
193     return _T("norm(x) - Returns the norm value of the complex number x.")
194            _T(" The norm value of a complex number is the squared magnitude,")
195            _T(" defined as the addition of the square of both the real part")
196            _T(" and the imaginary part (without the imaginary unit). This is")
197            _T(" the square of abs (x).");
198   }
199 
200   //-----------------------------------------------------------------------
Clone() const201   IToken* FunCmplxNorm::Clone() const
202   {
203     return new FunCmplxNorm(*this);
204   }
205 
206   //-----------------------------------------------------------------------
207   //
208   //  class FunCmplxCos
209   //
210   //-----------------------------------------------------------------------
211 
FunCmplxCos()212   FunCmplxCos::FunCmplxCos()
213     :ICallback(cmFUNC, _T("cos"), 1)
214   {}
215 
216   //-----------------------------------------------------------------------
Eval(ptr_val_type & ret,const ptr_val_type * a_pArg,int)217   void FunCmplxCos::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
218   {
219     if (a_pArg[0]->IsNonComplexScalar())
220     {
221       *ret = std::cos(a_pArg[0]->GetFloat());
222     }
223     else
224     {
225       cmplx_type v(a_pArg[0]->GetFloat(), a_pArg[0]->GetImag());
226       *ret = std::cos(v);
227     }
228   }
229 
230   //-----------------------------------------------------------------------
GetDesc() const231   const char_type* FunCmplxCos::GetDesc() const
232   {
233     return _T("cos(x) - Returns the cosine of the number x.");
234   }
235 
236   //-----------------------------------------------------------------------
Clone() const237   IToken* FunCmplxCos::Clone() const
238   {
239     return new FunCmplxCos(*this);
240   }
241 
242   //-----------------------------------------------------------------------
243   //
244   //  class FunCmplxSin
245   //
246   //-----------------------------------------------------------------------
247 
FunCmplxSin()248   FunCmplxSin::FunCmplxSin()
249     :ICallback(cmFUNC, _T("sin"), 1)
250   {}
251 
252   //-----------------------------------------------------------------------
Eval(ptr_val_type & ret,const ptr_val_type * a_pArg,int)253   void FunCmplxSin::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
254   {
255     if (a_pArg[0]->IsNonComplexScalar())
256     {
257       *ret = std::sin(a_pArg[0]->GetFloat());
258     }
259     else
260     {
261       cmplx_type v(a_pArg[0]->GetFloat(), a_pArg[0]->GetImag());
262       *ret = std::sin(v);
263     }
264   }
265 
266   //-----------------------------------------------------------------------
GetDesc() const267   const char_type* FunCmplxSin::GetDesc() const
268   {
269     return _T("sin(x) - Returns the sine of the number x.");
270   }
271 
272   //-----------------------------------------------------------------------
Clone() const273   IToken* FunCmplxSin::Clone() const
274   {
275     return new FunCmplxSin(*this);
276   }
277 
278   //-----------------------------------------------------------------------
279   //
280   //  class FunCmplxCosH
281   //
282   //-----------------------------------------------------------------------
283 
FunCmplxCosH()284   FunCmplxCosH::FunCmplxCosH()
285     :ICallback(cmFUNC, _T("cosh"), 1)
286   {}
287 
288   //-----------------------------------------------------------------------
Eval(ptr_val_type & ret,const ptr_val_type * a_pArg,int)289   void FunCmplxCosH::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
290   {
291     cmplx_type v(a_pArg[0]->GetFloat(), a_pArg[0]->GetImag());
292     *ret = cosh(v);
293   }
294 
295   //-----------------------------------------------------------------------
GetDesc() const296   const char_type* FunCmplxCosH::GetDesc() const
297   {
298     return _T("cosh(x) - Returns the hyperbolic cosine of the number x.");
299   }
300 
301   //-----------------------------------------------------------------------
Clone() const302   IToken* FunCmplxCosH::Clone() const
303   {
304     return new FunCmplxCosH(*this);
305   }
306 
307   //-----------------------------------------------------------------------
308   //
309   //  class FunCmplxSinH
310   //
311   //-----------------------------------------------------------------------
312 
FunCmplxSinH()313   FunCmplxSinH::FunCmplxSinH()
314     :ICallback(cmFUNC, _T("sinh"), 1)
315   {}
316 
317   //-----------------------------------------------------------------------
Eval(ptr_val_type & ret,const ptr_val_type * a_pArg,int)318   void FunCmplxSinH::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
319   {
320     cmplx_type v(a_pArg[0]->GetFloat(), a_pArg[0]->GetImag());
321     *ret = sinh(v);
322   }
323 
324   //-----------------------------------------------------------------------
GetDesc() const325   const char_type* FunCmplxSinH::GetDesc() const
326   {
327     return _T("sinh(x) - Returns the hyperbolic sine of the complex number x.");
328   }
329 
330   //-----------------------------------------------------------------------
Clone() const331   IToken* FunCmplxSinH::Clone() const
332   {
333     return new FunCmplxSinH(*this);
334   }
335 
336   //-----------------------------------------------------------------------
337   //
338   //  class FunCmplxTan
339   //
340   //-----------------------------------------------------------------------
341 
FunCmplxTan()342   FunCmplxTan::FunCmplxTan()
343     :ICallback(cmFUNC, _T("tan"), 1)
344   {}
345 
346   //-----------------------------------------------------------------------
Eval(ptr_val_type & ret,const ptr_val_type * a_pArg,int)347   void FunCmplxTan::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
348   {
349     if (a_pArg[0]->IsNonComplexScalar())
350     {
351       *ret = std::tan(a_pArg[0]->GetFloat());
352     }
353     else
354     {
355       cmplx_type v(a_pArg[0]->GetFloat(), a_pArg[0]->GetImag());
356       *ret = std::tan(v);
357     }
358   }
359 
360   //-----------------------------------------------------------------------
GetDesc() const361   const char_type* FunCmplxTan::GetDesc() const
362   {
363     return _T("tan(x) - Returns the tangens of the number x.");
364   }
365 
366   //-----------------------------------------------------------------------
Clone() const367   IToken* FunCmplxTan::Clone() const
368   {
369     return new FunCmplxTan(*this);
370   }
371 
372   //-----------------------------------------------------------------------
373   //
374   //  class FunCmplxTanH
375   //
376   //-----------------------------------------------------------------------
377 
FunCmplxTanH()378   FunCmplxTanH::FunCmplxTanH()
379     :ICallback(cmFUNC, _T("tanh"), 1)
380   {}
381 
382   //-----------------------------------------------------------------------
Eval(ptr_val_type & ret,const ptr_val_type * a_pArg,int)383   void FunCmplxTanH::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
384   {
385     cmplx_type v(a_pArg[0]->GetFloat(), a_pArg[0]->GetImag());
386     *ret = tanh(v);
387   }
388 
389   //-----------------------------------------------------------------------
GetDesc() const390   const char_type* FunCmplxTanH::GetDesc() const
391   {
392     return _T("tanh(x) - Returns the hyperbolic tangent of the complex number x.");
393   }
394 
395   //-----------------------------------------------------------------------
Clone() const396   IToken* FunCmplxTanH::Clone() const
397   {
398     return new FunCmplxTanH(*this);
399   }
400 
401   //-----------------------------------------------------------------------
402   //
403   //  class FunCmplxSqrt
404   //
405   //-----------------------------------------------------------------------
406 
FunCmplxSqrt()407   FunCmplxSqrt::FunCmplxSqrt()
408     :ICallback(cmFUNC, _T("sqrt"), 1)
409   {}
410 
411   //-----------------------------------------------------------------------
Eval(ptr_val_type & ret,const ptr_val_type * a_pArg,int)412   void FunCmplxSqrt::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
413   {
414     *ret = sqrt((*a_pArg[0]).GetComplex());
415   }
416 
417   //-----------------------------------------------------------------------
GetDesc() const418   const char_type* FunCmplxSqrt::GetDesc() const
419   {
420     return _T("sqrt(x) - Returns the square root of x.");
421   }
422 
423   //-----------------------------------------------------------------------
Clone() const424   IToken* FunCmplxSqrt::Clone() const
425   {
426     return new FunCmplxSqrt(*this);
427   }
428 
429 
430   //-----------------------------------------------------------------------
431   //
432   //  class FunCmplxExp
433   //
434   //-----------------------------------------------------------------------
435 
FunCmplxExp()436   FunCmplxExp::FunCmplxExp()
437     :ICallback(cmFUNC, _T("exp"), 1)
438   {}
439 
440   //-----------------------------------------------------------------------
Eval(ptr_val_type & ret,const ptr_val_type * a_pArg,int)441   void FunCmplxExp::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
442   {
443     cmplx_type v(a_pArg[0]->GetFloat(), a_pArg[0]->GetImag());
444     *ret = exp(v);
445   }
446 
447   //-----------------------------------------------------------------------
GetDesc() const448   const char_type* FunCmplxExp::GetDesc() const
449   {
450     return _T("exp(x) - Returns the base-e exponential of the complex number x.");
451   }
452 
453   //-----------------------------------------------------------------------
Clone() const454   IToken* FunCmplxExp::Clone() const
455   {
456     return new FunCmplxExp(*this);
457   }
458 
459   //-----------------------------------------------------------------------
460   //
461   //  class FunCmplxLn
462   //
463   //-----------------------------------------------------------------------
464 
FunCmplxLn()465   FunCmplxLn::FunCmplxLn()
466     :ICallback(cmFUNC, _T("ln"), 1)
467   {}
468 
469   //-----------------------------------------------------------------------
Eval(ptr_val_type & ret,const ptr_val_type * a_pArg,int)470   void FunCmplxLn::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
471   {
472     cmplx_type v(a_pArg[0]->GetFloat(), a_pArg[0]->GetImag());
473     *ret = log(v);
474   }
475 
476   //-----------------------------------------------------------------------
GetDesc() const477   const char_type* FunCmplxLn::GetDesc() const
478   {
479     return _T("ln(x) - Returns the natural (base-e) logarithm of the complex number x.");
480   }
481 
482   //-----------------------------------------------------------------------
Clone() const483   IToken* FunCmplxLn::Clone() const
484   {
485     return new FunCmplxLn(*this);
486   }
487 
488   //-----------------------------------------------------------------------
489   //
490   //  class FunCmplxLog
491   //
492   //-----------------------------------------------------------------------
493 
FunCmplxLog()494   FunCmplxLog::FunCmplxLog()
495     :ICallback(cmFUNC, _T("log"), 1)
496   {}
497 
498   //-----------------------------------------------------------------------
Eval(ptr_val_type & ret,const ptr_val_type * a_pArg,int)499   void FunCmplxLog::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
500   {
501     cmplx_type v(a_pArg[0]->GetFloat(), a_pArg[0]->GetImag());
502     *ret = log(v);
503   }
504 
505 
506   //-----------------------------------------------------------------------
GetDesc() const507   const char_type* FunCmplxLog::GetDesc() const
508   {
509     return _T("log(x) - Common logarithm of x, for values of x greater than zero.");
510   }
511 
512   //-----------------------------------------------------------------------
Clone() const513   IToken* FunCmplxLog::Clone() const
514   {
515     return new FunCmplxLog(*this);
516   }
517 
518   //-----------------------------------------------------------------------
519   //
520   //  class FunCmplxLog10
521   //
522   //-----------------------------------------------------------------------
523 
FunCmplxLog10()524   FunCmplxLog10::FunCmplxLog10()
525     :ICallback(cmFUNC, _T("log10"), 1)
526   {}
527 
528   //-----------------------------------------------------------------------
Eval(ptr_val_type & ret,const ptr_val_type * a_pArg,int)529   void FunCmplxLog10::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
530   {
531     cmplx_type v(a_pArg[0]->GetFloat(), a_pArg[0]->GetImag());
532     *ret = log10(v);
533   }
534 
535   //-----------------------------------------------------------------------
GetDesc() const536   const char_type* FunCmplxLog10::GetDesc() const
537   {
538     return _T("log10(x) - Common logarithm of x, for values of x greater than zero.");
539   }
540 
541   //-----------------------------------------------------------------------
Clone() const542   IToken* FunCmplxLog10::Clone() const
543   {
544     return new FunCmplxLog10(*this);
545   }
546 
547   //-----------------------------------------------------------------------
548   //
549   //  class FunCmplxLog2
550   //
551   //-----------------------------------------------------------------------
552 
FunCmplxLog2()553   FunCmplxLog2::FunCmplxLog2()
554     :ICallback(cmFUNC, _T("log2"), 1)
555   {}
556 
557   //-----------------------------------------------------------------------
Eval(ptr_val_type & ret,const ptr_val_type * a_pArg,int)558   void FunCmplxLog2::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
559   {
560     std::complex<float_type> v(a_pArg[0]->GetFloat(), a_pArg[0]->GetImag());
561     *ret = std::log(v) * (float_type)1.0/std::log((float_type)2.0);
562   }
563 
564   //-----------------------------------------------------------------------
GetDesc() const565   const char_type* FunCmplxLog2::GetDesc() const
566   {
567     return _T("log2(x) - Logarithm to base 2 of x, for values of x greater than zero.");
568   }
569 
570   //-----------------------------------------------------------------------
Clone() const571   IToken* FunCmplxLog2::Clone() const
572   {
573     return new FunCmplxLog2(*this);
574   }
575 
576   //-----------------------------------------------------------------------
577   //
578   //  class FunCmplxAbs
579   //
580   //-----------------------------------------------------------------------
581 
FunCmplxAbs()582   FunCmplxAbs::FunCmplxAbs()
583     :ICallback(cmFUNC, _T("abs"), 1)
584   {}
585 
586   //-----------------------------------------------------------------------
Eval(ptr_val_type & ret,const ptr_val_type * a_pArg,int)587   void FunCmplxAbs::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
588   {
589     float_type v = sqrt(a_pArg[0]->GetFloat()*a_pArg[0]->GetFloat() +
590                         a_pArg[0]->GetImag()*a_pArg[0]->GetImag());
591     *ret = v;
592   }
593 
594   //-----------------------------------------------------------------------
GetDesc() const595   const char_type* FunCmplxAbs::GetDesc() const
596   {
597     return _T("abs(x) - Returns the absolute value of x.");
598   }
599 
600   //-----------------------------------------------------------------------
Clone() const601   IToken* FunCmplxAbs::Clone() const
602   {
603     return new FunCmplxAbs(*this);
604   }
605 
606   //-----------------------------------------------------------------------
607   //
608   //  class FunCmplxPow
609   //
610   //-----------------------------------------------------------------------
611 
FunCmplxPow()612   FunCmplxPow::FunCmplxPow()
613     :ICallback(cmFUNC, _T("pow"), 2)
614   {}
615 
616   //-----------------------------------------------------------------------
Eval(ptr_val_type & ret,const ptr_val_type * a_pArg,int)617   void FunCmplxPow::Eval(ptr_val_type &ret, const ptr_val_type *a_pArg, int)
618   {
619     *ret = std::pow(a_pArg[0]->GetComplex(), a_pArg[1]->GetComplex());
620   }
621 
622   //-----------------------------------------------------------------------
GetDesc() const623   const char_type* FunCmplxPow::GetDesc() const
624   {
625     return _T("pox(x, y) - Raise x to the power of y.");
626   }
627 
628   //-----------------------------------------------------------------------
Clone() const629   IToken* FunCmplxPow::Clone() const
630   {
631     return new FunCmplxPow(*this);
632   }
633 
634 
635 MUP_NAMESPACE_END
636