Coverage Report

Created: 2026-09-28 06:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/moddable/xs/sources/xsum.c
Line
Count
Source
1
/* FUNCTIONS FOR EXACT SUMMATION. */
2
3
/* Copyright 2015, 2018, 2021, 2024 Radford M. Neal
4
5
   Permission is hereby granted, free of charge, to any person obtaining
6
   a copy of this software and associated documentation files (the
7
   "Software"), to deal in the Software without restriction, including
8
   without limitation the rights to use, copy, modify, merge, publish,
9
   distribute, sublicense, and/or sell copies of the Software, and to
10
   permit persons to whom the Software is furnished to do so, subject to
11
   the following conditions:
12
13
   The above copyright notice and this permission notice shall be
14
   included in all copies or substantial portions of the Software.
15
16
   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
   LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
   OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
   WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
*/
24
25
26
#include <stdio.h>
27
#include <string.h>
28
#include <math.h>
29
#include "xsum.h"
30
31
/* ---------------------- IMPLEMENTATION ASSUMPTIONS ----------------------- */
32
33
/* This code makes the following assumptions:
34
35
     o The 'double' type is a IEEE-754 standard 64-bit floating-point value.
36
37
     o The 'int64_t' and 'uint64_t' types exist, for 64-bit signed and
38
       unsigned integers.
39
40
     o The 'endianness' of 'double' and 64-bit integers is consistent
41
       between these types - that is, looking at the bits of a 'double'
42
       value as an 64-bit integer will have the expected result.
43
44
     o Right shifts of a signed operand produce the results expected for
45
       a two's complement representation.
46
47
     o Rounding should be done in the "round to nearest, ties to even" mode.
48
*/
49
50
51
/* --------------------------- CONFIGURATION ------------------------------- */
52
53
54
/* IMPLEMENTATION OPTIONS.  Can be set to either 0 or 1, whichever seems
55
   to be fastest. */
56
57
#define USE_SIMD 1          /* Use SIMD intrinsics (SSE2/AVX) if available?   */
58
59
#define USE_MEMSET_SMALL 1  /* Use memset rather than a loop (for small mem)? */
60
#define USE_MEMSET_LARGE 1  /* Use memset rather than a loop (for large mem)? */
61
#define USE_USED_LARGE 1    /* Use the used flags in a large accumulator? */
62
63
#define OPT_SMALL 0         /* Class of manual optimization for operations on */
64
                            /*   small accumulator: 0 (none), 1, 2, 3 (SIMD)  */
65
#define OPT_CARRY 1         /* Use manually optimized carry propagation?      */
66
67
#define OPT_LARGE_SUM 1     /* Should manually optimized routines be used for */
68
#define OPT_LARGE_SQNORM 1  /*   operations using the large accumulator?      */
69
#define OPT_LARGE_DOT 1
70
71
#define OPT_SIMPLE_SUM 1    /* Should manually optimized routines be used for */
72
#define OPT_SIMPLE_SQNORM 1 /*   operations done with simple FP arithmetic?   */
73
#define OPT_SIMPLE_DOT 1
74
75
#define OPT_KAHAN_SUM 0     /* Use manually optimized routine for Kahan sum?  */
76
77
#define INLINE_SMALL 1      /* Inline more of the small accumulator routines? */
78
                            /*   (Not currently used)                         */
79
#define INLINE_LARGE 1      /* Inline more of the large accumulator routines? */
80
81
82
/* INCLUDE INTEL INTRINSICS IF USED AND AVAILABLE. */
83
84
#if USE_SIMD && __SSE2__
85
# include <immintrin.h>
86
#endif
87
88
89
/* COPY A 64-BIT QUANTITY - DOUBLE TO 64-BIT INT OR VICE VERSA.  The
90
   arguments are destination and source variables (not values). */
91
92
142k
#define COPY64(dst,src) memcpy(&(dst),&(src),sizeof(double))
93
94
95
/* OPTIONAL INCLUSION OF PBINARY MODULE.  Used for debug output. */
96
97
#ifdef PBINARY
98
# include "pbinary.h"
99
#else
100
0
# define pbinary_int64(x,y) do {} while(0)
101
0
# define pbinary_double(x) do {} while(0)
102
#endif
103
104
105
/* SET UP DEBUG FLAG.  It's a variable if debuging is enabled, and a
106
   constant if disabled (so that no code will be generated then). */
107
108
611k
# define xsum_debug 0
109
# pragma push_macro("c_printf")
110
# undef c_printf
111
0
# define c_printf(...) do {} while(0)
112
113
/* SET UP INLINE / NOINLINE MACROS. */
114
115
#if __GNUC__
116
# define INLINE inline __attribute__ ((always_inline))
117
#ifndef NOINLINE
118
# define NOINLINE __attribute__ ((noinline))
119
#endif
120
#else
121
# define INLINE inline
122
# define NOINLINE
123
#endif
124
125
126
/* ------------------------ INTERNAL ROUTINES ------------------------------- */
127
128
129
/* ADD AN INF OR NAN TO A SMALL ACCUMULATOR.  This only changes the flags,
130
   not the chunks in the accumulator, which retains the sum of the finite
131
   terms (which is perhaps sometimes useful to access, though no function
132
   to do so is defined at present).  A NaN with larger payload (seen as a
133
   52-bit unsigned integer) takes precedence, with the sign of the NaN always
134
   being positive.  This ensures that the order of summing NaN values doesn't
135
   matter. */
136
137
static NOINLINE void xsum_small_add_inf_nan
138
                       (xsum_small_accumulator *restrict sacc, xsum_int ivalue)
139
4.62k
{
140
4.62k
  xsum_int mantissa;
141
4.62k
  double fltv;
142
143
4.62k
  mantissa = ivalue & XSUM_MANTISSA_MASK;
144
145
4.62k
  if (mantissa == 0) /* Inf */
146
3.81k
  { if (sacc->Inf == 0)
147
3.72k
    { /* no previous Inf */
148
3.72k
      sacc->Inf = ivalue;
149
3.72k
    }
150
86
    else if (sacc->Inf != ivalue)
151
5
    { /* previous Inf was opposite sign */
152
5
      COPY64 (fltv, ivalue);
153
5
      fltv = fltv - fltv;  /* result will be a NaN */
154
5
      COPY64 (sacc->Inf, fltv);
155
5
    }
156
3.81k
  }
157
808
  else /* NaN */
158
808
  { /* Choose the NaN with the bigger payload and clear its sign.  Using <=
159
       ensures that we will choose the first NaN over the previous zero. */
160
808
    if ((sacc->NaN & XSUM_MANTISSA_MASK) <= mantissa)
161
808
    { sacc->NaN = ivalue & ~XSUM_SIGN_MASK;
162
808
    }
163
808
  }
164
4.62k
}
165
166
167
/* PROPAGATE CARRIES TO NEXT CHUNK IN A SMALL ACCUMULATOR.  Needs to
168
   be called often enough that accumulated carries don't overflow out
169
   the top, as indicated by sacc->adds_until_propagate.  Returns the
170
   index of the uppermost non-zero chunk (0 if number is zero).
171
172
   After carry propagation, the uppermost non-zero chunk will indicate
173
   the sign of the number, and will not be -1 (all 1s).  It will be in
174
   the range -2^XSUM_LOW_MANTISSA_BITS to 2^XSUM_LOW_MANTISSA_BITS - 1.
175
   Lower chunks will be non-negative, and in the range from 0 up to
176
   2^XSUM_LOW_MANTISSA_BITS - 1. */
