Eigen::internal::accurate_log2< double > Struct Reference

#include <GenericPacketMathFunctions.h>

Public Member Functions

template<typename Packet >
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void operator() (const Packet &x, Packet &log2_x_hi, Packet &log2_x_lo)
 

Member Function Documentation

◆ operator()()

template<typename Packet >
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void Eigen::internal::accurate_log2< double >::operator() ( const Packet x,
Packet log2_x_hi,
Packet log2_x_lo 
)
inline
1900  {
1901  // We use a transformation of variables:
1902  // r = c * (x-1) / (x+1),
1903  // such that
1904  // log2(x) = log2((1 + r/c) / (1 - r/c)) = f(r).
1905  // The function f(r) can be approximated well using an odd polynomial
1906  // of the form
1907  // P(r) = ((Q(r^2) * r^2 + C) * r^2 + 1) * r,
1908  // For the implementation of log2<double> here, Q is of degree 6 with
1909  // coefficient represented in working precision (double), while C is a
1910  // constant represented in extra precision as a double word to achieve
1911  // full accuracy.
1912  //
1913  // The polynomial coefficients were computed by the Sollya script:
1914  //
1915  // c = 2 / log(2);
1916  // trans = c * (x-1)/(x+1);
1917  // itrans = (1+x/c)/(1-x/c);
1918  // interval=[trans(sqrt(0.5)); trans(sqrt(2))];
1919  // print(interval);
1920  // f = log2(itrans(x));
1921  // p=fpminimax(f,[|1,3,5,7,9,11,13,15,17|],[|1,DD,double...|],interval,relative,floating);
1922  const Packet q12 = pset1<Packet>(2.87074255468000586e-9);
1923  const Packet q10 = pset1<Packet>(2.38957980901884082e-8);
1924  const Packet q8 = pset1<Packet>(2.31032094540014656e-7);
1925  const Packet q6 = pset1<Packet>(2.27279857398537278e-6);
1926  const Packet q4 = pset1<Packet>(2.31271023278625638e-5);
1927  const Packet q2 = pset1<Packet>(2.47556738444535513e-4);
1928  const Packet q0 = pset1<Packet>(2.88543873228900172e-3);
1929  const Packet C_hi = pset1<Packet>(0.0400377511598501157);
1930  const Packet C_lo = pset1<Packet>(-4.77726582251425391e-19);
1931  const Packet one = pset1<Packet>(1.0);
1932 
1933  const Packet cst_2_log2e_hi = pset1<Packet>(2.88539008177792677);
1934  const Packet cst_2_log2e_lo = pset1<Packet>(4.07660016854549667e-17);
1935  // c * (x - 1)
1936  Packet t_hi, t_lo;
1937  // t = c * (x-1)
1938  twoprod(cst_2_log2e_hi, cst_2_log2e_lo, psub(x, one), t_hi, t_lo);
1939  // r = c * (x-1) / (x+1),
1940  Packet r_hi, r_lo;
1941  doubleword_div_fp(t_hi, t_lo, padd(x, one), r_hi, r_lo);
1942 
1943  // r2 = r * r
1944  Packet r2_hi, r2_lo;
1945  twoprod(r_hi, r_lo, r_hi, r_lo, r2_hi, r2_lo);
1946  // r4 = r2 * r2
1947  Packet r4_hi, r4_lo;
1948  twoprod(r2_hi, r2_lo, r2_hi, r2_lo, r4_hi, r4_lo);
1949 
1950  // Evaluate Q(r^2) in working precision. We evaluate it in two parts
1951  // (even and odd in r^2) to improve instruction level parallelism.
1952  Packet q_even = pmadd(q12, r4_hi, q8);
1953  Packet q_odd = pmadd(q10, r4_hi, q6);
1954  q_even = pmadd(q_even, r4_hi, q4);
1955  q_odd = pmadd(q_odd, r4_hi, q2);
1956  q_even = pmadd(q_even, r4_hi, q0);
1957  Packet q = pmadd(q_odd, r2_hi, q_even);
1958 
1959  // Now evaluate the low order terms of P(x) in double word precision.
1960  // In the following, due to the increasing magnitude of the coefficients
1961  // and r being constrained to [-0.5, 0.5] we can use fast_twosum instead
1962  // of the slower twosum.
1963  // Q(r^2) * r^2
1964  Packet p_hi, p_lo;
1965  twoprod(r2_hi, r2_lo, q, p_hi, p_lo);
1966  // Q(r^2) * r^2 + C
1967  Packet p1_hi, p1_lo;
1968  fast_twosum(C_hi, C_lo, p_hi, p_lo, p1_hi, p1_lo);
1969  // (Q(r^2) * r^2 + C) * r^2
1970  Packet p2_hi, p2_lo;
1971  twoprod(r2_hi, r2_lo, p1_hi, p1_lo, p2_hi, p2_lo);
1972  // ((Q(r^2) * r^2 + C) * r^2 + 1)
1973  Packet p3_hi, p3_lo;
1974  fast_twosum(one, p2_hi, p2_lo, p3_hi, p3_lo);
1975 
1976  // log(z) ~= ((Q(r^2) * r^2 + C) * r^2 + 1) * r
1977  twoprod(p3_hi, p3_lo, r_hi, r_lo, log2_x_hi, log2_x_lo);
1978  }
EIGEN_DEVICE_FUNC Packet padd(const Packet &a, const Packet &b)
Definition: GenericPacketMath.h:318
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void fast_twosum(const Packet &x, const Packet &y, Packet &s_hi, Packet &s_lo)
Definition: GenericPacketMathFunctions.h:1654
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void twoprod(const Packet &x, const Packet &y, Packet &p_hi, Packet &p_lo)
Definition: GenericPacketMathFunctions.h:1701
EIGEN_STRONG_INLINE Packet4f pmadd(const Packet4f &a, const Packet4f &b, const Packet4f &c)
Definition: AltiVec/PacketMath.h:1218
EIGEN_DEVICE_FUNC Packet psub(const Packet &a, const Packet &b)
Definition: GenericPacketMath.h:337
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void doubleword_div_fp(const Packet &x_hi, const Packet &x_lo, const Packet &y, Packet &z_hi, Packet &z_lo)
Definition: GenericPacketMathFunctions.h:1817
EIGEN_DEVICE_FUNC const Scalar & q
Definition: SpecialFunctionsImpl.h:2019
list x
Definition: plotDoE.py:28

References Eigen::internal::doubleword_div_fp(), Eigen::internal::fast_twosum(), Eigen::internal::padd(), Eigen::internal::pmadd(), Eigen::internal::psub(), Eigen::numext::q, Eigen::internal::twoprod(), and plotDoE::x.


The documentation for this struct was generated from the following file: