Michael G Schwern


Tie::Math - Hashes which represent mathematical functions.


  use Tie::Math;
  tie %fibo, 'Tie::Math', sub { f(n) = f(n-1) + f(n-2) },
                          sub { f(0) = 0;  f(1) = 1 };

  # Calculate and print the fifth fibonacci number
  print $fibo{5};


Defines hashes which represent mathematical functions, such as the fibonacci sequence, factorials, etc... Functions can be expressed in a manner which a math or physics student might find a bit more familiar. It also automatically employs memoization.

Multi-variable functions are supported. f() is simply passed two variables (f(X,Y) for instance) and the hash is accessed in the same way ($func{3,-4}).

  tie %func, 'Tie::Math', \&function;
  tie %func, 'Tie::Math', \&function, \&initialization;

&function contains the definition of the mathematical function. Use the f() subroutine and N index provided. So to do a simple exponential function represented by "f(N) = N**2":

    tie %exp, 'Tie::Math', sub { f(N) = N**2 };

&initialization contains any special cases of the function you need to define. In the fibonacci example in the SYNOPSIS you have to define f(0) = 1 and f(1) = 1;

    tie %fibo, 'Tie::Math', sub { f(N) = f(N-1) + f(N-2) },
                            sub { f(0) = 1;  f(1) = 1; };

The &initializaion routine is optional.

Each calculation is "memoized" so that for each element of the array the calculation is only done once.

While the variable N is given by default, A through Z are all available. Simply import them explicitly:

    # Don't forget to import f()
    use Tie::Math qw(f X);

There's no real difference which variable you use, its just there for your preference. (NOTE: I had to use captial letters to avoid clashing with the y// operator)


Display a polynomial equation in a table.

    use Tie::Math;

    tie %poly, 'Tie::Math', sub { f(N) = N**2 + 2*N + 1 };

    print "  f(N) = N**2 + 2*N + 1 where N == -3 to 3\n";
    print "\t x \t poly\n";
    for my $x (-3..3) {
        printf "\t % 2d \t % 3d\n", $x, $poly{$x};

This should display:

  f(N) = N**2 + 2*N + 1 where N == -3 to 3
         x       poly
         -3        4
         -2        1
         -1        0
          0        1
          1        4
          2        9
          3       16

How about Pascal's Triangle!

    use Tie::Math qw(f X Y);

    my %pascal;
    tie %pascal, 'Tie::Math', sub { 
                                  if( X <= Y and Y > 0 and X > 0 ) {
                                      f(X,Y) = f(X-1,Y-1) + f(X,Y-1);
                                  else {
                                      f(X,Y) = 0;
                              sub { 
                                  f(1,1) = 1;  
                                  f(1,2) = 1;  
                                  f(2,2) = 1; 

    $height = 5;
    for my $y (1..$height) {
        print " " x ($height - $y);
        for my $x (1..$y) {
            print $pascal{$x,$y};
        print "\n";

This should produce a nice neat little triangle:

       1 1
      1 2 1
     1 3 3 1
    1 4 6 4 1


Memoization is automatically employed so no f(X) is calculated twice. This radically increases efficiency in many cases.


Certain functions cannot be properly expressed. For example, the equation defining a circle, f(X) = sqrt(1 - X**2), has two solutions for each f(X).

There's some horrific hacks in here to make up for the limitations of the current lvalue subroutine implementation. Namely missing wantlvalue().

This code use the experimental lvalue subroutine feature which will hopefully change in the future.

The interface is currently very alpha and will probably change in the near future.

This module BREAKS 5.6.0's DEBUGGER! Neat, eh?

This module uses the old multidimensional hash emulation from the Perl 4 days. While this isn't currently a bad thing, it may eventually be destined for the junk heap.


Michael G Schwern <schwern@pobox.com>


Easier ways to set boundries ie. "f(X,Y) = X + Y where X > 0 and Y > 1"

1 POD Error

The following errors were encountered while parsing the POD:

Around line 208:

You forgot a '=back' before '=head1'