12,828,983 members (41,452 online)
alternative version

#### Stats

19K views
15 bookmarked
Posted 19 Jul 2010

# Using Nested Lambda Functions to Implement Numerical Algorithms

, 19 Jul 2010 CPOL
 Rate this:
For numerical computations, coding with lambda functions can substitute for the want of nested methods in C#.

## Introduction

Some twenty-seven years ago I had occasion to write some numerical methods in Pascal. Many algorithms used nested functions. This article describes how I successfully migrated many of these functions to C# 4.0 using nested lambda functions.

I was designing a yacht and the problem was to produce not only a fair surface but to calculate displacement, centre of buoyancy and wetted surface area, amongst other data arising from the hull surface definition. At the time there were no CAD programs available that could run on my BBC computer. It boasted an 8 bit 6502 processor, running at 2 MHz and 32 kbytes of RAM. In practice, at that time, hull lines were plotted full scale and smoothing was accomplished with a flexible wooden batten or spline. Measurements were taken from lofted lines or scale drawings and Simpson’s rule was used, with hand calculations, to determine displacement, centre of buoyancy and other data arising from the hull shape.

At that time, there was a Pascal compiler for the BBC computer. I was also able to program a function that specified the hull. Then, by using numerical computations, I could generate the required hull data. Moreover, I was able to iteratively modify the parameters that specified the hull and besides other desirable capabilities, optimize wetted surface area with a required heeling moment. Admittedly the graphics were absolutely rudimentary but by using general conics as fairing curves, a fair hull could be obtained.

The 12 m yacht, Apollonius (note those conics), a cruiser racer, was built. This yacht has successfully completed many blue water ocean races. These days I find more pleasure in cruising about the islands of Bass Strait, a turbulent stretch of water between Tasmania and the Australian mainland.

## Background

Let’s leave this digression. Last week, when clearing out some old cardboard folders, I came across some of my old Pascal code, just readable, produced on a long extinct dot matrix printer. It went something like this:

```program boatHull(input, output);
type posint = 1..maxint;
{Much code omitted - for brevity}

function integral(function f(x : real) : real; a, b : real; n : posint) : real;
type
{types} ;
var
{vars};
begin
{chosen algorithm}
end {integral};

function doubleIntegral (function f(x, y : real) : real;
function g(y : real): real; function h(y : real): real; a,
b : real; m, n: posint ) : real;
{end of parameters}
function area(y: real): real; {
first nested function; note g, h, and m are in scope}

function argument(x : real) : real; {
second nested function; note y is in scope}
begin {argument}
argument := f(x,y)
end {argument};

begin {area}
area := integral(argument, g(y), h(y), m)
end {area};

begin {doubleIntegral}
doubleIntegral:= integral(area, a, b, n)
end {doubleIntegral};

begin {demo}
{input, output code goes here}
end. {boatHull}```

We can see that the scopes of the functions `integral` and `doubleIntegral` make them available to the program boatHull. However, the function `doubleIntegral` is able to call the function `integral`. The function area is nested within `doubleIntegral` and is only available to `doubleIntegral`. Similarly the function argument is only available to the function area.

Encapsulation is the compelling reason for using nested functions in the Pascal function `doubleIntegral`. The nested function area has no significance outside `doubleIntegral` and neither does the function argument have any reason to exist outside the area function.

## Moving to C# 4.0

In my retirement I design and implement online SQL database applications for educational environments. I use C# for code-behind in .aspx pages. Naturally I wondered how, using coding principles similar to the above, a double integral could be achieved using nested functions.

In C#, Pascal functions correspond to methods. However, a direct translation of the code is not possible as C#, although supporting nested classes, does not support nested methods.However, lambda functions, relatively new to C#, may be nested. So, I downloaded Visual C# 2010 Express, a consumer of .NET 4.0, to have a go.

At this stage, if readers are unfamiliar with lambda notation and delegates, then they should consult an appropriate reference, of which there are many.

First, after preliminaries, some delegates:

```using System;
using System.Linq;

namespace Computationals
{
// Delegates

delegate double Function(double x);
delegate double Functionxy(double x, double y);
delegate double Integral(Function f, double a, double b, int n);
// for integration of function f over n subintervals from a to b

public class LambdaNumericals
{```

Next, some integration methods: Firstly, Simpson’s Method

```static Integral SimpInt()
{
// Simpson's rule
// integration of function f, over n (even) subintervals in the interval [a,b]
Integral integral = (f, a, b, n) =>
{
// n, not even, throw exception code should go here
double sum = 0;
double h = (b - a) / n;
for (int i = 0; i < n; i = i + 2)
sum = sum + (f(a + i * h) + 4 * f(a + (i + 1) * h) + f(a + (i + 2) * h)) * h / 3;
return sum;
};
return integral;
}```

Secondly, the Gaussian-Legendre 4 point Algorithm

