The following PHP source code is intellectual property of Jan Olligs, © 2003. You are invited to use it for your personal, non-commercial purposes in any way you like, provided that you mention the author (Jan Olligs), the copyright and the author's e-mail address (Jan_Olligs@msn.com) or a hypertext reference to send an e-mail to the address mentioned above and that the right to use the code freely for non-commercial purposes is preserved.
If you would like to use any of the code below to any different than the above mentioned conditions, please contact the author.

File parser.php:
<?php
   define("NOERROR",      0);
   define("ANYERROR",     1);
   define("DIVBYZERO",    2);
   define("OUTOFRANGE",   3);
   define("NOSUCHFUNC",   4);
   define("PARSEERR",     5);

   function errorType($errNum) {
      switch ($errNum) {
         case (NOERROR):
            return 'No error detected.';
         case (DIVBYZERO):
            return 'Division by zero.';
         case (OUTOFRANGE):
            return 'Out of range.';
         case (NOSUCHFUNC):
            return 'No such function.';
         case (PARSEERR):
            return 'Parse error.';
         case (ANYERROR):
         default:
            return 'Unknown error.';
      }
   }

   define("MAXSIZE",  100);       # maximal number of float digits

   $unaryOperators  = array('abs',   'sqrt',  'exp',   'ln',    'lg',    'ld',
                            'sin',   'cos',   'tan',   'cot',
                            'asin',  'acos',  'atan',  'acot',
                            'sinh',  'cosh',  'tanh',  'coth',
                            'asinh', 'acosh', 'atanh', 'acoth',
                            'floor', 'ceil',  'round', 'frac',  'int');

   $binaryOperators = array(array('^', 'root'),
                            array('%', 'mod', 'div'),
                            array('*', '/'),
                            array('+', '-'));

   $constants       = array('pi', 'e');
   $constValues     = array('pi' => M_PI,
                            'e'  => M_E);

   $openingParens   = array('(', '[', '{');

   $closingParens   = array(')', ']', '}');
   
   $oneCharOps      = array('+', '-', '*', '/', '%', '^');

   function applyUnaryOp($op, $value, &$error) {
      $error = NOERROR;
      switch ($op) {
         case 'abs':
            return abs($value);
         case 'sqrt':
            if ($value < 0) {
               $error = OUTOFRANGE;
               break;
            }
            return sqrt($value);
         case 'exp':
            if ($value > MAXSIZE * log(10)) { $error = OUTOFRANGE; break; }
            return exp($value);
         case 'ln':
            if ($value <= 0) {
               $error = OUTOFRANGE;
               break;
            } else {
               return log($value);
            }
         case 'lg':
            if ($value <= 0) {
               $error = OUTOFRANGE;
               break;
            } else {
               return log10($value);
            }
         case 'ld':
            if ($value <= 0) {
               $error = OUTOFRANGE;
               break;
            } else {
               return log($value, 2);
            }

         case 'sin':
            return sin($value);
         case 'cos':
            return cos($value);
         case 'tan':
            if (cos($value) == 0) {
               $error = DIVBYZERO;
               break;
            } else {
               return tan($value);
            }
         case 'cot':
            if (sin($value) == 0) {
               $error = DIVBYZERO;
               break;
            } else {
               return (cos($value)/sin($value));
            }

         case 'asin':
            if (abs($value) > 1) {
               $error = OUTOFRANGE;
               break;
            } else {
               return asin($value);
            }
         case 'acos':
            if (abs($value) > 1) {
               $error = OUTOFRANGE;
               break;
            } else {
               return acos($value);
            }
         case 'atan':
            return atan($value);
         case 'acot':
            if ($value == 0) {
               return 0;
            } else {
               return atan(1/$value);
            }

         case 'sinh':
            return sinh($value);
         case 'cosh':
            return cosh($value);
         case 'tanh':
            return tanh($value);
         case 'coth':
            if (tanh($value) == 0) {
               $error = DIVBYZERO;
               break;
            } else {
               return (1/tanh($value));
            }

         case 'asinh':
            return asinh($value);
         case 'acosh':
            if ($value < 1) {
               $error = OUTOFRANGE;
               break;
            } else {
               return acosh($value);
            }
         case 'atanh':
            if (abs($value) > 1) {
               $error = OUTOFRANGE;
               break;
            } else {
               return atanh($value);
            }
         case 'acoth':
            if ($value == 0) {
               return 0;
            } else {
               return atanh(1/$value);
            }

         case 'floor':
            return floor($value);
         case 'ceil':
            return ceil($value);
         case 'round':
            return round($value);
         case 'frac':
            return abs($value) - floor(abs($value));
         case 'int':
            if ($value > 0) {
               return floor($value);
            } else {
               return ceil($value);
            }
         default:
            $error = NOSUCHFUNC;
      }
   }

   function applyBinaryOp($op, $value1, $value2, &$error) {
      $error = NOERROR;
      switch ($op) {
         case '+':
            if (!($value1 == 0 || $value2 == 0) && $value1 / $value2 > 0) {
               if (abs(log10(abs($value1)) - log10(abs($value2))) < 0.01) {
                  if (2 * log10(abs($value1)) > MAXSIZE) {
                     $error = OUTOFRANGE;
                     break;
                  }
               }
            }
            return $value1 + $value2;
         case '-':
            $value2 = -$value2;
            if (!($value1 == 0 || $value2 == 0) && $value1 / $value2 > 0) {
               if (abs(log10(abs($value1)) - log10(abs($value2))) < 0.01) {
                  if (2 * log10(abs($value1)) > MAXSIZE) {
                     $error = OUTOFRANGE;
                     break;
                  }
               }
            }
            return $value1 + $value2;

         case '*':
            if (!($value1 == 0 || $value2 == 0)) {
               if (log10(abs($value1)) + log10(abs($value2)) > MAXSIZE) {
                  $error = OUTOFRANGE;
                  break;
               }
            }
            return $value1 * $value2;
         case '/':
            if ($value2 == 0) {
               $error = DIVBYZERO;
               break;
            }
            $value2 = 1 / $value2;
            if (!($value1 == 0 || $value2 == 0)) {
               if (log10(abs($value1)) + log10(abs($value2)) > MAXSIZE) {
                  $error = OUTOFRANGE;
                  break;
               }
            }
            return $value1 * $value2;

         case '%':
            if        ($value2 == 0) {
               $error = DIVBYZERO;
               break;
            } else if ($value2 < 0) {
               $error = OUTOFRANGE;
               break;
            } else {
               return fmod($value1, $value2);
            }
         case 'mod':
            if        ($value2 == 0) {
               $error = DIVBYZERO;
               break;
            } else if ($value2 < 0) {
               $error = OUTOFRANGE;
               break;
            } else {
               return fmod($value1, $value2);
            }
         case 'div':
            if ($value2 == 0) {
               $error = DIVBYZERO;
               break;
            } else {
               $i = 0;
               if ($value1 / $value2 < 0) {
                  while (abs($value1) > abs($value2)) { $value1 += $value2; --$i;}
               } else {
                  while (abs($value1) > abs($value2)) { $value1 -= $value2; ++$i;}
               }
               return $i;
            }

         case '^':
            if (log10(abs($value1)) * $value2 > MAXSIZE) {
               $error = OUTOFRANGE;
               break;
            } else if ($value1 < 0 && $value2 != round($value2)) {
               $error = OUTOFRANGE;
               break;
            } else {
               if ($value2 == 1) { return $value1; }
               if ($value2 == 0) { return 1; }
               if ($value2 < 0 && $value1 == 0) { return DIVBYZERO; }
               return pow($value1, $value2);
            }
         case 'root':
            if ($value1 == 0) {
               $error = DIVBYZERO;
               break;
            }
            $value = $value2;
            $value2 = 1 / $value1;
            $value1 = $value;
            if (log10(abs($value1)) * $value2 > MAXSIZE) {
               $error = OUTOFRANGE;
               break;
            } else if ($value1 < 0 && $value2 != round($value2)) {
               $error = OUTOFRANGE;
               break;
            } else {
               if ($value2 == 1) { return $value1; }
               if ($value2 == 0) { return 1; }
               if ($value2 < 0 && $value1 == 0) { return DIVBYZERO; }
               return pow($value1, $value2);
            }

         default:
            $error = NOSUCHFUNC;
      }
   }

   function matchingParens($term) {
      global $openingParens, $closingParens;
      $parens = '';
      for ($i = 0; $i < strlen($term); ++$i) {
         $j = $term{$i};
         if (in_array($j, $openingParens)) {
            $parens .= $j;
         }
         if (in_array($j, $closingParens)) {
            if (!($parens)) {
               return $i;
            }
            if (   array_search($parens{strlen($parens) - 1}, $openingParens)
                != array_search($j, $closingParens)) {
               return $i;
            }
            $parens = substr($parens, 0, strlen($parens) - 1);
         }
      }
      if ($parens) {
         return strlen($term);
      } else {
         return -1;
      }
   }

   function addTimes($term, $variables) {
      global $openingParens, $closingParens;
      foreach ($variables as $var) {
         for ($i = 0; $i < strlen($term) - strlen($var); ++$i) {
            $j = $term{$i};
            $k = substr($term, $i, strlen($var));
            if ($k == $var) {
               $i += strlen($var);
               $j = $term{$i};
               if (in_array($j, $openingParens) || ($j >= '0' && $j <= '9')) {
                  $term = substr($term, 0, $i) . '*' . substr($term, $i);
                  ++$i;
               }
            } else if (in_array($j, $closingParens) || ($j >= '0' && $j <= '9')) {
               $k = substr($term, ++$i, strlen($var));
               if ($k == $var) {
                  $term = substr($term, 0, $i) . '*' . substr($term, $i);
                  $i += strlen($var);
               }
            }
         }
      }
      return $term;
   }
   
   function splitTerm($term) {
      global $openingParens, $closingParens, $oneCharOps;
      $result = array();
      $preProc = preg_split('/\s+/', $term);
      foreach ($preProc as $value) {
         $accum = '';
         for ($i = 0; $i < strlen($value); ++$i) {
            $j = $value{$i};
            if        (in_array($j, $openingParens)) {
               $accum .= $j;
               $result[] = $accum;
               $accum = '';
            } else if (in_array($j, $closingParens)) {
               $result[] = $accum;
               $result[] = $j;
               $accum = '';
            } else if (in_array($j, $oneCharOps)) {
               $result[] = $accum;
               $result[] = $j;
               $accum = '';
            } else {
               $accum .= $j;
            }
         }
         if ($accum) { $result[] = $accum; }
      }
      $result = array_values($result);
      for ($i = 0; $i < count($result); ++$i) {
         if (!($result[$i])) {
            unset($result[$i]);
         }
      }
      $result = array_values($result);
      if ($result[0] == '-') { array_unshift($result, '0'); }
      $result = array_values($result);
      return $result;
   }
   
   function removeUnneccessaryParens($atoms) {
      global $openingParens, $closingParens;
      for ($i = 0; $i < count($atoms); ++$i) {
         settype($atoms[$i], "string");
      }
      if (in_array($atoms[0], $openingParens)) {
         $numParens = 1;
         $first = true;
         for ($i = 1; ($i < count($atoms)) && $first; ++$i) {
            if        (in_array($atoms[$i], $closingParens)) {
               --$numParens;
            } else if (in_array($atoms[$i], $openingParens)) {
               ++$numParens;
            }
            if ($numParens == 0 && ($i < count($atoms))) { $first = false; }
         }
         if ($first) {
            unset($atoms[count($atoms) - 1]);
            unset($atoms[0]);
            $atoms = array_values($atoms);
         }
      }
      for ($i = 0; $i < count($atoms) - 2; ++$i) {
         if (in_array($atoms[$i], $openingParens) &&
             in_array($atoms[$i + 2], $closingParens)) {
            unset($atoms[$i + 2]);
            unset($atoms[$i]);
            $i -= 2;
            $atoms = array_values($atoms);
         }
      }
      return $atoms;
   }

   function substitute($atoms, $varValues) {
      for ($i = 0; $i < count($atoms); ++$i) {
         $nucleon = $atoms[$i];
         if (array_key_exists($nucleon, $varValues)) {
            $atoms[$i] = $varValues[$nucleon];
         }
      }
      return $atoms;
   }

   function evalPart($atoms, $from, $to, &$errNo) {
      global $binaryOperators;
      $errNo = NOERROR;
      $useful = array_slice($atoms, $from, $to - $from + 1);
      if ($useful[0] == '-') { array_unshift($useful, '0'); }
      $useful = array_values($useful);
      while (count($useful) > 1) {
         $found = false;
         for ($op = 0; $op < count($binaryOperators); ++$op) {
            for ($i = 1; $i < count($useful) - 1; ++$i) {
               if (in_array($useful[$i], $binaryOperators[$op])) {
                  $found = true;
                  break;
               }
            }
            if ($found) {
               break;
            }
         }
         if (!$found) {
            $errNo = PARSEERR;
            return;
         }
         $value = applyBinaryOp($useful[$i], $useful[$i - 1],
                                $useful[$i + 1], $errNo);
         if ($errNo != NOERROR) {
            return;
         }
         $useful[$i] = $value;
         unset($useful[$i - 1]);
         unset($useful[$i + 1]);
         $useful = array_values($useful);
      }
      $tmp = array_values(
                array_merge(
                   array_merge(
                      array_slice($atoms, 0, $from),
                      $useful
                   ),
                   array_slice($atoms, $to + 1)
                )
             );
      return $tmp;
   }

   function evaluate($atoms, &$errNo) {
      global $openingParens, $closingParens, $unaryOperators;
      $errNo = NOERROR;
      while (count($atoms) > 1) {
         $i = 0;
         while ($i < count($atoms)) {
            $atoms = removeUnneccessaryParens($atoms);
            for ($i = 0; $i < count($atoms); ++$i) {
               $j = $atoms[$i];
               $j = $j{strlen($j) - 1};
               if      (in_array($j, $openingParens)) { $open  = $i; }
               else if (in_array($j, $closingParens)) { $close = $i; break; }
            }
            if ($close - $open <= 2) {
               break;
            }
            if ($i < count($atoms)) {
               $atoms = evalPart($atoms, $open + 1, $close - 1, $errNo);
               if ($errNo != NOERROR) { return; }
               $i = 0;
            }
         }
         $i = 0;
         while ($i < count($atoms) - 2) {
            $atoms = removeUnneccessaryParens($atoms);
            for ($i = 0; $i < count($atoms) - 2; ++$i) {
               $j = $atoms[$i];
               $j = $j{strlen($j) - 1};
               if (in_array($j, $openingParens)) {
                  if (in_array($atoms[$i + 2], $closingParens)) {
                     break;
                  }
               }
            }
            if ($i < count($atoms) - 2) {
               $result = applyUnaryOp(
                            substr(
                               $atoms[$i],
                               0,
                               strlen($atoms[$i]) - 1
                            ),
                            $atoms[$i + 1],
                            $errNo
                         );
               if ($errNo != NOERROR) { return; }
               $atoms[$i + 1] = $result;
               unset($atoms[$i + 2]);
               unset($atoms[$i]);
               $atoms = array_values($atoms);
               $i = 0;
            } else {
               $i += 2;
            }
         }
         $done = true;
         for ($i = 0; $i < count($atoms); ++$i) {
            if (in_array($atoms[$i], $closingParens)) {
               $done = false;
               break;
            }
         }
         if ($done) {
            break;
         }
      }
      if (count($atoms) > 1) {
         $atoms = evalPart($atoms, 0, count($atoms) - 1, $errNo);
         if ($errNo != 0) { return; }
      }
      $atoms = array_values($atoms);
      return $atoms[0];
   }
