------------------------------------------------------------------ */ decNumberFMA -- fused multiply add */ / This computes D = (A * B) + C with only one rounding */ / res is D, the result. D may be A or B or C (e.g., X=FMA(X,X,X)) */ lhs is A */ rhs is B
| 1090 | /* C must have space for set->digits digits. */ |
| 1091 | /* ------------------------------------------------------------------ */ |
| 1092 | decNumber * decNumberFMA(decNumber *res, const decNumber *lhs, |
| 1093 | const decNumber *rhs, const decNumber *fhs, |
| 1094 | decContext *set) { |
| 1095 | uInt status=0; // accumulator |
| 1096 | decContext dcmul; // context for the multiplication |
| 1097 | uInt needbytes; // for space calculations |
| 1098 | decNumber bufa[D2N(DECBUFFER*2+1)]; |
| 1099 | decNumber *allocbufa=NULL; // -> allocated bufa, iff allocated |
| 1100 | decNumber *acc; // accumulator pointer |
| 1101 | decNumber dzero; // work |
| 1102 | |
| 1103 | #if DECCHECK |
| 1104 | if (decCheckOperands(res, lhs, rhs, set)) return res; |
| 1105 | if (decCheckOperands(res, fhs, DECUNUSED, set)) return res; |
| 1106 | #endif |
| 1107 | |
| 1108 | do { // protect allocated storage |
| 1109 | #if DECSUBSET |
| 1110 | if (!set->extended) { // [undefined if subset] |
| 1111 | status|=DEC_Invalid_operation; |
| 1112 | break;} |
| 1113 | #endif |
| 1114 | // Check math restrictions [these ensure no overflow or underflow] |
| 1115 | if ((!decNumberIsSpecial(lhs) && decCheckMath(lhs, set, &status)) |
| 1116 | || (!decNumberIsSpecial(rhs) && decCheckMath(rhs, set, &status)) |
| 1117 | || (!decNumberIsSpecial(fhs) && decCheckMath(fhs, set, &status))) break; |
| 1118 | // set up context for multiply |
| 1119 | dcmul=*set; |
| 1120 | dcmul.digits=lhs->digits+rhs->digits; // just enough |
| 1121 | // [The above may be an over-estimate for subset arithmetic, but that's OK] |
| 1122 | dcmul.emax=DEC_MAX_EMAX; // effectively unbounded .. |
| 1123 | dcmul.emin=DEC_MIN_EMIN; // [thanks to Math restrictions] |
| 1124 | // set up decNumber space to receive the result of the multiply |
| 1125 | acc=bufa; // may fit |
| 1126 | needbytes=sizeof(decNumber)+(D2U(dcmul.digits)-1)*sizeof(Unit); |
| 1127 | if (needbytes>sizeof(bufa)) { // need malloc space |
| 1128 | allocbufa=(decNumber *)malloc(needbytes); |
| 1129 | if (allocbufa==NULL) { // hopeless -- abandon |
| 1130 | status|=DEC_Insufficient_storage; |
| 1131 | break;} |
| 1132 | acc=allocbufa; // use the allocated space |
| 1133 | } |
| 1134 | // multiply with extended range and necessary precision |
| 1135 | //printf("emin=%ld\n", dcmul.emin); |
| 1136 | decMultiplyOp(acc, lhs, rhs, &dcmul, &status); |
| 1137 | // Only Invalid operation (from sNaN or Inf * 0) is possible in |
| 1138 | // status; if either is seen than ignore fhs (in case it is |
| 1139 | // another sNaN) and set acc to NaN unless we had an sNaN |
| 1140 | // [decMultiplyOp leaves that to caller] |
| 1141 | // Note sNaN has to go through addOp to shorten payload if |
| 1142 | // necessary |
| 1143 | if ((status&DEC_Invalid_operation)!=0) { |
| 1144 | if (!(status&DEC_sNaN)) { // but be true invalid |
| 1145 | decNumberZero(res); // acc not yet set |
| 1146 | res->bits=DECNAN; |
| 1147 | break; |
| 1148 | } |
| 1149 | decNumberZero(&dzero); // make 0 (any non-NaN would do) |
nothing calls this directly
no test coverage detected