1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
//! Double-double, quad-double and octo-double floating-point arithmetic, scalar and on 8-lane SIMD vectors.
//!
//! A double-double is an unevaluated sum `hi + lo` of two `f64` (about 32 significant digits); a quad-double is a sum
//! of four (about 64 digits), an octo-double of eight (about 126 digits). The lane types run the same algorithms on 8
//! values at once, with **bitwise the same results per lane** as the scalar types, on every backend:
//!
//! * [`v8::V8`]: 8 `f64` in one AVX-512 register, two AVX2 registers, four SSE2 or four NEON registers, or a plain
//! array (the cargo feature `portable` forces it), with fused multiply-add throughout.
//! * [`simd`]: the backends behind `V8`. [`simd::dispatch`] runs code written once over the backend on the best one
//! the CPU has, detected at run time; [`native`] has the lane types on the backend the build's target features
//! select at compile time.
//! * [`dd::DD`] scalar and [`dv::DV`] 8-lane double-double; [`dv::DotAcc`] a sum-of-products accumulator.
//! * [`qd::QD`] scalar and [`qv::QV`] 8-lane quad-double (the algorithms of Hida, Li and Bailey's QD library, with two
//! repairs found by this crate's tests), exact decimal parsing and printing;
//! [`qd::QdAcc`] and [`qv::QDotAcc`] accumulators.
//! * [`od::OD`] scalar and [`ov::OV`] 8-lane octo-double (QD's algorithms carried to eight parts, written once for
//! both), with [`od::OdAcc`] and [`ov::ODotAcc`] accumulators; `OV` is a [`dual::Lane`].
//! * [`exact`]: exact dyadic and decimal arithmetic, the reference the tests compare against.
//! * [`dual`]: forward-mode dual numbers over these lanes ([`dual::Du`] double-double value and tangent,
//! [`dual::Dtn`] a double-double value with N f64 tangents, [`dual::Qu`] quad-double value and tangent,
//! [`dual::Ou`] octo-double value and tangent, [`dual::Dc`] a double-double value with a complex tangent, and f64
//! variants), behind the [`dual::Lane`] trait, so one generic code gives values and exact derivatives;
//! [`dual::Counted`] counts the operations of such code.
//! * [`jet`]: truncated power series over these lanes, in double-double ([`jet::Jet`]), quad-double ([`jet::QJet`])
//! and octo-double ([`jet::OJet`]), with their scalar parameter arithmetic ([`jet::Series`], [`jet::QSeries`],
//! [`jet::OSeries`]): one generic code gives its own Taylor coefficients in a parameter.
//! * [`field`]: 8 B values of a lane type as B lane vectors ([`field::Fl`]), with Cauchy products, Horner evaluation
//! a constant double-double matrix applied to them ([`field::DMat`]), solves with a `DDLu`, refined in the lane
//! type ([`field::FieldSolve`]), and an early end of a series for the tangents ([`field::TangentTail`]): the
//! arithmetic of power-series methods.
//! * [`linalg`]: dense LU with partial pivoting in double-double (and blocked in f64 for mixed precision) and in
//! quad-double ([`linalg::QDLu`], for systems too ill-conditioned for double-double) and in octo-double
//! ([`linalg::ODLu`], for those too ill-conditioned for quad-double), solves,
//! transpose solves, solves refined to quad-double and Gram matrices, and the determinant of a complex matrix
//! ([`linalg::clu_logdet`]); [`linalg::lu_rect_f64`], the f64 LU of the
//! first columns of a rectangular block (the step of a block LU), and [`linalg::StaircaseLu`], the LU of a staircase
//! system with one global parameter (the Newton system of multiple shooting) built from those steps.
//!
//! All operations are IEEE round-to-nearest with no reassociation, which the error-free transformations need.
//!
//! The cargo feature `f128` adds conversions between `f128` and [`dd::DD`] and [`qd::QD`]. It needs a nightly
//! compiler, as `f128` is unstable.
//!
//! ```
//! use multidouble::dd::DD;
//! use multidouble::qd::QD;
//!
//! let third = DD::from_f64(1.0) / DD::from_f64(3.0);
//! assert!(((third * DD::from_f64(3.0)) - DD::from_f64(1.0)).to_f64().abs() < 1e-31);
//!
//! let x: QD = "1.41421356237309504880168872420969807856967187537694807317667973799".parse().unwrap();
//! assert!((x * x - QD::from_f64(2.0)).to_f64().abs() < 1e-62);
//! ```
// Numerical kernels index several arrays with one loop variable, and the lane and accumulator types keep inherent
// add/sub/mul/div methods (the std::ops traits are implemented where they apply).
/// The lane types on the compile-time backend [`simd::Native`], for code that does not dispatch.
/// The README's examples, compiled and run as doctests.
;