177
178
static NOINLINE int xsum_carry_propagate (xsum_small_accumulator *restrict sacc)
179
32.7k
{
180
32.7k
  int i, u, uix;
181
182
32.7k
  if (xsum_debug) c_printf("\nCARRY PROPAGATING IN SMALL ACCUMULATOR\n");
183
184
  /* Set u to the index of the uppermost non-zero (for now) chunk, or
185
     return with value 0 if there is none. */
186
187
32.7k
# if OPT_CARRY
188
189
32.7k
  { u = XSUM_SCHUNKS-1;
190
32.7k
    switch (XSUM_SCHUNKS & 0x3)   /* get u to be a multiple of 4 minus one  */
191
32.7k
    {
192
32.7k
      case 3: if (sacc->chunk[u] != 0)
193
0
              { goto found2;
194
0
              }
195
32.7k
              u -= 1;                            /* XSUM_SCHUNKS is a */
196
32.7k
            mxFallThrough;
197
32.7k
      case 2: if (sacc->chunk[u] != 0)           /* constant, so the  */
198
0
              { goto found2;                     /* compiler will do  */
199
0
              }                                  /* simple code here  */
200
32.7k
              u -= 1;
201
32.7k
            mxFallThrough;
202
32.7k
      case 1: if (sacc->chunk[u] != 0)
203
252
              { goto found2;
204
252
              }
205
32.4k
              u -= 1;
206
32.4k
            mxFallThrough;
207
32.4k
      case 0: ;
208
32.7k
    }
209
210
32.4k
    do  /* here, u should be a multiple of 4 minus one, and at least 3 */
211
332k
    {
212
#     if USE_SIMD && __AVX__
213
      { __m256i ch;
214
        ch = _mm256_loadu_si256 ((__m256i *)(sacc->chunk+u-3));
215
        if (!_mm256_testz_si256(ch,ch))
216
        { goto found;
217
        }
218
        u -= 4;
219
        if (u < 0)  /* never actually happens, because value of XSUM_SCHUNKS */
220
        { break;    /*   is such that u < 0 occurs at end of do loop instead */
221
        }         
222
        ch = _mm256_loadu_si256 ((__m256i *)(sacc->chunk+u-3));
223
        if (!_mm256_testz_si256(ch,ch))
224
        { goto found;
225
        }
226
        u -= 4;
227
      }
228
#     else
229
332k
      { if (sacc->chunk[u] | sacc->chunk[u-1]
230
332k
          | sacc->chunk[u-2] | sacc->chunk[u-3])
231
31.6k
        { goto found;
232
31.6k
        }
233
301k
        u -= 4;
234
301k
      }
235
301k
#     endif
236
237
301k
    } while (u >= 0);
238
239
777
    if (xsum_debug) c_printf ("number is zero (1)\n");
240
777
    uix = 0;
241
777
    goto done;
242
243
31.6k
  found:
244
31.6k
    if (sacc->chunk[u] != 0)
245
1.53k
    { goto found2;
246
1.53k
    }
247
30.1k
    u -= 1;
248
30.1k
    if (sacc->chunk[u] != 0)
249
2.92k
    { goto found2;
250
2.92k
    }
251
27.2k
    u -= 1;
252
27.2k
    if (sacc->chunk[u] != 0)
253
21.4k
    { goto found2;
254
21.4k
    }
255
5.77k
    u -= 1;  
256
257
31.9k
   found2: ;
258
31.9k
  }
259
260
# else  /* Non-optimized search for uppermost non-zero chunk */
261
262
  { for (u = XSUM_SCHUNKS-1; sacc->chunk[u] == 0; u--)
263
    { if (u == 0)
264
      { if (xsum_debug) c_printf ("number is zero (1)\n");
265
        uix = 0;
266
        goto done;
267
      }
268
    }
269
  }
270
271
# endif
272
273
  /* At this point, sacc->chunk[u] must be non-zero */
274
275
31.9k
  if (xsum_debug) c_printf("u: %d, sacc->chunk[u]: %lld",u,sacc->chunk[u]);
276
277
  /* Carry propagate, starting at the low-order chunks.  Note that the
278
     loop limit of u may be increased inside the loop. */
279
280
31.9k
  i = 0;     /* set to the index of the next non-zero chunck, from bottom */
281
282
31.9k
# if OPT_CARRY
283
31.9k
  {
284
    /* Quickly skip over unused low-order chunks.  Done here at the start
285
       on the theory that there are often many unused low-order chunks,
286
       justifying some overhead to begin, but later stretches of unused
287
       chunks may not be as large. */
288
289
31.9k
    int e = u-3;  /* go only to 3 before so won't access beyond chunk array */
290
291
31.9k
    do
292
165k
    {
293
#     if USE_SIMD && __AVX__
294
      { __m256i ch;
295
        ch = _mm256_loadu_si256 ((__m256i *)(sacc->chunk+i));
296
        if (!_mm256_testz_si256(ch,ch))
297
        { break;
298
        }
299
        i += 4;
300
        if (i >= e)
301
        { break;
302
        }
303
        ch = _mm256_loadu_si256 ((__m256i *)(sacc->chunk+i));
304
        if (!_mm256_testz_si256(ch,ch))
305
        { break;
306
        }
307
      }
308
#     else
309
165k
      { if (sacc->chunk[i] | sacc->chunk[i+1]
310
165k
          | sacc->chunk[i+2] | sacc->chunk[i+3])
311
24.8k
        { break;
312
24.8k
        }
313
165k
      }
314
140k
#     endif
315
316
140k
      i += 4;
317
318
140k
    } while (i <= e);
319
31.9k
  }
320
31.9k
# endif
321
322
31.9k
  uix = -1;  /* indicates that a non-zero chunk has not been found yet */
323
324
31.9k
  do
325
125k
  { xsum_schunk c;       /* Set to the chunk at index i (next non-zero one) */
326
125k
    xsum_schunk clow;    /* Low-order bits of c */
327
125k
    xsum_schunk chigh;   /* High-order bits of c */
328
329
    /* Find the next non-zero chunk, setting i to its index, or break out
330
       of loop if there is none.  Note that the chunk at index u is not
331
       necessarily non-zero - it was initially, but u or the chunk at u
332
       may have changed. */
333
334
125k
#   if OPT_CARRY
335
125k
    { 
336
125k
      c = sacc->chunk[i];
337
125k
      if (c != 0)
338
106k
      { goto nonzero;
339
106k
      }
340
18.7k
      i += 1;
341
18.7k
      if (i > u)
342
0
      { break;  /* reaching here is only possible when u == i initially, */
343
0
      }         /*   with the last add to a chunk having changed it to 0 */
344
345
18.7k
      for (;;)
346
44.2k
      { c = sacc->chunk[i];
347
44.2k
        if (c != 0)
348
3.57k
        { goto nonzero;
349
3.57k
        }
350
40.6k
        i += 1;
351
40.6k
        c = sacc->chunk[i];
352
40.6k
        if (c != 0)
353
1.53k
        { goto nonzero;
354
1.53k
        }
355
39.0k
        i += 1;
356
39.0k
        c = sacc->chunk[i];
357
39.0k
        if (c != 0)
358
11.1k
        { goto nonzero;
359
11.1k
        }
360
27.9k
        i += 1;
361
27.9k
        c = sacc->chunk[i];
362
27.9k
        if (c != 0)
363
2.50k
        { goto nonzero;
364
2.50k
        }
365
25.4k
        i += 1;
366
25.4k
      }
367
18.7k
    }
368
#   else
369
    { 
370
      do
371
      { c = sacc->chunk[i];
372
        if (c != 0)
373
        { goto nonzero;
374
        }
375
        i += 1;
376
      } while (i <= u);
377
378
      break;
379
    }
380
#   endif
381
382
    /* Propagate possible carry from this chunk to next chunk up. */
383
384
125k
  nonzero:
385
125k
    chigh = c >> XSUM_LOW_MANTISSA_BITS;
386
125k
    if (chigh == 0)
387
33.8k
    { uix = i;
388
33.8k
      i += 1;
389
33.8k
      continue;  /* no need to change this chunk */
390
33.8k
    }
391
392
91.5k
    if (u == i)
393
29.4k
    { if (chigh == -1)
394
16.9k
      { uix = i;
395
16.9k
        break;   /* don't propagate -1 into the region of all zeros above */
396
16.9k
      }
397
12.5k
      u = i+1;   /* we will change chunk[u+1], so we'll need to look at it */
398
12.5k
    }
399
400
74.5k
    clow = c & XSUM_LOW_MANTISSA_MASK;
401
74.5k
    if (clow != 0)
402
70.6k
    { uix = i;
403
70.6k
    }
404
405
    /* We now change chunk[i] and add to chunk[i+1]. Note that i+1 should be
406
       in range (no bigger than XSUM_CHUNKS-1) if summing memory, since
407
       the number of chunks is big enough to hold any sum, and we do not
408
       store redundant chunks with values 0 or -1 above previously non-zero
409
       chunks.  But other add operations might cause overflow, in which
410
       case we produce a NaN with all 1s as payload.  (We can't reliably produce
411
       an Inf of the right sign.) */
412
413
74.5k
    sacc->chunk[i] = clow;
414
74.5k
    if (i+1 >= XSUM_SCHUNKS)
415
0
    { xsum_small_add_inf_nan (sacc,
416
0
        ((xsum_int)XSUM_EXP_MASK << XSUM_MANTISSA_BITS) | XSUM_MANTISSA_MASK);
417
0
      u = i;
418
0
    }
419
74.5k
    else
420
74.5k
    { sacc->chunk[i+1] += chigh;  /* note: this could make this chunk be zero */
421
74.5k
    }
422
423
74.5k
    i += 1;
424
425
108k
  } while (i <= u);
426
427
31.9k
  if (xsum_debug) c_printf ("  uix: %d  new u: %d\n", uix,u);
428
429
  /* Check again for the number being zero, since carry propagation might
430
     have created zero from something that initially looked non-zero. */
431
432
31.9k
  if (uix < 0)
433
0
  { if (xsum_debug) c_printf ("number is zero (2)\n");
434
0
    uix = 0;
435
0
    goto done;
436
0
  }
437
438
  /* While the uppermost chunk is negative, with value -1, combine it with
439
     the chunk below (if there is one) to produce the same number but with
440
     one fewer non-zero chunks. */
441
442
31.9k
  while (sacc->chunk[uix] == -1 && uix > 0)
443
0
  { /* Left shift of a negative number is undefined according to the standard,
444
       so do a multiply - it's all presumably constant-folded by the compiler.*/
445
0
    sacc->chunk[uix-1] += ((xsum_schunk) -1)
446
0
                             * (((xsum_schunk) 1) << XSUM_LOW_MANTISSA_BITS);
447
0
    sacc->chunk[uix] = 0;
448
0
    uix -= 1;
449
0
  }
450
451
  /* We can now add one less than the total allowed terms before the
452
     next carry propagate. */
453
454
32.7k
done:
455
32.7k
  sacc->adds_until_propagate = XSUM_SMALL_CARRY_TERMS-1;
456
457
  /* Return index of uppermost non-zero chunk. */
458
459
32.7k
  return uix;
460
31.9k
}
461
462
463
/* INITIALIZE LARGE ACCUMULATOR CHUNKS.  Sets all counts to -1. */
464
465
static void xsum_large_init_chunks (xsum_large_accumulator *restrict lacc)
466
0
{
467
0
# if USE_MEMSET_LARGE
468
0
  {
469
    /* Since in two's complement representation, -1 consists of all 1 bits,
470
       we can initialize 16-bit values to -1 by initializing their component
471
       bytes to 0xff. */
472
473
0
    memset (lacc->count, 0xff, XSUM_LCHUNKS * sizeof *lacc->count);
474
0
  }
475
# else
476
  { xsum_lcount *p;
477
    int n;
478
    p = lacc->count;
479
    n = XSUM_LCHUNKS;
480
    do { *p++ = -1; n -= 1; } while (n > 0);
481
  }
482
# endif
483
484
0
# if USE_USED_LARGE
485
0
#   if USE_MEMSET_SMALL
486
0
    { memset(lacc->chunks_used, 0, XSUM_LCHUNKS/64 * sizeof *lacc->chunks_used);
487
0
    }
488
#   elif USE_SIMD && __AVX__ && XSUM_LCHUNKS/64==64
489
    { xsum_used *ch = lacc->chunks_used;
490
      __m256i z = _mm256_setzero_si256();
491
      _mm256_storeu_si256 ((__m256i *)(ch+0), z);
492
      _mm256_storeu_si256 ((__m256i *)(ch+4), z);
493
      _mm256_storeu_si256 ((__m256i *)(ch+8), z);
494
      _mm256_storeu_si256 ((__m256i *)(ch+12), z);
495
      _mm256_storeu_si256 ((__m256i *)(ch+16), z);
496
      _mm256_storeu_si256 ((__m256i *)(ch+20), z);
497
      _mm256_storeu_si256 ((__m256i *)(ch+24), z);
498
      _mm256_storeu_si256 ((__m256i *)(ch+28), z);
499
      _mm256_storeu_si256 ((__m256i *)(ch+32), z);
500
      _mm256_storeu_si256 ((__m256i *)(ch+36), z);
501
      _mm256_storeu_si256 ((__m256i *)(ch+40), z);
502
      _mm256_storeu_si256 ((__m256i *)(ch+44), z);
503
      _mm256_storeu_si256 ((__m256i *)(ch+48), z);
504
      _mm256_storeu_si256 ((__m256i *)(ch+52), z);
505
      _mm256_storeu_si256 ((__m256i *)(ch+56), z);
506
      _mm256_storeu_si256 ((__m256i *)(ch+60), z);
507
    }
508
#   else
509
    { xsum_lchunk *p;
510
      int n;
511
      p = lacc->chunks_used;
512
      n = XSUM_LCHUNKS/64;
513
      do { *p++ = 0; n -= 1; } while (n > 0);
514
    }
515
#   endif
516
0
    lacc->used_used = 0;
517
0
# endif
518
0
}
519
520
521
/* ADD CHUNK FROM A LARGE ACCUMULATOR TO THE SMALL ACCUMULATOR WITHIN IT.
522
   The large accumulator chunk to add is indexed by ix.  This chunk will
523
   be cleared to zero and its count reset after it has been added to the
524
   small accumulator (except no add is done for a new chunk being initialized).
525
   This procedure should not be called for the special chunks correspnding to
526
   Inf or NaN, whose counts should always remain at -1. */
527
528
#if INLINE_LARGE
529
  INLINE
530
#endif
531
static void xsum_add_lchunk_to_small (xsum_large_accumulator *restrict lacc,
532
                                      xsum_expint ix)
533
0
{
534
0
  xsum_expint exp, low_exp, high_exp;
535
0
  xsum_uint low_chunk, mid_chunk, high_chunk;
536
0
  xsum_lchunk chunk;
537
538
0
  const xsum_expint count = lacc->count[ix];
539
540
  /* Add to the small accumulator only if the count is not -1, which
541
     indicates a chunk that contains nothing yet. */
542
543
0
  if (count >= 0)
544
0
  {
545
    /* Propagate carries in the small accumulator if necessary. */
546
547
0
    if (lacc->sacc.adds_until_propagate == 0)
548
0
    { (void) xsum_carry_propagate(&lacc->sacc);
549
0
    }
550
551
    /* Get the chunk we will add.  Note that this chunk is the integer sum
552
       of entire 64-bit floating-point representations, with sign, exponent,
553
       and mantissa, but we want only the sum of the mantissas. */
554
555
0
    chunk = lacc->chunk[ix];
556
557
0
    if (xsum_debug)
558
0
    { c_printf(
559
0
        "\nADDING CHUNK %d TO SMALL ACCUMULATOR (COUNT %d, CHUNK %016llx)\n",
560
0
        (int) ix, (int) count, (long long) chunk);
561
0
    }
562
563
    /* If we added the maximum number of values to 'chunk', the sum of
564
       the sign and exponent parts (all the same, equal to the index) will
565
       have overflowed out the top, leaving only the sum of the mantissas.
566
       If the count of how many more terms we could have summed is greater
567
       than zero, we therefore add this count times the index (shifted to
568
       the position of the sign and exponent) to get the unwanted bits to
569
       overflow out the top. */
570
571
0
    if (count > 0)
572
0
    { chunk += (xsum_lchunk)(count*ix) << XSUM_MANTISSA_BITS;
573
0
    }
574
575
    /* Find the exponent for this chunk from the low bits of the index,
576
       and split it into low and high parts, for accessing the small
577
       accumulator.  Noting that for denormalized numbers where the
578
       exponent part is zero, the actual exponent is 1 (before subtracting
579
       the bias), not zero. */
580
581
0
    exp = ix & XSUM_EXP_MASK;
582
0
    if (exp == 0)
583
0
    { low_exp = 1;
584
0
      high_exp = 0;
585
0
    }
586
0
    else
587
0
    { low_exp = exp & XSUM_LOW_EXP_MASK;
588
0
      high_exp = exp >> XSUM_LOW_EXP_BITS;
589
0
    }
590
591
    /* Split the mantissa into three parts, for three consecutive chunks in
592
       the small accumulator.  Except for denormalized numbers, add in the sum
593
       of all the implicit 1 bits that are above the actual mantissa bits. */
594
595
0
    low_chunk = (chunk << low_exp) & XSUM_LOW_MANTISSA_MASK;
596
0
    mid_chunk = chunk >> (XSUM_LOW_MANTISSA_BITS - low_exp);
597
0
    if (exp != 0) /* normalized */
598
0
    { mid_chunk += (xsum_lchunk)((1 << XSUM_LCOUNT_BITS) - count)
599
0
         << (XSUM_MANTISSA_BITS - XSUM_LOW_MANTISSA_BITS + low_exp);
600
0
    }
601
0
    high_chunk = mid_chunk >> XSUM_LOW_MANTISSA_BITS;
602
0
    mid_chunk &= XSUM_LOW_MANTISSA_MASK;
603
604
0
    if (xsum_debug)
605
0
    { c_printf("chunk div: low "); pbinary_int64(low_chunk,64); c_printf("\n");
606
0
      c_printf("           mid "); pbinary_int64(mid_chunk,64); c_printf("\n");
607
0
      c_printf("          high "); pbinary_int64(high_chunk,64); c_printf("\n");
608
0
    }
609
610
    /* Add or subtract the three parts of the mantissa from three small
611
       accumulator chunks, according to the sign that is part of the index. */
612
613
0
    if (xsum_debug)
614
0
    { c_printf("Small chunks %d, %d, %d before add or subtract:\n",
615
0
              (int)high_exp, (int)high_exp+1, (int)high_exp+2);
616
0
      pbinary_int64 (lacc->sacc.chunk[high_exp], 64); c_printf("\n");
617
0
      pbinary_int64 (lacc->sacc.chunk[high_exp+1], 64); c_printf("\n");
618
0
      pbinary_int64 (lacc->sacc.chunk[high_exp+2], 64); c_printf("\n");
619
0
    }
620
621
0
    if (ix & (1 << XSUM_EXP_BITS))
622
0
    { lacc->sacc.chunk[high_exp] -= low_chunk;
623
0
      lacc->sacc.chunk[high_exp+1] -= mid_chunk;
624
0
      lacc->sacc.chunk[high_exp+2] -= high_chunk;
625
0
    }
626
0
    else
627
0
    { lacc->sacc.chunk[high_exp] += low_chunk;
628
0
      lacc->sacc.chunk[high_exp+1] += mid_chunk;
629
0
      lacc->sacc.chunk[high_exp+2] += high_chunk;
630
0
    }
631
632
0
    if (xsum_debug)
633
0
    { c_printf("Small chunks %d, %d, %d after add or subtract:\n",
634
0
              (int)high_exp, (int)high_exp+1, (int)high_exp+2);
635
0
      pbinary_int64 (lacc->sacc.chunk[high_exp], 64); c_printf("\n");
636
0
      pbinary_int64 (lacc->sacc.chunk[high_exp+1], 64); c_printf("\n");
637
0
      pbinary_int64 (lacc->sacc.chunk[high_exp+2], 64); c_printf("\n");
638
0
    }
639
640
    /* The above additions/subtractions reduce by one the number we can
641
       do before we need to do carry propagation again. */
642
643
0
    lacc->sacc.adds_until_propagate -= 1;
644
0
  }
645
646
  /* We now clear the chunk to zero, and set the count to the number
647
     of adds we can do before the mantissa would overflow.  We also
648
     set the bit in chunks_used to indicate that this chunk is in use
649
     (if that is enabled). */
650
651
0
  lacc->chunk[ix] = 0;
652
0
  lacc->count[ix] = 1 << XSUM_LCOUNT_BITS;
653
654
0
# if USE_USED_LARGE
655
0
    lacc->chunks_used[ix>>6] |= (xsum_used)1 << (ix & 0x3f);
656
0
    lacc->used_used |= (xsum_used)1 << (ix>>6);
657
0
# endif
658
0
}
659
660
661
/* ADD A CHUNK TO THE LARGE ACCUMULATOR OR PROCESS NAN OR INF.  This routine
662
   is called when the count for a chunk is negative after decrementing, which
663
   indicates either inf/nan, or that the chunk has not been initialized, or
664
   that the chunk needs to be transferred to the small accumulator. */
