/* Copyright (C) 2015 William Hart Copyright (C) 2015 Fredrik Johansson Copyright (C) 2015 Kushagra Singh This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #define ulong ulongxx /* interferes with system includes */ #include #undef ulong #include "flint.h" #include "ulong_extras.h" mp_limb_t n_cbrt(mp_limb_t n) { int bits; double val, x, xcub, num, den; mp_limb_t ret, upper_limit; /* Taking care of smaller roots */ if (n < 125) return (n >= 1) + (n >= 8) + (n >= 27) + (n >= 64); if (n < 1331) return 5 + (n >= 216) + (n >= 343) + (n >= 512) + (n >= 729) + (n >= 1000); if (n < 4913) return 11 + (n >= 1728) + (n >= 2197) + (n >= 2744) + (n >= 3375) + (n >= 4096); val = (double)n; bits = FLINT_BIT_COUNT(n); if (bits > 46) /* for larger numbers chebyshev approximation method is faster */ return n_cbrt_chebyshev_approx(n); /* upper_limit is the max cube root possible for one word */ #ifdef FLINT64 upper_limit = 2642245; /* 2642245 < (2^64)^(1/3) */ #else upper_limit = 1625; /* 1625 < (2^32)^(1/3) */ #endif x = n_cbrt_estimate((double)n); /* initial estimate */ /* Kahan's iterations to get cube root */ xcub = x * x * x; num = (xcub - val) * x; den = (xcub + xcub + val); x -= (num / den); ret = x; /* In case ret^3 or (ret+1)^3 will cause overflow */ if (ret >= upper_limit) { if (n >= upper_limit * upper_limit * upper_limit) return upper_limit; ret = upper_limit - 1; } while (ret * ret * ret <= n) { (ret) += 1; if (ret == upper_limit) break; } while (ret * ret * ret > n) (ret) -= 1; return ret; }