[mono-vb] Implementation of Financial vb module

Rob.Tillie@Student.tUL.EDU Rob.Tillie@Student.tUL.EDU
Sat, 12 Jun 2004 13:17:52 +0200


This message is in MIME format. Since your mail reader does not understand
this format, some or all of this message may not be legible.

------_=_NextPart_000_01C4506E.E73FF6D0
Content-Type: text/plain

Hello all,

Because of the complexity of FileSystem, I implemented Financial first
together with unit tests, to get a feel for Mono and its formatting.

It is largely copied from the MainSoft code, but I corrected a few
implementation differences with MS.NET. 
Everything works like on MS.NET now.

Because this is my first contribution, I would love to get some feedback on
what I have done wrong, especially concerning formatting.
I used the tab character now for tabs, couldn't figure out if I was supposed
to use tab character or spaces.

The formatting of FileSystem is pretty screwed up, could someone fix this or
could I post a formatting patch?

Greetz,
-- Rob.


------_=_NextPart_000_01C4506E.E73FF6D0
Content-Type: application/octet-stream;
	name="FinancialTest.cs"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="FinancialTest.cs"

// FinancialTest.cs - 	NUnit Test Cases for vb module Financial
//						(class Microsoft.VisualBasic.Financial)
//
// Rob Tillie (Rob@flep-tech.nl)
//
// (C) 2004 Rob Tillie
//=20

using NUnit.Framework;
using System;
using Microsoft.VisualBasic;

namespace MonoTests.Microsoft.VisualBasic
{

	[TestFixture]
	public class FinancialTest : Assertion {
=09
		[SetUp]
		public void GetReady() {}

		[TearDown]
		public void Clean() {}
	=09
	=09
		// -- DDB Tests
		[Test]
		[ExpectedException(typeof(ArgumentException))]
		public void TestDDBArg1()
		{
			Financial.DDB (-1, 1, 1, 1, 1);
		}
	=09
		[Test]
		[ExpectedException(typeof(ArgumentException))]
		public void TestDDBArg2()
		{
			Financial.DDB (1, -1, 1, 1, 1);
		}
	=09
		[Test]
		[ExpectedException(typeof(ArgumentException))]
		public void TestDDBArg3()
		{
			Financial.DDB (1, 1, 0, 1, 1);
		}
	=09
		[Test]
		[ExpectedException(typeof(ArgumentException))]
		public void TestDDBArg4()
		{
			Financial.DDB (1, 1, 1, 1, 0);
		}
	=09
		[Test]
		[ExpectedException(typeof(ArgumentException))]
		public void TestDDBArg5()
		{
			// Period has to be > Life
			Financial.DDB (1, 1, 1, 2, 1);
		}
	=09
		[Test]
		public void TestDDB()
		{
			double ddb =3D Financial.DDB (1000, 50, 10, 5, 3);
			AssertEquals ("#DDB01", 1425, ddb, 0);
		=09
			// TODO: How should we test an optional parameter in C#?
			ddb =3D Financial.DDB (1000, 50, 10, 5, 2);
			AssertEquals ("#DDB02", 950, ddb, 0);
		}
	=09
		[Test]
		public void TestFV()
		{
			double d =3D Financial.FV (10, 5, 3, 7, DueDate.BegOfPeriod);
			AssertEquals ("#FV01", -1658822, d);
		=09
			d =3D Financial.FV (10, 5, 3, 7, DueDate.EndOfPeriod);
			AssertEquals ("#FV02", -1175672, d);
		=09
			d =3D Financial.FV (0, 5, 3, 7, DueDate.BegOfPeriod);
			AssertEquals ("#FV03", -22, d);
		=09
			d =3D Financial.FV(0, 1, 1, 1, DueDate.BegOfPeriod);
			AssertEquals ("#FV04", -2, d);
		=09
			d =3D Financial.FV (0, 0, 0, 0, DueDate.BegOfPeriod);
			AssertEquals ("#FV05", 0, d);
		=09
			d =3D Financial.FV (-3, -5, -6, -4, DueDate.BegOfPeriod);
			AssertEquals ("#FV06", -4.25, d);
		}
	=09
		[Test]
		[ExpectedException(typeof(ArgumentException))]
		public void TestIPmtArgs1()
		{
			Financial.IPmt (3, 6, 4, 2, 2, DueDate.BegOfPeriod);
		}
	=09
		[Test]
		[ExpectedException(typeof(ArgumentException))]
		public void TestIPmtArgs2()
		{
			Financial.IPmt (3, 0, 4, 2, 2, DueDate.BegOfPeriod);
		}
	=09
		[Test]
		public void TestIPmt()
		{
			double d =3D Financial.IPmt (10, 2, 3, 7, 9, DueDate.BegOfPeriod);
        		AssertEquals ("#IPmt01", -6.25427204374573, d);
		=09
        		d =3D Financial.IPmt (10, 4, 4, 7, 4, DueDate.EndOfPeriod);
        		AssertEquals ("#IPmt02", -60.0068306011053, d);
		=09
        		d =3D Financial.IPmt (0, 5, 7, 7, 2, DueDate.BegOfPeriod);
			AssertEquals ("#IPmt03", 0, d);
		=09
			d =3D Financial.IPmt (-5, 5, 7, -7, -2, DueDate.BegOfPeriod);
			AssertEquals ("#IPmt04", 8.92508391821792, d);
		}
	=09
		[Test]
		[ExpectedException(typeof(ArgumentException))]
		public void TestPmtArgs()
		{
			Financial.Pmt (1, 0, 1, 1, DueDate.BegOfPeriod);
		}
	=09
		[Test]
		public void TestPmt()
		{
			double d =3D Financial.Pmt (2, 5, 2, 3, DueDate.BegOfPeriod);
			AssertEquals ("#Pmt01", -1.34710743801653, d);
		=09
			d =3D Financial.Pmt (2, 5, 2, 3, DueDate.EndOfPeriod);
			AssertEquals ("#Pmt02", -4.04132231404959, d);
		=09
        		d =3D Financial.Pmt (-3, -5, -3, -4, DueDate.BegOfPeriod);
			AssertEquals ("#Pmt03", -5.68181818181818, d);
		=09
        		d =3D Financial.Pmt (-3, -5, -3, -4, DueDate.EndOfPeriod);
			AssertEquals ("#Pmt04", 11.3636363636364, d);
		=09
        		d =3D Financial.Pmt (0, 1, 0, 0, DueDate.BegOfPeriod);
			AssertEquals ("#Pmt05", 0, d);
		=09
        		d =3D Financial.Pmt (0, 1, 0, 0, DueDate.EndOfPeriod);
			AssertEquals ("#Pmt06", 0, d);
		}
	=09
		[Test]
		[ExpectedException(typeof(ArgumentException))]
		public void TestSLNArgs()
		{
			Financial.SLN (0, 0, 0);
		}	=09
	=09
		[Test]
		public void TestSLN()
		{
		        double d =3D Financial.SLN (0, 0, 1);
			AssertEquals ("#SLN01", 0, d);
       =20
        		d =3D Financial.SLN (45, 32, 345);
        		AssertEquals ("#SLN02", 0.0376811594202899, d, 0.0001);
       =20
        		d =3D Financial.SLN (-54, -4, -76);
			AssertEquals ("#SLN03", 0.657894736842105, d, 0.001);
        	}
        =09
        	[Test]
        	[ExpectedException(typeof(ArgumentException))]
		public void TestSYDArgs1()
		{
			Financial.SYD (1, 1, 1, -1);
		}=09
	=09
		[Test]
        	[ExpectedException(typeof(ArgumentException))]
		public void TestSYDArgs2()
		{
			Financial.SYD (1, -1, 1, 1);
		}
	=09
		[Test]
        	[ExpectedException(typeof(ArgumentException))]
		public void TestSYDArgs3()
		{
			Financial.SYD (1, 1, 1, 2);
		}
	=09
		[Test]
		public void TestSYD()
		{
			double d =3D Financial.SYD (23, 34, 26, 21);
        		AssertEquals ("#SYD01", -0.188034188034188, d);

        		d =3D Financial.SYD (0, 1, 1, 1);
        		AssertEquals ("#SYD02", -1, d);
		}
	=09
		[Test]
        	[ExpectedException(typeof(ArgumentException))]
		public void TestIRRArgs1()
		{
			double [] arr =3D new double [0];
			Financial.IRR (ref arr, 0.1);
		}
	=09
		[Test]
        	[ExpectedException(typeof(ArgumentException))]
		public void TestIRRArgs2()
		{
			double [] arr =3D new double [] {134};
			Financial.IRR (ref arr, 0.1);
		}
	=09
		[Test]
        	[ExpectedException(typeof(ArgumentException))]
		public void TestIRRArgs3()
		{
			// -0.99 as Guess throws an exception on MS.NET, -0.98 doesn't
			double [] arr =3D new double [] {-70000, 22000, 25000, 28000, =
31000};
			double d =3D Financial.IRR (ref arr, -0.99);
		}
	=09
		[Test]
		public void TestIRR()
		{
			double [] arr =3D new double [] {-70000, 22000, 25000, 28000, =
31000};
			double d =3D Financial.IRR (ref arr, 0.1);
			AssertEquals ("#IRR01", 0.177435884422527, d);
		}
	=09
		[Test]
        	[ExpectedException(typeof(ArgumentException))]
		public void TestNPVArgs1()
		{
			double [] arr =3D null;
			double d =3D Financial.NPV (0.0625, ref arr);
		}
	=09
		[Test]
        	[ExpectedException(typeof(ArgumentException))]
		public void TestNPVArgs2()
		{
			double [] arr =3D new double [] {-70000, 22000, 25000, 28000, =
31000};
			double d =3D Financial.NPV (-1, ref arr);
		}
		=09
		[Test]
		public void TestNPV()
		{
			double [] arr =3D new double [] {-70000, 22000, 25000, 28000, =
31000};
			double d =3D Financial.NPV (0.0625, ref arr);=09
			AssertEquals ("#NPV01", 19312.5702095352, d);
		}
	=09
		[Test]
        	[ExpectedException(typeof(ArgumentException))]
		public void TestNPerArgs1()
		{
			double d =3D Financial.NPer (-1, 2, 2, 2, DueDate.BegOfPeriod);
		}
	=09
		[Test]
        	[ExpectedException(typeof(ArgumentException))]
		public void TestNPerArgs2()
		{
			double d =3D Financial.NPer (0, 0, 2, 2, DueDate.BegOfPeriod);
		}
	=09
		[Test]
		public void TestNPer()
		{
			double d =3D Financial.NPer (3, 4, 6, 2, DueDate.BegOfPeriod);
			AssertEquals ("#NPer01", -0.882767373181489, d, 0.001);
		=09
			d =3D Financial.NPer (1, -4, -6, -2, DueDate.EndOfPeriod);
			AssertEquals ("#NPer02", -2.32192809488736, d, 0.001);
		}
	=09
		[Test]
        	[ExpectedException(typeof(ArgumentException))]
		public void TestMIRRArgs1()
		{
			double [] arr =3D new double [] {-70000, 22000, 25000, 28000, =
31000};
			double d =3D Financial.MIRR(ref arr, -1, 1);
		}
	=09
		[Test]
        	[ExpectedException(typeof(ArgumentException))]
		public void TestMIRRArgs2()
		{
			double [] arr =3D new double [] {-70000, 22000, 25000, 28000, =
31000};
			double d =3D Financial.MIRR(ref arr, 1, -1);
		}
	=09
		[Test]
		public void TestMIRR()
		{
			double [] arr =3D new double [] {-70000, 22000, 25000, 28000, =
31000};
			double d =3D Financial.MIRR (ref arr, 1, 1);
			AssertEquals ("#MIRR01", 0.509044845533018, d);
		=09
			arr =3D new double [] {-70000, 22000, 25000, 28000, 31000};
			d =3D Financial.MIRR (ref arr, 5, 5);
			AssertEquals ("#MIRR02", 2.02366041666348, d);
		}
	=09
		[Test]
        	[ExpectedException(typeof(ArgumentException))]
		public void TestPPmtArgs1()
		{
			double d =3D Financial.PPmt (2, -1, 1, 1, 1, DueDate.EndOfPeriod);
		}
	=09
		[Test]
        	[ExpectedException(typeof(ArgumentException))]
		public void TestPPmtArgs2()
		{
			double d =3D Financial.PPmt (1, 2, 1, 1, 1, DueDate.BegOfPeriod);
		}
	=09
		[Test]
		public void TestPPmt()
		{
			double d =3D Financial.PPmt (10, 2, 3, 7, 9, DueDate.BegOfPeriod);
        		AssertEquals("#PPmt01", -0.120300751879702, d);
		=09
        		d =3D Financial.PPmt (10, 4, 4, 7, 4, DueDate.EndOfPeriod);
        		AssertEquals("#PPmt02", -10.0006830600969, d);
		=09
        		d =3D Financial.PPmt (0, 5, 7, 7, 2, DueDate.BegOfPeriod);
			AssertEquals("#PPmt03", -1.28571428571429, d);
		=09
			d =3D Financial.PPmt (-5, 5, 7, -7, -2, DueDate.BegOfPeriod);
			AssertEquals("#PPmt04", -0.175770521818777, d);
		}
	=09
		[Test]
		public void TestPV()
		{
			double d =3D Financial.PV (1, 1, 1, 1, DueDate.BegOfPeriod);
			AssertEquals ("#PV01", -1.5, d);
		=09
			d =3D Financial.PV (1, 1, 1, 1, DueDate.EndOfPeriod);
			AssertEquals ("#PV02", -1, d);
		}
	=09
		[Test]
        	[ExpectedException(typeof(ArgumentException))]
		public void TestRateArgs1()
		{
			double d =3D Financial.Rate (-1, 1, 1, 1, DueDate.BegOfPeriod, 1);
		}
	=09
		[Test]
		public void TestRate()
		{
			double d =3D Financial.Rate (1, 1, 1, 1, DueDate.BegOfPeriod, 0.1);
			AssertEquals("#Rate01", -1.5, d, 0.01);
		=09
			d =3D Financial.Rate (1, -1, -1, -1, DueDate.BegOfPeriod, 0.1);
			AssertEquals("#Rate02", -1.50000000000001, d, 0.01);
		=09
			d =3D Financial.Rate (1, 2, 12, 10, DueDate.BegOfPeriod, 0.5);
			AssertEquals("#Rate03", -1.71428571428571, d);
		}
	}
}