665
666
#if INLINE_LARGE
667
  INLINE
668
#endif
669
static void xsum_large_add_value_inf_nan (xsum_large_accumulator *restrict lacc,
670
                                          xsum_expint ix, xsum_lchunk uintv)
671
0
{
672
0
  if ((ix & XSUM_EXP_MASK) == XSUM_EXP_MASK)
673
0
  { xsum_small_add_inf_nan (&lacc->sacc, uintv);
674
0
  }
675
0
  else
676
0
  { xsum_add_lchunk_to_small (lacc, ix);
677
0
    lacc->count[ix] -= 1;
678
0
    lacc->chunk[ix] += uintv;
679
0
  }
680
0
}
681
682
683
/* TRANSFER ALL CHUNKS IN LARGE ACCUMULATOR TO ITS SMALL ACCUMULATOR. */
684
685
static void xsum_large_transfer_to_small (xsum_large_accumulator *restrict lacc)
686
0
{
687
0
  if (xsum_debug) c_printf("\nTRANSFERRING CHUNKS IN LARGE ACCUMULATOR\n");
688
689
0
# if USE_USED_LARGE
690
0
  {
691
0
    xsum_used *p, *e;
692
0
    xsum_used u, uu;
693
0
    int ix;
694
695
0
    p = lacc->chunks_used;
696
0
    e = p + XSUM_LCHUNKS/64;
697
698
    /* Very quickly skip some unused low-order blocks of chunks by looking
699
       at the used_used flags. */
700
701
0
    uu = lacc->used_used;
702
0
    if ((uu & 0xffffffff) == 0)
703
0
    { uu >>= 32;
704
0
      p += 32;
705
0
    }
706
0
    if ((uu & 0xffff) == 0)
707
0
    { uu >>= 16;
708
0
      p += 16;
709
0
    }
710
0
    if ((uu & 0xff) == 0)
711
0
    { p += 8;
712
0
    }
713
714
    /* Loop over remaining blocks of chunks. */
715
716
0
    do
717
0
    {
718
      /* Loop to quickly find the next non-zero block of used flags, or finish
719
         up if we've added all the used blocks to the small accumulator. */
720
721
0
      for (;;)
722
0
      { u = *p;
723
0
        if (u != 0)
724
0
        { break;
725
0
        }
726
0
        p += 1;
727
0
        if (p == e)
728
0
        { return;
729
0
        }
730
0
        u = *p;
731
0
        if (u != 0)
732
0
        { break;
733
0
        }
734
0
        p += 1;
735
0
        if (p == e)
736
0
        { return;
737
0
        }
738
0
        u = *p;
739
0
        if (u != 0)
740
0
        { break;
741
0
        }
742
0
        p += 1;
743
0
        if (p == e)
744
0
        { return;
745
0
        }
746
0
        u = *p;
747
0
        if (u != 0)
748
0
        { break;
749
0
        }
750
0
        p += 1;
751
0
        if (p == e)
752
0
        { return;
753
0
        }
754
0
      }
755
756
      /* Find and process the chunks in this block that are used.  We skip
757
         forward based on the chunks_used flags until we're within eight
758
         bits of a chunk that is in use. */
759
760
0
      ix = (p - lacc->chunks_used) << 6;
761
0
      if ((u & 0xffffffff) == 0)
762
0
      { u >>= 32;
763
0
        ix += 32;
764
0
      }
765
0
      if ((u & 0xffff) == 0)
766
0
      { u >>= 16;
767
0
        ix += 16;
768
0
      }
769
0
      if ((u & 0xff) == 0)
770
0
      { u >>= 8;
771
0
        ix += 8;
772
0
      }
773
774
0
      do
775
0
      { if (lacc->count[ix] >= 0)
776
0
        { xsum_add_lchunk_to_small (lacc, ix);
777
0
        }
778
0
        ix += 1;
779
0
        u >>= 1;
780
0
      } while (u != 0);
781
782
0
      p += 1;
783
784
0
    } while (p != e);
785
0
  }
786
# else
787
  { xsum_expint ix;
788
789
    /* When there are no used flags, we scan sequentially for chunks that
790
       need to be added to the small accumulator. */
791
792
    for (ix = 0; ix < XSUM_LCHUNKS; ix++)
793
    { if (lacc->count[ix] >= 0)
794
      { xsum_add_lchunk_to_small (lacc, ix);
795
      }
796
    }
797
  }
798
# endif
799
0
}
800
801
802
/* ------------------------ EXTERNAL ROUTINES ------------------------------- */
803
804
805
/* INITIALIZE A SMALL ACCUMULATOR TO ZERO. */
806
807
void xsum_small_init (xsum_small_accumulator *restrict sacc)
808
38.1k
{
809
38.1k
  sacc->adds_until_propagate = XSUM_SMALL_CARRY_TERMS;
810
38.1k
  sacc->Inf = sacc->NaN = 0;
811
38.1k
# if USE_MEMSET_SMALL
812
38.1k
  { memset (sacc->chunk, 0, XSUM_SCHUNKS * sizeof(xsum_schunk));
813
38.1k
  }
814
# elif USE_SIMD && __AVX__ && XSUM_SCHUNKS==67
815
  { xsum_schunk *ch = sacc->chunk;
816
    __m256i z = _mm256_setzero_si256();
817
    _mm256_storeu_si256 ((__m256i *)(ch+0), z);
818
    _mm256_storeu_si256 ((__m256i *)(ch+4), z);
819
    _mm256_storeu_si256 ((__m256i *)(ch+8), z);
820
    _mm256_storeu_si256 ((__m256i *)(ch+12), z);
821
    _mm256_storeu_si256 ((__m256i *)(ch+16), z);
822
    _mm256_storeu_si256 ((__m256i *)(ch+20), z);
823
    _mm256_storeu_si256 ((__m256i *)(ch+24), z);
824
    _mm256_storeu_si256 ((__m256i *)(ch+28), z);
825
    _mm256_storeu_si256 ((__m256i *)(ch+32), z);
826
    _mm256_storeu_si256 ((__m256i *)(ch+36), z);
827
    _mm256_storeu_si256 ((__m256i *)(ch+40), z);
828
    _mm256_storeu_si256 ((__m256i *)(ch+44), z);
829
    _mm256_storeu_si256 ((__m256i *)(ch+48), z);
830
    _mm256_storeu_si256 ((__m256i *)(ch+52), z);
831
    _mm256_storeu_si256 ((__m256i *)(ch+56), z);
832
    _mm256_storeu_si256 ((__m256i *)(ch+60), z);
833
    _mm_storeu_si128    ((__m128i *)(ch+64), _mm256_castsi256_si128(z));
834
    _mm_storeu_si64     (ch+66, _mm256_castsi256_si128(z));
835
  }
836
# else
837
  { xsum_schunk *p;
838
    int n;
839
    p = sacc->chunk;
840
    n = XSUM_SCHUNKS;
841
    do { *p++ = 0; n -= 1; } while (n > 0);
842
  }
843
# endif
844
38.1k
}
845
846
847
/* ADD ONE NUMBER TO A SMALL ACCUMULATOR ASSUMING NO CARRY PROPAGATION REQ'D.
848
   This function is declared INLINE regardless of the setting of INLINE_SMALL
849
   and for good performance it must be inlined by the compiler (otherwise the
850
   procedure call overhead will result in substantial inefficiency). */
851
852
static INLINE void xsum_add1_no_carry (xsum_small_accumulator *restrict sacc,
853
                                       xsum_flt value)
854
78.8k
{
855
78.8k
  xsum_int ivalue;
856
78.8k
  xsum_int mantissa;
857
78.8k
  xsum_expint exp, low_exp, high_exp;
858
78.8k
  xsum_schunk *chunk_ptr;
859
860
78.8k
  if (xsum_debug)
861
0
  { c_printf ("ADD1 %+.17le\n     ", (double) value);
862
0
    pbinary_double ((double) value);
863
0
    c_printf("\n");
864
0
  }
865
866
  /* Extract exponent and mantissa.  Split exponent into high and low parts. */
867
868
78.8k
  COPY64 (ivalue, value);
869
870
78.8k
  exp = (ivalue >> XSUM_MANTISSA_BITS) & XSUM_EXP_MASK;
871
78.8k
  mantissa = ivalue & XSUM_MANTISSA_MASK;
872
78.8k
  high_exp = exp >> XSUM_LOW_EXP_BITS;
873
78.8k
  low_exp = exp & XSUM_LOW_EXP_MASK;
874
875
78.8k
  if (xsum_debug)
876
0
  { c_printf("  high exp: ");
877
0
    pbinary_int64 (high_exp, XSUM_HIGH_EXP_BITS);
878
0
    c_printf("  low exp: ");
879
0
    pbinary_int64 (low_exp, XSUM_LOW_EXP_BITS);
880
0
    c_printf("\n");
881
0
  }
882
883
  /* Categorize number as normal, denormalized, or Inf/NaN according to
884
     the value of the exponent field. */
885
886
78.8k
  if (exp == 0) /* zero or denormalized */
887
27.4k
  { /* If it's a zero (positive or negative), we do nothing. */
888
27.4k
    if (mantissa == 0)
889
15.2k
    { return;
890
15.2k
    }
891
    /* Denormalized mantissa has no implicit 1, but exponent is 1 not 0. */
892
12.1k
    exp = low_exp = 1;
893
12.1k
  }
894
51.4k
  else if (exp == XSUM_EXP_MASK)  /* Inf or NaN */
895
4.62k
  { /* Just update flags in accumulator structure. */
896
4.62k
    xsum_small_add_inf_nan (sacc, ivalue);
897
4.62k
    return;
898
4.62k
  }
899
46.7k
  else /* normalized */
900
46.7k
  { /* OR in implicit 1 bit at top of mantissa */
901
46.7k
    mantissa |= (xsum_int)1 << XSUM_MANTISSA_BITS;
902
46.7k
  }
903
904
58.9k
  if (xsum_debug)
905
0
  { c_printf("  mantissa: ");
906
0
    pbinary_int64 (mantissa, XSUM_MANTISSA_BITS+1);
907
0
    c_printf("\n");
908
0
  }
909
910
  /* Use high part of exponent as index of chunk, and low part of
911
     exponent to give position within chunk.  Fetch the two chunks
912
     that will be modified. */
913
914
58.9k
  chunk_ptr = sacc->chunk + high_exp;
915
916
  /* Separate mantissa into two parts, after shifting, and add to (or
917
     subtract from) this chunk and the next higher chunk (which always
918
     exists since there are three extra ones at the top).
919
920
     Note that low_mantissa will have at most XSUM_LOW_MANTISSA_BITS bits,
921
     while high_mantissa will have at most XSUM_MANTISSA_BITS bits, since
922
     even though the high mantissa includes the extra implicit 1 bit, it will
923
     also be shifted right by at least one bit. */
924
925
58.9k
  xsum_int split_mantissa[2];
926
58.9k
  split_mantissa[0] = ((xsum_uint)mantissa << low_exp) & XSUM_LOW_MANTISSA_MASK;
927
58.9k
  split_mantissa[1] = mantissa >> (XSUM_LOW_MANTISSA_BITS - low_exp);
928
929
  /* Add to, or subtract from, the two affected chunks. */
930
931
# if OPT_SMALL==1
932
  { xsum_int ivalue_sign = ivalue<0 ? -1 : 1;
933
    chunk_ptr[0] += ivalue_sign * split_mantissa[0];
934
    chunk_ptr[1] += ivalue_sign * split_mantissa[1];
935
  }
936
# elif OPT_SMALL==2
937
  { xsum_int ivalue_neg
938
              = ivalue>>(XSUM_SCHUNK_BITS-1); /* all 0s if +ve, all 1s if -ve */
939
    chunk_ptr[0] += (split_mantissa[0] ^ ivalue_neg) + (ivalue_neg & 1);
940
    chunk_ptr[1] += (split_mantissa[1] ^ ivalue_neg) + (ivalue_neg & 1);
941
  }
942
# elif OPT_SMALL==3 && USE_SIMD && __SSE2__
943
  { xsum_int ivalue_neg
944
              = ivalue>>(XSUM_SCHUNK_BITS-1); /* all 0s if +ve, all 1s if -ve */
945
    _mm_storeu_si128 ((__m128i *)chunk_ptr,
946
                      _mm_add_epi64 (_mm_loadu_si128 ((__m128i *)chunk_ptr),
947
                       _mm_add_epi64 (_mm_set1_epi64((__m64)(ivalue_neg&1)),
948
                        _mm_xor_si128 (_mm_set1_epi64((__m64)ivalue_neg),
949
                         _mm_loadu_si128 ((__m128i *)split_mantissa)))));
950
  }
951
# else
952
58.9k
  { if (ivalue < 0)
953
24.0k
    { chunk_ptr[0] -= split_mantissa[0];
954
24.0k
      chunk_ptr[1] -= split_mantissa[1];
955
24.0k
    }
956
34.9k
    else
957
34.9k
    { chunk_ptr[0] += split_mantissa[0];
958
34.9k
      chunk_ptr[1] += split_mantissa[1];
959
34.9k
    }
960
58.9k
  }
961
58.9k
# endif
962
963
58.9k
  if (xsum_debug)
964
0
  { if (ivalue < 0)
965
0
    { c_printf (" -high man: ");
966
0
      pbinary_int64 (-split_mantissa[1], XSUM_MANTISSA_BITS);
967
0
      c_printf ("\n  -low man: ");
968
0
      pbinary_int64 (-split_mantissa[0], XSUM_LOW_MANTISSA_BITS);
969
0
      c_printf("\n");
970
0
    }
971
0
    else
972
0
    { c_printf ("  high man: ");
973
0
      pbinary_int64 (split_mantissa[1], XSUM_MANTISSA_BITS);
974
0
      c_printf ("\n   low man: ");
975
0
      pbinary_int64 (split_mantissa[0], XSUM_LOW_MANTISSA_BITS);
976
0
      c_printf("\n");
977
0
    }
978
0
  }
979
58.9k
}
980
981
982
/* ADD ONE DOUBLE TO A SMALL ACCUMULATOR.  This is equivalent to, but
983
   somewhat faster than, calling xsum_small_addv with a vector of one
984
   value. */