``` static Integral GaussInt()
{
// 4-point Gaussian rule integration of the function f,
// over n subintervals in the interval (a,b)
Integral integral = (f, a, b, n) =>
{
double[] weight = new double[4];
weight[2] = 0.652145154862546;
weight[1] = weight[2];
weight[3] = 0.347854845137454;
weight[0] = weight[3];

double[] point = new double[4];
point[3] = 0.861136311594053;
point[0] = -point[3];
point[2] = 0.339981043584856;
point[1] = -point[2];

double sum = 0;
double h = (b - a) / n;

double xr, xl, m, c, s;

for (int i = 0; i < n; i++)
{
s = 0;

xl = a + i * h;
xr = xl + h;
m = (xr - xl) / 2;
c = (xr + xl) / 2;

for (int j = 0; j < 4; j++)
s = s + weight[j] * f(m * point[j] + c) * m;

sum = sum + s;
}
return sum;
};
return integral;
}```

Now, we can use the above in:

``` // Double integration using nested lambda functions
// Inner integral dx, from x=g(y) to x=h(y), over m subintervals, using algorithm inInt
// Outer integral dy, from y=a to y=b, over n subintervals, using algorithm outInt

static double dubInt(Functionxy fxy, Function g, Function h, double a, double b,
int m, int n, Integral inInt, Integral outInt)
{
return outInt((double y) => inInt((double x) => fxy(x, y), g(y), h(y), m), a, b, n);
}```

inInt and outInt are parameters accepting integration functions, SimpInt() or GaussInt().
The Pascal doubleIntegral function becomes outInt(area, a ,b, n).
The area function in the Pascal code corresponds to the snippet (double y) => inInt(argument, g(y), h(y), m).
Finally the argument function corresponds to (double x) => fxy(x, y).

To test our code we can define the following test functions to be used as parameters:

```public static double p(double x, double y)
{
return x * y;
}

public static double f1(double x)
{
return x;
}

public static double f2(double x)
{
return 2 * x;
}

public static double sine(double x)
{
return Math.Sin(x);
}```

We can then invoke our integration methods using:

```public static void Main()
{
Integral integrate1, integrate2;

integrate1 = SimpInt();
Console.WriteLine(integrate1(sine, 0, Math.PI, 60));
// result 2.00000008353986

integrate2 = GaussInt();
Console.WriteLine(integrate2(sine, 0, Math.PI, 15));
// result 2

Console.WriteLine(integrate2(Math.Sin, 0, Math.PI, 15));
// result 2

// analytically, exactly 2 for the above integrals –
// note the superior convergence of Gauss 4-point algorithm

// Now to test our double integration functtion
Console.WriteLine(dubInt(p, f1, f2, 1, 2, 4, 4, integrate1, integrate2));
// result 5.625
// analytically 5 5/8
}
}```

## Point of Interest

Following on, using similar strategies, I have applied lambda methodology to differentiation, double differentiation, curve length, partial derivatives, surface area and curvature. Code with examples is included is in the downloads.

The techniques demonstrated can easily be extended to integration in polar coordinates, triple integrals, and integration in cylindrical and spherical coordinates. Parametric functions, splines and surfaces and differential equations are possible candidates for lambda functions. No doubt this is only the tip of the iceberg.

## Limitations on the Application of Code

In conclusion, I must emphasise that this article concerns the techniques of lambda and nested lambda functions applied to numerical computations. The actual numerical algorithms, in a library context would, of course, contain error specifications. Also, the best values for some constants are machine dependant. I make no suggestions on the suitability of the above for particular applications.

Nevertheless, once a programmer is comfortable with the syntax of lambda functions, they potentially can provide a remarkably succinct and productive entry into non trivial, numerical computations.

## About the Author

 Australia
I am a retired Physics and Mathematics Teacher. For stimulation I now design SQL databases for online educational administration settings.
Most times I am relaxing at home but I have regular forays, lasting a couple of weeks, into Bass Strait on my yacht. I designed and built my timber composite 12m yacht after writing a CAD program, when none existed, in 1983.

## You may also be interested in...

 Pro Pro

## Comments and Discussions

 First Prev Next
 My vote of 5 manoj kumar choubey27-Mar-12 5:15 manoj kumar choubey 27-Mar-12 5:15
 Nice one bilo8128-Nov-10 5:45 bilo81 28-Nov-10 5:45
 My vote of 5 mb1820-Jul-10 11:18 mb18 20-Jul-10 11:18
 My vote of 5 HoyaSaxa9319-Jul-10 12:30 HoyaSaxa93 19-Jul-10 12:30
 My vote of 5 defconhaya19-Jul-10 12:16 defconhaya 19-Jul-10 12:16
 Last Visit: 31-Dec-99 19:00     Last Update: 29-Mar-17 12:55 Refresh 1

General    News    Suggestion    Question    Bug    Answer    Joke    Praise    Rant    Admin

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.