public BigDecimal add(BigDecimal rhs,MathContext set) { BigDecimal lhs; int reqdig; BigDecimal res; sbyte[] usel; int usellen; sbyte[] user; int userlen; int newlen=0; int tlen=0; int mult=0; sbyte[] t=null; int ia=0; int ib=0; int ea=0; int eb=0; sbyte ca=0; sbyte cb=0; /* determine requested digits and form */ if (set.lostDigits) checkdigits(rhs,set.digits); lhs=this; // name for clarity and proxy /* Quick exit for add floating 0 */ // plus() will optimize to return same object if possible if (lhs.ind==0) if (set.form!=MathContext.PLAIN) return rhs.plus(set); if (rhs.ind==0) if (set.form!=MathContext.PLAIN) return lhs.plus(set); /* Prepare numbers (round, unless unlimited precision) */ reqdig=set.digits; // local copy (heavily used) if (reqdig>0) { if (lhs.mant.Length>reqdig) lhs=clone(lhs).round(set); if (rhs.mant.Length>reqdig) rhs=clone(rhs).round(set); // [we could reuse the new LHS for result in this case] } res=new BigDecimal(); // build result here /* Now see how much we have to pad or truncate lhs or rhs in order to align the numbers. If one number is much larger than the other, then the smaller cannot affect the answer [but we may still need to pad with up to DIGITS trailing zeros]. */ // Note sign may be 0 if digits (reqdig) is 0 // usel and user will be the sbyte arrays passed to the adder; we'll // use them on all paths except quick exits usel=lhs.mant; usellen=lhs.mant.Length; user=rhs.mant; userlen=rhs.mant.Length; if (lhs.exp==rhs.exp) {/* no padding needed */ // This is the most common, and fastest, path res.exp=lhs.exp; } else if (lhs.exp>rhs.exp) { // need to pad lhs and/or truncate rhs newlen=(usellen+lhs.exp)-rhs.exp; /* If, after pad, lhs would be longer than rhs by digits+1 or more (and digits>0) then rhs cannot affect answer, so we only need to pad up to a length of DIGITS+1. */ if (newlen>=((userlen+reqdig)+1)) if (reqdig>0) { // LHS is sufficient res.mant=usel; res.exp=lhs.exp; res.ind=lhs.ind; if (usellen<reqdig) { // need 0 padding res.mant=extend(lhs.mant,reqdig); res.exp=res.exp-((reqdig-usellen)); } return res.finish(set,false); } // RHS may affect result res.exp=rhs.exp; // expected final exponent if (newlen>(reqdig+1)) if (reqdig>0) { // LHS will be max; RHS truncated tlen=(newlen-reqdig)-1; // truncation length userlen=userlen-tlen; res.exp=res.exp+tlen; newlen=reqdig+1; } if (newlen>usellen) usellen=newlen; // need to pad LHS } else{ // need to pad rhs and/or truncate lhs newlen=(userlen+rhs.exp)-lhs.exp; if (newlen>=((usellen+reqdig)+1)) if (reqdig>0) { // RHS is sufficient res.mant=user; res.exp=rhs.exp; res.ind=rhs.ind; if (userlen<reqdig) { // need 0 padding res.mant=extend(rhs.mant,reqdig); res.exp=res.exp-((reqdig-userlen)); } return res.finish(set,false); } // LHS may affect result res.exp=lhs.exp; // expected final exponent if (newlen>(reqdig+1)) if (reqdig>0) { // RHS will be max; LHS truncated tlen=(newlen-reqdig)-1; // truncation length usellen=usellen-tlen; res.exp=res.exp+tlen; newlen=reqdig+1; } if (newlen>userlen) userlen=newlen; // need to pad RHS } if (lhs.ind==iszero) res.ind=ispos; else res.ind=lhs.ind; // likely sign, all paths if (((lhs.ind==isneg)?1:0)==((rhs.ind==isneg)?1:0)) // same sign, 0 non-negative mult=1; else { mult=-1; // will cause subtract /* Before we can subtract we must determine which is the larger, as our add/subtract routine only handles non-negative results so we may need to swap the operands. */ if (rhs.ind==iszero){ // original A bigger }else if ((usellen<userlen)|(lhs.ind==iszero)) { // original B bigger t=usel; usel=user; user=t; // swap tlen=usellen; usellen=userlen; userlen=tlen; // .. res.ind=(sbyte)-res.ind; // and set sign } else if (usellen>userlen){ // original A bigger }else{ {/* logical lengths the same */ // need compare /* may still need to swap: compare the strings */ ia=0; ib=0; ea=usel.Length-1; eb=user.Length-1; for(;;){ if (ia<=ea) ca=usel[ia]; else { if (ib>eb) {/* identical */ if (set.form!=MathContext.PLAIN) return ZERO; // [if PLAIN we must do the subtract, in case of 0.000 results] break; } ca=(sbyte)0; } if (ib<=eb) cb=user[ib]; else cb=(sbyte)0; if (ca!=cb) { if (ca<cb) {/* swap needed */ t=usel; usel=user; user=t; // swap tlen=usellen; usellen=userlen; userlen=tlen; // .. res.ind=(sbyte)-res.ind; } break; } /* mantissas the same, so far */ ia++; ib++; } } // lengths the same } } res.mant=byteaddsub(usel,usellen,user,userlen,mult,false); return res.finish(set,false); }
public BigDecimal min(BigDecimal rhs,MathContext set) { if ((this.CompareTo(rhs,set))<=0) return this.plus(set); else return rhs.plus(set); }