Skip to content

Instantly share code, notes, and snippets.

@rygorous
Created May 23, 2019 17:06
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rygorous/68e3d59ea4bdb9a5813812fdde314d0c to your computer and use it in GitHub Desktop.
Save rygorous/68e3d59ea4bdb9a5813812fdde314d0c to your computer and use it in GitHub Desktop.
Fifth root for doubles.
static double
fifth_root_pos_finite(double x)
{
static const double fifth_roots_pow2[9] = { // 2^((i-4)/5)
0.57434917749851754908974044155911542475223541259766,
0.65975395538644709958475687017198652029037475585937,
0.75785828325519899451023775327485054731369018554687,
0.87055056329612412469032278750091791152954101562500,
1.00000000000000000000000000000000000000000000000000,
1.14869835499703509817948088311823084950447082519530,
1.31950791077289419916951374034397304058074951171875,
1.51571656651039798902047550654970109462738037109375,
1.74110112659224824938064557500183582305908203125000,
};
double z = x;
int e, new_e;
if (x == 0.0)
return x;
// extract power of 2, reducing mantissa to [0.5,1)
x = frexp(x, &e);
// Approximate fifth root of number in [0.5,1), relative error below 7.78e-6
x = 0.59493167584123773927728962007677182555198669433594 + x *
( 0.84132549636479991850279702703119255602359771728516 + x *
(-0.7812833955684315156986485817469656467437744140625 + x *
( 0.45952167932621135193471673119347542524337768554687 + x *
(-0.114503232341356855905623035596363479271531105041504))));
// adjustment based on exponent%5 (covers both positive and negative exponent range)
new_e = e/5;
x *= fifth_roots_pow2[e - new_e*5 + 4];
// multiply by power of 2
x = ldexp(x, new_e);
// refine via Newton
x -= (x - (z / (x*x*x*x))) * 0.2;
x -= (x - (z / (x*x*x*x))) * 0.2;
return x;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment