Hi, I've implemented a very simple class for doing integration. This is nothing special, but because Iridium hasn't integration till now this might be helpful anyway.
// A very simple integration class
// Licensed under the terms of CC-GNU LGPL 2.1
// http://creativecommons.org/licenses/LGPL/2.1/
// coded by mailto:movgp0/AT/gmail.com
using System;
namespace MathNet.Numerics.Integration
{
/// <summary>
/// Methods for the integration of any function.
/// </summary>
public class IntegrateFunction
{
// TODO: Calculate epsilon (Error)
// TODO: Integration of multidimensional functions.
/// <summary>
/// The delegate prototype which a function to integrate must match.
/// </summary>
/// <param name="value">The argument of the function. </param>
/// <returns>The result of the function. </returns>
public delegate double IntegrateableFunction(double value);
/// <summary>Defines the algorithm that is used for integration. </summary>
public enum IntegrationMethod
{
/// <summary>
/// Calculates a straight line from start- to the endpoint of a given segment.
/// </summary>
ChordTrapezoid,
/// <summary>
/// Calculates a tangent in the point between the start- and entpoint of a given segment.
/// </summary>
TangentTrapezoid,
/// <summary>
/// Interpolation using a quadratic Polynom using a midpoint between the start- and endpoint.
/// </summary>
Simpson,
/// <summary>This one is not implemented yet.</summary>
Hermit
}
/// <summary>
/// Integrates any function that matches the IntegrateableFunction-Delegate
/// <see cref="IntegrateableFunction"/>
/// </summary>
/// <param name="Method">
/// The Algorithm that should get used for integration.
/// </param>
/// <param name="From">
/// The startpoint of the range in which the function
/// has to be integrated.
/// </param>
/// <param name="Steps">The number of steps used for integration. The higher this value the lower the error, but the longer the algorithm will run.</param>
/// <param name="To">
/// The endpoint of the range in which the function
/// has to be integrated.
/// </param>
/// <param name="Function">The function to integrate. </param>
/// <returns>The integrated Value of the function in the given range. </returns>
public static double IntegrateFunction(IntegrationMethod Method, double From, int Steps, double To, IntegrateableFunction Function)
{
double value = 0d;
switch(Method)
{
case IntegrationMethod.ChordTrapezoid:
double a, b;
for (b = From; b += StepWidth; b < To)
{
value += (b - a) / 2d * (Function(a) + Function(b));
a = b;
}
// calculate the remaining part
b = To;
value += (b - a) / 2d * (Function(a) + Function(b));
return value;
case IntegrationMethod.TangentTrapezoid:
double a, b;
for (b = From; b += StepWidth; b < To)
{
value += (b - a) * Function((a + b) / 2d);
a = b;
}
// calculate the remaining part
b = To;
value += (b - a) * Function((a + b) / 2d);
return value;
case IntegrationMethod.Simpson:
double a, b;
for (b = From; b += StepWidth; b < To)
{
value += (b - a) / 6d * (Function(a) + 4 * Function((a + b) / 2d) + Function(b));
a = b;
}
// calculate the remaining part
b = To;
value += (b - a) / 6d * (Function(a) + 4 * Function((a + b) / 2d) + Function(b));
return value;
case IntegrationMethod.Hermit:
throw new NotImplementedException();
break;
default:
throw new NotImplementedException();
break;
};
}
}
/// <summary>
/// Methods for the integration of a list of values.
/// </summary>
public class Integrate
{
/// <summary>
/// Declares the implemented integration methods.
/// </summary>
public enum IntegrationMethod {
/// <summary>
/// This algorithm just sums the values.
/// </summary>
Simple,
/// <summary>
/// This algorithm adds the mean between the last and the current value.
/// </summary>
Trapezium
};
/// <summary>
/// The value that is currently accumulated.
/// </summary>
private double value = 0d;
/// <summary>
/// The last value that got added for integration.
/// This is used by the Trapezium-based Integration-Algorithm.
/// </summary>
private double last = 0d;
/// <summary>
/// Declares if the current value is the first to be added for integration.
/// This is used by the Trapezium-based Integration-Algorithm.
/// </summary>
private bool isFirst = true;
/// <summary>
/// Stores the Integration method that was declared during the Construction of the object.
/// </summary>
private IntegrationMethod method;
/// <summary>
/// Returns the Integration Algorithm that is currently in use.
/// </summary>
public IntegrationMethod CurrentIntegrationMethod
{
get{
return method;
}
}
/// <summary>
/// Constructs a new Integration-Objects.
/// </summary>
/// <param name="method">The Integration-Algorithm to use.</param>
public Integrate(IntegrationMethod method)
{
this.method = method;
}
/// <summary>
/// Integrates a new value to the stored value.
/// The width of the segment is calculated to be 1.
/// </summary>
/// <param name="value">The value that should get added.</param>
public void AddNext(double value)
{
AddNext(value, 1d);
}
/// <summary>
/// Integrates a new value to the stored value.
/// </summary>
/// <param name="value">The value that should get added.</param>
/// <param name="width">The width of the current step.</param>
public void AddNext(double value, double width)
{
switch(this.method)
{
case IntegrationMethod.Simple:
this.value += value;
break;
case IntegrationMethod.Trapezium:
if(isFirst)
{
this.last = value;
isFirst = false;
return;
}
this.value += (last + value)/2d * width;
break;
default: throw new NotImplementedException();
break;
}
}
/// <summary>
/// The value that is current accumulated during integration.
/// </summary>
/// <returns>The current Value.</returns>
public double Value()
{
return value;
}
// TODO: calculate epsilon (rounding error)
}
}