Skip to content

Commit e6c24e0

Browse files
authored
Merge pull request #6 from rikardn/module
Starting point for a modern fortran module
2 parents b60fc07 + 360bac4 commit e6c24e0

File tree

2 files changed

+267
-0
lines changed

2 files changed

+267
-0
lines changed

src/symengine.f08

+244
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
1+
module symengine
2+
3+
use iso_c_binding, only: c_size_t, c_long, c_char, c_ptr, c_null_ptr, c_null_char, c_f_pointer, c_associated
4+
implicit none
5+
6+
interface
7+
function c_strlen(string) bind(C, name="strlen")
8+
import :: c_size_t, c_ptr
9+
type(c_ptr), intent(in), value :: string
10+
integer(kind=c_size_t) :: c_strlen
11+
end function c_strlen
12+
function c_basic_new_heap() bind(c, name='basic_new_heap')
13+
import :: c_ptr
14+
type(c_ptr) :: c_basic_new_heap
15+
end function
16+
subroutine c_basic_free_heap(s) bind(c, name='basic_free_heap')
17+
import :: c_ptr
18+
type(c_ptr), value :: s
19+
end subroutine
20+
function c_basic_assign(a, b) bind(c, name='basic_assign')
21+
import c_long, c_ptr
22+
type(c_ptr), value :: a, b
23+
integer(c_long) :: c_basic_assign
24+
end function
25+
function c_basic_str(s) bind(c, name='basic_str')
26+
import :: c_ptr
27+
type(c_ptr), value :: s
28+
type(c_ptr) :: c_basic_str
29+
end function
30+
function c_basic_parse(s, c) bind(c, name='basic_parse')
31+
import c_long, c_ptr, c_char
32+
type(c_ptr), value :: s
33+
character(kind=c_char), dimension(*) :: c
34+
integer(c_long) :: c_basic_parse
35+
end function
36+
subroutine c_basic_str_free(s) bind(c, name='basic_str_free')
37+
import :: c_ptr
38+
type(c_ptr), value :: s
39+
end subroutine
40+
function c_basic_add(s, a, b) bind(c, name='basic_add')
41+
import :: c_long, c_ptr
42+
type(c_ptr), value :: s, a, b
43+
integer(c_long) :: c_basic_add
44+
end function
45+
function c_basic_sub(s, a, b) bind(c, name='basic_sub')
46+
import :: c_long, c_ptr
47+
type(c_ptr), value :: s, a, b
48+
integer(c_long) :: c_basic_sub
49+
end function
50+
function c_basic_mul(s, a, b) bind(c, name='basic_mul')
51+
import :: c_long, c_ptr
52+
type(c_ptr), value :: s, a, b
53+
integer(c_long) :: c_basic_mul
54+
end function
55+
function c_basic_div(s, a, b) bind(c, name='basic_div')
56+
import :: c_long, c_ptr
57+
type(c_ptr), value :: s, a, b
58+
integer(c_long) :: c_basic_div
59+
end function
60+
function c_basic_pow(s, a, b) bind(c, name='basic_pow')
61+
import :: c_long, c_ptr
62+
type(c_ptr), value :: s, a, b
63+
integer(c_long) :: c_basic_pow
64+
end function
65+
function c_integer_set_si(s, i) bind(c, name='integer_set_si')
66+
import :: c_long, c_ptr
67+
type(c_ptr), value :: s
68+
integer(c_long), value :: i
69+
integer(c_long) :: c_integer_set_si
70+
end function
71+
function c_integer_get_si(s) bind(c, name='integer_get_si')
72+
import c_long, c_ptr
73+
type(c_ptr), value :: s
74+
integer(c_long) :: c_integer_get_si
75+
end function
76+
function c_symbol_set(s, c) bind(c, name='symbol_set')
77+
import c_long, c_ptr, c_char
78+
type(c_ptr), value :: s
79+
character(kind=c_char), dimension(*) :: c
80+
integer(c_long) :: c_symbol_set
81+
end function
82+
end interface
83+
84+
85+
type Basic
86+
type(c_ptr) :: ptr = c_null_ptr
87+
logical :: tmp = .false.
88+
contains
89+
procedure :: str, basic_assign, basic_add, basic_sub, basic_mul, basic_div, basic_pow
90+
generic :: assignment(=) => basic_assign
91+
generic :: operator(+) => basic_add
92+
generic :: operator(-) => basic_sub
93+
generic :: operator(*) => basic_mul
94+
generic :: operator(/) => basic_div
95+
generic :: operator(**) => basic_pow
96+
final :: basic_free
97+
end type
98+
99+
interface Basic
100+
module procedure basic_new
101+
end interface
102+
103+
type, extends(Basic) :: SymInteger
104+
contains
105+
procedure :: get
106+
end type SymInteger
107+
108+
interface SymInteger
109+
module procedure integer_new
110+
end interface
111+
112+
type, extends(Basic) :: Symbol
113+
end type Symbol
114+
115+
interface Symbol
116+
module procedure symbol_new
117+
end interface
118+
119+
120+
contains
121+
122+
123+
function basic_new() result(new)
124+
type(Basic) :: new
125+
new%ptr = c_basic_new_heap()
126+
end function
127+
128+
subroutine basic_free(this)
129+
type(Basic) :: this
130+
call c_basic_free_heap(this%ptr)
131+
end subroutine
132+
133+
function str(e)
134+
class(Basic) :: e
135+
character, pointer, dimension(:) :: tempstr
136+
character(:), allocatable :: str
137+
type(c_ptr) :: cstring
138+
integer :: nchars
139+
cstring = c_basic_str(e%ptr)
140+
nchars = c_strlen(cstring)
141+
call c_f_pointer(cstring, tempstr, [nchars])
142+
allocate(character(len=nchars) :: str)
143+
str = transfer(tempstr(1:nchars), str)
144+
call c_basic_str_free(cstring)
145+
end function
146+
147+
subroutine basic_assign(a, b)
148+
class(basic), intent(inout) :: a
149+
class(basic), intent(in) :: b
150+
integer(c_long) :: dummy
151+
if (.not. c_associated(a%ptr)) then
152+
a%ptr = c_basic_new_heap()
153+
end if
154+
dummy = c_basic_assign(a%ptr, b%ptr)
155+
if (b%tmp) then
156+
call basic_free(b)
157+
end if
158+
end subroutine
159+
160+
function basic_add(a, b)
161+
class(basic), intent(in) :: a, b
162+
type(basic) :: basic_add
163+
integer(c_long) :: dummy
164+
basic_add = Basic()
165+
dummy = c_basic_add(basic_add%ptr, a%ptr, b%ptr)
166+
basic_add%tmp = .true.
167+
end function
168+
169+
function basic_sub(a, b)
170+
class(basic), intent(in) :: a, b
171+
type(basic) :: basic_sub
172+
integer(c_long) :: dummy
173+
basic_sub = Basic()
174+
dummy = c_basic_sub(basic_sub%ptr, a%ptr, b%ptr)
175+
basic_sub%tmp = .true.
176+
end function
177+
178+
function basic_mul(a, b)
179+
class(basic), intent(in) :: a, b
180+
type(basic) :: basic_mul
181+
integer(c_long) :: dummy
182+
basic_mul = Basic()
183+
dummy = c_basic_mul(basic_mul%ptr, a%ptr, b%ptr)
184+
basic_mul%tmp = .true.
185+
end function
186+
187+
function basic_div(a, b)
188+
class(basic), intent(in) :: a, b
189+
type(basic) :: basic_div
190+
integer(c_long) :: dummy
191+
basic_div = Basic()
192+
dummy = c_basic_div(basic_div%ptr, a%ptr, b%ptr)
193+
basic_div%tmp = .true.
194+
end function
195+
196+
function basic_pow(a, b)
197+
class(basic), intent(in) :: a, b
198+
type(basic) :: basic_pow
199+
integer(c_long) :: dummy
200+
basic_pow = Basic()
201+
dummy = c_basic_pow(basic_pow%ptr, a%ptr, b%ptr)
202+
basic_pow%tmp = .true.
203+
end function
204+
205+
function integer_new(i)
206+
integer :: i
207+
integer(c_long) :: j
208+
integer(c_long) :: dummy
209+
type(SymInteger) :: integer_new
210+
j = int(i)
211+
integer_new%ptr = c_basic_new_heap()
212+
dummy = c_integer_set_si(integer_new%ptr, j)
213+
integer_new%tmp = .true.
214+
end function
215+
216+
function get(this) result(i)
217+
class(SymInteger) :: this
218+
integer :: i
219+
i = int(c_integer_get_si(this%ptr))
220+
end function
221+
222+
function symbol_new(c)
223+
character(len=*) :: c
224+
character(len=len_trim(c) + 1) :: new_c
225+
integer(c_long) :: dummy
226+
type(Symbol) :: symbol_new
227+
new_c = trim(c) // c_null_char
228+
symbol_new%ptr = c_basic_new_heap()
229+
symbol_new%tmp = .true.
230+
dummy = c_symbol_set(symbol_new%ptr, new_c)
231+
end function
232+
233+
function parse(c)
234+
character(len=*) :: c
235+
type(Basic) :: parse
236+
integer(c_long) :: dummy
237+
character(len=len_trim(c) + 1) :: new_c
238+
new_c = trim(c) // c_null_char
239+
parse%ptr = c_basic_new_heap()
240+
dummy = c_basic_parse(parse%ptr, new_c)
241+
parse%tmp = .true.
242+
end function
243+
244+
end module

src/test.f08

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
subroutine dostuff()
2+
use symengine
3+
type(Basic) :: a, b, c
4+
5+
a = SymInteger(12)
6+
b = Symbol('x')
7+
c = a * b
8+
print *, c%str()
9+
c = parse('2*(24+x)')
10+
print *, c%str()
11+
end subroutine
12+
13+
14+
15+
program test
16+
17+
implicit none
18+
19+
call dostuff
20+
21+
print *, "Finishing"
22+
23+
end program

0 commit comments

Comments
 (0)