1
/* This file is a collection of wrappers around the
2
* Specfun Fortran library of functions
5
#include "specfun_wrappers.h"
8
#define CADDR(z) (double *)(&((z).real)), (double*)(&((z).imag))
9
#define F2C_CST(z) (double *)&((z)->real), (double *)&((z)->imag)
11
#if defined(NO_APPEND_FORTRAN)
12
#if defined(UPPERCASE_FORTRAN)
18
#if defined(UPPERCASE_FORTRAN)
19
#define F_FUNC(f,F) F##_
21
#define F_FUNC(f,F) f##_
25
extern double psi(double);
26
extern double struve(double, double);
28
extern void F_FUNC(cgama,CGAMA)(double*,double*,int*,double*,double*);
29
extern void F_FUNC(cpsi,CPSI)(double*,double*,double*,double*);
30
extern void F_FUNC(hygfz,HYGFZ)(double*,double*,double*,Py_complex*,Py_complex*);
31
extern void F_FUNC(cchg,CCHG)(double*,double*,Py_complex*,Py_complex*);
32
extern void F_FUNC(chgu,CHGU)(double*,double*,double*,double*,int*);
33
extern void F_FUNC(itairy,ITAIRY)(double*,double*,double*,double*,double*);
34
extern void F_FUNC(e1xb,E1XB)(double*,double*);
35
extern void F_FUNC(e1z,E1Z)(Py_complex*,Py_complex*);
36
extern void F_FUNC(eix,EIX)(double*,double*);
37
extern void F_FUNC(cerror,CERROR)(Py_complex*,Py_complex*);
38
extern void F_FUNC(stvh0,STVH0)(double*,double*);
39
extern void F_FUNC(stvh1,STVH1)(double*,double*);
40
extern void F_FUNC(stvhv,STVHV)(double*,double*,double*);
41
extern void F_FUNC(stvl0,STVL0)(double*,double*);
42
extern void F_FUNC(stvl1,STVL1)(double*,double*);
43
extern void F_FUNC(stvlv,STVLV)(double*,double*,double*);
44
extern void F_FUNC(itsh0,ITSH0)(double*,double*);
45
extern void F_FUNC(itth0,ITTH0)(double*,double*);
46
extern void F_FUNC(itsl0,ITSL0)(double*,double*);
47
extern void F_FUNC(klvna,KLVNA)(double*,double*,double*,double*,double*,double*,double*,double*,double*);
48
extern void F_FUNC(itjya,ITJYA)(double*,double*,double*);
49
extern void F_FUNC(ittjya,ITTJYA)(double*,double*,double*);
50
extern void F_FUNC(itika,ITIKA)(double*,double*,double*);
51
extern void F_FUNC(ittika,ITTIKA)(double*,double*,double*);
52
extern void F_FUNC(cfc,CFC)(Py_complex*,Py_complex*,Py_complex*);
53
extern void F_FUNC(cfs,CFS)(Py_complex*,Py_complex*,Py_complex*);
54
extern void F_FUNC(cva2,CVA2)(int*,int*,double*,double*);
55
extern void F_FUNC(mtu0,MTU0)(int*,int*,double*,double*,double*,double*);
56
extern void F_FUNC(mtu12,MTU12)(int*,int*,int*,double*,double*,double*,double*,double*,double*);
57
extern void F_FUNC(lpmv,LPMV)(double*,int*,double*,double*);
58
extern void F_FUNC(pbwa,PBWA)(double*,double*,double*,double*,double*,double*);
59
extern void F_FUNC(pbdv,PBDV)(double*,double*,double*,double*,double*,double*);
60
extern void F_FUNC(pbvv,PBVV)(double*,double*,double*,double*,double*,double*);
61
extern void F_FUNC(segv,SEGV)(int*,int*,double*,int*,double*,double*);
62
extern void F_FUNC(aswfa,ASWFA)(int*,int*,double*,double*,int*,double*,double*,double*);
63
extern void F_FUNC(rswfp,RSWFP)(int*,int*,double*,double*,double*,int*,double*,double*,double*,double*);
64
extern void F_FUNC(rswfo,RSWFO)(int*,int*,double*,double*,double*,int*,double*,double*,double*,double*);
65
extern void F_FUNC(ffk,FFK)(int*,double*,double*,double*,double*,double*,double*,double*,double*,double*);
68
/* This must be linked with fortran
71
Py_complex cgamma_wrap( Py_complex z) {
75
F_FUNC(cgama,CGAMA)(CADDR(z), &kf, CADDR(cy));
79
Py_complex clngamma_wrap( Py_complex z) {
83
F_FUNC(cgama,CGAMA)(CADDR(z), &kf, CADDR(cy));
87
Py_complex cpsi_wrap( Py_complex z) {
91
REAL(cy) = psi(REAL(z));
95
F_FUNC(cpsi,CPSI)(CADDR(z), CADDR(cy));
100
Py_complex crgamma_wrap( Py_complex z) {
106
F_FUNC(cgama,CGAMA)(CADDR(z), &kf, CADDR(cy));
108
REAL(cy2) = REAL(cy) / magsq;
109
IMAG(cy2) = -IMAG(cy) / magsq;
113
Py_complex chyp2f1_wrap( double a, double b, double c, Py_complex z) {
118
l0 = ((c == floor(c)) && (c < 0));
119
l1 = ((fabs(1-REAL(z)) < 1e-15) && (IMAG(z) == 0) && (c-a-b <= 0));
121
REAL(outz) = INFINITY;
125
F_FUNC(hygfz, HYGFZ)(&a, &b, &c, &z, &outz);
129
Py_complex chyp1f1_wrap(double a, double b, Py_complex z) {
132
F_FUNC(cchg,CCHG)(&a, &b, &z, &outz);
133
if (REAL(outz) == 1e300) {
134
REAL(outz) = INFINITY;
140
double hypU_wrap(double a, double b, double x) {
142
int md; /* method code --- not returned */
144
F_FUNC(chgu,CHGU)(&a, &b, &x, &out, &md);
145
if (out == 1e300) out = INFINITY;
151
int itairy_wrap(double x, double *apt, double *bpt, double *ant, double *bnt) {
159
F_FUNC(itairy,ITAIRY)(&x, apt, bpt, ant, bnt);
160
if (flag) { /* negative limit -- switch signs and roles */
172
double exp1_wrap(double x) {
175
F_FUNC(e1xb,E1XB)(&x, &out);
180
Py_complex cexp1_wrap(Py_complex z) {
183
F_FUNC(e1z,E1Z)(&z, &outz);
188
double expi_wrap(double x) {
191
F_FUNC(eix,EIX)(&x, &out);
196
Py_complex cerf_wrap(Py_complex z) {
199
F_FUNC(cerror,CERROR)(&z, &outz);
203
double struve_wrap(double v, double x) {
207
if ((v<-8.0) || (v>12.5)) {
208
return struve(v, x); /* from cephes */
211
if (x < 0) {x = -x; flag=1;}
212
F_FUNC(stvh0,STVH0)(&x,&out);
214
if (flag) out = -out;
219
F_FUNC(stvh1,STVH1)(&x,&out);
223
F_FUNC(stvhv,STVHV)(&v,&x,&out);
228
double modstruve_wrap(double v, double x) {
232
if ((x < 0) & (floor(v)!=v)) return NAN;
234
if (x < 0) {x = -x; flag=1;}
235
F_FUNC(stvl0,STVl0)(&x,&out);
237
if (flag) out = -out;
242
F_FUNC(stvl1,STVl1)(&x,&out);
250
F_FUNC(stvlv,STVlV)(&v,&x,&out);
252
if (flag && (!((int)floor(v) % 2))) out = -out;
256
double itstruve0_wrap(double x) {
260
F_FUNC(itsh0,ITSH0)(&x,&out);
265
double it2struve0_wrap(double x) {
269
if (x<0) {x=-x; flag=1;}
270
F_FUNC(itth0,ITTH0)(&x,&out);
278
double itmodstruve0_wrap(double x) {
282
F_FUNC(itsl0,ITSL0)(&x,&out);
288
double ber_wrap(double x)
290
Py_complex Be, Ke, Bep, Kep;
293
F_FUNC(klvna,KLVNA)(&x, CADDR(Be), CADDR(Ke), CADDR(Bep), CADDR(Kep));
298
double bei_wrap(double x)
300
Py_complex Be, Ke, Bep, Kep;
303
F_FUNC(klvna,KLVNA)(&x, CADDR(Be), CADDR(Ke), CADDR(Bep), CADDR(Kep));
308
double ker_wrap(double x)
310
Py_complex Be, Ke, Bep, Kep;
313
F_FUNC(klvna,KLVNA)(&x, CADDR(Be), CADDR(Ke), CADDR(Bep), CADDR(Kep));
318
double kei_wrap(double x)
320
Py_complex Be, Ke, Bep, Kep;
323
F_FUNC(klvna,KLVNA)(&x, CADDR(Be), CADDR(Ke), CADDR(Bep), CADDR(Kep));
328
double berp_wrap(double x)
330
Py_complex Be, Ke, Bep, Kep;
333
if (x<0) {x=-x; flag=1;}
334
F_FUNC(klvna,KLVNA)(&x, CADDR(Be), CADDR(Ke), CADDR(Bep), CADDR(Kep));
336
if (flag) return -REAL(Bep);
340
double beip_wrap(double x)
342
Py_complex Be, Ke, Bep, Kep;
345
if (x<0) {x=-x; flag=1;}
346
F_FUNC(klvna,KLVNA)(&x, CADDR(Be), CADDR(Ke), CADDR(Bep), CADDR(Kep));
348
if (flag) return -IMAG(Bep);
352
double kerp_wrap(double x)
354
Py_complex Be, Ke, Bep, Kep;
357
F_FUNC(klvna,KLVNA)(&x, CADDR(Be), CADDR(Ke), CADDR(Bep), CADDR(Kep));
362
double keip_wrap(double x)
364
Py_complex Be, Ke, Bep, Kep;
367
F_FUNC(klvna,KLVNA)(&x, CADDR(Be), CADDR(Ke), CADDR(Bep), CADDR(Kep));
373
int kelvin_wrap(double x, Py_complex *Be, Py_complex *Ke, Py_complex *Bep, Py_complex *Kep) {
376
if (x<0) {x=-x; flag=1;}
377
F_FUNC(klvna,KLVNA)(&x, F2C_CST(Be), F2C_CST(Ke), F2C_CST(Bep), F2C_CST(Kep));
383
REAL(*Bep) = -REAL(*Bep);
384
IMAG(*Bep) = -IMAG(*Bep);
393
/* Integrals of bessel functions */
395
/* int(j0(t),t=0..x) */
396
/* int(y0(t),t=0..x) */
398
int it1j0y0_wrap(double x, double *j0int, double *y0int)
402
if (x < 0) {x = -x; flag=1;}
403
F_FUNC(itjya, ITJYA)(&x, j0int, y0int);
406
*y0int = NAN; /* domain error */
411
/* int((1-j0(t))/t,t=0..x) */
412
/* int(y0(t)/t,t=x..inf) */
414
int it2j0y0_wrap(double x, double *j0int, double *y0int)
418
if (x < 0) {x=-x; flag=1;}
419
F_FUNC(ittjya, ITTJYA)(&x, j0int, y0int);
421
*y0int = NAN; /* domain error */
426
/* Integrals of modified bessel functions */
428
int it1i0k0_wrap(double x, double *i0int, double *k0int)
432
if (x < 0) {x = -x; flag=1;}
433
F_FUNC(itika, ITIKA)(&x, i0int, k0int);
436
*k0int = NAN; /* domain error */
441
int it2i0k0_wrap(double x, double *i0int, double *k0int)
445
if (x < 0) {x=-x; flag=1;}
446
F_FUNC(ittika, ITTIKA)(&x, i0int, k0int);
448
*k0int = NAN; /* domain error */
454
/* Fresnel integrals of complex numbers */
456
int cfresnl_wrap(Py_complex z, Py_complex *zfs, Py_complex *zfc)
459
F_FUNC(cfs,CFS)(&z,zfs,&zfd);
460
F_FUNC(cfc,CFC)(&z,zfc,&zfd);
464
/* Mathieu functions */
465
/* Characteristic values */
466
double cem_cva_wrap(double m, double q) {
470
if ((m < 0) || (m != floor(m)))
474
F_FUNC(cva2,CVA2)(&kd, &int_m, &q, &out);
478
double sem_cva_wrap(double m, double q) {
482
if ((m < 1) || (m != floor(m)))
486
F_FUNC(cva2,CVA2)(&kd, &int_m, &q, &out);
490
/* Mathieu functions */
491
int cem_wrap(double m, double q, double x, double *csf, double *csd)
494
if ((m < 1) || (m != floor(m)) || (q<0)) {
499
F_FUNC(mtu0,MTU0)(&kf,&int_m, &q, &x, csf, csd);
503
int sem_wrap(double m, double q, double x, double *csf, double *csd)
506
if ((m < 1) || (m != floor(m)) || (q<0)) {
511
F_FUNC(mtu0,MTU0)(&kf,&int_m, &q, &x, csf, csd);
516
int mcm1_wrap(double m, double q, double x, double *f1r, double *d1r)
518
int int_m, kf=1, kc=1;
521
if ((m < 1) || (m != floor(m)) || (q<0)) {
526
F_FUNC(mtu12,MTU12)(&kf,&kc,&int_m, &q, &x, f1r, d1r, &f2r, &d2r);
530
int msm1_wrap(double m, double q, double x, double *f1r, double *d1r)
532
int int_m, kf=2, kc=1;
535
if ((m < 1) || (m != floor(m)) || (q<0)) {
540
F_FUNC(mtu12,MTU12)(&kf,&kc,&int_m, &q, &x, f1r, d1r, &f2r, &d2r);
544
int mcm2_wrap(double m, double q, double x, double *f2r, double *d2r)
546
int int_m, kf=1, kc=2;
549
if ((m < 1) || (m != floor(m)) || (q<0)) {
554
F_FUNC(mtu12,MTU12)(&kf,&kc,&int_m, &q, &x, &f1r, &d1r, f2r, d2r);
558
int msm2_wrap(double m, double q, double x, double *f2r, double *d2r)
560
int int_m, kf=2, kc=2;
563
if ((m < 1) || (m != floor(m)) || (q<0)) {
568
F_FUNC(mtu12,MTU12)(&kf,&kc,&int_m, &q, &x, &f1r, &d1r, f2r, d2r);
573
double pmv_wrap(double m, double v, double x){
577
if (m != floor(m)) return NAN;
579
F_FUNC(lpmv,LPMV)(&v, &int_m, &x, &out);
584
/* if x > 0 return w1f and w1d.
585
otherwise return w2f and w2d (after abs(x))
587
int pbwa_wrap(double a, double x, double *wf, double *wd) {
589
double w1f, w1d, w2f, w2d;
591
if (x < 0) {x=-x; flag=1;}
592
F_FUNC(pbwa,PBWA)(&a, &x, &w1f, &w1d, &w2f, &w2d);
604
int pbdv_wrap(double v, double x, double *pdf, double *pdd) {
610
num = ABS((int) v)+1;
611
dv = (double *)PyMem_Malloc(sizeof(double)*2*num);
613
printf("Warning: Memory allocation error.\n");
619
F_FUNC(pbdv,PBDV)(&v, &x, dv, dp, pdf, pdd);
624
int pbvv_wrap(double v, double x, double *pvf, double *pvd) {
629
num = ABS((int) v)+1;
630
vv = (double *)PyMem_Malloc(sizeof(double)*2*num);
632
printf("Warning: Memory allocation error.\n");
638
F_FUNC(pbvv,PBVV)(&v, &x, vv, vp, pvf, pvd);
643
double prolate_segv_wrap(double m, double n, double c)
649
if ((m<0) || (n<m) || (m!=floor(m)) || (n!=floor(n)) || ((n-m)>198)) {
654
eg = (double *)PyMem_Malloc(sizeof(double)*(n-m+2));
656
printf("Warning: Memory allocation error.\n");
659
F_FUNC(segv,SEGV)(&int_m,&int_n,&c,&kd,&cv,eg);
664
double oblate_segv_wrap(double m, double n, double c)
670
if ((m<0) || (n<m) || (m!=floor(m)) || (n!=floor(n)) || ((n-m)>198)) {
675
eg = (double *)PyMem_Malloc(sizeof(double)*(n-m+2));
677
printf("Warning: Memory allocation error.\n");
680
F_FUNC(segv,SEGV)(&int_m,&int_n,&c,&kd,&cv,eg);
686
double prolate_aswfa_nocv_wrap(double m, double n, double c, double x, double *s1d)
692
if ((x >=1) || (x <=-1) || (m<0) || (n<m) || \
693
(m!=floor(m)) || (n!=floor(n)) || ((n-m)>198)) {
699
eg = (double *)PyMem_Malloc(sizeof(double)*(n-m+2));
701
printf("Warning: Memory allocation error.\n");
705
F_FUNC(segv,SEGV)(&int_m,&int_n,&c,&kd,&cv,eg);
706
F_FUNC(aswfa,ASWFA)(&int_m,&int_n,&c,&x,&kd,&cv,&s1f,s1d);
712
double oblate_aswfa_nocv_wrap(double m, double n, double c, double x, double *s1d)
718
if ((x >=1) || (x <=-1) || (m<0) || (n<m) || \
719
(m!=floor(m)) || (n!=floor(n)) || ((n-m)>198)) {
725
eg = (double *)PyMem_Malloc(sizeof(double)*(n-m+2));
727
printf("Warning: Memory allocation error.\n");
731
F_FUNC(segv,SEGV)(&int_m,&int_n,&c,&kd,&cv,eg);
732
F_FUNC(aswfa,ASWFA)(&int_m,&int_n,&c,&x,&kd,&cv,&s1f,s1d);
738
int prolate_aswfa_wrap(double m, double n, double c, double cv, double x, double *s1f, double *s1d)
743
if ((x >=1) || (x <=-1) || (m<0) || (n<m) || \
744
(m!=floor(m)) || (n!=floor(n))) {
751
F_FUNC(aswfa,ASWFA)(&int_m,&int_n,&c,&x,&kd,&cv,s1f,s1d);
756
int oblate_aswfa_wrap(double m, double n, double c, double cv, double x, double *s1f, double *s1d)
761
if ((x >=1) || (x <=-1) || (m<0) || (n<m) || \
762
(m!=floor(m)) || (n!=floor(n))) {
769
F_FUNC(aswfa,ASWFA)(&int_m,&int_n,&c,&x,&kd,&cv,s1f,s1d);
774
double prolate_radial1_nocv_wrap(double m, double n, double c, double x, double *r1d)
777
double r2f, r2d, r1f, cv, *eg;
780
if ((x <=1.0) || (m<0) || (n<m) || \
781
(m!=floor(m)) || (n!=floor(n)) || ((n-m)>198)) {
787
eg = (double *)PyMem_Malloc(sizeof(double)*(n-m+2));
789
printf("Warning: Memory allocation error.\n");
793
F_FUNC(segv,SEGV)(&int_m,&int_n,&c,&kd,&cv,eg);
794
F_FUNC(rswfp,RSWFP)(&int_m,&int_n,&c,&x,&cv,&kf,&r1f,r1d,&r2f,&r2d);
799
double prolate_radial2_nocv_wrap(double m, double n, double c, double x, double *r2d)
802
double r1f, r1d, r2f, cv, *eg;
805
if ((x <=1.0) || (m<0) || (n<m) || \
806
(m!=floor(m)) || (n!=floor(n)) || ((n-m)>198)) {
812
eg = (double *)PyMem_Malloc(sizeof(double)*(n-m+2));
814
printf("Warning: Memory allocation error.\n");
818
F_FUNC(segv,SEGV)(&int_m,&int_n,&c,&kd,&cv,eg);
819
F_FUNC(rswfp,RSWFP)(&int_m,&int_n,&c,&x,&cv,&kf,&r1f,&r1d,&r2f,r2d);
824
int prolate_radial1_wrap(double m, double n, double c, double cv, double x, double *r1f, double *r1d)
830
if ((x <= 1.0) || (m<0) || (n<m) || \
831
(m!=floor(m)) || (n!=floor(n))) {
838
F_FUNC(rswfp,RSWFP)(&int_m,&int_n,&c,&x,&cv,&kf,r1f,r1d,&r2f,&r2d);
842
int prolate_radial2_wrap(double m, double n, double c, double cv, double x, double *r2f, double *r2d)
848
if ((x <= 1.0) || (m<0) || (n<m) || \
849
(m!=floor(m)) || (n!=floor(n))) {
856
F_FUNC(rswfp,RSWFP)(&int_m,&int_n,&c,&x,&cv,&kf,&r1f,&r1d,r2f,r2d);
860
double oblate_radial1_nocv_wrap(double m, double n, double c, double x, double *r1d)
863
double r2f, r2d, r1f, cv, *eg;
866
if ((x < 0.0) || (m<0) || (n<m) || \
867
(m!=floor(m)) || (n!=floor(n)) || ((n-m)>198)) {
873
eg = (double *)PyMem_Malloc(sizeof(double)*(n-m+2));
875
printf("Warning: Memory allocation error.\n");
879
F_FUNC(segv,SEGV)(&int_m,&int_n,&c,&kd,&cv,eg);
880
F_FUNC(rswfo,RSWFO)(&int_m,&int_n,&c,&x,&cv,&kf,&r1f,r1d,&r2f,&r2d);
885
double oblate_radial2_nocv_wrap(double m, double n, double c, double x, double *r2d)
888
double r1f, r1d, r2f, cv, *eg;
891
if ((x < 0.0) || (m<0) || (n<m) || \
892
(m!=floor(m)) || (n!=floor(n)) || ((n-m)>198)) {
898
eg = (double *)PyMem_Malloc(sizeof(double)*(n-m+2));
900
printf("Warning: Memory allocation error.\n");
904
F_FUNC(segv,SEGV)(&int_m,&int_n,&c,&kd,&cv,eg);
905
F_FUNC(rswfo,RSWFO)(&int_m,&int_n,&c,&x,&cv,&kf,&r1f,&r1d,&r2f,r2d);
910
int oblate_radial1_wrap(double m, double n, double c, double cv, double x, double *r1f, double *r1d)
916
if ((x <0.0) || (m<0) || (n<m) || \
917
(m!=floor(m)) || (n!=floor(n))) {
924
F_FUNC(rswfo,RSWFO)(&int_m,&int_n,&c,&x,&cv,&kf,r1f,r1d,&r2f,&r2d);
928
int oblate_radial2_wrap(double m, double n, double c, double cv, double x, double *r2f, double *r2d)
934
if ((x <0.0) || (m<0) || (n<m) || \
935
(m!=floor(m)) || (n!=floor(n))) {
942
F_FUNC(rswfo,RSWFO)(&int_m,&int_n,&c,&x,&cv,&kf,&r1f,&r1d,r2f,r2d);
947
int modified_fresnel_plus_wrap(double x, Py_complex *Fplus, Py_complex *Kplus)
950
double fm, fa, gm, ga;
952
F_FUNC(ffk,FFK)(&ks,&x,F2C_CST(Fplus),&fm,&fa,F2C_CST(Kplus),&gm,&ga);
956
int modified_fresnel_minus_wrap(double x, Py_complex *Fminus, Py_complex *Kminus)
959
double fm, fa, gm, ga;
961
F_FUNC(ffk,FFK)(&ks,&x,F2C_CST(Fminus),&fm,&fa,F2C_CST(Kminus),&gm,&ga);