with ConsAK ; use ConsAK; with FloaAK ; use FloaAK; with InteAK ; use InteAK; with StriAK ; use StriAK; with Text_IO; use Text_IO; with TypeAK ; use TypeAK; package body MathAK is ---------------------------------------------------------------------- -- Copyright (C) 1994 David Wallace Croft. All rights reserved. ---------------------------------------------------------------------- function "**" ( X, Y : float ) return float is ---------------------------------------------------------------------- begin return Exp ( Y * Ln ( X ) ); end "**"; procedure Alpha ( V : in out float; dV_dt : in out float; Stimulus : in float := 0.0; Decay : in float := 1.0; dt : in float := 0.001 ) is ---------------------------------------------------------------------- -- Alpha Function ___ -- V(t) = time * exp ( -Decay * time ) / \______ -- Time_Peak = 1 / Decay ---------------------------------------------------------------------- dV_dt_2 : float; begin dV_dt_2 := Stimulus - 2.0 * Decay * dV_dt - ( Decay ** 2 ) * V; dV_dt := dV_dt + dt * dV_dt_2; V := V + dt * dV_dt; end Alpha; function Crosscorrelation ( X, Y : in Vector_Type ) return Vector_Type is ---------------------------------------------------------------------- -- page 170 and 479, Introduction to Communications Systems -- If X'range = 1..2000, returns -999..1000. -- If X'range = 0..1999, returns -1000..999. ---------------------------------------------------------------------- R : Vector_Type ( X'range ) := ( others => 0.0 ); Slip : Vector_Type ( ( R'last / 2 - R'last + R'first )..( R'last / 2 ) ); T : positive; begin T := X'last - X'first + 1; for Tau in R'range loop for Time in X'range loop if Time + Tau <= Y'last then R ( Tau ) := R ( Tau ) + X ( Time ) * Y ( Time + Tau ); else R ( Tau ) := R ( Tau ) + X ( Time ) * Y ( Time + Tau - Y'last ); end if; end loop; R ( Tau ) := R ( Tau ) / float ( T ); end loop; for Index in R'first..( R'last / 2 ) loop Slip ( Index ) := R ( Index ); end loop; for Index in ( R'last / 2 + 1 )..R'last loop Slip ( Index - R'last + R'first - 1 ) := R ( Index ); end loop; return Slip; end Crosscorrelation; function Characteristic ( InFloat : in float ) return integer is ---------------------------------------------------------------------- -- Rounds towards zero. Example: Characteristic ( -1.999 ) => -1 -- Integer ( float ) will round to the nearest long_integer, or the -- nearest _even_ integer when it is centered ( 0.5 ==> 0.0 ). -- Characteristic ( float ) truncates, instead. ---------------------------------------------------------------------- Temp : integer; begin if ( InFloat >= float ( integer'last ) + 1.0 ) or ( InFloat <= float ( integer'first ) - 1.0 ) then raise Constraint_Error; end if; if Infloat >= 0.0 then Temp := integer ( InFloat - 0.5 ); else Temp := integer ( InFloat ); end if; if abs ( float ( Temp ) ) + 1.0 = abs ( InFloat ) then if InFloat > 0.0 then Temp := Temp + 1; else Temp := Temp - 1; end if; end if; return Temp; end Characteristic; function Combination ( N : in natural; R : in natural ) return float is --------------------------------------------------------------------------- -- The number of ways to form combinations of length r from a set of n -- distinct objects, repetitions not allowed, is denoted by the symbol -- / n \ / n \ n! -- | |, where | | = ---------------. -- \ r / \ r / r! * ( n - r )! -- "An Introduction to Probability and Its Applications" -- by Larsen & Marx, 1985, p117, Theorem 3.3.1. -- constraint_error if not N >= R ---------------------------------------------------------------------- begin return Factorial ( N ) / ( Factorial ( R ) * Factorial ( N - R ) ); end Combination; function Cos ( R : in float ) -- radians return float is ---------------------------------------------------------------------- Temp : float := 1.0; Temp_New : float; R2 : float; Index : positive := 2; Add : boolean := false; Two_Pi : constant float := 2.0 * Pi; begin if abs ( R ) > 2.0 * Pi then R2 := R / Two_Pi; R2 := R2 - float ( Characteristic ( R2 ) ); R2 := R2 * Two_Pi; else R2 := R; end if; loop begin if Add then Temp_New := Temp + ( R2 ** Index ) / Factorial ( Index ); else Temp_New := Temp - ( R2 ** Index ) / Factorial ( Index ); end if; exception when others => return Temp; end; exit when Temp = Temp_New; Temp := Temp_New; Index := Index + 2; Add := not Add; end loop; return Temp; end Cos; procedure Demo is ---------------------------------------------------------------------- use ConsAK; Default : natural := 1; Min : constant natural := 0; Max : constant natural := 13; Option : natural; begin loop Put_Line ( Copyright ); Put_Line ( "" ); Put_Line ( "General math sub-programs package." ); Put_Line ( "" ); Put_Line ( " 0 = Quit" ); Put_Line ( " 1 = ** -- X ** Y, X and Y are of type float" ); Put_Line ( " 2 = Characteristic -- truncates float to integer" ); Put_Line ( " 3 = Combination" ); Put_Line ( " 4 = Cos ( radians )" ); Put_Line ( " 5 = Exp -- exponent of an integer" ); Put_Line ( " 6 = Exp -- exponent of a float" ); Put_Line ( " 7 = Factorial" ); Put_Line ( " 8 = Integrate" ); Put_Line ( " 9 = Interpolate" ); Put_Line ( "10 = Ln -- natural log" ); Put_Line ( "11 = Minimum" ); Put_Line ( "12 = Odd -- returns true if integer is odd" ); Put_Line ( "13 = Sin ( radians )" ); Put_Line ( "" ); Option := Ask_Nat ( "Option ", Default, Min, Max ); Default := Option + 1; if Default > Max then Default := Min; end if; case Option is when 0 => exit; when 1 => declare X : float := 4.0; Y : float := 0.5; begin X := Ask ( "X", X ); Y := Ask ( "Y", Y ); Put_Line ( X ** Y ); end; Pause; when 2 => Put_Line ( Characteristic ( Ask ) ); Pause; when 3 => declare N, R : natural; begin N := Ask_Nat ( "N" ); R := Ask_Nat ( "R" ); Put_Line ( Combination ( N, R ) ); end; Pause; when 4 => Put_Line ( Cos ( Ask ) ); Pause; when 5 => Put_Line ( Exp ( Ask ) ); Pause; when 6 => Put_Line ( Exp ( Ask ) ); Pause; when 7 => declare F : natural; begin F := Ask_Nat ( "F" ); Put_Line ( Factorial ( F ) ); end; Pause; -- when 8 => Integrate; -- when 9 => Interpolate; when 10 => Put_Line ( Ln ( Ask ) ); Pause; when 11 => Put_Line ( Minimum ( Ask, Ask ) ); Pause; when 12 => Put_Line ( Odd ( Ask_Int ( "I" ) ) ); Pause; when 13 => Put_Line ( Sin ( Ask ) ); Pause; when others => Put_Line ( "The demonstration of that option is currently" & " not available." ); Pause; end case; Put_Line ( "" ); end loop; -- exception -- when others => -- ErroAK.Notify ( "MathAK.Demo" ); -- raise; end Demo; function Exp ( I : in integer ) return float is ---------------------------------------------------------------------- begin return E ** I; end Exp; function Exp ( F : in float ) return float is ---------------------------------------------------------------------- Index_Max : constant positive := 10; -- limits accuracy Temp : float := 1.0 + F; -- Temp_1 : float; -- Index : positive := 2; begin if F = 0.0 then return 1.0; elsif F = 1.0 then return E; end if; -- loop -- begin -- Temp_1 := Temp + ( F ** Index ) / Factorial ( Index ); -- exception -- when others => return Temp; -- end; -- exit when Temp = Temp_1; -- Temp := Temp_1; -- Index := Index + 1; -- end loop; for Index in 2..Index_Max loop Temp := Temp + ( F ** Index ) / Factorial ( Index ); end loop; return Temp; exception when others => New_Line; Put_Line ( "Exception in MathAK.Exp!" ); New_Line; raise; end Exp; function Factorial ( X : in natural ) return float is ---------------------------------------------------------------------- Result : float := 1.0; begin for index in 1..X loop Result := Result * float ( index ); end loop; return Result; exception -- when constraint_error => -- ErroADK.Notify ( "MathADK.Factorial", "Constraint_Error" ); -- raise; -- when numeric_error => -- ErroADK.Notify ( "MathADK.Factorial", "Numeric_Error" ); -- raise; when others => New_Line; Put_Line ( "Exception in MathAK.Factorial!" ); New_Line; raise; end Factorial; procedure Integrate ( Y: in out Float_Array; F: in Float_Array_2; E: in float ) is --------------------------------------------------------------------------- -- Euler's method -- -- y'' + 0.1y' + y = 0 becomes -- -- y1 = y -- y2 = y' = 0.0y1 + 1.0y2 F = ( ( 0.0, 1.0 ), -- y3 = y''= -1.0y1 - 0.1y2 ( -1.0, -0.1 ) ) -- -- Y' = ( y1' , = ( y' , = FY = F ( y1 , = F ( y , -- y2' , y'' , y2 , y' , -- y3' ) y''' ) y3 ) y'' ) -- -- Integrate by -- Y_New = Y_Old + Epsilon * F * Y_Old --------------------------------------------------------------------------- -- use DC_Type; --------------------------------------------------------------------------- begin null; -- Y := Y + E * ( F * Y ); -- exception -- when Constraint_Error => -- DC_Errr.Notify ( "DC_Math.Integrate", "Constraint_Error" ); -- raise; end Integrate; -- procedure Interpolate ( -- Completed : out boolean; -- Mid_Point : in out float; -- Rec : in out Interpolate_Type; -- Results : in string := ""; -- Old_File_Name : in string := ""; -- Tmp_File_Name : in string := "" ) is -- ---------------------------------------------------------------------- -- Completed_Temp : boolean := false; -- begin -- if Rec.Start_Over then -- Open ( Rec.Old_File, In_File , Old_File_Name ); -- if End_Of_File ( Rec.Old_File ) then -- Completed_Temp := true; -- Close ( Rec.Old_File ); -- else -- Create ( Rec.Tmp_File, Out_File, Tmp_File_Name ); -- Get ( Rec.Old_File, Rec.Old_1 ); -- Get_Line ( Rec.Old_File, Rec.Old_Line_1, Rec.Last_1 ); -- end if; -- end if; -- if not Completed_Temp then -- if not Rec.Start_Over then -- Put ( Rec.Tmp_File, Mid_Point ); -- Put_Line ( Rec.Tmp_File, Results ); -- else -- Rec.Start_Over := false; -- end if; -- Put ( Rec.Tmp_File, Rec.Old_1 ); -- Put_Line ( Rec.Tmp_File, Rec.Old_Line_1 ( 1..Rec.Last_1 ) ); -- if End_Of_File ( Rec.Old_File ) then -- Rec.Start_Over := true; -- else -- Get ( Rec.Old_File, Rec.Old_2 ); -- Get_Line ( Rec.Old_File, Rec.Old_Line_2, Rec.Last_2 ); -- Mid_Point := ( Rec.Old_1 + Rec.Old_2 ) / 2.0; -- Completed_Temp := Mid_Point = Rec.Old_1; -- Rec.Old_Line_1 := Rec.Old_Line_2; -- Rec.Last_1 := Rec.Last_2; -- Rec.Old_1 := Rec.Old_2; -- end if; -- if Completed_Temp or Rec.Start_Over then -- Close ( Rec.Tmp_File ); -- Delete ( Rec.Old_File ); -- Copy ( Tmp_File_Name, Old_File_Name ); -- Delete ( Tmp_File_Name ); -- end if; -- end if; -- Completed := Completed_Temp; -- end Interpolate; -- -- procedure Interpolate_Demo is -- ---------------------------------------------------------------------- -- Completed : boolean; -- Mid_Point : float := 0.0; -- Rec : Interpolate_Type; -- Results : Line_Type; -- begin -- loop -- Interpolate ( Completed, Mid_Point, Rec, -- integer'image ( integer ( Mid_Point ) ), -- "Old_File", "TempFile" ); -- Put ( Mid_Point ); -- Put_Line ( " " & integer'image ( integer ( Mid_Point ) ) ); -- exit when Completed; -- end loop; -- end Interpolate_Demo; function Ln ( X : float ) return float is ---------------------------------------------------------------------- -- p308, Handbook of Mathematical, Scientific, and Engineering -- Formulas, Functions, Tables, Graphs, Transforms -- Only valid for X > 0 ---------------------------------------------------------------------- Loops : constant integer := 20; -- limits accuracy Temp, Temp_Old : float := 0.0; Index : positive := 1; A : float; B : integer; begin if X < 0.0 then raise Numeric_Error; end if; A := ( X - 1.0 ) / ( X + 1.0 ); for Index in 1..Loops loop B := 2 * Index - 1; Temp := Temp + ( A ** B ) / float ( B ); end loop; return 2.0 * Temp; end Ln; function Minimum ( X, Y : float ) return float is ---------------------------------------------------------------------- begin if X < Y then return X; else return Y; end if; end Minimum; function Odd ( I : in integer ) return boolean is ---------------------------------------------------------------------- begin return ( I mod 2 ) = 1; end Odd; function Sigmoid ( F : float ) return float is ---------------------------------------------------------------------- begin return 1.0 / ( 1.0 + Exp ( -F ) ); end Sigmoid; function Sin ( R : in float ) -- radians return float is ---------------------------------------------------------------------- Temp : float := R; R2 : float; Temp_New : float; Index : positive := 3; Add : boolean := false; Two_Pi : constant float := 2.0 * Pi; begin if abs ( R ) > 2.0 * Pi then R2 := R / Two_Pi; R2 := R2 - float ( Characteristic ( R2 ) ); R2 := R2 * Two_Pi; Temp := R2; else R2 := R; end if; loop begin if Add then Temp_New := Temp + ( R2 ** Index ) / Factorial ( Index ); else Temp_New := Temp - ( R2 ** Index ) / Factorial ( Index ); end if; exception when others => return Temp; end; exit when Temp = Temp_New; Temp := Temp_New; Index := Index + 2; Add := not Add; end loop; return Temp; end Sin; function Sqr ( F : float ) return float is ---------------------------------------------------------------------- begin return F ** 2; end Sqr; function Tanh ( F : float ) return float is --------------------------------------------------------------------------- -- Input : - Infinity 0.0 + Infinity -- Output: -1.0 0.0 1.0 --------------------------------------------------------------------------- begin return ( Exp ( F ) - Exp ( -F ) ) / ( Exp ( F ) + Exp ( -F ) ); end Tanh; ---------------------------------------------------------------------- ---------------------------------------------------------------------- end MathAK;