?>


File graphics.php:
<?php
   # standard colors
   $colors = array(
                array('Black',             0,   0,   0),
                array('White',           255, 255, 255),
                array('Grey',            200, 200, 200),
                array('Blue',              0,   0, 160),
                array('Light Blue',        0,   0, 255),
                array('Bordeaux',        160,   0,   0),
                array('Red',             255,   0,   0),
                array('Green',             0, 160,   0),
                array('Light Green',       0, 255,   0),
                array('Yellow',          160, 160,   0),
                array('Light Yellow',    255, 255,   0),
                array('Cyan',              0, 160, 160),
                array('Light Cyan',        0, 255, 255),
                array('Mangenta',        160,   0, 160),
                array('Light Mangenta',  255,   0, 255)
             );

   # stardard values
   define('stdFunc',   'cos(a*x)*sin(x)'); # standard function term

   define('stdWidth',  640); # standard picture width
   define('stdHeight', 480); # standard picture height

   define('stdXmin',   '-2pi');
   define('stdXmax',   '2pi');
   define('stdXgrid',  'pi/4');

   define('stdYmin',   '-1.5');
   define('stdYmax',   '1.5');
   define('stdYgrid',  '0.5');

   define('stdStep',   0.025);

   define('stdAmin',   '1');
   define('stdAmax',   '3');
   define('stdAstep',  '2');

   define('stdBGcol',  1); # standard background color
   define('stdPLcol',  5); # standard plot color
   define('stdAXcol',  0); # standard axis color
   define('stdGRcol',  2); # standard grid color

   define('stdSmin',   '0');
   define('stdSmax',   'pi');
   define('stdSHcol',  2); # standard shading color
   define('stdShade', 'false');

   define('stdAutoStep', 'true');
   define('HGHTUPTHRES', 1.5);
   define('HGHTLWTHRES', 0.6);

   function initPlot($image, $width, $height, $xmin, $xmax, $xgrid, $ymin, $ymax, $ygrid, $back, $axes, $grid) {
     # graph background
     ImageFilledRectangle(
        $image,
        0,
        0,
        $width - 1,
        $height - 1,
        $back
     );

     # grid lines
     # x grids
     for ($y = $ygrid; $y <= $ymax; $y += $ygrid) {
        ImageLine(
           $image,
           0,
           ($ymax - $y) * ($height - 1) / ($ymax - $ymin),
           $width - 1,
           ($ymax - $y) * ($height - 1) / ($ymax - $ymin),
           $grid
        );
     }
     for ($y = -$ygrid; $y >= $ymin; $y -= $ygrid) {
        ImageLine(
           $image,
           0,
           ($ymax - $y) * ($height - 1) / ($ymax - $ymin),
           $width - 1,
           ($ymax - $y) * ($height - 1) / ($ymax - $ymin),
           $grid
        );
     }
     # y grids
     for ($x = $xgrid; $x <= $xmax; $x += $xgrid) {
        ImageLine(
           $image,
           ($x - $xmin) * ($width - 1) / ($xmax - $xmin),
           0,
           ($x - $xmin) * ($width - 1) / ($xmax - $xmin),
           $height - 1,
           $grid
        );
     }
     for ($x = -$xgrid; $x >= $xmin; $x -= $xgrid) {
        ImageLine(
           $image,
           ($x - $xmin) * ($width - 1) / ($xmax - $xmin),
           0,
           ($x - $xmin) * ($width - 1) / ($xmax - $xmin),
           $height - 1,
           $grid
        );
     }

     # axes
     # x axis
     ImageLine(
        $image,
        0,
        $ymax * ($height - 1) / ($ymax - $ymin),
        $width - 1,
        $ymax * ($height - 1) / ($ymax - $ymin),
        $axes
     );
     # y axis
     ImageLine(
        $image,
        (-$xmin) * ($width - 1) / ($xmax - $xmin),
        0,
        (-$xmin) * ($width - 1) / ($xmax - $xmin),
        $height - 1,
        $axes
     );
     return $image;
   }

   function plotGraph($image, $width, $height, $xmin, $xmax, $ymin, $ymax, $points, $color) {
     $lastx = 0;      # last x value
     $lasty = 0;      # last y value
     $undef = true;   # last y undefined / error
     $up    = false;  # last y out-of-range (top)
     $down  = false;  # last y out-of-range (bottom)
     ksort($points, SORT_NUMERIC);
     reset($points);
     foreach ($points as $x => $content) {
        # get the y value and error type
        $y = $content[0];
        $error  = $content[1];
        if ($error != NOERROR) {
           $undef = true;
           $up    = false;
           $down  = false;
        } else {
          if (!$undef) {
             if ($y > $ymax) {
                if (!$up && !$down) {
                   $dx = $x - $lastx;
                   $dy = $y - $lasty;
                   $newx = $lastx + $dx * ($ymax - $lasty) / $dy;
                   ImageLine(
                      $image,
                      ($lastx - $xmin) * ($width - 1) / ($xmax - $xmin),
                      ($ymax - $lasty) * ($height - 1) / ($ymax - $ymin),
                      ($newx - $xmin) * ($width - 1) / ($xmax - $xmin),
                      0,
                      $color
                   );
                }
                $up    = true;
                $down  = false;
             } else if ($y < $ymin) {
                if (!$up && !$down) {
                   $dx = $x - $lastx;
                   $dy = $y - $lasty;
                   $newx = $lastx + $dx * ($ymin - $lasty) / $dy;
                   ImageLine(
                      $image,
                      ($lastx - $xmin) * ($width - 1) / ($xmax - $xmin),
                      ($ymax - $lasty) * ($height - 1) / ($ymax - $ymin),
                      ($newx - $xmin) * ($width - 1) / ($xmax - $xmin),
                      $height - 1,
                      $color
                   );
                }
                $up    = false;
                $down  = true;
             } else {
                if ($up) {
                   $dx = $x - $lastx;
                   $dy = $y - $lasty;
                   $newx = $lastx + $dx * ($ymax - $lasty) / $dy;
                   ImageLine(
                     $image,
                     ($newx - $xmin) * ($width - 1) / ($xmax - $xmin),
                     0,
                     ($x - $xmin) * ($width - 1) / ($xmax - $xmin),
                     ($ymax - $y) * ($height - 1) / ($ymax - $ymin),
                     $color
                   );
                } else if ($down) {
                   $dx = $x - $lastx;
                   $dy = $y - $lasty;
                   $newx = $lastx + $dx * ($ymin - $lasty) / $dy;
                   ImageLine(
                     $image,
                     ($newx - $xmin) * ($width - 1) / ($xmax - $xmin),
                     $height - 1,
                     ($x - $xmin) * ($width - 1) / ($xmax - $xmin),
                     ($ymax - $y) * ($height - 1) / ($ymax - $ymin),
                     $color
                   );
                } else {
                   ImageLine(
                     $image,
                     ($lastx - $xmin) * ($width - 1) / ($xmax - $xmin),
                     ($ymax - $lasty) * ($height - 1) / ($ymax - $ymin),
                     ($x - $xmin) * ($width - 1) / ($xmax - $xmin),
                     ($ymax - $y) * ($height - 1) / ($ymax - $ymin),
                     $color
                   );
                }
                $up    = false;
                $down  = false;
             }
          } else {
             $undef = false;
             $up    = false;
             $down  = false;
             if ($y > $ymax) {
                $up = true;
             } else
             if ($y < $ymin) {
                $down = true;
             }
          }
        }
        $lastx = $x;
        $lasty = $y;
      }
      return $image;
   }
   
   function fixedStep($a, $xmin, $xmax, $step, $function) {
      $results = array();
      # set the value of a to its current value for processing
      $constValues['a'] = "$a";
      for ($x = $xmin; $x <= $xmax; $x += $step) {
         # set the value of x to its current value for processing
         $constValues['x'] = "$x";
         # evaluate the function ...
         $y = substitute($function, $constValues);
         $y = evaluate(
                 array_values($y),
                 $error
              );
         $results["$x"] = array($y, $error);
         if ($error == NOSUCHFUNC || $error == PARSEERR) { return array(); }
      }
      # if the right image border has not been covered yet ...
      if ($x < $xmax + $step) {
         # ... repeat the procedure
         $constValues['x'] = "$xmax";
         # evaluate the function ...
         $y = substitute($function, $constValues);
         $y = evaluate(
                 array_values($y),
                 $error
              );
         $results["$xmax"] = array($y, $error);
      }
      return $results;
   }

   function getHeight($x1, $y1, $x2, $y2, $x3, $y3, $resx, $resy) {
      $a = sqrt($resx * $resx * ($x1 - $x3) * ($x1 - $x3)
              + $resy * $resy * ($y1 - $y3) * ($y1 - $y3));
      $b = sqrt($resx * $resx * ($x1 - $x2) * ($x1 - $x2)
              + $resy * $resy * ($y1 - $y2) * ($y1 - $y2));
      $c = sqrt($resx * $resx * ($x2 - $x3) * ($x2 - $x3)
              + $resy * $resy * ($y2 - $y3) * ($y2 - $y3));
      return ($a + $b + $c) * (-$a + $b + $c) * ($a - $b + $c) * ($a + $b - $c) / (8 * $a);
   }

   # resolution in pixels per unit
   function autoStep($a, $xmin, $xmax, $ymin, $ymax, $resx, $resy, $function) {
      if ($resx == 0) { return array(); }
      $stepmin = 1 / $resx;
      $step = 4 * $stepmin;
      # set the value of a to its current value for processing
      $constValues['a'] = "$a";
      $results = array();
      $x = $xmin;
         # set the value of x to its current value for processing
         $constValues['x'] = "$x";
         # evaluate the function ...
         $y = substitute($function, $constValues);
         $y = evaluate(
                 array_values($y),
                 $error
              );
         $results["$x"] = array($y, $error);
         $x2 = $x;
         if ($error == NOSUCHFUNC || $error == PARSEERR) { return array(); }
         if ($error != NOERROR) {
            $noprocess = true;
         } else {
            $noprocess = false;
         }
      $x += $step;
         # set the value of x to its current value for processing
         $constValues['x'] = "$x";
         # evaluate the function ...
         $y = substitute($function, $constValues);
         $y = evaluate(
                 array_values($y),
                 $error
              );
         $results["$x"] = array($y, $error);
         $x1 = $x;
     if ($error != NOERROR) {
        $noprocess = true;
     }
     if ($y < $ymin || $y > $ymax) {
        $outofrange = true;
     } else {
        $outofrange = false;
     }
     $x += $step;
     while ($x <= $xmax) {
         # set the value of x to its current value for processing
         $constValues['x'] = "$x";
         # evaluate the function ...
         $y = substitute($function, $constValues);
         $y = evaluate(
                 array_values($y),
                 $error
              );
         $results["$x"] = array($y, $error);
         if ($error == NOERROR) {
            if (!$noprocess) {
               $height = getHeight($x2, $results["$x2"][0],
                                   $x1, $results["$x1"][0],
                                   $x,  $y,
                                   $resx, $resy);
               if ($height > HGHTUPTHRES && $step > 2 * $stepmin) {
                  $x = $x1;
                  $x1 = $x2;
                  $step /= 2;
               } else if ($height < HGHTLWTHRES) {
                  $step *= 2;
               }
            } else {
               if ($results["$x1"][1] == NOERROR) {
                   $noprocess = false;
                } else {
                   $noprocess = true;
                }
            }
            if ($y < $ymin || $y > $ymax) {
               $outofrange = true;
            } else {
               $outofrange = false;
            }
         } else {
            if (!$outofrange && $step > 2 * $stepmin) {
               $x = $x1;
               $x1 = $x2;
               $step /= 2;
            } else {
               $noprocess = true;
            }
         }
         $x2 = $x1;
         $x1 = $x;
         $x += $step;
      }
      if ($x < $xmax + $step) {
         $x = $xmax;
         while ($x <= $xmax) {
             # set the value of x to its current value for processing
             $constValues['x'] = "$x";
             # evaluate the function ...
             $y = substitute($function, $constValues);
             $y = evaluate(
                     array_values($y),
                     $error
                  );
             $results["$x"] = array($y, $error);
             if ($error == NOERROR) {
                if (!$noprocess) {
                   $height = getHeight($x2, $results["$x2"][0],
                                       $x1, $results["$x1"][0],
                                       $x,  $y,
                                       $resx, $resy);
                   if ($height > HGHTUPTHRES && $step > 2 * $stepmin) {
                      $x = $x1;
                      $x1 = $x2;
                      $step /= 2;
                   } else if ($height < HGHTLWTHRES) {
                      $step *= 2;
                   }
                } else {
                   if ($results["$x1"][1] == NOERROR) {
                       $noprocess = false;
                    } else {
                       $noprocess = true;
                    }
                }
                if ($y < $ymin || $y > $ymax) {
                   $outofrange = true;
                } else {
                   $outofrange = false;
                }
             } else {
                if (!$outofrange && $step > 2 * $stepmin) {
                   $x = $x1;
                   $x1 = $x2;
                   $step /= 2;
                } else {
                   $noprocess = true;
                }
             }
             $x2 = $x1;
             $x1 = $x;
             $x += $step;
          }
      }
      return $results;
   }