985
986
void xsum_small_add1 (xsum_small_accumulator *restrict sacc, xsum_flt value)
987
78.8k
{
988
78.8k
  if (sacc->adds_until_propagate == 0)
989
0
  { (void) xsum_carry_propagate(sacc);
990
0
  }
991
992
78.8k
  xsum_add1_no_carry (sacc, value);
993
994
78.8k
  sacc->adds_until_propagate -= 1;
995
78.8k
}
996
997
998
/* ADD A VECTOR OF FLOATING-POINT NUMBERS TO A SMALL ACCUMULATOR.  Mixes
999
   calls of xsum_carry_propagate with calls of xsum_add1_no_carry. */
1000
1001
void xsum_small_addv (xsum_small_accumulator *restrict sacc,
1002
                      const xsum_flt *restrict vec,
1003
                      xsum_length n)
1004
0
{ xsum_length m, i;
1005
1006
0
  while (n > 0)
1007
0
  { if (sacc->adds_until_propagate == 0)
1008
0
    { (void) xsum_carry_propagate(sacc);
1009
0
    }
1010
0
    m = n <= sacc->adds_until_propagate ? n : sacc->adds_until_propagate;
1011
0
    for (i = 0; i < m; i++)
1012
0
    { xsum_add1_no_carry (sacc, vec[i]);
1013
0
    }
1014
0
    sacc->adds_until_propagate -= m;
1015
0
    vec += m;
1016
0
    n -= m;
1017
0
  }
1018
0
}
1019
1020
1021
/* ADD SQUARED NORM OF VECTOR OF FLOATING-POINT NUMBERS TO SMALL ACCUMULATOR.
1022
   Mixes calls of xsum_carry_propagate with calls of xsum_add1_no_carry. */
1023
1024
void xsum_small_add_sqnorm (xsum_small_accumulator *restrict sacc,
1025
                            const xsum_flt *restrict vec,
1026
                            xsum_length n)
1027
0
{ xsum_length m, i;
1028
1029
0
  while (n > 0)
1030
0
  { if (sacc->adds_until_propagate == 0)
1031
0
    { (void) xsum_carry_propagate(sacc);
1032
0
    }
1033
0
    m = n <= sacc->adds_until_propagate ? n : sacc->adds_until_propagate;
1034
0
    for (i = 0; i < m; i++)
1035
0
    { xsum_add1_no_carry (sacc, vec[i] * vec[i]);
1036
0
    }
1037
0
    sacc->adds_until_propagate -= m;
1038
0
    vec += m;
1039
0
    n -= m;
1040
0
  }
1041
0
}
1042
1043
1044
/* ADD DOT PRODUCT OF VECTORS OF FLOATING-POINT NUMBERS TO SMALL ACCUMULATOR.
1045
   Mixes calls of xsum_carry_propagate with calls of xsum_add1_no_carry. */
1046
1047
void xsum_small_add_dot (xsum_small_accumulator *restrict sacc,
1048
                         const xsum_flt *vec1, const xsum_flt *vec2,
1049
                         xsum_length n)
1050
0
{ xsum_length m, i;
1051
1052
0
  while (n > 0)
1053
0
  { if (sacc->adds_until_propagate == 0)
1054
0
    { (void) xsum_carry_propagate(sacc);
1055
0
    }
1056
0
    m = n <= sacc->adds_until_propagate ? n : sacc->adds_until_propagate;
1057
0
    for (i = 0; i < m; i++)
1058
0
    { xsum_add1_no_carry (sacc, vec1[i] * vec2[i]);
1059
0
    }
1060
0
    sacc->adds_until_propagate -= m;
1061
0
    vec1 += m;
1062
0
    vec2 += m;
1063
0
    n -= m;
1064
0
  }
1065
0
}
1066
1067
1068
/* ADD A SMALL ACCUMULATOR TO ANOTHER SMALL ACCUMULATOR.  The first argument
1069
   is the destination, which is modified.  The second is the accumulator to
1070
   add, which may also be modified, but should still represent the same
1071
   number.  Source and destination may be the same. */
1072
1073
void xsum_small_add_accumulator (xsum_small_accumulator *dst_sacc,
1074
                                 xsum_small_accumulator *src_sacc)
1075
0
{
1076
0
  int i;
1077
1078
0
  if (xsum_debug) c_printf("\nADDING ACCUMULATOR TO A SMALL ACCUMULATOR\n");
1079
1080
0
  xsum_carry_propagate (dst_sacc);
1081
1082
0
  if (dst_sacc == src_sacc)
1083
0
  { for (i = 0; i < XSUM_SCHUNKS; i++)
1084
0
    { dst_sacc->chunk[i] += dst_sacc->chunk[i];
1085
0
    }
1086
0
  }
1087
0
  else
1088
0
  {
1089
0
    xsum_carry_propagate (src_sacc);
1090
1091
0
    if (src_sacc->Inf) xsum_small_add_inf_nan (dst_sacc, src_sacc->Inf);
1092
0
    if (src_sacc->NaN) xsum_small_add_inf_nan (dst_sacc, src_sacc->NaN);
1093
1094
0
    for (i = 0; i < XSUM_SCHUNKS; i++)
1095
0
    { dst_sacc->chunk[i] += src_sacc->chunk[i];
1096
0
    }
1097
0
  }
1098
1099
0
  dst_sacc->adds_until_propagate = XSUM_SMALL_CARRY_TERMS-2;
1100
0
}
1101
1102
1103
/* NEGATE THE VALUE IN A SMALL ACCUMULATOR. */
1104
1105
void xsum_small_negate (xsum_small_accumulator *restrict sacc)
1106
0
{
1107
0
  int i;
1108
1109
0
  if (xsum_debug) c_printf("\nNEGATING A SMALL ACCUMULATOR\n");
1110
1111
0
  for (i = 0; i < XSUM_SCHUNKS; i++)
1112
0
  { sacc->chunk[i] = -sacc->chunk[i];
1113
0
  }
1114
1115
0
  if (sacc->Inf != 0)
1116
0
  { sacc->Inf ^= XSUM_SIGN_MASK;
1117
0
  }
1118
0
}
1119
1120
1121
/* RETURN THE RESULT OF ROUNDING A SMALL ACCUMULATOR.  The rounding mode
1122
   is to nearest, with ties to even.  The small accumulator may be modified
1123
   by this operation (by carry propagation being done), but the value it
1124
   represents should not change. */
