1 # coding: utf-8
2 # frozen_string_literal: true
3
4
5
6 module Umu
7
8 module Value
9
10 module Core
11
12 module Atom
13
14 module Number
15
16 class Float < Abstract
17 # Class property
18
19 define_class_method(
20 :meth_make_nan,
21 :nan, [],
22 [], self
23 )
24 def self.meth_make_nan(_loc, _env, _event)
25 VC.make_nan
26 end
27
28
29 define_class_method(
30 :meth_make_infinity,
31 :infinity, [],
32 [], self
33 )
34 def self.meth_make_infinity(_loc, _env, _event)
35 VC.make_infinity
36 end
37
38
39 # Instance property
40
41 def initialize(val)
42 ASSERT.kind_of val, ::Float
43
44 super
45 end
46
47
48 def to_s
49 if self.val.nan?
50 'NAN'
51 elsif self.val.infinite?
52 format("%sINFINITY",
53 if self.val < 0
54 '-'
55 else
56 ''
57 end
58 )
59 elsif val.finite?
60 super
61 else
62 ASSERT.abort
63 end
64 end
65
66
67 define_instance_method(
68 :meth_is_nan,
69 :nan?, [],
70 [], VCA::Bool
71 )
72 def meth_is_nan(_loc, _env, _event)
73 VC.make_bool self.val.nan?
74 end
75
76
77 define_instance_method(
78 :meth_is_infinite,
79 :infinite?, [],
80 [], VCA::Bool
81 )
82 def meth_is_infinite(_loc, _env, _event)
83 VC.make_bool self.val.infinite?.kind_of?(::Integer)
84 end
85
86
87 define_instance_method(
88 :meth_is_finite,
89 :finite?, [],
90 [], VCA::Bool
91 )
92 def meth_is_finite(_loc, _env, _event)
93 VC.make_bool self.val.finite?
94 end
95
96
97 define_instance_method(
98 :meth_is_less_than,
99 :'<', [],
100 [self], VCA::Bool
101 )
102
103
104 define_instance_method(
105 :meth_is_greater_than,
106 :'>', [],
107 [self], VCA::Bool
108 )
109
110
111 define_instance_method(
112 :meth_is_less_equal,
113 :'<=', [],
114 [self], VCA::Bool
115 )
116
117
118 define_instance_method(
119 :meth_is_greater_equal,
120 :'>=', [],
121 [self], VCA::Bool
122 )
123
124
125 define_instance_method(
126 :meth_compare,
127 :'<=>', [],
128 [self], VCAN::Int
129 )
130
131
132
133
134 define_instance_method(
135 :meth_to_float,
136 :'to-f', [],
137 [], VCAN::Float
138 )
139 def meth_to_float(_loc, _env, _event)
140 self
141 end
142
143
144 define_instance_method(
145 :meth_truncate,
146 :truncate, [],
147 [VCAN::Int], self
148 )
149 def meth_truncate(loc, env, _event, ndigits)
150 ASSERT.kind_of ndigits, VCAN::Int
151
152 unless ndigits.val >= 0
153 raise X::ArgumentError.new(
154 loc,
155 env,
156 "truncate: Expected zero or positive number, but: %d",
157 ndigits.val.to_i
158 )
159 end
160
161 VC.make_float self.val.truncate(ndigits.val).to_f
162 end
163
164
165 define_instance_method(
166 :meth_ceil,
167 :ceil, [],
168 [VCAN::Int], self
169 )
170 def meth_ceil(loc, env, _event, ndigits)
171 ASSERT.kind_of ndigits, VCAN::Int
172
173 unless ndigits.val >= 0
174 raise X::ArgumentError.new(
175 loc,
176 env,
177 "ceil: expected zero or positive for digits number: %d",
178 ndigits.val.to_i
179 )
180 end
181
182 VC.make_float self.val.ceil(ndigits.val).to_f
183 end
184
185
186 define_instance_method(
187 :meth_floor,
188 :floor, [],
189 [VCAN::Int], self
190 )
191 def meth_floor(loc, env, _event, ndigits)
192 ASSERT.kind_of ndigits, VCAN::Int
193
194 unless ndigits.val >= 0
195 raise X::ArgumentError.new(
196 loc,
197 env,
198 "floor: expected zero or positive for digits number: %d",
199 ndigits.val.to_i
200 )
201 end
202
203 VC.make_float self.val.floor(ndigits.val).to_f
204 end
205
206
207 define_instance_method(
208 :meth_add,
209 :'+', [],
210 [self], self
211 )
212
213
214 define_instance_method(
215 :meth_sub,
216 :'-', [],
217 [self], self
218 )
219
220
221 define_instance_method(
222 :meth_multiply,
223 :'*', [],
224 [self], self
225 )
226
227
228 define_instance_method(
229 :meth_divide,
230 :'/', [],
231 [self], self
232 )
233
234
235 define_instance_method(
236 :meth_modulo,
237 :mod, [],
238 [self], self
239 )
240
241
242 define_instance_method(
243 :meth_power,
244 :pow, [],
245 [self], self
246 )
247 end
248 Float.freeze
249
250 NAN = Atom::Number::Float.new(::Float::NAN).freeze
251 INFINITY = Atom::Number::Float.new(::Float::INFINITY).freeze
252
253 end # Umu::Value::Core::Atom::Number
254
255 end # Umu::Value::Core::Atom
256
257
258 module_function
259
260 def make_float(val)
261 ASSERT.kind_of val, ::Float
262
263 Atom::Number::Float.new(val).freeze
264 end
265
266
267 def make_nan
268 Atom::Number::NAN
269 end
270
271
272 def make_infinity
273 Atom::Number::INFINITY
274 end
275
276 end # Umu::Value::Core
277
278 end # Umu::Value
279
280 end # Umu