cannam@95
|
1 /*
|
cannam@95
|
2 * Copyright (c) 2003, 2007-11 Matteo Frigo
|
cannam@95
|
3 * Copyright (c) 2003, 2007-11 Massachusetts Institute of Technology
|
cannam@95
|
4 *
|
cannam@95
|
5 * This program is free software; you can redistribute it and/or modify
|
cannam@95
|
6 * it under the terms of the GNU General Public License as published by
|
cannam@95
|
7 * the Free Software Foundation; either version 2 of the License, or
|
cannam@95
|
8 * (at your option) any later version.
|
cannam@95
|
9 *
|
cannam@95
|
10 * This program is distributed in the hope that it will be useful,
|
cannam@95
|
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
cannam@95
|
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
cannam@95
|
13 * GNU General Public License for more details.
|
cannam@95
|
14 *
|
cannam@95
|
15 * You should have received a copy of the GNU General Public License
|
cannam@95
|
16 * along with this program; if not, write to the Free Software
|
cannam@95
|
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
cannam@95
|
18 *
|
cannam@95
|
19 */
|
cannam@95
|
20
|
cannam@95
|
21 #include "api.h"
|
cannam@95
|
22 #include "dft.h"
|
cannam@95
|
23 #include "rdft.h"
|
cannam@95
|
24
|
cannam@95
|
25 #include "x77.h"
|
cannam@95
|
26
|
cannam@95
|
27 /* if F77_FUNC is not defined, then we don't know how to mangle identifiers
|
cannam@95
|
28 for the Fortran linker, and we must omit the f77 API. */
|
cannam@95
|
29 #if defined(F77_FUNC) || defined(WINDOWS_F77_MANGLING)
|
cannam@95
|
30
|
cannam@95
|
31 /*-----------------------------------------------------------------------*/
|
cannam@95
|
32 /* some internal functions used by the f77 api */
|
cannam@95
|
33
|
cannam@95
|
34 /* in fortran, the natural array ordering is column-major, which
|
cannam@95
|
35 corresponds to reversing the dimensions relative to C's row-major */
|
cannam@95
|
36 static int *reverse_n(int rnk, const int *n)
|
cannam@95
|
37 {
|
cannam@95
|
38 int *nrev;
|
cannam@95
|
39 int i;
|
cannam@95
|
40 A(FINITE_RNK(rnk));
|
cannam@95
|
41 nrev = (int *) MALLOC(sizeof(int) * rnk, PROBLEMS);
|
cannam@95
|
42 for (i = 0; i < rnk; ++i)
|
cannam@95
|
43 nrev[rnk - i - 1] = n[i];
|
cannam@95
|
44 return nrev;
|
cannam@95
|
45 }
|
cannam@95
|
46
|
cannam@95
|
47 /* f77 doesn't have data structures, so we have to pass iodims as
|
cannam@95
|
48 parallel arrays */
|
cannam@95
|
49 static X(iodim) *make_dims(int rnk, const int *n,
|
cannam@95
|
50 const int *is, const int *os)
|
cannam@95
|
51 {
|
cannam@95
|
52 X(iodim) *dims;
|
cannam@95
|
53 int i;
|
cannam@95
|
54 A(FINITE_RNK(rnk));
|
cannam@95
|
55 dims = (X(iodim) *) MALLOC(sizeof(X(iodim)) * rnk, PROBLEMS);
|
cannam@95
|
56 for (i = 0; i < rnk; ++i) {
|
cannam@95
|
57 dims[i].n = n[i];
|
cannam@95
|
58 dims[i].is = is[i];
|
cannam@95
|
59 dims[i].os = os[i];
|
cannam@95
|
60 }
|
cannam@95
|
61 return dims;
|
cannam@95
|
62 }
|
cannam@95
|
63
|
cannam@95
|
64 typedef struct {
|
cannam@95
|
65 void (*f77_write_char)(char *, void *);
|
cannam@95
|
66 void *data;
|
cannam@95
|
67 } write_char_data;
|
cannam@95
|
68
|
cannam@95
|
69 static void write_char(char c, void *d)
|
cannam@95
|
70 {
|
cannam@95
|
71 write_char_data *ad = (write_char_data *) d;
|
cannam@95
|
72 ad->f77_write_char(&c, ad->data);
|
cannam@95
|
73 }
|
cannam@95
|
74
|
cannam@95
|
75 typedef struct {
|
cannam@95
|
76 void (*f77_read_char)(int *, void *);
|
cannam@95
|
77 void *data;
|
cannam@95
|
78 } read_char_data;
|
cannam@95
|
79
|
cannam@95
|
80 static int read_char(void *d)
|
cannam@95
|
81 {
|
cannam@95
|
82 read_char_data *ed = (read_char_data *) d;
|
cannam@95
|
83 int c;
|
cannam@95
|
84 ed->f77_read_char(&c, ed->data);
|
cannam@95
|
85 return (c < 0 ? EOF : c);
|
cannam@95
|
86 }
|
cannam@95
|
87
|
cannam@95
|
88 static X(r2r_kind) *ints2kinds(int rnk, const int *ik)
|
cannam@95
|
89 {
|
cannam@95
|
90 if (!FINITE_RNK(rnk) || rnk == 0)
|
cannam@95
|
91 return 0;
|
cannam@95
|
92 else {
|
cannam@95
|
93 int i;
|
cannam@95
|
94 X(r2r_kind) *k;
|
cannam@95
|
95
|
cannam@95
|
96 k = (X(r2r_kind) *) MALLOC(sizeof(X(r2r_kind)) * rnk, PROBLEMS);
|
cannam@95
|
97 /* reverse order for Fortran -> C */
|
cannam@95
|
98 for (i = 0; i < rnk; ++i)
|
cannam@95
|
99 k[i] = (X(r2r_kind)) ik[rnk - 1 - i];
|
cannam@95
|
100 return k;
|
cannam@95
|
101 }
|
cannam@95
|
102 }
|
cannam@95
|
103
|
cannam@95
|
104 /*-----------------------------------------------------------------------*/
|
cannam@95
|
105
|
cannam@95
|
106 #define F77(a, A) F77x(x77(a), X77(A))
|
cannam@95
|
107
|
cannam@95
|
108 #ifndef WINDOWS_F77_MANGLING
|
cannam@95
|
109
|
cannam@95
|
110 #if defined(F77_FUNC)
|
cannam@95
|
111 # define F77x(a, A) F77_FUNC(a, A)
|
cannam@95
|
112 # include "f77funcs.h"
|
cannam@95
|
113 #endif
|
cannam@95
|
114
|
cannam@95
|
115 /* If identifiers with underscores are mangled differently than those
|
cannam@95
|
116 without underscores, then we include *both* mangling versions. The
|
cannam@95
|
117 reason is that the only Fortran compiler that does such differing
|
cannam@95
|
118 mangling is currently g77 (which adds an extra underscore to names
|
cannam@95
|
119 with underscores), whereas other compilers running on the same
|
cannam@95
|
120 machine are likely to use non-underscored mangling. (I'm sick
|
cannam@95
|
121 of users complaining that FFTW works with g77 but not with e.g.
|
cannam@95
|
122 pgf77 or ifc on the same machine.) Note that all FFTW identifiers
|
cannam@95
|
123 contain underscores, and configure picks g77 by default. */
|
cannam@95
|
124 #if defined(F77_FUNC_) && !defined(F77_FUNC_EQUIV)
|
cannam@95
|
125 # undef F77x
|
cannam@95
|
126 # define F77x(a, A) F77_FUNC_(a, A)
|
cannam@95
|
127 # include "f77funcs.h"
|
cannam@95
|
128 #endif
|
cannam@95
|
129
|
cannam@95
|
130 #else /* WINDOWS_F77_MANGLING */
|
cannam@95
|
131
|
cannam@95
|
132 /* Various mangling conventions common (?) under Windows. */
|
cannam@95
|
133
|
cannam@95
|
134 /* g77 */
|
cannam@95
|
135 # define WINDOWS_F77_FUNC(a, A) a ## __
|
cannam@95
|
136 # define F77x(a, A) WINDOWS_F77_FUNC(a, A)
|
cannam@95
|
137 # include "f77funcs.h"
|
cannam@95
|
138
|
cannam@95
|
139 /* Intel, etc. */
|
cannam@95
|
140 # undef WINDOWS_F77_FUNC
|
cannam@95
|
141 # define WINDOWS_F77_FUNC(a, A) a ## _
|
cannam@95
|
142 # include "f77funcs.h"
|
cannam@95
|
143
|
cannam@95
|
144 /* Digital/Compaq/HP Visual Fortran, Intel Fortran. stdcall attribute
|
cannam@95
|
145 is apparently required to adjust for calling conventions (callee
|
cannam@95
|
146 pops stack in stdcall). See also:
|
cannam@95
|
147 http://msdn.microsoft.com/library/en-us/vccore98/html/_core_mixed.2d.language_programming.3a_.overview.asp
|
cannam@95
|
148 */
|
cannam@95
|
149 # undef WINDOWS_F77_FUNC
|
cannam@95
|
150 # if defined(__GNUC__)
|
cannam@95
|
151 # define WINDOWS_F77_FUNC(a, A) __attribute__((stdcall)) A
|
cannam@95
|
152 # elif defined(_MSC_VER) || defined(_ICC) || defined(_STDCALL_SUPPORTED)
|
cannam@95
|
153 # define WINDOWS_F77_FUNC(a, A) __stdcall A
|
cannam@95
|
154 # else
|
cannam@95
|
155 # define WINDOWS_F77_FUNC(a, A) A /* oh well */
|
cannam@95
|
156 # endif
|
cannam@95
|
157 # include "f77funcs.h"
|
cannam@95
|
158
|
cannam@95
|
159 #endif /* WINDOWS_F77_MANGLING */
|
cannam@95
|
160
|
cannam@95
|
161 #endif /* F77_FUNC */
|