1 | % (c) 2020-2024 Lehrstuhl fuer Softwaretechnik und Programmiersprachen, | |
2 | % Heinrich Heine Universitaet Duesseldorf | |
3 | % This software is licenced under EPL 1.0 (http://www.eclipse.org/org/documents/epl-v10.html) | |
4 | ||
5 | :- module(external_functions_reals,['STRING_TO_REAL'/3, | |
6 | 'RADD'/4,'RSUB'/4,'RMUL'/4,'RDIV'/5, 'RINV'/4, | |
7 | 'RPI'/1, 'RZERO'/1, 'RONE'/1, 'REULER'/1, | |
8 | 'REPSILON'/1, 'RMAXFLOAT'/1, | |
9 | 'RSIN'/3, 'RCOS'/3, 'RTAN'/3, 'RCOT'/3, | |
10 | 'RSINH'/3, 'RCOSH'/3, 'RTANH'/3, 'RCOTH'/3, | |
11 | 'RASIN'/3, 'RACOS'/3, 'RATAN'/3, 'RACOT'/3, | |
12 | 'RASINH'/3, 'RACOSH'/3, 'RATANH'/3, 'RACOTH'/3, | |
13 | 'RADIANS'/4, 'DEGREE'/4, | |
14 | 'RUMINUS'/3, | |
15 | 'REXP'/3, 'RLOGe'/4, 'RSQRT'/4, | |
16 | 'RABS'/3, 'ROUND'/3, 'RSIGN'/3, | |
17 | 'RINTEGER'/3, 'RFRACTION'/3, | |
18 | 'RMAX'/5, 'RMIN'/5, | |
19 | 'RPOW'/5, 'RLOG'/5, | |
20 | 'RDECIMAL'/5, % scientific notation using integers | |
21 | 'RLT'/4, 'REQ'/4, 'RNEQ'/4, 'RLEQ'/4, 'RGT'/4, 'RGEQ'/4, | |
22 | 'RMAXIMUM'/4, 'RMINIMUM'/4, | |
23 | ||
24 | 'RNEXT'/2, | |
25 | ||
26 | 'SFADD16'/3, | |
27 | 'SFSUB16'/3, | |
28 | 'SFMUL16'/3, | |
29 | 'SFDIV16'/3, | |
30 | 'SFSQRT16'/2, | |
31 | 'SFMULADD16'/4, | |
32 | ||
33 | 'SFADD32'/3, | |
34 | 'SFSUB32'/3, | |
35 | 'SFMUL32'/3, | |
36 | 'SFDIV32'/3, | |
37 | 'SFSQRT32'/2, | |
38 | 'SFMULADD32'/4, | |
39 | ||
40 | 'SFADD64'/3, | |
41 | 'SFSUB64'/3, | |
42 | 'SFMUL64'/3, | |
43 | 'SFDIV64'/3, | |
44 | 'SFSQRT64'/2, | |
45 | 'SFMULADD64'/4, | |
46 | ||
47 | 'SFADD80'/3, | |
48 | 'SFSUB80'/3, | |
49 | 'SFMUL80'/3, | |
50 | 'SFDIV80'/3, | |
51 | 'SFSQRT80'/2, | |
52 | ||
53 | 'SFADD128'/3, | |
54 | 'SFSUB128'/3, | |
55 | 'SFMUL128'/3, | |
56 | 'SFDIV128'/3, | |
57 | 'SFSQRT128'/2, | |
58 | 'SFMULADD128'/4 | |
59 | ]). | |
60 | ||
61 | ||
62 | % ------------------------------- | |
63 | :- use_module(probsrc(kernel_reals),[construct_real/2, | |
64 | is_largest_positive_float/1, is_smallest_positive_float/1, is_next_larger_float/2]). | |
65 | ||
66 | %external_fun_type('STRING_TO_REAL',[],[string,real]). | |
67 | % allows to call construct_real/2; also works for numbers without decimal point | |
68 | ||
69 | :- block 'STRING_TO_REAL'(-,?,?). | |
70 | 'STRING_TO_REAL'(string(A),Result,_) :- | |
71 | construct_real(A,Result). | |
72 | ||
73 | % ------------------------------- | |
74 | ||
75 | :- use_module(probsrc(kernel_reals),[real_addition_wf/4, real_subtraction_wf/4, | |
76 | real_multiplication_wf/4, real_division_wf/5, real_power_of_wf/5, | |
77 | real_unary_minus_wf/3, | |
78 | convert_int_to_real/2, | |
79 | real_round_wf/3, | |
80 | real_unop_wf/4, real_unop_wf/5, real_binop_wf/6, | |
81 | real_comp_wf/5, | |
82 | real_maximum_of_set/4, real_minimum_of_set/4]). | |
83 | ||
84 | 'RADD'(RX,RY,RR,WF) :- | |
85 | real_addition_wf(RX,RY,RR,WF). | |
86 | ||
87 | 'RSUB'(RX,RY,RR,WF) :- | |
88 | real_subtraction_wf(RX,RY,RR,WF). | |
89 | ||
90 | 'RMUL'(RX,RY,RR,WF) :- | |
91 | real_multiplication_wf(RX,RY,RR,WF). | |
92 | ||
93 | 'RDIV'(RX,RY,RR,Span,WF) :- | |
94 | real_division_wf(RX,RY,RR,Span,WF). | |
95 | ||
96 | 'RINV'(RY,RR,Span,WF) :- | |
97 | 'RONE'(RX), | |
98 | real_division_wf(RX,RY,RR,Span,WF). | |
99 | ||
100 | % ---- constants | |
101 | ||
102 | 'RPI'(term(floating(R))) :- R is pi. | |
103 | ||
104 | 'RZERO'(term(floating(R))) :- R = 0.0. | |
105 | ||
106 | 'RONE'(term(floating(R))) :- R = 1.0. | |
107 | ||
108 | 'REULER'(term(floating(R))) :- R is exp(1.0). | |
109 | ||
110 | 'REPSILON'(R) :- is_smallest_positive_float(R). % 5.0E-324 | |
111 | ||
112 | 'RMAXFLOAT'(R) :- is_largest_positive_float(R). % 1.7976931348623157E+308 | |
113 | ||
114 | % ---- unary operators | |
115 | ||
116 | % --- Trigonometric | |
117 | ||
118 | :- block 'RSIN'(-,?,?). | |
119 | 'RSIN'(X,R,WF) :- | |
120 | real_unop_wf('sin',X,R,WF). | |
121 | ||
122 | :- block 'RCOS'(-,?,?). | |
123 | 'RCOS'(X,R,WF) :- | |
124 | real_unop_wf('cos',X,R,WF). | |
125 | ||
126 | :- block 'RTAN'(-,?,?). | |
127 | 'RTAN'(X,R,WF) :- | |
128 | real_unop_wf('tan',X,R,WF). | |
129 | ||
130 | :- block 'RCOT'(-,?,?). | |
131 | 'RCOT'(X,R,WF) :- | |
132 | real_unop_wf('cot',X,R,WF). | |
133 | ||
134 | :- block 'RSINH'(-,?,?). | |
135 | 'RSINH'(X,R,WF) :- | |
136 | real_unop_wf('sinh',X,R,WF). | |
137 | ||
138 | :- block 'RCOSH'(-,?,?). | |
139 | 'RCOSH'(X,R,WF) :- | |
140 | real_unop_wf('cosh',X,R,WF). | |
141 | ||
142 | :- block 'RTANH'(-,?,?). | |
143 | 'RTANH'(X,R,WF) :- | |
144 | real_unop_wf('tanh',X,R,WF). | |
145 | ||
146 | :- block 'RCOTH'(-,?,?). | |
147 | 'RCOTH'(X,R,WF) :- | |
148 | real_unop_wf('coth',X,R,WF). | |
149 | ||
150 | :- block 'RASIN'(-,?,?). | |
151 | 'RASIN'(X,R,WF) :- | |
152 | real_unop_wf('asin',X,R,WF). | |
153 | ||
154 | :- block 'RACOS'(-,?,?). | |
155 | 'RACOS'(X,R,WF) :- | |
156 | real_unop_wf('acos',X,R,WF). | |
157 | ||
158 | :- block 'RATAN'(-,?,?). | |
159 | 'RATAN'(X,R,WF) :- | |
160 | real_unop_wf('atan',X,R,WF). | |
161 | ||
162 | :- block 'RACOT'(-,?,?). | |
163 | 'RACOT'(X,R,WF) :- | |
164 | real_unop_wf('acot',X,R,WF). | |
165 | ||
166 | :- block 'RASINH'(-,?,?). | |
167 | 'RASINH'(X,R,WF) :- | |
168 | real_unop_wf('asinh',X,R,WF). | |
169 | ||
170 | :- block 'RACOSH'(-,?,?). | |
171 | 'RACOSH'(X,R,WF) :- | |
172 | real_unop_wf('acosh',X,R,WF). | |
173 | ||
174 | :- block 'RATANH'(-,?,?). | |
175 | 'RATANH'(X,R,WF) :- | |
176 | real_unop_wf('atanh',X,R,WF). | |
177 | ||
178 | :- block 'RACOTH'(-,?,?). | |
179 | 'RACOTH'(X,R,WF) :- | |
180 | real_unop_wf('acoth',X,R,WF). | |
181 | ||
182 | :- block 'RADIANS'(-,?,?,?). | |
183 | 'RADIANS'(Degree,Res,Span,WF) :- | |
184 | D180 = term(floating(180.0)), | |
185 | 'RDIV'(Degree,D180,Deg2,Span,WF), | |
186 | 'RPI'(PI), | |
187 | 'RMUL'(PI,Deg2,Res,WF). | |
188 | ||
189 | :- block 'DEGREE'(-,?,?,?). | |
190 | 'DEGREE'(Radians,Res,Span,WF) :- | |
191 | D180 = term(floating(180.0)), | |
192 | 'RPI'(PI), | |
193 | 'RDIV'(Radians,PI,Deg2,Span,WF), | |
194 | 'RMUL'(D180,Deg2,Res,WF). | |
195 | ||
196 | % ----------------------- | |
197 | ||
198 | ||
199 | :- block 'RUMINUS'(-,?,?). | |
200 | 'RUMINUS'(RX,RR,WF) :- % unary minus | |
201 | real_unary_minus_wf(RX,RR,WF). | |
202 | ||
203 | :- block 'REXP'(-,?,?). | |
204 | 'REXP'(X,R,WF) :- | |
205 | real_unop_wf('exp',X,R,WF). | |
206 | ||
207 | :- block 'RLOGe'(-,?,?,?). | |
208 | 'RLOGe'(X,R,Span,WF) :- | |
209 | real_unop_wf('log',X,R,Span,WF). | |
210 | ||
211 | :- block 'RSQRT'(-,?,?,?). | |
212 | 'RSQRT'(X,R,Span,WF) :- | |
213 | real_unop_wf('sqrt',X,R,Span,WF). | |
214 | ||
215 | :- block 'RABS'(-,?,?). | |
216 | 'RABS'(X,R,WF) :- | |
217 | real_unop_wf('abs',X,R,WF). | |
218 | ||
219 | :- block 'ROUND'(-,?,?). | |
220 | 'ROUND'(X,R,WF) :- | |
221 | real_round_wf(X,R,WF). | |
222 | ||
223 | :- block 'RSIGN'(-,?,?). | |
224 | 'RSIGN'(X,R,WF) :- | |
225 | real_unop_wf('sign',X,R,WF). | |
226 | ||
227 | :- block 'RINTEGER'(-,?,?). | |
228 | 'RINTEGER'(X,R,WF) :- | |
229 | real_unop_wf('float_integer_part',X,R,WF). | |
230 | ||
231 | :- block 'RFRACTION'(-,?,?). | |
232 | 'RFRACTION'(X,R,WF) :- | |
233 | real_unop_wf('float_fractional_part',X,R,WF). | |
234 | ||
235 | % ---- other binary operators | |
236 | 'RMAX'(RX,RY,RR,Span,WF) :- | |
237 | real_binop_wf(max,RX,RY,RR,Span,WF). | |
238 | ||
239 | 'RMIN'(RX,RY,RR,Span,WF) :- | |
240 | real_binop_wf(min,RX,RY,RR,Span,WF). | |
241 | ||
242 | 'RPOW'(RX,RY,RR,Span,WF) :- | |
243 | real_power_of_wf(RX,RY,RR,Span,WF). | |
244 | ||
245 | % convert integers x,y to reak x*10^y | |
246 | 'RDECIMAL'(IntX,IntY,RR,Span,WF) :- | |
247 | convert_int_to_real(int(10),R10), | |
248 | convert_int_to_real(IntY,RY), | |
249 | real_power_of_wf(R10,RY,RR10,Span,WF), | |
250 | convert_int_to_real(IntX,RX), | |
251 | 'RMUL'(RX,RR10,RR,WF). | |
252 | ||
253 | 'RLOG'(RX,RY,RR,Span,WF) :- | |
254 | real_binop_wf(log,RX,RY,RR,Span,WF). | |
255 | ||
256 | % ---- other binary predicates | |
257 | ||
258 | 'RLT'(RX,RY,RR,WF) :- | |
259 | real_comp_wf('<',RX,RY,RR,WF). | |
260 | ||
261 | 'REQ'(RX,RY,RR,WF) :- | |
262 | real_comp_wf('=:=',RX,RY,RR,WF). | |
263 | ||
264 | 'RNEQ'(RX,RY,RR,WF) :- | |
265 | real_comp_wf('=\\=',RX,RY,RR,WF). % =\= | |
266 | ||
267 | 'RLEQ'(RX,RY,RR,WF) :- | |
268 | real_comp_wf('=<',RX,RY,RR,WF). | |
269 | ||
270 | 'RGT'(RY,RX,RR,WF) :-'RLT'(RX,RY,RR,WF). | |
271 | ||
272 | 'RGEQ'(RY,RX,RR,WF) :-'RLEQ'(RX,RY,RR,WF). | |
273 | ||
274 | % set operators | |
275 | ||
276 | 'RMAXIMUM'(Set,Res,Span,WF) :- | |
277 | real_maximum_of_set(Set,Res,Span,WF). | |
278 | 'RMINIMUM'(Set,Res,Span,WF) :- | |
279 | real_minimum_of_set(Set,Res,Span,WF). | |
280 | ||
281 | % ---- Float operators | |
282 | ||
283 | 'RNEXT'(Nr,NextNr) :- | |
284 | is_next_larger_float(Nr,NextNr). | |
285 | ||
286 | % softfloat functions. | |
287 | ||
288 | :- use_module(extension('softfloat/softfloat')). | |
289 | ||
290 | 'SFADD16'(term(floating(X)),term(floating(Y)),term(floating(R))) :- | |
291 | init_softfloat, | |
292 | add16(X,Y,R). | |
293 | ||
294 | 'SFSUB16'(term(floating(X)),term(floating(Y)),term(floating(R))) :- | |
295 | init_softfloat, | |
296 | sub16(X,Y,R). | |
297 | ||
298 | 'SFMUL16'(term(floating(X)),term(floating(Y)),term(floating(R))) :- | |
299 | init_softfloat, | |
300 | mul16(X,Y,R). | |
301 | ||
302 | 'SFDIV16'(term(floating(X)),term(floating(Y)),term(floating(R))) :- | |
303 | init_softfloat, | |
304 | div16(X,Y,R). | |
305 | ||
306 | 'SFSQRT16'(term(floating(X)),term(floating(R))) :- | |
307 | init_softfloat, | |
308 | sqrt16(X,R). | |
309 | ||
310 | 'SFMULADD16'(term(floating(X)),term(floating(Y)),term(floating(Z)),term(floating(R))) :- | |
311 | init_softfloat, | |
312 | muladd16(X,Y,Z,R). | |
313 | %32bit | |
314 | ||
315 | 'SFADD32'(term(floating(X)),term(floating(Y)),term(floating(R))) :- | |
316 | init_softfloat, | |
317 | add32(X,Y,R). | |
318 | ||
319 | 'SFSUB32'(term(floating(X)),term(floating(Y)),term(floating(R))) :- | |
320 | init_softfloat, | |
321 | sub32(X,Y,R). | |
322 | ||
323 | 'SFMUL32'(term(floating(X)),term(floating(Y)),term(floating(R))) :- | |
324 | init_softfloat, | |
325 | mul32(X,Y,R). | |
326 | ||
327 | 'SFDIV32'(term(floating(X)),term(floating(Y)),term(floating(R))) :- | |
328 | init_softfloat, | |
329 | div32(X,Y,R). | |
330 | ||
331 | 'SFSQRT32'(term(floating(X)),term(floating(R))) :- | |
332 | init_softfloat, | |
333 | sqrt32(X,R). | |
334 | ||
335 | 'SFMULADD32'(term(floating(X)),term(floating(Y)),term(floating(Z)),term(floating(R))) :- | |
336 | init_softfloat, | |
337 | muladd32(X,Y,Z,R). | |
338 | ||
339 | %32bit | |
340 | %64bit | |
341 | ||
342 | 'SFADD64'(term(floating(X)),term(floating(Y)),term(floating(R))) :- | |
343 | init_softfloat, | |
344 | add64(X,Y,R). | |
345 | ||
346 | 'SFSUB64'(term(floating(X)),term(floating(Y)),term(floating(R))) :- | |
347 | init_softfloat, | |
348 | sub64(X,Y,R). | |
349 | ||
350 | 'SFMUL64'(term(floating(X)),term(floating(Y)),term(floating(R))) :- | |
351 | init_softfloat, | |
352 | mul64(X,Y,R). | |
353 | ||
354 | 'SFDIV64'(term(floating(X)),term(floating(Y)),term(floating(R))) :- | |
355 | init_softfloat, | |
356 | div64(X,Y,R). | |
357 | ||
358 | 'SFSQRT64'(term(floating(X)),term(floating(R))) :- | |
359 | init_softfloat, | |
360 | sqrt64(X,R). | |
361 | ||
362 | 'SFMULADD64'(term(floating(X)),term(floating(Y)),term(floating(Z)),term(floating(R))) :- | |
363 | init_softfloat, | |
364 | muladd64(X,Y,Z,R). | |
365 | %64bit | |
366 | %80bit | |
367 | 'SFADD80'((int(X1),int(X2)),(int(Y1),int(Y2)),(int(R1),int(R2))) :- | |
368 | init_softfloat, | |
369 | add80(X1,X2,Y1,Y2,R1,R2). | |
370 | ||
371 | 'SFSUB80'((int(X1),int(X2)),(int(Y1),int(Y2)),(int(R1),int(R2))) :- | |
372 | init_softfloat, | |
373 | sub80(X1,X2,Y1,Y2,R1,R2). | |
374 | ||
375 | 'SFMUL80'((int(X1),int(X2)),(int(Y1),int(Y2)),(int(R1),int(R2))) :- | |
376 | init_softfloat, | |
377 | mul80(X1,X2,Y1,Y2,R1,R2). | |
378 | ||
379 | 'SFDIV80'((int(X1),int(X2)),(int(Y1),int(Y2)),(int(R1),int(R2))) :- | |
380 | init_softfloat, | |
381 | div80(X1,X2,Y1,Y2,R1,R2). | |
382 | ||
383 | 'SFSQRT80'( (int(X1),int(X2)),(int(R1),int(R2)) ) :- | |
384 | init_softfloat, | |
385 | sqrt80(X1,X2,R1,R2). | |
386 | %80bit | |
387 | %128bit | |
388 | 'SFADD128'((int(X1),int(X2)),(int(Y1),int(Y2)),(int(R1),int(R2))) :- | |
389 | init_softfloat, | |
390 | add128(X1,X2,Y1,Y2,R1,R2). | |
391 | ||
392 | 'SFSUB128'((int(X1),int(X2)),(int(Y1),int(Y2)),(int(R1),int(R2))) :- | |
393 | init_softfloat, | |
394 | sub128(X1,X2,Y1,Y2,R1,R2). | |
395 | ||
396 | 'SFMUL128'((int(X1),int(X2)),(int(Y1),int(Y2)),(int(R1),int(R2))) :- | |
397 | init_softfloat, | |
398 | mul128(X1,X2,Y1,Y2,R1,R2). | |
399 | ||
400 | 'SFDIV128'((int(X1),int(X2)),(int(Y1),int(Y2)),(int(R1),int(R2))) :- | |
401 | init_softfloat, | |
402 | div128(X1,X2,Y1,Y2,R1,R2). | |
403 | ||
404 | 'SFSQRT128'((int(X1),int(X2)),(int(R1),int(R2))) :- | |
405 | init_softfloat, | |
406 | sqrt128(X1,X2,R1,R2). | |
407 | ||
408 | 'SFMULADD128'((int(X1),int(X2)),(int(Y1),int(Y2)),(int(Z1),int(Z2)),(int(R1),int(R2))) :- | |
409 | init_softfloat, | |
410 | muladd128(X1,X2,Y1,Y2,Z1,Z2,R1,R2). | |
411 | %128bit |