static bool valid(index_type i, index_type j, matrix_type *output, std::complex<float> const &value) { vsip_cscalar_f c = vsip_cmget_f(output, i, j); return (equal(c.r, value.real()) && equal(c.i, value.imag())); }
/*! * \copydoc is_zero */ inline bool is_zero(std::complex<double> a) { return a.real() == 0.0 && a.imag() == 0.0; }
void set_iq_balance(const std::complex<double> &cor){ _iface->poke32(REG_TX_FE_MAG_CORRECTION, fs_to_bits(cor.real(), 18)); _iface->poke32(REG_TX_FE_PHASE_CORRECTION, fs_to_bits(cor.imag(), 18)); }
static inline U apply(std::complex<T> const & arg) { return static_cast<U>(arg.real()); }
/*! * \copydoc is_zero */ inline bool is_zero(std::complex<float> a) { return a.real() == 0.0f && a.imag() == 0.0f; }
arma_inline static T get(const std::complex<T>& val) { return -val.real(); }
//=================Strassen=============================== QDebug operator <<(QDebug qd,std::complex<double> a) { qd<<"("<<QString::number(a.real())/*+","+QString::number(a.imag())*/<<")"; return qd; }
template <typename T> void readDouble(QDataStream &in, std::complex<T> &el) { double v; in >> v; el.real(v); el.imag(0); }
template <typename T> void readComplex(QDataStream &in, std::complex<T> &el) { double re, im; in >> re >> im; el.real(re); el.imag(im); }
double abs_sum_value( std::complex< double > const& f ) { using namespace std ; return abs(f.real()) + abs(f.imag()) ; }
template <typename T> void dumpElement(QDataStream &out, const std::complex<T> &el) { out << (double)el.real() << (double)el.imag(); }
inline static const T tmp_real(const std::complex<T>& X) { return X.real(); }
static inline std::string apply(std::complex<T> const & arg) { return cast<std::string>(arg.real()) + "+" + cast<std::string>(arg.imag()) + "i"; }
static inline std::complex<U> apply(std::complex<T> const & arg) { return std::complex<U>(arg.real(), arg.imag()); }
inline void mumps_assign_Scalar(ZMUMPS_COMPLEX & a, std::complex<double> b) { a.r = b.real(); a.i = b.imag(); }
std::complex<T> atanh(const std::complex<T>& z) { // // References: // // Eric W. Weisstein. "Inverse Hyperbolic Tangent." // From MathWorld--A Wolfram Web Resource. // http://mathworld.wolfram.com/InverseHyperbolicTangent.html // // Also: The Wolfram Functions Site, // http://functions.wolfram.com/ElementaryFunctions/ArcTanh/ // // Also "Abramowitz and Stegun. Handbook of Mathematical Functions." // at : http://jove.prohosting.com/~skripty/toc.htm // static const T half_pi = static_cast<T>(1.57079632679489661923132169163975144L); static const T pi = static_cast<T>(3.141592653589793238462643383279502884197L); static const T one = static_cast<T>(1.0L); static const T two = static_cast<T>(2.0L); static const T four = static_cast<T>(4.0L); static const T zero = static_cast<T>(0); static const T a_crossover = static_cast<T>(0.3L); T x = std::fabs(z.real()); T y = std::fabs(z.imag()); T real, imag; // our results T safe_upper = detail::safe_max(two); T safe_lower = detail::safe_min(static_cast<T>(2)); // // Begin by handling the special cases specified in C99: // if(detail::test_is_nan(x)) { if(detail::test_is_nan(y)) return std::complex<T>(x, x); else if(std::numeric_limits<T>::has_infinity && (y == std::numeric_limits<T>::infinity())) return std::complex<T>(0, ((z.imag() < 0) ? -half_pi : half_pi)); else return std::complex<T>(x, x); } else if(detail::test_is_nan(y)) { if(x == 0) return std::complex<T>(x, y); if(std::numeric_limits<T>::has_infinity && (x == std::numeric_limits<T>::infinity())) return std::complex<T>(0, y); else return std::complex<T>(y, y); } else if((x > safe_lower) && (x < safe_upper) && (y > safe_lower) && (y < safe_upper)) { T xx = x*x; T yy = y*y; T x2 = x * two; /// // The real part is given by: // // real(atanh(z)) == log((1 + x^2 + y^2 + 2x) / (1 + x^2 + y^2 - 2x)) // // However, when x is either large (x > 1/E) or very small // (x < E) then this effectively simplifies // to log(1), leading to wildly inaccurate results. // By dividing the above (top and bottom) by (1 + x^2 + y^2) we get: // // real(atanh(z)) == log((1 + (2x / (1 + x^2 + y^2))) / (1 - (-2x / (1 + x^2 + y^2)))) // // which is much more sensitive to the value of x, when x is not near 1 // (remember we can compute log(1+x) for small x very accurately). // // The cross-over from one method to the other has to be determined // experimentally, the value used below appears correct to within a // factor of 2 (and there are larger errors from other parts // of the input domain anyway). // T alpha = two*x / (one + xx + yy); if(alpha < a_crossover) { real = boost::math::log1p(alpha) - boost::math::log1p(-alpha); } else { T xm1 = x - one; real = boost::math::log1p(x2 + xx + yy) - std::log(xm1*xm1 + yy); } real /= four; if(z.real() < 0) real = -real; imag = std::atan2((y * two), (one - xx - yy)); imag /= two; if(z.imag() < 0) imag = -imag; } else { // // This section handles exception cases that would normally cause // underflow or overflow in the main formulas. // // Begin by working out the real part, we need to approximate // alpha = 2x / (1 + x^2 + y^2) // without either overflow or underflow in the squared terms. // T alpha = 0; if(x >= safe_upper) { // this is really a test for infinity, // but we may not have the necessary numeric_limits support: if((x > (std::numeric_limits<T>::max)()) || (y > (std::numeric_limits<T>::max)())) { alpha = 0; } else if(y >= safe_upper) { // Big x and y: divide alpha through by x*y: alpha = (two/y) / (x/y + y/x); } else if(y > one) { // Big x: divide through by x: alpha = two / (x + y*y/x); } else { // Big x small y, as above but neglect y^2/x: alpha = two/x; } } else if(y >= safe_upper) { if(x > one) { // Big y, medium x, divide through by y: alpha = (two*x/y) / (y + x*x/y); } else { // Small x and y, whatever alpha is, it's too small to calculate: alpha = 0; } } else { // one or both of x and y are small, calculate divisor carefully: T div = one; if(x > safe_lower) div += x*x; if(y > safe_lower) div += y*y; alpha = two*x/div; } if(alpha < a_crossover) { real = boost::math::log1p(alpha) - boost::math::log1p(-alpha); } else { // We can only get here as a result of small y and medium sized x, // we can simply neglect the y^2 terms: BOOST_ASSERT(x >= safe_lower); BOOST_ASSERT(x <= safe_upper); //BOOST_ASSERT(y <= safe_lower); T xm1 = x - one; real = std::log(1 + two*x + x*x) - std::log(xm1*xm1); } real /= four; if(z.real() < 0) real = -real; // // Now handle imaginary part, this is much easier, // if x or y are large, then the formula: // atan2(2y, 1 - x^2 - y^2) // evaluates to +-(PI - theta) where theta is negligible compared to PI. // if((x >= safe_upper) || (y >= safe_upper)) { imag = pi; } else if(x <= safe_lower) { // // If both x and y are small then atan(2y), // otherwise just x^2 is negligible in the divisor: // if(y <= safe_lower) imag = std::atan2(two*y, one); else { if((y == zero) && (x == zero)) imag = 0; else imag = std::atan2(two*y, one - y*y); } } else { // // y^2 is negligible: // if((y == zero) && (x == one)) imag = 0; else imag = std::atan2(two*y, 1 - x*x); } imag /= two; if(z.imag() < 0) imag = -imag; } return std::complex<T>(real, imag); }
/** * \brief Constructor from std::complex * * \pre complex number must not be zero */ SOPHUS_FUNC explicit SO2Group(const std::complex<Scalar>& complex) : unit_complex_(complex.real(), complex.imag()) { Base::normalize(); }
Expr::Expr(const std::complex<double>& c) : Playa::Handle<ExprBase>(new ComplexExpr(new ConstantExpr(c.real()), new ConstantExpr(c.imag()))) {}
arma_inline static T get(const std::complex<T>& val) { return -std::abs(val.imag()); }
void LTransform::set( PQIndex pq1, PQIndex pq2, std::complex<double> Cpq1pq2, std::complex<double> Cqp1pq2) { assert(pq1.pqValid() && !pq1.pastOrder(_orderOut)); assert(pq2.pqValid() && !pq2.pastOrder(_orderIn)); take_ownership(); const double RoundoffTolerance=1.e-15; std::complex<double> Cpq1qp2; if (pq2.needsConjugation()) { pq2 = pq2.swapPQ(); std::complex<double> tmp=conj(Cqp1pq2); Cqp1pq2 = conj(Cpq1pq2); Cpq1pq2 = tmp; } if (pq1.needsConjugation()) { pq1 = pq1.swapPQ(); std::complex<double> tmp=Cqp1pq2; Cqp1pq2 = Cpq1pq2; Cpq1pq2 = tmp; } int rIndex1 = pq1.rIndex(); int rIndex2 = pq2.rIndex(); int iIndex1 = rIndex1+1; int iIndex2 = rIndex2+1; if (pq1.isReal()) { if (Cpq1pq2!=Cqp1pq2) { FormatAndThrow<>() << "Invalid LTransform elements for p1=q1, " << Cpq1pq2 << " != " << Cqp1pq2; } (*_m)(rIndex1,rIndex2) = Cpq1pq2.real() * (pq2.isReal()? 1. : 2.); if (pq2.isReal()) { if (std::abs(Cpq1pq2.imag()) > RoundoffTolerance) { FormatAndThrow<>() << "Nonzero imaginary LTransform elements for p1=q1, p2=q2: " << Cpq1pq2; } } else { (*_m)(rIndex1,iIndex2) = -2.*Cpq1pq2.imag(); } return; } else if (pq2.isReal()) { // Here we know p1!=q1: if (norm(Cpq1pq2-conj(Cqp1pq2))>RoundoffTolerance) { FormatAndThrow<>() << "Inputs to LTransform.set are not conjugate for p2=q2: " << Cpq1pq2 << " vs " << Cqp1pq2 ; } (*_m)(rIndex1, rIndex2) = Cpq1pq2.real(); (*_m)(iIndex1, rIndex2) = Cpq1pq2.imag(); } else { // Neither pq is real: std::complex<double> z=Cpq1pq2 + Cqp1pq2; (*_m)(rIndex1, rIndex2) = z.real(); (*_m)(rIndex1, iIndex2) = -z.imag(); z=Cpq1pq2 - Cqp1pq2; (*_m)(iIndex1, rIndex2) = z.imag(); (*_m)(iIndex1, iIndex2) = z.real(); } }
void microfacetNoExpFourierSeries(Float mu_o, Float mu_i, std::complex<Float> eta_, Float alpha, size_t n, Float phiMax, std::vector<Float> &result) { bool reflect = -mu_i * mu_o > 0; Float sinMu2 = math::safe_sqrt((1 - mu_i * mu_i) * (1 - mu_o * mu_o)), phiCritical = 0.0f; bool conductor = (eta_.imag() != 0.0f); std::complex<Float> eta = (-mu_i > 0 || conductor) ? eta_ : std::complex<Float>(1) / eta_; if (reflect) { if (!conductor) phiCritical = math::safe_acos((2*eta.real()*eta.real()-mu_i*mu_o-1)/sinMu2); } else if (!reflect) { if (conductor) throw std::runtime_error("lowfreqFourierSeries(): encountered refraction case for a conductor"); Float etaDenser = (eta.real() > 1 ? eta.real() : 1 / eta.real()); phiCritical = math::safe_acos((1 - etaDenser * mu_i * mu_o) / (etaDenser * sinMu2)); } if (!conductor && phiCritical > math::Epsilon && phiCritical < math::Pi - math::Epsilon && phiCritical < phiMax - math::Epsilon) { /* Uh oh, some high frequency content leaked in the generally low frequency part. Increase the number of coefficients so that we can capture it. Fortunately, this happens very rarely. */ n = std::max(n, (size_t) 100); } VectorX coeffs(n); coeffs.setZero(); std::function<Float(Float)> integrand = std::bind( µfacetNoExp, mu_o, mu_i, eta_, alpha, std::placeholders::_1); const int nEvals = 200; if (reflect) { if (phiCritical > math::Epsilon && phiCritical < phiMax-math::Epsilon) { filonIntegrate(integrand, coeffs.data(), n, nEvals, 0, phiCritical); filonIntegrate(integrand, coeffs.data(), n, nEvals, phiCritical, phiMax); } else { filonIntegrate(integrand, coeffs.data(), n, nEvals, 0, phiMax); } } else { filonIntegrate(integrand, coeffs.data(), n, nEvals, 0, std::min(phiCritical, phiMax)); } if (phiMax < math::Pi - math::Epsilon) { /* Precompute some sines and cosines */ VectorX cosPhi(n), sinPhi(n); for (int i=0; i<n; ++i) { sinPhi[i] = std::sin(i*phiMax); cosPhi[i] = std::cos(i*phiMax); } /* The fit only occurs on a subset [0, phiMax], where the Fourier Fourier basis functions are not orthogonal anymore! The following then does a change of basis to proper Fourier coefficients. */ MatrixX A(n, n); for (int i=0; i<n; ++i) { for (int j=0; j<=i; ++j) { if (i != j) { A(i, j) = A(j, i) = (i * cosPhi[j] * sinPhi[i] - j * cosPhi[i] * sinPhi[j]) / (i * i - j * j); } else if (i != 0) { A(i, i) = (std::sin(2 * i * phiMax) + 2 * i * phiMax) / (4 * i); } else { A(i, i) = phiMax; } } } auto svd = A.bdcSvd(Eigen::ComputeFullU | Eigen::ComputeFullV); const MatrixX &U = svd.matrixU(); const MatrixX &V = svd.matrixV(); const VectorX &sigma = svd.singularValues(); if (sigma[0] == 0) { result.clear(); result.push_back(0); return; } VectorX temp = VectorX::Zero(n); coeffs[0] *= math::Pi; coeffs.tail(n-1) *= 0.5 * math::Pi; for (int i=0; i<n; ++i) { if (sigma[i] < 1e-9f * sigma[0]) break; temp += V.col(i) * U.col(i).dot(coeffs) / sigma[i]; } coeffs = temp; } result.resize(coeffs.size()); memcpy(result.data(), coeffs.data(), sizeof(Float) * coeffs.size()); }
inline std::complex<T> asin(const std::complex<T>& z) { // // This implementation is a transcription of the pseudo-code in: // // "Implementing the complex Arcsine and Arccosine Functions using Exception Handling." // T E Hull, Thomas F Fairgrieve and Ping Tak Peter Tang. // ACM Transactions on Mathematical Software, Vol 23, No 3, Sept 1997. // // // These static constants should really be in a maths constants library: // static const T one = static_cast<T>(1); //static const T two = static_cast<T>(2); static const T half = static_cast<T>(0.5L); static const T a_crossover = static_cast<T>(1.5L); static const T b_crossover = static_cast<T>(0.6417L); static const T s_pi = lslboost::math::constants::pi<T>(); static const T half_pi = s_pi / 2; static const T log_two = lslboost::math::constants::ln_two<T>(); static const T quarter_pi = s_pi / 4; #ifdef BOOST_MSVC #pragma warning(push) #pragma warning(disable:4127) #endif // // Get real and imaginary parts, discard the signs as we can // figure out the sign of the result later: // T x = std::fabs(z.real()); T y = std::fabs(z.imag()); T real, imag; // our results // // Begin by handling the special cases for infinities and nan's // specified in C99, most of this is handled by the regular logic // below, but handling it as a special case prevents overflow/underflow // arithmetic which may trip up some machines: // if((lslboost::math::isnan)(x)) { if((lslboost::math::isnan)(y)) return std::complex<T>(x, x); if((lslboost::math::isinf)(y)) { real = x; imag = std::numeric_limits<T>::infinity(); } else return std::complex<T>(x, x); } else if((lslboost::math::isnan)(y)) { if(x == 0) { real = 0; imag = y; } else if((lslboost::math::isinf)(x)) { real = y; imag = std::numeric_limits<T>::infinity(); } else return std::complex<T>(y, y); } else if((lslboost::math::isinf)(x)) { if((lslboost::math::isinf)(y)) { real = quarter_pi; imag = std::numeric_limits<T>::infinity(); } else { real = half_pi; imag = std::numeric_limits<T>::infinity(); } } else if((lslboost::math::isinf)(y)) { real = 0; imag = std::numeric_limits<T>::infinity(); } else { // // special case for real numbers: // if((y == 0) && (x <= one)) return std::complex<T>(std::asin(z.real()), z.imag()); // // Figure out if our input is within the "safe area" identified by Hull et al. // This would be more efficient with portable floating point exception handling; // fortunately the quantities M and u identified by Hull et al (figure 3), // match with the max and min methods of numeric_limits<T>. // T safe_max = detail::safe_max(static_cast<T>(8)); T safe_min = detail::safe_min(static_cast<T>(4)); T xp1 = one + x; T xm1 = x - one; if((x < safe_max) && (x > safe_min) && (y < safe_max) && (y > safe_min)) { T yy = y * y; T r = std::sqrt(xp1*xp1 + yy); T s = std::sqrt(xm1*xm1 + yy); T a = half * (r + s); T b = x / a; if(b <= b_crossover) { real = std::asin(b); } else { T apx = a + x; if(x <= one) { real = std::atan(x/std::sqrt(half * apx * (yy /(r + xp1) + (s-xm1)))); } else { real = std::atan(x/(y * std::sqrt(half * (apx/(r + xp1) + apx/(s+xm1))))); } } if(a <= a_crossover) { T am1; if(x < one) { am1 = half * (yy/(r + xp1) + yy/(s - xm1)); } else { am1 = half * (yy/(r + xp1) + (s + xm1)); } imag = lslboost::math::log1p(am1 + std::sqrt(am1 * (a + one))); } else { imag = std::log(a + std::sqrt(a*a - one)); } } else { // // This is the Hull et al exception handling code from Fig 3 of their paper: // if(y <= (std::numeric_limits<T>::epsilon() * std::fabs(xm1))) { if(x < one) { real = std::asin(x); imag = y / std::sqrt(-xp1*xm1); } else { real = half_pi; if(((std::numeric_limits<T>::max)() / xp1) > xm1) { // xp1 * xm1 won't overflow: imag = lslboost::math::log1p(xm1 + std::sqrt(xp1*xm1)); } else { imag = log_two + std::log(x); } } } else if(y <= safe_min) { // There is an assumption in Hull et al's analysis that // if we get here then x == 1. This is true for all "good" // machines where : // // E^2 > 8*sqrt(u); with: // // E = std::numeric_limits<T>::epsilon() // u = (std::numeric_limits<T>::min)() // // Hull et al provide alternative code for "bad" machines // but we have no way to test that here, so for now just assert // on the assumption: // BOOST_ASSERT(x == 1); real = half_pi - std::sqrt(y); imag = std::sqrt(y); } else if(std::numeric_limits<T>::epsilon() * y - one >= x) { real = x/y; // This can underflow! imag = log_two + std::log(y); } else if(x > one) { real = std::atan(x/y); T xoy = x/y; imag = log_two + std::log(y) + half * lslboost::math::log1p(xoy*xoy); } else { T a = std::sqrt(one + y*y); real = x/a; // This can underflow! imag = half * lslboost::math::log1p(static_cast<T>(2)*y*(y+a)); } } } // // Finish off by working out the sign of the result: // if((lslboost::math::signbit)(z.real())) real = (lslboost::math::changesign)(real); if((lslboost::math::signbit)(z.imag())) imag = (lslboost::math::changesign)(imag); return std::complex<T>(real, imag); #ifdef BOOST_MSVC #pragma warning(pop) #endif }