home *** CD-ROM | disk | FTP | other *** search
- /* XLISP-STAT 2.1 Copyright (c) 1990, by Luke Tierney */
- /* Additions to Xlisp 2.1, Copyright (c) 1989 by David Michael Betz */
- /* You may give out copies of this software; for conditions see the */
- /* file COPYING included with this distribution. */
-
- #include <math.h>
- #include "gnuplot.h"
- #include "xlisp.h"
-
- # define numberp(x) (fixp(x) || floatp(x))
- # define makefloat(x) ((fixp(x)) ? (double) getfixnum(x) : getflonum(x))
- # define sequencep(x) (listp(x) || simplevectorp(x))
-
- extern LVAL coerce_to_list();
-
- static double NiceValue(x)
- double x;
- {
- long ilx;
- double lx, v1, v2, v3, v4;
-
- if (x <= 0) return (0.0);
- else {
- lx = log(x) / log(10.0);
- ilx = floor(lx);
- v1 = pow(10.0, (float) ilx);
- v2 = pow(10.0, (float) ilx) * 2.0;
- v3 = pow(10.0, (float) ilx) * 5.0;
- v4 = pow(10.0, (float) ilx + 1);
-
- if ((fabs(x - v1) < fabs(x - v2))
- && (fabs(x - v1) < fabs(x - v3))
- && (fabs(x - v1) < fabs(x - v4)))
- return(v1);
- else if ((fabs(x - v2) < fabs(x - v3))
- && (fabs(x - v2) < fabs(x - v4)))
- return(v2);
- else if (fabs(x - v3) < fabs(x - v4))
- return(v3);
- else
- return(v4);
- }
- }
-
- static SetNiceRange(xmin, xmax, ticks)
- double *xmin, *xmax;
- int *ticks;
- {
- double delta;
-
- if ((*xmax <= *xmin) || (*ticks < 2)) return;
-
- delta = NiceValue((*xmax - *xmin) / (*ticks - 1));
-
- *xmin = floor(*xmin / delta) * delta;
- *xmax = ceil(*xmax / delta) * delta;
-
- *ticks = 1 + (.01 + (*xmax - *xmin) / delta);/* add .01 for rounding */
- }
-
- static set_range(low, high)
- double *low, *high;
- {
- int ticks = 4;
-
- if (*low == *high) {
- (*low)--;
- (*high)++;
- }
- else SetNiceRange(low, high, &ticks);
- }
-
- static LVAL gnupointlineplot(plot_style)
- enum PLOT_STYLE plot_style;
- {
- LVAL next, nextx, nexty;
- int n, i;
- struct curve_points *this_plot, real_plot;
- struct coordinate *pts;
- double xmin, xmax, ymin, ymax, dx, dy;
- LVAL x, y;
-
- xlstkcheck(2);
- xlsave(x);
- xlsave(y);
-
- x = xlgetarg();
- if (consp(x) && sequencep(car(x))) {
- y = car(cdr(x));
- x = car(x);
- }
- else y = xlgetarg();
- x = coerce_to_list(x);
- y = coerce_to_list(y);
-
- n = llength(x);
- if (llength(y) != n) xlfail("lengths do not match");
- for (next = x; next != NULL; next = cdr(next))
- if (! numberp(car(next))) xlerror("not a number", car(next));
- for (next = y; next != NULL; next = cdr(next))
- if (! numberp(car(next))) xlerror("not a number", car(next));
-
- pts = (struct coordinate *) calloc(sizeof(struct coordinate), n);
-
- this_plot = &real_plot;
- this_plot->points = (struct coordinate *) pts;
- this_plot->next_cp = 0;
- this_plot->plot_type = DATA;
- this_plot->plot_style = plot_style;
- this_plot->title = "";
- this_plot->p_count = n;
-
- xmin = HUGE;
- xmax = -HUGE;
- ymin = HUGE;
- ymax = -HUGE;
- for(i = 0, nextx = x, nexty = y; i < n;
- i++, nextx = cdr(nextx), nexty = cdr(nexty)) {
- dx = makefloat(car(nextx));
- dy = makefloat(car(nexty));
- this_plot->points[i].undefined = FALSE;
- this_plot->points[i].x = dx;
- this_plot->points[i].y = dy;
- if (dx > xmax) xmax = dx;
- if (dx < xmin) xmin = dx;
- if (dy > ymax) ymax = dy;
- if (dy < ymin) ymin = dy;
- }
-
- set_range(&xmin, &xmax);
- set_range(&ymin, &ymax);
-
- do_plot(this_plot, 1, xmin, xmax, ymin, ymax);
-
- free(pts);
- xlpopn(2);
-
- return(NIL);
- }
-
- LVAL gnupointplot() { return(gnupointlineplot(POINTS)); }
- LVAL gnulineplot() { return(gnupointlineplot(LINES)); }
-