Report a bug
If you spot a problem with this page, click here to create a Github issue.
Improve this page
Quickly fork, edit online, and submit a pull request for this page. Requires a signed-in GitHub account. This works well for small changes. If you'd like to make larger changes you may want to consider using a local clone.

mir.math.numeric

This module contains simple numeric algorithms.
Authors:
Ilya Yaroshenko

Sponsors This work has been sponsored by and Kaleidic Associates.

struct Prod(T) if (isFloatingPoint!T);
long exp;
T x;
alias mantissa = x;
this(T value);
this(long exp, T x);
void put(T e);
void put(Prod p);
const @property scope T value();
const Prod opUnary(string op : "-")();
const Prod opUnary(string op : "+")();
Prod!(Unqual!(DeepElementType!Range)) wipProd(Range)(Range r)
if (isInputRange!Range && isFloatingPoint!(DeepElementType!Range));
Decompose a range or nd-slice of floating point numbers into a single product structure.
Prod!T wipProd(T)(const T x)
if (isFloatingPoint!T);
Decompose a single floating point number.
Unqual!(DeepElementType!Range) prod(Range)(Range r, ref long exp)
if (isInputRange!Range && isFloatingPoint!(DeepElementType!Range));

Unqual!(DeepElementType!Range) prod(Range)(Range r)
if (isInputRange!Range && isFloatingPoint!(DeepElementType!Range));
Compute the product of the input range r using separate exponent accumulation.
Examples:
Arrays and Ranges
enum l = 2.0 ^^ (double.max_exp - 1);
enum s = 2.0 ^^ -(double.max_exp - 1);
auto r = [l, l, l, s, s, s, 0.8 * 2.0 ^^ 10];
long e;
assert(r.prod(e) == 0.8);
assert(e == 10);
assert(r.prod == 0.8 * 2.0 ^^ 10);
Examples:
Ndslices
import mir.math.numeric: prod;
import mir.ndslice.slice: sliced;
import mir.algorithm.iteration: reduce;

enum l = 2.0 ^^ (double.max_exp - 1);
enum s = 2.0 ^^ -(double.max_exp - 1);
auto c = 0.8;
auto u = c * 2.0 ^^ 10;
auto r = [l, l, l,
          s, s, s,
          u, u, u].sliced(3, 3);
long e;
assert(r.prod(e) == reduce!"a * b"(1.0, [c, c, c]));
assert(e == 30);
assert(r.prod == reduce!"a * b"(1.0, [u, u, u]));
Unqual!(DeepElementType!Range) sumOfLog2s(Range)(Range r)
if (isFloatingPoint!(DeepElementType!Range));
Compute the sum of binary logarithms of the input range r. The error of this method is much smaller than with a naive sum of log2.
Examples:
alias isNaN = x => x != x;

assert(sumOfLog2s(new double[0]) == 0);
assert(sumOfLog2s([0.0L]) == -real.infinity);
assert(sumOfLog2s([-0.0L]) == -real.infinity);
assert(sumOfLog2s([2.0L]) == 1);
assert(isNaN(sumOfLog2s([-2.0L])));
assert(isNaN(sumOfLog2s([real.nan])));
assert(isNaN(sumOfLog2s([-real.nan])));
assert(sumOfLog2s([real.infinity]) == real.infinity);
assert(isNaN(sumOfLog2s([-real.infinity])));
assert(sumOfLog2s([ 0.25, 0.25, 0.25, 0.125 ]) == -9);