-- This file is free software, which comes along with SmartEiffel. This -- software 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. You can modify it as you want, provided -- this header is kept unaltered, and a notification of the changes is added. -- You are allowed to redistribute it and sell it, alone or as a part of -- another product. -- Copyright (C) 1994-2002 LORIA - INRIA - U.H.P. Nancy 1 - FRANCE -- Dominique COLNET and Suzanne COLLIN - SmartEiffel@loria.fr -- http://SmartEiffel.loria.fr -- expanded class INTEGER_GENERAL -- -- General integer abstraction to share feature definition of INTEGER_8, -- INTEGER_16, INTEGER, INTEGER_32 and INTEGER_64. -- -- If you need integers with bigger values, use NUMBER (lib/number cluster). -- inherit NUMERIC COMPARABLE undefine is_equal, infix "<", infix "<=", infix ">", infix ">=" redefine fill_tagged_out_memory, out_in_tagged_out_memory end feature infix "+" (other: like Current): like Current is external "SmartEiffel" end infix "-" (other: like Current): like Current is external "SmartEiffel" end infix "*" (other: like Current): like Current is external "SmartEiffel" end infix "/" (other: like Current): DOUBLE is external "SmartEiffel" end infix "//" (other: like Current): like Current is external "SmartEiffel" end infix "\\" (other: like Current): like Current is external "SmartEiffel" end infix "^" (exp: like Current): INTEGER_64 is do if exp = 0 then Result := 1 elseif exp \\ 2 = 0 then Result := (item * item) ^ (exp // 2) else Result := item * (item ^ (exp - 1)) end end abs: like Current is -- Absolute value of `Current'. do if item < 0 then Result := - item else Result := Current end end infix "<" (other: like Current): BOOLEAN is -- Is 'Current' strictly less than 'other'? external "SmartEiffel" end infix "<=" (other: like Current): BOOLEAN is -- Is 'Current' less or equal 'other'? external "SmartEiffel" end infix ">" (other: like Current): BOOLEAN is -- Is 'Current' strictly greater than 'other'? external "SmartEiffel" end infix ">=" (other: like Current): BOOLEAN is -- Is 'Current' greater or equal than 'other'? external "SmartEiffel" end prefix "+": like Current is do Result := Current end prefix "-": like Current is external "SmartEiffel" end odd: BOOLEAN is -- Is odd ? do Result := (item \\ 2) = 1 end even: BOOLEAN is -- Is even ? do Result := (item \\ 2) = 0 end sqrt: DOUBLE is -- Compute the square routine. do Result := to_double.sqrt end log: DOUBLE is -- (ANSI C log). do Result := to_double.log end log10: DOUBLE is -- (ANSI C log10). do Result := to_double.log10 end gcd(other: like Current): like Current is -- Great Common Divisor of `Current' and `other'. require Current >= 0 other >= 0 do if other = 0 then Result := Current else Result := other.gcd(item \\ other) end ensure Result = other.gcd(Current) end feature -- Conversions: to_real: REAL is do Result := Current end to_double: DOUBLE is do Result := Current end to_string: STRING is -- Convert the decimal view of `Current' into a new allocated -- STRING. For example, if `Current' is -1 the new STRING is "-1". -- Note: see also `append_in' to save memory. do string_buffer.clear append_in(string_buffer) Result := string_buffer.twin end to_boolean: BOOLEAN is -- Return false for 0, otherwise true. do Result := Current /= 0 ensure Result = (Current /= 0) end fit_integer_8: BOOLEAN is -- Does `Current' fit on an INTEGER_8 ? do if item >= -128 then Result := Current <= 127 end ensure Result = Current.in_range(-128, 127) end to_integer_8: INTEGER_8 is -- Explicit conversion to INTEGER_8. require fit_integer_8 external "SmartEiffel" ensure Current = Result end fit_integer_16: BOOLEAN is -- Does `Current' fit on an INTEGER_16 ? do if item >= -32768 then Result := Current <= 32767 end ensure Result = Current.in_range(-32768, 32767) end to_integer_16: INTEGER_16 is -- Explicit conversion to INTEGER_16. require fit_integer_16 external "SmartEiffel" ensure Current = Result end fit_integer_32, fit_integer: BOOLEAN is -- Does `Current' fit on an INTEGER_32 ? do if item >= -2147483648 then Result := item <= 2147483647 end ensure Result = Current.in_range(-2147483648, 2147483647) end to_integer_32, to_integer: INTEGER_32 is -- Explicit conversion to INTEGER_32. require fit_integer_32 external "SmartEiffel" ensure Current = Result end to_integer_64: INTEGER_64 is -- Explicit conversion to INTEGER_64. do Result := Current ensure Current = Result end to_number: NUMBER is -- *** Note: the require assertion will be removed as soon as -- we will find some time to update the NUMBER hierarchy. -- September 20th 2002 D.Colnet require fit_integer_32 local number_tools: NUMBER_TOOLS do Result := number_tools.from_integer(Current.to_integer) ensure Result @= Current.to_integer end to_bit: BIT Integer_bits is -- Portable BIT_N conversion. external "SmartEiffel" end append_in(buffer: STRING) is -- Append in the `buffer' the equivalent of `to_string'. No new -- STRING creation during the process. require buffer /= Void local val: INTEGER_64; i, idx: INTEGER do if Current = 0 then buffer.extend('0') else if Current > 0 then from i := buffer.count + 1 val := Current until val = 0 loop buffer.extend((val \\ 10).digit) val := val // 10 end else buffer.extend('-') from i := buffer.count + 1 val := Current until val = 0 loop buffer.extend((-(val \\ 10)).digit) val := val // 10 end end from idx := buffer.count until i >= idx loop buffer.swap(i,idx) idx := idx - 1 i := i + 1 end end end to_string_format(s: INTEGER): STRING is -- Same as `to_string' but the result is on `s' character and the -- number is right aligned. -- Note: see `append_in_format' to save memory. require to_string.count <= s local i: like Current do string_buffer.clear append_in(string_buffer) from create Result.make(string_buffer.count.max(s)) i := s - string_buffer.count until i <= 0 loop Result.extend(' ') i := i - 1 end Result.append(string_buffer) ensure Result.count = s end append_in_format(str: STRING; s: like Current) is -- Append the equivalent of `to_string_format' at the end of -- `str'. Thus you can save memory because no other -- STRING is allocate for the job. require to_string.count <= s local i: like Current do string_buffer.clear append_in(string_buffer) from i := s - string_buffer.count until i <= 0 loop str.extend(' ') i := i - 1 end str.append(string_buffer) ensure str.count >= (old str.count) + s end decimal_digit, digit: CHARACTER is -- Gives the corresponding CHARACTER for range 0..9. require in_range(0,9) do Result := (Current + ('0').code).to_character ensure (once "0123456789").has(Result) Result.value = Current end hexadecimal_digit: CHARACTER is -- Gives the corresponding CHARACTER for range 0..15. require in_range(0,15) do if item <= 9 then Result := digit else Result := (('A').code + (item - 10)).to_character end ensure (once "0123456789ABCDEF").has(Result) end to_character: CHARACTER is -- Return the coresponding ASCII character. require Current >= 0 external "SmartEiffel" end to_octal: INTEGER is -- Gives coresponding octal value. -- *** THE RESULT IS OF TYPE INTEGER (not like Current) ... -- ... IS THIS THE RIGHT CHOICE ??? -- *** do if Current = 0 then elseif item < 0 then Result := -((-Current).to_octal) else from string_buffer.clear Result := Current.to_integer until Result = 0 loop string_buffer.extend((Result \\ 8).digit) Result := Result // 8 end string_buffer.reverse Result := string_buffer.to_integer end end to_hexadecimal: STRING is -- Convert the hexadecimal view of `Current' into a new allocated -- STRING. For example, if `Current' is -1 and if `Current' is a -- 32 bits integer the `Result' is "FFFFFFFF". -- Note: see also `to_hexadecimal_in' to save memory. do string_buffer.clear to_hexadecimal_in(string_buffer) Result := string_buffer.twin ensure Result.count = object_size * 2 end to_hexadecimal_in(buffer: STRING) is -- Append in `buffer' the equivalent of `to_hexadecimal'. No new -- STRING creation during the process. local one_digit: like Current; index, times: INTEGER; value: like Current do from value := Current times := object_size * 2 index := buffer.count + times buffer.extend_multiple(' ',times) until times = 0 loop one_digit := value and 15 -- 0xF buffer.put(one_digit.hexadecimal_digit,index) index := index - 1 value := value |>> 4 times := times - 1 end ensure buffer.count = old buffer.count + object_size * 2 end feature -- Hashing: hash_code: INTEGER is do Result := item.to_integer_32 if Result < 0 then Result := -(Result + 1) end end feature -- Bitwise Logical Operators: bit_test(idx: INTEGER): BOOLEAN is -- The value of the `idx'-ith bit. external "SmartEiffel" end bit_shift(s: INTEGER): like Current is -- Shift by `s' positions (positive `s' shifts right (sign bit -- copied), negative shifts left bits falling off the end are lost). -- See also infix "|>>" and infix "|<<". external "SmartEiffel" end bit_shift_unsigned(s: INTEGER): like Current is -- Shift by `s' positions (positive `s' shifts right (sign bit not -- copied), negative left bits falling off the end are lost). -- See also infix "|>>>" and infix "|<<". external "SmartEiffel" end bit_shift_right, infix "|>>" (s: INTEGER): like Current is -- Shift by `s' positions right (sign bit copied) bits falling -- off the end are lost. require s >= 0 external "SmartEiffel" end infix "@>>" (s: INTEGER): like Current is obsolete "Use %"|>>%" instead of %"@>>%" (september 2002)." require s > 0 external "SmartEiffel" end bit_shift_right_unsigned, infix "|>>>" (s: INTEGER): like Current is -- Shift by `s' positions right (sign bit not copied) bits -- falling off the end are lost. require s >= 0 external "SmartEiffel" end bit_shift_left, infix "|<<" (s: INTEGER): like Current is -- Shift by `s' positions left bits falling off the end are lost. require s >= 0 external "SmartEiffel" end infix "@<<" (s: INTEGER): like Current is obsolete "Use %"|<<%" instead of %"@<<%" (september 2002)." require s > 0 external "SmartEiffel" end bit_rotate(s: INTEGER): like Current is -- Rotate by `s' positions (positive `s' shifts -- right, negative left -- See also infix "#>>" and infix "#<<". external "SmartEiffel" end bit_rotate_right, infix "#>>" (s: INTEGER): like Current is -- Rotate by `s' positions right. require s >= 0 external "SmartEiffel" end bit_rotate_left, infix "#<<" (s: INTEGER): like Current is -- Rotate by `s' positions left. require s >= 0 external "SmartEiffel" end bit_not: like Current is -- One's complement of `Current'. external "SmartEiffel" end bit_and, infix "&" (other: like Current): like Current is -- Bitwise logical and of `Current' with `other'. external "SmartEiffel" end bit_or, infix "|" (other: like Current): like Current is -- Bitwise logical inclusive or of `Current' with `other'. external "SmartEiffel" end bit_xor(other: like Current): like Current is -- Bitwise logical exclusive or of `Current' with `other'. external "SmartEiffel" end infix "and" (other: like Current): like Current is -- Bitwise `and' of `Current' with `other' external "SmartEiffel" end prefix "not": like Current is -- Bitwise `not' of `Current'. external "SmartEiffel" end infix "or" (other: like Current): like Current is -- Bitwise `or' of `Current' with `other' external "SmartEiffel" end infix "xor" (other : like Current) : like Current is -- Bitwise `xor' of `Current' with `other' external "SmartEiffel" end feature -- Object Printing: out_in_tagged_out_memory, fill_tagged_out_memory is do Current.append_in(tagged_out_memory) end feature -- Miscellaneous: sign: INTEGER_8 is -- Sign of `Current' (0 -1 or 1). do if item < 0 then Result := -1 elseif 0 < item then Result := 1 else Result := 0 end end one: INTEGER_8 is 1 zero: INTEGER_8 is 0 divisible(other: like Current): BOOLEAN is do Result := (other /= 0) end feature -- For experts only: item: like Current -- The value of `Current' in the corresponding reference type. feature {NONE} string_buffer: STRING is once create Result.make(128) end end -- INTEGER_GENERAL