docs: public static BigDecimal root(BigDecimal x, BigDecimal n, MathContext mathContext) {
  		checkMathContext(mathContext);
  		switch (x.signum()) {
  		case 0:
  			return ZERO;
  		case -1:
  			throw new ArithmeticException("Illegal root(x) for x < 0: x = " + x);
  		}
  
  		if (n.compareTo(BigDecimal.ONE) <= 0) {
  			MathContext mc = new MathContext(mathContext.getPrecision() + 6, mathContext.getRoundingMode());
  			return pow(x, BigDecimal.ONE.divide(n, mc), mathContext);
  		}
  		
  		int maxPrecision = mathContext.getPrecision() + 4;
  		BigDecimal acceptableError = ONE.movePointLeft(mathContext.getPrecision() + 1);
  
  		BigDecimal nMinus1 = n.subtract(ONE);
  		BigDecimal result = x.divide(TWO, MathContext.DECIMAL32);
  		int adaptivePrecision = 2; // first approximation has really bad precision
  		BigDecimal step;
  
  		do {
  			adaptivePrecision = adaptivePrecision * 3;
  			if (adaptivePrecision > maxPrecision) {
  				adaptivePrecision = maxPrecision;
  			}
  			MathContext mc = new MathContext(adaptivePrecision, mathContext.getRoundingMode());
  			
  			step = x.divide(pow(result, nMinus1, mc), mc).subtract(result, mc).divide(n, mc);
  			result = result.add(step, mc);
  		} while (adaptivePrecision < maxPrecision || step.abs().compareTo(acceptableError) > 0);
  
  		return round(result, mathContext);
  	}