------_=_NextPart_000_01C4506E.E73FF6D0
Content-Type: application/octet-stream;
	name="Financial.patch"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="Financial.patch"

Index: Financial.cs
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: =
/mono/mcs/class/Microsoft.VisualBasic/Microsoft.VisualBasic/Financial.cs=
,v
retrieving revision 1.4
diff -u -r1.4 Financial.cs
--- Financial.cs	31 May 2004 05:35:21 -0000	1.4
+++ Financial.cs	11 Jun 2004 20:43:57 -0000
@@ -3,14 +3,38 @@
 //
 // Author:
 //   Chris J Breisch (cjbreisch@altavista.net)=20
+//   Rob Tillie (Rob@flep-tech.nl)
 //
 // (C) 2002 Chris J Breisch
-//
+// (C) 2004 Rob Tillie
+// (C) 2002-2003 MainSoft
+ /*
+  * Copyright (c) 2002-2003 Mainsoft Corporation.
+  *
+  * Permission is hereby granted, free of charge, to any person =
obtaining a
+  * copy of this software and associated documentation files (the =
"Software"),
+  * to deal in the Software without restriction, including without =
limitation
+  * the rights to use, copy, modify, merge, publish, distribute, =
sublicense,
+  * and/or sell copies of the Software, and to permit persons to whom =
the
+  * Software is furnished to do so, subject to the following =
conditions:
+  *=20
+  * The above copyright notice and this permission notice shall be =
included in
+  * all copies or substantial portions of the Software.
+  *=20
+  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, =
EXPRESS OR
+  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF =
MERCHANTABILITY,
+  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT =
SHALL THE
+  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR =
OTHER
+  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, =
ARISING
+  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR =
OTHER
+  * DEALINGS IN THE SOFTWARE.
+  */
=20
 using System;
 using Microsoft.VisualBasic.CompilerServices;
