------------------------------------------------------------------ */ decFloatShift -- shift the coefficient of a decFloat left or right */ / result gets the result of shifting dfl */ dfl is the source decFloat to shift */ dfr is the count of digits to shift, an integer (with q=0) */ set is the context
| 3396 | /* operand is an sNaN. The result is canonical. */ |
| 3397 | /* ------------------------------------------------------------------ */ |
| 3398 | decFloat * decFloatShift(decFloat *result, |
| 3399 | const decFloat *dfl, const decFloat *dfr, |
| 3400 | decContext *set) { |
| 3401 | Int shift; // dfr as an Int |
| 3402 | uByte buf[DECPMAX*2]; // coefficient + padding |
| 3403 | uInt digits, savestat; // work |
| 3404 | bcdnum num; // .. |
| 3405 | uInt uiwork; // for macros |
| 3406 | |
| 3407 | if (DFISNAN(dfl)||DFISNAN(dfr)) return decNaNs(result, dfl, dfr, set); |
| 3408 | if (!DFISINT(dfr)) return decInvalid(result, set); |
| 3409 | digits=decFloatDigits(dfr); // calculate digits |
| 3410 | if (digits>2) return decInvalid(result, set); // definitely out of range |
| 3411 | shift=DPD2BIN[DFWORD(dfr, DECWORDS-1)&0x3ff]; // is in bottom declet |
| 3412 | if (shift>DECPMAX) return decInvalid(result, set); // too big |
| 3413 | // [from here on no error or status change is possible] |
| 3414 | |
| 3415 | if (DFISINF(dfl)) return decInfinity(result, dfl); // canonical |
| 3416 | // handle no-shift and all-shift (clear to zero) cases |
| 3417 | if (shift==0) return decCanonical(result, dfl); |
| 3418 | if (shift==DECPMAX) { // zero with sign |
| 3419 | uByte sign=(uByte)(DFBYTE(dfl, 0)&0x80); // save sign bit |
| 3420 | decFloatZero(result); // make +0 |
| 3421 | DFBYTE(result, 0)=(uByte)(DFBYTE(result, 0)|sign); // and set sign |
| 3422 | // [cannot safely use CopySign] |
| 3423 | return result; |
| 3424 | } |
| 3425 | // a real shift is needed: 0 < shift < DECPMAX |
| 3426 | num.sign=DFWORD(dfl, 0)&DECFLOAT_Sign; |
| 3427 | num.exponent=GETEXPUN(dfl); |
| 3428 | num.msd=buf; |
| 3429 | GETCOEFF(dfl, buf); |
| 3430 | if (DFISSIGNED(dfr)) { // shift right |
| 3431 | // edge cases are taken care of, so this is easy |
| 3432 | num.lsd=buf+DECPMAX-shift-1; |
| 3433 | } |
| 3434 | else { // shift left -- zero padding needed to right |
| 3435 | UBFROMUI(buf+DECPMAX, 0); // 8 will handle most cases |
| 3436 | UBFROMUI(buf+DECPMAX+4, 0); // .. |
| 3437 | if (shift>8) memset(buf+DECPMAX+8, 0, 8+QUAD*18); // all other cases |
| 3438 | num.msd+=shift; |
| 3439 | num.lsd=num.msd+DECPMAX-1; |
| 3440 | } |
| 3441 | savestat=set->status; // record |
| 3442 | decFinalize(result, &num, set); |
| 3443 | set->status=savestat; // restore |
| 3444 | return result; |
| 3445 | } // decFloatShift |
| 3446 | |
| 3447 | /* ------------------------------------------------------------------ */ |
| 3448 | /* decFloatSubtract -- subtract a decFloat from another */ |
nothing calls this directly
no test coverage detected