/*
(non-Javadoc)

@see org.javamoney.moneta.AbstractMoney#remainder(java.math.BigDecimal)
550377
@Override
    public Money remainder(Number divisor) {
        if (NumberVerifier.isInfinityAndNotNaN(divisor)) {
            return new Money(BigDecimal.ZERO, getCurrency());
        }
        MathContext mc = MoneyUtils.getMathContext(monetaryContext, RoundingMode.HALF_EVEN);
        BigDecimal bd = MoneyUtils.getBigDecimal(divisor);
        return new Money(this.number.remainder(bd, mc), getCurrency(), monetaryContext);
    }
767599
public BigDecimal compute(RoundingMode mode) {
    int scale = numerator.precision() + denominator.precision();
    scale = Math.max(MIN_SCALE, Math.min(MAX_SCALE, scale));
    return numerator.divide(denominator, scale, mode).stripTrailingZeros();
  }
243080
@Override
    public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException
    {
        checkParameterBounds(parameterIndex);
        this.parameters[parameterIndex-1] = x == null ? VoltType.NULL_DECIMAL : x;
    }
1174895
private static void divideUnsignedMultiPrecision(int[] dividend, int[] divisor, int[] quotient)
    {
        checkArgument(dividend.length == NUMBER_OF_INTS * 2 + 1);
        checkArgument(divisor.length == NUMBER_OF_INTS * 2);
        checkArgument(quotient.length == NUMBER_OF_INTS * 2);

        int divisorLength = digitsInIntegerBase(divisor);
        int dividendLength = digitsInIntegerBase(dividend);

        if (dividendLength < divisorLength) {
            return;
        }

        if (divisorLength == 1) {
            int remainder = divideUnsignedMultiPrecision(dividend, dividendLength, divisor[0]);
            checkState(dividend[dividend.length - 1] == 0);
            arraycopy(dividend, 0, quotient, 0, quotient.length);
            fill(dividend, 0);
            dividend[0] = remainder;
            return;
        }

        // normalize divisor. Most significant divisor word must be > BASE/2
        // effectively it can be achieved by shifting divisor left until the leftmost bit is 1
        int nlz = Integer.numberOfLeadingZeros(divisor[divisorLength - 1]);
        shiftLeftMultiPrecision(divisor, divisorLength, nlz);
        int normalizedDividendLength = Math.min(dividend.length, dividendLength + 1);
        shiftLeftMultiPrecision(dividend, normalizedDividendLength, nlz);

        divideKnuthNormalized(dividend, normalizedDividendLength, divisor, divisorLength, quotient);

        // un-normalize remainder which is stored in dividend
        shiftRightMultiPrecision(dividend, normalizedDividendLength, nlz);
    }
308712
@Override
    public RoundedMoney remainder(Number divisor) {
        MathContext mc = monetaryContext.get(MathContext.class);
        if(mc==null){
            mc = MathContext.DECIMAL64;
        }
        return new RoundedMoney(number.remainder(MoneyUtils.getBigDecimal(divisor), mc),
                currency, rounding);
    }
804191
public static BigDecimal decimalRound(BigDecimal number, int numDigits, RoundingMode rounding) {
        BigDecimal rounded = number.setScale(numDigits, rounding);

        if (numDigits < 0) {
            rounded = rounded.setScale(0, BigDecimal.ROUND_UNNECESSARY);
        }

        return rounded;
    }
579288
public BigDecimal calculate(BigDecimal x, MathContext mathContext) {
		BigDecimal acceptableError = ONE.movePointLeft(mathContext.getPrecision() + 1);

		PowerIterator powerIterator = createPowerIterator(x, mathContext);
		
		BigDecimal sum = BigDecimal.ZERO;
		BigDecimal step;
		int i = 0;
		do {
			BigRational factor = getFactor(i);
			BigDecimal xToThePower  = powerIterator.getCurrentPower();
			powerIterator.calculateNextPower();
			step = factor.getNumerator().multiply(xToThePower, mathContext).divide(factor.getDenominator(), mathContext);
			i++;

			if (calculateInPairs) {
				xToThePower  = powerIterator.getCurrentPower();
				powerIterator.calculateNextPower();
				factor = getFactor(i);
				BigDecimal step2 = factor.getNumerator().multiply(xToThePower, mathContext).divide(factor.getDenominator(), mathContext);
				step = step.add(step2, mathContext);
				i++;
			}

			sum = sum.add(step, mathContext);
			//System.out.println(sum + " " + step);
		} while (step.abs().compareTo(acceptableError) > 0);
		
		return sum.round(mathContext);
	}
910911
@Override
    public Money[] divideAndRemainder(double divisor) {
        if (NumberVerifier.isInfinityAndNotNaN(divisor)) {
            Money zero = Money.of(0, getCurrency());
            return new Money[]{zero, zero};
        }
        return divideAndRemainder(new BigDecimal(String.valueOf(divisor)));
    }
252874
private static BigInteger divideAndRoundByTenPow(BigInteger intVal, int tenPow, int roundingMode) {
        if (tenPow < LONG_TEN_POWERS_TABLE.length)
            intVal = divideAndRound(intVal, LONG_TEN_POWERS_TABLE[tenPow], roundingMode);
        else
            intVal = divideAndRound(intVal, bigTenToThe(tenPow), roundingMode);
        return intVal;
    }
788329
private static BigInteger divideAndRound(BigInteger bdividend, long ldivisor, int roundingMode) {
        boolean isRemainderZero; // record remainder is zero or not
        int qsign; // quotient sign
        long r = 0; // store quotient & remainder in long
        MutableBigInteger mq = null; // store quotient
        // Descend into mutables for faster remainder checks
        MutableBigInteger mdividend = new MutableBigInteger(bdividend.mag);
        mq = new MutableBigInteger();
        r = mdividend.divide(ldivisor, mq);
        isRemainderZero = (r == 0);
        qsign = (ldivisor < 0) ? -bdividend.signum : bdividend.signum;
        if (!isRemainderZero) {
            if(needIncrement(ldivisor, roundingMode, qsign, mq, r)) {
                mq.add(MutableBigInteger.ONE);
            }
        }
        return mq.toBigInteger(qsign);
    }
755636
static void divide(Slice dividend, int dividendScaleFactor, Slice divisor, int divisorScaleFactor, Slice quotient, Slice remainder)
    {
        divide(getRawLong(dividend, 0), getRawLong(dividend, 1), dividendScaleFactor, getRawLong(divisor, 0), getRawLong(divisor, 1), divisorScaleFactor, quotient, remainder);
    }
15002
private static BigDecimal doCalculate(String formula) throws Exception {
        Stack<BigDecimal> stack = new Stack<>();
        BigDecimal result = BigDecimal.valueOf(0);
        BigDecimal number = BigDecimal.valueOf(0);
        char sign = '+';
        boolean isDecimal = false;
        BigDecimal decimalSign = new BigDecimal(0.1);

        for (int i = 0; i < formula.length(); i++) {
            char c = formula.charAt(i);
            if (Character.isDigit(c)) {
                BigDecimal num = new BigDecimal(c - '0');
                number = isDecimal ? number.add(num.multiply(decimalSign)) : num.add(number.multiply(BigDecimal
                        .valueOf(10)));
                decimalSign = decimalSign.multiply(BigDecimal.valueOf(0.1));
            } else if (c == '.') {
                isDecimal = true;
                decimalSign = BigDecimal.valueOf(0.1);
            } else if (c == '(') {
                BigDecimal[] res = calculateInlineFormula(i + 1, formula);
                number = number.compareTo(BigDecimal.valueOf(0)) == 0 ? res[0] : number.multiply(res[0]);
                i = res[1].intValue();
            }
            boolean isNotDigit = (!Character.isDigit(c) && c != '.' && c != '(') || i == formula.length() - 1;
            if (isNotDigit) {
                if (sign == '+') {
                    stack.push(number);
                } else if (sign == '-') {
                    stack.push(number.multiply(BigDecimal.valueOf(-1)));
                } else if (sign == '*') {
                    stack.push(number.multiply(stack.pop()));
                } else if (sign == '/') {
                    stack.push(stack.pop().divide(number, getPrecision(), BigDecimal.ROUND_HALF_UP));
                }
                sign = c;
                isDecimal = false;
                number = BigDecimal.valueOf(0);
            }
        }
        for (BigDecimal i : stack) {
            result = result.add(i);
        }
        return result.setScale(getPrecision(), BigDecimal.ROUND_HALF_UP);
    }
103465
public static int divideWithCeilingRoundingMode(int p, int q) {
        if (q == 0) {
            throw new ArithmeticException("/ by zero"); // for GWT
        }
        int div = p / q;
        int rem = p - q * div; // equal to p % q

        if (rem == 0) {
            return div;
        }

        /*
         * Normal Java division rounds towards 0, consistently with RoundingMode.DOWN. We just have to
         * deal with the cases where rounding towards 0 is wrong, which typically depends on the sign of
         * p / q.
         *
         * signum is 1 if p and q are both nonnegative or both negative, and -1 otherwise.
         */
        int signum = 1 | ((p ^ q) >> (Integer.SIZE - 1));
        boolean increment = signum > 0;
        return increment ? div + signum : div;
    }
