Loading...
Searching...
No Matches
eonc::exact Namespace Reference

Functions

double dot (const double *x, const double *y, std::size_t n)
 Round-to-nearest-even value of the exact sum of x[i] * y[i].
double orderedDot (const double *x, const double *y, std::size_t n)
 A fixed summation tree: four lanes (term i goes to lane i mod 4, each lane a left-to-right sum of rounded products), then (l0 + l1) + (l2 + l3).
double sum (const double *x, std::size_t n)
 Round-to-nearest-even value of the exact sum of x[i].
double sumStrided (const double *x, std::size_t n, std::size_t stride)
 Same sum for x[i * stride].
template<typename A, typename B>
double dot (const Eigen::MatrixBase< A > &x, const Eigen::MatrixBase< B > &y)
template<typename A, typename B>
double orderedDot (const Eigen::MatrixBase< A > &x, const Eigen::MatrixBase< B > &y)
template<typename A>
double squaredNorm (const Eigen::MatrixBase< A > &x)
template<typename A>
double norm (const Eigen::MatrixBase< A > &x)
 sqrt of the correctly rounded squared norm; IEEE sqrt is itself correctly rounded, so this is reproducible as well.
template<typename A>
double orderedNorm (const Eigen::MatrixBase< A > &x)
 sqrt of orderedDot(x, x): reproducible, not correctly rounded.
template<typename A>
A::PlainObject normalized (const Eigen::MatrixBase< A > &x, double min_norm=1e-300)
 x / norm(x), or zero below min_norm (the safemath convention).

Variables

constexpr std::size_t kLanes = 4

Function Documentation

◆ dot() [1/2]

double eonc::exact::dot ( const double * x,
const double * y,
std::size_t n )
nodiscard

Round-to-nearest-even value of the exact sum of x[i] * y[i].

An exact zero returns +0. A non-finite input returns the plain IEEE sum, so NaN and infinity propagate as they would without this function.

Definition at line 451 of file ExactReduction.cpp.

451 {
452 double certified;
453 if (certifiedDot(x, y, n, certified)) {
454 return certified;
455 }
456 std::array<Accumulator, kLanes> acc;
457 for (std::size_t i = 0; i < n; ++i) {
458 Decoded a;
459 Decoded b;
460 if (!decode(x[i], a) || !decode(y[i], b)) [[unlikely]] {
461 double plain = 0.0;
462 for (std::size_t j = 0; j < n; ++j) {
463 plain += x[j] * y[j];
464 }
465 return plain;
466 }
467 uint64_t hi;
468 uint64_t lo;
469 mul64(a.m, b.m, hi, lo);
470 acc[i % kLanes].add(hi, lo, a.e + b.e, a.neg != b.neg);
471 if ((i + 1) % kNormalizeEvery == 0) [[unlikely]] {
472 for (auto &lane : acc) {
473 lane.fold();
474 }
475 }
476 }
477 for (std::size_t k = 1; k < kLanes; ++k) {
478 acc[0].absorb(acc[k]);
479 }
480 return acc[0].round();
481}
constexpr std::size_t kLanes

◆ dot() [2/2]

template<typename A, typename B>
double eonc::exact::dot ( const Eigen::MatrixBase< A > & x,
const Eigen::MatrixBase< B > & y )
nodiscard

Definition at line 67 of file ExactReduction.h.

68 {
69 eigen_assert(x.size() == y.size());
70 const auto &xe = x.derived().eval();
71 const auto &ye = y.derived().eval();
72 return dot(xe.data(), ye.data(), static_cast<std::size_t>(xe.size()));
73}
double dot(const double *x, const double *y, std::size_t n)
Round-to-nearest-even value of the exact sum of x[i] * y[i].

◆ norm()

template<typename A>
double eonc::exact::norm ( const Eigen::MatrixBase< A > & x)
nodiscard

sqrt of the correctly rounded squared norm; IEEE sqrt is itself correctly rounded, so this is reproducible as well.

Definition at line 92 of file ExactReduction.h.

92 {
93 return std::sqrt(squaredNorm(x));
94}
double squaredNorm(const Eigen::MatrixBase< A > &x)

◆ normalized()

template<typename A>
A::PlainObject eonc::exact::normalized ( const Eigen::MatrixBase< A > & x,
double min_norm = 1e-300 )
nodiscard

x / norm(x), or zero below min_norm (the safemath convention).

Definition at line 106 of file ExactReduction.h.

