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

Function decUnitAddSub

extern/decNumber/decNumber.c:6335–6572  ·  view source on GitHub ↗

------------------------------------------------------------------ */ decUnitAddSub -- add or subtract two >=0 integers in Unit arrays */ / This routine performs the calculation: */ / C=A+(B*M) */ / Where M is in the range -DECDPUNMAX through +DECDPUNMAX. */ / A may be shorter or longer than B.

Source from the content-addressed store, hash-verified

6333/* (IBM Warwick, UK) for some of the ideas used in this routine. */
6334/* ------------------------------------------------------------------ */
6335static Int decUnitAddSub(const Unit *a, Int alength,
6336 const Unit *b, Int blength, Int bshift,
6337 Unit *c, Int m) {
6338 const Unit *alsu=a; // A lsu [need to remember it]
6339 Unit *clsu=c; // C ditto
6340 Unit *minC; // low water mark for C
6341 Unit *maxC; // high water mark for C
6342 eInt carry=0; // carry integer (could be Long)
6343 Int add; // work
6344 #if DECDPUN<=4 // myriadal, millenary, etc.
6345 Int est; // estimated quotient
6346 #endif
6347
6348 #if DECTRACE
6349 if (alength<1 || blength<1)
6350 printf("decUnitAddSub: alen blen m %ld %ld [%ld]\n", alength, blength, m);
6351 #endif
6352
6353 maxC=c+alength; // A is usually the longer
6354 minC=c+blength; // .. and B the shorter
6355 if (bshift!=0) { // B is shifted; low As copy across
6356 minC+=bshift;
6357 // if in place [common], skip copy unless there's a gap [rare]
6358 if (a==c && bshift<=alength) {
6359 c+=bshift;
6360 a+=bshift;
6361 }
6362 else for (; c<clsu+bshift; a++, c++) { // copy needed
6363 if (a<alsu+alength) *c=*a;
6364 else *c=0;
6365 }
6366 }
6367 if (minC>maxC) { // swap
6368 Unit *hold=minC;
6369 minC=maxC;
6370 maxC=hold;
6371 }
6372
6373 // For speed, do the addition as two loops; the first where both A
6374 // and B contribute, and the second (if necessary) where only one or
6375 // other of the numbers contribute.
6376 // Carry handling is the same (i.e., duplicated) in each case.
6377 for (; c<minC; c++) {
6378 carry+=*a;
6379 a++;
6380 carry+=((eInt)*b)*m; // [special-casing m=1/-1
6381 b++; // here is not a win]
6382 // here carry is new Unit of digits; it could be +ve or -ve
6383 if ((ueInt)carry<=DECDPUNMAX) { // fastpath 0-DECDPUNMAX
6384 *c=(Unit)carry;
6385 carry=0;
6386 continue;
6387 }
6388 #if DECDPUN==4 // use divide-by-multiply
6389 if (carry>=0) {
6390 est=(((ueInt)carry>>11)*53687)>>18;
6391 *c=(Unit)(carry-est*(DECDPUNMAX+1)); // remainder
6392 carry=est; // likely quotient [89%]

Callers 3

decNumber.cFile · 0.85
decUnitCompareFunction · 0.85
decApplyRoundFunction · 0.85

Calls

no outgoing calls

Tested by

no test coverage detected