use of ByVal in VBA - vba

During an interpolation scheme I had to write, I needed a minimum and maximum function so I quickly wrote functions Min and Max that are called from within my interpolation function. It looked like this:
Function interpolateVol(Strike As Double, Maturity As Double, coupon As Variant)
Dim i, k, j As Long
Dim timeIndex, strikeIndex As Long
Dim vol_minus1, vol_zero, volmin, volmax, vol As Double
Dim w1, w2 As Double
If coupon = "1M" Then
j = 3
ElseIf coupon = "3M" Then
j = 4
ElseIf coupon = "6M" Then
j = 5
End If
' we set i = 1 as the maturities do not matter for
' picking up the time index
If Maturity <= volatilityCube(1, 1, 2) Then
timeIndex = 1
ElseIf Maturity > volatilityCube(noMaturities, 1, 2) Then
timeIndex = noMaturities
Else
i = 1
While volatilityCube(i, 1, 2) < Maturity
i = i + 1
Wend
timeIndex = i ' volatilityCube(timeIndex-1,2) < Maturity <= volatilityCube(timeIndex,2)
End If
' we set k = 1 as the strikes do not matter for
' picking up the strike index
If Strike <= volatilityCube(1, 1, 1) Then
strikeIndex = 1
ElseIf Strike > volatilityCube(1, noStrikes, 1) Then
strikeIndex = noStrikes
Else
k = 1
While volatilityCube(1, k, 1) < Strike
k = k + 1
Wend
strikeIndex = k ' volatilityCube(strikeIndex-1,1) < Strike <= volatilityCube(strikeIndex,1)
End If
' first we interpolate on the tenors
' as a result we will have two interpolated values:
' one for timeIndex, another for timeIndex + 1
w1 = (Maturity - volatilityCube(timeIndex - 1, 1, 2)) / _
(volatilityCube(timeIndex, 1, 2) - volatilityCube(timeIndex - 1, 1, 2))
w2 = (volatilityCube(timeIndex, 1, 2) - Maturity) / _
(volatilityCube(timeIndex, 1, 2) - volatilityCube(timeIndex - 1, 1, 2))
vol_minus1 = w1 * volatilityCube(timeIndex - 1, strikeIndex - 1, j) + _
w2 * volatilityCube(timeIndex, strikeIndex - 1, j)
vol_zero = w1 * volatilityCube(timeIndex - 1, strikeIndex, j) + _
w2 * volatilityCube(timeIndex, strikeIndex, j)
' Now we have two vols interpolated in time, each for another strike.
' These two vols need to be interpolated in strikes:
volmin = Min(vol_minus1, vol_zero)
volmax = Max(vol_minus1, vol_zero)
w1 = (Strike - volatilityCube(1, strikeIndex - 1, 1)) / _
(volatilityCube(1, strikeIndex, 1) - volatilityCube(1, strikeIndex - 1, 1))
w2 = (volatilityCube(1, strikeIndex, 1) - Strike) / _
(volatilityCube(1, strikeIndex, 1) - volatilityCube(1, strikeIndex - 1, 1))
vol = w1 * volmin + w2 * volmax
interpolateVol = vol
End Function
Function Min(number1 As Double, number2 As Double) As Double
Dim var As Double
If (number1 < number2) Then
var = number1
Else
var = number2
End If
Min = var
End Function
Function Max(number1 As Double, number2 As Double) As Double
Max = number1 + number2 - Min(number1, number2)
End Function
However, running the code prompted the `byref argument type mismatch' error. As it turns out, I had to make explicit that I pass values and not references by adding ByVal to the function arguments:
Function Min(ByVal number1 As Double, ByVal number2 As Double) As Double
Dim var As Double
If (number1 < number2) Then
var = number1
Else
var = number2
End If
Min = var
End Function
Function Max(ByVal number1 As Double, ByVal number2 As Double) As Double
Max = number1 + number2 - Min(number1, number2)
End Function
Now I have two questions about this:
I find it surprising to discover that I need to make passing by value explicit. In C++, function variables pass by value by default. Should I conclude that VBA passes variables by references as default?
Why does it help to add Byval to the function arguments? I do not see the relation between types (as the error supposedly is about) and passing by value and/or reference ....
Many thanks in advance.

Try changing this part of interpolateVol:
Dim vol_minus1, vol_zero, volmin, volmax, vol As Double
To this:
Dim vol_minus1 As Double, vol_zero As Double, volmin As Double, volmax As Double, vol As Double
The issue is that in the original version, only vol is declared as Double because it is right next to the word Double. The other four declarations do not have that Double applied to them, so they get declared as the Excel VBA default type, which is Variant. This can be confusing because VBA is not like other languages you might be used to, e.g. C where you can say things like double vol_minus1, vol_zero, volmin, volmax, vol;

That error has nothing to do with ByRef or ByVal; it's simply stating that the type of either a, b, or both is incorrect. For example, if you do this:
Public Sub interpolate()
Dim a As String
Dim b As String
a = 1
b = 2
x = Min(a, b)
End Sub
You'll get that error, but if you do this, you won't:
Public Sub interpolate()
Dim a As Double
Dim b As Double
a = 1
b = 2
x = Min(a, b)
End Sub
The difference between the two is that, in the second one, a and b are have types that the Min function expects.
The reason that it even uses the term ByRef in that error is that it's just trying to be more specific to help you figure out which argument it's referring to. It's like saying "look at the BLACK dog" instead of just "look at the dog."

Related

Errors using Arrays in VBA

I am new to VBA ans really appreciate your help.
I am writing a custom function. I am trying to use arrays to store values from the for loop and retrieve the values based on their location on the array.
Please refer to the code below
Function Amounttopay(Original_Principal As Integer, APR As Double, Npayperyear As Integer, term As Integer, Paydone As Integer)
Dim strinitialamount() As Integer
Dim strInterestp() As Integer
Dim strendamount() As Integer
Dim i As Integer
r = (APR / Npayperyear)
n = Npayperyear * term
emi = (Original_Principal * r) / (1 - ((1 + r) ^ (-1 * n)))
ReDim strinitialamount(n)
ReDim strInterestp(n)
ReDim strendamount(n)
strinitialamount(0) = Original_Principal
strInterestp(0) = (Original_Principal * r)
strendamount(0) = (Original_Principal - (emi - strInterestp(0)))
For i = 1 To (n - 1)
strinitialamount(i) = strendamount(i - 1)
strInterestp(i) = (strinitialamount(i)) * r
strendamount(i) = (strinitialamount(i)) - (emi - strInterestp(i))
Next i
Amounttopay = strendamount(Paydone)
End Function
You need change it to Long because an integer only goes between -32,768 to 32,767.
I ran this with your values:
Function Amounttopay(Original_Principal As Long, APR As Variant, Npayperyear As Integer, term As Integer, Paydone As Integer)
Dim strinitialamount() As Long
Dim strInterestp() As Long
Dim strendamount() As Long
Dim i As Integer
r = (APR / Npayperyear)
n = Npayperyear * term
emi = (Original_Principal * r) / (1 - ((1 + r) ^ (-1 * n)))
ReDim strinitialamount(n)
ReDim strInterestp(n)
ReDim strendamount(n)
strinitialamount(0) = Original_Principal
strInterestp(0) = (Original_Principal * r)
strendamount(0) = (Original_Principal - (emi - strInterestp(0)))
For i = 1 To (n - 1)
strinitialamount(i) = strendamount(i - 1)
strInterestp(i) = (strinitialamount(i)) * r
strendamount(i) = (strinitialamount(i)) - (emi - strInterestp(i))
Next i
Amounttopay = strendamount(Paydone)
End Function
Sub TestFunction()
Debug.Print Amounttopay(1000000, 0.1, 12, 1, 6)
'Original_Principal = 1000000, APR = 0.1, Npayperyear = 12, term = 1, Paydone = 6
End Sub
I received this as a result: 428798

Calculating an exponentially weighted moving average

I am trying a fairly simple function to calculate an exponentially weighted moving average volatility in Excel VBA, following. However, I think there is some error in my function that I can't pinpoint, because I don't get the correct solution.
Function EWMA(numbers As Range, Lambda As Single) As Double
Dim mean As Double
Dim x As Double
Dim c As Range
Dim n As Integer
mean = WorksheetFunction.Average(numbers)
n = WorksheetFunction.Count(numbers)
For Each c In numbers
x = x + (Lambda ^ (n - c.Count)) * ((c.Value - mean) ^ 2)
Next c
EWMA = (1 - Lambda) * x
End Function
The values I am using and the target volatility (calculated using a spreadsheet EWMA) are here.
What am I doing wrong?
Update: using Ron Rosenfeld's solution:
Option Explicit
Function EWMA(Zero As Range, Lambda As Double) As Double
Dim vZero As Variant
Dim SumWtdRtn As Double
Dim I As Long
Dim vPrices As Variant
Dim LogRtn As Double, RtnSQ As Double, WT As Double, WtdRtn As Double
vZero = Zero
For I = 2 To UBound(vZero, 1)
vPrices = 1 / ((1 + vZero(I, 1)) ^ (3 / 12))
LogRtn = Log(vPrices(I - 1, 1) / vPrices(I, 1))
RtnSQ = LogRtn ^ 2
WT = (1 - Lambda) * Lambda ^ (I - 2)
WtdRtn = WT * RtnSQ
SumWtdRtn = SumWtdRtn + WtdRtn
Next I
EWMA = SumWtdRtn ^ (1 / 2)
End Function
Here's a little bit different way of doing it as a VBA function. The inputs are an array of prices, which is assumed to be in descending order as you show, and Lambda. Hopefully, the names of the variables will let you see the logic:
Option Explicit
Function EWMA2(Prices As Range, Lambda As Double) As Double
Dim vPrices As Variant
Dim dSumWtdRtn As Double
Dim I As Long
Dim dLogRtn As Double, dRtnSQ As Double, dWT As Double, dWtdRtn As Double
vPrices = Prices
For I = 2 To UBound(vPrices, 1)
dLogRtn = Log(vPrices(I - 1, 1) / vPrices(I, 1))
dRtnSQ = dLogRtn ^ 2
dWT = (1 - Lambda) * Lambda ^ (I - 2)
dWtdRtn = dWT * dRtnSQ
dSumWtdRtn = dSumWtdRtn + dWtdRtn
Next I
EWMA2 = dSumWtdRtn ^ (1 / 2)
End Function
With your data, it gives the same results as the spreadsheet calculation (within the limits of precision of the data types)
EDIT
If you want to input the 3M CAD Zero Rates as the range input, and not the pricing, then you could modify the above to compute the two relevant prices from the returns data. In this case, it would be:
Option Explicit
Function EWMAV(Zeros As Range, Lambda As Double) As Double
Dim vZeros() As Variant
Dim dPrice1 As Double, dPrice2 As Double
Dim dSumWtdRtn As Double
Dim I As Long
Dim dLogRtn As Double, dRtnSQ As Double, dWT As Double, dWtdRtn As Double
vZeros = Zeros
For I = 2 To UBound(vZeros, 1)
dPrice1 = 1 / ((1 + vZeros(I - 1, 1)) ^ (3 / 12))
dPrice2 = 1 / ((1 + vZeros(I, 1)) ^ (3 / 12))
dLogRtn = Log(dPrice1 / dPrice2)
dRtnSQ = dLogRtn ^ 2
dWT = (1 - Lambda) * Lambda ^ (I - 2)
dWtdRtn = dWT * dRtnSQ
dSumWtdRtn = dSumWtdRtn + dWtdRtn
Next I
EWMAV = dSumWtdRtn ^ (1 / 2)
End Function

Excel VBA: Variable as First Row of Selection?

I am creating a function in Excel VBA. I am trying to set a variable equal to the first cell in a selection on the worksheet. Basically the equivalent of something like
x = Worksheets("Data").Range("D2").Offset(i - 1, 0)
y = Worksheets("Data").Range("E2").Offset(i - 1, 0)
z = Worksheets("Data").Range("F2").Offset(i - 1, 0)
except I want "Range("D2")" E2 and F2 to instead refer to the first, second and third cell of whatever I've got highlighted on the sheet, rather than a preset cell.
The specific code I've got is:
Function VarunModel(Table As Range, Optional EndCondition As Integer = 0) As Variant
Dim iNumCols As Integer, iNumRows As Integer
Dim i As Integer
Dim SelectedRange As Range
Set SelectedRange = Selection
iNumCols = Table.Columns.Count
iNumRows = Table.Rows.Count
maturity = Worksheets("KMV-Merton").Range("B2").Value
For i = 1 To iNumRows
equity(i) = SelectedRange.Cells(1).Value
debt(i) = SelectedRange.Cells(2).Value
riskFree(i) = Selection.Cells(3).Value
Next i
Dim equityReturn As Variant: ReDim equityReturn(2 To iNumRows)
Dim sigmaEquity As Double
Dim asset() As Double: ReDim asset(1 To iNumRows)
Dim assetReturn As Variant: ReDim assetReturn(2 To iNumRows)
Dim sigmaAsset As Double, meanAsset As Double
Dim x(1 To 1) As Double, n As Integer, prec As Double, precFlag As Boolean, maxDev As Double
For i = 2 To iNumRows: equityReturn(i) = Log(equity(i) / equity(i - 1)): Next i
sigmaEquity = WorksheetFunction.StDev(equityReturn) * Sqr(260)
sigmaAsset = sigmaEquity * equity(iNumRows) / (equity(iNumRows) + debt(iNumRows))
NextItr: sigmaAssetLast = sigmaAsset
For iptr = 1 To iNumRows
x(1) = equity(iptr) + debt(iptr)
n = 1
prec = 0.00000001
Call NewtonRaphson(n, prec, x, precFlag, maxDev)
asset(iptr) = x(1)
Next iptr
For i = 2 To iNumRows: assetReturn(i) = Log(asset(i) / asset(i - 1)): Next i
sigmaAsset = WorksheetFunction.StDev(assetReturn) * Sqr(260)
meanAsset = WorksheetFunction.Average(assetReturn) * 260
If (Abs(sigmaAssetLast - sigmaAsset) > prec) Then GoTo NextItr
Dim disToDef As Double: disToDef = (Log(asset(iNumRows) / debt(iNumRows)) + (meanAsset - sigmaAsset ^ 2 / 2) * maturity) / (sigmaAsset * Sqr(maturity))
Dim defProb As Double: defProb = WorksheetFunction.NormSDist(-disToDef)
VarunModel = defProb
End Function
Thanks.
Try the below code
Dim SelectedRange As Range
Set SelectedRange = Selection
x = SelectedRange.Cells(1).Value
y = SelectedRange.Cells(2).Value
z = SelectedRange.Cells(3).Value
try this:
Dim Row as integer
Dim Col as Integer
Row = 2
Col = 4 'column "D"
x = Worksheets("Data").cells(row, col).Offset(i - 1, 0)
col = col + 1
y = Worksheets("Data").cells(row, col).Offset(i - 1, 0)
col = col + 1
z = Worksheets("Data").cells(row, col).Offset(i - 1, 0)
See the example below for using the selection on the excel, you can control the column you want by changing the column index. If you select only 1 cell, it will also work:
Sub Solution()
x = Selection.Cells(1, 0) 'By using the zero index on the column, it will get the left cell from the selected one.
y = Selection.Cells(2, 0)
Z = Selection.Cells(3, 0)
End Sub

Perlin Noise acting strange

I am trying to implement a 2D Perlin Noise in VB.Net. I've spent the whole day searching for sources that explain the subject and one of the most notable was this article by Hugo Elias
Most of the implementation went well. On the exception of a very important part that did not seem to work in VB.Net, causing overflows.
function Noise1(integer x, integer y)
n = x + y * 57
n = (n<<13) ^ n;
return ( 1.0 - ( (n * (n * n * 15731 + 789221) + 1376312589) & 7fffffff) / 1073741824.0);
end function
In VB.net I translated it to
Private Function Noise(tX As Integer, tY As Integer) As Double
'Return a double between -1 & 1 according to a fixed random seed
Dim n As Integer = tX + tY * 57
n = (n << 13) Xor n
Return (1.0 - ((n * (n * n * 15731 + 789221) + BaseSeed) And &H7FFFFFFF) / 1073741824.0)
End Function
Which cause overflows.
Since the idea seem to be to simply generate a fractional number between -1 and 1. I've made this little function which create a Integer Number based on the coordinates and BaseSeed. BaseSeed(999999) being the base for every noise I'll create in this particular part of my game.
Private Function Noise(tX As Integer, tY As Integer) As Double
Dim tSeed As Integer
tSeed = WrapInteger(789221, BaseSeed, (tX * 1087) + (tY * 2749))
RandomGenerator = New Random(tSeed)
Return (RandomGenerator.Next(-10000, 10001) / 10000)
End Function
WrapInteger simply makes sure that the number will always be in the range of an integer, to avoid overflow errors.
Public Function WrapInteger(ByVal Lenght As Integer, ByVal Position As Integer, ByVal Movement As Integer) As Integer
Lenght += 1
Return ((Position + Movement) + (Lenght * ((Abs(Movement) \ Lenght) + 1))) Mod Lenght
End Function
When I fire it up with a Persistence of 0.25, 6 Octaves and a starting frequency of 2. this is what I get. This is a 128x128 pixel bitmap that I scaled.
Result
Anyone have an idea of why it would be so linear? When I look at this picture I have the feeling that it's not far from the truth, as if it only worked in 1D. All suposition.
Below you will find my entire PerlinNoise Class. I think the rest of it is just fine, but I added it for reference purpose. Beside, I haven't been able to find a single VB implementation of Perlin Noise on the internet. So I guess if I can fix this one, it might help others. There seem to be alot of question about Perlin noise malfunction on StackOverflow
Public Class cdPerlinNoise
Private RandomGenerator As Random
Private BaseSeed As Integer
Private Persistence As Double
Private Frequency As Integer
Private Octaves As Integer
Public Sub New(tSeed As Integer, tPersistence As Double, tOctaves As Integer, tFrequency As Integer)
Frequency = tFrequency
BaseSeed = tSeed
Persistence = tPersistence
Octaves = tOctaves
End Sub
Private Function Noise(tX As Integer, tY As Integer) As Double
Dim tSeed As Integer
tSeed = WrapInteger(789221, BaseSeed, (tX * 1087) + (tY * 2749))
RandomGenerator = New Random(tSeed)
Return (RandomGenerator.Next(-10000, 10001) / 10000)
End Function
Private Function SmoothNoise(tX As Integer, tY As Integer) As Double
Dim Corners As Double = (Noise(tX - 1, tY - 1) + Noise(tX + 1, tY - 1) + Noise(tX - 1, tY + 1) + Noise(tX + 1, tY + 1)) / 16
Dim Sides As Double = (Noise(tX - 1, tY) + Noise(tX + 1, tY) + Noise(tX, tY - 1) + Noise(tX, tY + 1)) / 8
Return (Noise(tX, tY) / 4) + Corners + Sides
End Function
Private Function InterpolateCosine(tA As Double, tB As Double, tX As Double) As Double
Dim f As Double = (1 - Cos(tX * 3.1415927)) * 0.5
Return tA * (1 - f) + tB * f
End Function
Private Function Interpolate2D(tX As Double, tY As Double) As Double
Dim WholeX As Integer = CInt(Fix(tX))
Dim RemainsX As Double = tX - WholeX
Dim WholeY As Integer = CInt(Fix(tY))
Dim RemainsY As Double = tY - WholeY
Dim v1 As Double = SmoothNoise(WholeX, WholeY)
Dim v2 As Double = SmoothNoise(WholeX + 1, WholeY)
Dim v3 As Double = SmoothNoise(WholeX, WholeY + 1)
Dim v4 As Double = SmoothNoise(WholeX + 1, WholeY + 1)
Dim i1 As Double = InterpolateCosine(v1, v2, RemainsX)
Dim i2 As Double = InterpolateCosine(v3, v4, RemainsX)
Return InterpolateCosine(i1, i2, RemainsY)
End Function
Public Function PerlinValue(tX As Double, tY As Double) As Double
Dim Total As Double = 0
Dim Frequency As Double
Dim Amplitude As Double
For i = 0 To Octaves - 1
Frequency = Frequency ^ i
Amplitude = Persistence ^ i
Total = Total + (Interpolate2D(tX * Frequency, tY * Frequency) * Amplitude)
Next
Return Total
End Function
Public Function ScaleNoise(ByVal tX As Double, ByVal tY As Double, ByVal OutputLow As Double, ByVal OutputHigh As Double) As Double
Dim Range1 As Double
Dim Range2 As Double
Dim Result As Double
Range1 = 1 - -1
Range2 = OutputHigh - OutputLow
'(B*C - A*D)/R1 + n1*(R2/R1)
Result = (((1 * OutputLow) - (-1 * OutputHigh)) / Range1) + ((PerlinValue(tX, tY) * (Range2 / Range1)))
If Result < OutputLow Then
Return OutputLow
ElseIf Result > OutputHigh Then
Return OutputHigh
Else
Return Result
End If
End Function
End Class

Normal Distributed Random Number in VB.NET

Is there anybody know how to make normal distributed random number in vb.net?
thank you
From this forum post :
Usage:
GaussNumDist(Mean, Standard Deviation, Sample Size)
Code example below, which will populate GaussNumArray() with the sample of numbers, whose distribution will have the mean and standard deviation specified:
Imports System.Math
Module Module1
Friend GaussNumArray() As Double
Friend intICell As Long
Friend Function GaussNumDist(ByVal Mean As Double, ByVal StdDev As Double, ByVal SampleSize As Integer)
intICell = 1 'Loop variable
ReDim GaussNumArray(SampleSize)
Do While (intICell < (SampleSize + 1))
Call NumDist(Mean, StdDev)
Application.DoEvents()
Loop
End Function
Sub NumDist(ByVal meanin As Double, ByVal sdin As Double)
'---------------------------------------------------------------------------------
'Converts uniform random numbers over the region 0 to 1 into Gaussian distributed
'random numbers using Box-Muller algorithm.
'Adapted from Numerical Recipes in C
'---------------------------------------------------------------------------------
'Defining variables
Dim dblR1 As Double
Dim dblR2 As Double
Dim mean As Double
Dim var As Double
Dim circ As Double
Dim trans As Double
Dim dblY1 As Double
Dim dblY2 As Double
Dim Pi As Double
Pi = 4 * Atan(1)
'Get two random numbers
dblR1 = (2 * UniformRandomNumber()) - 1
dblR2 = (2 * UniformRandomNumber()) - 1
circ = (dblR1 ^ 2) + (dblR2 ^ 2) 'Radius of circle
If circ >= 1 Then 'If outside unit circle, then reject number
Call NumDist(meanin, sdin)
Exit Sub
End If
'Transform to Gaussian
trans = Sqrt(-2 * Log(circ) / circ)
dblY1 = (trans * dblR1 * sdin) + meanin
dblY2 = (trans * dblR2 * sdin) + meanin
GaussNumArray(intICell) = dblY1 'First number
'Increase intICell for next random number
intICell = (intICell + 1)
GaussNumArray(intICell) = dblY2 'Second number
'Increase intICell again ready for next call of ConvertNumberDistribution
intICell = (intICell + 1)
End Sub
Friend Function UniformRandomNumber() As Double
'-----------------------------------------------------------------------------------
'Outputs random numbers with a period of > 2x10^18 in the range 0 to 1 (exclusive)
'Implements a L'Ecuyer generator with Bays-Durham shuffle
'Adapted from Numerical Recipes in C
'-----------------------------------------------------------------------------------
'Defining constants
Const IM1 As Double = 2147483563
Const IM2 As Double = 2147483399
Const AM As Double = (1.0# / IM1)
Const IMM1 As Double = (IM1 - 1.0#)
Const IA1 As Double = 40014
Const IA2 As Double = 40692
Const IQ1 As Double = 53668
Const IQ2 As Double = 52774
Const IR1 As Double = 12211
Const IR2 As Double = 3791
Const NTAB As Double = 32
Const NDIV As Double = (1.0# + IM1 / NTAB)
Const ESP As Double = 0.00000012
Const RNMX As Double = (1.0# - ESP)
Dim iCell As Integer
Dim idum As Double
Dim j As Integer
Dim k As Long
Dim temp As Double
Static idum2 As Long
Static iy As Long
Static iv(NTAB) As Long
idum2 = 123456789
iy = 0
'Seed value required is a negative integer (idum)
Randomize()
idum = (-Rnd() * 1000)
'For loop to generate a sequence of random numbers based on idum
For iCell = 1 To 10
'Initialize generator
If (idum <= 0) Then
'Prevent idum = 0
If (-(idum) < 1) Then
idum = 1
Else
idum = -(idum)
End If
idum2 = idum
For j = (NTAB + 7) To 0
k = ((idum) / IQ1)
idum = ((IA1 * (idum - (k * IQ1))) - (k * IR1))
If (idum < 0) Then
idum = (idum + IM1)
End If
If (j < NTAB) Then
iv(j) = idum
End If
Next j
iy = iv(0)
End If
'Start here when not initializing
k = (idum / IQ1)
idum = ((IA1 * (idum - (k * IQ1))) - (k * IR1))
If (idum < 0) Then
idum = (idum + IM1)
End If
k = (idum2 / IQ2)
idum2 = ((IA2 * (idum2 - (k * IQ2))) - (k * IR2))
If (idum2 < 0) Then
idum2 = idum2 + IM2
End If
j = (iy / NDIV)
iy = (iv(j) - idum2)
iv(j) = idum
If (iy < 1) Then
iy = (iy + IMM1)
End If
temp = AM * iy
If (temp <= RNMX) Then
'Return the value of the random number
UniformRandomNumber = temp
End If
Next iCell
End Function
End Module
You can use following line
Dim x1 as Double = MathNet.Numerics.Distributions.Normal.Sample(MEAN, STDEV)
Math.Net Numeric package can be installed using following NuGet command
Install-Package MathNet.Numerics -Version 4.9.0
You can found more information on NuGet site