Esempio n. 1
0
        public BigDecimal pow(BigDecimal rhs,MathContext set)
        {
            int n;
            BigDecimal lhs;
            int reqdig;
            int workdigits=0;
            int L=0;
            MathContext workset;
            BigDecimal res;
            bool seenbit;
            int i=0;
            if (set.lostDigits)
                checkdigits(rhs,set.digits);
            n=rhs.intcheck(MinArg,MaxArg); // check RHS by the rules
            lhs=this; // clarified name

            reqdig=set.digits; // local copy (heavily used)
            if (reqdig==0)
                {
                    if (rhs.ind==isneg)
                        throw new System.ArithmeticException("Negative power:"+" "+rhs.ToString());
                    workdigits=0;
                }
            else
                {/* non-0 digits */
                    if ((rhs.mant.Length+rhs.exp)>reqdig)
                        throw new System.ArithmeticException("Too many digits:"+" "+rhs.ToString());

                    /* Round the lhs to DIGITS if need be */
                    if (lhs.mant.Length>reqdig)
                        lhs=clone(lhs).round(set);

                    /* L for precision calculation [see ANSI X3.274-1996] */
                    L=rhs.mant.Length+rhs.exp; // length without decimal zeros/exp
                    workdigits=(reqdig+L)+1; // calculate the working DIGITS
                }

            workset=new MathContext(workdigits,set.form,false,set.roundingMode);

            res=ONE; // accumulator
            if (n==0)
                return res; // x**0 == 1
            if (n<0)
                n=(int)-n; // [rhs.ind records the sign]
            seenbit=false; // set once we've seen a 1-bit
            for(i=1;;i++){ // for each bit [top bit ignored]
                    n=n+n; // shift left 1 bit
                    if (n<0)
                        { // top bit is set
                            seenbit=true; // OK, we're off
                            res=res.multiply(lhs,workset); // acc=acc*x
                        }
                    if (i==31)
                        break; // that was the last bit
                    if ((!seenbit))
                        continue; // we don't have to square 1
                    res=res.multiply(res,workset); // acc=acc*acc [square]
                }
            if (rhs.ind<0)  // was a **-n [hence digits>0]
                res=ONE.divide(res,workset); // .. so acc=1/acc
            return res.finish(set,true); // round and strip [original digits]
        }