-- 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 -- deferred class ABSTRACT_FRACTION -- -- To implement NUMBER (do not use this class, see NUMBER). -- inherit NUMBER feature is_zero: BOOLEAN is false is_one: BOOLEAN is false frozen to_integer: INTEGER is do check false end end infix "@=" (other: INTEGER): BOOLEAN is do end infix "//"(other: NUMBER): NUMBER is do check false end end infix "@//"(other: INTEGER): NUMBER is do check false end end infix "\\"(other: NUMBER): NUMBER is do check false end end infix "@\\"(other: INTEGER): NUMBER is do check false end end feature {NUMBER} from_two_integer(n, d: INTEGER): NUMBER is local num, den, g: INTEGER do g := n.abs.gcd(d.abs) num := n.abs // g den := d.abs // g if (den = 1) then if (n < 0) xor (d < 0) then !SMALL_INTEGER!Result.make(-num) else !SMALL_INTEGER!Result.make(num) end else if (n < 0) xor (d < 0) then !INTEGER_FRACTION!Result.make(-num,den) else !INTEGER_FRACTION!Result.make(num,den) end end end from_two_abstract_integer(n, d: ABSTRACT_INTEGER): NUMBER is local num, den : ABSTRACT_INTEGER n_abs, g: ABSTRACT_INTEGER do n_abs ?= n.abs g := n_abs.gcd(d.abs) if (g @= 1) then num := n den := d else num ?= n // g den ?= d // g end if (den.is_one) then Result := num else num ?= num.abs den ?= den.abs if num.is_small_integer and then den.is_small_integer and then (n.is_negative xor d.is_negative) then !INTEGER_FRACTION!Result.make(-num.to_integer,den.to_integer) elseif (num.is_small_integer and then den.is_small_integer) then !INTEGER_FRACTION!Result.make(num.to_integer,den.to_integer) else !NUMBER_FRACTION!Result.make_simply(num,den,(n.is_negative xor d.is_negative)) end end end from_integer_and_abstract_integer(n: INTEGER; d: ABSTRACT_INTEGER): NUMBER is require d /= Void local num: ABSTRACT_INTEGER do if n >= Base then !LARGE_POSITIVE_INTEGER!num.make_smaller(n) elseif n <= -Base then !LARGE_NEGATIVE_INTEGER!num.make_smaller(n) else !SMALL_INTEGER!num.make(n) end Result := from_two_abstract_integer(num,d) end from_abstract_integer_and_integer(n: ABSTRACT_INTEGER; d: INTEGER): NUMBER is require n /= Void local den: ABSTRACT_INTEGER do if d >= Base then !LARGE_POSITIVE_INTEGER!den.make_smaller(d) elseif d <= -Base then !LARGE_NEGATIVE_INTEGER!den.make_smaller(d) else !SMALL_INTEGER!den.make(d) end Result := from_two_abstract_integer(n,den) end feature {NONE} decimal_in(buffer: STRING; numerator, denominator: NUMBER; negative: BOOLEAN digits: INTEGER; all_digits: BOOLEAN) is local n, div, remainder: NUMBER; counter: INTEGER do n := numerator if negative then buffer.extend('-') end div := (n // denominator) div.append_in(buffer) remainder := n \\ denominator if digits > 0 then if all_digits or else not (remainder @= 0) then buffer.extend('.') from counter := 1 until (counter > digits) or else (remainder @= 0) loop n := remainder @* 10 ; (n // denominator).append_in(buffer) remainder := n \\ denominator counter := counter + 1 end if all_digits then from until counter > digits loop buffer.extend('0') counter := counter + 1 end end end end end end -- class ABSTRACT_FRACTION