- // Need a precision of ((1+sqrt(5))/2)^-n.
- cl_float_format_t prec = ::cl_float_format((int)(0.208987641*nn+5));
- cl_R sqrt5 = ::sqrt(::cl_float(5,prec));
- cl_R phi = (1+sqrt5)/2;
- return numeric(::round1(::expt(phi,nn)/sqrt5)*sig);
+ cl_I u(0);
+ cl_I v(1);
+ cl_I m = The(cl_I)(*n.value) >> 1L; // floor(n/2);
+ for (uintL bit=::integer_length(m); bit>0; --bit) {
+ // Since a squaring is cheaper than a multiplication, better use
+ // three squarings instead of one multiplication and two squarings.
+ cl_I u2 = ::square(u);
+ cl_I v2 = ::square(v);
+ if (::logbitp(bit-1, m)) {
+ v = ::square(u + v) - u2;
+ u = u2 + v2;
+ } else {
+ u = v2 - ::square(v - u);
+ v = u2 + v2;
+ }
+ }
+ if (n.is_even())
+ // Here we don't use the squaring formula because one multiplication
+ // is cheaper than two squarings.
+ return u * ((v << 1) - u);
+ else
+ return ::square(u) + ::square(v);