?>


File graph.php:
<?php
   header ("Content-type: image/png");

   include("parser.php");
   include("graphics.php");

   $width = $_GET['width']; $height = $_GET['height'];
   $xmin  = $_GET['xmin'];  $xmax   = $_GET['xmax'];   $xgrid = $_GET['xgrid'];
   $ymin  = $_GET['ymin'];  $ymax   = $_GET['ymax'];   $ygrid = $_GET['ygrid'];
   $step  = $_GET['step'];
   $amin  = $_GET['amin'];  $amax   = $_GET['amax'];   $astep = $_GET['astep'];
   $smin  = $_GET['smin'];  $smax   = $_GET['smax']; # shading

   if (is_null($width))  { $width  = stdWidth; }
   if (is_null($height)) { $height = stdHeight; }
   if (is_null($xmin))   { $xmin   = stdXmin; }
   if (is_null($xmax))   { $xmax   = stdXmax; }
   if (is_null($ymin))   { $ymin   = stdYmin; }
   if (is_null($ymax))   { $ymax   = stdYmax; }
   if (is_null($step))   { $step   = stdStep; }
   if (is_null($amin))   { $amin   = stdAmin; }
   if (is_null($amax))   { $amax   = stdAmax; }
   if (is_null($astep))  { $astep  = stdAstep; }
   if (is_null($smin))   { $smin   = stdSmin; }
   if (is_null($smax))   { $smax   = stdSmax; }

   $bgcol = $_GET['bgcol'];
   if (-1 < $bgcol && $bgcol < count($colors)) {
      $bgcol = array_slice($colors[$bgcol], 1, 3);
   } else {
      $bgcol = array_slice($colors[stdBGcol], 1, 3);
   }
   $plcol = $_GET['plcol'];
   if (-1 < $plcol && $plcol < count($colors)) {
      $plcol = array_slice($colors[$plcol], 1, 3);
   } else {
      $plcol = array_slice($colors[stdPLcol], 1, 3);
   }
   $axcol = $_GET['axcol'];
   if (-1 < $axcol && $axcol < count($colors)) {
      $axcol = array_slice($colors[$axcol], 1, 3);
   } else {
      $axcol = array_slice($colors[stdAXcol], 1, 3);
   }
   $grcol = $_GET['grcol'];
   if (-1 < $grcol && $grcol < count($colors)) {
      $grcol = array_slice($colors[$grcol], 1, 3);
   } else {
      $grcol = array_slice($colors[stdGRcol], 1, 3);
   }
   $shcol = $_GET['shcol'];
   if (-1 < $shcol && $shcol < count($colors)) {
      $shcol = array_slice($colors[$shcol], 1, 3);
   } else {
      $shcol = array_slice($colors[stdSHcol], 1, 3);
   }

   $givenFunction = $_GET["func"];

   if (!$givenFunction) {
      $givenFunction = 'x';
   } else {
      $givenFunction = urldecode($givenFunction);
      for ($i = 0; $i < strlen($givenFunction); ++$i) {
         if ($givenFunction{$i} == '_') {
            $givenFunction{$i} = '+';
         }
      }
   }

   $func = removeUnneccessaryParens(
              splitTerm(
                 addTimes(
                    $givenFunction,
                    array('x', 'a', 'pi', 'e')
                 )
              )
           );
           
   # check whether the function contains a parameter
   if (!in_array('a', $func)) { $amin = $amax; }

   # Actual drawing process starts here

   # create an image resource with the specified width and height
   $image = @ImageCreate($width, $height)
      or die ("Fatal error when creating image");

   # create the colors from the given color values
   $bcolor = ImageColorAllocate($image, $bgcol[0], $bgcol[1], $bgcol[2]); # background
   $grid   = ImageColorAllocate($image, $grcol[0], $grcol[1], $grcol[2]);
   $axes   = ImageColorAllocate($image, $axcol[0], $axcol[1], $axcol[2]);
   $lines  = ImageColorAllocate($image, $plcol[0], $plcol[1], $plcol[2]); # graph and text

   # initialize the image with background, grid lines, and axes
   $image = initPlot(
      $image,
      $width,
      $height,
      $xmin,
      $xmax,
      $xgrid,
      $ymin,
      $ymax,
      $ygrid,
      $bcolor,
      $axes,
      $grid
   );

   # loop through the different parameter values
   for ($a = $amin; $a <= $amax; $a += $astep) {
     if ($_GET["autostep"] == "true") {
        $values = autoStep(
                     $a,
                     $xmin, $xmax,
                     $ymin, $ymax,
                     $width / ($xmax - $xmin), $height / ($ymax - $ymin),
                     $func
                  );
     } else {
        $values = fixedStep($a, $xmin, $xmax, $step, $func);
     }
     $image = plotGraph(
        $image,
        $width,
        $height,
        $xmin,
        $xmax,
        $ymin,
        $ymax,
        $values,
        $lines
     );
   }

   if ($smin < $smax) {
     $tempimg = @ImageCreate($width, $height)
        or die ("Fatal error when creating image");
     # create the colors from the given color values
     $tbcolor = ImageColorAllocate($tempimg, $bgcol[0], $bgcol[1], $bgcol[2]); # background
     $tgrid   = ImageColorAllocate($tempimg, $grcol[0], $grcol[1], $grcol[2]);
     $taxes   = ImageColorAllocate($tempimg, $axcol[0], $axcol[1], $axcol[2]);
     $tlines  = ImageColorAllocate($tempimg, $shcol[0], $shcol[1], $shcol[2]); # graph and text
     $tempimg = initPlot(
        $tempimg,
        $width,
        $height,
        $xmin,
        $xmax,
        $xgrid,
        $ymin,
        $ymax,
        $ygrid,
        $tbcolor,
        $taxes,
        $tgrid
     );
     reset($values);
     settype($xold, 'array');
     foreach ($values as $x => $content) {
        $y = $content[0];
        if (!is_array($xold)) {
          if ($x <= $smax) {
             if ($smin <= $xold) {
                $points[0] = ($xold - $xmin) * ($width - 1) / ($xmax - $xmin);
                $points[1] = ($ymax - $yold) * ($height - 1) / ($ymax - $ymin);
                $points[2] = ($x - $xmin) * ($width - 1) / ($xmax - $xmin);
                $points[3] = ($ymax - $y) * ($height - 1) / ($ymax - $ymin);
                $points[4] = $points[2];
                $points[5] = $ymax * ($height - 1) / ($ymax - $ymin);
                $points[6] = $points[0];
                $points[7] = $points[5];
                imageFilledPolygon(
                   $tempimg,
                   $points,
                   4,
                   $tlines
                );
             } else if ($smin <= $x) {
                $points[0] = ($smin - $xmin) * ($width - 1) / ($xmax - $xmin);
                $newy = $yold + ($y - $yold) * ($smin - $xold) / ($x - $xold);
                $points[1] = ($ymax - $newy) * ($height - 1) / ($ymax - $ymin);
                $points[2] = ($x - $xmin) * ($width - 1) / ($xmax - $xmin);
                $points[3] = ($ymax - $y) * ($height - 1) / ($ymax - $ymin);
                $points[4] = $points[2];
                $points[5] = $ymax * ($height - 1) / ($ymax - $ymin);
                $points[6] = $points[0];
                $points[7] = $points[5];
                imageFilledPolygon(
                   $tempimg,
                   $points,
                   4,
                   $tlines
                );
             }
          } else {
             $points[0] = ($xold - $xmin) * ($width - 1) / ($xmax - $xmin);
             $points[1] = ($ymax - $yold) * ($height - 1) / ($ymax - $ymin);
             $points[2] = ($smax - $xmin) * ($width - 1) / ($xmax - $xmin);
             $newy = $yold + ($y - $yold) * ($smax - $xold) / ($x - $xold);
             $points[3] = ($ymax - $newy) * ($height - 1) / ($ymax - $ymin);
             $points[4] = $points[2];
             $points[5] = $ymax * ($height - 1) / ($ymax - $ymin);
             $points[6] = $points[0];
             $points[7] = $points[5];
             imageFilledPolygon(
                $tempimg,
                $points,
                4,
                $tlines
             );
             break;
          }
        }
        $xold = $x;
        $yold = $y;
     }
     imageCopyMerge($image, $tempimg, 0, 0, 0, 0, $width, $height, 30);
   }

   # people NEED to know where to find this handy script, so tell them
   imagestring($image, 2, $width - 143, $height - 15, 'http://stable.moltke.de', $lines);

   ImagePNG($image); # output the image

   ImageDestroy($image); # and deallocate the memory for the resource
