32static inline vcl::Vec8d make_vcl_vec8d(
double x,
int i){
35static inline vcl::Vec8d make_vcl_vec8d(
const double* x,
int i){
36 return vcl::Vec8d().load( x+i);
38static inline vcl::Vec8d make_vcl_vec8d(
double x,
int i,
int num){
41static inline vcl::Vec8d make_vcl_vec8d(
const double* x,
int i,
int num){
42 return vcl::Vec8d().load_partial( num, x+i);
44static inline vcl::Vec8d make_vcl_vec8d(
float x,
int i){
45 return vcl::Vec8d((
double)x);
47static inline vcl::Vec8d make_vcl_vec8d(
const float* x,
int i){
48 return vcl::Vec8d( x[i], x[i+1], x[i+2], x[i+3], x[i+4], x[i+5], x[i+6], x[i+7]);
50static inline vcl::Vec8d make_vcl_vec8d(
float x,
int i,
int num){
51 return vcl::Vec8d((
double)x);
53static inline vcl::Vec8d make_vcl_vec8d(
const float* x,
int i,
int num){
55 for(
int j=0; j<num; j++)
56 tmp[j] = (
double)x[i+j];
57 return vcl::Vec8d().load_partial( num, tmp);
61inline double get_element( T x,
int i){
65inline double get_element( T* x,
int i){
66 return (
double)(*(x+i));
73static inline void AccumulateWord( int64_t *accumulator,
int i, int64_t x) {
79 unsigned char overflow;
82 int64_t oldword = cpu::xadd(accumulator[i], x, overflow);
84 while(unlikely(overflow)) {
91 carry = (oldword + carry) >> DIGITS;
93 carrybit = (s ? 1ll << KRX : (
unsigned long long)(-1ll) << KRX);
96 cpu::xadd(accumulator[i], (int64_t) -(carry << DIGITS), overflow);
97 if(TSAFE && unlikely(s ^ overflow)) {
108 oldword = cpu::xadd(accumulator[i], carry, overflow);
120static inline void Accumulate( int64_t* accumulator,
double x) {
126 int e = cpu::exponent(x);
127 int exp_word = e / DIGITS;
128 int iup = exp_word + F_WORDS;
130 double xscaled = cpu::myldexp(x, -DIGITS * exp_word);
133 for (i = iup; i>=0 && xscaled != 0; --i) {
134 double xrounded = cpu::myrint(xscaled);
135 int64_t xint = cpu::myllrint(xscaled);
136 AccumulateWord(accumulator, i, xint);
139 xscaled *= DELTASCALE;
143static inline void Accumulate( int64_t* accumulator, vcl::Vec8d x) {
150 for(
unsigned int j = 0; j != 8; ++j) {
171static inline bool Normalize( int64_t *accumulator,
int& imin,
int& imax) {
172 int64_t carry_in = accumulator[imin] >> DIGITS;
173 accumulator[imin] -= carry_in << DIGITS;
176 for (i = imin + 1; i < BIN_COUNT; ++i) {
177 accumulator[i] += carry_in;
178 int64_t carry_out = accumulator[i] >> DIGITS;
179 accumulator[i] -= (carry_out << DIGITS);
180 carry_in = carry_out;
185 accumulator[imax] += carry_in << DIGITS;
202static inline double Round( int64_t * accumulator) {
205 bool negative =
Normalize(accumulator, imin, imax);
210 for(i = imax; i >= imin && accumulator[i] == 0; --i) {
216 for(; i >= imin && (accumulator[i] & ((1ll << DIGITS) - 1)) == ((1ll << DIGITS) - 1); --i) {
223 int64_t hiword = negative ? ((1ll << DIGITS) - 1) - accumulator[i] : accumulator[i];
224 double rounded = (double)hiword;
225 double hi = ldexp(rounded, (i - F_WORDS) * DIGITS);
227 return negative ? -hi : hi;
229 hiword -= std::llrint(rounded);
230 double mid = ldexp((
double) hiword, (i - F_WORDS) * DIGITS);
234 for (
int j = imin; j != i - 1; ++j) {
235 sticky |= negative ? ((1ll << DIGITS) - accumulator[j]) : accumulator[j];
238 int64_t loword = negative ? ((1ll << DIGITS) - accumulator[i - 1]) : accumulator[i - 1];
240 double lo = ldexp((
double) loword, (i - 1 - F_WORDS) * DIGITS);
245 lo = cpu::OddRoundSumNonnegative(mid, lo);
249 return negative ? -hi : hi;
static double Round(int64_t *accumulator)
Convert a superaccumulator to the nearest double precision number (CPU version)
Definition: accumulate.h:202
static void Accumulate(int64_t *accumulator, double x)
Accumulate a double to the superaccumulator.
Definition: accumulate.h:120
static bool Normalize(int64_t *accumulator, int &imin, int &imax)
Normalize a superaccumulator.
Definition: accumulate.h:171