-- 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 DOUBLE -- -- DOUBLE is the type for real numbers with more precision than 'REAL' type. -- The precision is not infinite. -- -- Note: An Eiffel DOUBLE is mapped as a C double or as a Java double. -- 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): like Current is external "SmartEiffel" end infix "^" (e: INTEGER): like Current is -- Raise Current to `e'-th power (see also `pow'). external "SmartEiffel" end prefix "+" : like Current is do Result := Current end prefix "-": like Current is external "SmartEiffel" end abs: like Current is do if Current < 0.0 then Result := -Current else Result := Current end end infix "<" (other: like Current): BOOLEAN is external "SmartEiffel" end infix "<=" (other: like Current): BOOLEAN is external "SmartEiffel" end infix ">" (other: like Current): BOOLEAN is external "SmartEiffel" end infix ">=" (other: like Current): BOOLEAN is external "SmartEiffel" end double_floor: like Current is -- Greatest integral value no greater than Current. external "SmartEiffel" end floor: INTEGER is -- Greatest integral value no greater than Current. local d: like Current do d := double_floor Result := d.truncated_to_integer ensure result_no_greater: Result <= Current close_enough: Current - Result < one end double_ceiling: like Current is -- Smallest integral value no smaller than Current. do Result := ceil end ceiling: INTEGER is -- Smallest integral value no smaller than Current. local d: like Current do d := double_ceiling Result := d.truncated_to_integer ensure result_no_smaller: Result >= Current close_enough: Result - Current < one end rounded: INTEGER is -- Rounded integral value. do if double_floor + 0.5 < Current then Result := double_ceiling.truncated_to_integer else Result := double_floor.truncated_to_integer end end truncated_to_integer: INTEGER is -- Integer part (same sign, largest absolute value -- no greater than Current). external "SmartEiffel" ensure Result.to_double <= Current end to_real: REAL is -- Note: C conversion from "double" to "float". -- Thus, Result can be undefine (ANSI C). external "SmartEiffel" end to_string: STRING is -- Convert the DOUBLE into a new allocated STRING. -- As ANSI C, the default number of digit for the -- fractionnal part is 6. -- Note: see `append_in' to save memory. do create Result.make(16) append_in(Result) end append_in(str: STRING) is -- Append the equivalent of `to_string' at the end of -- `str'. Thus you can save memory because no other -- STRING is allocate for the job. require str /= Void do append_in_format(str,6) end to_string_format(f: INTEGER): STRING is -- Convert the DOUBLE into a new allocated STRING including -- only `f' digits in fractionnal part. -- Note: see `append_in_format' to save memory. require f >= 0 do basic_sprintf_double(sprintf_buffer,f,Current) !!Result.from_external_copy(sprintf_buffer.to_pointer) end append_in_format(str: STRING; f: INTEGER) is -- Same as `append_in' but produce `f' digit of -- the fractionnal part. require str /= Void f >= 0 local i: INTEGER do from basic_sprintf_double(sprintf_buffer,f,Current) i := 0 until sprintf_buffer.item(i) = '%U' loop str.extend(sprintf_buffer.item(i)) i := i + 1 end end feature -- Maths functions: sqrt: like Current is -- Square root of `Current' (ANSI C `sqrt'). require Current >= 0 external "SmartEiffel" end sin: like Current is -- Sine of `Current' (ANSI C `sin'). external "SmartEiffel" end cos: like Current is -- Cosine of `Current' (ANSI C `cos'). external "SmartEiffel" end tan: like Current is -- Tangent of `Current' (ANSI C `tan'). external "SmartEiffel" end asin: like Current is -- Arc Sine of `Current' (ANSI C `asin'). external "SmartEiffel" end acos: like Current is -- Arc Cosine of `Current' (ANSI C `acos'). external "SmartEiffel" end atan: like Current is -- Arc Tangent of `Current' (ANSI C `atan'). external "SmartEiffel" end atan2(x: like Current): like Current is -- Arc Tangent of `Current' / `x' (ANSI C `atan2'). external "SmartEiffel" end sinh: like Current is -- Hyperbolic Sine of `Current' (ANSI C `sinh'). external "SmartEiffel" end cosh: like Current is -- Hyperbolic Cosine of `Current' (ANSI C `cosh'). external "SmartEiffel" end tanh: like Current is -- Hyperbolic Tangent of `Current' (ANSI C `tanh'). external "SmartEiffel" end exp: like Current is -- Exponential of `Current' (ANSI C `exp'). external "SmartEiffel" end log: like Current is -- Natural Logarithm of `Current' (ANSI C `log'). external "SmartEiffel" end log10: like Current is -- Base-10 Logarithm of Current (ANSI C `log10'). external "SmartEiffel" end pow(e: like Current): like Current is -- `Current' raised to the power of `e' (ANSI C `pow'). 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 Current < 0.0 then Result := -1 elseif 0.0 < Current then Result := 1 else Result := 0 end end one: DOUBLE is 1.0 zero: DOUBLE is 0.0 divisible(other: like Current): BOOLEAN is do Result := (other /= 0.0) end feature -- Hashing: hash_code: INTEGER is do Result := truncated_to_integer if Result < 0 then Result := - (Result + 1) end end feature -- For compatibility with the obsolete DOUBLE_REF style: item: DOUBLE set_item(value: like item) is do item := value ensure item = value end feature {NONE} ceil: like Current is external "SmartEiffel" end basic_sprintf_double(buffer: NATIVE_ARRAY[CHARACTER]; f: INTEGER; d: DOUBLE) is -- Put in the `buffer' a viewable version of Current with -- `f' digit of the fractionnal part. Assume the `buffer' is -- large enougth. require f >= 0 external "SmartEiffel" end sprintf_buffer: NATIVE_ARRAY[CHARACTER] is once Result := Result.calloc(1024) end end -- DOUBLE