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