class interface MUTABLE_BIG_INTEGER
--
-- A class used to represent multiprecision integers that makes efficient use
-- of allocated space by allowing a number to occupy only part of an array so
-- that the arrays do not have to be reallocated as often. When performing an
-- operation with many iterations the array used to hold a number is only
-- reallocated when necessary and does not have to be the same size as the
-- number it represents. A mutable number allows calculations to occur on the
-- same number without having to create a new number for every step of the
-- calculation as it occurs with NUMBERs.
--
creation
from_integer (value: INTEGER)
-- Create or initialize Current using value as an initializer.
ensure
to_integer = value
from_integer_64 (value: INTEGER_64)
-- Create or set Current using value as an initializer.
ensure
to_integer_64 = value
copy (other: like Current)
-- Update current object using fields of object attached
-- to other, so as to yield equal objects.
-- Note: you can't copy object from a different dynamic type.
require
same_dynamic_type(other)
ensure
is_equal(other)
feature(s) from HASHABLE
hash_code: INTEGER
-- The hash-code value of Current.
ensure
good_hash_value: Result >= 0
feature(s) from COMPARABLE
is_equal (other: like Current): BOOLEAN
-- Is other attached to an object considered equal to
-- current object ?
require
other /= Void
ensure
trichotomy: Result = (not (Current < other) and not (other < Current));
generating_type = other.generating_type implies Result = other.is_equal(Current)
infix "<" (other: like Current): BOOLEAN
-- Is Current strictly less than other?
require
other_exists: other /= Void
ensure
asymmetric: Result implies not (other < Current)
infix "<=" (other: like Current): BOOLEAN
-- Is Current less than or equal other?
require
other_exists: other /= Void
ensure
definition: Result = (Current < other or is_equal(other))
infix ">" (other: like Current): BOOLEAN
-- Is Current strictly greater than other?
require
other_exists: other /= Void
ensure
definition: Result = (other < Current)
infix ">=" (other: like Current): BOOLEAN
-- Is Current greater than or equal than other?
require
other_exists: other /= Void
ensure
definition: Result = (other <= Current)
in_range (lower, upper: like Current): BOOLEAN
-- Return True if Current is in range [lower..upper]
ensure
Result = (Current >= lower and Current <= upper)
compare (other: like Current): INTEGER
-- If current object equal to other, 0
-- if smaller, -1; if greater, 1.
require
other_exists: other /= Void
ensure
equal_zero: Result = 0 = is_equal(other);
smaller_negative: Result = -1 = (Current < other);
greater_positive: Result = 1 = (Current > other)
three_way_comparison (other: like Current): INTEGER
-- If current object equal to other, 0
-- if smaller, -1; if greater, 1.
require
other_exists: other /= Void
ensure
equal_zero: Result = 0 = is_equal(other);
smaller_negative: Result = -1 = (Current < other);
greater_positive: Result = 1 = (Current > other)
min (other: like Current): like Current
-- Minimum of Current and other.
require
other /= Void
ensure
Result <= Current and then Result <= other;
compare(Result) = 0 or else other.compare(Result) = 0
max (other: like Current): like Current
-- Maximum of Current and other.
require
other /= Void
ensure
Result >= Current and then Result >= other;
compare(Result) = 0 or else other.compare(Result) = 0
feature(s) from MUTABLE_BIG_INTEGER
-- Creation / initialization from INTEGER_32 or INTEGER_64:
from_integer (value: INTEGER)
-- Create or initialize Current using value as an initializer.
ensure
to_integer = value
is_integer: BOOLEAN
-- Do Current fit on an INTEGER_32?
ensure
Result implies is_integer_64;
Result implies integer_length <= 1
to_integer: INTEGER
-- Convert Current as a 32 bit INTEGER.
require
is_integer
from_integer_64 (value: INTEGER_64)
-- Create or set Current using value as an initializer.
ensure
to_integer_64 = value
is_integer_64: BOOLEAN
-- Do Current fit on an INTEGER_64?
ensure
not Result implies not is_integer;
Result implies integer_length <= 2
to_integer_64: INTEGER_64
-- Convert Current as a INTEGER_64.
require
is_integer_64
feature(s) from MUTABLE_BIG_INTEGER
-- Conversion tool
to_double: DOUBLE
-- only a tool
-- unsigned conversion
feature(s) from MUTABLE_BIG_INTEGER
-- Addition:
add (other: like Current)
-- Add other into Current.
-- (See also add_integer add_integer_64 and add_natural.)
require
other /= Void
add_to (other, res: like Current)
-- Add other and Current, and put the result in res.
require
other /= Void;
res /= Void;
res /= Current;
res /= other
add_integer (other: INTEGER)
-- Add other into Current.
add_integer_64 (other: INTEGER_64)
-- Add other into Current.
add_natural (other: like Current)
-- Same behavior as add, but this one works only when Current
-- and other are both positive numbers and are both greater than
-- zero. The only one advantage of using add_natural instead of the
-- general add is the gain of efficiency.
require
not is_zero and not is_negative;
not other.is_zero and not other.is_negative
feature(s) from MUTABLE_BIG_INTEGER
-- Subtract:
subtract (other: like Current)
-- Subtract other from Current.
require
other /= Void
subtract_to (other, res: like Current)
-- Subtract other from Current and put it in res.
require
other /= Void;
res /= Void;
res /= Current;
res /= other
subtract_integer (other: INTEGER)
feature(s) from MUTABLE_BIG_INTEGER
-- To divide:
divide (other: like Current)
-- Put the the quotient of the Euclidian division of
-- Current by other in Current.
-- (The contents of other is not changed.)
require
not other.is_zero;
other /= Current
mod (other: like Current)
-- Put the the remainder of the Euclidian division of
-- Current by other in Current.
-- (The contents of other is not changed.)
require
not other.is_zero;
other /= Current
ensure
not negative and abs_compare(other) = -1
divide_with_remainder_to (other, remainder: like Current)
-- Euclidian division.
-- Calculates the quotient and remainder of Current
-- divided by other.
-- Quotient is put in Current.
-- (The contents of other is not changed.)
require
not other.is_zero;
remainder /= Void;
remainder /= other;
remainder /= Current
ensure
not remainder.negative and remainder.abs_compare(other) = -1
remainder_with_quotient_to (other, quotient: like Current)
-- Euclidian division.
-- Calculates the quotient and remainder of Current
-- divided by other.
-- Remainder is put in Current.
-- (The contents of other is not changed.)
--
-- Note: Uses Algorithm D in Knuth section 4.3.1.
require
not other.is_zero;
quotient /= Void;
quotient /= other;
quotient /= Current
ensure
not negative and abs_compare(other) = -1
divide_to (other, quotient, remainder: like Current)
-- Euclidian division.
-- Calculates the quotient and remainder of Current
-- divided by other. (The contents of Current and other are
-- not changed.)
--
-- Note: Uses Algorithm D in Knuth section 4.3.1.
require
not other.is_zero;
quotient /= Void;
remainder /= Void;
quotient /= other;
quotient /= Current;
remainder /= other;
remainder /= Current
ensure
is_a_good_divide(other,quotient,remainder);
not remainder.negative and remainder.abs_compare(other) = -1
shift_left (n: INTEGER)
-- Shift bits of magnitude by n position left. (Note that no bit can
-- be lost because the storage area is automatically extended when
-- it is necessary.)
require
n > 0
shift_right (n: INTEGER)
-- Right shift Current n bits. (Current is left in normal form.)
require
n > 0
feature(s) from MUTABLE_BIG_INTEGER
-- GCD
gcd (other: like Current)
-- Compute GCD of Current and other.
-- GCD is put in Current (other is not modified).
require
other /= Void
ensure
is_positive;
is_zero implies other.is_zero
feature(s) from MUTABLE_BIG_INTEGER
-- To multiply:
multiply (other: like Current)
-- Multiply Current by other.
require
other /= Void
multiply_to (other, res: like Current)
-- Multiply the contents of Current and other and place the
-- result in res. (Current and other are not modified.)
require
other /= Void;
res /= Void;
res /= Current
multiply_integer (other: INTEGER; res: like Current)
-- Multiply the contents of Current and other and place the
-- result in res. (Current is not modified.)
require
res /= Current;
res /= Void
feature(s) from MUTABLE_BIG_INTEGER
-- to multiply
multiply_like_human (other: like Current)
-- Simple multiply.
-- Complexity = O(integer_length*other.integer_length).
require
not is_zero;
not other.is_zero
multiply_like_human_aux (other: like Current)
-- Only used by multiply_to_like_human.
require
not is_zero;
not other.is_zero;
offset >= other.integer_length
multiply_like_human_aux_reverse (other: like Current)
-- Only used by multiply_to_like_human.
require
not is_zero;
not other.is_zero;
offset + integer_length <= capacity - other.integer_length
multiply_to_like_human (other, res: like Current)
-- Simple multiply.
-- Complexity = O(integer_length*other.integer_length).
require
res /= Current;
not is_zero;
not other.is_zero
feature(s) from MUTABLE_BIG_INTEGER
-- Comparison:
is_zero: BOOLEAN
-- Is it 0?
ensure
Result implies not is_negative
is_one: BOOLEAN
-- Is it 1?
ensure
Result implies not is_negative
is_one_negative: BOOLEAN
-- Is it -1 ?
ensure
Result implies is_negative
is_negative: BOOLEAN
-- Is Current negative integer?
is_positive: BOOLEAN
-- Is Current positive (or equal to zero) integer?
is_even: BOOLEAN
-- Is Current even?
ensure
Result = not Current.is_odd
is_odd: BOOLEAN
-- Is Current odd?
ensure
Result = not Current.is_even
abs_compare (other: like Current): INTEGER
-- Compare the magnitude of Current and other. Returns -1, 0 or 1
-- as this MutableBigInteger is numerically less than, equal to, or
-- greater than other.
feature(s) from MUTABLE_BIG_INTEGER
-- Printing:
to_string: STRING
-- Create a decimal view of the Current big integer.
-- Note: see also append_in to save memory.
append_in (buffer: STRING)
-- Append in the buffer the equivalent of to_string. No new
-- STRING creation during the process.
require
is_printable
is_printable: BOOLEAN
-- True if decimal view of Current is short enougth
-- to be put in a STRING.
out_in_tagged_out_memory
-- Append terse printable represention of current object
-- in tagged_out_memory.
ensure
not_cleared: tagged_out_memory.count >= old tagged_out_memory.count;
append_only: (old tagged_out_memory.twin).is_equal(tagged_out_memory.substring(1,old tagged_out_memory.count))
fill_tagged_out_memory
-- Append a viewable information in tagged_out_memory in
-- order to affect the behavior of out, tagged_out, etc.
feature(s) from MUTABLE_BIG_INTEGER
-- Miscellaneous:
negate
-- Negate the sign of Current.
abs
-- Absolute value of Current.
set_with_zero
ensure
is_zero
copy (other: like Current)
-- Update current object using fields of object attached
-- to other, so as to yield equal objects.
-- Note: you can't copy object from a different dynamic type.
require
same_dynamic_type(other)
ensure
is_equal(other)
swap_with (other: like Current)
-- Swap the value of Current with the value of other.
ensure
-- *** other.to_string.is_equal(old to_string)
-- *** Current.to_string.is_equal(old other.to_string)
feature(s) from MUTABLE_BIG_INTEGER
storage: NATIVE_ARRAY[INTEGER]
-- Holds the magnitude of Current in natural order (the most
-- significant INTEGER_32 word has the highest address). To avoid many
-- reallocation of this storage area, only some words are
-- significant. The magnitude is stored in the following significant
-- range [offset .. offset + integer_length - 1].
capacity: INTEGER
-- Of the allocated storage area.
integer_length: INTEGER
-- The number of significant INTEGER_32 words in the storage area.
offset: INTEGER
-- The offset of the less significant word into the storage area.
negative: BOOLEAN
-- True when Current is negative.
item (index: INTEGER): INTEGER
require
-- index.in_range(0, capacity - 1)
index.in_range(offset,offset + integer_length - 1)
put (value: INTEGER; index: INTEGER)
require
index.in_range(0,capacity - 1)
set_negative (n: BOOLEAN)
require
n implies not is_zero
ensure
negative = n or is_zero
set_integer_length (il: INTEGER)
require
il.in_range(0,capacity - offset)
ensure
integer_length = il
set_offset (o: INTEGER)
require
o.in_range(0,capacity - integer_length)
ensure
offset = o
set_ilo (il: INTEGER; o: INTEGER)
require
il.in_range(0,capacity);
o.in_range(0,capacity - il)
ensure
integer_length = il;
offset = o
set_storage (new_storage: NATIVE_ARRAY[INTEGER])
set_capacity (new_capacity: INTEGER)
set_all (new_storage: NATIVE_ARRAY[INTEGER]; new_capacity, new_integer_length, new_offset: INTEGER; new_negative: BOOLEAN)
require
new_capacity > 0;
new_storage.is_not_null;
new_integer_length.in_range(0,new_capacity);
new_integer_length /= 0 implies new_offset.in_range(0,new_capacity - new_integer_length) and new_storage.item(new_offset + new_integer_length - 1) /= 0;
new_integer_length = 0 implies not new_negative;
new_capacity.is_a_power_of_2
ensure
storage = new_storage;
capacity = new_capacity;
integer_length = new_integer_length;
offset = new_offset;
negative = new_negative
primitive_shift_left (n: INTEGER_8)
-- Left shift Current with no need to extend the storage.
-- *** Can be a little faster (Vincent Croizier, 26/04/04) ***
require
integer_length > 0;
n.in_range(1,31);
no_bit_lost: item(offset + integer_length - 1) |<< n |>>> n = item(offset + integer_length - 1)
primitive_shift_right (n: INTEGER_8)
-- Right shift Current of n bits.
require
integer_length > 0;
n.in_range(1,31)
ensure
offset = 0
divide_one_word (divisor: INTEGER): INTEGER
-- This method is used by divide. The one word divisor is
-- specified by divisor is saw as unsigned.
-- Current is the dividend (saw positive) at invocation but is replaced by
-- the quotient. The remainder is returned as unsigned INTEGER.
-- Note: Current is modified by this method.
require
divisor /= 0
divide_sign_correction (other, quotient, remainder: like Current)
-- Correct the value of quotient and remainder after an
-- "unsigned" division.
-- Only used by divide.
require
remainder.is_positive
ensure
remainder.is_positive
divide_sign_correction_bis (other, quotient: like Current; current_negative: BOOLEAN)
-- Correct the value of quotient and remainder after an
-- "unsigned" division.
-- Only used by divide.
require
is_positive
ensure
is_positive
multiply_and_subtract (u1, qhat: INTEGER; d_storage: NATIVE_ARRAY[INTEGER]; d_offset: INTEGER; r_storage: NATIVE_ARRAY[INTEGER]; r_offset, length: INTEGER): BOOLEAN
-- Only used by divide.
require
qhat /= 0
add_back (old_u1: INTEGER; d_storage: NATIVE_ARRAY[INTEGER]; d_offset: INTEGER; r_storage: NATIVE_ARRAY[INTEGER]; r_offset, length: INTEGER): BOOLEAN
-- Only used by divide.
-- old_u1 is the value of u1 before multiply_and_subtract.
is_a_good_divide (other, quotient, remainder: like Current): BOOLEAN
require
other /= Void;
quotient /= Void;
remainder /= Void
normalize: INTEGER_8
-- Shift left until the most significant bit is on.
-- Result give the number of left shift.
require
not is_zero
ensure
item(offset + integer_length - 1) < 0
feature(s) from MUTABLE_BIG_INTEGER
-- Implementation:
register1: MUTABLE_BIG_INTEGER
register2: MUTABLE_BIG_INTEGER
Double_base: DOUBLE
add_magnitude (other: like Current)
-- Add the magnitude of Current and other regardless of signs.
require
not is_zero;
not other.is_zero
feature(s) from MUTABLE_BIG_INTEGER
-- Implementation:
subtract_magnitude (other: like Current)
-- Subtract other from Current (The result is placed in Current)
-- and change negative (the sign) if necessary.
require
not is_zero;
not other.is_zero
subtract_magnitude_raw (other: like Current)
-- Subtract (raw) the storage of other from Current.
-- Used by subtract_magnitude.
require
not is_zero;
not other.is_zero;
abs_compare(other) = 1
ensure
offset = 0
subtract_magnitude_raw_reverse (other: like Current)
-- Subtract (raw) the storage of Current from other and
-- put it in Current.
-- Used by subtract_magnitude.
require
not is_zero;
not other.is_zero;
abs_compare(other) = -1
ensure
offset = 0
subtract_magnitude_raw_truncated (other: like Current)
-- Subtract (raw) the storage of other from Current
-- where other is truncated to the size of Current.
-- Used by subtract_magnitude.
require
not other.is_zero;
other.integer_length >= integer_length;
unsigned_greater_than(item(offset + integer_length - 1),other.item(offset + integer_length - 1))
ensure
offset = 0
subtract_magnitude_raw_reverse_truncated (other: like Current)
-- Subtract (raw) the storage of Current from other and
-- put it in Current,
-- where other is truncated to the size of Current.
-- Used by subtract_magnitude.
require
not other.is_zero;
other.integer_length >= integer_length;
unsigned_less_than(item(offset + integer_length - 1),other.item(offset + integer_length - 1))
ensure
offset = 0
invariant
capacity > 0;
storage.is_not_null;
integer_length.in_range(0,capacity);
integer_length /= 0 implies offset.in_range(0,capacity - integer_length) and item(offset + integer_length - 1) /= 0;
integer_length = 0 implies not negative;
capacity.is_a_power_of_2;
end of MUTABLE_BIG_INTEGER