Coverage Report

Created: 2026-09-02 07:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/pxfm-0.1.30/src/polyeval.rs
Line
Count
Source
1
/*
2
 * // Copyright (c) Radzivon Bartoshyk 7/2025. All rights reserved.
3
 * //
4
 * // Redistribution and use in source and binary forms, with or without modification,
5
 * // are permitted provided that the following conditions are met:
6
 * //
7
 * // 1.  Redistributions of source code must retain the above copyright notice, this
8
 * // list of conditions and the following disclaimer.
9
 * //
10
 * // 2.  Redistributions in binary form must reproduce the above copyright notice,
11
 * // this list of conditions and the following disclaimer in the documentation
12
 * // and/or other materials provided with the distribution.
13
 * //
14
 * // 3.  Neither the name of the copyright holder nor the names of its
15
 * // contributors may be used to endorse or promote products derived from
16
 * // this software without specific prior written permission.
17
 * //
18
 * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
 * // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
 * // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
 * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22
 * // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
 * // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24
 * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25
 * // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26
 * // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27
 * // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
 */
29
use crate::common::{f_fmla, f_fmlaf};
30
use crate::double_double::DoubleDouble;
31
use crate::dyadic_float::DyadicFloat128;
32
use std::ops::Mul;
33
34
pub(crate) trait PolyevalMla {
35
    fn polyeval_mla(a: Self, b: Self, c: Self) -> Self;
36
}
37
38
impl PolyevalMla for f64 {
39
    #[inline(always)]
40
0
    fn polyeval_mla(a: Self, b: Self, c: Self) -> Self {
41
0
        f_fmla(a, b, c)
42
0
    }
43
}
44
45
impl PolyevalMla for f32 {
46
    #[inline(always)]
47
0
    fn polyeval_mla(a: Self, b: Self, c: Self) -> Self {
48
0
        f_fmlaf(a, b, c)
49
0
    }
50
}
51
52
impl PolyevalMla for DoubleDouble {
53
    #[inline(always)]
54
0
    fn polyeval_mla(a: Self, b: Self, c: Self) -> Self {
55
0
        DoubleDouble::mul_add(a, b, c)
56
0
    }
57
}
58
59
impl PolyevalMla for DyadicFloat128 {
60
    #[inline(always)]
61
0
    fn polyeval_mla(a: Self, b: Self, c: Self) -> Self {
62
0
        c.quick_add(&a.quick_mul(&b))
63
0
    }
64
}
65
66
// impl PolyevalMla for DyadicFloat256 {
67
//     #[inline(always)]
68
//     fn polyeval_mla(a: Self, b: Self, c: Self) -> Self {
69
//         c.quick_add(&a.quick_mul(&b))
70
//     }
71
// }
72
73
#[inline(always)]
74
#[allow(clippy::too_many_arguments)]
75
0
pub(crate) fn f_polyeval6<T: PolyevalMla + Copy + Mul<T, Output = T>>(
76
0
    x: T,
77
0
    a0: T,
78
0
    a1: T,
79
0
    a2: T,
80
0
    a3: T,
81
0
    a4: T,
82
0
    a5: T,
83
0
) -> T {
84
0
    let x2 = x * x;
85
86
0
    let u0 = T::polyeval_mla(x, a5, a4);
87
0
    let u1 = T::polyeval_mla(x, a3, a2);
88
0
    let u2 = T::polyeval_mla(x, a1, a0);
89
90
0
    let v0 = T::polyeval_mla(x2, u0, u1);
91
92
0
    T::polyeval_mla(x2, v0, u2)
93
0
}
94
95
#[inline(always)]
96
#[allow(clippy::too_many_arguments)]
97
0
pub(crate) fn dd_quick_polyeval6(
98
0
    x: DoubleDouble,
99
0
    a0: DoubleDouble,
100
0
    a1: DoubleDouble,
101
0
    a2: DoubleDouble,
102
0
    a3: DoubleDouble,
103
0
    a4: DoubleDouble,
104
0
    a5: DoubleDouble,
105
0
) -> DoubleDouble {
106
0
    let x2 = DoubleDouble::quick_mult(x, x);
107
108
0
    let u0 = DoubleDouble::quick_mul_add(x, a5, a4);
109
0
    let u1 = DoubleDouble::quick_mul_add(x, a3, a2);
110
0
    let u2 = DoubleDouble::quick_mul_add(x, a1, a0);
111
112
0
    let v0 = DoubleDouble::quick_mul_add(x2, u0, u1);
113
114
0
    DoubleDouble::quick_mul_add(x2, v0, u2)
115
0
}
116
117
#[inline(always)]
118
#[allow(unused)]
119
#[allow(clippy::too_many_arguments)]
120
0
pub(crate) fn dd_quick_polyeval6_fma(
121
0
    x: DoubleDouble,
122
0
    a0: DoubleDouble,
123
0
    a1: DoubleDouble,
124
0
    a2: DoubleDouble,
125
0
    a3: DoubleDouble,
126
0
    a4: DoubleDouble,
127
0
    a5: DoubleDouble,
128
0
) -> DoubleDouble {
129
0
    let x2 = DoubleDouble::quick_mult_fma(x, x);
130
131
0
    let u0 = DoubleDouble::quick_mul_add_fma(x, a5, a4);
132
0
    let u1 = DoubleDouble::quick_mul_add_fma(x, a3, a2);
133
0
    let u2 = DoubleDouble::quick_mul_add_fma(x, a1, a0);
134
135
0
    let v0 = DoubleDouble::quick_mul_add_fma(x2, u0, u1);
136
137
0
    DoubleDouble::quick_mul_add_fma(x2, v0, u2)
138
0
}
139
140
#[inline(always)]
141
#[allow(unused)]
142
#[allow(clippy::too_many_arguments)]
143
0
pub(crate) fn d_polyeval6(x: f64, a0: f64, a1: f64, a2: f64, a3: f64, a4: f64, a5: f64) -> f64 {
144
0
    let x2 = x * x;
145
146
0
    let u0 = f64::mul_add(x, a5, a4);
147
0
    let u1 = f64::mul_add(x, a3, a2);
148
0
    let u2 = f64::mul_add(x, a1, a0);
149
150
0
    let v0 = f64::mul_add(x2, u0, u1);
151
152
0
    f64::mul_add(x2, v0, u2)
153
0
}
154
155
#[inline(always)]
156
#[allow(clippy::too_many_arguments)]
157
0
pub(crate) fn f_polyeval9<T: PolyevalMla + Copy + Mul<T, Output = T>>(
158
0
    x: T,
159
0
    a0: T,
160
0
    a1: T,
161
0
    a2: T,
162
0
    a3: T,
163
0
    a4: T,
164
0
    a5: T,
165
0
    a6: T,
166
0
    a7: T,
167
0
    a8: T,
168
0
) -> T {
169
0
    let mut acc = a8;
170
0
    acc = T::polyeval_mla(x, acc, a7);
171
0
    acc = T::polyeval_mla(x, acc, a6);
172
0
    acc = T::polyeval_mla(x, acc, a5);
173
0
    acc = T::polyeval_mla(x, acc, a4);
174
0
    acc = T::polyeval_mla(x, acc, a3);
175
0
    acc = T::polyeval_mla(x, acc, a2);
176
0
    acc = T::polyeval_mla(x, acc, a1);
177
0
    T::polyeval_mla(x, acc, a0)
178
0
}
179
180
#[inline(always)]
181
#[allow(clippy::too_many_arguments)]
182
0
pub(crate) fn f_estrin_polyeval9<T: PolyevalMla + Copy + Mul<T, Output = T>>(
183
0
    x: T,
184
0
    a0: T,
185
0
    a1: T,
186
0
    a2: T,
187
0
    a3: T,
188
0
    a4: T,
189
0
    a5: T,
190
0
    a6: T,
191
0
    a7: T,
192
0
    a8: T,
193
0
) -> T {
194
0
    let x2 = x * x;
195
0
    let x4 = x2 * x2;
196
0
    let x8 = x4 * x4;
197
0
    let p0 = T::polyeval_mla(x, a1, a0);
198
0
    let p1 = T::polyeval_mla(x, a3, a2);
199
0
    let p2 = T::polyeval_mla(x, a5, a4);
200
0
    let p3 = T::polyeval_mla(x, a7, a6);
201
202
0
    let q0 = T::polyeval_mla(x2, p1, p0);
203
0
    let q1 = T::polyeval_mla(x2, p3, p2);
204
0
    let r0 = T::polyeval_mla(x4, q1, q0);
205
0
    T::polyeval_mla(x8, a8, r0)
206
0
}
207
208
#[inline(always)]
209
#[allow(clippy::too_many_arguments)]
210
0
pub(crate) fn f_polyeval10<T: PolyevalMla + Copy + Mul<T, Output = T>>(
211
0
    x: T,
212
0
    a0: T,
213
0
    a1: T,
214
0
    a2: T,
215
0
    a3: T,
216
0
    a4: T,
217
0
    a5: T,
218
0
    a6: T,
219
0
    a7: T,
220
0
    a8: T,
221
0
    a9: T,
222
0
) -> T {
223
0
    let x2 = x * x;
224
0
    let x4 = x2 * x2;
225
0
    let x8 = x4 * x4;
226
227
0
    let p0 = T::polyeval_mla(x, a1, a0);
228
0
    let p1 = T::polyeval_mla(x, a3, a2);
229
0
    let p2 = T::polyeval_mla(x, a5, a4);
230
0
    let p3 = T::polyeval_mla(x, a7, a6);
231
0
    let p4 = T::polyeval_mla(x, a9, a8);
232
233
0
    let q0 = T::polyeval_mla(x2, p1, p0);
234
0
    let q1 = T::polyeval_mla(x2, p3, p2);
235
236
0
    let r0 = T::polyeval_mla(x4, q1, q0);
237
0
    T::polyeval_mla(x8, p4, r0)
238
0
}
Unexecuted instantiation: pxfm::polyeval::f_polyeval10::<f64>
Unexecuted instantiation: pxfm::polyeval::f_polyeval10::<pxfm::double_double::DoubleDouble>
239
240
#[inline(always)]
241
#[allow(clippy::too_many_arguments)]
242
0
pub(crate) fn dd_quick_polyeval10(
243
0
    x: DoubleDouble,
244
0
    a0: DoubleDouble,
245
0
    a1: DoubleDouble,
246
0
    a2: DoubleDouble,
247
0
    a3: DoubleDouble,
248
0
    a4: DoubleDouble,
249
0
    a5: DoubleDouble,
250
0
    a6: DoubleDouble,
251
0
    a7: DoubleDouble,
252
0
    a8: DoubleDouble,
253
0
    a9: DoubleDouble,
254
0
) -> DoubleDouble {
255
0
    let x2 = DoubleDouble::quick_mult(x, x);
256
0
    let x4 = DoubleDouble::quick_mult(x2, x2);
257
0
    let x8 = DoubleDouble::quick_mult(x4, x4);
258
259
0
    let p0 = DoubleDouble::quick_mul_add(x, a1, a0);
260
0
    let p1 = DoubleDouble::quick_mul_add(x, a3, a2);
261
0
    let p2 = DoubleDouble::quick_mul_add(x, a5, a4);
262
0
    let p3 = DoubleDouble::quick_mul_add(x, a7, a6);
263
0
    let p4 = DoubleDouble::quick_mul_add(x, a9, a8);
264
265
0
    let q0 = DoubleDouble::quick_mul_add(x2, p1, p0);
266
0
    let q1 = DoubleDouble::quick_mul_add(x2, p3, p2);
267
268
0
    let r0 = DoubleDouble::quick_mul_add(x4, q1, q0);
269
0
    DoubleDouble::quick_mul_add(x8, p4, r0)
270
0
}
271
272
#[inline(always)]
273
#[allow(unused)]
274
#[allow(clippy::too_many_arguments)]
275
0
pub(crate) fn dd_quick_polyeval10_fma(
276
0
    x: DoubleDouble,
277
0
    a0: DoubleDouble,
278
0
    a1: DoubleDouble,
279
0
    a2: DoubleDouble,
280
0
    a3: DoubleDouble,
281
0
    a4: DoubleDouble,
282
0
    a5: DoubleDouble,
283
0
    a6: DoubleDouble,
284
0
    a7: DoubleDouble,
285
0
    a8: DoubleDouble,
286
0
    a9: DoubleDouble,
287
0
) -> DoubleDouble {
288
0
    let x2 = DoubleDouble::quick_mult_fma(x, x);
289
0
    let x4 = DoubleDouble::quick_mult_fma(x2, x2);
290
0
    let x8 = DoubleDouble::quick_mult_fma(x4, x4);
291
292
0
    let p0 = DoubleDouble::quick_mul_add_fma(x, a1, a0);
293
0
    let p1 = DoubleDouble::quick_mul_add_fma(x, a3, a2);
294
0
    let p2 = DoubleDouble::quick_mul_add_fma(x, a5, a4);
295
0
    let p3 = DoubleDouble::quick_mul_add_fma(x, a7, a6);
296
0
    let p4 = DoubleDouble::quick_mul_add_fma(x, a9, a8);
297
298
0
    let q0 = DoubleDouble::quick_mul_add_fma(x2, p1, p0);
299
0
    let q1 = DoubleDouble::quick_mul_add_fma(x2, p3, p2);
300
301
0
    let r0 = DoubleDouble::quick_mul_add_fma(x4, q1, q0);
302
0
    DoubleDouble::quick_mul_add_fma(x8, p4, r0)
303
0
}
304
305
#[inline(always)]
306
#[allow(clippy::too_many_arguments)]
307
0
pub(crate) fn f_polyeval11<T: PolyevalMla + Copy + Mul<T, Output = T>>(
308
0
    x: T,
309
0
    a0: T,
310
0
    a1: T,
311
0
    a2: T,
312
0
    a3: T,
313
0
    a4: T,
314
0
    a5: T,
315
0
    a6: T,
316
0
    a7: T,
317
0
    a8: T,
318
0
    a9: T,
319
0
    a10: T,
320
0
) -> T {
321
0
    let x2 = x * x;
322
0
    let x4 = x2 * x2;
323
0
    let x8 = x4 * x4;
324
325
0
    let q0 = T::polyeval_mla(x, a1, a0);
326
0
    let q1 = T::polyeval_mla(x, a3, a2);
327
0
    let q2 = T::polyeval_mla(x, a5, a4);
328
0
    let q3 = T::polyeval_mla(x, a7, a6);
329
0
    let q4 = T::polyeval_mla(x, a9, a8);
330
331
0
    let r0 = T::polyeval_mla(x2, q1, q0);
332
0
    let r1 = T::polyeval_mla(x2, q3, q2);
333
334
0
    let s0 = T::polyeval_mla(x4, r1, r0);
335
0
    let s1 = T::polyeval_mla(x2, a10, q4);
336
0
    T::polyeval_mla(x8, s1, s0)
337
0
}
338
339
#[inline(always)]
340
0
pub(crate) fn f_polyeval3<T: PolyevalMla + Copy>(x: T, a0: T, a1: T, a2: T) -> T {
341
0
    T::polyeval_mla(x, T::polyeval_mla(x, a2, a1), a0)
342
0
}
343
344
#[inline(always)]
345
#[allow(unused)]
346
0
pub(crate) fn d_polyeval3(x: f64, a0: f64, a1: f64, a2: f64) -> f64 {
347
0
    f64::mul_add(x, f64::mul_add(x, a2, a1), a0)
348
0
}
349
350
#[inline(always)]
351
#[allow(clippy::too_many_arguments)]
352
0
pub(crate) fn f_polyeval4<T: PolyevalMla + Copy>(x: T, a0: T, a1: T, a2: T, a3: T) -> T {
353
0
    let t2 = T::polyeval_mla(x, a3, a2);
354
0
    let t5 = T::polyeval_mla(x, t2, a1);
355
0
    T::polyeval_mla(x, t5, a0)
356
0
}
Unexecuted instantiation: pxfm::polyeval::f_polyeval4::<f64>
Unexecuted instantiation: pxfm::polyeval::f_polyeval4::<pxfm::dyadic_float::DyadicFloat128>
357
358
#[inline(always)]
359
#[allow(unused)]
360
#[allow(clippy::too_many_arguments)]
361
0
pub(crate) fn d_polyeval4(x: f64, a0: f64, a1: f64, a2: f64, a3: f64) -> f64 {
362
0
    let t2 = f64::mul_add(x, a3, a2);
363
0
    let t5 = f64::mul_add(x, t2, a1);
364
0
    f64::mul_add(x, t5, a0)
365
0
}
366
367
#[inline(always)]
368
#[allow(clippy::too_many_arguments)]
369
0
pub(crate) fn f_estrin_polyeval4<T: PolyevalMla + Copy + Mul<T, Output = T>>(
370
0
    x: T,
371
0
    a0: T,
372
0
    a1: T,
373
0
    a2: T,
374
0
    a3: T,
375
0
) -> T {
376
0
    let x2 = x * x;
377
378
0
    let p01 = T::polyeval_mla(x, a1, a0);
379
0
    let p23 = T::polyeval_mla(x, a3, a2);
380
381
0
    T::polyeval_mla(x2, p23, p01)
382
0
}
383
384
#[inline(always)]
385
#[allow(clippy::too_many_arguments)]
386
0
pub(crate) fn f_polyeval13<T: PolyevalMla + Copy + Mul<T, Output = T>>(
387
0
    x: T,
388
0
    a0: T,
389
0
    a1: T,
390
0
    a2: T,
391
0
    a3: T,
392
0
    a4: T,
393
0
    a5: T,
394
0
    a6: T,
395
0
    a7: T,
396
0
    a8: T,
397
0
    a9: T,
398
0
    a10: T,
399
0
    a11: T,
400
0
    a12: T,
401
0
) -> T {
402
0
    let x2 = x * x;
403
0
    let x4 = x2 * x2;
404
0
    let x8 = x4 * x4;
405
406
0
    let t0 = T::polyeval_mla(x, a3, a2);
407
0
    let t1 = T::polyeval_mla(x, a1, a0);
408
0
    let t2 = T::polyeval_mla(x, a7, a6);
409
0
    let t3 = T::polyeval_mla(x, a5, a4);
410
0
    let t4 = T::polyeval_mla(x, a11, a10);
411
0
    let t5 = T::polyeval_mla(x, a9, a8);
412
413
0
    let q0 = T::polyeval_mla(x2, t0, t1);
414
0
    let q1 = T::polyeval_mla(x2, t2, t3);
415
416
0
    let q2 = T::polyeval_mla(x2, t4, t5);
417
418
0
    let q3 = a12;
419
420
0
    let r0 = T::polyeval_mla(x4, q1, q0);
421
0
    let r1 = T::polyeval_mla(x4, q3, q2);
422
423
0
    T::polyeval_mla(x8, r1, r0)
424
0
}
425
426
#[inline(always)]
427
#[allow(clippy::too_many_arguments)]
428
0
pub(crate) fn f_polyeval12<T: PolyevalMla + Copy + Mul<T, Output = T>>(
429
0
    x: T,
430
0
    a0: T,
431
0
    a1: T,
432
0
    a2: T,
433
0
    a3: T,
434
0
    a4: T,
435
0
    a5: T,
436
0
    a6: T,
437
0
    a7: T,
438
0
    a8: T,
439
0
    a9: T,
440
0
    a10: T,
441
0
    a11: T,
442
0
) -> T {
443
0
    let x2 = x * x;
444
0
    let x4 = x2 * x2;
445
0
    let x8 = x4 * x4;
446
447
0
    let e0 = T::polyeval_mla(x, a1, a0);
448
0
    let e1 = T::polyeval_mla(x, a3, a2);
449
0
    let e2 = T::polyeval_mla(x, a5, a4);
450
0
    let e3 = T::polyeval_mla(x, a7, a6);
451
0
    let e4 = T::polyeval_mla(x, a9, a8);
452
0
    let e5 = T::polyeval_mla(x, a11, a10);
453
454
0
    let f0 = T::polyeval_mla(x2, e1, e0);
455
0
    let f1 = T::polyeval_mla(x2, e3, e2);
456
0
    let f2 = T::polyeval_mla(x2, e5, e4);
457
458
0
    let g0 = T::polyeval_mla(x4, f1, f0);
459
460
0
    T::polyeval_mla(x8, f2, g0)
461
0
}
Unexecuted instantiation: pxfm::polyeval::f_polyeval12::<f64>
Unexecuted instantiation: pxfm::polyeval::f_polyeval12::<pxfm::double_double::DoubleDouble>
462
463
#[inline(always)]
464
#[allow(clippy::too_many_arguments)]
465
0
pub(crate) fn f_polyeval14<T: PolyevalMla + Copy + Mul<T, Output = T>>(
466
0
    x: T,
467
0
    a0: T,
468
0
    a1: T,
469
0
    a2: T,
470
0
    a3: T,
471
0
    a4: T,
472
0
    a5: T,
473
0
    a6: T,
474
0
    a7: T,
475
0
    a8: T,
476
0
    a9: T,
477
0
    a10: T,
478
0
    a11: T,
479
0
    a12: T,
480
0
    a13: T,
481
0
) -> T {
482
0
    let x2 = x * x;
483
0
    let x4 = x2 * x2;
484
0
    let x8 = x4 * x4;
485
486
0
    let g0 = T::polyeval_mla(x, a1, a0);
487
0
    let g1 = T::polyeval_mla(x, a3, a2);
488
0
    let g2 = T::polyeval_mla(x, a5, a4);
489
0
    let g3 = T::polyeval_mla(x, a7, a6);
490
0
    let g4 = T::polyeval_mla(x, a9, a8);
491
0
    let g5 = T::polyeval_mla(x, a11, a10);
492
0
    let g6 = T::polyeval_mla(x, a13, a12);
493
494
0
    let h0 = T::polyeval_mla(x2, g1, g0);
495
0
    let h1 = T::polyeval_mla(x2, g3, g2);
496
0
    let h2 = T::polyeval_mla(x2, g5, g4);
497
498
0
    let q0 = T::polyeval_mla(x4, h1, h0);
499
0
    let q1 = T::polyeval_mla(x4, g6, h2);
500
501
0
    T::polyeval_mla(x8, q1, q0)
502
0
}
503
504
#[inline(always)]
505
#[allow(unused)]
506
#[allow(clippy::too_many_arguments)]
507
0
pub(crate) fn d_polyeval14(
508
0
    x: f64,
509
0
    a0: f64,
510
0
    a1: f64,
511
0
    a2: f64,
512
0
    a3: f64,
513
0
    a4: f64,
514
0
    a5: f64,
515
0
    a6: f64,
516
0
    a7: f64,
517
0
    a8: f64,
518
0
    a9: f64,
519
0
    a10: f64,
520
0
    a11: f64,
521
0
    a12: f64,
522
0
    a13: f64,
523
0
) -> f64 {
524
0
    let x2 = x * x;
525
0
    let x4 = x2 * x2;
526
0
    let x8 = x4 * x4;
527
528
0
    let g0 = f64::mul_add(x, a1, a0);
529
0
    let g1 = f64::mul_add(x, a3, a2);
530
0
    let g2 = f64::mul_add(x, a5, a4);
531
0
    let g3 = f64::mul_add(x, a7, a6);
532
0
    let g4 = f64::mul_add(x, a9, a8);
533
0
    let g5 = f64::mul_add(x, a11, a10);
534
0
    let g6 = f64::mul_add(x, a13, a12);
535
536
0
    let h0 = f64::mul_add(x2, g1, g0);
537
0
    let h1 = f64::mul_add(x2, g3, g2);
538
0
    let h2 = f64::mul_add(x2, g5, g4);
539
540
0
    let q0 = f64::mul_add(x4, h1, h0);
541
0
    let q1 = f64::mul_add(x4, g6, h2);
542
543
0
    f64::mul_add(x8, q1, q0)
544
0
}
545
546
#[inline(always)]
547
#[allow(clippy::too_many_arguments)]
548
0
pub(crate) fn f_polyeval7<T: PolyevalMla + Copy>(
549
0
    x: T,
550
0
    a0: T,
551
0
    a1: T,
552
0
    a2: T,
553
0
    a3: T,
554
0
    a4: T,
555
0
    a5: T,
556
0
    a6: T,
557
0
) -> T {
558
0
    let t1 = T::polyeval_mla(x, a6, a5);
559
0
    let t2 = T::polyeval_mla(x, t1, a4);
560
0
    let t3 = T::polyeval_mla(x, t2, a3);
561
0
    let t4 = T::polyeval_mla(x, t3, a2);
562
0
    let t5 = T::polyeval_mla(x, t4, a1);
563
0
    T::polyeval_mla(x, t5, a0)
564
0
}
565
566
#[inline(always)]
567
#[allow(unused)]
568
#[allow(clippy::too_many_arguments)]
569
0
pub(crate) fn d_polyeval7(
570
0
    x: f64,
571
0
    a0: f64,
572
0
    a1: f64,
573
0
    a2: f64,
574
0
    a3: f64,
575
0
    a4: f64,
576
0
    a5: f64,
577
0
    a6: f64,
578
0
) -> f64 {
579
0
    let t1 = f64::mul_add(x, a6, a5);
580
0
    let t2 = f64::mul_add(x, t1, a4);
581
0
    let t3 = f64::mul_add(x, t2, a3);
582
0
    let t4 = f64::mul_add(x, t3, a2);
583
0
    let t5 = f64::mul_add(x, t4, a1);
584
0
    f64::mul_add(x, t5, a0)
585
0
}
586
587
#[inline(always)]
588
#[allow(clippy::too_many_arguments)]
589
0
pub(crate) fn f_estrin_polyeval7<T: PolyevalMla + Copy + Mul<T, Output = T>>(
590
0
    x: T,
591
0
    a0: T,
592
0
    a1: T,
593
0
    a2: T,
594
0
    a3: T,
595
0
    a4: T,
596
0
    a5: T,
597
0
    a6: T,
598
0
) -> T {
599
0
    let x2 = x * x;
600
0
    let x4 = x2 * x2;
601
602
0
    let b0 = T::polyeval_mla(x, a1, a0);
603
0
    let b1 = T::polyeval_mla(x, a3, a2);
604
0
    let b2 = T::polyeval_mla(x, a5, a4);
605
606
0
    let c0 = T::polyeval_mla(x2, b1, b0);
607
0
    let c1 = T::polyeval_mla(x2, a6, b2);
608
609
0
    T::polyeval_mla(x4, c1, c0)
610
0
}
611
612
#[inline(always)]
613
#[allow(unused)]
614
#[allow(clippy::too_many_arguments)]
615
0
pub(crate) fn d_estrin_polyeval7(
616
0
    x: f64,
617
0
    a0: f64,
618
0
    a1: f64,
619
0
    a2: f64,
620
0
    a3: f64,
621
0
    a4: f64,
622
0
    a5: f64,
623
0
    a6: f64,
624
0
) -> f64 {
625
0
    let x2 = x * x;
626
0
    let x4 = x2 * x2;
627
628
0
    let b0 = f64::mul_add(x, a1, a0);
629
0
    let b1 = f64::mul_add(x, a3, a2);
630
0
    let b2 = f64::mul_add(x, a5, a4);
631
632
0
    let c0 = f64::mul_add(x2, b1, b0);
633
0
    let c1 = f64::mul_add(x2, a6, b2);
634
635
0
    f64::mul_add(x4, c1, c0)
636
0
}
637
638
#[allow(clippy::too_many_arguments)]
639
#[inline(always)]
640
0
pub(crate) fn f_polyeval5<T: PolyevalMla + Copy>(x: T, a0: T, a1: T, a2: T, a3: T, a4: T) -> T {
641
0
    let mut acc = a4;
642
0
    acc = T::polyeval_mla(x, acc, a3);
643
0
    acc = T::polyeval_mla(x, acc, a2);
644
0
    acc = T::polyeval_mla(x, acc, a1);
645
0
    T::polyeval_mla(x, acc, a0)
646
0
}
647
648
#[allow(clippy::too_many_arguments)]
649
#[inline(always)]
650
#[allow(unused)]
651
0
pub(crate) fn d_polyeval5(x: f64, a0: f64, a1: f64, a2: f64, a3: f64, a4: f64) -> f64 {
652
0
    let mut acc = a4;
653
0
    acc = f64::mul_add(x, acc, a3);
654
0
    acc = f64::mul_add(x, acc, a2);
655
0
    acc = f64::mul_add(x, acc, a1);
656
0
    f64::mul_add(x, acc, a0)
657
0
}
658
659
#[allow(clippy::too_many_arguments)]
660
#[inline(always)]
661
0
pub(crate) fn f_estrin_polyeval5<T: PolyevalMla + Copy + Mul<T, Output = T>>(
662
0
    x: T,
663
0
    a0: T,
664
0
    a1: T,
665
0
    a2: T,
666
0
    a3: T,
667
0
    a4: T,
668
0
) -> T {
669
0
    let x2 = x * x;
670
0
    let p01 = T::polyeval_mla(x, a1, a0);
671
0
    let p23 = T::polyeval_mla(x, a3, a2);
672
0
    let t = T::polyeval_mla(x2, a4, p23);
673
0
    T::polyeval_mla(x2, t, p01)
674
0
}
675
676
#[allow(clippy::too_many_arguments)]
677
#[inline(always)]
678
#[allow(unused)]
679
0
pub(crate) fn d_estrin_polyeval5(x: f64, a0: f64, a1: f64, a2: f64, a3: f64, a4: f64) -> f64 {
680
0
    let x2 = x * x;
681
0
    let p01 = f64::mul_add(x, a1, a0);
682
0
    let p23 = f64::mul_add(x, a3, a2);
683
0
    let t = f64::mul_add(x2, a4, p23);
684
0
    f64::mul_add(x2, t, p01)
685
0
}
686
687
#[inline(always)]
688
#[allow(clippy::too_many_arguments)]
689
0
pub(crate) fn f_polyeval8<T: PolyevalMla + Copy>(
690
0
    x: T,
691
0
    a0: T,
692
0
    a1: T,
693
0
    a2: T,
694
0
    a3: T,
695
0
    a4: T,
696
0
    a5: T,
697
0
    a6: T,
698
0
    a7: T,
699
0
) -> T {
700
0
    let z0 = T::polyeval_mla(x, a7, a6);
701
0
    let t1 = T::polyeval_mla(x, z0, a5);
702
0
    let t2 = T::polyeval_mla(x, t1, a4);
703
0
    let t3 = T::polyeval_mla(x, t2, a3);
704
0
    let t4 = T::polyeval_mla(x, t3, a2);
705
0
    let t5 = T::polyeval_mla(x, t4, a1);
706
0
    T::polyeval_mla(x, t5, a0)
707
0
}
708
709
#[inline(always)]
710
#[allow(clippy::too_many_arguments)]
711
0
pub(crate) fn f_estrin_polyeval8<T: PolyevalMla + Copy + Mul<T, Output = T>>(
712
0
    x: T,
713
0
    a0: T,
714
0
    a1: T,
715
0
    a2: T,
716
0
    a3: T,
717
0
    a4: T,
718
0
    a5: T,
719
0
    a6: T,
720
0
    a7: T,
721
0
) -> T {
722
0
    let x2 = x * x;
723
0
    let x4 = x2 * x2;
724
725
0
    let p0 = T::polyeval_mla(x, a1, a0);
726
0
    let p1 = T::polyeval_mla(x, a3, a2);
727
0
    let p2 = T::polyeval_mla(x, a5, a4);
728
0
    let p3 = T::polyeval_mla(x, a7, a6);
729
730
0
    let q0 = T::polyeval_mla(x2, p1, p0);
731
0
    let q1 = T::polyeval_mla(x2, p3, p2);
732
733
0
    T::polyeval_mla(x4, q1, q0)
734
0
}
735
736
#[inline(always)]
737
#[allow(clippy::too_many_arguments)]
738
0
pub(crate) fn f_polyeval16<T: PolyevalMla + Copy + Mul<T, Output = T>>(
739
0
    x: T,
740
0
    a0: T,
741
0
    a1: T,
742
0
    a2: T,
743
0
    a3: T,
744
0
    a4: T,
745
0
    a5: T,
746
0
    a6: T,
747
0
    a7: T,
748
0
    a8: T,
749
0
    a9: T,
750
0
    a10: T,
751
0
    a11: T,
752
0
    a12: T,
753
0
    a13: T,
754
0
    a14: T,
755
0
    a15: T,
756
0
) -> T {
757
0
    let x2 = x * x;
758
0
    let x4 = x2 * x2;
759
0
    let x8 = x4 * x4;
760
761
0
    let q0 = T::polyeval_mla(x, a1, a0);
762
0
    let q1 = T::polyeval_mla(x, a3, a2);
763
0
    let q2 = T::polyeval_mla(x, a5, a4);
764
0
    let q3 = T::polyeval_mla(x, a7, a6);
765
0
    let q4 = T::polyeval_mla(x, a9, a8);
766
0
    let q5 = T::polyeval_mla(x, a11, a10);
767
0
    let q6 = T::polyeval_mla(x, a13, a12);
768
0
    let q7 = T::polyeval_mla(x, a15, a14);
769
770
0
    let r0 = T::polyeval_mla(x2, q1, q0);
771
0
    let r1 = T::polyeval_mla(x2, q3, q2);
772
0
    let r2 = T::polyeval_mla(x2, q5, q4);
773
0
    let r3 = T::polyeval_mla(x2, q7, q6);
774
775
0
    let s0 = T::polyeval_mla(x4, r1, r0);
776
0
    let s1 = T::polyeval_mla(x4, r3, r2);
777
778
0
    T::polyeval_mla(x8, s1, s0)
779
0
}
780
781
#[inline(always)]
782
#[allow(clippy::too_many_arguments)]
783
0
pub(crate) fn f_polyeval15<T: PolyevalMla + Copy + Mul<T, Output = T>>(
784
0
    x: T,
785
0
    a0: T,
786
0
    a1: T,
787
0
    a2: T,
788
0
    a3: T,
789
0
    a4: T,
790
0
    a5: T,
791
0
    a6: T,
792
0
    a7: T,
793
0
    a8: T,
794
0
    a9: T,
795
0
    a10: T,
796
0
    a11: T,
797
0
    a12: T,
798
0
    a13: T,
799
0
    a14: T,
800
0
) -> T {
801
0
    let x2 = x * x;
802
0
    let x4 = x2 * x2;
803
0
    let x8 = x4 * x4;
804
805
0
    let e0 = T::polyeval_mla(x, a1, a0);
806
0
    let e1 = T::polyeval_mla(x, a3, a2);
807
0
    let e2 = T::polyeval_mla(x, a5, a4);
808
0
    let e3 = T::polyeval_mla(x, a7, a6);
809
0
    let e4 = T::polyeval_mla(x, a9, a8);
810
0
    let e5 = T::polyeval_mla(x, a11, a10);
811
0
    let e6 = T::polyeval_mla(x, a13, a12);
812
813
    // Level 2
814
0
    let f0 = T::polyeval_mla(x2, e1, e0);
815
0
    let f1 = T::polyeval_mla(x2, e3, e2);
816
0
    let f2 = T::polyeval_mla(x2, e5, e4);
817
0
    let f3 = T::polyeval_mla(x2, a14, e6);
818
819
    // Level 3
820
0
    let g0 = T::polyeval_mla(x4, f1, f0);
821
0
    let g1 = T::polyeval_mla(x4, f3, f2);
822
823
    // Final
824
0
    T::polyeval_mla(x8, g1, g0)
825
0
}
826
827
#[inline(always)]
828
#[allow(clippy::too_many_arguments)]
829
0
pub(crate) fn f_polyeval18<T: PolyevalMla + Copy + Mul<T, Output = T>>(
830
0
    x: T,
831
0
    a0: T,
832
0
    a1: T,
833
0
    a2: T,
834
0
    a3: T,
835
0
    a4: T,
836
0
    a5: T,
837
0
    a6: T,
838
0
    a7: T,
839
0
    a8: T,
840
0
    a9: T,
841
0
    a10: T,
842
0
    a11: T,
843
0
    a12: T,
844
0
    a13: T,
845
0
    a14: T,
846
0
    a15: T,
847
0
    a16: T,
848
0
    a17: T,
849
0
) -> T {
850
0
    let x2 = x * x;
851
0
    let x4 = x2 * x2;
852
0
    let x8 = x4 * x4;
853
0
    let x16 = x8 * x8;
854
855
0
    let q0 = T::polyeval_mla(x, a1, a0);
856
0
    let q1 = T::polyeval_mla(x, a3, a2);
857
0
    let q2 = T::polyeval_mla(x, a5, a4);
858
0
    let q3 = T::polyeval_mla(x, a7, a6);
859
0
    let q4 = T::polyeval_mla(x, a9, a8);
860
0
    let q5 = T::polyeval_mla(x, a11, a10);
861
0
    let q6 = T::polyeval_mla(x, a13, a12);
862
0
    let q7 = T::polyeval_mla(x, a15, a14);
863
0
    let q8 = T::polyeval_mla(x, a17, a16);
864
865
0
    let r0 = T::polyeval_mla(x2, q1, q0);
866
0
    let r1 = T::polyeval_mla(x2, q3, q2);
867
0
    let r2 = T::polyeval_mla(x2, q5, q4);
868
0
    let r3 = T::polyeval_mla(x2, q7, q6);
869
870
0
    let s0 = T::polyeval_mla(x4, r1, r0);
871
0
    let s1 = T::polyeval_mla(x4, r3, r2);
872
873
0
    let t0 = T::polyeval_mla(x8, s1, s0);
874
875
0
    T::polyeval_mla(x16, q8, t0)
876
0
}
877
878
#[inline(always)]
879
#[allow(clippy::too_many_arguments)]
880
0
pub(crate) fn f_polyeval19<T: PolyevalMla + Copy + Mul<T, Output = T>>(
881
0
    x: T,
882
0
    a0: T,
883
0
    a1: T,
884
0
    a2: T,
885
0
    a3: T,
886
0
    a4: T,
887
0
    a5: T,
888
0
    a6: T,
889
0
    a7: T,
890
0
    a8: T,
891
0
    a9: T,
892
0
    a10: T,
893
0
    a11: T,
894
0
    a12: T,
895
0
    a13: T,
896
0
    a14: T,
897
0
    a15: T,
898
0
    a16: T,
899
0
    a17: T,
900
0
    a18: T,
901
0
) -> T {
902
0
    let x2 = x * x;
903
0
    let x4 = x2 * x2;
904
0
    let x8 = x4 * x4;
905
0
    let x16 = x8 * x8;
906
907
    // Level 0: pairs
908
0
    let e0 = T::polyeval_mla(x, a1, a0); // a0 + a1·x
909
0
    let e1 = T::polyeval_mla(x, a3, a2); // a2 + a3·x
910
0
    let e2 = T::polyeval_mla(x, a5, a4);
911
0
    let e3 = T::polyeval_mla(x, a7, a6);
912
0
    let e4 = T::polyeval_mla(x, a9, a8);
913
0
    let e5 = T::polyeval_mla(x, a11, a10);
914
0
    let e6 = T::polyeval_mla(x, a13, a12);
915
0
    let e7 = T::polyeval_mla(x, a15, a14);
916
0
    let e8 = T::polyeval_mla(x, a17, a16);
917
918
    // Level 1: combine with x²
919
0
    let f0 = T::polyeval_mla(x2, e1, e0);
920
0
    let f1 = T::polyeval_mla(x2, e3, e2);
921
0
    let f2 = T::polyeval_mla(x2, e5, e4);
922
0
    let f3 = T::polyeval_mla(x2, e7, e6);
923
924
    // Level 2: combine with x⁴
925
0
    let g0 = T::polyeval_mla(x4, f1, f0);
926
0
    let g1 = T::polyeval_mla(x4, f3, f2);
927
928
    // Level 3: combine with x⁸
929
0
    let h0 = T::polyeval_mla(x8, g1, g0);
930
931
    // Final: combine with x¹⁶
932
0
    let final_poly = T::polyeval_mla(x16, e8, h0);
933
934
    // Degree 18: Add a18·x¹⁸
935
    // This assumes `x18 = x16 * x2`, since x² already computed
936
0
    let x18 = x16 * x2;
937
0
    T::polyeval_mla(x18, a18, final_poly)
938
0
}
939
940
#[inline(always)]
941
#[allow(clippy::too_many_arguments)]
942
0
pub(crate) fn f_polyeval22<T: PolyevalMla + Copy + Mul<T, Output = T>>(
943
0
    x: T,
944
0
    a0: T,
945
0
    a1: T,
946
0
    a2: T,
947
0
    a3: T,
948
0
    a4: T,
949
0
    a5: T,
950
0
    a6: T,
951
0
    a7: T,
952
0
    a8: T,
953
0
    a9: T,
954
0
    a10: T,
955
0
    a11: T,
956
0
    a12: T,
957
0
    a13: T,
958
0
    a14: T,
959
0
    a15: T,
960
0
    a16: T,
961
0
    a17: T,
962
0
    a18: T,
963
0
    a19: T,
964
0
    a20: T,
965
0
    a21: T,
966
0
) -> T {
967
0
    let x2 = x * x;
968
0
    let x4 = x2 * x2;
969
0
    let x8 = x4 * x4;
970
0
    let x16 = x8 * x8;
971
972
0
    let p0 = T::polyeval_mla(x, a1, a0); // a1·x + a0
973
0
    let p1 = T::polyeval_mla(x, a3, a2); // a3·x + a2
974
0
    let p2 = T::polyeval_mla(x, a5, a4);
975
0
    let p3 = T::polyeval_mla(x, a7, a6);
976
0
    let p4 = T::polyeval_mla(x, a9, a8);
977
0
    let p5 = T::polyeval_mla(x, a11, a10);
978
0
    let p6 = T::polyeval_mla(x, a13, a12);
979
0
    let p7 = T::polyeval_mla(x, a15, a14);
980
0
    let p8 = T::polyeval_mla(x, a17, a16);
981
0
    let p9 = T::polyeval_mla(x, a19, a18);
982
0
    let p10 = T::polyeval_mla(x, a21, a20);
983
984
0
    let q0 = T::polyeval_mla(x2, p1, p0); // (a3·x + a2)·x² + (a1·x + a0)
985
0
    let q1 = T::polyeval_mla(x2, p3, p2);
986
0
    let q2 = T::polyeval_mla(x2, p5, p4);
987
0
    let q3 = T::polyeval_mla(x2, p7, p6);
988
0
    let q4 = T::polyeval_mla(x2, p9, p8);
989
0
    let r0 = T::polyeval_mla(x4, q1, q0); // q1·x⁴ + q0
990
0
    let r1 = T::polyeval_mla(x4, q3, q2);
991
0
    let s0 = T::polyeval_mla(x8, r1, r0); // r1·x⁸ + r0
992
0
    let r2 = T::polyeval_mla(x4, p10, q4); // p10·x⁴ + q4
993
0
    T::polyeval_mla(x16, r2, s0)
994
0
}
995
996
#[inline(always)]
997
#[allow(clippy::too_many_arguments)]
998
0
pub(crate) fn f_polyeval24<T: PolyevalMla + Copy + Mul<T, Output = T>>(
999
0
    x: T,
1000
0
    a0: T,
1001
0
    a1: T,
1002
0
    a2: T,
1003
0
    a3: T,
1004
0
    a4: T,
1005
0
    a5: T,
1006
0
    a6: T,
1007
0
    a7: T,
1008
0
    a8: T,
1009
0
    a9: T,
1010
0
    a10: T,
1011
0
    a11: T,
1012
0
    a12: T,
1013
0
    a13: T,
1014
0
    a14: T,
1015
0
    a15: T,
1016
0
    a16: T,
1017
0
    a17: T,
1018
0
    a18: T,
1019
0
    a19: T,
1020
0
    a20: T,
1021
0
    a21: T,
1022
0
    a22: T,
1023
0
    a23: T,
1024
0
) -> T {
1025
0
    let x2 = x * x;
1026
0
    let x4 = x2 * x2;
1027
0
    let x8 = x4 * x4;
1028
0
    let x16 = x8 * x8;
1029
1030
    // Group degree 0–1
1031
0
    let e0 = T::polyeval_mla(x, a1, a0);
1032
    // Group degree 2–3
1033
0
    let e1 = T::polyeval_mla(x, a3, a2);
1034
    // Group degree 4–5
1035
0
    let e2 = T::polyeval_mla(x, a5, a4);
1036
    // Group degree 6–7
1037
0
    let e3 = T::polyeval_mla(x, a7, a6);
1038
    // Group degree 8–9
1039
0
    let e4 = T::polyeval_mla(x, a9, a8);
1040
    // Group degree 10–11
1041
0
    let e5 = T::polyeval_mla(x, a11, a10);
1042
    // Group degree 12–13
1043
0
    let e6 = T::polyeval_mla(x, a13, a12);
1044
    // Group degree 14–15
1045
0
    let e7 = T::polyeval_mla(x, a15, a14);
1046
    // Group degree 16–17
1047
0
    let e8 = T::polyeval_mla(x, a17, a16);
1048
    // Group degree 18–19
1049
0
    let e9 = T::polyeval_mla(x, a19, a18);
1050
    // Group degree 20–21
1051
0
    let e10 = T::polyeval_mla(x, a21, a20);
1052
    // Group degree 22–23
1053
0
    let e11 = T::polyeval_mla(x, a23, a22);
1054
1055
    // Now group into x2 terms
1056
0
    let f0 = T::polyeval_mla(x2, e1, e0);
1057
0
    let f1 = T::polyeval_mla(x2, e3, e2);
1058
0
    let f2 = T::polyeval_mla(x2, e5, e4);
1059
0
    let f3 = T::polyeval_mla(x2, e7, e6);
1060
0
    let f4 = T::polyeval_mla(x2, e9, e8);
1061
0
    let f5 = T::polyeval_mla(x2, e11, e10);
1062
1063
    // Now group into x4 terms
1064
0
    let g0 = T::polyeval_mla(x4, f1, f0);
1065
0
    let g1 = T::polyeval_mla(x4, f3, f2);
1066
0
    let g2 = T::polyeval_mla(x4, f5, f4);
1067
1068
    // Now group into x8 terms
1069
0
    let h0 = T::polyeval_mla(x8, g1, g0);
1070
0
    let h1 = g2;
1071
1072
    // Final step (x16 term)
1073
0
    T::polyeval_mla(x16, h1, h0)
1074
0
}