PageRenderTime 23ms CodeModel.GetById 9ms app.highlight 6ms RepoModel.GetById 1ms app.codeStats 0ms

/src/lib/numeric/integral.e

http://github.com/tybor/Liberty
Specman e | 581 lines | 352 code | 69 blank | 160 comment | 0 complexity | 4c157ff13ecacb916dfd25fc66e54d1c MD5 | raw file
  1-- This file is part of a Liberty Eiffel library.
  2-- See the full copyright at the end.
  3--
  4deferred class INTEGRAL
  5   --
  6   -- General integer abstraction for both integers and naturals.
  7   --
  8
  9inherit
 10   COMPARABLE
 11      undefine infix "<=", infix ">", infix ">=", is_equal
 12      end
 13
 14insert
 15   NUMERIC
 16   PLATFORM
 17
 18feature {ANY}
 19   infix "+" (other: like Current): like Current
 20      require
 21         no_overflow: Current > zero = (other > zero) implies Current #+ other > zero = (Current > zero) -- this means: if operand are of same sign, it will be sign of the Result.
 22      deferred
 23      ensure
 24         Result #- other = Current
 25      end
 26
 27   infix "-" (other: like Current): like Current
 28      require
 29         no_overflow: Current > zero /= (other > zero) implies Current #- other > zero = (Current > zero) -- this means: if operand are of different sign, sign of the Result will be the same sign as Current.
 30      deferred
 31      ensure
 32         Result #+ other = Current
 33      end
 34
 35   infix "*" (other: like Current): like Current
 36      require
 37         no_overflow: (other /= zero) implies Current #* other #// other = Current
 38      deferred
 39      ensure
 40         Current /= zero and other /= zero implies Result /= zero
 41         Result /= zero implies Result #// other = Current
 42         Result /= zero implies Result #\\ other = zero
 43      end
 44
 45   infix "/" (other: like Current): REAL
 46      deferred
 47      end
 48
 49   infix "//" (other: like Current): like Current
 50         -- Quotient of the Euclidian division of `Current' by `other'.
 51         -- The corresponding remainder is given by infix "\\".
 52         --
 53         -- See also infix "#//".
 54      require
 55         other /= zero
 56         no_overflow: other = -one implies Current = zero or Current |<< 1 /= zero
 57      deferred
 58      ensure
 59         euclidian_divide_case1: Current >= zero implies Result * other + Current \\ other = Current
 60         euclidian_divide_case2: Current < zero implies Result #* other #+ (Current \\ other) = Current
 61      end
 62
 63   infix "\\" (other: like Current): like Current
 64         -- Remainder of the Euclidian division of `Current' by `other'.
 65         -- By definition, `zero <= Result < other.abs'.
 66         --
 67         -- See also infix "#\\", infix "//".
 68      require
 69         other /= zero
 70      deferred
 71      ensure
 72         Result >= zero
 73         other |<< 1 /= zero implies Result < other.abs
 74         good_remainder: Result #- (Current #\\ other) #\\ other = zero
 75      end
 76
 77   infix "^" (exp: like Current): INTEGER_64
 78         -- Integer power of `Current' by `other'
 79      require
 80         exp >= zero
 81      deferred
 82      end
 83
 84   abs: like Current
 85         -- Absolute value of `Current'.
 86      require
 87         not_minimum_value: Current < zero implies zero < #-Current
 88      deferred
 89      ensure
 90         Result >= zero
 91      end
 92
 93   infix "<" (other: like Current): BOOLEAN
 94      deferred
 95      end
 96
 97   infix "<=" (other: like Current): BOOLEAN
 98      deferred
 99      end
100
101   infix ">" (other: like Current): BOOLEAN
102      deferred
103      end
104
105   infix ">=" (other: like Current): BOOLEAN
106      deferred
107      end
108
109   prefix "+": like Current
110      deferred
111      end
112
113   prefix "-": like Current
114      require
115         not_minimum_value: Current < zero implies zero < #-Current
116      deferred
117      end
118
119   is_odd: BOOLEAN
120         -- Is odd?
121      deferred
122      end
123
124   is_even: BOOLEAN
125         -- Is even?
126      deferred
127      end
128
129   sqrt: REAL
130         -- Square root of `Current'.
131      require
132         Current >= zero
133      deferred
134      end
135
136   log: REAL
137         -- Natural Logarithm of `Current'.
138      require
139         Current > zero
140      deferred
141      end
142
143   log10: REAL
144         -- Base-10 Logarithm of Current.
145      require
146         Current > zero
147      deferred
148      end
149
150   gcd (other: like Current): like Current
151         -- Greatest Common Divisor of `Current' and `other'.
152      deferred
153      ensure
154         Result >= zero
155         Result = zero implies Current = zero and other = zero
156         Result >= (one + one) implies Current \\ Result = zero and other \\ Result = zero and (Current // Result).gcd(other // Result) = one
157      end
158
159   lcm (other: like Current): like Current
160         -- Least Common Multiple of `Current' and `other'.
161      do
162         Result := abs // gcd(other) * other.abs
163      ensure
164         Result >= zero
165         Result = zero implies Current = zero or other = zero
166         Result * gcd(other) = (Current * other).abs
167      end
168
169feature {ANY} -- Conversions:
170   to_string: STRING
171         -- The decimal view of `Current' into a new allocated STRING.
172         -- For example, if `Current' is -1 the `Result' is "-1".
173         --
174         -- See also `append_in', `to_string_format', `to_unicode_string', `to_hexadecimal', `to_octal'.
175      deferred
176      end
177
178   to_unicode_string: UNICODE_STRING
179         -- The decimal view of `Current' into a new allocated UNICODE_STRING.
180         -- For example, if `Current' is -1 the `Result' is U"-1".
181         --
182         -- See also `append_in_unicode', `to_unicode_string_format', `to_string', `to_hexadecimal', `to_octal'.
183      deferred
184      end
185
186   to_boolean: BOOLEAN
187         -- Return False for 0, otherwise True.
188         --
189         -- See also `to_string', `to_character', `to_hexadecimal', `to_number'.
190      deferred
191      ensure
192         Result = (Current /= zero)
193      end
194
195   to_number: NUMBER
196         -- Convert `Current' into a new allocated NUMBER.
197         --
198         -- See also `to_boolean', `to_string', `to_character', `to_hexadecimal'.
199      deferred
200      ensure
201         Result.to_string.is_equal(to_string)
202      end
203
204   append_in (buffer: STRING)
205         -- Append in the `buffer' the equivalent of `to_string'.
206         -- If you look for performances, you should always prefer `append_in' which allow you to recycle
207         -- a unique common `buffer' (each call of `to_string' allocate a new object!).
208         --
209         -- See also `append_in_format', `append_in_unicode', `append_in_unicode_format', `to_hexadecimal_in'.
210      require
211         buffer /= Void
212      deferred
213      end
214
215   append_in_unicode (buffer: UNICODE_STRING)
216         -- Append in the `buffer' the equivalent of `to_unicode_string'.
217         -- If you look for performances, you should always prefer `append_in_unicode' which allow you to recycle
218         -- a unique common `buffer' (each call of `to_unicode_string' allocate a new object!).
219         --
220         -- See also `append_in_unicode_format', `append_in', `append_in_format', `to_hexadecimal_in'.
221      require
222         buffer /= Void
223      deferred
224      end
225
226   to_string_format (s: INTEGER): STRING
227         -- Same as `to_string' but the result is on `s' character and the number is right aligned.
228         --
229         -- See also `append_in_format', `to_character', `to_number', `to_hexadecimal'.
230      require
231         to_string.count <= s
232      deferred
233      ensure
234         Result.count = s
235      end
236
237   to_unicode_string_format (s: INTEGER): UNICODE_STRING
238         -- Same as `to_unicode_string' but the result is on `s' character and the number is right aligned.
239         --
240         -- See also `append_in_unicode_format', `to_string', `to_hexadecimal', `to_octal'.
241      require
242         to_string.count <= s
243      deferred
244      ensure
245         Result.count = s
246      end
247
248   append_in_format (buffer: STRING; s: INTEGER)
249         -- Append in the `buffer' the equivalent of `to_string_format'.
250         -- If you look for performances, you should always prefer `append_in_format' which allow you to recycle
251         -- a unique common `buffer' (each call of `to_string_format' allocate a new object!).
252         --
253         -- See also `append_in', `append_in_unicode', `append_in_unicode_format', `to_hexadecimal_in'.
254      require
255         to_string.count <= s
256      deferred
257      ensure
258         buffer.count >= old buffer.count + s
259      end
260
261   append_in_unicode_format (buffer: UNICODE_STRING; s: INTEGER)
262         -- Append in the `buffer' the equivalent of `to_unicode_string_format'.
263         -- If you look for performances, you should always prefer `append_in_unicode_format' which allow you to recycle
264         -- a unique common `buffer' (each call of `to_unicode_string_format' allocate a new object!).
265         --
266         -- See also `append_in_format', `append_in', `append_in_format', `to_hexadecimal_in'.
267      require
268         to_string.count <= s
269      deferred
270      ensure
271         buffer.count >= old buffer.count + s
272      end
273
274   digit: CHARACTER
275         -- Legacy synonym for `decimal_digit'.
276         -- Note: already prefer `decimal_digit' because digit may become obsolete (feb 4th 2006).
277      deferred
278      ensure
279         Result = decimal_digit
280      end
281
282   is_decimal_digit: BOOLEAN
283      deferred
284      end
285
286   decimal_digit: CHARACTER
287         -- Gives the corresponding CHARACTER for range 0..9.
288      require
289         is_decimal_digit
290      deferred
291      ensure
292         (once "0123456789").has(Result)
293         --Current.is_equal(Result.value)
294      end
295
296   is_hexadecimal_digit: BOOLEAN
297      deferred
298      end
299
300   hexadecimal_digit: CHARACTER
301         -- Gives the corresponding CHARACTER for range 0..15.
302      require
303         is_hexadecimal_digit
304      deferred
305      ensure
306         (once "0123456789ABCDEF").has(Result)
307      end
308
309   to_character: CHARACTER
310         -- Return the corresponding ASCII character.
311         --
312         -- See also `to_boolean', `to_number', `to_string', `to_hexadecimal'.
313      require
314         Current >= zero
315         --Current <= Maximum_character_code
316      deferred
317      end
318
319   to_octal_in (buffer: STRING)
320         -- Append in the `buffer' the equivalent of `to_octal'.
321         -- If you look for performances, you should always prefer `to_octal_in' which allow you to recycle
322         -- a unique common `buffer' (each call of `to_octal' allocate a new object!).
323         --
324         -- See also `to_hexadecimal_in', `append_in', `append_in_format', `append_in_unicode'.
325      deferred
326      ensure
327         buffer.count = old buffer.count + bit_count #// 3 + 1
328      end
329
330   to_octal: STRING
331         -- The octal view of `Current' into a new allocated STRING.
332         -- For example, if `Current' is -1 and if `Current' is a 16 bits integer the `Result' is "177777".
333         --
334         -- See also `to_octal_in', `to_hexadecimal', `to_number', `to_string'.
335      deferred
336      ensure
337         Result.count = bit_count #// 3 + 1
338      end
339
340   to_hexadecimal: STRING
341         -- The hexadecimal view of `Current' into a new allocated STRING.
342         -- For example, if `Current' is -1 and if `Current' is a 32 bits integer the `Result' is "FFFFFFFF".
343         --
344         -- See also `to_hexadecimal_in', `to_octal', `to_number', `to_string'.
345      deferred
346      ensure
347         Result.count = object_size * 2
348      end
349
350   to_hexadecimal_in (buffer: STRING)
351         -- Append in the `buffer' the equivalent of `to_hexadecimal'.
352         -- If you look for performances, you should always prefer `to_hexadecimal_in' which allow you to recycle
353         -- a unique common `buffer' (each call of `to_hexadecimal' allocate a new object!).
354         --
355         -- See also `to_octal_in', `append_in', `append_in_format', `append_in_unicode'.
356      deferred
357      ensure
358         buffer.count = old buffer.count + object_size * 2
359      end
360
361feature {ANY} -- Bitwise Logical Operators:
362   bit_test (idx: INTEGER_8): BOOLEAN
363         -- The value of the `idx'-ith bit (the right-most bit is at index 0).
364      require
365         idx.in_range(0, bit_count - 1)
366      deferred
367      end
368
369   bit_set (idx: INTEGER_8): like Current
370         -- The value of the `idx'-ith bit (the right-most bit is at index 0).
371      require
372         idx.in_range(0, bit_count - 1)
373      deferred
374      ensure
375         Result.bit_test(idx)
376         Result = Current or Result.bit_reset(idx) = Current
377      end
378
379   bit_reset (idx: INTEGER_8): like Current
380         -- The value of the `idx'-ith bit (the right-most bit is at index 0).
381      require
382         idx.in_range(0, bit_count - 1)
383      deferred
384      ensure
385         not Result.bit_test(idx)
386         Result = Current or Result.bit_set(idx) = Current
387      end
388
389   infix "|>>", bit_shift_right (s: INTEGER_8): like Current
390         -- Shift by `s' positions right (sign bit copied) bits falling off the end are lost.
391      require
392         s.in_range(0, bit_count - 1)
393      deferred
394      end
395
396   infix "|>>>", bit_shift_right_unsigned (s: INTEGER_8): like Current
397         -- Shift by `s' positions right (sign bit not copied) bits falling off the end are lost.
398      require
399         s.in_range(0, bit_count - 1)
400      deferred
401      end
402
403   infix "|<<", bit_shift_left (s: INTEGER_8): like Current
404         -- Shift by `s' positions left bits falling off the end are lost.
405      require
406         s.in_range(0, bit_count - 1)
407      deferred
408      end
409
410   infix "#>>", bit_rotate_right (s: INTEGER_8): like Current
411         -- Rotate by `s' positions right.
412         --
413         -- See also `bit_rotate_left' and `bit_rotate'.
414      require
415         s.in_range(1, bit_count - 1)
416      deferred
417      end
418
419   infix "#<<", bit_rotate_left (s: INTEGER_8): like Current
420         -- Rotate by `s' positions left.
421         --
422         -- See also `bit_rotate_right' and `bit_rotate'.
423      require
424         s.in_range(1, bit_count - 1)
425      deferred
426      end
427
428   bit_rotate (s: INTEGER_8): like Current
429         -- Rotate by `s' positions (positive `s' shifts right, negative left
430         --
431         -- See also `bit_rotate_right' and `bit_rotate_left'.
432      require
433         s.in_range(- (bit_count - 1), bit_count - 1)
434      deferred
435      end
436
437   prefix "~", bit_not: like Current
438         -- One's complement of `Current'.
439      deferred
440      end
441
442   infix "&", bit_and (other: like Current): like Current
443         -- Bitwise logical and of `Current' with `other'.
444      deferred
445      end
446
447   infix "|", bit_or (other: like Current): like Current
448         -- Bitwise logical inclusive or of `Current' with `other'.
449      deferred
450      end
451
452   bit_xor (other: like Current): like Current
453         -- Bitwise logical exclusive or of `Current' with `other'.
454      deferred
455      end
456
457   bit_shift (s: INTEGER_8): like Current
458         -- Shift by `s' positions (positive `s' shifts right (sign bit
459         -- copied), negative shifts left bits falling off the end are lost).
460         --
461         -- See also infix "|>>" and infix "|<<".
462      require
463         s /= 0
464      deferred
465      end
466
467   bit_shift_unsigned (s: INTEGER_8): like Current
468         -- Shift by `s' positions (positive `s' shifts right (sign bit not
469         -- copied), negative left bits falling off the end are lost).
470         --
471         -- See also infix "|>>>" and infix "|<<".
472      require
473         s /= 0
474      deferred
475      end
476
477feature {ANY} -- Miscellaneous:
478   sign: INTEGER_8
479         -- Sign of `Current' (0 or -1 or 1).
480      deferred
481      end
482
483   divisible (other: like Current): BOOLEAN
484      deferred
485      ensure
486         definition: Result = (other /= zero)
487      end
488
489   is_a_power_of_2: BOOLEAN
490         -- Is `Current' a power of 2?
491      require
492         Current > zero
493      deferred
494      end
495
496feature {ANY} -- Modular arithmetic (these wrap around on overflow)
497   infix "#+" (other: like Current): like Current
498      deferred
499      end
500
501   prefix "#-": like Current
502      deferred
503      end
504
505   infix "#-" (other: like Current): like Current
506      deferred
507      end
508
509   infix "#*" (other: like Current): like Current
510      deferred
511      end
512
513   infix "#//" (other: like Current): like Current
514         -- Integer division of `Current' by `other'.
515         --
516         -- According to the ANSI C99: if `Current' and `other' are both non-negative, the `Result' is the
517         -- quotient of the Euclidian division; but this is not the general case, the `Result' value is the
518         -- algebraic quotient `Current/other' with any fractional part discarded. (This is often called
519         -- "truncated toward zero"). So, the corresponding remainder value only verifies the expression
520         -- `remainder.abs < other.abs'.
521         --
522         -- See also infix "//", infix "#\\".
523      require
524         other /= zero
525      deferred
526      ensure
527         Result * other + Current #\\ other = Current
528         ansi_c_remainder: (other |<< 1 /= zero) implies (Current - Result * other).abs < other.abs
529         ansi_c_good_case: Current >= zero and other > zero implies Current - Result * other >= zero
530      end
531
532   infix "#\\" (other: like Current): like Current
533         -- Remainder of the integer division of `Current' by `other'.
534         -- According to the ANSI C99:
535         --   * if `Current' and `other' are both non-negative,
536         --     the `Result' is the remainder of the Euclidian division.
537         --   * but this is not the general case,
538         --     `Result' as the same sign as `Current' and only verify
539         --     the expression `Result.abs < other.abs'.
540         --
541         -- See also infix "\\", infix "#//".
542      require
543         other /= zero
544      deferred
545      ensure
546         (Current - Result) #\\ other = zero
547         ansi_c_remainder: (other |<< 1 /= zero) implies Result.abs < other.abs
548         ansi_c_good_case: (Current >= zero and other > zero) implies Result >= zero
549      end
550
551feature {}
552   bit_count: INTEGER_8
553         -- Well, it is 8 for INTEGER_8, 16 for INTEGER_16 and so on.
554         -- Note that this feature is not exported because this information is part of the type.
555         -- This is actually used only for assertion here, in INTEGER_GENERAL.
556      deferred
557      ensure
558         Result = (object_size * 8)
559      end
560
561end -- class INTEGRAL
562--
563-- Copyright (C) 2009-2017: by all the people cited in the AUTHORS file.
564--
565-- Permission is hereby granted, free of charge, to any person obtaining a copy
566-- of this software and associated documentation files (the "Software"), to deal
567-- in the Software without restriction, including without limitation the rights
568-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
569-- copies of the Software, and to permit persons to whom the Software is
570-- furnished to do so, subject to the following conditions:
571--
572-- The above copyright notice and this permission notice shall be included in
573-- all copies or substantial portions of the Software.
574--
575-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
576-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
577-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
578-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
579-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
580-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
581-- THE SOFTWARE.