11#ifndef EIGEN_ARCH_GENERIC_PACKET_MATH_DOUBLE_WORD_H
12#define EIGEN_ARCH_GENERIC_PACKET_MATH_DOUBLE_WORD_H
15#include "../../InternalHeaderCheck.h"
22template <
typename Packet>
23EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void absolute_split(
const Packet& x, Packet& n, Packet& r) {
30template <
typename Packet>
31EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void fast_twosum(
const Packet& x,
const Packet& y, Packet& s_hi, Packet& s_lo) {
33 const Packet t = psub(s_hi, x);
37#ifdef EIGEN_VECTORIZE_FMA
39template <typename Packet, std::enable_if_t<!is_scalar<Packet>::value,
int> = 0>
40EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet twoprod_low(
const Packet& x,
const Packet& y,
const Packet& xy) {
41 return pmsub(x, y, xy);
44template <typename Scalar, std::enable_if_t<is_scalar<Scalar>::value,
int> = 0>
45EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar twoprod_low(
const Scalar& x,
const Scalar& y,
const Scalar& xy) {
47 return numext::fma(x, y, Scalar(-xy));
54template <
typename Packet>
55EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void twoprod(
const Packet& x,
const Packet& y, Packet& p_hi, Packet& p_lo) {
57 p_lo = twoprod_low(x, y, p_hi);
65template <
typename Scalar>
66struct has_fast_fma : std::false_type {};
69struct has_fast_fma<float> : std::true_type {};
73struct has_fast_fma<double> : std::true_type {};
77struct has_fast_fma<long double> : std::true_type {};
80template <typename Scalar, std::enable_if_t<has_fast_fma<Scalar>::value,
int> = 0>
81EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar twoprod_low(
const Scalar& x,
const Scalar& y,
const Scalar& xy) {
82 return numext::fma(x, y, Scalar(-xy));
85template <typename Scalar, std::enable_if_t<has_fast_fma<Scalar>::value,
int> = 0>
86EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void twoprod(
const Scalar& x,
const Scalar& y, Scalar& p_hi, Scalar& p_lo) {
88 p_lo = twoprod_low(x, y, p_hi);
96template <
typename Packet>
97EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void veltkamp_splitting(
const Packet& x, Packet& x_hi, Packet& x_lo) {
98 using Scalar =
typename unpacket_traits<Packet>::type;
99 constexpr int shift = (NumTraits<Scalar>::digits() + 1) / 2;
100 const Scalar shift_scale = Scalar(uint64_t(1) << shift);
101 const Packet gamma = pmul(pset1<Packet>(shift_scale + Scalar(1)), x);
102 Packet rho = psub(x, gamma);
103 x_hi = padd(rho, gamma);
104 x_lo = psub(x, x_hi);
111template <typename Packet, std::enable_if_t<!has_fast_fma<Packet>::value,
int> = 0>
112EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void twoprod(
const Packet& x,
const Packet& y, Packet& p_hi, Packet& p_lo) {
113 Packet x_hi, x_lo, y_hi, y_lo;
114 veltkamp_splitting(x, x_hi, x_lo);
115 veltkamp_splitting(y, y_hi, y_lo);
118 p_lo = pmadd(x_hi, y_hi, pnegate(p_hi));
119 p_lo = pmadd(x_hi, y_lo, p_lo);
120 p_lo = pmadd(x_lo, y_hi, p_lo);
121 p_lo = pmadd(x_lo, y_lo, p_lo);
126template <typename Packet, std::enable_if_t<!has_fast_fma<Packet>::value,
int> = 0>
127EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Packet twoprod_low(
const Packet& x,
const Packet& y,
const Packet& xy) {
128 Packet x_hi, x_lo, y_hi, y_lo;
129 veltkamp_splitting(x, x_hi, x_lo);
130 veltkamp_splitting(y, y_hi, y_lo);
132 Packet p_lo = pmadd(x_hi, y_hi, pnegate(xy));
133 p_lo = pmadd(x_hi, y_lo, p_lo);
134 p_lo = pmadd(x_lo, y_hi, p_lo);
135 p_lo = pmadd(x_lo, y_lo, p_lo);
149template <
typename Packet>
150EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void twosum(
const Packet& x_hi,
const Packet& x_lo,
const Packet& y_hi,
151 const Packet& y_lo, Packet& s_hi, Packet& s_lo) {
152 Packet s = padd(x_hi, y_hi);
153 Packet y_part = psub(s, x_hi);
154 Packet err = padd(psub(x_hi, psub(s, y_part)), psub(y_hi, y_part));
155 fast_twosum(s, padd(err, padd(x_lo, y_lo)), s_hi, s_lo);
160template <
typename Packet>
161EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void twodiff(
const Packet& x_hi,
const Packet& x_lo,
const Packet& y_hi,
162 const Packet& y_lo, Packet& s_hi, Packet& s_lo) {
163 Packet s = psub(x_hi, y_hi);
164 Packet y_part = psub(x_hi, s);
165 Packet err = psub(psub(x_hi, padd(s, y_part)), psub(y_hi, y_part));
166 fast_twosum(s, padd(err, psub(x_lo, y_lo)), s_hi, s_lo);
171template <
typename Packet>
172EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void fast_twosum(
const Packet& x_hi,
const Packet& x_lo,
const Packet& y_hi,
173 const Packet& y_lo, Packet& s_hi, Packet& s_lo) {
175 fast_twosum(x_hi, y_hi, r_hi, r_lo);
176 const Packet s = padd(padd(y_lo, r_lo), x_lo);
177 fast_twosum(r_hi, s, s_hi, s_lo);
183template <
typename Packet>
184EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void fast_twosum(
const Packet& x,
const Packet& y_hi,
const Packet& y_lo,
185 Packet& s_hi, Packet& s_lo) {
187 fast_twosum(x, y_hi, r_hi, r_lo);
188 const Packet s = padd(y_lo, r_lo);
189 fast_twosum(r_hi, s, s_hi, s_lo);
200template <
typename Packet>
201EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void twoprod(
const Packet& x_hi,
const Packet& x_lo,
const Packet& y,
202 Packet& p_hi, Packet& p_lo) {
204 twoprod(x_hi, y, c_hi, c_lo1);
205 const Packet c_lo2 = pmul(x_lo, y);
207 fast_twosum(c_hi, c_lo2, t_hi, t_lo1);
208 const Packet t_lo2 = padd(t_lo1, c_lo1);
209 fast_twosum(t_hi, t_lo2, p_hi, p_lo);
223template <
typename Packet>
224EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void twoprod(
const Packet& x_hi,
const Packet& x_lo,
const Packet& y_hi,
225 const Packet& y_lo, Packet& p_hi, Packet& p_lo) {
226 Packet p_hi_hi, p_hi_lo;
227 twoprod(x_hi, x_lo, y_hi, p_hi_hi, p_hi_lo);
228 Packet p_lo_hi, p_lo_lo;
229 twoprod(x_hi, x_lo, y_lo, p_lo_hi, p_lo_lo);
230 fast_twosum(p_hi_hi, p_hi_lo, p_lo_hi, p_lo_lo, p_hi, p_lo);
240template <
typename Packet>
241EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void fast_twoprod(
const Packet& x_hi,
const Packet& x_lo,
const Packet& y_hi,
242 const Packet& y_lo, Packet& p_hi, Packet& p_lo) {
244 twoprod(x_hi, y_hi, c_hi, c_lo);
245 c_lo = pmadd(x_hi, y_lo, pmadd(x_lo, y_hi, c_lo));
246 fast_twosum(c_hi, c_lo, p_hi, p_lo);
253template <
typename Packet>
254EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void doubleword_div_fp(
const Packet& x_hi,
const Packet& x_lo,
const Packet& y,
255 Packet& z_hi, Packet& z_lo) {
256 const Packet t_hi = pdiv(x_hi, y);
258 twoprod(t_hi, y, pi_hi, pi_lo);
259 const Packet delta_hi = psub(x_hi, pi_hi);
260 const Packet delta_t = psub(delta_hi, pi_lo);
261 const Packet delta = padd(delta_t, x_lo);
262 const Packet t_lo = pdiv(delta, y);
263 fast_twosum(t_hi, t_lo, z_hi, z_lo);