Multiplies a DDValue by a regular f64 (Value) using similar techniques as dd_mul. It multiplies both the high and low parts by b, computes the rounding error, and then renormalizes the result.
(&mut self, a: DDValue, b: Value)
| 931 | /// It multiplies both the high and low parts by b, computes the rounding error, |
| 932 | /// and then renormalizes the result. |
| 933 | fn dd_mul_f64(&mut self, a: DDValue, b: Value) -> DDValue { |
| 934 | // p = a.hi * b (primary product) |
| 935 | let p = self.builder.ins().fmul(a.hi, b); |
| 936 | // Compute the rounding error using fma. |
| 937 | let zero = self.builder.ins().f64const(0.0); |
| 938 | let neg_p = self.builder.ins().fsub(zero, p); |
| 939 | let err = self.builder.ins().fma(a.hi, b, neg_p); |
| 940 | // Multiply the low part. |
| 941 | let cross = self.builder.ins().fmul(a.lo, b); |
| 942 | // Sum the primary product and the low multiplication. |
| 943 | let s = self.builder.ins().fadd(p, cross); |
| 944 | // Capture rounding error from addition. |
| 945 | let t = self.builder.ins().fsub(s, p); |
| 946 | let s_minus_t = self.builder.ins().fsub(s, t); |
| 947 | let part1 = self.builder.ins().fsub(p, s_minus_t); |
| 948 | let part2 = self.builder.ins().fsub(cross, t); |
| 949 | let e = self.builder.ins().fadd(part1, part2); |
| 950 | // Combine the error components. |
| 951 | let lo_sum = self.builder.ins().fadd(err, e); |
| 952 | // Renormalize to form the final double–double number. |
| 953 | let hi_new = self.builder.ins().fadd(s, lo_sum); |
| 954 | let hi_new_minus_s = self.builder.ins().fsub(hi_new, s); |
| 955 | let lo_new = self.builder.ins().fsub(lo_sum, hi_new_minus_s); |
| 956 | DDValue { |
| 957 | hi: hi_new, |
| 958 | lo: lo_new, |
| 959 | } |
| 960 | } |
| 961 | |
| 962 | /// Scales a DDValue by multiplying both its high and low parts by the given factor. |
| 963 | fn dd_scale(&mut self, dd: DDValue, factor: Value) -> DDValue { |
no test coverage detected