treams_core/special/integrals/
double.rs1use crate::Complex;
8
9#[derive(Clone, Copy, Debug)]
11struct Double {
12 hi: f64,
13 lo: f64,
14}
15
16impl Double {
17 fn normalized(hi: f64, lo: f64) -> Self {
19 let sum = hi + lo;
20 Self {
21 hi: sum,
22 lo: lo - (sum - hi),
23 }
24 }
25
26 fn product(a: f64, b: f64) -> Self {
28 let hi = a * b;
29 Self {
30 hi,
31 lo: a.mul_add(b, -hi),
32 }
33 }
34
35 fn sum(a: f64, b: f64) -> Self {
37 let hi = a + b;
38 let b_part = hi - a;
39 Self {
40 hi,
41 lo: (a - (hi - b_part)) + (b - b_part),
42 }
43 }
44
45 fn divide(self, divisor: Self) -> Self {
47 let quotient = self.hi / divisor.hi;
48 let remainder = self - Self::from(quotient) * divisor;
49 Self::normalized(quotient, remainder.hi / divisor.hi)
50 }
51}
52
53impl From<f64> for Double {
54 fn from(hi: f64) -> Self {
55 Self { hi, lo: 0.0 }
56 }
57}
58
59impl std::ops::Add for Double {
60 type Output = Self;
61 fn add(self, other: Self) -> Self {
62 let sum = Self::sum(self.hi, other.hi);
63 Self::normalized(sum.hi, sum.lo + self.lo + other.lo)
64 }
65}
66
67impl std::ops::Neg for Double {
68 type Output = Self;
69 fn neg(self) -> Self {
70 Self {
71 hi: -self.hi,
72 lo: -self.lo,
73 }
74 }
75}
76
77impl std::ops::Sub for Double {
78 type Output = Self;
79 fn sub(self, other: Self) -> Self {
80 self + -other
81 }
82}
83
84impl std::ops::Mul for Double {
85 type Output = Self;
86 fn mul(self, other: Self) -> Self {
87 let product = Self::product(self.hi, other.hi);
88 let lo = self
89 .hi
90 .mul_add(other.lo, self.lo.mul_add(other.hi, product.lo));
91 Self::normalized(product.hi, lo)
92 }
93}
94
95#[derive(Clone, Copy, Debug)]
97pub(super) struct DoubleComplex {
98 re: Double,
99 im: Double,
100}
101
102impl DoubleComplex {
103 pub(super) fn half_inverse_square(eta: Complex) -> Self {
105 let (re, im) = (Double::from(eta.re), Double::from(eta.im));
106 let (u, v) = (re * re - im * im, Double::from(2.0) * re * im);
108 let scale = Double::from(2.0) * (u * u + v * v);
109 Self {
110 re: u.divide(scale),
111 im: (-v).divide(scale),
112 }
113 }
114
115 pub(super) fn divide(self, divisor: f64) -> Self {
117 Self {
118 re: self.re.divide(Double::from(divisor)),
119 im: self.im.divide(Double::from(divisor)),
120 }
121 }
122
123 pub(super) fn rounded(self) -> Complex {
125 Complex::new(self.re.hi, self.im.hi)
126 }
127}
128
129impl From<Complex> for DoubleComplex {
130 fn from(value: Complex) -> Self {
131 Self {
132 re: Double::from(value.re),
133 im: Double::from(value.im),
134 }
135 }
136}
137
138impl std::ops::Mul for DoubleComplex {
139 type Output = Self;
140 fn mul(self, other: Self) -> Self {
141 Self {
142 re: self.re * other.re - self.im * other.im,
143 im: self.re * other.im + self.im * other.re,
144 }
145 }
146}