From fa9b6f2b9bcb80778e63ef2aa4e17c7573de0015 Mon Sep 17 00:00:00 2001 From: Ian Jauslin Date: Tue, 24 May 2016 13:39:23 +0000 Subject: Initial commit --- src/hh_integral.c | 276 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 276 insertions(+) create mode 100644 src/hh_integral.c (limited to 'src/hh_integral.c') diff --git a/src/hh_integral.c b/src/hh_integral.c new file mode 100644 index 0000000..f8eda10 --- /dev/null +++ b/src/hh_integral.c @@ -0,0 +1,276 @@ +/* +Copyright 2016 Ian Jauslin + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#include "hh_integral.h" + +#include +// define MPFR_USE_VA_LIST to enable the use of mpfr_inits and mpfr_clears +#define MPFR_USE_VA_LIST +#include +#include + +int hh_integrate(mpfr_t* out, hh_params params, array_mpfr abcissa, array_mpfr weights){ + mpfr_t lower, upper; + // arguments for first integral + hh_argsint1 args1; + int ret; + + args1.params=params; + args1.abcissa=abcissa; + args1.weights=weights; + + mpfr_inits(lower, upper, NULL); + + // compute the boundaries of the integral over theta + // pi/6 + mpfr_const_pi(upper, MPFR_RNDN); + mpfr_div_ui(upper, upper, 6, MPFR_RNDN); + // -pi/6 + mpfr_neg(lower, upper, MPFR_RNDN); + + // integrate + ret=integrate_gauss_mpfr(out, &hh_integrand1, lower, upper, abcissa, weights, &args1); + + mpfr_clears(lower, upper, NULL); + + return(ret); +} + +// integrand of the integral over theta +int hh_integrand1(mpfr_t* out, mpfr_t theta, void* args){ + hh_argsint2 args2; + mpfr_t lower, upper; + int ret; + + mpfr_inits(upper, lower, NULL); + + // recover parameters + args2.params=((hh_argsint1*)args)->params; + args2.theta=theta; + + // boundaries of the integral over rho + // 1/cos(theta-pi/6) + mpfr_const_pi(upper, MPFR_RNDN); + mpfr_div_ui(upper, upper, 6, MPFR_RNDN); + mpfr_sub(upper, theta, upper, MPFR_RNDN); + mpfr_cos(upper, upper, MPFR_RNDN); + mpfr_ui_div(upper, 1, upper, MPFR_RNDN); + + // 0 + mpfr_set_ui(lower, 0, MPFR_RNDN); + + ret=integrate_gauss_mpfr(out, &hh_integrand2, lower, upper, ((hh_argsint1*)args)->abcissa, ((hh_argsint1*)args)->weights, &args2); + + mpfr_clears(upper, lower, NULL); + + return(ret); +} + +// integrand of the integral over rho +int hh_integrand2(mpfr_t* out, mpfr_t rho, void* args){ + mpfr_t tmp1, tmp2, tmp3; + + mpfr_inits(tmp1, tmp2, tmp3, NULL); + + // out = Omega^2 + // tmp1 = alpha2 + hh_Omega2_alpha2(*out, tmp1, rho, ((hh_argsint2*)args)->theta, tmp2, tmp3); + // tmp1 = m + hh_m(tmp1, ((hh_argsint2*)args)->params.W, ((hh_argsint2*)args)->params.t2, ((hh_argsint2*)args)->params.sinphi, tmp1); + // out = xi^2 + hh_xi2(*out, *out, tmp1, ((hh_argsint2*)args)->params.t1, tmp2); + + // out = rho/sqrt(xi^2)*m + mpfr_sqrt(*out, *out, MPFR_RNDN); + mpfr_div(*out, rho, *out, MPFR_RNDN); + mpfr_mul(*out, *out, tmp1, MPFR_RNDN); + + mpfr_clears(tmp1, tmp2, tmp3, NULL); + + return(0); +} + +// derivative +int hh_d_integrate(mpfr_t* out, hh_params params, array_mpfr abcissa, array_mpfr weights){ + mpfr_t lower, upper; + // arguments for first integral + hh_argsint1 args1; + int ret; + + args1.params=params; + args1.abcissa=abcissa; + args1.weights=weights; + + mpfr_inits(lower, upper, NULL); + + // compute the boundaries of the integral over theta + // pi/6 + mpfr_const_pi(upper, MPFR_RNDN); + mpfr_div_ui(upper, upper, 6, MPFR_RNDN); + // -pi/6 + mpfr_neg(lower, upper, MPFR_RNDN); + + // integrate + ret=integrate_gauss_mpfr(out, &hh_d_integrand1, lower, upper, abcissa, weights, &args1); + + mpfr_clears(lower, upper, NULL); + + return(ret); +} + +// derivative of the integrand of the integral over theta +int hh_d_integrand1(mpfr_t* out, mpfr_t theta, void* args){ + hh_argsint2 args2; + mpfr_t lower, upper; + int ret; + + mpfr_inits(lower, upper, NULL); + + // recover parameters + args2.params=((hh_argsint1*)args)->params; + args2.theta=theta; + + // boundaries of the integral over rho + // 1/cos(theta-pi/6) + mpfr_const_pi(upper, MPFR_RNDN); + mpfr_div_ui(upper, upper, 6, MPFR_RNDN); + mpfr_sub(upper, theta, upper, MPFR_RNDN); + mpfr_cos(upper, upper, MPFR_RNDN); + mpfr_ui_div(upper, 1, upper, MPFR_RNDN); + + // 0 + mpfr_set_ui(lower, 0, MPFR_RNDN); + + ret=integrate_gauss_mpfr(out, &hh_d_integrand2, lower, upper, ((hh_argsint1*)args)->abcissa, ((hh_argsint1*)args)->weights, &args2); + + mpfr_clears(lower, upper, NULL); + + return(ret); +} + +// derivative of the integrand of the integral over rho +int hh_d_integrand2(mpfr_t* out, mpfr_t rho, void* args){ + mpfr_t tmp1, tmp2, tmp3; + + mpfr_inits(tmp1, tmp2, tmp3, NULL); + + // out = Omega^2 + // tmp1 = alpha2 + hh_Omega2_alpha2(*out, tmp1, rho, ((hh_argsint2*)args)->theta, tmp2, tmp3); + // tmp1 = m + hh_m(tmp1, ((hh_argsint2*)args)->params.W, ((hh_argsint2*)args)->params.t2, ((hh_argsint2*)args)->params.sinphi, tmp1); + // out = xi^2 + hh_xi2(*out, *out, tmp1, ((hh_argsint2*)args)->params.t1, tmp2); + + // tmp2 = 1-m^2/xi^2 + mpfr_pow_ui(tmp2, tmp1, 2,MPFR_RNDN); + mpfr_div(tmp2, tmp2, *out, MPFR_RNDN); + mpfr_ui_sub(tmp2, 1, tmp2, MPFR_RNDN); + + // out = rho/sqrt(xi^2)*(1-m^2/xi^2) + mpfr_sqrt(*out, *out, MPFR_RNDN); + mpfr_div(*out, rho, *out, MPFR_RNDN); + mpfr_mul(*out, *out, tmp2, MPFR_RNDN); + + mpfr_clears(tmp1, tmp2, tmp3, NULL); + + return(0); +} + +// Omega^2 and alpha_2 +// provide two initialized tmp mpfr_t's +// Omega2 and alpha2 must be initialized +int hh_Omega2_alpha2(mpfr_t Omega2, mpfr_t alpha2, mpfr_t rho, mpfr_t theta, mpfr_t tmp1, mpfr_t tmp2){ + // Omega2 and alpha2 will be used as tmp variables whenever possible + + // Omega2 = pi + mpfr_const_pi(Omega2, MPFR_RNDN); + + // tmp1 = pi/sqrt(3)*rho + mpfr_sqrt_ui(tmp1, 3, MPFR_RNDN); + mpfr_div(tmp1, Omega2, tmp1, MPFR_RNDN); + mpfr_mul(tmp1, tmp1, rho, MPFR_RNDN); + + // alpha2 = cos(theta) + mpfr_cos(alpha2, theta, MPFR_RNDN); + + // tmp1 = cos(pi/sqrt(3)*rho*cos(theta)) + mpfr_mul(tmp1, tmp1, alpha2, MPFR_RNDN); + //// alpha2 free + mpfr_cos(tmp1, tmp1, MPFR_RNDN); + + // alpha2 = pi/3*(1+rho*sin(theta)) + mpfr_sin(alpha2, theta, MPFR_RNDN); + mpfr_mul(alpha2, alpha2, rho, MPFR_RNDN); + mpfr_add_ui(alpha2, alpha2, 1, MPFR_RNDN); + mpfr_div_ui(alpha2, alpha2, 3, MPFR_RNDN); + mpfr_mul(alpha2, alpha2, Omega2, MPFR_RNDN); + //// Omega2 free + + // Omega2 = cos(pi/3*(1+rho*sin(theta))) + mpfr_cos(Omega2, alpha2, MPFR_RNDN); + + // tmp2 = sin(pi/3*(1+rho*sin(theta))) + mpfr_sin(tmp2, alpha2, MPFR_RNDN); + //// alpha2 free + + // alpha2 = -2*sin(pi/3*(1+rho*sin(theta)))*(cos(pi/3*(1+rho*sin(theta)))+cos(pi/sqrt(3)*rho*cos(theta))) + mpfr_add(alpha2, Omega2, tmp1, MPFR_RNDN); + mpfr_mul(alpha2, alpha2, tmp2, MPFR_RNDN); + //// tmp2 free + mpfr_mul_si(alpha2, alpha2, -2, MPFR_RNDN); + + // tmp1 = cos(pi/3*(1+rho*sin(theta)))-cos(pi/sqrt(3)*rho*cos(theta)) + mpfr_sub(tmp1, Omega2, tmp1, MPFR_RNDN); + // Omega2 = 1+4*cos(pi/3*(1+rho*sin(theta)))*(cos(pi/3*(1+rho*sin(theta)))-cos(pi/sqrt(3)*rho*cos(theta))) + mpfr_mul(Omega2, Omega2, tmp1, MPFR_RNDN); + //// tmp1 free + mpfr_mul_ui(Omega2, Omega2, 4, MPFR_RNDN); + mpfr_add_ui(Omega2, Omega2, 1, MPFR_RNDN); + + return(0); +} + +// m +// out must be initialized +// out and alpha2 can point to the same number +int hh_m(mpfr_t out, mpfr_t W, mpfr_t t2, mpfr_t sinphi, mpfr_t alpha2){ + // out = W-2*t2*sinphi*alpha2 + mpfr_mul(out, alpha2, sinphi, MPFR_RNDN); + mpfr_mul(out, out, t2, MPFR_RNDN); + mpfr_mul_ui(out, out, 2, MPFR_RNDN); + mpfr_sub(out, W, out, MPFR_RNDN); + return(0); +} + +// xi^2 +// provide one initialized tmp mpfr_t +// out must be initialized +// out and Omega2 can point to the same number +// tmp and m can point to the same number +int hh_xi2(mpfr_t out, mpfr_t Omega2, mpfr_t m, mpfr_t t1, mpfr_t tmp){ + // out = t1^2*Omega^2 + mpfr_mul(out, Omega2, t1, MPFR_RNDN); + mpfr_mul(out, out, t1, MPFR_RNDN); + + // tmp = m^2 + mpfr_pow_ui(tmp, m, 2, MPFR_RNDN); + + // out = m^2+t1^2*Omega^2 + mpfr_add(out, out, tmp, MPFR_RNDN); + + return(0); +} -- cgit v1.2.3-54-g00ecf