Skip to content

Commit f8660eb

Browse files
committed
Add support for C complex variables
1 parent 128ef37 commit f8660eb

File tree

5 files changed

+54
-11
lines changed

5 files changed

+54
-11
lines changed

Examples/test-suite/fortran/Makefile.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ C_TEST_CASES = \
3636
fortran_bindc_c \
3737
fortran_callback_c \
3838
fortran_global_const \
39+
complextest_c \
3940

4041
FAILING_CPP_TESTS += \
4142
contract \
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
! File : complextest_c_runme.F90
2+
3+
#include "fassert.h"
4+
5+
program complextest_c_runme
6+
use complextest_c
7+
use ISO_C_BINDING
8+
implicit none
9+
complex(C_FLOAT_COMPLEX) :: cflt
10+
complex(C_DOUBLE_COMPLEX) :: cdbl
11+
12+
cflt = (1, 3) ! 1 + 3i
13+
cflt = Conjf(cflt)
14+
ASSERT(cflt == (1, -3))
15+
16+
cdbl = (4.0000000001d0, 1d0)
17+
ASSERT(Conj(cdbl) == (4.0000000001d0, -1d0))
18+
19+
cdbl = (4, 5)
20+
cdbl = Conj2(cdbl)
21+
ASSERT(cdbl == (4d0, -5d0))
22+
23+
end program
24+
25+

Lib/fortran/ccomplex.i

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,20 @@
88
#define SWIG_ccomplex_construct(REAL, IMAG) ((REAL) + I * (IMAG))
99
%}
1010

11-
%define %fortran_typemap_ccomplex(CPLX_TYPE, CTYPE, FKIND)
12-
%fortran_typemap_complex(CPLX_TYPE, SWIG_ccomplex_construct, CTYPE, FKIND)
11+
/* TODO: SWIG's parser defines "complex" but does *not* define _Complex;
12+
* this is the reverse of the standard. */
13+
#define _Complex complex
14+
15+
%define %fortran_typemap_ccomplex(CTYPE, FKIND)
16+
%fortran_typemap_complex(complex CTYPE, SWIG_ccomplex_construct, CTYPE, FKIND)
1317
%enddef
1418

15-
#error "C complex numbers are not currently supported"
19+
%fortran_typemap_ccomplex(float, C_FLOAT_COMPLEX)
20+
%fortran_typemap_ccomplex(double, C_DOUBLE_COMPLEX)
21+
22+
%typemap(out, fragment="SWIG_complex_float", noblock=1) complex float
23+
{$result = SWIG_create_complex_float(crealf($1), cimagf($1));}
24+
%typemap(out, fragment="SWIG_complex_double", noblock=1) complex double
25+
{$result = SWIG_create_complex_double(creal($1), cimag($1));}
26+
27+

Lib/fortran/complex.i

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
%define %fortran_typemap_complex(CPPTYPE, CONSTRUCT_CPPTYPE, CTYPE, FKIND)
22

33
%fragment("SWIG_complex_"{CTYPE}, "header", noblock=1) {
4+
#ifdef __cplusplus
45
extern "C" {
6+
#endif
57
typedef struct {
68
CTYPE real;
79
CTYPE imag;
810
} SwigComplex_ ## CTYPE;
11+
#ifdef __cplusplus
912
}
13+
#endif
1014

1115
SWIGINTERN SwigComplex_ ## CTYPE SWIG_create_complex_ ## CTYPE(CTYPE real, CTYPE imag) {
1216
SwigComplex_ ## CTYPE result;
@@ -18,11 +22,11 @@ SWIGINTERN SwigComplex_ ## CTYPE SWIG_create_complex_ ## CTYPE(CTYPE real, CTYPE
1822

1923
struct SwigComplex_ ## CTYPE;
2024

21-
%naturalvar CPPTYPE;
22-
2325
%fortran_intrinsic(SwigComplex_ ## CTYPE, complex, FKIND)
2426
%fortran_apply_typemaps(SwigComplex_ ## CTYPE, CPPTYPE)
2527

28+
// _Complex and std::complex are required to have the same layout as
29+
// struct { double real, imag; };, so array interfaces should be equivalent
2630
%apply SwigComplex_ ## CTYPE { CPPTYPE };
2731
%apply SwigComplex_ ## CTYPE[] { CPPTYPE[] };
2832
%apply SwigComplex_ ## CTYPE ARRAY[] { CPPTYPE ARRAY[] };
@@ -34,9 +38,6 @@ struct SwigComplex_ ## CTYPE;
3438
%typemap(in, noblock=1) CPPTYPE {
3539
$1 = CONSTRUCT_CPPTYPE($input->real, $input->imag);
3640
}
37-
%typemap(out, fragment="SWIG_complex_"{CTYPE}, noblock=1) CPPTYPE
38-
{$result = SWIG_create_complex_ ## CTYPE($1.real(), $1.imag());}
39-
4041
%typemap(out, noblock=1) CPPTYPE&
4142
{$result = (SwigComplex_ ## CTYPE*)($1);}
4243

@@ -45,9 +46,6 @@ struct SwigComplex_ ## CTYPE;
4546
temp = CONSTRUCT_CPPTYPE($input->real, $input->imag);
4647
$1 = &temp;
4748
}
48-
%typemap(out, noblock=1) const CPPTYPE&
49-
{$result = SWIG_create_complex_ ## CTYPE($1->real(), $1->imag());}
50-
5149
%enddef // %fortran_typemap_complex
5250

5351
#ifdef __cplusplus

Lib/fortran/std_complex.i

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,14 @@ namespace std {
1313

1414
%define %fortran_typemap_std_complex(CTYPE, FKIND)
1515
%template() std::complex<CTYPE>;
16+
%naturalvar std::complex<CTYPE>;
1617
%fortran_typemap_complex(std::complex<CTYPE>, std::complex<CTYPE>, CTYPE, FKIND)
18+
19+
%typemap(out, fragment="SWIG_complex_"{CTYPE}, noblock=1) std::complex<CTYPE>
20+
{$result = SWIG_create_complex_ ## CTYPE($1.real(), $1.imag());}
21+
%typemap(out, noblock=1) const std::complex<CTYPE>&
22+
{$result = SWIG_create_complex_ ## CTYPE($1->real(), $1->imag());}
23+
1724
%enddef
1825

1926
%fortran_typemap_std_complex(float, C_FLOAT_COMPLEX)

0 commit comments

Comments
 (0)