107 {
108 const double n = norm(x);
109 if (n < min_norm) [[unlikely]] {
110 return A::PlainObject::Zero(x.rows(), x.cols());
111 }
112 return (x / n).eval();
113}
double norm(const Eigen::MatrixBase< A > &x)
sqrt of the correctly rounded squared norm; IEEE sqrt is itself correctly rounded,...

◆ orderedDot() [1/2]

double eonc::exact::orderedDot ( const double * x,
const double * y,
std::size_t n )
nodiscard

A fixed summation tree: four lanes (term i goes to lane i mod 4, each lane a left-to-right sum of rounded products), then (l0 + l1) + (l2 + l3).

Not exact, but every operation is a single IEEE multiply or add in an order this translation unit fixes (it is compiled without contraction), so the bits match on every compiler, Eigen release and CPU. For bulk products that set a vector, not a branch.

Definition at line 483 of file ExactReduction.cpp.

483 {
484 double l0 = 0.0;
485 double l1 = 0.0;
486 double l2 = 0.0;
487 double l3 = 0.0;
488 std::size_t i = 0;
489 for (; i + 4 <= n; i += 4) {
490 const double p0 = x[i] * y[i];
491 const double p1 = x[i + 1] * y[i + 1];
492 const double p2 = x[i + 2] * y[i + 2];
493 const double p3 = x[i + 3] * y[i + 3];
494 l0 += p0;
495 l1 += p1;
496 l2 += p2;
497 l3 += p3;
498 }
499 if (i < n) {
500 const double p = x[i] * y[i];
501 l0 += p;
502 }
503 if (i + 1 < n) {
504 const double p = x[i + 1] * y[i + 1];
505 l1 += p;
506 }
507 if (i + 2 < n) {
508 const double p = x[i + 2] * y[i + 2];
509 l2 += p;
510 }
511 return (l0 + l1) + (l2 + l3);
512}

◆ orderedDot() [2/2]

template<typename A, typename B>
double eonc::exact::orderedDot ( const Eigen::MatrixBase< A > & x,
const Eigen::MatrixBase< B > & y )
nodiscard

Definition at line 76 of file ExactReduction.h.

77 {
78 eigen_assert(x.size() == y.size());
79 const auto &xe = x.derived().eval();
80 const auto &ye = y.derived().eval();
81 return orderedDot(xe.data(), ye.data(), static_cast<std::size_t>(xe.size()));
82}
double orderedDot(const double *x, const double *y, std::size_t n)
A fixed summation tree: four lanes (term i goes to lane i mod 4, each lane a left-to-right sum of rou...

◆ orderedNorm()

template<typename A>
double eonc::exact::orderedNorm ( const Eigen::MatrixBase< A > & x)
nodiscard

sqrt of orderedDot(x, x): reproducible, not correctly rounded.

For the per-atom lengths of a step, where an exact sum per atom costs more than the step.

Definition at line 100 of file ExactReduction.h.

100 {
101 return std::sqrt(orderedDot(x, x));
102}

◆ squaredNorm()

template<typename A>
double eonc::exact::squaredNorm ( const Eigen::MatrixBase< A > & x)
nodiscard

Definition at line 85 of file ExactReduction.h.

85 {
86 const auto &xe = x.derived().eval();
87 return dot(xe.data(), xe.data(), static_cast<std::size_t>(xe.size()));
88}

◆ sum()

double eonc::exact::sum ( const double * x,
std::size_t n )
nodiscard

Round-to-nearest-even value of the exact sum of x[i].

Definition at line 514 of file ExactReduction.cpp.

514{ return sumStrided(x, n, 1); }
double sumStrided(const double *x, std::size_t n, std::size_t stride)
Same sum for x[i * stride].

◆ sumStrided()

double eonc::exact::sumStrided ( const double * x,
std::size_t n,
std::size_t stride )
nodiscard

Same sum for x[i * stride].

A row-major atom matrix stores one column this way. stride 1 is sum().

Definition at line 516 of file ExactReduction.cpp.

516 {
517 Accumulator acc;
518 for (std::size_t i = 0; i < n; ++i) {
519 Decoded a;
520 if (!decode(x[i * stride], a)) [[unlikely]] {
521 double plain = 0.0;
522 for (std::size_t j = 0; j < n; ++j) {
523 plain += x[j * stride];
524 }
525 return plain;
526 }
527 acc.add(0, a.m, a.e, a.neg);
528 if ((i + 1) % kNormalizeEvery == 0) [[unlikely]] {
529 acc.fold();
530 }
531 }
532 return acc.round();
533}

Variable Documentation

◆ kLanes

std::size_t eonc::exact::kLanes = 4
constexpr

Definition at line 278 of file ExactReduction.cpp.