#include <stdio.h>
#include <assert.h>
#include <math.h>

#define MAX_STRING		72  /* Maximum length of a documentation string */
#define NUM_AVAILABLE_ROWS	36
#define NUM_AVAILABLE_COLS	78

typedef char doc_string[MAX_STRING];

void
write_star_in_column(int column)
{
  if ((column < 0) || (column >= NUM_AVAILABLE_COLS))
    putchar('\n');
  else printf("%*c\n", column, '*');
}

void
plot(double (*fn_to_plot)(double),
     doc_string documentation,
     double lowest_x, double highest_x,
     double lowest_y, double highest_y)
{
  double x_value;
  double y_value;
  int row_to_plot;
  double x_increment_per_row;
  double y_increment_per_col;

  assert(lowest_x < highest_x);
  assert(lowest_y < highest_y);
  printf("Plot of %s for %f <= x <= %f and %f <= y <= %f\n\n",
         documentation, lowest_x, highest_x, lowest_y, highest_y); 
  x_increment_per_row = (highest_x - lowest_x) / (NUM_AVAILABLE_ROWS - 1);
  y_increment_per_col = (highest_y - lowest_y) / (NUM_AVAILABLE_COLS - 1);
  for (row_to_plot = 0; row_to_plot < NUM_AVAILABLE_ROWS; row_to_plot++) {
    x_value = lowest_x + (((double) row_to_plot) * x_increment_per_row);
    y_value = fn_to_plot(x_value);
    write_star_in_column((int) floor((y_value - lowest_y) / y_increment_per_col) + 1);
  }
  putchar('\n');
}


/* Functions to be plotted: */

#define PI	3.14159265358979

double
f1(double x)
{
  return(exp(-x) * sin(2 * PI * x));
}

double
f2(double x)
{
  return(sin(10 * x));
}

double
identity(double x)
{
  return(x);
}

main()
{
  plot(f1, "f(x) = exp(-x)sin(2 pi x)", 0.0, 2.0, -0.5, 1.5);
  plot(f2, "f(x) = sin(10x)", 0.0, 2.0, -2.0, 2.0);
  plot(identity, "f(x) = x", -1.0, 1.0, -1.0, 1.0);
}

