Program Listing for File xsum.h#
↰ Return to documentation for file (source/pele/xsum.h)
/* modified for c++ compatibility for pele */
/* With extra function to add a single number to skip the loop */
/* INTERFACE TO FUNCTIONS FOR EXACT SUMMATION. */
/* Written by Radford M. Neal, 2015 */
#ifndef EXACTSUM_RADFORD
#define EXACTSUM_RADFORD
/* using restrict with c++ https://github.com/rurban/safeclib/issues/58 */
#include <stdint.h>
#include <stdlib.h>
/* CONSTANTS DEFINING THE FLOATING POINT FORMAT. */
typedef double xsum_flt; /* C floating point type sums are done for */
typedef int64_t xsum_int; /* Signed integer type for a fp value */
typedef uint64_t xsum_uint; /* Unsigned integer type for a fp value */
typedef int_fast16_t xsum_expint; /* Integer type for holding an exponent */
#define XSUM_MANTISSA_BITS 52 /* Bits in fp mantissa, excludes implict 1 */
#define XSUM_EXP_BITS 11 /* Bits in fp exponent */
#define XSUM_MANTISSA_MASK \
(((xsum_int)1 << XSUM_MANTISSA_BITS) - 1) /* Mask for mantissa bits */
#define XSUM_EXP_MASK ((1 << XSUM_EXP_BITS) - 1) /* Mask for exponent */
#define XSUM_EXP_BIAS \
((1 << (XSUM_EXP_BITS - 1)) - 1) /* Bias added to signed exponent */
#define XSUM_SIGN_BIT \
(XSUM_MANTISSA_BITS + XSUM_EXP_BITS) /* Position of sign bit */
#define XSUM_SIGN_MASK ((xsum_uint)1 << XSUM_SIGN_BIT) /* Mask for sign bit */
/* CONSTANTS DEFINING THE SMALL ACCUMULATOR FORMAT. */
#define XSUM_SCHUNK_BITS 64 /* Bits in chunk of the small accumulator */
typedef int64_t xsum_schunk; /* Integer type of small accumulator chunk */
#define XSUM_LOW_EXP_BITS 5 /* # of low bits of exponent, in one chunk */
#define XSUM_LOW_EXP_MASK \
((1 << XSUM_LOW_EXP_BITS) - 1) /* Mask for low-order exponent bits */
#define XSUM_HIGH_EXP_BITS \
(XSUM_EXP_BITS - XSUM_LOW_EXP_BITS) /* # of high exponent bits for index */
#define XSUM_HIGH_EXP_MASK \
((1 << HIGH_EXP_BITS) - 1) /* Mask for high-order exponent bits */
#define XSUM_SCHUNKS \
((1 << XSUM_HIGH_EXP_BITS) + 3) /* # of chunks in small accumulator */
#define XSUM_LOW_MANTISSA_BITS \
(1 << XSUM_LOW_EXP_BITS) /* Bits in low part of mantissa */
#define XSUM_HIGH_MANTISSA_BITS \
(XSUM_MANTISSA_BITS - XSUM_LOW_MANTISSA_BITS) /* Bits in high part */
#define XSUM_LOW_MANTISSA_MASK \
(((xsum_int)1 << XSUM_LOW_MANTISSA_BITS) - 1) /* Mask for low bits */
#define XSUM_SMALL_CARRY_BITS \
((XSUM_SCHUNK_BITS - 1) - XSUM_MANTISSA_BITS) /* Bits sums can carry into */
#define XSUM_SMALL_CARRY_TERMS \
((1 << XSUM_SMALL_CARRY_BITS) - 1) /* # terms can add before need prop. */
struct xsum_small_accumulator_t {
xsum_schunk chunk[XSUM_SCHUNKS]; /* Chunks making up small accumulator */
xsum_int Inf; /* If non-zero, +Inf, -Inf, or NaN */
xsum_int NaN; /* If non-zero, a NaN value with payload */
int adds_until_propagate; /* Number of remaining adds before carry */
};
typedef struct xsum_small_accumulator_t
xsum_small_accumulator; /* propagation must be done again */
/* CONSTANTS DEFINING THE LARGE ACCUMULATOR FORMAT. */
#define XSUM_LCHUNK_BITS 64 /* Bits in chunk of the large accumulator */
typedef uint64_t xsum_lchunk; /* Integer type of large accumulator chunk,
must be EXACTLY 64 bits in size */
#define XSUM_LCOUNT_BITS (64 - XSUM_MANTISSA_BITS) /* # of bits in count */
typedef int_least16_t xsum_lcount; /* Signed int type of counts for large acc.*/
#define XSUM_LCHUNKS \
(1 << (XSUM_EXP_BITS + 1)) /* # of chunks in large accumulator */
typedef uint_fast64_t xsum_used; /* Unsigned type for holding used flags */
struct xsum_large_accumulator_t {
xsum_lchunk chunk[XSUM_LCHUNKS]; /* Chunks making up large accumulator */
xsum_lcount count[XSUM_LCHUNKS]; /* Counts of # adds remaining for chunks,
or -1 if not used yet or special. */
xsum_used chunks_used[XSUM_LCHUNKS / 64]; /* Bits indicate chunks in use */
xsum_used used_used; /* Bits indicate chunk_used entries not 0 */
xsum_small_accumulator sacc; /* The small accumulator to condense into */
};
typedef struct xsum_large_accumulator_t xsum_large_accumulator;
/* TYPE FOR LENGTHS OF ARRAYS. Must be a signed integer type. */
typedef int xsum_length;
/* FUNCTIONS FOR EXACT SUMMATION. */
void xsum_small_init(xsum_small_accumulator *restrict);
void xsum_small_add1(xsum_small_accumulator *restrict, xsum_flt);
void xsum_small_addv(xsum_small_accumulator *restrict, const xsum_flt *restrict,
xsum_length);
void xsum_small_add_sqnorm(xsum_small_accumulator *restrict,
const xsum_flt *restrict, xsum_length);
void xsum_small_add_dot(xsum_small_accumulator *restrict, const xsum_flt *,
const xsum_flt *, xsum_length);
xsum_flt xsum_small_round(xsum_small_accumulator *restrict);
void xsum_small_display(xsum_small_accumulator *restrict);
int xsum_small_chunks_used(xsum_small_accumulator *restrict);
void xsum_large_init(xsum_large_accumulator *restrict);
void xsum_large_addv(xsum_large_accumulator *restrict, const xsum_flt *restrict,
xsum_length);
void xsum_large_add_sqnorm(xsum_large_accumulator *restrict,
const xsum_flt *restrict, xsum_length);
void xsum_large_add_dot(xsum_large_accumulator *restrict, const xsum_flt *,
const xsum_flt *, xsum_length);
xsum_flt xsum_large_round(xsum_large_accumulator *restrict);
void xsum_large_display(xsum_large_accumulator *restrict);
int xsum_large_chunks_used(xsum_large_accumulator *restrict);
/* FUNCTIONS FOR DOUBLE AND OTHER INEXACT SUMMATION. */
xsum_flt xsum_sum_double(const xsum_flt *restrict, xsum_length);
xsum_flt xsum_sum_double_not_ordered(const xsum_flt *restrict, xsum_length);
xsum_flt xsum_sum_float128(const xsum_flt *restrict, xsum_length);
xsum_flt xsum_sum_kahan(const xsum_flt *restrict, xsum_length);
xsum_flt xsum_sqnorm_double(const xsum_flt *restrict, xsum_length);
xsum_flt xsum_sqnorm_double_not_ordered(const xsum_flt *restrict, xsum_length);
xsum_flt xsum_dot_double(const xsum_flt *, const xsum_flt *, xsum_length);
xsum_flt xsum_dot_double_not_ordered(const xsum_flt *, const xsum_flt *,
xsum_length);
/* DEBUG FLAG. Set to non-zero for debug ouptut. Ignored unless xsum.c
is compiled with -DDEBUG. */
extern int xsum_debug;
/* EXTRA ADDNUMBER FUNCTION for large accumulator */
void xsum_large_add1(xsum_large_accumulator *restrict, xsum_flt);
/* ADD A SMALL ACCUMULATOR TO ANOTHER SMALL ACCUMULATOR. */
void xsum_small_add_acc(xsum_small_accumulator *restrict sacc,
xsum_small_accumulator *restrict sacc_to_add);
void xsum_small_subtract_acc_and_set(
xsum_small_accumulator *restrict sacc,
xsum_small_accumulator *restrict sacc_to_subtract,
xsum_small_accumulator *restrict sacc_to_assign);
/* ASSIGN A SMALL ACCUMULATOR TO ANOTHER SMALL ACCUMULATOR */
void xsum_small_equal(xsum_small_accumulator *restrict sacc,
xsum_small_accumulator *restrict sacc_to_assign);
/* ASSIGNS THE ACCUMULATOR DIFFERENCE TO A THIRD ACCUMULATOR SET TO ZERO */
#endif