=20
-namespace Microsoft.VisualBasic=20
+namespace Microsoft.VisualBasic=20
+
 {
 	[StandardModule]=20
 	sealed public class Financial {
@@ -19,32 +43,331 @@
 		private Financial() {} // prevent public default constructor
 		// Properties
 		// Methods
-		[MonoTODO]
-		public static System.Double DDB (System.Double Cost, System.Double =
Salvage, System.Double Life, System.Double Period, =
[System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(2)] System.Double Factor) { throw =
new NotImplementedException (); }
-		[MonoTODO]
-		public static System.Double FV (System.Double Rate, System.Double =
NPer, System.Double Pmt, [System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] System.Double PV, =
[System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] Microsoft.VisualBasic.DueDate =
Due) { throw new NotImplementedException (); }
-		[MonoTODO]
-		public static System.Double IPmt (System.Double Rate, System.Double =
Per, System.Double NPer, System.Double PV, =
[System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] System.Double FV, =
[System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] Microsoft.VisualBasic.DueDate =
Due) { throw new NotImplementedException (); }
-		[MonoTODO]
-		public static System.Double IRR (ref System.Double[] ValueArray, =
[System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0.1)] System.Double Guess) { throw =
new NotImplementedException (); }
-		[MonoTODO]
-		public static System.Double MIRR (ref System.Double[] ValueArray, =
System.Double FinanceRate, System.Double ReinvestRate) { throw new =
NotImplementedException (); }
-		[MonoTODO]
-		public static System.Double NPer (System.Double Rate, System.Double =
Pmt, System.Double PV, [System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] System.Double FV, =
[System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] Microsoft.VisualBasic.DueDate =
Due) { throw new NotImplementedException (); }
-		[MonoTODO]
-		public static System.Double NPV (System.Double Rate, ref =
System.Double[] ValueArray) { throw new NotImplementedException (); }
-		[MonoTODO]
-		public static System.Double Pmt (System.Double Rate, System.Double =
NPer, System.Double PV, [System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] System.Double FV, =
[System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] Microsoft.VisualBasic.DueDate =
Due) { throw new NotImplementedException (); }
-		[MonoTODO]
-		public static System.Double PPmt (System.Double Rate, System.Double =
Per, System.Double NPer, System.Double PV, =
[System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] System.Double FV, =
[System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] Microsoft.VisualBasic.DueDate =
Due) { throw new NotImplementedException (); }
-		[MonoTODO]
-		public static System.Double PV (System.Double Rate, System.Double =
NPer, System.Double Pmt, [System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] System.Double FV, =
[System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] Microsoft.VisualBasic.DueDate =
Due) { throw new NotImplementedException (); }
-		[MonoTODO]
-		public static System.Double Rate (System.Double NPer, System.Double =
Pmt, System.Double PV, [System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] System.Double FV, =
[System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] Microsoft.VisualBasic.DueDate =
Due, [System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0.1)] System.Double Guess) { throw =
new NotImplementedException (); }
-		[MonoTODO]
-		public static System.Double SLN (System.Double Cost, System.Double =
Salvage, System.Double Life) { throw new NotImplementedException (); }
-		[MonoTODO]
-		public static System.Double SYD (System.Double Cost, System.Double =
Salvage, System.Double Life, System.Double Period) { throw new =
NotImplementedException (); }
+		public static System.Double DDB (System.Double Cost, System.Double =
Salvage, System.Double Life, System.Double Period, =
[System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(2)] System.Double Factor)=20
+		{=20
+			// LAMESPEC: MSDN says Life and Factor only throws exception if < =
0, but Implementation throws exception if <=3D 0
+			if (Cost < 0
+			    || Salvage < 0
+			    || Life <=3D 0
+			    || Period < 0
+			    || Factor <=3D 0
+			    || Period > Life)
+				throw new ArgumentException ("Invalid argument value");
+		=09
+			return (((Cost - Salvage) * Factor) / Life) * Period;
+		}
+	=09
+		public static System.Double FV (System.Double Rate, System.Double =
NPer, System.Double Pmt, [System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] System.Double PV, =
[System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] Microsoft.VisualBasic.DueDate =
Due)=20
+		{=20
+			Pmt =3D -Pmt;
+			PV =3D -PV;
+			double currentRate =3D Math.Pow (Rate + 1, NPer);
+			double sum =3D 0;
+		=09
+			if (Rate !=3D 0)
+				sum =3D Pmt * ((currentRate - 1) / Rate);
+			else
+				sum =3D Pmt * NPer;
+=09
+			if (Due =3D=3D DueDate.BegOfPeriod)
+				sum *=3D (1 + Rate);
+		=09
+			return PV * currentRate + sum;
+		}
+	=09
+		public static System.Double IPmt (System.Double Rate, System.Double =
Per, System.Double NPer, System.Double PV, =
[System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] System.Double FV, =
[System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] Microsoft.VisualBasic.DueDate =
Due)
+		{=20
+			double totalFutureVal;
+		        double totalPaymentValue;
+		        double numberOfPeriods;
+		       =20
+		        if ((Per <=3D 0) || (Per >=3D (NPer + 1)))
+		        	throw new ArgumentException ("Argument 'Per' is not =
valid");
+		        if ((Due =3D=3D DueDate.BegOfPeriod) && (Per =3D=3D 1))
+		        	return 0;
+		       =20
+		        totalPaymentValue =3D Pmt (Rate, NPer, PV, FV, Due);
+		        if (Due =3D=3D DueDate.BegOfPeriod)
+		        	PV =3D (PV + totalPaymentValue);
+		=09
+		        numberOfPeriods =3D Per - ((int)Due) - 1;
+		        totalFutureVal =3D
+		        	Financial.FV (Rate, numberOfPeriods, totalPaymentValue, PV, =
DueDate.EndOfPeriod);
+		       =20
+		        return (totalFutureVal * Rate);
+		}
+	=09
+		public static System.Double IRR (ref System.Double[] ValueArray, =
[System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0.1)] System.Double Guess)=20
+		{=20
+			double origPV, updatedPV, updateGuess, tmp;
+		        double rateDiff =3D 0.0;
+		        double pvDiff =3D 0.0;
+		        int length;
+		=09
+			// MS.NET 2.0 docs say that Guess may not be <=3D -1
+		        if (Guess <=3D -1)       =20
+		            	throw new ArgumentException ("Argument 'Guess' is =
invalid");       =20
+		        try {
+		        	length =3D ValueArray.GetLength(0);
+		        }
+		        catch {
+		            	throw new ArgumentException ("Argument 'ValueArray' is =
invalid");
+		        }
+		        if (length < 2)       =20
+		            throw new ArgumentException ("Argument 'ValueArray' is =
invalid");      =20
+		=09
+		        origPV =3D NPV (Guess, ref ValueArray);
+		        updateGuess =3D (origPV > 0) ? Guess + 0.00001 : Guess - =
0.00001;  =20
+		       =20
+		        if (updateGuess < -1)
+		            throw new ArgumentException ("Argument 'ValueArray:Rate' =
is invalid");
+		=09
+		        rateDiff =3D  updateGuess - Guess;      =20
+		        updatedPV =3D NPV (updateGuess, ref ValueArray);
+		        pvDiff =3D updatedPV - origPV;
+		        for (int i =3D 0; i < 20; i++) {
+				Guess =3D (updateGuess > Guess) ? (Guess - 0.00001) : (Guess + =
0.00001);
+				origPV =3D NPV (Guess, ref ValueArray);
+				rateDiff =3D  updateGuess - Guess;
+				pvDiff =3D updatedPV - origPV;  =20
+				if (pvDiff =3D=3D 0)
+					throw new ArgumentException ("Argument is invalid.");
+				Guess =3D updateGuess - (rateDiff * updatedPV / pvDiff);
+				if (Guess < -1)
+				Guess =3D -1;
+				origPV =3D NPV (Guess, ref ValueArray);
+				if ((Math.Abs (origPV) < 0.0000001) && (Math.Abs (rateDiff) < =
0.00001))
+					return Guess;
+		        =09
+				tmp =3D Guess;
+				Guess =3D updateGuess;
+				updateGuess =3D tmp;
+				tmp =3D origPV;
+				origPV =3D updatedPV;
+				updatedPV =3D tmp;
+		        }
+		        double origPVAbs =3D Math.Abs (origPV);
+		        double updatedPVAbs =3D Math.Abs (updatedPV);
+		        if ((origPVAbs < 0.0000001) && (updatedPVAbs < 0.0000001))
+		            return (origPVAbs < updatedPVAbs) ? Guess : updateGuess;
+		        else if (origPVAbs < 0.0000001)
+		            return  Guess;
+		        else if (updatedPVAbs < 0.0000001)
+		            return updateGuess;
+		        else               =20
+		            throw new ArgumentException("Argument is invalid.");
+		}
+	=09
+		public static System.Double MIRR (ref System.Double[] ValueArray, =
System.Double FinanceRate, System.Double ReinvestRate)
+		{=20
+			double [] array =3D ValueArray;
+			double loansVal =3D 0;
+			double assetsVal =3D 0;
+			double currentLoanRate =3D 1;
+			double currentAssetsRate =3D 1;
+			double totalInterestRate =3D 0;
+			int arrayLength =3D 0;
+			if (array.Rank !=3D 1)
+				throw new ArgumentException ("Rank of 'ValueArray' must be 1.");
+			else if (FinanceRate =3D=3D -1)
+				throw new ArgumentException ("Argument 'FinanceRate' is =
invalid.");
+			else if (ReinvestRate =3D=3D -1)
+				throw new ArgumentException ("Argument 'ReinvestRate' is =
invalid.");
+		=09
+			arrayLength =3D array.Length;
+			if (arrayLength < 2)
+				throw new ArgumentException ("Argument 'ValueArray' is invalid.");
+		=09
+			for (int i =3D 0; i < arrayLength; i++) {
+				currentLoanRate *=3D (1 + FinanceRate);
+				currentAssetsRate *=3D (1 + ReinvestRate);
+				if (array [i] < 0)
+				loansVal +=3D (array [i] / currentLoanRate);
+				else if (array [i] > 0)
+				assetsVal +=3D (array [i] / currentAssetsRate);
+			}
+		=09
+			if (loansVal =3D=3D 0)
+				throw new DivideByZeroException ("Division by zero has =
occurred.");
+		=09
+			totalInterestRate =3D
+				((-assetsVal * Math.Pow (ReinvestRate + 1, arrayLength))
+				/ (loansVal * (FinanceRate + 1)));
+			if (totalInterestRate < 0)
+				throw new ArgumentException ("Argument is invalid.");
+		=09
+			return (Math.Pow (totalInterestRate, 1 / (double) (arrayLength - =
1))) - 1;
+		}
+	=09
+		public static System.Double NPer (System.Double Rate, System.Double =
Pmt, System.Double PV, [System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] System.Double FV, =
[System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] Microsoft.VisualBasic.DueDate =
Due)=20
+		{=20
+			double totalIncomeFromFlow, sumOfPvAndPayment, =
currentValueOfPvAndPayment;
+			if (Rate =3D=3D 0 && Pmt =3D=3D 0)
+				throw new ArgumentException ("Argument 'Pmt' is invalid.");
+			else if (Rate =3D=3D 0)
+				return (- (PV + FV) / Pmt);
+			// MainSoft had Rate < -1, but MS.NET 2.0 Doc says Rate should not =
be <=3D -1
+			else if (Rate <=3D -1)
+				throw new ArgumentException("Argument 'Rate' is invalid.");
+			totalIncomeFromFlow =3D (Pmt / Rate);
+			if (Due =3D=3D DueDate.BegOfPeriod)
+			totalIncomeFromFlow *=3D (1 + Rate);
+		=09
+			sumOfPvAndPayment =3D (-FV + totalIncomeFromFlow);
+			currentValueOfPvAndPayment =3D (PV + totalIncomeFromFlow);
+			if ((sumOfPvAndPayment < 0) && (currentValueOfPvAndPayment < 0)) {
+				sumOfPvAndPayment =3D -sumOfPvAndPayment;
+				currentValueOfPvAndPayment =3D -currentValueOfPvAndPayment;
+			}
+			else if ((sumOfPvAndPayment <=3D 0) || (currentValueOfPvAndPayment =
< 0))
+				throw new ArgumentException ("Cannot calculate NPer");
+		=09
+			double totalInterestRate =3D sumOfPvAndPayment / =
currentValueOfPvAndPayment;
+			return Math.Log (totalInterestRate) / Math.Log (Rate + 1);
+		}
+	=09
+		public static System.Double NPV (System.Double Rate, ref =
System.Double[] ValueArray)=20
+		{=20
+			if (ValueArray =3D=3D null)
+				throw new ArgumentException ("Argument 'ValueArray' is invalid.");
+		=09
+			double [] arr =3D ValueArray;
+			if (arr.Rank !=3D 1)
+				throw new ArgumentException ("Argument 'ValueArray' is invalid, =
rank must be 1.");
+			if (Rate =3D=3D -1)
+				throw new ArgumentException ("Argument 'Rate' is invalid");
+			int length =3D arr.Length;
+			if (length < 0)
+				throw new ArgumentException ("Argument 'ValueArray' is invalid");
+		=09
+			double currentValue =3D 0;
+			double currentRate =3D 1;
+			double sum =3D 0;
+			for (int index =3D 0; index < length; index++) {
+				currentValue =3D arr [index];
+				currentRate *=3D (1 + Rate);
+				sum +=3D (currentValue / currentRate);
+			}
+			return sum;
+		}
+	=09
+		public static System.Double Pmt (System.Double Rate, System.Double =
NPer, System.Double PV, [System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] System.Double FV, =
[System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] Microsoft.VisualBasic.DueDate =
Due)=20
+		{=20
+			PV =3D -PV;
+		        FV =3D -FV;
+		        if (NPer =3D=3D 0)
+		        	throw new ArgumentException ("Argument 'NPer' is =
invalid.");
+		=09
+		        double totalFutureVal =3D 0;
+		        double geometricSum =3D 0;=20
+		        if (Rate =3D=3D 0) {
+		        	totalFutureVal =3D FV + PV;
+		        	geometricSum =3D NPer;
+		        }
+		        else if (Due =3D=3D DueDate.EndOfPeriod) {
+		        	double totalRate =3D Math.Pow (Rate + 1, NPer);
+		        	totalFutureVal =3D FV + PV * totalRate;
+		        	geometricSum =3D (totalRate - 1) / Rate;
+		        }
+		        else if (Due =3D=3D DueDate.BegOfPeriod) {
+		        	double totalRate =3D Math.Pow (Rate + 1, NPer);
+		        	totalFutureVal =3D FV + PV * totalRate;
+				geometricSum =3D ((1 + Rate) * (totalRate - 1)) / Rate;       =20
+		        }
+		        return (totalFutureVal) / geometricSum;=20
+		}
+	=09
+		public static System.Double PPmt (System.Double Rate, System.Double =
Per, System.Double NPer, System.Double PV, =
[System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] System.Double FV, =
[System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] Microsoft.VisualBasic.DueDate =
Due)=20
+		{=20
+			if ((Per <=3D 0) || (Per >=3D (NPer + 1)))
+				throw new ArgumentException("Argument 'Per' is invalid.");
+			double interestPayment =3D IPmt (Rate, Per, NPer, PV, FV, Due);
+			double totalPayment =3D Pmt (Rate, NPer, PV, FV, Due);
+			return (totalPayment - interestPayment);
+		}
+	=09
+		public static System.Double PV (System.Double Rate, System.Double =
NPer, System.Double Pmt, [System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] System.Double FV, =
[System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] Microsoft.VisualBasic.DueDate =
Due)=20
+		{=20
+			Pmt =3D -Pmt;
+			FV =3D -FV;
+			double currentRate =3D 1;
+			double sum =3D 0;
+			for (int index =3D 1; index <=3D NPer; index++) {
+				currentRate *=3D (1 + Rate);
+				sum +=3D (Pmt / currentRate);
+			}
+		=09
+			if (Due =3D=3D DueDate.BegOfPeriod)
+				sum *=3D (1 + Rate);
+			return sum + FV / currentRate;   =20
+		}
+	=09
+		public static System.Double Rate (System.Double NPer, System.Double =
Pmt, System.Double PV, [System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] System.Double FV, =
[System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] Microsoft.VisualBasic.DueDate =
Due, [System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0.1)] System.Double Guess)
+		{=20
+			double updatedGuess, tmp, origFv, updatedFv;
+			double rateDiff =3D 0.0;
+			double fvDiff =3D 0.0;
+		=09
+			if (NPer < 0)
+				throw new ArgumentException ("Invalid argument 'NPer', must be =
greater then zero.");
+			origFv =3D -Financial.FV (Guess, NPer, Pmt, PV, Due) + FV;
+			updatedGuess =3D (origFv > 0) ? (Guess / 2) : (Guess * 2);
+			rateDiff =3D updatedGuess - Guess;
+			updatedFv =3D -Financial.FV (updatedGuess, NPer, Pmt, PV, Due) + =
FV;
+			fvDiff =3D updatedFv - origFv;
+			for (int i =3D 0; i < 20; i++) {
+				Guess +=3D (updatedGuess > Guess) ? -0.00001 : 0.00001;
+				origFv =3D -Financial.FV (Guess, NPer, Pmt, PV, Due) + FV;
+				rateDiff =3D updatedGuess - Guess;
+				fvDiff =3D updatedFv - origFv;
+				if (fvDiff =3D=3D 0)
+					throw new ArgumentException ("Division by zero.");
+				Guess =3D updatedGuess - (rateDiff * updatedFv / fvDiff);
+				origFv =3D -Financial.FV (Guess, NPer, Pmt, PV, Due) + FV;
+				if (Math.Abs (origFv) < 0.0000001)
+					return Guess;
+				tmp =3D Guess;
+				Guess =3D updatedGuess;
+				updatedGuess =3D tmp;
+				tmp =3D origFv;
+				origFv =3D updatedFv;
+				updatedFv =3D tmp;
+			}
+			double origFVAbs =3D Math.Abs (origFv);
+			double updatedFVAbs =3D Math.Abs (updatedFv);
+			if ((origFVAbs < 0.0000001) && (updatedFVAbs < 0.0000001))
+				return (origFVAbs < updatedFVAbs) ? Guess : updatedGuess;
+			else if (origFVAbs < 0.0000001)
+				return Guess;
+			else if (updatedFVAbs < 0.0000001)
+				return updatedGuess;
+			else
+				throw new ArgumentException ("Cannot calculate Rate.");=20
+		}
+	=09
+		public static System.Double SLN (System.Double Cost, System.Double =
Salvage, System.Double Life)
+		{=20
+			if (Life =3D=3D 0)
+            			throw new ArgumentException ("Argument 'Life' is =
invalid");
+        	=09
+        		return (Cost - Salvage) / Life;
+		}
+	=09
+		public static System.Double SYD (System.Double Cost, System.Double =
Salvage, System.Double Life, System.Double Period)=20
+		{=20
+			if (Period < 0)
+            			throw new ArgumentException ("Argument 'Period' is =
invalid");
+        		else if (Salvage < 0)
+            			throw new ArgumentException ("Argument 'Salvage' is =
invalid");
+        		else if (Period > Life)
+            			throw new ArgumentException ("Invalid argument, Period =
> Life");
+		       =20
+		        double depreciation =3D  (Cost - Salvage);
+		        double sumOfDigits =3D (Life + 1) * Life / 2;
+		        double currentPeriodPart =3D Life + 1 - Period ;=20
+		=09
+		        return depreciation * currentPeriodPart / sumOfDigits;
+		}
 		// Events
 	};
 }

------_=_NextPart_000_01C4506E.E73FF6D0--