@@ -316,22 +316,22 @@ Private Sub Class_Initialize()
316316 P_FORMATRESULT = False
317317 BuildinFunctIDList = "abs;floor;achisq;asin;acos;aerf;afishf;agauss;asc;anorm;atn;astudt;array;avg;beta.dist" & _
318318 ";betainv;ceil;chisq;cholesky;cholinverse;cholsolve;chr;cos;choose;date;dateadd;datediff" & _
319- ";datepart;dateserial;datevalue;day;ddb;det;erf;exp;fishf;fit;format;fv;fzero" & _
320- ";gamma;gammaln;gauss;get;hour;ibeta;iff;instr;inverse;ipmt;irr;lcase;left;len;log;lgn" & _
319+ ";datepart;dateserial;datevalue;day;ddb;det;distance; erf;exp;fishf;fit;format;fv;fzero" & _
320+ ";gamma;gammaln;gauss;get;hour;ibeta;iff;instr;inverse;ipmt;irr;lcase;left;len;linesintersect; log;lgn" & _
321321 ";ln;lsqrsolve;ludecomp;lusolve;max;mid;min;minute;mirr;mlr;mmult;mneg;mround" & _
322- ";msum;mtranspose;month;monthname;norm;now;nper;npv;percent;pmt;ppmt;pow;pv" & _
322+ ";msum;mtranspose;month;monthname;norm;now;nper;npv;parallel; percent;perpendicular ;pmt;ppmt;pow;pv" & _
323323 ";qr;rate;rem;replace;right;round;sgn;sin;sln;solve;sqr;sqrt;sum;studt;switch" & _
324324 ";syd;tan;timeserial;timevalue;tinv;tinv_1t;tinv_2t;trim;ucase;weekday" & _
325325 ";weekdayname;year"
326326 BuildinFunctNameList = "Absolute;aFloor;ACHISQ;ArcSin;ArcCos;AERF;AFISHF;AGAUSS;ASCII;ANORM;ArcTan" & _
327327 ";ASTUDT;strArray;Average;Beta_Distribution;BETAINV;aCeiling;CHISQ;CholeskyDec;CholeskyInverseMatrix" & _
328328 ";CholeskySolve;ASCIIchr;Cosin;aChoose;aDate;aDateAdd;aDateDiff;aDatePart;aDateSerial" & _
329- ";aDateValue;aDay;aDDB;MatrixDeterminant;ERF;ExpEuler;FISHF;CurveFit" & _
329+ ";aDateValue;aDay;aDDB;MatrixDeterminant;Distance; ERF;ExpEuler;FISHF;CurveFit" & _
330330 ";aFormat;aFV;FunctionZero;Gamma;GammaLN;GAUSS;GET;aHour;iBETA;aIff;aInstr;InverseMatrix" & _
331- ";aIPMT;aIRR;LowerCase;aLeft;aLen;Logarithm;LgN;LN;LSQRsolve;LUdecomposition" & _
331+ ";aIPMT;aIRR;LowerCase;aLeft;aLen;LinesIntersect; Logarithm;LgN;LN;LSQRsolve;LUdecomposition" & _
332332 ";LUSolveLinearSystem;Max;Middle;Min;aMinute;aMIRR;MultiLinearReg;MatrixMult" & _
333333 ";MatrixNegation;MatrixRound;MatrixSum;MatrixTranspose;aMonth;aMonthName;NORM" & _
334- ";aNow;aNPER;aNPV;Percent;aPMT;aPPMT;Power;aPV;QRdecomposition;aRATE;REM" & _
334+ ";aNow;aNPER;aNPV;ParallelLine; Percent;PerpendicularLine ;aPMT;aPPMT;Power;aPV;QRdecomposition;aRATE;REM" & _
335335 ";aReplace;aRight;ROUND;Sign;Sine;aSLN;SolveLinearSystem;SquareRoot;SquareRoot;SUM" & _
336336 ";STUDT;aSwitch;aSYD;Tangent;aTimeSerial;aTimeValue;TINV;TINV_1T;TINV_2T;aTrim" & _
337337 ";aUcase;aWweekDay;aWeekDayName;aYear"
@@ -1632,7 +1632,7 @@ Private Function BETAINV_(p As Double, A As Double, B As Double) As Double
16321632 Dim a1, b1 As Double
16331633 Dim j As Long
16341634 Dim lna As Double , lnb As Double
1635- Dim pp As Double , t As Double
1635+ Dim PP As Double , t As Double
16361636 Dim u As Double , err As Double
16371637 Dim x As Double , H As Double
16381638 Dim w As Double , afac As Double
@@ -1649,11 +1649,11 @@ Private Function BETAINV_(p As Double, A As Double, B As Double) As Double
16491649 End If
16501650 If A >= 1 And B >= 1 Then
16511651 If p < 0.5 Then
1652- pp = p
1652+ PP = p
16531653 Else
1654- pp = 1 - p
1654+ PP = 1 - p
16551655 End If
1656- t = Sqr(-2 * Log(pp ))
1656+ t = Sqr(-2 * Log(PP ))
16571657 x = (2.30753 + t * 0.27061 ) / (1 + t * (0.99229 + t * 0.04481 )) - t
16581658 If p < 0.5 Then x = -x
16591659 aL = (x * x - 3 ) / 6
@@ -2887,6 +2887,45 @@ err_Handler:
28872887 d_lParenthesis & err.Description & d_rParenthesis
28882888End Function
28892889
2890+ ''' <summary>
2891+ ''' Returns the distance between two given points. The points
2892+ ''' must be given each one in array format, ex.:
2893+ ''' {{x1;y1}};{{x2;y2}}
2894+ ''' </summary>
2895+ Private Function Distance (ByRef expression As String , ByRef fName As String ) As String
2896+ Dim argsCount As Long
2897+ Dim tmpData() As String
2898+ Dim tmpEval As String
2899+ Dim LB As Long , UB As Long
2900+
2901+ On Error GoTo err_Handler
2902+ tmpData() = SplitArgs(expression)
2903+ LB = LBound(tmpData)
2904+ UB = UBound(tmpData)
2905+ argsCount = UB - LB + 1
2906+ Select Case argsCount
2907+ Case 2
2908+ Dim aArray() As Variant
2909+ ReDim aArray(0 To 1 )
2910+
2911+ aArray(0 ) = ToDblArray(ArrayFromString(tmpData(LB)))
2912+ aArray(1 ) = ToDblArray(ArrayFromString(tmpData(UB)))
2913+ tmpEval = ( _
2914+ (aArray(1 )(0 ) - aArray(0 )(0 )) ^ 2 + _
2915+ (aArray(1 )(1 ) - aArray(0 )(1 )) ^ 2 _
2916+ ) ^ 0.5
2917+ Case Else
2918+ tmpEval = e_ValueError
2919+ BuildErrMessage errMissingArgsOrTooManyArgs, d_lCurly & fName & d_rCurly
2920+ End Select
2921+ Distance = tmpEval: Erase tmpData
2922+ Exit Function
2923+ err_Handler:
2924+ Distance = e_ValueError
2925+ BuildErrMessage errEvalError, d_lCurly & fName & d_rCurly & " | Error#: " & err.Number & d_Space & _
2926+ d_lParenthesis & err.Description & d_rParenthesis
2927+ End Function
2928+
28902929''' <summary>
28912930''' Finds for constant sub-expressions
28922931''' </summary>
@@ -3018,6 +3057,7 @@ Private Function EvalFunction(ByRef Argument As String, ByRef FunctionName As St
30183057 Case "aDateValue" : EvalFunction = DateValue_(Argument, FunctionName)
30193058 Case "aDay" : EvalFunction = Day_(Argument, FunctionName)
30203059 Case "aDDB" : EvalFunction = DDB_(Argument, FunctionName)
3060+ Case "Distance" : EvalFunction = Distance(Argument, FunctionName)
30213061 Case "MatrixDeterminant" : EvalFunction = Determinant(Argument, FunctionName)
30223062 Case "ERF" : EvalFunction = ERF(Argument, FunctionName)
30233063 Case "ExpEuler" : EvalFunction = ExpEuler(Argument, FunctionName)
@@ -3041,6 +3081,7 @@ Private Function EvalFunction(ByRef Argument As String, ByRef FunctionName As St
30413081 Case "aLeft" : EvalFunction = Left_(Argument, FunctionName)
30423082 Case "aLen" : EvalFunction = Len_(Argument, FunctionName)
30433083 Case "LowerCase" : EvalFunction = LCase_(Argument, FunctionName)
3084+ Case "LinesIntersect" : EvalFunction = LinesIntersect(Argument, FunctionName)
30443085 Case "Logarithm" : EvalFunction = Logarithm(Argument, FunctionName)
30453086 Case "LgN" : EvalFunction = LgN(Argument, FunctionName)
30463087 Case "LUdecomposition" : EvalFunction = LUdecomposition(Argument, FunctionName)
@@ -5121,7 +5162,7 @@ Private Function iBETAINV(p As Double, A As Double, B As Double) As Double
51215162 Dim a1, b1 As Double
51225163 Dim j As Long
51235164 Dim lna As Double , lnb As Double
5124- Dim pp As Double , t As Double
5165+ Dim PP As Double , t As Double
51255166 Dim u As Double , err As Double
51265167 Dim x As Double , H As Double
51275168 Dim w As Double , afac As Double
@@ -5138,11 +5179,11 @@ Private Function iBETAINV(p As Double, A As Double, B As Double) As Double
51385179 End If
51395180 If A >= 1 And B >= 1 Then
51405181 If p < 0.5 Then
5141- pp = p
5182+ PP = p
51425183 Else
5143- pp = 1 - p
5184+ PP = 1 - p
51445185 End If
5145- t = Sqr(-2 * Log(pp ))
5186+ t = Sqr(-2 * Log(PP ))
51465187 x = (2.30753 + t * 0.27061 ) / (1 + t * (0.99229 + t * 0.04481 )) - t
51475188 If p < 0.5 Then x = -x
51485189 aL = (x * x - 3 ) / 6
@@ -5770,6 +5811,116 @@ err_Handler:
57705811 d_lParenthesis & err.Description & d_rParenthesis
57715812End Function
57725813
5814+ ''' <summary>
5815+ ''' This function return the intersection of two lines given
5816+ ''' two ordered pairs of points for each line. The PointsInLine1
5817+ ''' and PointsInLine2 arguments must have the array form |[x] [y]|
5818+ ''' with the same size (2 rows and 2 columns). The returned value
5819+ ''' is an array |[x] [y]| if the lines meet and a #Null error value
5820+ ''' for parallel lines.
5821+ ''' </summary>
5822+ Private Function LinesIntersection (ByRef PointsInLine1 As Variant , _
5823+ PointsInLine2 As Variant , Optional k As Integer = 1 ) As Variant
5824+ Dim i As Double
5825+ Dim j As Double
5826+ Dim m As Double
5827+ Dim n As Double
5828+ Dim O As Double
5829+ Dim PP As Double
5830+ Dim HomogeneousPointsL1(0 To 1 , 0 To 2 ) As Variant
5831+ Dim HomogeneousPointsL2(0 To 1 , 0 To 2 ) As Variant
5832+ Dim HomogeneousEcuations(0 To 1 , 0 To 2 ) As Variant
5833+ Dim EcuationsProduct(0 To 0 , 0 To 2 ) As Variant
5834+ Dim Intersection(0 To 0 , 0 To 1 ) As Variant
5835+
5836+ If k <= 0 Then k = 1 'Ensure positive scalar value
5837+ m = LBound(PointsInLine1, 1 )
5838+ n = LBound(PointsInLine1, 2 )
5839+ 'Represent the points with homogeneous coordinates
5840+ i = 0
5841+ For O = m To m + 1
5842+ j = 0
5843+ For PP = n To n + 2
5844+ If PP < n + 2 Then
5845+ HomogeneousPointsL1(i, j) = PointsInLine1(O, PP)
5846+ HomogeneousPointsL2(i, j) = PointsInLine2(O, PP)
5847+ Else
5848+ HomogeneousPointsL1(i, j) = k
5849+ HomogeneousPointsL2(i, j) = k
5850+ End If
5851+ j = j + 1
5852+ Next PP
5853+ i = i + 1
5854+ Next O
5855+ 'Compute the lines homogeneous ecuations using Vectorial Matrix Products
5856+ HomogeneousEcuations(0 , 0 ) = (HomogeneousPointsL1(0 , 1 ) * HomogeneousPointsL1(1 , 2 )) - _
5857+ (HomogeneousPointsL1(1 , 1 ) * HomogeneousPointsL1(0 , 2 )) '[a01*a12 - a11*a02]
5858+ HomogeneousEcuations(0 , 1 ) = -1 * ((HomogeneousPointsL1(0 , 0 ) * HomogeneousPointsL1(1 , 2 )) - _
5859+ (HomogeneousPointsL1(1 , 0 ) * HomogeneousPointsL1(0 , 2 ))) '-[a00*a12 - a10*a02]
5860+ HomogeneousEcuations(0 , 2 ) = (HomogeneousPointsL1(0 , 0 ) * HomogeneousPointsL1(1 , 1 )) - _
5861+ (HomogeneousPointsL1(1 , 0 ) * HomogeneousPointsL1(0 , 1 )) '[a00*a11 - a10*a01]
5862+ HomogeneousEcuations(1 , 0 ) = (HomogeneousPointsL2(0 , 1 ) * HomogeneousPointsL2(1 , 2 )) - _
5863+ (HomogeneousPointsL2(1 , 1 ) * HomogeneousPointsL2(0 , 2 ))
5864+ HomogeneousEcuations(1 , 1 ) = -1 * ((HomogeneousPointsL2(0 , 0 ) * HomogeneousPointsL2(1 , 2 )) - _
5865+ (HomogeneousPointsL2(1 , 0 ) * HomogeneousPointsL2(0 , 2 )))
5866+ HomogeneousEcuations(1 , 2 ) = (HomogeneousPointsL2(0 , 0 ) * HomogeneousPointsL2(1 , 1 )) - _
5867+ (HomogeneousPointsL2(1 , 0 ) * HomogeneousPointsL2(0 , 1 ))
5868+ 'Compute the lines meet using Vectorial Matrix Products
5869+ EcuationsProduct(0 , 0 ) = (HomogeneousEcuations(0 , 1 ) * HomogeneousEcuations(1 , 2 )) - _
5870+ (HomogeneousEcuations(1 , 1 ) * HomogeneousEcuations(0 , 2 )) '[a01*a12 - a11*a02]
5871+ EcuationsProduct(0 , 1 ) = -1 * ((HomogeneousEcuations(0 , 0 ) * HomogeneousEcuations(1 , 2 )) - _
5872+ (HomogeneousEcuations(1 , 0 ) * HomogeneousEcuations(0 , 2 ))) '-[a00*a12 - a10*a02]
5873+ EcuationsProduct(0 , 2 ) = (HomogeneousEcuations(0 , 0 ) * HomogeneousEcuations(1 , 1 ) - _
5874+ (HomogeneousEcuations(1 , 0 ) * HomogeneousEcuations(0 , 1 ))) '[a00*a11 - a10*a01]
5875+ If EcuationsProduct(0 , 2 ) = 0 Then
5876+ LinesIntersection = "#Null" 'Return a Null value. The lines meet at the infinity.
5877+ Else
5878+ Intersection(0 , 0 ) = k * EcuationsProduct(0 , 0 ) / EcuationsProduct(0 , 2 )
5879+ Intersection(0 , 1 ) = k * EcuationsProduct(0 , 1 ) / EcuationsProduct(0 , 2 )
5880+ LinesIntersection = Intersection
5881+ End If
5882+ End Function
5883+
5884+ ''' <summary>
5885+ ''' Returns the intersection point for two lines.
5886+ ''' The lines must be given by two crossing points each
5887+ ''' in array format, ex.:
5888+ ''' {{x1;y1};{x2;y2}}; {{x3;y3};{x4;y4}}
5889+ ''' </summary>
5890+ Private Function LinesIntersect (ByRef expression As String , ByRef fName As String ) As String
5891+ Dim argsCount As Long
5892+ Dim tmpData() As String
5893+ Dim tmpEval As Variant
5894+ Dim LB As Long , UB As Long
5895+
5896+ On Error GoTo err_Handler
5897+ tmpData() = SplitArgs(expression)
5898+ LB = LBound(tmpData)
5899+ UB = UBound(tmpData)
5900+ argsCount = UB - LB + 1
5901+ Select Case argsCount
5902+ Case 2
5903+ Dim aArray() As Variant
5904+ ReDim aArray(0 To 1 )
5905+
5906+ aArray(0 ) = ToDblArray(ArrayFromString(tmpData(LB)))
5907+ aArray(1 ) = ToDblArray(ArrayFromString(tmpData(UB)))
5908+ tmpEval = LinesIntersection(aArray(0 ), aArray(1 ))
5909+ If IsArray(tmpEval) Then
5910+ tmpEval = ArrayToString(tmpEval)
5911+ End If
5912+ Case Else
5913+ tmpEval = e_ValueError
5914+ BuildErrMessage errMissingArgsOrTooManyArgs, d_lCurly & fName & d_rCurly
5915+ End Select
5916+ LinesIntersect = tmpEval: Erase tmpData
5917+ Exit Function
5918+ err_Handler:
5919+ LinesIntersect = e_ValueError
5920+ BuildErrMessage errEvalError, d_lCurly & fName & d_rCurly & " | Error#: " & err.Number & d_Space & _
5921+ d_lParenthesis & err.Description & d_rParenthesis
5922+ End Function
5923+
57735924Private Function LN (ByRef expression As String , ByRef fName As String ) As String
57745925 On Error GoTo err_Handler
57755926 LN = CStr(Log(CDbl(expression)))
@@ -7978,7 +8129,7 @@ Private Function RegressionString(ByRef SolverResult() As Double, Optional ByRef
79788129 Dim strPNames As String
79798130 Dim m As Long
79808131 Dim n As Long
7981- Dim o As Long
8132+ Dim O As Long
79828133 Dim s As Long
79838134
79848135 m = -1
@@ -7988,9 +8139,9 @@ Private Function RegressionString(ByRef SolverResult() As Double, Optional ByRef
79888139 strPNames = Join$(PredNames, P_SEPARATORCHAR)
79898140 End If
79908141 If Not IsNumeric(PredInteractions) Then n = UBound(PredInteractions)
7991- o = UBound(SolverResult)
7992- ReDim tmpNames(0 To o - 1 )
7993- For i = 0 To o - 1
8142+ O = UBound(SolverResult)
8143+ ReDim tmpNames(0 To O - 1 )
8144+ For i = 0 To O - 1
79948145 If m >= 0 And n >= 0 Then
79958146 If s <= m Then
79968147 tmpNames(i) = PredNames(i)
@@ -7999,14 +8150,14 @@ Private Function RegressionString(ByRef SolverResult() As Double, Optional ByRef
79998150 tmpNames(i) = FormatNamedPredictors(strPNames, CStr(PredInteractions(i - s)), False )
80008151 End If
80018152 Else
8002- If n + 1 - (o - i) >= 0 Then 'Save predictors relations without names
8003- tmpNames(i) = PredInteractions(n + 1 - (o - i))
8153+ If n + 1 - (O - i) >= 0 Then 'Save predictors relations without names
8154+ tmpNames(i) = PredInteractions(n + 1 - (O - i))
80048155 Else
80058156 tmpNames(i) = "X" & CStr(i + 1 )
80068157 End If
80078158 End If
80088159 Next i
8009- For i = 0 To o
8160+ For i = 0 To O
80108161 If i = 0 Then
80118162 tmpResult = CStr(Round(SolverResult(i, 0 ), 4 ))
80128163 Else
0 commit comments