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.