1125
1126
xsum_flt xsum_small_round (xsum_small_accumulator *restrict sacc)
1127
37.2k
{
1128
37.2k
  xsum_int ivalue;
1129
37.2k
  xsum_schunk lower;
1130
37.2k
  int i, j, e, more;
1131
37.2k
  xsum_int intv;
1132
37.2k
  double fltv;
1133
1134
37.2k
  if (xsum_debug) c_printf("\nROUNDING SMALL ACCUMULATOR\n");
1135
1136
  /* See if we have a NaN from one of the numbers being a NaN, in
1137
     which case we return the NaN with largest payload, or an infinite
1138
     result (+Inf, -Inf, or a NaN if both +Inf and -Inf occurred).
1139
     Note that we do NOT return NaN if we have both an infinite number
1140
     and a sum of other numbers that overflows with opposite sign,
1141
     since there is no real ambiguity regarding the sign in such a case. */
1142
1143
37.2k
  if (sacc->NaN != 0)
1144
807
  { COPY64(fltv, sacc->NaN);
1145
807
    return fltv;
1146
807
  }
1147
1148
36.4k
  if (sacc->Inf != 0)
1149
3.72k
  { COPY64 (fltv, sacc->Inf);
1150
3.72k
    return fltv;
1151
3.72k
  }
1152
1153
  /* If none of the numbers summed were infinite or NaN, we proceed to
1154
     propagate carries, as a preliminary to finding the magnitude of
1155
     the sum.  This also ensures that the sign of the result can be
1156
     determined from the uppermost non-zero chunk.
1157
1158
     We also find the index, i, of this uppermost non-zero chunk, as
1159
     the value returned by xsum_carry_propagate, and set ivalue to
1160
     sacc->chunk[i].  Note that ivalue will not be 0 or -1, unless
1161
     i is 0 (the lowest chunk), in which case it will be handled by
1162
     the code for denormalized numbers. */
1163
1164
32.7k
  i = xsum_carry_propagate(sacc);
1165
1166
32.7k
  if (xsum_debug) xsum_small_display(sacc);
1167
1168
32.7k
  ivalue = sacc->chunk[i];
1169
1170
  /* Handle a possible denormalized number, including zero. */
1171
1172
32.7k
  if (i <= 1)
1173
8.98k
  {
1174
    /* Check for zero value, in which case we can return immediately. */
1175
1176
8.98k
    if (ivalue == 0)
1177
777
    { return 0.0;
1178
777
    }
1179
1180
    /* Check if it is actually a denormalized number.  It always is if only
1181
       the lowest chunk is non-zero.  If the highest non-zero chunk is the
1182
       next-to-lowest, we check the magnitude of the absolute value.
1183
       Note that the real exponent is 1 (not 0), so we need to shift right
1184
       by 1 here. */
1185
1186
8.20k
    if (i == 0)
1187
1.10k
    { intv = ivalue >= 0 ? ivalue : -ivalue;
1188
1.10k
      intv >>= 1;
1189
1.10k
      if (ivalue < 0)
1190
877
      { intv |= XSUM_SIGN_MASK;
1191
877
      }
1192
1.10k
      if (xsum_debug)
1193
0
      { c_printf("denormalized with i==0: intv %016llx\n",
1194
0
                (long long)intv);
1195
0
      }
1196
1.10k
      COPY64 (fltv, intv);
1197
1.10k
      return fltv;
1198
1.10k
    }
1199
7.10k
    else
1200
7.10k
    { /* Note: Left shift of -ve number is undefined, so do a multiply instead,
1201
               which is probably optimized to a shift. */
1202
7.10k
      intv = ivalue * ((xsum_int)1 << (XSUM_LOW_MANTISSA_BITS-1))
1203
7.10k
               + (sacc->chunk[0] >> 1);
1204
7.10k
      if (intv < 0)
1205
3.35k
      { if (intv > - ((xsum_int)1 << XSUM_MANTISSA_BITS))
1206
1.55k
        { intv = (-intv) | XSUM_SIGN_MASK;
1207
1.55k
          if (xsum_debug)
1208
0
          { c_printf("denormalized with i==1: intv %016llx\n",
1209
0
                    (long long)intv);
1210
0
          }
1211
1.55k
          COPY64 (fltv, intv);
1212
1.55k
          return fltv;
1213
1.55k
        }
1214
3.35k
      }
1215
3.75k
      else /* non-negative */
1216
3.75k
      { if ((xsum_uint)intv < (xsum_uint)1 << XSUM_MANTISSA_BITS)
1217
1.75k
        { if (xsum_debug)
1218
0
          { c_printf("denormalized with i==1: intv %016llx\n",
1219
0
                    (long long)intv);
1220
0
          }
1221
1.75k
          COPY64 (fltv, intv);
1222
1.75k
          return fltv;
1223
1.75k
        }
1224
3.75k
      }
1225
      /* otherwise, it's not actually denormalized, so fall through to below */
1226
7.10k
    }
1227
8.20k
  }
1228
1229
  /* Find the location of the uppermost 1 bit in the absolute value of
1230
     the upper chunk by converting it (as a signed integer) to a
1231
     floating point value, and looking at the exponent.  Then set
1232
     'more' to the number of bits from the lower chunk (and maybe the
1233
     next lower) that are needed to fill out the mantissa of the
1234
     result (including the top implicit 1 bit), plus two extra bits to
1235
     help decide on rounding.  For negative numbers, it may turn out
1236
     later that we need another bit, because negating a negative value
1237
     may carry out of the top here, but not carry out of the top once
1238
     more bits are shifted into the bottom later on. */
1239
1240
27.5k
  fltv = (xsum_flt) ivalue;  /* finds position of topmost 1 bit of |ivalue| */
1241
27.5k
  COPY64 (intv, fltv);
1242
27.5k
  e = (intv >> XSUM_MANTISSA_BITS) & XSUM_EXP_MASK; /* e-bias is in 0..32 */
1243
27.5k
  more = 2 + XSUM_MANTISSA_BITS + XSUM_EXP_BIAS - e;
1244
1245
27.5k
  if (xsum_debug)
1246
0
  { c_printf("e: %d, more: %d,             ivalue: %016llx\n",
1247
0
            e,more,(long long)ivalue);
1248
0
  }
1249
1250
  /* Change 'ivalue' to put in 'more' bits from lower chunks into the bottom.
1251
     Also set 'j' to the index of the lowest chunk from which these bits came,
1252
     and 'lower' to the remaining bits of that chunk not now in 'ivalue'.
1253
     Note that 'lower' initially has at least one bit in it, which we can
1254
     later move into 'ivalue' if it turns out that one more bit is needed. */
1255
1256
27.5k
  ivalue *= (xsum_int)1 << more;  /* multiply, since << of negative undefined */
1257
27.5k
  if (xsum_debug)
1258
0
  { c_printf("after ivalue <<= more,         ivalue: %016llx\n",
1259
0
            (long long)ivalue);
1260
0
  }
1261
27.5k
  j = i-1;
1262
27.5k
  lower = sacc->chunk[j];  /* must exist, since denormalized if i==0 */
1263
27.5k
  if (more >= XSUM_LOW_MANTISSA_BITS)
1264
22.8k
  { more -= XSUM_LOW_MANTISSA_BITS;
1265
22.8k
    ivalue += lower << more;
1266
22.8k
    if (xsum_debug)
1267
0
    { c_printf("after ivalue += lower << more, ivalue: %016llx\n",
1268
0
              (long long)ivalue);
1269
0
    }
1270
22.8k
    j -= 1;
1271
22.8k
    lower = j < 0 ? 0 : sacc->chunk[j];
1272
22.8k
  }
1273
27.5k
  ivalue += lower >> (XSUM_LOW_MANTISSA_BITS - more);
1274
27.5k
  lower &= ((xsum_schunk)1 << (XSUM_LOW_MANTISSA_BITS - more)) - 1;
1275
1276
27.5k
  if (xsum_debug)
1277
0
  { c_printf("after final add to ivalue,     ivalue: %016llx\n",
1278
0
            (long long)ivalue);
1279
0
    c_printf("j: %d, e: %d, |ivalue|: %016llx, lower: %016llx (a)\n",
1280
0
           j, e, (long long) (ivalue<0 ? -ivalue : ivalue), (long long)lower);
1281
0
    c_printf("   mask of low 55 bits:   007fffffffffffff,  mask: %016llx\n",
1282
0
            (long long)((xsum_schunk)1 << (XSUM_LOW_MANTISSA_BITS - more)) - 1);
1283
0
  }
1284
1285
  /* Decide on rounding, with separate code for positive and negative values.
1286
1287
     At this point, 'ivalue' has the signed mantissa bits, plus two extra
1288
     bits, with 'e' recording the exponent position for these within their
1289
     top chunk.  For positive 'ivalue', the bits in 'lower' and chunks
1290
     below 'j' add to the absolute value; for negative 'ivalue' they
1291
     subtract.
1292
1293
     After setting 'ivalue' to the tentative unsigned mantissa
1294
     (shifted left 2), and 'intv' to have the correct sign, this
1295
     code goes to done_rounding if it finds that just discarding lower
1296
     order bits is correct, and to round_away_from_zero if instead the
1297
     magnitude should be increased by one in the lowest mantissa bit. */
1298
1299
27.5k
  if (ivalue >= 0)  /* number is positive, lower bits are added to magnitude */
1300
13.0k
  {
1301
13.0k
    intv = 0;  /* positive sign */
1302
1303
13.0k
    if ((ivalue & 2) == 0)  /* extra bits are 0x */
1304
6.54k
    { if (xsum_debug)
1305
0
      { c_printf("+, no adjustment, since remainder adds <1/2\n");
1306
0
      }
1307
6.54k
      goto done_rounding;
1308
6.54k
    }
1309
1310
6.47k
    if ((ivalue & 1) != 0)  /* extra bits are 11 */
1311
1.55k
    { if (xsum_debug)
1312
0
      { c_printf("+, round away from 0, since remainder adds >1/2\n");
1313
0
      }
1314
1.55k
      goto round_away_from_zero;
1315
1.55k
    }
1316
1317
4.91k
    if ((ivalue & 4) != 0)  /* low bit is 1 (odd), extra bits are 10 */
1318
2.44k
    { if (xsum_debug)
1319
0
      { c_printf("+odd, round away from 0, since remainder adds >=1/2\n");
1320
0
      }
1321
2.44k
      goto round_away_from_zero;
1322
2.44k
    }
1323
1324
2.47k
    if (lower == 0)  /* see if any lower bits are non-zero */
1325
58.8k
    { while (j > 0)
1326
56.7k
      { j -= 1;
1327
56.7k
        if (sacc->chunk[j] != 0)
1328
131
        { lower = 1;
1329
131
          break;
1330
131
        }
1331
56.7k
      }
1332
2.21k
    }
1333
1334
2.47k
    if (lower != 0)  /* low bit 0 (even), extra bits 10, non-zero lower bits */
1335
391
    { if (xsum_debug)
1336
0
      { c_printf("+even, round away from 0, since remainder adds >1/2\n");
1337
0
      }
1338
391
      goto round_away_from_zero;
1339
391
    }
1340
2.08k
    else  /* low bit 0 (even), extra bits 10, all lower bits 0 */
1341
2.08k
    { if (xsum_debug)
1342
0
      { c_printf("+even, no adjustment, since reaminder adds exactly 1/2\n");
1343
0
      }
1344
2.08k
      goto done_rounding;
1345
2.08k
    }
1346
2.47k
  }
1347
1348
14.5k
  else  /* number is negative, lower bits are subtracted from magnitude */
1349
14.5k
  {
1350
    /* Check for a negative 'ivalue' that when negated doesn't contain a full
1351
       mantissa's worth of bits, plus one to help rounding.  If so, move one
1352
       more bit into 'ivalue' from 'lower' (and remove it from 'lower').
1353
       This happens when the negation of the upper part of 'ivalue' has the
1354
       form 10000... but the negation of the full 'ivalue' is not 10000... */
1355
1356
14.5k
    if (((-ivalue) & ((xsum_int)1 << (XSUM_MANTISSA_BITS+2))) == 0)
1357
4.12k
    { int pos = (xsum_schunk)1 << (XSUM_LOW_MANTISSA_BITS - 1 - more);
1358
4.12k
      ivalue *= 2;  /* note that left shift undefined if ivalue is negative */
1359
4.12k
      if (lower & pos)
1360
1.62k
      { ivalue += 1;
1361
1.62k
        lower &= ~pos;
1362
1.62k
      }
1363
4.12k
      e -= 1;
1364
4.12k
      if (xsum_debug)
1365
0
      { c_printf("j: %d, e: %d, |ivalue|: %016llx, lower: %016llx (b)\n",
1366
0
             j, e, (long long) (ivalue<0 ? -ivalue : ivalue), (long long)lower);
1367
0
      }
1368
4.12k
    }
1369
1370
14.5k
    intv = XSUM_SIGN_MASK;    /* negative sign */
1371
14.5k
    ivalue = -ivalue;         /* ivalue now contains the absolute value */
1372
1373
14.5k
    if ((ivalue & 3) == 3)  /* extra bits are 11 */
1374
3.05k
    { if (xsum_debug)
1375
0
      { c_printf("-, round away from 0, since remainder adds >1/2\n");
1376
0
      }
1377
3.05k
      goto round_away_from_zero;
1378
3.05k
    }
1379
1380
11.4k
    if ((ivalue & 3) <= 1)  /* extra bits are 00 or 01 */
1381
6.69k
    { if (xsum_debug)
1382
0
      { c_printf(
1383
0
         "-, no adjustment, since remainder adds <=1/4 or subtracts <1/4\n");
1384
0
      }
1385
6.69k
      goto done_rounding;
1386
6.69k
    }
1387
1388
4.74k
    if ((ivalue & 4) == 0)  /* low bit is 0 (even), extra bits are 10 */
1389
1.22k
    { if (xsum_debug)
1390
0
      { c_printf("-even, no adjustment, since remainder adds <=1/2\n");
1391
0
      }
1392
1.22k
      goto done_rounding;
1393
1.22k
    }
1394
1395
3.52k
    if (lower == 0)  /* see if any lower bits are non-zero */
1396
60.8k
    { while (j > 0)
1397
58.9k
      { j -= 1;
1398
58.9k
        if (sacc->chunk[j] != 0)
1399
37
        { lower = 1;
1400
37
          break;
1401
37
        }
1402
58.9k
      }
1403
1.90k
    }
1404
1405
3.52k
    if (lower != 0)  /* low bit 1 (odd), extra bits 10, non-zero lower bits */
1406
1.65k
    { if (xsum_debug)
1407
0
      { c_printf("-odd, no adjustment, since remainder adds <1/2\n");
1408
0
      }
1409
1.65k
      goto done_rounding;
1410
1.65k
    }
1411
1.86k
    else  /* low bit 1 (odd), extra bits are 10, lower bits are all 0 */
1412
1.86k
    { if (xsum_debug)
1413
0
      { c_printf("-odd, round away from 0, since remainder adds exactly 1/2\n");
1414
0
      }
1415
1.86k
      goto round_away_from_zero;
1416
1.86k
    }
1417
1418
3.52k
  }
1419
1420
9.31k
round_away_from_zero:
1421
1422
  /* Round away from zero, then check for carry having propagated out the
1423
     top, and shift if so. */
1424
1425
9.31k
  ivalue += 4;  /* add 1 to low-order mantissa bit */
1426
9.31k
  if (ivalue & ((xsum_int)1 << (XSUM_MANTISSA_BITS+3)))
1427
1.86k
  { ivalue >>= 1;
1428
1.86k
    e += 1;
1429
1.86k
  }
1430
1431
27.5k
done_rounding: ;
1432
1433
  /* Get rid of the bottom 2 bits that were used to decide on rounding. */
1434
1435
27.5k
  ivalue >>= 2;
1436
1437
  /* Adjust to the true exponent, accounting for where this chunk is. */
1438
1439
27.5k
  e += (i<<XSUM_LOW_EXP_BITS) - XSUM_EXP_BIAS - XSUM_MANTISSA_BITS;
1440
1441
  /* If exponent has overflowed, change to plus or minus Inf and return. */
1442
1443
27.5k
  if (e >= XSUM_EXP_MASK)
1444
63
  { intv |= (xsum_int) XSUM_EXP_MASK << XSUM_MANTISSA_BITS;
1445
63
    COPY64 (fltv, intv);
1446
63
    if (xsum_debug)
1447
0
    { c_printf ("Final rounded result: %.17le (overflowed)\n  ", fltv);
1448
0
      pbinary_double(fltv);
1449
0
      c_printf("\n");
1450
0
    }
1451
63
    return fltv;
1452
63
  }
1453
1454
  /* Put exponent and mantissa into intv, which already has the sign,
1455
     then copy into fltv. */
1456
1457
27.4k
  intv += (xsum_int)e << XSUM_MANTISSA_BITS;
1458
27.4k
  intv += ivalue & XSUM_MANTISSA_MASK;  /* mask out the implicit 1 bit */
1459
27.4k
  COPY64 (fltv, intv);
1460
1461
27.4k
  if (xsum_debug)
1462
0
  { c_printf ("Final rounded result: %.17le\n  ", fltv);
1463
0
    pbinary_double(fltv);
1464
0
    c_printf("\n");
1465
0
    if ((ivalue >> XSUM_MANTISSA_BITS) != 1) c_abort();
1466
0
  }
1467
1468
27.4k
  return fltv;
1469
27.4k
}
1470
1471
1472
/* INITIALIZE A LARGE ACCUMULATOR TO ZERO. */
1473
1474
void xsum_large_init (xsum_large_accumulator *restrict lacc)
1475
0
{
1476
0
  xsum_large_init_chunks (lacc);
1477
0
  xsum_small_init (&lacc->sacc);
1478
0
}
1479
1480
1481
/* ADD A VECTOR OF FLOATING-POINT NUMBERS TO A LARGE ACCUMULATOR. */
1482
1483
void xsum_large_addv (xsum_large_accumulator *restrict lacc,
1484
                      const xsum_flt *restrict vec,
1485
                      xsum_length n)
