# Crate accurate [−] [src]

A collection of (more or less) accurate floating point algorithms

This crate implements several algorithms for floating point summation and dot product. The algorithms are realized as types that implement the `SumAccumulator` and `DotAccumulator` trait.

# Basic usage

Calculating a sum (or a dot product) begins by initializing an accumulator to zero:

``` use accurate::traits::*; // Most functionality is derived from traits in this module
use accurate::sum::NaiveSum; // Chose a specific algorithm to perform summation / dot product

let s = NaiveSum::<f32>::zero();```

The accumulator traits are generic over the type of the underlying floating point numbers and the `zero()` constructor is supported if the number type implements the Zero trait. Alternatively the accumulator traits imply that an accumulator can be constructed `from()` an arbitrary value of the number type.

` let s = NaiveSum::from(42.0f64);`

The actual calculation is performed via the `Add<F, Output = Self>` trait that is also implied by the `SumAccumulator` trait, where `F` is the type of the floating point numbers.

``` use accurate::sum::Sum2;

let s = Sum2::zero() + 1.0f64 + 2.0 + 3.0;```

For dot products, the `DotAccumulator` trait implies `Add<(F, F), Output = Self>` to allow accumulation of the products of pairs into the final result.

``` use accurate::dot::NaiveDot;

let d = NaiveDot::zero() + (1.0f64, 1.0f64) + (2.0, 2.0) + (3.0, 3.0);```

Once all of the terms have been accumulated, the result can be evaluated using the `sum()` and `dot()` methods respectively.

``` let s = Sum2::zero() + 1.0f64 + 2.0 + 3.0;
assert_eq!(6.0, s.sum());

let d = NaiveDot::zero() + (1.0f64, 1.0f64) + (2.0, 2.0) + (3.0, 3.0);
assert_eq!(14.0, d.dot());```

Both `sum()` and `dot()` take their argument by value, because the evaluation of the final result is in some cases a destructive operation on the internal state of the accumulator. However, the evaluation of partial results is supported by `clone()`ing the accumulator.

``` let s = Sum2::zero() + 1.0f32 + 2.0;
assert_eq!(3.0, s.clone().sum());
let s = s + 3.0;
assert_eq!(6.0, s.sum());```

# Iterator consumption

Accumulators can be used in `fold()` operations on iterators as one would expect.

``` use accurate::dot::Dot2;

let s = vec![1.0f32, 2.0, 3.0].into_iter().fold(Sum2::zero(), |acc, x| acc + x);
assert_eq!(6.0, s.sum());

let d = vec![1.0f32, 2.0, 3.0].into_iter()
.zip(vec![1.0, 2.0, 3.0].into_iter())
.fold(Dot2::zero(), |acc, xy| acc + xy);
assert_eq!(14.0, d.dot());```

For convenience, the accumulator traits also define `absorb()` methods to absorb values from anything that implements `IntoIterator`.

```
let s = Sum2::zero().absorb(vec![1.0f32, 2.0, 3.0]);
assert_eq!(6.0, s.sum());

let d = Dot2::zero().absorb(vec![(1.0f32, 1.0), (2.0, 2.0), (3.0, 3.0)]);
assert_eq!(14.0, d.dot());```

And for even more convenience, suitable iterators are extended by a `sum_with_accumulator()` (and `dot_with_accumulator()`) method that directly evaluates to the result in the floating point number type.

```
let s = Sum2::zero().absorb(vec![1.0f32, 2.0, 3.0]);
assert_eq!(6.0f64, vec![1.0, 2.0, 3.0].into_iter().sum_with_accumulator::<Sum2<_>>());

assert_eq!(14.0f64, vec![(1.0, 1.0), (2.0, 2.0), (3.0, 3.0)].into_iter()
.dot_with_accumulator::<Dot2<_>>());```

# Parallel computation

If compiled with the `parallel` feature enabled (which is the default) the `rayon` parallel iterator facilities are used to perform large calculations in parallel. Parallel calculations are performed through the `parallel_sum_with_accumulator()` and `parallel_dot_with_accumulator()` extension methods on parallel iterators.

```extern crate rayon;

use rayon::prelude::*;

let xs = vec![1.0f64; 100_000];
let s = xs.par_iter().map(|&x| x).parallel_sum_with_accumulator::<Sum2<_>>();
assert_eq!(100_000.0, s);```

## Modules

 dot Algorithms for dot product sum Algorithms for summation traits Includes all traits of this crate util Common infrastructure