?>


File form.php:
<html>
<head><title>Function Plotter</title></head>
<body>
<?php
   include("parser.php");
   include("graphics.php");

   $givenFunction = $_POST["func_term"];
   if (is_null($givenFunction) || strlen($givenFunction) == 0) {
      $givenFunction = stdFunc;
   } else {
      $givenFunction = strtolower($givenFunction);
   }

   $xmin = $_POST["xmin"];
   if (is_null($xmin) || strlen($xmin) == 0) {
      $xmin = stdXmin;
   } else {
      $xmin = strtolower($xmin);
   }

   $xmax = $_POST["xmax"];
   if (is_null($xmax) || strlen($xmax) == 0) {
      $xmax = stdXmax;
   } else {
      $xmax = strtolower($xmax);
   }

   $xgrid = $_POST["xgrid"];
   if (is_null($xgrid) || strlen($xgrid) == 0) {
      $xgrid = stdXgrid;
   } else {
      $xgrid = strtolower($xgrid);
   }

   $ymin = $_POST["ymin"];
   if (is_null($ymin) || strlen($ymin) == 0) {
      $ymin = stdYmin;
   } else {
      $ymin = strtolower($ymin);
   }

   $ymax = $_POST["ymax"];
   if (is_null($ymax) || strlen($ymax) == 0) {
      $ymax = stdYmax;
   } else {
      $ymax = strtolower($ymax);
   }

   $ygrid = $_POST["ygrid"];
   if (is_null($ygrid) || strlen($ygrid) == 0) {
      $ygrid = stdYgrid;
   } else {
      $ygrid = strtolower($ygrid);
   }

   $step = $_POST["step"];
   if (is_null($step) || strlen($step) == 0) {
      $step = stdStep;
   } else {
      $step = strtolower($step);
   }

   $autostep = $_POST["autostep"];
   if ($autostep != "false" && $autostep != "true") {
      $autostep = stdAutoStep;
   }

   $amin = $_POST["amin"];
   if (is_null($amin) || strlen($amin) == 0) {
      $amin = stdAmin;
   } else {
      $amin = strtolower($amin);
   }

   $amax = $_POST["amax"];
   if (is_null($amax) || strlen($amax) == 0) {
      $amax = stdAmax;
   } else {
      $amax = strtolower($amax);
   }

   $astep = $_POST["astep"];
   if (is_null($astep) || strlen($astep) == 0) {
      $astep = stdAstep;
   } else {
      $astep = strtolower($astep);
   }

   $width = $_POST["width"];
   if (is_null($width) || strlen($width) == 0) {
      $width = stdWidth;
   } else {
      $width = strtolower($width);
   }

   $height = $_POST["height"];
   if (is_null($height) || strlen($height) == 0) {
      $height = stdHeight;
   } else {
      $height = strtolower($height);
   }

   $bgcol = $_POST["bgcol"];
   if (is_null($bgcol)) {
      $bgcol = stdBGcol;
   }

   $plcol = $_POST["plcol"];
   if (is_null($plcol)) {
      $plcol = stdPLcol;
   }

   $axcol = $_POST["axcol"];
   if (is_null($axcol)) {
      $axcol = stdAXcol;
   }

   $grcol = $_POST["grcol"];
   if (is_null($grcol)) {
      $grcol = stdGRcol;
   }

   $smin = $_POST["smin"];
   if (is_null($smin)) {
      $smin = stdSmin;
   } else {
      $smin = strtolower($smin);
   }

   $smax = $_POST["smax"];
   if (is_null($smax)) {
      $smax = stdSmax;
   } else {
      $smax = strtolower($smax);
   }

   $shcol = $_POST["shcol"];
   if (is_null($shcol)) {
      $shcol = stdSHcol;
   }

   $shade = $_POST["shade"];
   if ($shade != "false" && $shade != "true") {
      $shade = stdShade;
   }

   if (matchingParens($xmin) == -1) {
     evaluate(
        array_values(
           substitute(
              removeUnneccessaryParens(
                 splitTerm(
                    addTimes(
                       $xmin,
                       array('pi', 'e')
                    )
                 )
              ),
              $constValues
           )
        ),
        $error
     );
     if ($error != NOERROR) {
        print "There is an error in the expression for <i>X min</i> (<i>$xmin</i>). "
            . "Error: <b>" . errorType($error) . "</b>. <i>X min</i> will be set to "
            . stdXmin . "<br>\n";
        $xmin = stdXmin;
     }
   } else {
      print "The parentheses in your expression for <i>X min</i> do not match. Its "
          . "value will be set to " . stdXmin . "<br>\n";
      $xmin = stdXmin;
   }

   if (matchingParens($xmax) == -1) {
     evaluate(
        array_values(
           substitute(
              removeUnneccessaryParens(
                 splitTerm(
                    addTimes(
                       $xmax,
                       array('pi', 'e')
                    )
                 )
              ),
              $constValues
           )
        ),
        $error
     );
     if ($error != NOERROR) {
        print "There is an error in the expression for <i>X max</i> (<i>$xmax</i>). "
            . "Error: <b>" . errorType($error) . "</b>. <i>X max</i> will be set to "
            . stdXmax . "<br>\n";
        $xmax = stdXmax;
     }
   } else {
      print "The parentheses in your expression for <i>X max</i> do not match. Its "
          . "value will be set to " . stdXmax . "<br>\n";
      $xmax = stdXmax;
   }

   if (matchingParens($xgrid) == -1) {
     evaluate(
        array_values(
           substitute(
              removeUnneccessaryParens(
                 splitTerm(
                    addTimes(
                       $xgrid,
                       array('pi', 'e')
                    )
                 )
              ),
              $constValues
           )
        ),
        $error
     );
     if ($error != NOERROR) {
        print "There is an error in the expression for <i>X grid</i> (<i>$xgrid</i>). "
            . "Error: <b>" . errorType($error) . "</b>. <i>X grid</i> will be set to "
            . stdXgrid . "<br>\n";
        $xgrid = stdXgrid;
     }
   } else {
      print "The parentheses in your expression for <i>X grid</i> do not match. Its "
          . "value will be set to " . stdXgrid . "<br>\n";
      $xgrid = stdXgrid;
   }

   if (matchingParens($ymin) == -1) {
     evaluate(
        array_values(
           substitute(
              removeUnneccessaryParens(
                 splitTerm(
                    addTimes(
                       $ymin,
                       array('pi', 'e')
                    )
                 )
              ),
              $constValues
           )
        ),
        $error
     );
     if ($error != NOERROR) {
        print "There is an error in the expression for <i>Y min</i> (<i>$ymin</i>). "
            . "Error: <b>" . errorType($error) . "</b>. <i>Y min</i> will be set to "
            . stdYmin . "<br>\n";
        $ymin = stdYmin;
     }
   } else {
      print "The parentheses in your expression for <i>Y min</i> do not match. Its "
          . "value will be set to " . stdYmin . "<br>\n";
      $ymin = stdYmin;
   }

   if (matchingParens($ymax) == -1) {
     evaluate(
        array_values(
           substitute(
              removeUnneccessaryParens(
                 splitTerm(
                    addTimes(
                       $ymax,
                       array('pi', 'e')
                    )
                 )
              ),
              $constValues
           )
        ),
        $error
     );
     if ($error != NOERROR) {
        print "There is an error in the expression for <i>Y max</i> (<i>$ymax</i>). "
            . "Error: <b>" . errorType($error) . "</b>. <i>Y max</i> will be set to "
            . stdYmax . "<br>\n";
        $ymax = stdYmax;
     }
   } else {
      print "The parentheses in your expression for <i>Y max</i> do not match. Its "
          . "value will be set to " . stdYmax . "<br>\n";
      $ymax = stdYmax;
   }

   if (matchingParens($ygrid) == -1) {
     evaluate(
        array_values(
           substitute(
              removeUnneccessaryParens(
                 splitTerm(
                    addTimes(
                       $ygrid,
                       array('pi', 'e')
                    )
                 )
              ),
              $constValues
           )
        ),
        $error
     );
     if ($error != NOERROR) {
        print "There is an error in the expression for <i>Y grid</i> (<i>$ygrid</i>). "
            . "Error: <b>" . errorType($error) . "</b>. <i>Y grid</i> will be set to "
            . stdYgrid . "<br>\n";
        $ygrid = stdYgrid;
     }
   } else {
      print "The parentheses in your expression for <i>Y grid</i> do not match. Its "
          . "value will be set to " . stdYgrid . "<br>\n";
      $ygrid = stdYgrid;
   }

   if (matchingParens($step) == -1) {
     evaluate(
        array_values(
           substitute(
              removeUnneccessaryParens(
                 splitTerm(
                    addTimes(
                       $step,
                       array('pi', 'e')
                    )
                 )
              ),
              $constValues
           )
        ),
        $error
     );
     if ($error != NOERROR) {
        print "There is an error in the expression for the step width (<i>$step</i>). "
            . "Error: <b>" . errorType($error) . "</b>. <i>Step</i> will be set to "
            . stdStep . "<br>\n";
        $step = stdStep;
     }
   } else {
      print "The parentheses in your expression for the step width do not match. Its "
          . "value will be set to " . stdStep . "<br>\n";
      $step = stdStep;
   }

   if (matchingParens($amin) == -1) {
     evaluate(
        array_values(
           substitute(
              removeUnneccessaryParens(
                 splitTerm(
                    addTimes(
                       $amin,
                       array('pi', 'e')
                    )
                 )
              ),
              $constValues
           )
        ),
        $error
     );
     if ($error != NOERROR) {
        print "There is an error in the expression for <i>A min</i> (<i>$amin</i>). "
            . "Error: <b>" . errorType($error) . "</b>. <i>A min</i> will be set to "
            . stdAmin . "<br>\n";
        $amin = stdAmin;
     }
   } else {
      print "The parentheses in your expression for <i>A min</i> do not match. Its "
          . "value will be set to " . stdAmin . "<br>\n";
      $amin = stdAmin;
   }

   if (matchingParens($amax) == -1) {
     evaluate(
        array_values(
           substitute(
              removeUnneccessaryParens(
                 splitTerm(
                    addTimes(
                       $amax,
                       array('pi', 'e')
                    )
                 )
              ),
              $constValues
           )
        ),
        $error
     );
     if ($error != NOERROR) {
        print "There is an error in the expression for <i>A max</i> (<i>$amax</i>). "
            . "Error: <b>" . errorType($error) . "</b>. <i>A max</i> will be set to "
            . stdAmax . "<br>\n";
        $amax = stdAmax;
     }
   } else {
      print "The parentheses in your expression for <i>A max</i> do not match. Its "
          . "value will be set to " . stdAmax . "<br>\n";
      $amax = stdAmax;
   }

   if (matchingParens($astep) == -1) {
     evaluate(
        array_values(
           substitute(
              removeUnneccessaryParens(
                 splitTerm(
                    addTimes(
                       $astep,
                       array('pi', 'e')
                    )
                 )
              ),
              $constValues
           )
        ),
        $error
     );
     if ($error != NOERROR) {
        print "There is an error in the expression for <i>A step</i> (<i>$astep</i>). "
            . "Error: <b>" . errorType($error) . "</b>. <i>A step</i> will be set to "
            . stdAstep . "<br>\n";
        $astep = stdAstep;
     }
   } else {
      print "The parentheses in your expression for <i>A step</i> do not match. Its "
          . "value will be set to " . stdAstep . "<br>\n";
      $astep = stdAstep;
   }

   if (matchingParens($smin) == -1) {
     evaluate(
        array_values(
           substitute(
              removeUnneccessaryParens(
                 splitTerm(
                    addTimes(
                       $smin,
                       array('pi', 'e')
                    )
                 )
              ),
              $constValues
           )
        ),
        $error
     );
     if ($error != NOERROR) {
        print "There is an error in the expression for the shading minimum (<i>$smin</i>). "
            . "Error: <b>" . errorType($error) . "</b>. The shading minimum will be set to "
            . stdSmin . "<br>\n";
        $smin = stdSmin;
     }
   } else {
      print "The parentheses in your expression for the shading minimum do not match. Its "
          . "value will be set to " . stdSmin . "<br>\n";
      $smin = stdSmin;
   }

   if (matchingParens($smax) == -1) {
     evaluate(
        array_values(
           substitute(
              removeUnneccessaryParens(
                 splitTerm(
                    addTimes(
                       $smax,
                       array('pi', 'e')
                    )
                 )
              ),
              $constValues
           )
        ),
        $error
     );
     if ($error != NOERROR) {
        print "There is an error in the expression for the shading maximum (<i>$smax</i>). "
            . "Error: <b>" . errorType($error) . "</b>. The shading maximum will be set to "
            . stdSmax . "<br>\n";
        $smax = stdSmax;
     }
   } else {
      print "The parentheses in your expression for the shading maximum do not match. Its "
          . "value will be set to " . stdSmax . "<br>\n";
      $smax = stdSmax;
   }
