------------------------------------------------------------------ */ decFloatFMA -- multiply and add three decFloats, fused */ / result gets the result of (dfl*dfr)+dff with a single rounding */ dfl is the first decFloat (lhs) */ dfr is the second decFloat (rhs) */ dff is the final decFloat (fhs)
| 1994 | /* */ |
| 1995 | /* ------------------------------------------------------------------ */ |
| 1996 | decFloat * decFloatFMA(decFloat *result, const decFloat *dfl, |
| 1997 | const decFloat *dfr, const decFloat *dff, |
| 1998 | decContext *set) { |
| 1999 | |
| 2000 | // The accumulator has the bytes needed for FiniteMultiply, plus |
| 2001 | // one byte to the left in case of carry, plus DECPMAX+2 to the |
| 2002 | // right for the final addition (up to full fhs + round & sticky) |
| 2003 | #define FMALEN (ROUNDUP4(1+ (DECPMAX9*18+1) +DECPMAX+2)) |
| 2004 | uByte acc[FMALEN]; // for multiplied coefficient in BCD |
| 2005 | // .. and for final result |
| 2006 | bcdnum mul; // for multiplication result |
| 2007 | bcdnum fin; // for final operand, expanded |
| 2008 | uByte coe[ROUNDUP4(DECPMAX)]; // dff coefficient in BCD |
| 2009 | bcdnum *hi, *lo; // bcdnum with higher/lower exponent |
| 2010 | uInt diffsign; // non-zero if signs differ |
| 2011 | uInt hipad; // pad digit for hi if needed |
| 2012 | Int padding; // excess exponent |
| 2013 | uInt carry; // +1 for ten's complement and during add |
| 2014 | uByte *ub, *uh, *ul; // work |
| 2015 | uInt uiwork; // for macros |
| 2016 | |
| 2017 | // handle all the special values [any special operand leads to a |
| 2018 | // special result] |
| 2019 | if (DFISSPECIAL(dfl) || DFISSPECIAL(dfr) || DFISSPECIAL(dff)) { |
| 2020 | decFloat proxy; // multiplication result proxy |
| 2021 | // NaNs are handled as usual, giving priority to sNaNs |
| 2022 | if (DFISSNAN(dfl) || DFISSNAN(dfr)) return decNaNs(result, dfl, dfr, set); |
| 2023 | if (DFISSNAN(dff)) return decNaNs(result, dff, NULL, set); |
| 2024 | if (DFISNAN(dfl) || DFISNAN(dfr)) return decNaNs(result, dfl, dfr, set); |
| 2025 | if (DFISNAN(dff)) return decNaNs(result, dff, NULL, set); |
| 2026 | // One or more of the three is infinite |
| 2027 | // infinity times zero is bad |
| 2028 | decFloatZero(&proxy); |
| 2029 | if (DFISINF(dfl)) { |
| 2030 | if (DFISZERO(dfr)) return decInvalid(result, set); |
| 2031 | decInfinity(&proxy, &proxy); |
| 2032 | } |
| 2033 | else if (DFISINF(dfr)) { |
| 2034 | if (DFISZERO(dfl)) return decInvalid(result, set); |
| 2035 | decInfinity(&proxy, &proxy); |
| 2036 | } |
| 2037 | // compute sign of multiplication and place in proxy |
| 2038 | DFWORD(&proxy, 0)|=(DFWORD(dfl, 0)^DFWORD(dfr, 0))&DECFLOAT_Sign; |
| 2039 | if (!DFISINF(dff)) return decFloatCopy(result, &proxy); |
| 2040 | // dff is Infinite |
| 2041 | if (!DFISINF(&proxy)) return decInfinity(result, dff); |
| 2042 | // both sides of addition are infinite; different sign is bad |
| 2043 | if ((DFWORD(dff, 0)&DECFLOAT_Sign)!=(DFWORD(&proxy, 0)&DECFLOAT_Sign)) |
| 2044 | return decInvalid(result, set); |
| 2045 | return decFloatCopy(result, &proxy); |
| 2046 | } |
| 2047 | |
| 2048 | /* Here when all operands are finite */ |
| 2049 | |
| 2050 | // First multiply dfl*dfr |
| 2051 | decFiniteMultiply(&mul, acc+1, dfl, dfr); |
| 2052 | // The multiply is complete, exact and unbounded, and described in |
| 2053 | // mul with the coefficient held in acc[1...] |
no test coverage detected