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

Function decSetSubnormal

extern/decNumber/decNumber.c:7426–7492  ·  view source on GitHub ↗

------------------------------------------------------------------ */ decSetSubnormal -- process value whose exponent is <Emin */ / dn is the number (used as input as well as output; it may have */ an allowed subnormal value, which may need to be rounded) */ set is the context [used for the rounding mode] */ residue is any pending residue

Source from the content-addressed store, hash-verified

7424/* necessary. Underflow is set if the result is Inexact. */
7425/* ------------------------------------------------------------------ */
7426static void decSetSubnormal(decNumber *dn, decContext *set, Int *residue,
7427 uInt *status) {
7428 decContext workset; // work
7429 Int etiny, adjust; // ..
7430
7431 #if DECSUBSET
7432 // simple set to zero and 'hard underflow' for subset
7433 if (!set->extended) {
7434 decNumberZero(dn);
7435 // always full overflow
7436 *status|=DEC_Underflow | DEC_Subnormal | DEC_Inexact | DEC_Rounded;
7437 return;
7438 }
7439 #endif
7440
7441 // Full arithmetic -- allow subnormals, rounded to minimum exponent
7442 // (Etiny) if needed
7443 etiny=set->emin-(set->digits-1); // smallest allowed exponent
7444
7445 if ISZERO(dn) { // value is zero
7446 // residue can never be non-zero here
7447 #if DECCHECK
7448 if (*residue!=0) {
7449 printf("++ Subnormal 0 residue %ld\n", (LI)*residue);
7450 *status|=DEC_Invalid_operation;
7451 }
7452 #endif
7453 if (dn->exponent<etiny) { // clamp required
7454 dn->exponent=etiny;
7455 *status|=DEC_Clamped;
7456 }
7457 return;
7458 }
7459
7460 *status|=DEC_Subnormal; // have a non-zero subnormal
7461 adjust=etiny-dn->exponent; // calculate digits to remove
7462 if (adjust<=0) { // not out of range; unrounded
7463 // residue can never be non-zero here, except in the Nmin-residue
7464 // case (which is a subnormal result), so can take fast-path here
7465 // it may already be inexact (from setting the coefficient)
7466 if (*status&DEC_Inexact) *status|=DEC_Underflow;
7467 return;
7468 }
7469
7470 // adjust>0, so need to rescale the result so exponent becomes Etiny
7471 // [this code is similar to that in rescale]
7472 workset=*set; // clone rounding, etc.
7473 workset.digits=dn->digits-adjust; // set requested length
7474 workset.emin-=adjust; // and adjust emin to match
7475 // [note that the latter can be <1, here, similar to Rescale case]
7476 decSetCoeff(dn, &workset, dn->lsu, dn->digits, residue, status);
7477 decApplyRound(dn, &workset, *residue, status);
7478
7479 // Use 754 default rule: Underflow is set iff Inexact
7480 // [independent of whether trapped]
7481 if (*status&DEC_Inexact) *status|=DEC_Underflow;
7482
7483 // if rounded up a 999s case, exponent will be off by one; adjust

Callers 1

decFinalizeFunction · 0.85

Calls 3

decSetCoeffFunction · 0.85
decApplyRoundFunction · 0.85
decShiftToMostFunction · 0.85

Tested by

no test coverage detected