?>
   The form parameter is called <b><i>a</i></b><br>
   <form action="form.php" method="post">
      <table border="0" cellpadding="0" cellspacing="4">
         <tr>
            <td align="left"><b>Function <i>f(x)</i>:</b></td>
            <td>
               <?php
                  print "<input name=\"func_term\" type=\"text\" value=\"$givenFunction\" size=\"30\" maxlength=\"100\">\n";
               ?>
            </td>
         </tr>
         <tr>
            <td align="left"><b>X min:</b></td>
            <td>
               <?php
                  print "<input name=\"xmin\" type=\"text\" value=\"$xmin\" size=\"30\" maxlength=\"100\">\n";
               ?>
            </td>
         </tr>
         <tr>
            <td align="left"><b>X max:</b></td>
            <td>
               <?php
                  print "<input name=\"xmax\" type=\"text\" value=\"$xmax\" size=\"30\" maxlength=\"100\">\n";
               ?>
            </td>
         </tr>
         <tr>
            <td align="left"><b>X grid width:</b></td>
            <td>
               <?php
                  print "<input name=\"xgrid\" type=\"text\" value=\"$xgrid\" size=\"30\" maxlength=\"100\">\n";
               ?>
            </td>
         </tr>
         <tr>
            <td align="left"><b>Y min:</b></td>
            <td>
               <?php
                  print "<input name=\"ymin\" type=\"text\" value=\"$ymin\" size=\"30\" maxlength=\"100\">\n";
               ?>
            </td>
         </tr>
         <tr>
            <td align="left"><b>Y max:</b></td>
            <td>
               <?php
                  print "<input name=\"ymax\" type=\"text\" value=\"$ymax\" size=\"30\" maxlength=\"100\">\n";
               ?>
            </td>
         </tr>
         <tr>
            <td align="left"><b>Y grid width:</b></td>
            <td>
               <?php
                  print "<input name=\"ygrid\" type=\"text\" value=\"$ygrid\" size=\"30\" maxlength=\"100\">\n";
               ?>
            </td>
         </tr>
         <tr>
            <td align="left"><b>Step width:</b></td>
            <td>
               <?php
                  print "<input name=\"step\" type=\"text\" value=\"$step\" size=\"30\" maxlength=\"100\">\n";
               ?>
            </td>
         </tr>
         <tr>
            <td align="left"><b>Automatic step width control:</b></td>
            <td>
               <?php
                  print "<input name=\"autostep\" type=\"radio\" value=\"true\"";
                  if ($autostep == "true") { print " checked"; }
                  print "> Activated<br>\n";
                  print "<input name=\"autostep\" type=\"radio\" value=\"false\"";
                  if ($autostep == "false") { print " checked"; }
                  print "> Desactivated\n";
               ?>
            </td>
         </tr>
         <tr>
            <td align="left"><b><i>A</i> min:</b></td>
            <td>
               <?php
                  print "<input name=\"amin\" type=\"text\" value=\"$amin\" size=\"30\" maxlength=\"100\">\n";
               ?>
            </td>
         </tr>
         <tr>
            <td align="left"><b><i>A</i> max:</b></td>
            <td>
               <?php
                  print "<input name=\"amax\" type=\"text\" value=\"$amax\" size=\"30\" maxlength=\"100\">\n";
               ?>
            </td>
         </tr>
         <tr>
            <td align="left"><b><i>A</i> step:</b></td>
            <td>
               <?php
                  print "<input name=\"astep\" type=\"text\" value=\"$astep\" size=\"30\" maxlength=\"100\">\n";
               ?>
            </td>
         </tr>
         <tr>
            <td align="left"><b>Image width:</b></td>
            <td>
               <?php
                  print "<input name=\"width\" type=\"text\" value=\"$width\" size=\"30\" maxlength=\"100\">\n";
               ?>
            </td>
         </tr>
         <tr>
            <td align="left"><b>Image height:</b></td>
            <td>
               <?php
                  print "<input name=\"height\" type=\"text\" value=\"$height\" size=\"30\" maxlength=\"100\">\n";
               ?>
            </td>
         </tr>
         <tr>
            <td align="left"><b>Background Color:</b></td>
            <td>
               <?php
                  print "<select name=\"bgcol\" size=\"1\">\n";
                  for ($i = 0; $i < count($colors); ++$i) {
                     print "<option";
                     if ($i == $bgcol) { print " selected"; }
                     print " value=\"" . $i . "\">" . $colors[$i][0]. "</option>\n";
                  }
                  print "</select>\n";
               ?>
            </td>
         </tr>
         <tr>
            <td align="left"><b>Plot Color:</b></td>
            <td>
               <?php
                  print "<select name=\"plcol\" size=\"1\">\n";
                  for ($i = 0; $i < count($colors); ++$i) {
                     print "<option";
                     if ($i == $plcol) { print " selected"; }
                     print " value=\"" . $i . "\">" . $colors[$i][0]. "</option>\n";
                  }
                  print "</select>\n";
               ?>
            </td>
         </tr>
         <tr>
            <td align="left"><b>Axis Color:</b></td>
            <td>
               <?php
                  print "<select name=\"axcol\" size=\"1\">\n";
                  for ($i = 0; $i < count($colors); ++$i) {
                     print "<option";
                     if ($i == $axcol) { print " selected"; }
                     print " value=\"" . $i . "\">" . $colors[$i][0]. "</option>\n";
                  }
                  print "</select>\n";
               ?>
            </td>
         </tr>
         <tr>
            <td align="left"><b>Grid Color:</b></td>
            <td>
               <?php
                  print "<select name=\"grcol\" size=\"1\">\n";
                  for ($i = 0; $i < count($colors); ++$i) {
                     print "<option";
                     if ($i == $grcol) { print " selected"; }
                     print " value=\"" . $i . "\">" . $colors[$i][0]. "</option>\n";
                  }
                  print "</select>\n";
               ?>
            </td>
         </tr>
         <tr>
            <td align="left"><b>Shading:</b></td>
            <td>
               <?php
                  print "<input name=\"shade\" type=\"radio\" value=\"true\"";
                  if ($shade == "true") { print " checked"; }
                  print "> Shade<br>\n";
                  print "<input name=\"shade\" type=\"radio\" value=\"false\"";
                  if ($shade == "false") { print " checked"; }
                  print "> Do not shade\n";
               ?>
            </td>
         </tr>
         <tr>
            <td align="left"><b>Shading min:</b></td>
            <td>
               <?php
                  print "<input name=\"smin\" type=\"text\" value=\"$smin\" size=\"30\" maxlength=\"100\">\n";
               ?>
            </td>
         </tr>
         <tr>
            <td align="left"><b>Shading max:</b></td>
            <td>
               <?php
                  print "<input name=\"smax\" type=\"text\" value=\"$smax\" size=\"30\" maxlength=\"100\">\n";
               ?>
            </td>
         </tr>
         <tr>
            <td align="left"><b>Shading Color:</b></td>
            <td>
               <?php
                  print "<select name=\"shcol\" size=\"1\">\n";
                  for ($i = 0; $i < count($colors); ++$i) {
                     print "<option";
                     if ($i == $shcol) { print " selected"; }
                     print " value=\"" . $i . "\">" . $colors[$i][0]. "</option>\n";
                  }
                  print "</select>\n";
               ?>
            </td>
         </tr>
      </table>
      <br><br>
         <input type="submit" value=" Plot ">
         <input type="reset" value=" Reset ">
      <br><br>
   </form>
