/***************** Listing 3 *************************

            Cubic Spline Interpolation

   double cubic(image, x, y)
     float image[4][4], x, y;

   image: pointer to the four values of grid i.e.
          a 4 x 4 array ( image[4][4] )
   x    : sample coordinate
   y    : line coordinate

          (0,0)           (0,3)   
            *----*----*----*
            |    |    |    |
            *----*----*----*
            |    | o  |    |
            *----*----*----*
            |    |    |    | 
            *----*----*----*
          (3,0)           (3,3)

    If point "o" falls on upper left corner, then 
    return image(1,1). The point should never fall on 
    any of the other corners because the calling 
    program will ensure against this according to the
    filling sequence of the array image[4][4].

    Interpolation is first performed in the sample
    direction and then in the line direction, 
    using separability.

******************************************************
#include <stdio.h>

double cubic(image, x, y)
 float image[4][4], x, y;
{
  register i;
  float p, q;
  double I_x[4];
  double val = 0.0;

  double a1, a2, a3, a4;
  double b1, b2, b3, b4;

  p = x - (int) x;
  q = y - (int) y;
  if( (p == 0.0) && (q == 0.0) )
     return( (double) image[1][1] ); 

  a1 = p*(1-p)(1-p);      b1 = q*(1-q)(1-q);
  a2 = 1 - 2*p*p + p*p*p; b2 = 1 - 2*q*q + q*q*q;
  a3 = p*( 1 + p - p*p ); b3 = q*( 1 + q - q*q );
  a4 = p*p*(1-p);         b4 = q*q*(1-q);

  for(i=0 ; i < 4 ; i++)
    I_x[i] = -a1*image[i][0] + a2*image[i][1] +      \
                a3*image[i][2] - a4*image[i][3] ;

  val = -b1*I_x[0] + b2*I_x[1] + b3*I_x[2] - b4*I_x[3];

  return( val );
}
