PageRenderTime 17ms CodeModel.GetById 12ms app.highlight 2ms RepoModel.GetById 1ms app.codeStats 0ms

/src/lib/numeric/internal/integer_64_number.e

http://github.com/tybor/Liberty
Specman e | 372 lines | 287 code | 50 blank | 35 comment | 14 complexity | 3ee9d65dd140be8a0bd7c8006b3cd182 MD5 | raw file
  1-- This file is part of a Liberty Eiffel library.
  2-- See the full copyright at the end.
  3--
  4class INTEGER_64_NUMBER
  5   --
  6   -- To implement NUMBER (do not use this class, see NUMBER).
  7   --
  8   -- This is an INTEGER_64
  9   --
 10
 11inherit
 12   INTEGER_GENERAL_NUMBER
 13
 14create {ANY}
 15   make
 16
 17feature {ANY}
 18   is_zero: BOOLEAN
 19      do
 20         Result := value = 0
 21      end
 22
 23   is_one: BOOLEAN
 24      do
 25         Result := value = 1
 26      end
 27
 28   is_positive: BOOLEAN
 29      do
 30         Result := value > 0
 31      end
 32
 33   is_negative: BOOLEAN
 34      do
 35         Result := value < 0
 36      end
 37
 38   is_integer_value: BOOLEAN
 39      do
 40         Result := True
 41      end
 42
 43   force_to_real_64: REAL_64
 44      do
 45         Result := value.force_to_real_64
 46      end
 47
 48   append_in (buffer: STRING)
 49      do
 50         buffer.append(value.to_string)
 51      end
 52
 53   append_in_unicode (buffer: UNICODE_STRING)
 54      do
 55         buffer.append(value.to_unicode_string)
 56      end
 57
 58   prefix "-": INTEGER_GENERAL_NUMBER
 59      do
 60         if value = Minimum_integer_64 then
 61            mutable_register1.from_integer_64(Minimum_integer_64)
 62            mutable_register1.negate
 63            Result := mutable_register1.to_integer_general_number
 64         else
 65            create {INTEGER_64_NUMBER} Result.make(-value)
 66         end
 67      end
 68
 69   infix "+" (other: NUMBER): NUMBER
 70      do
 71         Result := other @+ value
 72      end
 73
 74   infix "@+" (other: INTEGER_64): NUMBER
 75      local
 76         sum: INTEGER_64
 77      do
 78         sum := value #+ other
 79         if value < 0 = (other < 0) implies sum < 0 = (value < 0) then
 80            -- no overflow
 81            create {INTEGER_64_NUMBER} Result.make(sum)
 82         else
 83            mutable_register1.from_integer_64(value)
 84            mutable_register1.add_integer_64(other)
 85            Result := mutable_register1.to_integer_general_number
 86         end
 87      end
 88
 89   infix "*" (other: NUMBER): NUMBER
 90      do
 91         if is_zero then
 92            Result := zero
 93         else
 94            Result := other @* value
 95         end
 96      end
 97
 98   infix "@*" (other: INTEGER_64): NUMBER
 99      do
