-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathfpu.ml
executable file
·153 lines (124 loc) · 5.92 KB
/
fpu.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
(*
Copyright 2011 Jean-Marc Alliot / Jean-Baptiste Gotteland
This file is part of the ocaml interval library.
The ocaml interval library is free software:
you can redistribute it and/or modify it under the terms of
the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
The ocaml interval library is distributed in the hope that it will be
useful,but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the ocaml interval library.
If not, see <http://www.gnu.org/licenses/>.
*)
let _ = Callback.register_exception "failure" (Failure "")
external set_low: unit -> unit = "set_low" "noalloc"
external set_high: unit -> unit = "set_high" "noalloc"
external set_nearest: unit -> unit = "set_nearest" "noalloc"
external ffloat: int -> float = "ffloat_caml"
external ffloat_high: int -> float = "ffloat_high_caml"
external ffloat_low: int -> float = "ffloat_low_caml"
external fadd: float -> float -> float = "fadd_caml"
external fadd_low: float -> float -> float = "fadd_low_caml"
external fadd_high: float -> float -> float = "fadd_high_caml"
external fsub: float -> float -> float = "fsub_caml"
external fsub_low: float -> float -> float = "fsub_low_caml"
external fsub_high: float -> float -> float = "fsub_high_caml"
external fmul: float -> float -> float = "fmul_caml"
external fmul_low: float -> float -> float = "fmul_low_caml"
external fmul_high: float -> float -> float = "fmul_high_caml"
external fdiv: float -> float -> float = "fdiv_caml"
external fdiv_low: float -> float -> float = "fdiv_low_caml"
external fdiv_high: float -> float -> float = "fdiv_high_caml"
external fmod: float -> float -> float = "fprem_caml"
external fsqrt: float -> float = "fsqrt_caml"
external fsqrt_low: float -> float = "fsqrt_low_caml"
external fsqrt_high: float -> float = "fsqrt_high_caml"
external flog: float -> float = "flog_caml"
external flog_low: float -> float = "flog_low_caml"
external flog_high: float -> float = "flog_high_caml"
external fexp: float -> float = "fexp_caml"
external fexp_low: float -> float = "fexp_low_caml"
external fexp_high: float -> float = "fexp_high_caml"
external flog_pow: float -> float -> float = "flog_pow_caml"
external flog_pow_low: float -> float -> float = "flog_pow_low_caml"
external flog_pow_high: float -> float -> float = "flog_pow_high_caml"
external fsin: float -> float = "fsin_caml"
external fsin_low: float -> float = "fsin_low_caml"
external fsin_high: float -> float = "fsin_high_caml"
external fcos: float -> float = "fcos_caml"
external fcos_low: float -> float = "fcos_low_caml"
external fcos_high: float -> float = "fcos_high_caml"
external ftan: float -> float = "ftan_caml"
external ftan_low: float -> float = "ftan_low_caml"
external ftan_high: float -> float = "ftan_high_caml"
external fasin: float -> float = "fasin_caml"
external fasin_low: float -> float = "fasin_low_caml"
external fasin_high: float -> float = "fasin_high_caml"
external facos: float -> float = "facos_caml"
external facos_low: float -> float = "facos_low_caml"
external facos_high: float -> float = "facos_high_caml"
external fatan: float -> float -> float = "fatan_caml"
external fatan_low: float -> float -> float = "fatan_low_caml"
external fatan_high: float -> float -> float = "fatan_high_caml"
external fsinh: float -> float = "fsinh_caml"
external fsinh_low: float -> float = "fsinh_low_caml"
external fsinh_high: float -> float = "fsinh_high_caml"
external fcosh: float -> float = "fcosh_caml"
external fcosh_low: float -> float = "fcosh_low_caml"
external fcosh_high: float -> float = "fcosh_high_caml"
external ftanh: float -> float = "ftanh_caml"
external ftanh_low: float -> float = "ftanh_low_caml"
external ftanh_high: float -> float = "ftanh_high_caml"
external is_neg: float -> bool = "is_neg_caml"
let inf_pow y =
if y < 0. then 0. else if y = 0. then 1. else infinity
let zero_pow x y =
if 0. < y then 0.
else if y = 0. || y = neg_infinity || (is_neg x && floor y <> y) then nan
else if is_neg x && mod_float y 2. <> 0. then neg_infinity
else infinity
let neg_inf_pow y =
if classify_float y = FP_infinite || floor y <> y then nan
else if y = 0. then 1. else if y < 0. then 0.
else if mod_float y 2. = 0. then infinity else neg_infinity
let pos_pow_inf x =
if x < 1. then 0. else if x = 1. then 1. else infinity
let pos_pow_neg_inf x =
if x < 1. then infinity else if x = 1. then 1. else 0.
let fpow x y =
if x = infinity then inf_pow y
else if 0. < x then
if y = infinity then pos_pow_inf x
else if y = neg_infinity then pos_pow_neg_inf x
else flog_pow x y
else if x = 0. then zero_pow x y
else if x = neg_infinity then neg_inf_pow y
else if classify_float y = FP_infinite || floor y <> y then nan
else if mod_float y 2. = 0. then flog_pow (-.x) y
else -.flog_pow (-.x) y
let fpow_low x y =
if x = infinity then inf_pow y
else if 0. < x then
if y = infinity then pos_pow_inf x
else if y = neg_infinity then pos_pow_neg_inf x
else flog_pow_low x y
else if x = 0. then zero_pow x y
else if x = neg_infinity then neg_inf_pow y
else if classify_float y = FP_infinite || floor y <> y then nan
else if mod_float y 2. = 0. then flog_pow_low (-.x) y
else -.flog_pow_high (-.x) y
let fpow_high x y =
if x = infinity then inf_pow y
else if 0. < x then
if y = infinity then pos_pow_inf x
else if y = neg_infinity then pos_pow_neg_inf x
else flog_pow_high x y
else if x = 0. then zero_pow x y
else if x = neg_infinity then neg_inf_pow y
else if classify_float y = FP_infinite || floor y <> y then nan
else if mod_float y 2. = 0. then flog_pow_high (-.x) y
else -.flog_pow_low (-.x) y