/*
This file is part of liberferfc.
Copyright 2009-2010 by
Laboratoire de l'Informatique du Parallélisme, UMR CNRS - ENS Lyon -
UCB Lyon 1 - INRIA 5668,
and by LORIA (CNRS, INPL, INRIA, UHP, U-Nancy 2).
It has been written by S. Chevillard.
Liberferfc is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
Liberferfc is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with liberferfc. If not, see .
*/
#include
#include "erferfc_utils.h"
/* Multiplication by a double. This function is useless with */
/* MPFR > 2.4 since there exists now a function mpfr_mul_d. However */
/* we provide an implementation for compatibility reasons. */
int mpfr_my_mul_d(mpfr_t rop, mpfr_t op, double a, mpfr_rnd_t rnd) {
mpfr_t op2;
int r;
mpfr_init2(op2, 53);
ASSERT(mpfr_set_d(op2, a, MPFR_RNDN)==0);
r = mpfr_mul(rop, op, op2, rnd);
mpfr_clear(op2);
return r;
}
/* Computes an approximate value of x^N and store it in variable y. */
/* The precision used during the computation is the precision of y. */
/* All the computations are performed with rounding mode rnd. */
/* The algorithm is based on the following remarks. */
/* Let (bn ... b1 b0) be the binary development of N. */
/* Hence x^N = x^(sum_{k=0}^n bk*2^{k}) */
/* = prod_{k such that bk==1} x^{2^k} */
/* The bits bi are explored from b0 to bn. */
/* The variable pow is used to store the current x^{2^k} and the */
/* variable res is used to store the partial product. */
int binaryPow(mpfr_t y, mpfr_t x, unsigned long int N, mpfr_rnd_t rnd) {
mpfr_t pow, res;
mpfr_prec_t prec;
int i;
i = N;
prec = mpfr_get_prec(y);
mpfr_init2(pow, prec);
mpfr_init2(res, prec);
mpfr_set(pow, x, rnd);
mpfr_set_d(res, 1, rnd);
while(i!=0) {
/* Loop invariants: pow ~ x^(2^(N-i)) */
if ((i%2)==1) mpfr_mul(res, res, pow, rnd);
i = i/2;
mpfr_sqr(pow, pow, rnd);
}
mpfr_set(y, res, rnd);
mpfr_clear(pow);
mpfr_clear(res);
return 0;
}