Complex<T> HyperbolicCosine::computeOnComplex(const Complex<T> c, AngleUnit angleUnit) { if (c.b() == 0) { return Complex<T>::Float(std::cosh(c.a())); } Complex<T> e = Complex<T>::Float(M_E); Complex<T> exp1 = Power::compute(e, c); Complex<T> exp2 = Power::compute(e, Complex<T>::Cartesian(-c.a(), -c.b())); Complex<T> sum = Addition::compute(exp1, exp2); return Division::compute(sum, Complex<T>::Float(2)); }
Complex<T> Division::compute(const Complex<T> c, const Complex<T> d) { /* We want to avoid multiplies in the middle of the calculation that could * overflow. * aa, ab, ba, bb, min, max = |d.a| <= |d.b| ? (c.a, c.b, -c.a, c.b, d.a, d.b) * : (c.b, c.a, c.b, -c.a, d.b, d.a) * c c.a+c.b*i d.a-d.b*i 1/max (c.a+c.b*i) * (d.a-d.b*i) / max * - == --------- * --------- * ----- == ------------------------------- * d d.a+d.b*i d.a-d.b*i 1/max (d.a+d.b*i) * (d.a-d.b*i) / max * (c.a*d.a - c.a*d.b*i + c.b*i*d.a - c.b*i*d.b*i) / max * == ----------------------------------------------------- * (d.a*d.a - d.a*d.b*i + d.b*i*d.a - d.b*i*d.b*i) / max * (c.a*d.a - c.b*d.b*i^2 + c.b*d.b*i - c.a*d.a*i) / max * == ----------------------------------------------------- * (d.a*d.a - d.b*d.b*i^2) / max * (c.a*d.a/max + c.b*d.b/max) + (c.b*d.b/max - c.a*d.a/max)*i * == ----------------------------------------------------------- * d.a^2/max + d.b^2/max * aa*min/max + ab*max/max bb*min/max + ba*max/max * == ----------------------- + -----------------------*i * min^2/max + max^2/max min^2/max + max^2/max * min/max*aa + ab min/max*bb + ba * == ----------------- + -----------------*i * min/max*min + max min/max*min + max * |min| <= |max| => |min/max| <= 1 * => |min/max*x| <= |x| * => |min/max*x+y| <= |x|+|y| * So the calculation is guaranteed to not overflow until the last divides as * long as none of the input values have the representation's maximum exponent. * Plus, the method does not propagate any error on real inputs: temp = 0, * norm = d.a and then result = c.a/d.a. */ T aa = c.a(), ab = c.b(), ba = -aa, bb = ab; T min = d.a(), max = d.b(); if (std::fabs(max) < std::fabs(min)) { T temp = min; min = max; max = temp; temp = aa; aa = ab; ab = temp; temp = ba; ba = bb; bb = temp; } T temp = min/max; T norm = temp*min + max; return Complex<T>::Cartesian((temp*aa + ab) / norm, (temp*bb + ba) / norm); }
Complex<T> ArcSine::computeOnComplex(const Complex<T> c, AngleUnit angleUnit) { assert(angleUnit != AngleUnit::Default); if (c.b() != 0) { return Complex<T>::Float(NAN); } T result = std::asin(c.a()); if (angleUnit == AngleUnit::Degree) { return Complex<T>::Float(result*180/M_PI); } return Complex<T>::Float(result); }
real Optimizer::calcError(const TVReal <s, const TVComplex &vs, const TVReal <e, const TVComplex &ve, real normak, real normab) { real err = 0; for(size_t i(0); i<ve.size(); i++) { Complex v = ve[i]; for(size_t j(0); j<lts.size(); j++) { v -= _rm->eval_tabled(lte[i], lts[j], vs[j]); } err += v.a() / exp(lte[i]*normak+normab); } return err; }
Complex<T> HyperbolicArcSine::computeOnComplex(const Complex<T> c, AngleUnit angleUnit) { if (c.b() != 0) { return Complex<T>::Float(NAN); } return Complex<T>::Float(std::asinh(c.a())); }
Complex<T> RealPart::computeOnComplex(const Complex<T> c, AngleUnit angleUnit) { return Complex<T>::Float(c.a()); }
Complex<T> NaperianLogarithm::computeOnComplex(const Complex<T> c, AngleUnit angleUnit) { if (c.b() != 0) { return Complex<T>::Float(NAN); } return Complex<T>::Float(std::log(c.a())); }