100         if other = 0 or else value = 0 then
101            create {INTEGER_64_NUMBER} Result.make(0)
102         elseif other = 1 then
103            Result := Current
104         elseif value = 1 then
105            create {INTEGER_64_NUMBER} Result.make(other)
106         else
107            mutable_register1.from_integer_64(value)
108            mutable_register2.from_integer_64(other)
109            mutable_register1.multiply_to(mutable_register2, mutable_register3)
110            Result := mutable_register3.to_integer_general_number
111         end
112      end
113
114   infix "@/" (other: INTEGER_64): NUMBER
115      local
116         n, other_number: INTEGER_64_NUMBER; g: INTEGER_64
117      do
118         if value = 0 or else other = 1 then
119            Result := Current
120         elseif other = -1 then
121            if value = Minimum_integer_64 then
122               mutable_register1.from_integer_64(value)
123               mutable_register1.negate
124               Result := mutable_register1.to_integer_general_number
125            else
126               create {INTEGER_64_NUMBER} Result.make(-value)
127            end
128         else
129            g := value.gcd(other)
130            check
131               g /= 0
132            end
133            if g = 1 then
134               create other_number.make(other)
135               if other < 0 then
136                  create {FRACTION_WITH_BIG_INTEGER_NUMBER} Result.make_simply(-Current, -other_number)
137               else
138                  create {FRACTION_WITH_BIG_INTEGER_NUMBER} Result.make_simply(Current, other_number)
139               end
140            elseif other = g or else other = -g then
141               Result := (value // other).to_number
142            elseif other < 0 then
143               create other_number.make(-(other // g))
144               create n.make(-(value // g))
145               create {FRACTION_WITH_BIG_INTEGER_NUMBER} Result.make_simply(n, other_number)
146            else
147               create other_number.make(other // g)
148               create n.make(value // g)
149               create {FRACTION_WITH_BIG_INTEGER_NUMBER} Result.make_simply(n, other_number)
150            end
151         end
152      end
153
154   infix "//" (other: NUMBER): NUMBER
155      local
156         oth: INTEGER_GENERAL_NUMBER
157      do
158         oth ::= other
159         Result := oth.integer_divide_integer_64_number(Current)
160      end
161
162   infix "@//" (other: INTEGER_64): NUMBER
163      do
164         --|*** Must be rewrited directly with integer_64 (Vincent Croizier, 04/07/04) ***
165         put_into_mutable_big_integer(mutable_register1)
166         mutable_register2.from_integer_64(other)
167         mutable_register1.divide_to(mutable_register2, mutable_register3, mutable_register4)
168         Result := mutable_register3.to_integer_general_number
169      end
170
171   infix "\\" (other: NUMBER): NUMBER
172      local
173         oth: INTEGER_GENERAL_NUMBER
174      do
175         oth ::= other
176         Result := oth.remainder_of_divide_integer_64_number(Current)
177      end
178
179   infix "@\\" (other: INTEGER_64): NUMBER
180      do
181         --|*** Must be rewrited directly with integer_64 (Vincent Croizier, 04/07/04) ***
182         put_into_mutable_big_integer(mutable_register1)
183         mutable_register2.from_integer_64(other)
184         mutable_register1.divide_to(mutable_register2, mutable_register3, mutable_register4)
185         Result := mutable_register4.to_integer_general_number
186      end
187
188feature {ANY} -- Misc:
189   hash_code: INTEGER
190      do
191         Result := value.hash_code
192      end
193
194   gcd (other: NUMBER): INTEGER_GENERAL_NUMBER
195      do
196         Result := other.gcd_with_integer_64_number(Current)
197      end
198
199   infix "@=" (other: INTEGER_64): BOOLEAN
200      do
201         Result := value = other
202      end
203
204   infix "@<" (other: INTEGER_64): BOOLEAN
205      do
206         Result := value < other
207      end
208
209   infix "@<=" (other: INTEGER_64): BOOLEAN
210      do
211         Result := value <= other
212      end
213
214   infix "@>" (other: INTEGER_64): BOOLEAN
215      do
216         Result := value > other
217      end
218
219   infix "@>=" (other: INTEGER_64): BOOLEAN
220      do
221         Result := value >= other
222      end
223
224   infix "#=" (other: REAL_64): BOOLEAN
225      do
226         --|*** Vincent, can you check ? *** (Dom Oct 2004) ***
227         Result := value.force_to_real_64 = other
228      end
229
230   infix "#<" (other: REAL_64): BOOLEAN
231      do
232         --|*** Vincent, can you check ? *** (Dom Oct 2004) ***
233         Result := value.force_to_real_64 < other
234      end
235
236   infix "#<=" (other: REAL_64): BOOLEAN
237      do
238         Result := value.force_to_real_64 <= other
239      end
240
241   infix "#>" (other: REAL_64): BOOLEAN
242      do
243         Result := value.force_to_real_64 > other
244         --|*** Vincent, can you check ? *** (Dom Oct 2004) ***
245      end
246
247   infix "#>=" (other: REAL_64): BOOLEAN
248      do
249         Result := value.force_to_real_64 >= other
250         --|*** Vincent, can you check ? *** (Dom Oct 2004) ***
251      end
252
253   infix "<" (other: NUMBER): BOOLEAN
254      do
255         Result := other @> value
256      end
257
258   is_equal (other: NUMBER): BOOLEAN
259      local
260         n2: like Current
261      do
262         if n2 ?:= other then
263            n2 ::= other
264            Result := value = n2.value
265         end
266      end
267
268   inverse: NUMBER
269      do
270         if is_one or else Current @= -1 then
271            Result := Current
272         elseif is_negative then
273            create {FRACTION_WITH_BIG_INTEGER_NUMBER} Result.make_simply(integer_general_number_one_negative, -Current)
274         else
275            create {FRACTION_WITH_BIG_INTEGER_NUMBER} Result.make_simply(integer_general_number_one, Current)
276         end
277      end
278
279feature {NUMBER} -- Implementation:
280   value: INTEGER_64
281
282   add_with_big_integer_number (other: BIG_INTEGER_NUMBER): NUMBER
283      do
284         Result := other @+ value
285      end
286
287   add_with_fraction_with_big_integer_number (other: FRACTION_WITH_BIG_INTEGER_NUMBER): NUMBER
288      do
289         Result := other @+ value
290      end
291
292   multiply_with_big_integer_number (other: BIG_INTEGER_NUMBER): NUMBER
293      do
294         Result := other @* value
295      end
296
297   multiply_with_fraction_with_big_integer_number (other: FRACTION_WITH_BIG_INTEGER_NUMBER): NUMBER
298      do
299         Result := other.multiply_with_integer_64_number(Current)
300      end
301
302   integer_divide_integer_64_number (other: INTEGER_64_NUMBER): INTEGER_GENERAL_NUMBER
303      do
304         Result ::= other @// value
305      end
306
307   integer_divide_big_integer_number (other: BIG_INTEGER_NUMBER): INTEGER_GENERAL_NUMBER
308      do
309         Result ::= other @// value
310      end
311
312   remainder_of_divide_integer_64_number (other: INTEGER_64_NUMBER): INTEGER_GENERAL_NUMBER
313      do
314         Result ::= other @\\ value
315      end
316
317   remainder_of_divide_big_integer_number (other: BIG_INTEGER_NUMBER): INTEGER_GENERAL_NUMBER
318      do
319         Result ::= other @\\ value
320      end
321
322   greater_with_big_integer_number (other: BIG_INTEGER_NUMBER): BOOLEAN
323      do
324         Result := other.is_negative
325      end
326
327   greater_with_fraction_with_big_integer_number (other: FRACTION_WITH_BIG_INTEGER_NUMBER): BOOLEAN
328      do
329         Result := other.denominator * Current > other.numerator
330      end
331
332feature {NUMBER} -- Implementation:
333   gcd_with_integer_64_number (other: INTEGER_64_NUMBER): INTEGER_64_NUMBER
334      do
335         create Result.make(value.gcd(other.value))
336      end
337
338feature {NUMBER}
339   put_into_mutable_big_integer (mut: MUTABLE_BIG_INTEGER)
340      do
341         mut.from_integer_64(value)
342      end
343
344feature {}
345   make (val: INTEGER_64)
346      do
347         value := val
348      ensure
349         Current.to_integer_64 = val
350      end
351
352end -- class INTEGER_64_NUMBER
353--
354-- Copyright (C) 2009-2017: by all the people cited in the AUTHORS file.
355--
356-- Permission is hereby granted, free of charge, to any person obtaining a copy
357-- of this software and associated documentation files (the "Software"), to deal
358-- in the Software without restriction, including without limitation the rights
359-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
360-- copies of the Software, and to permit persons to whom the Software is
361-- furnished to do so, subject to the following conditions:
362--
363-- The above copyright notice and this permission notice shall be included in
364-- all copies or substantial portions of the Software.
365--
366-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
367-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
368-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
369-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
370-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
371-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
372-- THE SOFTWARE.