This is fscale.c in view mode; [Download] [Up]
#if ( !defined(lint) && !defined(SABER)) static char PCN_rcsid[] = "$Header: /tmp_mnt/ufs/pcn/carl/PCN/IF/Xsw/RCS/fscale.c,v 1.2 91/09/13 17:02:51 carl Exp $"; #endif /****************************************************************************** * * * Copyright (C) The Aerospace Corporation 1991 * * * * This software was developed by The Aerospace Corporation as a * * research endeavor for the United States Air Force * * Space Systems Division. The current version of the Gauge * * computer program is available for release to you for * * educational and research purposes only. It is not * * to be used for commercial purposes. * * * * In addition, the following conditions shall apply. * * * * 1) The computer software and documentation were designed to * * satisfy internal Aerospace requirements only. * * The software is provided ``as is,'' and The Aerospace Corporation * * makes no warranty, expressed or implied, as to it accuracy, * * functioning, or fitness for a particular purpose. * * * * 2) The Aerospace Corporation and its personnel are not * * responsible for providing technical support or general assistance * * with respect to the software. * * * * 3) Neither The Aerospace Corporation nor its personnel shall be * * liable for claims, losses, or damages arising out of or connected * * with the use of this software. * * Your sole and exclusive remedy shall be to request a replacement * * copy of the program. * * * ******************************************************************************/ #include <stdio.h> #include <math.h> /* * The following scaling algorithm is taken from C. R. Lewart, * algorithm #463, CACM Volume 16, 10 (October 1973) pp. 639-640. */ /* * Given min, max, and n, linear_scale finds a new range * minPtr, maxPtr divisible into approximately n linear intervals * of size intervalPtr. Vint is an array of acceptable values for * the interval (times an integer power of 10). * Sqr is an array of geometric means of adjacent values of vint, it * is used as break points to determine which vint value to assign * to intervalPtr. * Del accounts for computer roundoff. Del should be greater than the * round-off expected from a division and float operation, it should be less * than the minimum increment of the plotting device used by the main program * (in.) divided by the plot size (in.) times number of intervals n. */ static double Del = 0.00002; linear_scale (min, max, n, minPtr, maxPtr, intervalPtr) double min; double max; register int n; double *minPtr; double *maxPtr; double *intervalPtr; { double a; double b; double dist; double fm1; double fm2; double maxp; double minp; int m1; int m2; int nal; register int i; static double Vint[] = {1.0, 5.0, 10.0}; /* Sqr[i] = sqrt (Vint[i] * Vint[i + 1]) */ static double Sqr[] = {2.236068, 7.071068}; /* Check whether proper input values were supplied */ if (min >= max || n <= 0) { return (-1); } /* Find an approximate interval size */ a = (max - min) / n; nal = (int)log10 (a); /* A is scaled into variable named b between 1 and 10 */ if (a < 1.0) { nal -= 1; } b = a / pow (10.0, (double)nal); /* The closest permissible value for b is found */ for (i = 0; i < sizeof (Sqr) / sizeof (Sqr[0]); i++) { if (b < Sqr[i]) { break; } } /* The interval size is computed */ dist = Vint[i] * pow (10.0, (double)nal); m1 = fm1 = min / dist; if (fm1 < 0.0) { m1 -= 1; } if (abs ((double)m1 + 1.0 - fm1) < Del) { m1 += 1; } /* The new minimum and maximum limits are found */ minp = dist * (double)m1; m2 = (int)(fm2 = max / dist) + 1; if (fm2 < -1.0) { m2 -= 1; } if (abs (fm2 + 1.0 - (double)m2) < Del) { m2 -= 1; } maxp = dist * (double)m2; /* Adjust limits to account for round-off if necessary */ if (minp > min) { minp = min; } if (maxp < max) { maxp = max; } *minPtr = minp; *maxPtr = maxp; *intervalPtr = dist; return (0); } /* * Given min, max, and n, where n is greater than 1, log_scale * finds a new range, minPtr and maxPtr divisible into exactly * n logarithmic intervals, where the ratio of adjacent uniformly * spaced scale values is *intervalPtr. */ log_scale (min, max, n, minPtr, maxPtr, intervalPtr) double min; double max; register int n; double *minPtr; double *maxPtr; double *intervalPtr; { double a; double distl; double fm1; double minl; double maxl; int m1; /* Check whether proper input values were supplied */ if (min >= max || min <= 0.0 || n < 1) { fprintf (stderr, "log_scale: Invalid parameters (%g, %g, %d)\n", min, max, n); return (-1); } /* Translate min and max to logarithmic values */ minl = log10 (min); maxl = log10 (max); /* Find approximate interval size (lower bound) */ a = (maxl - minl) / (double)n; /* Make sure the interval is an even power of 10 */ if (a < 0.0) { distl = floor (a); } else { distl = ceil (a); } fm1 = minl / distl; m1 = fm1; if (fm1 < 0.0) { m1 -= 1; } if (fabs ((double)m1 + 1.0 - fm1) < Del) { m1 += 1; } *minPtr = distl * (double)m1; do { *maxPtr = *minPtr + (double)n * distl; n -= 1; } while (n > 0 && *minPtr + (double)n * distl > maxl); /* Now translate from logarithmic to linear region */ *intervalPtr = pow (10.0, distl); *minPtr = pow (10.0, *minPtr); *maxPtr = pow (10.0, *maxPtr); /* Finally, adjust the limits to account for roundoff (if necessary) */ if (*minPtr > min) { *minPtr = min; } if (*maxPtr < max) { *maxPtr = max; } return (0); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.