1 /* specfunc/transport.c
3 * Copyright (C) 1996, 1997, 1998, 1999, 2000 Gerard Jungman
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or (at
8 * your option) any later version.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 /* Author: G. Jungman */
23 #include <gsl/gsl_math.h>
24 #include <gsl/gsl_errno.h>
25 #include <gsl/gsl_sf_transport.h>
30 #include "chebyshev.h"
31 #include "cheb_eval.c"
33 static double transport2_data[18] = {
35 -0.147735359946794490,
36 0.148213819946936338e-01,
37 -0.14195330326305613e-02,
38 0.1306541324415708e-03,
39 -0.117155795867579e-04,
53 static cheb_series transport2_cs = {
60 static double transport3_data[18] = {
62 -0.105674387705058533,
63 0.119778084819657810e-01,
64 -0.12144015203698307e-02,
65 0.1155099769392855e-03,
66 -0.105815992124423e-04,
80 static cheb_series transport3_cs = {
88 static double transport4_data[18] = {
89 0.4807570994615110579,
90 -0.8175378810321083956e-01,
91 0.1002700665975162973e-01,
92 -0.10599339359820151e-02,
93 0.1034506245030405e-03,
94 -0.96442705485899e-05,
108 static cheb_series transport4_cs = {
116 static double transport5_data[18] = {
117 0.347777777133910789,
118 -0.66456988976050428e-01,
119 0.8611072656883309e-02,
120 -0.9396682223755538e-03,
121 0.936324806081513e-04,
122 -0.88571319340833e-05,
136 static cheb_series transport5_cs = {
146 transport_sumexp(const int numexp, const int order, const double t, double x)
148 double rk = (double)numexp;
151 for(k=1; k<=numexp; k++) {
153 double xk = 1.0/(rk*x);
156 for(j=1; j<=order; j++) {
157 sum2 = sum2*xk1*xk + 1.0;
168 /*-*-*-*-*-*-*-*-*-*-*-* Functions with Error Codes *-*-*-*-*-*-*-*-*-*-*-*/
171 gsl_sf_transport_2_e(const double x, gsl_sf_result * result)
173 const double val_infinity = 3.289868133696452873;
175 /* CHECK_POINTER(result) */
178 DOMAIN_ERROR(result);
180 else if(x < 3.0*GSL_SQRT_DBL_EPSILON) {
182 result->err = GSL_DBL_EPSILON*fabs(x) + x*x/2.0;
186 double t = (x*x/8.0 - 0.5) - 0.5;
187 gsl_sf_result result_c;
188 cheb_eval_e(&transport2_cs, t, &result_c);
189 result->val = x * result_c.val;
190 result->err = x * result_c.err;
191 result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);
194 else if(x < -GSL_LOG_DBL_EPSILON) {
195 const int numexp = (int)((-GSL_LOG_DBL_EPSILON)/x) + 1;
196 const double sumexp = transport_sumexp(numexp, 2, exp(-x), x);
197 const double t = 2.0 * log(x) - x + log(sumexp);
198 if(t < GSL_LOG_DBL_EPSILON) {
199 result->val = val_infinity;
200 result->err = 2.0 * GSL_DBL_EPSILON * val_infinity;
203 const double et = exp(t);
204 result->val = val_infinity - et;
205 result->err = 2.0 * GSL_DBL_EPSILON * (val_infinity + fabs(t) * et);
209 else if(x < 2.0/GSL_DBL_EPSILON) {
210 const int numexp = 1;
211 const double sumexp = transport_sumexp(numexp, 2, 1.0, x);
212 const double t = 2.0 * log(x) - x + log(sumexp);
213 if(t < GSL_LOG_DBL_EPSILON) {
214 result->val = val_infinity;
215 result->err = 2.0 * GSL_DBL_EPSILON * val_infinity;
218 const double et = exp(t);
219 result->val = val_infinity - et;
220 result->err = 2.0 * GSL_DBL_EPSILON * (val_infinity + (fabs(t)+1.0) * et);
225 const double t = 2.0 * log(x) - x;
226 if(t < GSL_LOG_DBL_EPSILON) {
227 result->val = val_infinity;
228 result->err = 2.0 * GSL_DBL_EPSILON * val_infinity;
231 const double et = exp(t);
232 result->val = val_infinity - et;
233 result->err = 2.0 * GSL_DBL_EPSILON * (val_infinity + (fabs(t)+1.0) * et);
241 gsl_sf_transport_3_e(const double x, gsl_sf_result * result)
243 const double val_infinity = 7.212341418957565712;
245 /* CHECK_POINTER(result) */
248 DOMAIN_ERROR(result);
255 else if(x < 3.0*GSL_SQRT_DBL_EPSILON) {
256 result->val = 0.5*x*x;
257 result->err = 2.0 * GSL_DBL_EPSILON * result->val;
258 CHECK_UNDERFLOW(result);
262 const double x2 = x*x;
263 const double t = (x2/8.0 - 0.5) - 0.5;
264 gsl_sf_result result_c;
265 cheb_eval_e(&transport3_cs, t, &result_c);
266 result->val = x2 * result_c.val;
267 result->err = x2 * result_c.err;
268 result->err += GSL_DBL_EPSILON * fabs(result->val);
271 else if(x < -GSL_LOG_DBL_EPSILON) {
272 const int numexp = (int)((-GSL_LOG_DBL_EPSILON)/x) + 1;
273 const double sumexp = transport_sumexp(numexp, 3, exp(-x), x);
274 const double t = 3.0 * log(x) - x + log(sumexp);
275 if(t < GSL_LOG_DBL_EPSILON) {
276 result->val = val_infinity;
277 result->err = 2.0 * GSL_DBL_EPSILON * val_infinity;
280 const double et = exp(t);
281 result->val = val_infinity - et;
282 result->err = 2.0 * GSL_DBL_EPSILON * (val_infinity + fabs(t) * et);
286 else if(x < 3.0/GSL_DBL_EPSILON) {
287 const int numexp = 1;
288 const double sumexp = transport_sumexp(numexp, 3, 1.0, x);
289 const double t = 3.0 * log(x) - x + log(sumexp);
290 if(t < GSL_LOG_DBL_EPSILON) {
291 result->val = val_infinity;
292 result->err = 2.0 * GSL_DBL_EPSILON * val_infinity;
295 const double et = exp(t);
296 result->val = val_infinity - et;
297 result->err = 2.0 * GSL_DBL_EPSILON * (val_infinity + (fabs(t)+1.0) * et);
302 const double t = 3.0 * log(x) - x;
303 if(t < GSL_LOG_DBL_EPSILON) {
304 result->val = val_infinity;
305 result->err = 2.0 * GSL_DBL_EPSILON * val_infinity;
308 const double et = exp(t);
309 result->val = val_infinity - et;
310 result->err = 2.0 * GSL_DBL_EPSILON * (val_infinity + (fabs(t)+1.0) * et);
318 gsl_sf_transport_4_e(const double x, gsl_sf_result * result)
320 const double val_infinity = 25.97575760906731660;
322 /* CHECK_POINTER(result) */
325 DOMAIN_ERROR(result);
332 else if(x < 3.0*GSL_SQRT_DBL_EPSILON) {
333 result->val = x*x*x/3.0;
334 result->err = 3.0 * GSL_DBL_EPSILON * result->val;
335 CHECK_UNDERFLOW(result);
339 const double x2 = x*x;
340 const double t = (x2/8.0 - 0.5) - 0.5;
341 gsl_sf_result result_c;
342 cheb_eval_e(&transport4_cs, t, &result_c);
343 result->val = x2*x * result_c.val;
344 result->err = x2*x * result_c.err;
345 result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);
348 else if(x < -GSL_LOG_DBL_EPSILON) {
349 const int numexp = (int)((-GSL_LOG_DBL_EPSILON)/x) + 1;
350 const double sumexp = transport_sumexp(numexp, 4, exp(-x), x);
351 const double t = 4.0 * log(x) - x + log(sumexp);
352 if(t < GSL_LOG_DBL_EPSILON) {
353 result->val = val_infinity;
354 result->err = 2.0 * GSL_DBL_EPSILON * val_infinity;
357 const double et = exp(t);
358 result->val = val_infinity - et;
359 result->err = 2.0 * GSL_DBL_EPSILON * (val_infinity + (fabs(t)+1.0) * et);
363 else if(x < 3.0/GSL_DBL_EPSILON) {
364 const int numexp = 1;
365 const double sumexp = transport_sumexp(numexp, 4, 1.0, x);
366 const double t = 4.0 * log(x) - x + log(sumexp);
367 if(t < GSL_LOG_DBL_EPSILON) {
368 result->val = val_infinity;
369 result->err = 2.0 * GSL_DBL_EPSILON * val_infinity;
372 const double et = exp(t);
373 result->val = val_infinity - et;
374 result->err = 2.0 * GSL_DBL_EPSILON * (val_infinity + (fabs(t)+1.0) * et);
379 const double t = 4.0 * log(x) - x;
380 if(t < GSL_LOG_DBL_EPSILON) {
381 result->val = val_infinity;
382 result->err = 2.0 * GSL_DBL_EPSILON * val_infinity;
385 const double et = exp(t);
386 result->val = val_infinity - et;
387 result->err = 2.0 * GSL_DBL_EPSILON * (val_infinity + (fabs(t)+1.0) * et);
395 gsl_sf_transport_5_e(const double x, gsl_sf_result * result)
397 const double val_infinity = 124.4313306172043912;
399 /* CHECK_POINTER(result) */
402 DOMAIN_ERROR(result);
409 else if(x < 3.0*GSL_SQRT_DBL_EPSILON) {
410 result->val = x*x*x*x/4.0;
411 result->err = 4.0 * GSL_DBL_EPSILON * result->val;
412 CHECK_UNDERFLOW(result);
416 const double x2 = x*x;
417 const double t = (x2/8.0 - 0.5) - 0.5;
418 gsl_sf_result result_c;
419 cheb_eval_e(&transport5_cs, t, &result_c);
420 result->val = x2*x2 * result_c.val;
421 result->err = x2*x2 * result_c.err;
422 result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);
425 else if(x < -GSL_LOG_DBL_EPSILON) {
426 const int numexp = (int)((-GSL_LOG_DBL_EPSILON)/x) + 1;
427 const double sumexp = transport_sumexp(numexp, 5, exp(-x), x);
428 const double t = 5.0 * log(x) - x + log(sumexp);
429 if(t < GSL_LOG_DBL_EPSILON) {
430 result->val = val_infinity;
431 result->err = 2.0 * GSL_DBL_EPSILON * val_infinity;
434 const double et = exp(t);
435 result->val = val_infinity - et;
436 result->err = 2.0 * GSL_DBL_EPSILON * (val_infinity + (fabs(t)+1.0) * et);
440 else if(x < 3.0/GSL_DBL_EPSILON) {
441 const int numexp = 1;
442 const double sumexp = transport_sumexp(numexp, 5, 1.0, x);
443 const double t = 5.0 * log(x) - x + log(sumexp);
444 if(t < GSL_LOG_DBL_EPSILON) {
445 result->val = val_infinity;
446 result->err = 2.0 * GSL_DBL_EPSILON * val_infinity;
449 const double et = exp(t);
450 result->val = val_infinity - et;
451 result->err = 2.0 * GSL_DBL_EPSILON * (val_infinity + (fabs(t)+1.0) * et);
456 const double t = 5.0 * log(x) - x;
457 if(t < GSL_LOG_DBL_EPSILON) {
458 result->val = val_infinity;
459 result->err = 2.0 * GSL_DBL_EPSILON * val_infinity;
462 const double et = exp(t);
463 result->val = val_infinity - et;
464 result->err = 2.0 * GSL_DBL_EPSILON * (val_infinity + (fabs(t)+1.0) * et);
470 /*-*-*-*-*-*-*-*-*-* Functions w/ Natural Prototypes *-*-*-*-*-*-*-*-*-*-*/
474 double gsl_sf_transport_2(const double x)
476 EVAL_RESULT(gsl_sf_transport_2_e(x, &result));
479 double gsl_sf_transport_3(const double x)
481 EVAL_RESULT(gsl_sf_transport_3_e(x, &result));
484 double gsl_sf_transport_4(const double x)
486 EVAL_RESULT(gsl_sf_transport_4_e(x, &result));
489 double gsl_sf_transport_5(const double x)
491 EVAL_RESULT(gsl_sf_transport_5_e(x, &result));