1486
0
{
1487
0
  if (xsum_debug) c_printf("\nLARGE ADDV OF %ld VALUES\n",(long)n);
1488
1489
0
# if OPT_LARGE_SUM
1490
0
  {
1491
0
    xsum_lcount count;
1492
0
    xsum_expint ix;
1493
0
    xsum_uint uintv;
1494
1495
0
    while (n > 3)
1496
0
    {
1497
0
      COPY64 (uintv, *vec);
1498
0
      vec += 1;
1499
1500
0
      ix = uintv >> XSUM_MANTISSA_BITS;
1501
1502
0
      count = lacc->count[ix] - 1;
1503
1504
0
      if (count < 0)
1505
0
      { xsum_large_add_value_inf_nan (lacc, ix, uintv);
1506
0
      }
1507
0
      else
1508
0
      { lacc->count[ix] = count;
1509
0
        lacc->chunk[ix] += uintv;
1510
0
      }
1511
1512
0
      COPY64 (uintv, *vec);
1513
0
      vec += 1;
1514
1515
0
      ix = uintv >> XSUM_MANTISSA_BITS;
1516
1517
0
      count = lacc->count[ix] - 1;
1518
1519
0
      if (count < 0)
1520
0
      { xsum_large_add_value_inf_nan (lacc, ix, uintv);
1521
0
      }
1522
0
      else
1523
0
      { lacc->count[ix] = count;
1524
0
        lacc->chunk[ix] += uintv;
1525
0
      }
1526
1527
0
      COPY64 (uintv, *vec);
1528
0
      vec += 1;
1529
1530
0
      ix = uintv >> XSUM_MANTISSA_BITS;
1531
1532
0
      count = lacc->count[ix] - 1;
1533
1534
0
      if (count < 0)
1535
0
      { xsum_large_add_value_inf_nan (lacc, ix, uintv);
1536
0
      }
1537
0
      else
1538
0
      { lacc->count[ix] = count;
1539
0
        lacc->chunk[ix] += uintv;
1540
0
      }
1541
1542
0
      COPY64 (uintv, *vec);
1543
0
      vec += 1;
1544
1545
0
      ix = uintv >> XSUM_MANTISSA_BITS;
1546
1547
0
      count = lacc->count[ix] - 1;
1548
1549
0
      if (count < 0)
1550
0
      { xsum_large_add_value_inf_nan (lacc, ix, uintv);
1551
0
      }
1552
0
      else
1553
0
      { lacc->count[ix] = count;
1554
0
        lacc->chunk[ix] += uintv;
1555
0
      }
1556
1557
0
      n -= 4;
1558
0
    }
1559
1560
0
    while (n > 0)
1561
0
    {
1562
0
      COPY64 (uintv, *vec);
1563
0
      vec += 1;
1564
1565
0
      ix = uintv >> XSUM_MANTISSA_BITS;
1566
1567
0
      count = lacc->count[ix] - 1;
1568
1569
0
      if (count < 0)
1570
0
      { xsum_large_add_value_inf_nan (lacc, ix, uintv);
1571
0
      }
1572
0
      else
1573
0
      { lacc->count[ix] = count;
1574
0
        lacc->chunk[ix] += uintv;
1575
0
      }
1576
1577
0
      n -= 1;
1578
0
    }
1579
0
  }
1580
# else
1581
  {
1582
    /* Version not manually optimized - maybe the compiler can do better. */
1583
1584
    if (n == 0)
1585
    { return;
1586
    }
1587
1588
    xsum_lcount count;
1589
    xsum_expint ix;
1590
    xsum_uint uintv;
1591
1592
    do
1593
    {
1594
      /* Fetch the next number, and convert to integer form in uintv. */
1595
1596
      COPY64 (uintv, *vec);
1597
      vec += 1;
1598
1599
      /* Isolate the upper sign+exponent bits that index the chunk. */
1600
1601
      ix = uintv >> XSUM_MANTISSA_BITS;
1602
1603
      /* Find the count for this chunk, and subtract one. */
1604
1605
      count = lacc->count[ix] - 1;
1606
1607
      if (count < 0)
1608
      {
1609
        /* If the decremented count is negative, it's either a special
1610
           Inf/NaN chunk (in which case count will stay at -1), or one that
1611
           needs to be transferred to the small accumulator, or one that
1612
           has never been used before and needs to be initialized. */
1613
1614
        xsum_large_add_value_inf_nan (lacc, ix, uintv);
1615
      }
1616
      else
1617
      {
1618
        /* Store the decremented count of additions allowed before transfer,
1619
           and add this value to the chunk. */
1620
1621
        lacc->count[ix] = count;
1622
        lacc->chunk[ix] += uintv;
1623
      }
1624
1625
      n -= 1;
1626
1627
    } while (n > 0);
1628
  }
1629
# endif
1630
0
}
1631
1632
1633
/* ADD ONE DOUBLE TO A LARGE ACCUMULATOR.  Just calls xsum_large_addv. */
1634
1635
void xsum_large_add1 (xsum_large_accumulator *restrict lacc, xsum_flt value)
1636
0
{
1637
0
  xsum_large_addv (lacc, &value, 1);
1638
0
}
1639
1640
1641
/* ADD SQUARED NORM OF VECTOR OF FLOATING-POINT NUMBERS TO LARGE ACCUMULATOR. */
1642
1643
void xsum_large_add_sqnorm (xsum_large_accumulator *restrict lacc,
1644
                            const xsum_flt *restrict vec,
1645
                            xsum_length n)
1646
0
{
1647
0
  if (xsum_debug) c_printf("\nLARGE ADD_SQNORM OF %ld VALUES\n",(long)n);
1648
1649
0
# if OPT_LARGE_SQNORM
1650
0
  {
1651
0
    xsum_lcount count;
1652
0
    xsum_expint ix;
1653
0
    xsum_uint uintv;
1654
0
    double fltv;
1655
1656
0
    while (n > 3)
1657
0
    {
1658
0
      fltv = *vec * *vec;
1659
0
      COPY64 (uintv, fltv);
1660
0
      vec += 1;
1661
1662
0
      ix = uintv >> XSUM_MANTISSA_BITS;
1663
1664
0
      count = lacc->count[ix] - 1;
1665
1666
0
      if (count < 0)
1667
0
      { xsum_large_add_value_inf_nan (lacc, ix, uintv);
1668
0
      }
1669
0
      else
1670
0
      { lacc->count[ix] = count;
1671
0
        lacc->chunk[ix] += uintv;
1672
0
      }
1673
1674
0
      fltv = *vec * *vec;
1675
0
      COPY64 (uintv, fltv);
1676
0
      vec += 1;
1677
1678
0
      ix = uintv >> XSUM_MANTISSA_BITS;
1679
1680
0
      count = lacc->count[ix] - 1;
1681
1682
0
      if (count < 0)
1683
0
      { xsum_large_add_value_inf_nan (lacc, ix, uintv);
1684
0
      }
1685
0
      else
1686
0
      { lacc->count[ix] = count;
1687
0
        lacc->chunk[ix] += uintv;
1688
0
      }
1689
1690
0
      fltv = *vec * *vec;
1691
0
      COPY64 (uintv, fltv);
1692
0
      vec += 1;
1693
1694
0
      ix = uintv >> XSUM_MANTISSA_BITS;
1695
1696
0
      count = lacc->count[ix] - 1;
1697
1698
0
      if (count < 0)
1699
0
      { xsum_large_add_value_inf_nan (lacc, ix, uintv);
1700
0
      }
1701
0
      else
1702
0
      { lacc->count[ix] = count;
1703
0
        lacc->chunk[ix] += uintv;
1704
0
      }
1705
1706
0
      fltv = *vec * *vec;
1707
0
      COPY64 (uintv, fltv);
1708
0
      vec += 1;
1709
1710
0
      ix = uintv >> XSUM_MANTISSA_BITS;
1711
1712
0
      count = lacc->count[ix] - 1;
1713
1714
0
      if (count < 0)
1715
0
      { xsum_large_add_value_inf_nan (lacc, ix, uintv);
1716
0
      }
1717
0
      else
1718
0
      { lacc->count[ix] = count;
1719
0
        lacc->chunk[ix] += uintv;
1720
0
      }
1721
1722
0
      n -= 4;
1723
0
    }
1724
1725
0
    while (n > 0)
1726
0
    {
1727
0
      fltv = *vec * *vec;
1728
0
      COPY64 (uintv, fltv);
1729
0
      vec += 1;
1730
1731
0
      ix = uintv >> XSUM_MANTISSA_BITS;
1732
1733
0
      count = lacc->count[ix] - 1;
1734
1735
0
      if (count < 0)
1736
0
      { xsum_large_add_value_inf_nan (lacc, ix, uintv);
1737
0
      }
1738
0
      else
1739
0
      { lacc->count[ix] = count;
1740
0
        lacc->chunk[ix] += uintv;
1741
0
      }
1742
1743
0
      n -= 1;
1744
0
    }
1745
0
  }
1746
# else
1747
  {
1748
    /* Version not manually optimized - maybe the compiler can do better. */
1749
1750
    xsum_lcount count;
1751
    xsum_expint ix;
1752
    xsum_uint uintv;
1753
    double fltv;
1754
1755
    if (n == 0)
1756
    { return;
1757
    }
1758
1759
    do
1760
    {
1761
      /* Fetch the next number, square it, and convert to integer form in
1762
         uintv. */
1763
1764
      fltv = *vec * *vec;
1765
      COPY64 (uintv, fltv);
1766
      vec += 1;
1767
1768
      /* Isolate the upper sign+exponent bits that index the chunk. */
1769
1770
      ix = uintv >> XSUM_MANTISSA_BITS;
1771
1772
      /* Find the count for this chunk, and subtract one. */
1773
1774
      count = lacc->count[ix] - 1;
1775
1776
      if (count < 0)
1777
      {
1778
        /* If the decremented count is negative, it's either a special
1779
           Inf/NaN chunk (in which case count will stay at -1), or one that
1780
           needs to be transferred to the small accumulator, or one that
1781
           has never been used before and needs to be initialized. */
1782
1783
        xsum_large_add_value_inf_nan (lacc, ix, uintv);
1784
      }
1785
      else
1786
      {
1787
        /* Store the decremented count of additions allowed before transfer,
1788
           and add this value to the chunk. */
1789
1790
        lacc->count[ix] = count;
1791
        lacc->chunk[ix] += uintv;
1792
      }
1793
1794
      n -= 1;
1795
1796
    } while (n > 0);
1797
  }
1798
# endif
1799
0
}
1800
1801
1802
/* ADD DOT PRODUCT OF VECTORS OF FLOATING-POINT NUMBERS TO LARGE ACCUMULATOR. */
1803
1804
void xsum_large_add_dot (xsum_large_accumulator *restrict lacc,
1805
                         const xsum_flt *vec1,
1806
                         const xsum_flt *vec2,
1807
                         xsum_length n)
