File: Microsoft\VisualBasic\VBMath.vb
Web Access
Project: src\src\libraries\Microsoft.VisualBasic.Core\src\Microsoft.VisualBasic.Core.vbproj (Microsoft.VisualBasic.Core)
' Licensed to the .NET Foundation under one or more agreements.
' The .NET Foundation licenses this file to you under the MIT license.
 
Imports System
Imports Microsoft.VisualBasic.CompilerServices
 
Namespace Microsoft.VisualBasic
 
    Public Module VBMath
 
        ' Equivalent to calling VB6 rtRandomNext(1.0)
        Public Function Rnd() As Single
            Return Rnd(CSng(1))
        End Function
 
        ' Equivalent to VB6 rtRandomNext function
        Public Function Rnd(ByVal Number As Single) As Single
            Dim oProj As ProjectData = ProjectData.GetProjectData()
            Dim rndSeed As Integer = oProj.m_rndSeed
 
            '  if parameter is zero, generate float from present seed
            If (Number <> 0.0) Then
                '  if parameter is negative, use to create new seed
                If (Number < 0.0) Then
                    'Original C++ code
                    'rndSeed = *(ULONG *) & fltVal;
                    'rndSeed = (rndSeed + (rndSeed >> 24)) & 0xffffffL;
 
                    rndSeed = BitConverter.ToInt32(BitConverter.GetBytes(Number), 0)
 
                    Dim i64 As Int64 = rndSeed
                    i64 = (i64 And &HFFFFFFFFL)
                    rndSeed = CInt((i64 + (i64 >> 24)) And &HFFFFFFI)
                End If
 
                '  if parameter is non-zero, generate a new seed
                rndSeed = CInt((CLng(rndSeed) * &H43FD43FDL + &HC39EC3L) And &HFFFFFFL)
            End If
 
            '  copy back seed value to per-project structure
            oProj.m_rndSeed = rndSeed
 
            '  normalize seed to floating value from 0.0 up to 1.0
            Return CSng(rndSeed) / CSng(16777216.0)
        End Function
 
        'Equivalent to RandomizeTimer in the VB6 codebase
        Public Sub Randomize()
            Dim oProj As ProjectData = ProjectData.GetProjectData()
            Dim sngTimer As Single = GetTimer()
            Dim rndSeed As Int32 = oProj.m_rndSeed
            Dim lValue As Int32
 
            '  treat Single as a long Integer
            lValue = BitConverter.ToInt32(BitConverter.GetBytes(sngTimer), 0)
 
            '  xor the upper and lower words of the long and put in
            '  the middle two bytes
            lValue = ((lValue And &HFFFFI) Xor (lValue >> 16)) << 8
 
            '  replace the middle two bytes of the seed with lValue
            rndSeed = (rndSeed And &HFF0000FFI) Or lValue
 
            '  copy back seed value to per-project structure
            oProj.m_rndSeed = rndSeed
        End Sub
 
        'Equivalent to RandomizeValue in the VB6 codebase
        Public Sub Randomize(ByVal Number As Double)
            Dim rndSeed As Integer
            Dim lValue As Integer
            Dim oProj As ProjectData
 
            oProj = ProjectData.GetProjectData()
            rndSeed = oProj.m_rndSeed
 
            '  for little-endian R8, the high-order Integer is second half
            If BitConverter.IsLittleEndian Then
                lValue = BitConverter.ToInt32(BitConverter.GetBytes(Number), 4)
            Else
                lValue = BitConverter.ToInt32(BitConverter.GetBytes(Number), 0)
            End If
 
            '  xor the upper and lower words of the Integer and put in
            '  the middle two bytes
            ' Original C++ line
            ' lValue = ((lValue & 0xffff) ^ (lValue >> 16)) << 8;
            lValue = ((lValue And &HFFFFI) Xor (lValue >> 16)) << 8
 
            '  replace the middle two bytes of the seed with lValue
            'Original C++ line
            ' rndSeed = (rndSeed & 0xff0000ff) | lValue;
            rndSeed = (rndSeed And &HFF0000FFI) Or lValue
 
            '  copy back seed value to per-project structure
            oProj.m_rndSeed = rndSeed
        End Sub
 
        Private Function GetTimer() As Single
            Dim dt As Date
 
            dt = System.DateTime.Now
            Return CSng((60 * dt.Hour + dt.Minute) * 60 + dt.Second + (dt.Millisecond / 1000))
        End Function
 
    End Module
 
End Namespace