/* horner.c
** Mth 351 Summer 2001
** Bent Petersen
**
** Usage:  horner datafile abscissae
**
** Only minimal error checking is done.
**
** Typical:  horner poly.dat 3.40 4.21 5.98
** where the numbers are the evaluation points (abscissae).
**
** Format of the data file
**   degree n
**   coefficient of term of degree n
**   coefficient of term of degree n-1
**   ...
**   coefficient of term of degree 0
**
** The numbers can be all on one line, or several lines,
** as long as they are separated by white space. Blank
** lines are ignored.
**
** Microsoft C/C++    cl horner.c
** GNU Project GCC    gcc -i horner.c -o horner
*/

#include <stdio.h>
#include <math.h>    /* atof() */
#include <stdlib.h>  /* exit() */

typedef struct Poly { 
  int deg; 
  double * coef; } POLY;

POLY getpoly( char * filename );
void showpoly( POLY poly );
double horner( int degree, double * coefs, double abscissa );

/********************************/
int main( int argc, char ** argv ) {

POLY       poly;
int        k;
double     temp; 

if ( argc < 3 )
    printf("\nUsage: %s datafile abscissae\n", argv[0] );
else {
  poly = getpoly( argv[1] );
  showpoly( poly );

  for ( k=2; k < argc; k++ ) {
    temp = atof(argv[k]);
    printf( "\nThe value at %+18.8f is %+15.8e",temp,
          horner( poly.deg, poly.coef, temp ) );
    }
  printf("\n");
  }   
return 0; 
}

/*****************************/
POLY getpoly( char * filename ) {

POLY              poly;
FILE              *fileptr;
int               k;

if ( (fileptr = fopen( filename, "r" )) == NULL ) {
  printf( "\nData file not found." );
  exit( 1 );
  }                 

fscanf( fileptr, "%d", &poly.deg );
if ( poly.deg < 1 ) {
  printf( "\nBad degree: %d", poly.deg ); 
  exit( 1 );
  }

poly.coef = (double *)malloc( (size_t)((1+poly.deg)*sizeof(double)) );
if ( poly.coef == NULL ) {
  printf( "\nUnable to allocate memory." );
  exit( 1 );
}

for ( k=0 ; k<=poly.deg ; k++ )
  fscanf( fileptr, "%lf", &poly.coef[poly.deg-k] );
  
fclose( fileptr );
return poly;
}

/************************/
void showpoly( POLY poly ) {
  
  int        k;

  printf("\nDegree: %d", poly.deg);

  for (k=poly.deg; k>=0; k--)
    printf("\nCoefficient of term of degree %5d:%4s%+19.12e", 
          k, " ",poly.coef[k] );
  printf("\n");
}

/**********************************************************/
double horner( int degree, double * coefs, double abscissa ) {

double   x;
int      k;

x = coefs[degree];

for ( k=degree-1; k>=0; k-- )
  x = x * abscissa + coefs[k];

return x;
}
/*** END ***/