1808
0
{
1809
0
  if (xsum_debug) c_printf("\nLARGE ADD_DOT OF %ld VALUES\n",(long)n);
1810
1811
0
# if OPT_LARGE_DOT
1812
0
  {
1813
0
    xsum_lcount count;
1814
0
    xsum_expint ix;
1815
0
    xsum_uint uintv;
1816
0
    double fltv;
1817
1818
0
    while (n > 3)
1819
0
    {
1820
0
      fltv = *vec1 * *vec2;
1821
0
      COPY64 (uintv, fltv);
1822
0
      vec1 += 1; vec2 += 1;
1823
1824
0
      ix = uintv >> XSUM_MANTISSA_BITS;
1825
1826
0
      count = lacc->count[ix] - 1;
1827
1828
0
      if (count < 0)
1829
0
      { xsum_large_add_value_inf_nan (lacc, ix, uintv);
1830
0
      }
1831
0
      else
1832
0
      { lacc->count[ix] = count;
1833
0
        lacc->chunk[ix] += uintv;
1834
0
      }
1835
1836
0
      fltv = *vec1 * *vec2;
1837
0
      COPY64 (uintv, fltv);
1838
0
      vec1 += 1; vec2 += 1;
1839
1840
0
      ix = uintv >> XSUM_MANTISSA_BITS;
1841
1842
0
      count = lacc->count[ix] - 1;
1843
1844
0
      if (count < 0)
1845
0
      { xsum_large_add_value_inf_nan (lacc, ix, uintv);
1846
0
      }
1847
0
      else
1848
0
      { lacc->count[ix] = count;
1849
0
        lacc->chunk[ix] += uintv;
1850
0
      }
1851
1852
0
      fltv = *vec1 * *vec2;
1853
0
      COPY64 (uintv, fltv);
1854
0
      vec1 += 1; vec2 += 1;
1855
1856
0
      ix = uintv >> XSUM_MANTISSA_BITS;
1857
1858
0
      count = lacc->count[ix] - 1;
1859
1860
0
      if (count < 0)
1861
0
      { xsum_large_add_value_inf_nan (lacc, ix, uintv);
1862
0
      }
1863
0
      else
1864
0
      { lacc->count[ix] = count;
1865
0
        lacc->chunk[ix] += uintv;
1866
0
      }
1867
1868
0
      fltv = *vec1 * *vec2;
1869
0
      COPY64 (uintv, fltv);
1870
0
      vec1 += 1; vec2 += 1;
1871
1872
0
      ix = uintv >> XSUM_MANTISSA_BITS;
1873
1874
0
      count = lacc->count[ix] - 1;
1875
1876
0
      if (count < 0)
1877
0
      { xsum_large_add_value_inf_nan (lacc, ix, uintv);
1878
0
      }
1879
0
      else
1880
0
      { lacc->count[ix] = count;
1881
0
        lacc->chunk[ix] += uintv;
1882
0
      }
1883
1884
0
      n -= 4;
1885
0
    }
1886
1887
0
    while (n > 0)
1888
0
    {
1889
0
      fltv = *vec1 * *vec2;
1890
0
      COPY64 (uintv, fltv);
1891
0
      vec1 += 1; vec2 += 1;
1892
1893
0
      ix = uintv >> XSUM_MANTISSA_BITS;
1894
1895
0
      count = lacc->count[ix] - 1;
1896
1897
0
      if (count < 0)
1898
0
      { xsum_large_add_value_inf_nan (lacc, ix, uintv);
1899
0
      }
1900
0
      else
1901
0
      { lacc->count[ix] = count;
1902
0
        lacc->chunk[ix] += uintv;
1903
0
      }
1904
1905
0
      n -= 1;
1906
0
    }
1907
0
  }
1908
# else
1909
  {
1910
    /* Version not manually optimized - maybe the compiler can do better. */
1911
1912
    xsum_lcount count;
1913
    xsum_expint ix;
1914
    xsum_uint uintv;
1915
    double fltv;
1916
1917
    if (n == 0)
1918
    { return;
1919
    }
1920
1921
    do
1922
    {
1923
      /* Fetch the next numbers, multiply them, and convert the result to
1924
         integer form in uintv. */
1925
1926
      fltv = *vec1 * *vec2;
1927
      COPY64 (uintv, fltv);
1928
      vec1 += 1; vec2 += 1;
1929
1930
      /* Isolate the upper sign+exponent bits that index the chunk. */
1931
1932
      ix = uintv >> XSUM_MANTISSA_BITS;
1933
1934
      /* Find the count for this chunk, and subtract one. */
1935
1936
      count = lacc->count[ix] - 1;
1937
1938
      if (count < 0)
1939
      {
1940
        /* If the decremented count is negative, it's either a special
1941
           Inf/NaN chunk (in which case count will stay at -1), or one that
1942
           needs to be transferred to the small accumulator, or one that
1943
           has never been used before and needs to be initialized. */
1944
1945
        xsum_large_add_value_inf_nan (lacc, ix, uintv);
1946
      }
1947
      else
1948
      {
1949
        /* Store the decremented count of additions allowed before transfer,
1950
           and add this value to the chunk. */
1951
1952
        lacc->count[ix] = count;
1953
        lacc->chunk[ix] += uintv;
1954
      }
1955
1956
      n -= 1;
1957
1958
    } while (n > 0);
1959
  }
1960
# endif
1961
0
}
1962
1963
1964
/* ADD A LARGE ACCUMULATOR TO ANOTHER LARGE ACCUMULATOR.  The first argument
1965
   is the destination, which is modified.  The second is the accumulator to
1966
   add, which may also be modified, but should still represent the same
1967
   number.  Source and destination may be the same. */
1968
1969
void xsum_large_add_accumulator (xsum_large_accumulator *dst_lacc,
1970
                                 xsum_large_accumulator *src_lacc)
1971
0
{
1972
0
  if (xsum_debug) c_printf("\nADDING ACCUMULATOR TO A LARGE ACCUMULATOR\n");
1973
1974
0
  xsum_large_transfer_to_small (src_lacc);
1975
0
  xsum_small_add_accumulator (&dst_lacc->sacc, &src_lacc->sacc);
1976
0
}
1977
1978
1979
/* NEGATE THE VALUE IN A LARGE ACCUMULATOR. */
1980
1981
void xsum_large_negate (xsum_large_accumulator *restrict lacc)
1982
0
{
1983
0
  if (xsum_debug) c_printf("\nNEGATING A LARGE ACCUMULATOR\n");
1984
1985
0
  xsum_large_transfer_to_small (lacc);
1986
0
  xsum_small_negate (&lacc->sacc);
1987
0
}
1988
1989
1990
1991
/* RETURN RESULT OF ROUNDING A LARGE ACCUMULATOR.  Rounding mode is to nearest,
1992
   with ties to even.
1993
1994
   This is done by adding all the chunks in the large accumulator to the
1995
   small accumulator, and then calling its rounding procedure. */
1996
1997
xsum_flt xsum_large_round (xsum_large_accumulator *restrict lacc)
1998
0
{
1999
0
  if (xsum_debug) c_printf("\nROUNDING LARGE ACCUMULATOR\n");
2000
2001
0
  xsum_large_transfer_to_small (lacc);
2002
2003
0
  return xsum_small_round (&lacc->sacc);
2004
0
}
2005
2006
2007
/* TRANSFER NUMBER FROM A LARGE ACCUMULATOR TO A SMALL ACCUMULATOR. */
2008
2009
void xsum_large_to_small_accumulator (xsum_small_accumulator *restrict sacc,
2010
                                      xsum_large_accumulator *restrict lacc)
2011
0
{
2012
0
  if (xsum_debug) c_printf("\nTRANSFERRING FROM LARGE TO SMALL ACCUMULATOR\n");
2013
0
  xsum_large_transfer_to_small (lacc);
2014
0
  *sacc = lacc->sacc;
2015
0
}
2016
2017
2018
/* TRANSFER NUMBER FROM A SMALL ACCUMULATOR TO A LARGE ACCUMULATOR. */
2019
2020
void xsum_small_to_large_accumulator (xsum_large_accumulator *restrict lacc,
2021
                                      xsum_small_accumulator *restrict sacc)
2022
0
{
2023
0
  if (xsum_debug) c_printf("\nTRANSFERRING FROM SMALL TO LARGE ACCUMULATOR\n");
2024
0
  xsum_large_init_chunks (lacc);
2025
0
  lacc->sacc = *sacc;
2026
0
}
2027
2028
2029
/* FIND RESULT OF DIVIDING SMALL ACCUMULATOR BY UNSIGNED INTEGER. */
2030
2031
xsum_flt xsum_small_div_unsigned
2032
           (xsum_small_accumulator *restrict sacc, unsigned div)
2033
0
{
2034
0
  xsum_flt result;
2035
0
  unsigned rem;
2036
0
  double fltv;
2037
0
  int sign;
2038
0
  int i, j;
2039
2040
0
  if (xsum_debug) c_printf("\nDIVIDE SMALL ACCUMULATOR BY UNSIGNED INTEGER\n");
2041
2042
  /* Return NaN or an Inf if that's what's in the superaccumulator. */
2043
2044
0
  if (sacc->NaN != 0)
2045
0
  { COPY64(fltv, sacc->NaN);
2046
0
    return fltv;
2047
0
  }
2048
2049
0
  if (sacc->Inf != 0)
2050
0
  { COPY64 (fltv, sacc->Inf);
2051
0
    return fltv;
2052
0
  }
2053
2054
  /* Make a copy of the superaccumulator, so we can change it here without
2055
     changing *sacc. */
2056
2057
0
  xsum_small_accumulator tacc = *sacc;
2058
2059
  /* Carry propagate in the temporary copy of the superaccumulator.
2060
     Sets 'i' to the index of the topmost nonzero chunk. */
2061
2062
0
  i = xsum_carry_propagate(&tacc);
2063
2064
  /* Check for division by zero, and if so, return +Inf, -Inf, or NaN,
2065
     depending on whether the superaccumulator is positive, negative,
2066
     or zero. */
2067
2068
0
  if (div == 0)
2069
0
  { if (xsum_debug)
2070
0
    { c_printf("divide by zero, top chunk has index %d, value %lld\n",
2071
0
              i, tacc.chunk[i]);
2072
0
    }
2073
0
    return tacc.chunk[i] > 0 ? INFINITY : tacc.chunk[i] < 0 ? -INFINITY : NAN;
2074
0
  }
2075
2076
  /* Record sign of accumulator, and if it's negative, negate and
2077
     re-propagate so that it will be positive. */
2078
2079
0
  sign = +1;
2080
2081
0
  if (tacc.chunk[i] < 0)
2082
0
  { xsum_small_negate(&tacc);
2083
0
    i = xsum_carry_propagate(&tacc);
2084
0
    if (xsum_debug)
2085
0
    { c_printf("Negated accumulator to make it non-negative\n");
2086
0
      if (tacc.chunk[i] < 0) c_abort();
2087
0
    }
2088
0
    sign = -1;
2089
0
  }
2090
2091
  /* Do the division in the small accumulator, putting the remainder after
2092
     dividing the bottom chunk in 'rem'. */
2093
2094
0
  if (xsum_debug)
2095
0
  { c_printf("\nBefore division by %u: ",div);
2096
0
    xsum_small_display (&tacc);
2097
0
  }
2098
2099
0
  rem = 0;
2100
0
  for (j = i; j>=0; j--)
2101
0
  { xsum_uint num = ((xsum_uint) rem << XSUM_LOW_MANTISSA_BITS) + tacc.chunk[j];
2102
0
    xsum_uint quo = num / div;
2103
0
    rem = num - quo*div;
2104
0
    tacc.chunk[j] = quo;
2105
0
  }
2106
2107
0
  if (xsum_debug)
2108
0
  { c_printf("After division by %u: ",div);
2109
0
    xsum_small_display (&tacc);
2110
0
  }
2111
2112
  /* Find new top chunk. */
2113
2114
0
  while (i > 0 && tacc.chunk[i] == 0)
2115
0
  { i -= 1;
2116
0
  }
2117
2118
  /* Do rounding, with separate approachs for a normal number with biased
2119
     exponent greater than 1, and for a normal number with exponent of 1 
2120
     or a denormalized number (also having true biased exponent of 1). */
2121
2122
0
  if (i > 1 || tacc.chunk[1] >= (1 << (XSUM_HIGH_MANTISSA_BITS+2)))
2123
0
  {
2124
    /* Normalized number with at least two bits at bottom of chunk 0
2125
       below the mantissa.  Just need to 'or' in a 1 at the bottom if
2126
       remainder is non-zero to break a tie if bits below bottom of
2127
       mantissa are exactly 1/2. */
2128
2129
0
    if (xsum_debug) 
2130
0
    { c_printf("normalized (2+ bits below), low %016llx %016llx, remainder %u\n",
2131
0
              tacc.chunk[1],tacc.chunk[0],rem);
2132
0
    }
2133
2134
0
    if (rem > 0)
2135
0
    { tacc.chunk[0] |= 1;
2136
0
    }
2137
0
  }
2138
0
  else
2139
0
  {
2140
    /* Denormalized number or normal number with biased exponent of 1.
2141
       Lowest bit of bottom chunk is just below lowest bit of
2142
       mantissa.  Need to explicitly round here using the bottom bit
2143
       and the remainder - round up if lower > 1/2 or >= 1/2 and
2144
       odd. */
2145
2146
0
    if (xsum_debug)
2147
0
    { if (tacc.chunk[1] >= (1 << (XSUM_HIGH_MANTISSA_BITS+1)))
2148
0
      { c_printf("small normalized, low %016llx %016llx, remainder %u\n",
2149
0
                tacc.chunk[1],tacc.chunk[0],rem);
2150
0
      }
2151
0
      else
2152
0
      { c_printf("denormalized, low %016llx %016llx, remainder %u\n",
2153
0
                tacc.chunk[1],tacc.chunk[0],rem);
2154
0
      }
2155
0
    }
2156
2157
0
    if (tacc.chunk[0] & 1)  /* lower part is >= 1/2 */
2158
0
    {
2159
0
      if (tacc.chunk[0] & 2)  /* lowest bit of mantissa is 1 (odd) */
2160
0
      { tacc.chunk[0] += 2;     /* round up */
2161
0
      }
2162
0
      else                    /* lowest bit of mantissa is 0 (even) */
2163
0
      { if (rem > 0)            /* lower part is > 1/2 */
2164
0
        { tacc.chunk[0] += 2;     /* round up */
2165
0
        }
2166
0
      }
2167
2168
0
      tacc.chunk[0] &= ~1;  /* clear low bit (but should anyway be ignored) */
2169
0
    }
2170
0
  }
2171
2172
0
  if (xsum_debug)
2173
0
  { c_printf(
2174
0
     "New low chunk after adjusting to correct rounding with remainder %u:\n\n",
2175
0
      rem);
2176
0
    pbinary_int64 (tacc.chunk[0], XSUM_SCHUNK_BITS);
2177
0
  }
2178
2179
  /* Do the final rounding, with the lowest bit set as above. */
2180
2181
0
  result = xsum_small_round (&tacc);
2182
2183
0
  return sign*result;
2184
0
}
2185
2186
2187
/* FIND RESULT OF DIVIDING SMALL ACCUMULATOR BY SIGNED INTEGER. */
2188
2189
xsum_flt xsum_small_div_int
2190
           (xsum_small_accumulator *restrict sacc, int div)
