MCPcopy Create free account
hub / github.com/FirebirdSQL/firebird / decNumberFMA

Function decNumberFMA

extern/decNumber/decNumber.c:1092–1167  ·  view source on GitHub ↗

------------------------------------------------------------------ */ 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

Source from the content-addressed store, hash-verified

1090/* C must have space for set->digits digits. */
1091/* ------------------------------------------------------------------ */
1092decNumber * 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)

Callers

nothing calls this directly

Calls 4

decCheckOperandsFunction · 0.85
decCheckMathFunction · 0.85
decStatusFunction · 0.85
decCheckInexactFunction · 0.85

Tested by

no test coverage detected