| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* | ||
| 2 | POLYFLOAT - Extended precision floating points | ||
| 3 | Copyright : POLYFLOAT Contributors & Maintainers | ||
| 4 | SPDX-License-Identifier: BSL-1.0 | ||
| 5 | */ | ||
| 6 | //====================================================================================================================== | ||
| 7 | #pragma once | ||
| 8 | #include <polyfloat/module/core/three_fma.hpp> | ||
| 9 | |||
| 10 | namespace plf::_ | ||
| 11 | { | ||
| 12 | template<typename Z1, typename Z2, typename Z3> | ||
| 13 | 4 | constexpr auto inner_fma(Z1 const& x, Z2 const& y, Z3 const& z) noexcept | |
| 14 | { | ||
| 15 | using r_t = as_polyfloat_t<Z1, Z2, Z3>; | ||
| 16 | if constexpr (dimension_v<r_t> == 1) return eve::fma[pedantic](x, y, z); | ||
| 17 | else if constexpr ((dimension_v<Z1> > 2) || (dimension_v<Z2> > 2) || (dimension_v<Z3> > 2)) | ||
| 18 | { | ||
| 19 | using r_t = as_polyfloat_t<Z1, Z2, Z3>; | ||
| 20 | 12 | auto cvt = [](auto a) { return plf::convert(a, eve::as<eve::element_type_t<r_t>>()); }; | |
| 21 | 12 | auto [r, e0, e1] = three_fma(cvt(x), cvt(y), cvt(z)); | |
| 22 | 4 | return r; | |
| 23 | } | ||
| 24 | else if constexpr ((dimension_v<Z1> == 2) && (dimension_v<Z2> == 2) && (dimension_v<Z3> == 2)) | ||
| 25 | { | ||
| 26 | // auto fmap = eve::fma[pedantic]; | ||
| 27 | auto [xhi, xlo] = x; | ||
| 28 | auto [yhi, ylo] = y; | ||
| 29 | auto [zhi, zlo] = z; | ||
| 30 | auto [chi, c1] = eve::two_prod(xhi, yhi); | ||
| 31 | auto t0 = xlo * ylo; | ||
| 32 | auto t1 = eve::fma(xhi, ylo, t0); | ||
| 33 | auto c2 = eve::fma(xlo, yhi, t1); | ||
| 34 | auto c3 = c1 + c2; | ||
| 35 | auto [dhi, dlo] = eve::two_add[eve::raw](chi, c3); | ||
| 36 | |||
| 37 | auto [shi, slo] = eve::two_add(zhi, dhi); | ||
| 38 | auto [thi, tlo] = eve::two_add(zlo, dlo); | ||
| 39 | auto c = slo + thi; | ||
| 40 | auto [vhi, vlo] = eve::two_add[eve::raw](shi, c); | ||
| 41 | auto w = tlo + vlo; | ||
| 42 | auto [hi, lo] = eve::two_add[eve::raw](vhi, w); | ||
| 43 | return r_t(hi, lo); | ||
| 44 | } | ||
| 45 | else if constexpr ((dimension_v<Z1> == 1) && (dimension_v<Z2> == 1)) | ||
| 46 | { | ||
| 47 | auto [zhi, zlo] = z; | ||
| 48 | auto [chi, c1] = eve::two_prod(x, y); | ||
| 49 | auto [shi, slo] = eve::two_add(zhi, chi); | ||
| 50 | auto [thi, tlo] = eve::two_add(zlo, c1); | ||
| 51 | auto c = slo + thi; | ||
| 52 | auto [vhi, vlo] = eve::two_add[eve::raw](shi, c); | ||
| 53 | auto w = tlo + vlo; | ||
| 54 | auto [hi, lo] = eve::two_add[eve::raw](vhi, w); | ||
| 55 | return r_t(hi, lo); | ||
| 56 | } | ||
| 57 | // else | ||
| 58 | // { | ||
| 59 | // using r_t = as_polyfloat_t<Z1, Z2, Z3>; | ||
| 60 | // auto cvt = [](auto a){return plf::convert(a, eve::as<eve::element_type_t<r_t>>());}; | ||
| 61 | // return fma(cvt(x), cvt(y), cvt(z)); | ||
| 62 | // } | ||
| 63 | } | ||
| 64 | } | ||
| 65 |