2191
0
{ if (xsum_debug) c_printf("\nDIVIDE SMALL ACCUMULATOR BY SIGNED INTEGER\n");
2192
0
  if (div < 0)
2193
0
  { return -xsum_small_div_unsigned (sacc, (unsigned) -div);
2194
0
  }
2195
0
  else
2196
0
  { return xsum_small_div_unsigned (sacc, (unsigned) div);
2197
0
  }
2198
0
}
2199
2200
2201
/* FIND RESULT OF DIVIDING LARGE ACCUMULATOR BY UNSIGNED INTEGER. */
2202
2203
xsum_flt xsum_large_div_unsigned
2204
           (xsum_large_accumulator *restrict lacc, unsigned div)
2205
0
{ if (xsum_debug) c_printf("\nDIVIDE LARGE ACCUMULATOR BY UNSIGNED INTEGER\n");
2206
0
  xsum_large_transfer_to_small (lacc);
2207
0
  return xsum_small_div_unsigned (&lacc->sacc, div);
2208
0
}
2209
2210
2211
/* FIND RESULT OF DIVIDING LARGE ACCUMULATOR BY SIGNED INTEGER. */
2212
2213
xsum_flt xsum_large_div_int
2214
           (xsum_large_accumulator *restrict lacc, int div)
2215
0
{ if (xsum_debug) c_printf("\nDIVIDE LARGE ACCUMULATOR BY SIGNED INTEGER\n");
2216
0
  xsum_large_transfer_to_small (lacc);
2217
0
  return xsum_small_div_int (&lacc->sacc, div);
2218
0
}
2219
2220
2221
/* ------------------- ROUTINES FOR NON-EXACT SUMMATION --------------------- */
2222
2223
2224
/* SUM A VECTOR WITH DOUBLE FP ACCUMULATOR. */
2225
2226
xsum_flt xsum_sum_double (const xsum_flt *restrict vec,
2227
                          xsum_length n)
2228
0
{ double s;
2229
0
  xsum_length j;
2230
0
  s = 0.0;
2231
0
# if OPT_SIMPLE_SUM
2232
0
  { for (j = 3; j < n; j += 4)
2233
0
    { s += vec[j-3];
2234
0
      s += vec[j-2];
2235
0
      s += vec[j-1];
2236
0
      s += vec[j];
2237
0
    }
2238
0
    for (j = j-3; j < n; j++)
2239
0
    { s += vec[j];
2240
0
    }
2241
0
  }
2242
# else
2243
  { for (j = 0; j < n; j++)
2244
    { s += vec[j];
2245
    }
2246
  }
2247
# endif
2248
0
  return (xsum_flt) s;
2249
0
}
2250
2251
2252
/* SUM A VECTOR WITH FLOAT128 ACCUMULATOR. */
2253
2254
#ifdef FLOAT128
2255
2256
#include <quadmath.h>
2257
2258
xsum_flt xsum_sum_float128 (const xsum_flt *restrict vec,
2259
                            xsum_length n)
2260
{ __float128 s;
2261
  xsum_length j;
2262
  s = 0.0;
2263
  for (j = 0; j < n; j++)
2264
  { s += vec[j];
2265
  }
2266
  return (xsum_flt) s;
2267
}
2268
2269
#endif
2270
2271
2272
/* SUM A VECTOR WITH DOUBLE FP, NOT IN ORDER. */
2273
2274
xsum_flt xsum_sum_double_not_ordered (const xsum_flt *restrict vec,
2275
                                      xsum_length n)
2276
0
{ double s[2] = { 0, 0 };
2277
0
  xsum_length j;
2278
0
  for (j = 1; j < n; j += 2)
2279
0
  { s[0] += vec[j-1];
2280
0
    s[1] += vec[j];
2281
0
  }
2282
0
  if (j == n)
2283
0
  { s[0] += vec[j-1];
2284
0
  }
2285
0
  return (xsum_flt) (s[0]+s[1]);
2286
0
}
2287
2288
2289
/* SUM A VECTOR WITH KAHAN'S METHOD. */
2290
2291
xsum_flt xsum_sum_kahan (const xsum_flt *restrict vec,
2292
                         xsum_length n)
2293
0
{ double s, t, c, y;
2294
0
  xsum_length j;
2295
0
  s = 0.0;
2296
0
  c = 0.0;
2297
# if OPT_KAHAN_SUM
2298
  { for (j = 1; j < n; j += 2)
2299
    { y = vec[j-1] - c;
2300
      t = s;
2301
      s += y;
2302
      c = (s - t) - y;
2303
      y = vec[j] - c;
2304
      t = s;
2305
      s += y;
2306
      c = (s - t) - y;
2307
    }
2308
    for (j = j-1; j < n; j++)
2309
    { y = vec[j] - c;
2310
      t = s;
2311
      s += y;
2312
      c = (s - t) - y;
2313
    }
2314
  }
2315
# else
2316
0
  { for (j = 0; j < n; j++)
2317
0
    { y = vec[j] - c;
2318
0
      t = s;
2319
0
      s += y;
2320
0
      c = (s - t) - y;
2321
0
    }
2322
0
  }
2323
0
# endif
2324
0
  return (xsum_flt) s;
2325
0
}
2326
2327
2328
/* SQUARED NORM OF A VECTOR WITH DOUBLE FP ACCUMULATOR. */
2329
2330
xsum_flt xsum_sqnorm_double (const xsum_flt *restrict vec,
2331
                             xsum_length n)
2332
0
{ double s;
2333
0
  xsum_length j;
2334
2335
0
  s = 0.0;
2336
0
# if OPT_SIMPLE_SQNORM
2337
0
  { double a, b, c, d;
2338
0
    for (j = 3; j < n; j += 4)
2339
0
    { a = vec[j-3];
2340
0
      b = vec[j-2];
2341
0
      c = vec[j-1];
2342
0
      d = vec[j];
2343
0
      s += a*a;
2344
0
      s += b*b;
2345
0
      s += c*c;
2346
0
      s += d*d;
2347
0
    }
2348
0
    for (j = j-3; j < n; j++)
2349
0
    { a = vec[j];
2350
0
      s += a*a;
2351
0
    }
2352
0
  }
2353
# else
2354
  { double a;
2355
    for (j = 0; j < n; j++)
2356
    { a = vec[j];
2357
      s += a*a;
2358
    }
2359
  }
2360
# endif
2361
0
  return (xsum_flt) s;
2362
0
}
2363
2364
2365
/* SQUARED NORM OF A VECTOR WITH DOUBLE FP, NOT IN ORDER. */
2366
2367
xsum_flt xsum_sqnorm_double_not_ordered (const xsum_flt *restrict vec,
2368
                                         xsum_length n)
2369
0
{ double s[2] = { 0, 0 };
2370
0
  double a[2];
2371
0
  xsum_length j;
2372
0
  for (j = 1; j < n; j += 2)
2373
0
  { a[0] = vec[j-1];
2374
0
    a[1] = vec[j];
2375
0
    s[0] += a[0]*a[0];
2376
0
    s[1] += a[1]*a[1];
2377
0
  }
2378
0
  if (j == n)
2379
0
  { a[0] = vec[j-1];
2380
0
    s[0] += a[0]*a[0];
2381
0
  }
2382
0
  return (xsum_flt) (s[0]+s[1]);
2383
0
}
2384
2385
2386
/* DOT PRODUCT OF VECTORS WITH DOUBLE FP ACCUMULATOR. */
2387
2388
xsum_flt xsum_dot_double (const xsum_flt *vec1,
2389
                          const xsum_flt *vec2,
2390
                          xsum_length n)
2391
0
{ double s;
2392
0
  xsum_length j;
2393
2394
0
  s = 0.0;
2395
0
# if OPT_SIMPLE_DOT
2396
0
  { for (j = 3; j < n; j += 4)
2397
0
    { s += vec1[j-3] * vec2[j-3];
2398
0
      s += vec1[j-2] * vec2[j-2];
2399
0
      s += vec1[j-1] * vec2[j-1];
2400
0
      s += vec1[j] * vec2[j];
2401
0
    }
2402
0
    for (j = j-3; j < n; j++)
2403
0
    { s += vec1[j] * vec2[j];
2404
0
    }
2405
0
  }
2406
# else
2407
  { for (j = 0; j < n; j++)
2408
    { s += vec1[j] * vec2[j];
2409
    }
2410
  }
2411
# endif
2412
0
  return (xsum_flt) s;
2413
0
}
2414
2415
2416
/* DOT PRODUCT OF VECTORS WITH DOUBLE FP, NOT IN ORDER. */
2417
2418
xsum_flt xsum_dot_double_not_ordered (const xsum_flt *vec1,
2419
                                      const xsum_flt *vec2,
2420
                                      xsum_length n)
2421
0
{ double s[2] = { 0, 0 };
2422
0
  xsum_length j;
2423
0
  for (j = 1; j < n; j += 2)
2424
0
  { s[0] += vec1[j-1] * vec2[j-1];
2425
0
    s[1] += vec1[j] * vec2[j];
2426
0
  }
2427
0
  if (j == n)
2428
0
  { s[0] += vec1[j-1] * vec2[j-1];
2429
0
  }
2430
0
  return (xsum_flt) (s[0]+s[1]);
2431
0
}
2432
2433
2434
/* ------------------------- DEBUGGING ROUTINES ----------------------------- */
2435
2436
2437
/* DISPLAY A SMALL ACCUMULATOR. */
2438
2439
void xsum_small_display (xsum_small_accumulator *restrict sacc)
2440
0
{
2441
0
  int i, dots;
2442
0
  c_printf("Small accumulator:");
2443
0
  if (sacc->Inf)
2444
0
  { c_printf (" %cInf", sacc->Inf>0 ? '+' : '-');
2445
0
    if ((sacc->Inf & ((xsum_uint)XSUM_EXP_MASK << XSUM_MANTISSA_BITS))
2446
0
          != ((xsum_uint)XSUM_EXP_MASK << XSUM_MANTISSA_BITS))
2447
0
    { c_printf(" BUT WRONG CONTENTS: %llx", (long long) sacc->Inf);
2448
0
    }
2449
0
  }
2450
0
  if (sacc->NaN)
2451
0
  { c_printf (" NaN (%llx)", (long long) sacc->NaN);
2452
0
  }
2453
0
  c_printf("\n");
2454
0
  dots = 0;
2455
0
  for (i = XSUM_SCHUNKS-1; i >= 0; i--)
2456
0
  { if (sacc->chunk[i] == 0)
2457
0
    { if (!dots) c_printf("            ...\n");
2458
0
      dots = 1;
2459
0
    }
2460
0
    else
2461
0
    { c_printf ("%5d %5d ", i, (int)
2462
0
       ((i<<XSUM_LOW_EXP_BITS) - XSUM_EXP_BIAS - XSUM_MANTISSA_BITS));
2463
0
      pbinary_int64 ((int64_t) sacc->chunk[i] >> 32, XSUM_SCHUNK_BITS-32);
2464
0
      c_printf(" ");
2465
0
      pbinary_int64 ((int64_t) sacc->chunk[i] & 0xffffffff, 32);
2466
0
      c_printf ("\n");
2467
0
      dots = 0;
2468
0
    }
2469
0
  }
2470
0
  c_printf("\n");
2471
0
}
2472
2473
2474
/* RETURN NUMBER OF CHUNKS IN USE IN SMALL ACCUMULATOR. */
2475
2476
int xsum_small_chunks_used (xsum_small_accumulator *restrict sacc)
2477
0
{
2478
0
  int i, c;
2479
0
  c = 0;
2480
0
  for (i = 0; i < XSUM_SCHUNKS; i++)
2481
0
  { if (sacc->chunk[i] != 0)
2482
0
    { c += 1;
2483
0
    }
2484
0
  }
2485
0
  return c;
2486
0
}
2487
2488
2489
/* DISPLAY A LARGE ACCUMULATOR. */
2490
2491
void xsum_large_display (xsum_large_accumulator *restrict lacc)
2492
0
{
2493
0
  int i, dots;
2494
0
  c_printf("Large accumulator:\n");
2495
0
  dots = 0;
2496
0
  for (i = XSUM_LCHUNKS-1; i >= 0; i--)
2497
0
  { if (lacc->count[i] < 0)
2498
0
    { if (!dots) c_printf("            ...\n");
2499
0
      dots = 1;
2500
0
    }
2501
0
    else
2502
0
    { c_printf ("%c%4d %5d ", i & 0x800 ? '-' : '+', i & 0x7ff, lacc->count[i]);
2503
0
      pbinary_int64 ((int64_t) lacc->chunk[i] >> 32, XSUM_LCHUNK_BITS-32);
2504
0
      c_printf(" ");
2505
0
      pbinary_int64 ((int64_t) lacc->chunk[i] & 0xffffffff, 32);
2506
0
      c_printf ("\n");
2507
0
      dots = 0;
2508
0
    }
2509
0
  }
2510
0
  c_printf("\nWithin large accumulator:  ");
2511
0
  xsum_small_display (&lacc->sacc);
2512
2513
0
}
2514
2515
2516
/* RETURN NUMBER OF CHUNKS IN USE IN LARGE ACCUMULATOR. */
2517
2518
int xsum_large_chunks_used (xsum_large_accumulator *restrict lacc)
2519
0
{
2520
0
  int i, c;
2521
0
  c = 0;
2522
0
  for (i = 0; i < XSUM_LCHUNKS; i++)
2523
0
  { if (lacc->count[i] >= 0)
2524
0
    { c += 1;
2525
0
    }
2526
0
  }
2527
0
  return c;
2528
0
}
2529
2530
# pragma pop_macro("c_printf")