BigFloat invsqrt(uint32_t x,size_t p,int tds){ // Compute inverse square root using Newton's Method. // ( r0^2 * x - 1 ) // r1 = r0 - (----------------) * r0 // ( 2 ) if (x == 0) throw "Divide by Zero"; // End of recursion. Generate starting point. if (p == 0){ double val = 1. / sqrt((double)x); int64_t exponent = 0; // Scale while (val < 1000000000.){ val *= 1000000000.; exponent--; } // Rebuild a BigFloat. uint64_t val64 = (uint64_t)val; BigFloat out; out.sign = true; out.T = std::unique_ptr<uint32_t[]>(new uint32_t[2]); out.T[0] = (uint32_t)(val64 % 1000000000); out.T[1] = (uint32_t)(val64 / 1000000000); out.L = 2; out.exp = exponent; return out; } // Half the precision size_t s = p / 2 + 1; if (p == 1) s = 0; if (p == 2) s = 1; // Recurse at half the precision BigFloat T = invsqrt(x,s,tds); BigFloat temp = T.mul(T,p); // r0^2 temp = temp.mul(x,p,tds); // r0^2 * x temp = temp.sub(BigFloat(1),p); // r0^2 * x - 1 temp = temp.mul(500000000); // (r0^2 * x - 1) / 2 temp.exp--; temp = temp.mul(T,p,tds); // (r0^2 * x - 1) / 2 * r0 return T.sub(temp,p); // r0 - (r0^2 * x - 1) / 2 * r0 }
BigFloat BigFloat::rcp(size_t p,int tds) const{ // Compute reciprocal using Newton's Method. // r1 = r0 - (r0 * x - 1) * r0 if (L == 0) throw "Divide by Zero"; // Collect operand int64_t Aexp = exp; size_t AL = L; uint32_t *AT = T.get(); // End of recursion. Generate starting point. if (p == 0){ // Truncate precision to 3. p = 3; if (AL > p){ size_t chop = AL - p; AL = p; Aexp += chop; AT += chop; } // Convert number to floating-point. double val = AT[0]; if (AL >= 2) val += AT[1] * 1000000000.; if (AL >= 3) val += AT[2] * 1000000000000000000.; // Compute reciprocal. val = 1. / val; Aexp = -Aexp; // Scale while (val < 1000000000.){ val *= 1000000000.; Aexp--; } // Rebuild a BigFloat. uint64_t val64 = (uint64_t)val; BigFloat out; out.sign = sign; out.T = std::unique_ptr<uint32_t[]>(new uint32_t[2]); out.T[0] = (uint32_t)(val64 % 1000000000); out.T[1] = (uint32_t)(val64 / 1000000000); out.L = 2; out.exp = Aexp; return out; } // Half the precision size_t s = p / 2 + 1; if (p == 1) s = 0; if (p == 2) s = 1; // Recurse at half the precision BigFloat T = rcp(s,tds); // r1 = r0 - (r0 * x - 1) * r0 return T.sub(this->mul(T,p,tds).sub(BigFloat(1),p).mul(T,p,tds),p); }