'
'
' This unique sequence of symbols
' was arranged by Steve Bazinet.
'
' Spring 2000
' Copyright (c) 2000 Steven Roland Bazinet
'
Option Explicit
'
' FUNCTIONS HEREIN:
'
' ARC SINE IN RADIANS fnArcSineRad
' OR DEGREES fnArcSineDeg
'
' RADIANS TO DEGREES fnRadsToDegs
' DEGREES TO RADIANS fnDegsToRads
'
'
' NOTE: there is also a testing section below these functions.
'
'
'
Const mcPI = 3.14159265358979 ' Approximation of Pi.
'
'
' Name: ARC SINE IN RADIANS
' Purpose: This function determines the ArcSine of the passed argument.
' Inputs: vntSine The sine of an angle.
' Assumptions: None.
' Effects: Will raise "Overflow" error if vntSine is not a valid sine or
' if any other error occurs during execution.
' Returns: The angle in radians.
' If an error occurs fnArcSine is indeterminate.
'
Public Function fnArcSineRad(vntSine As Variant) As Double
On Error GoTo ERROR_ArcSine ' Trap strangeness.Const cOVERFLOW = 6 ' "Overflow" message #.
Dim blnEditPassed As Boolean ' Edit results variable.
Dim dblTemp As Double ' Temporary double.
blnEditPassed = False ' It hasn't passed yet!
If IsNumeric(vntSine) Then ' Is arg numeric?
If vntSine >= -1 And vntSine <= 1 Then ' Yup, is it within limits?
blnEditPassed = True ' Yup, employ Derived Math Function:
' Arcsin(X) = Atn(X / Sqr(-X * X + 1))
dblTemp = Sqr(-vntSine * vntSine + 1) ' Calculate denominator.
If dblTemp = 0 Then ' Is it 0? Can only happen if arg is +1 or -1.
fnArcSineRad = Sgn(vntSine) * mcPI / 2 ' Yup, assign +Pi/2 or -Pi/2 based on sign of arg.
Else
fnArcSineRad = Atn(vntSine / dblTemp) ' Complete derived math function.
End If
End If
End If
EXIT__ArcSine:
If Not blnEditPassed Then Err.Raise cOVERFLOW ' Raise overflow error if arg failed edits.
Exit Function
ERROR_ArcSine:
On Error GoTo 0 ' Turn off error trapping.
blnEditPassed = False ' Should never happen!
Resume EXIT__ArcSine ' But if it does give overflow error.
End Function
'
'
' Name: ARC SINE IN DEGREES
' Purpose: This function determines the ArcSine of the passed argument.
' Inputs: vntSine The sine of an angle.
' Assumptions: None.
' Effects: None.
' Returns: The angle in degrees.
' If an error occurs fnArcSine is indeterminate.
'
Public Function fnArcSineDeg(vntSine As Variant) As Double
' No error trap; allow fnArcSineRad errors to be seen.
fnArcSineDeg = fnRadsToDegs(fnArcSineRad(vntSine)) ' Get Degree ArcSin by converting Radian ArcSin.
End Function
'
'
' Name: DEGREES TO RADIANS
' Purpose: This function converts passed degrees into radians.
' Inputs: dblDegrees A quantity in degrees.
' Assumptions: Passed arg is a Double.
' Effects: None.
' Returns: The angle in radians.
' If an error occurs fnDegsToRads is indeterminate.
'
Public Function fnDegsToRads(dblDegrees As Double) As Double
On Error Resume Next ' Trap strangeness.
fnDegsToRads = dblDegrees * mcPI / 180 ' Convert.
End Function
'
'
' Name: RADIANS TO DEGREES
' Purpose: This function converts passed radians into degrees.
' Inputs: dblRadians A quantity in radians.
' Assumptions: Passed arg is a Double.
' Effects: None.
' Returns: The angle in degrees.
' If an error occurs fnRadsToDegs is indeterminate.
'
Public Function fnRadsToDegs(dblRadians As Double) As Double
On Error Resume Next ' Trap strangeness.
fnRadsToDegs = dblRadians * 180 / mcPI ' Convert.
End Function
'
'
'
'
' TESTING SECTION.
' This section is less strictly commented.
'
' Test mainline.
Public Sub subTest()
Dim dblD As Double ' Degrees.
For dblD = -450 To 450 Step 1 ' Test range: -450 to 450 degrees.
Debug.Assert fnTest(dblD) ' Test and halt on failure.
Next dblD
Exit Sub ' Exit routine.
' These should raise an overflow error.
' To test copy all to debug windows and execute.
Debug.Print fnArcSineRad(Null)
Debug.Print fnArcSineRad("a")
Debug.Print fnArcSineRad(5)
Debug.Print fnArcSineDeg(Null)
Debug.Print fnArcSineDeg("a")
Debug.Print fnArcSineDeg(5)
End Sub
'
'
' Compare the function, SineToAngleDegrees to expected results.
Public Function fnTest(ByVal dblD As Double) As Boolean
Const cTOLERANCE As Double = 0.000000000001 ' A difference less then this is nil.
Dim dblR As Double ' Radians.
subDisplay dblD ' Display the current test results.
dblR = fnDegsToRads(dblD) ' Convert to radians.
dblD = Abs((fnArcSineDeg(Sin(dblR)) - fnSinRange(dblD))) ' Find delta.
fnTest = dblD < cTOLERANCE ' Is it within tolerance?
End Function
'
'
' Display the current degrees, SineToAngleDegrees' results, expected results.
Public Sub subDisplay(dblD As Double)
Debug.Print Right(Space(20) & Format(dblD, "0.00000 "), 15);
Debug.Print Right(Space(20) & Format(fnArcSineDeg(Sin(fnDegsToRads(dblD))), "0.00000 "), 15);
Debug.Print Right(Space(20) & Format(fnSinRange(dblD), "0.00000"), 15)
End Sub
'
'
' Convert (-infinity degrees to +infinity degrees) to -90 to +90.
' -90 to +90 is the range of values the correspond to ArcSine(-1) to ArcSine(1).
'
' Why? Because the Sin(390) is 0.5 but the ArcSine(0.5) is 30.
' Therefore to test if ArcSin(Sin(390))=390 I must translate 390 to
' the range returned by ArcSin.
'
Public Function fnSinRange(ByVal dblAngle As Double) As Double
dblAngle = fnRealMod(dblAngle, 360) ' Remove extra cycles.
If dblAngle < 0 Then dblAngle = 360 + dblAngle ' Compensate for negatives.
Select Case Int(dblAngle / 90) ' Find the quadrant.
Case 0: fnSinRange = dblAngle ' 1st quadrant: 0 to 89.9999 => 0 to 89.9999
Case 1: fnSinRange = 180 - dblAngle ' 2nd quadrant: 90 to 179.9999 => 90 to 0.0001
Case 2: fnSinRange = -(dblAngle - 180) ' 3rd quadrant: 180 to 269.9999 => 0 to -89.9999
Case 3: fnSinRange = -(360 - dblAngle) ' 4th quadrant: 270 to 359.9999 => -90 to -0.0001
End Select
End Function
'
'
' Modulus with fractional part of remainder also.
Public Function fnRealMod(dblReal As Double, lngModulus As Long) As Double
Dim dblTimes As Double ' # of complete divisions.
dblTimes = dblReal / lngModulus ' Divide.
fnRealMod = dblReal - (Int(dblTimes) * lngModulus) ' Get the real remainder.
End Function
'
'
' Copyright (c) 2000 Steven Roland Bazinet
'
'