|
|
DataMuseum.dkPresents historical artifacts from the history of: Rational R1000/400 Tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Rational R1000/400 Tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: B T
Length: 5066 (0x13ca)
Types: TextFile
Names: »B«
└─⟦180fe333a⟧ Bits:30000405 8mm tape, Rational 1000, SW CATALOG, 10_20_0
└─⟦180fe333a⟧ Bits:30000537 8mm tape, Rational 1000, SW Catalog 10_20_0
└─⟦5cb1d1d7f⟧ »DATA«
└─⟦3b1ee7bd8⟧
└─⟦this⟧
with System;
package body Natural_Package is
--==================================================================
-- This package provides the natural log function that returns the
-- log base e of a positive, floating-point number.
--
-- This package attempts to do some minimal numerical analysis in
-- order to compute the result to the requested accuracy. The
-- expression for the termination of the loop comes from the book
-- "Portability and Style in Ada" by Nissen and Wallis.
--
-- The method used to compute the natural log is based on the
-- Taylor series expansion for ln x:
-- ln(x) = 2 * { (x-1)/(x+1) +
-- 1/3[(x-1)/(x+1)]**3 +
-- 1/5[(x-1)/(x+1)]**5 + ...}
--
-- The accuracy of the calcuation is improved by first by using the
-- mathmatical property that ln(e**x) = x*ln(e) = x. In this case,
-- the number being passed into the log function is repeatedly
-- divided by e to find out the highest power of e that is a factor
-- of the argument. This power then becomes the characteristic of
-- the log function. The remainder of the log function is then
-- put into the Taylor series and it's value calculated. This is
-- then the mantissa of the log of the argument.
--
-- The exception Negative_Log is raised if the argument to the
-- log function is <= 0.0
--
-- The exception Value_To_Large is raised if the argument to the
-- log function causes an overflow to occur. (i.e. if Numeric_Error
-- or Constraint_Error is raised).
--
-- Version 2.0 December 5, 1985
--
-- Written by Brad Balfour with help and suggestions from
-- Ed Berard, Johan Margono and Gary Russell
--==================================================================
function Log (Of_Value : in Argument) return Return_Value is
--===============================================================
--
-- calculates the natural log of a positive floating point number
-- as described above
--
-- Version 2.0 December 5, 1985
--
-- Written by Brad Balfour with help and suggestions from
-- Ed Berard, Johan Margono and Gary Russell
--===============================================================
type Accurate_Float is digits System.Max_Digits;
-- a very accurate floating point number used for
-- all internal calculations
Copy_Of_Value : Accurate_Float := Accurate_Float (Of_Value);
-- a copy of the argument that may be changed
Single_Term : Accurate_Float := 0.0;
-- holds a single term in the series
Characteristic : Accurate_Float := 0.0;
-- holds the characteritic of the log value
New_Log_Value : Accurate_Float := 0.0;
-- accumulates the new log value mantissa
type Exponent is range 1 .. System.Max_Int;
-- this holds the exponent for the Taylor series
Current_Exponent : Exponent := 1;
-- holds the exponent for the current term in the series
Fraction : Accurate_Float;
-- contains the expression used in the Taylor series
E : constant := 2.718_281_828_459_045_235_360_287; --...
-- the natural logarithm base
begin
-- Log
if Of_Value <= 0.0 then
raise Negative_Log;
else
-- ok to compute the log
Find_Characteristic:
while Copy_Of_Value > E loop
Copy_Of_Value := Copy_Of_Value / E;
Characteristic := Characteristic + 1.0;
-- add 1 to the characteristic
end loop Find_Characteristic;
--
-- Now 0 <= Copy_Of_Value < E
--
if Copy_Of_Value /= 0.0 then
-- was not an exact multiple of E. calc. mantissa
Fraction := (Copy_Of_Value - 1.0) / (Copy_Of_Value + 1.0);
-- used in the Taylor series
Compute_Mantissa:
loop
-- must do at least one term to know if it
-- is accurate
Single_Term := (Fraction **
Integer (Current_Exponent)) /
Accurate_Float (Current_Exponent);
exit Compute_Mantissa when
Single_Term <= (New_Log_Value *
Accurate_Float'Epsilon);
New_Log_Value := New_Log_Value + Single_Term;
Current_Exponent := Current_Exponent + 1;
end loop Compute_Mantissa;
end if;
return Return_Value ((2.0 * New_Log_Value) + Characteristic);
end if;
exception
when Numeric_Error | Constraint_Error =>
raise Value_Too_Large;
end Log;
end Natural_Package;