ftp.nice.ch/pub/next/unix/developer/pcn.2.0.s.tar.gz#/contrib/gauge/Xsw/fscale.c

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 Marcel Waldvogel and Netfuture.ch.