This is auxil.m in view mode; [Download] [Up]
/* * Auxiliary routines, all taken from xyplot (translated from Fortran to C). */ #include "defs.h" #include <strings.h> #include <stdio.h> #include <math.h> #include <stdlib.h> /* for exit() */ #include <appkit/Panel.h> /* for NXRunAlertPanel */ /* * Count the number of labels on a given axis. */ void count_labels(int *pn, double *pfirst, double min, double inc, double max) { int bottom, top, j; double range, absinc, tol, guess; if (inc != 0.0) { *pn = 0; bottom = (int)(min/inc) - 1; top = (int)(max/inc) + 1; range = ABS(max - min); absinc = MIN(range, ABS(inc)); tol = absinc * (range + absinc) / 100.0; for (j=top; j>=bottom; j--) { guess = (double)j * inc; if ( (max-guess)*(guess-min) >= -tol) { *pn += 1; *pfirst = guess; } } } else { *pn = 0; *pfirst = 0.0; } return; } /* * Write a float into a string and see how many characters are to the left * of the decimal point, how many total decimal characters there are, and * how many characters there are in the exponent (if exponential notation). */ void numstring(double x, int *nl, int *nd, int *ne) { char string[80]; double ax; int i, nc, net; ax = ABS(x); i = ax; if ((double)i==ax && ax<99999.0) { sprintf(string, "%1d", (int)x); } else { if (ax>=1.e-4 && ax<1.e5) { if ( ((int)(x*10000.0) % 10000) == 0 ) sprintf(string, "%-6.0f", x); /* left-justify */ else if ( ((int)(x*10000.0) % 1000) == 0 ) sprintf(string, "%-7.1f", x); else if ( ((int)(x*10000.0) % 100) == 0 ) sprintf(string, "%-8.2f", x); else if ( ((int)(x*10000.0) % 10) == 0 ) sprintf(string, "%-9.3f", x); else /* sprintf(string, "%-10.4f", x); this can fail -- e.g., x=0.000718 */ sprintf(string, "%10.6f", x); /* will this always work? */ } else { sprintf(string, "%-#11.2e", x); } } nc = strlen(string); /* strip off blanks from the end of the string: */ while (string[nc-1] == ' ') { string[--nc] = '\0'; } nc = strlen(string); /* nl = no. of characters left of the decimal point (including sign) */ *nl = 0; for (i=nc-1; i>=0; i--) { *nl += 1; if (string[i] == '.') *nl = 0; } /* nd = no. of decimal characters (including decimal point, omitting * trailing zeros) */ *nd = 0; for (i=nc-1; i>=*nl; i--) { *nd += 1; if (string[i] == 'e' || string[i] == 'E') *nd = 0; if (string[i] == '0' && *nd == 1) *nd = 0; } /* ne = no. of exponent characters (including the 'E' if any) */ *ne = 0; for (i=*nl + *nd; i<nc; i++) { if (string[i] == 'e' || string[i] == 'E') *ne = nc - i; } net = 0; for (i = nc-1; i >= nc - *ne + 2; i--) { if (string[i] != '0') net = 2 + nc - i; } *ne = net; /* Some special cases where floating point numbers may be * expressed as integers. */ if (*nd==1 && *ne==0) *nd = 1; return; } /* * See what the formatting would be if we go from min to max in * steps of inc. */ void autoformat(double min, double inc, double max, int *axformat) { int nlabels, i, nl, nd, ne; double first, value; *axformat = 0; *(axformat + 1) = 0; *(axformat + 2) = 0; count_labels(&nlabels, &first, min, inc, max); for (i=0; i<nlabels; i++) { /* Special test here for what should be exact 0 (but isn't sometimes * due to floating-point arithmetic. */ if (inc != 0.0 && fabs(first/inc + (double)i) < 1.0e-14) { /* ugly */ value = 0.0; } else { value = first + inc*(double)i; } numstring(value, &nl, &nd, &ne); if (*(axformat+2)==0 && ne!=0) { *axformat = nl; *(axformat+1) = nd; *(axformat+2) = ne; } else { *axformat = MAX(nl, *axformat); *(axformat+1) = MAX(nd, *(axformat+1)); *(axformat+2) = MAX(ne, *(axformat+2)); } } return; } /* * Put a float into a string with a specified format. */ void handformat(float number, char *string, int *axformat) { int nl, nd, ne; nl = *(axformat+0); nd = *(axformat+1); ne = *(axformat+2); // if all axformat[i] are 0, return just a blank: if (ne==0 && nd==0 && nl==0) { sprintf(string, " "); return; } // special case 0: if (number == 0.0) { sprintf(string, "%1d", 0); return; } if (ne==0) { if (nd==0) { sprintf(string, "%*d", nl, (int)rint((double)number)); } else sprintf(string, "%*.*f", nl, nd-1, number); } else { if (nd==0) sprintf(string, "%*.*e", nl, nd, number); else sprintf(string, "%*.*e", ne+1, nd-1, number); } return; } /* * Compute nice increment for linear plotting, given min and max. */ void computeNiceLinInc(float *pmin, float *pmax, float *pinc) { float fmin = *pmin, fmax = *pmax, finc = (fmax - fmin)/5.0, x; int n; if (finc <= 0.0) { fmin = (fmin>0.0? 0.9*fmin : 1.1*fmin); fmax = (fmax>0.0? 1.1*fmax : 0.9*fmax); finc = (fmax - fmin)/5.0; // for safety: if (finc < 0.0) { n = NXRunAlertPanel("computeNiceLinInc", "Impossible increment = %g.\n" "I'm very confused " "(Perhaps all data is being ignored -- no lines, no symbols)", "Quit", "Continue", NULL, finc); if (n==NX_ALERTDEFAULT) exit(0); else if (n==NX_ALERTALTERNATE) { *pmin = 0.0; *pmax = 1.0; *pinc = 0.2; return; } } } n = ( log10((double)finc) >= 0.0 ? (int)floor(log10((double)finc)) : (int)ceil(log10((double)finc)) ); if (finc > 1.0) n++; x = finc * (float)pow((double)10.0, (double)(-n)); finc = 0.1; if (x > 0.1) finc = 0.2; if (x > 0.2) finc = 0.25; if (x > 0.25) finc = 0.5; if (x > 0.5) finc = 1.0; finc = finc * (float)pow((double)10.0, (double)n); if (fmin < ((int)(fmin/finc))*finc) fmin = ((int)(fmin/finc - 1))*finc; else fmin = ((int)(fmin/finc))*finc; if (fmax > ((int)(fmax/finc))*finc) fmax = ((int)(fmax/finc + 1))*finc; else fmax = ((int)(fmax/finc))*finc; *pmin = fmin; *pmax = fmax; *pinc = finc; return; } /* * Compute a nice min and max for logarithmic plotting (we take increment=1). */ void computeNiceLogInc(float *pmin, float *pmax, float *pinc) { float fmin, fmax, finc; int n; // for safety: if (*pmin <= 0.0 || *pmax <= 0.0) { n = NXRunAlertPanel("computeNiceLogInc", "Impossible min/max = %g, %g.\n" "I'm very confused " "(Perhaps all data is being ignored -- no lines, no symbols)", "Quit", "Continue", NULL, *pmin, *pmax); if (n==NX_ALERTDEFAULT) exit(0); else if (n==NX_ALERTALTERNATE) { *pmin = 1.0; *pmax = 10.0; *pinc = 1.0; return; } } fmin = (float)log10(*pmin); fmax = (float)log10(*pmax); finc = 1.0; fmin = (float) floor((double)fmin); fmax = (float) ceil((double)fmax); if (fmin == fmax) { fmin = fmin - 1.0; fmax = fmax + 1.0; } *pmin = (float)pow((double)10.0, (double)fmin); *pmax = (float)pow((double)10.0, (double)fmax); *pinc = (float)pow((double)10.0, (double)finc); return; }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.