1277506
public static void writeUnpaddedInteger(Writer out, int value)
        throws IOException
    {
        if (value < 0) {
            out.write('-');
            if (value != Integer.MIN_VALUE) {
                value = -value;
            } else {
                out.write("" + -(long)Integer.MIN_VALUE);
                return;
            }
        }
        if (value < 10) {
            out.write(value + '0');
        } else if (value < 100) {
            // Calculate value div/mod by 10 without using two expensive
            // division operations. (2 ^ 27) / 10 = 13421772. Add one to
            // value to correct rounding error.
            int d = ((value + 1) * 13421772) >> 27;
            out.write(d + '0');
            // Append remainder by calculating (value - d * 10).
            out.write(value - (d << 3) - (d << 1) + '0');
        } else {
            out.write(Integer.toString(value));
        }
    }
448791
static BigDecimal decimal(String value) {
        BigDecimal result;
        if (value != null) {
            value = value.trim();
            Matcher matcher = DECIMAL_PATTERN.matcher(value);
            if (matcher.matches()) {
                result = new BigDecimal(matcher.group(1));
            } else {
                throw new IllegalArgumentException("Unknown format for value: " + value);
            }
        } else {
            result = null;
        }
        return result;
    }
1165684
@Override
  public void setDecimal(int ordinal, Decimal value, int precision) {
    assertIndexIsValid(ordinal);
    if (precision <= Decimal.MAX_LONG_DIGITS()) {
      // compact format
      if (value == null) {
        setNullAt(ordinal);
      } else {
        setLong(ordinal, value.toUnscaledLong());
      }
    } else {
      // fixed length
      long cursor = getLong(ordinal) >>> 32;
      assert cursor > 0 : "invalid cursor " + cursor;
      // zero-out the bytes
      Platform.putLong(baseObject, baseOffset + cursor, 0L);
      Platform.putLong(baseObject, baseOffset + cursor + 8, 0L);

      if (value == null) {
        setNullAt(ordinal);
        // keep the offset for future update
        Platform.putLong(baseObject, getFieldOffset(ordinal), cursor << 32);
      } else {

        final BigInteger integer = value.toJavaBigDecimal().unscaledValue();
        byte[] bytes = integer.toByteArray();
        assert(bytes.length <= 16);

        // Write the bytes to the variable length portion.
        Platform.copyMemory(
          bytes, Platform.BYTE_ARRAY_OFFSET, baseObject, baseOffset + cursor, bytes.length);
        setLong(ordinal, (cursor << 32) | ((long) bytes.length));
      }
    }
  }
111101
private static BigDecimal doAdd(final BigDecimal v1, final BigDecimal v2) {
        BigDecimal total = v1;
        if (v1 != null && v2 != null) {
            total = v1.add(v2);
        } else if (v2 != null) {
            total = v2;
        }
        return total;
    }