<?php
   $xmin = evaluate(
              array_values(
                 substitute(
                    removeUnneccessaryParens(
                       splitTerm(
                          addTimes(
                             $xmin,
                             array('pi', 'e')
                          )
                       )
                    ),
                    $constValues
                 )
              ),
             $error
          );

   $xmax = evaluate(
              array_values(
                 substitute(
                    removeUnneccessaryParens(
                       splitTerm(
                          addTimes(
                             $xmax,
                             array('pi', 'e')
                          )
                       )
                    ),
                    $constValues
                 )
              ),
             $error
          );

   $xgrid = evaluate(
              array_values(
                 substitute(
                    removeUnneccessaryParens(
                       splitTerm(
                          addTimes(
                             $xgrid,
                             array('pi', 'e')
                          )
                       )
                    ),
                    $constValues
                 )
              ),
             $error
          );

   $ymin = evaluate(
              array_values(
                 substitute(
                    removeUnneccessaryParens(
                       splitTerm(
                          addTimes(
                             $ymin,
                             array('pi', 'e')
                          )
                       )
                    ),
                    $constValues
                 )
              ),
             $error
          );

   $ymax = evaluate(
              array_values(
                 substitute(
                    removeUnneccessaryParens(
                       splitTerm(
                          addTimes(
                             $ymax,
                             array('pi', 'e')
                          )
                       )
                    ),
                    $constValues
                 )
              ),
             $error
          );

   $ygrid = evaluate(
              array_values(
                 substitute(
                    removeUnneccessaryParens(
                       splitTerm(
                          addTimes(
                             $ygrid,
                             array('pi', 'e')
                          )
                       )
                    ),
                    $constValues
                 )
              ),
             $error
          );

   $step = evaluate(
              array_values(
                 substitute(
                    removeUnneccessaryParens(
                       splitTerm(
                          addTimes(
                             $step,
                             array('pi', 'e')
                          )
                       )
                    ),
                    $constValues
                 )
              ),
             $error
          );

   $amin = evaluate(
              array_values(
                 substitute(
                    removeUnneccessaryParens(
                       splitTerm(
                          addTimes(
                             $amin,
                             array('pi', 'e')
                          )
                       )
                    ),
                    $constValues
                 )
              ),
             $error
          );

   $amax = evaluate(
              array_values(
                 substitute(
                    removeUnneccessaryParens(
                       splitTerm(
                          addTimes(
                             $amax,
                             array('pi', 'e')
                          )
                       )
                    ),
                    $constValues
                 )
              ),
             $error
          );

   $astep = evaluate(
              array_values(
                 substitute(
                    removeUnneccessaryParens(
                       splitTerm(
                          addTimes(
                             $astep,
                             array('pi', 'e')
                          )
                       )
                    ),
                    $constValues
                 )
              ),
             $error
          );

   if ($shade == 'true') {
     $smin = evaluate(
                array_values(
                   substitute(
                      removeUnneccessaryParens(
                         splitTerm(
                            addTimes(
                               $smin,
                               array('pi', 'e')
                            )
                         )
                      ),
                      $constValues
                   )
                ),
               $error
            );
  
     $smax = evaluate(
                array_values(
                   substitute(
                      removeUnneccessaryParens(
                         splitTerm(
                            addTimes(
                               $smax,
                               array('pi', 'e')
                            )
                         )
                      ),
                      $constValues
                   )
                ),
               $error
            );
   } else {
      $smin = 1;
      $smax = -1;
   }

   if ($xmin > $xmax) {
      print "<i>X min</i> is greater than <i>X max</i>. Their values will be switched.<br>\n";
      $temp = $xmax; $xmax = $xmin; $xmin = $temp;
   }
   if ($ymin > $ymax) {
      print "<i>Y min</i> is greater than <i>Y max</i>. Their values will be switched.<br>\n";
      $temp = $ymax; $ymax = $ymin; $ymin = $temp;
   }
   if ($amin > $amax) {
      print "<i>A min</i> is greater than <i>A max</i>. Their values will be switched.<br>\n";
      $temp = $amax; $amax = $amin; $amin = $temp;
   }

   if ($step < ($xmax - $xmin) / $width) {
      print "<b>WARNING:</b> The step width you chose is smaller than the graph resolution. "
          . "It will probably just take more processing time to plot the same graph.<br>"
          . "Please note that PHP stops processing a script after 30 seconds.<br>";
   }

   if ($astep < ($amax - $amin) / 5) {
      print "<b>WARNING:</b> You chose to draw more than 6 functions at the same time.<br>"
          . "Please note that PHP stops processing a script after 30 seconds.<br>";
   }

   settype($xmin,   "double");
   settype($xmax,   "double");
   settype($xgrid,  "double");
   settype($ymin,   "double");
   settype($ymax,   "double");
   settype($ygrid,  "double");
   settype($step,   "double");
   settype($amin,   "double");
   settype($amax,   "double");
   settype($astep,  "double");
   settype($smin,   "double");
   settype($smax,   "double");

   for ($i = 0; $i < strlen($givenFunction); ++$i) {
      if ($givenFunction{$i} == '+') {
         $givenFunction{$i} = '_';
      }
   }
   $givenFunction = urlencode($givenFunction);

   print "<img src=\"graph.php?func=$givenFunction&xmin=$xmin&xmax=$xmax&xgrid=$xgrid&ymin=$ymin&ymax=$ymax&ygrid=$ygrid&step=$step&width=$width&height=$height&amin=$amin&amax=$amax&astep=$astep&bgcol=$bgcol&plcol=$plcol&axcol=$axcol&grcol=$grcol&autostep=$autostep&smin=$smin&smax=$smax&shcol=$shcol\" width=$width height=$height alt=\"Function Graph\">\n";
?>
<br><br><br>
<a href="source.php">&copy; Jan Olligs, 2003</a>
</body>
</html>