Num sq_exp(Num sq) //up > down { int i0, i1 = IDS.sqr_exp_bits; if (sq.down.IsEven && (up.Sign < 0)) IDS.sys.error("exp: neg sqr"); Num res = new Num(1), _sq = new Num(sq), tmp = new Num(1), _t = new Num(this); // (5/11-1/2)*2 = ((5*2-11)/(11*2))*2 BigInteger _ud = up / down; if (_ud > 3) { int l2 = Num._l2(_ud); while (l2 > 1) { _t._sq2_n(tmp, IDS.sqr2[l2]); i0 = IDS.sqr_steps; while (i0-- > 0) _t._sq2_n(tmp, tmp); _sq.up <<= 1; if (_sq.up >= _sq.down) { _sq.up -= _sq.down; res.mul(tmp); } if (_sq.up.IsZero || (i1 < 0)) return res.simple(); _t.up = tmp.up; _t.down = tmp.down; l2 >>= 1; i1--; } } while ((!_sq.up.IsZero) && (i1 > 0)) { tmp.up = _t.up + _t.down; if (tmp.up.IsEven) { tmp.up >>= 1; tmp.down = BigInteger.Abs(_t.down); } else tmp.down = _t.down << 1; i0 = IDS.sqr_steps; while (i0-- > 0) _t._sq2_n(tmp, tmp); _sq.up <<= 1; if (_sq.up >= _sq.down) { _sq.up -= _sq.down; res.mul(tmp); res.prec_this(); } _t.up = tmp.up; _t.down = tmp.down; i1--; } return res.simple(); }