//-----------------------------------------------------------------------------
// Copyright © 2004 - Philip Howard - All rights reserved
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
//-----------------------------------------------------------------------------
// package	libh/arith
// homepage	http://libh.slashusr.org/
//-----------------------------------------------------------------------------
// author	Philip Howard
// email	libh at ipal dot org
// homepage	http://phil.ipal.org/
//-----------------------------------------------------------------------------
// This file is best viewed using a fixed spaced font such as Courier
// and in a display at least 120 columns wide.
//-----------------------------------------------------------------------------

__FMACRO_BEGIN__
//-----------------------------------------------------------------------------
// macro	rescale
//
// purpose	Given a new linear value range and an old linear value range,
//		rescale a value from the old range to the new range and return
//		the result.
//
// arguments	1 (number) 1st value of new value range
//		2 (number) 2nd value of new value range
//		3 (number) 1st value of old value range
//		4 (number) 2nd value of old value range
//		5 (number) value to be rescaled
//
// yields	(number) value rescaled to new range
//
// note		Ranges can be reversed to invert the scaling.
//
// note		For reasonable results, all arguments should be floating point.
//		However, integers will work to some extent.
//
// note		Values to be rescaled which are outside the old range will be
//		extrapolated linearly outside of the new range.
//-----------------------------------------------------------------------------
#define rescale(na,nz,oa,oz,v) ({						\
	__typeof__(na)	libh__n;						\
	__typeof__(oa)	libh__o;						\
	__typeof__(v)	libh__v;						\
	libh__n = (na);								\
	libh__o = (oa);								\
	libh__v = ( (nz) - libh__n ) * ( (v) - libh__o );			\
	libh__o = (oz) - libh__o;						\
	( libh__v + ( libh__n * libh__o ) ) / libh__o;				\
})

//-----------------------------------------------------------------------------
// macro	rescale0
//
// purpose	Given a new linear value range and an old linear value range
//		which always begins with 0.0, rescale a value from the old
//		range to the new range and return the result.  With the first
//		value of the old range being 0.0, the calculation is slightly
//		less involved.
//
// arguments	1 (number) 1st value of new value range
//		2 (number) 2nd value of new value range
//		3 (number) 2nd value of old value range (1st is zero)
//		4 (number) value to be rescaled
//
// yields	(number) value rescaled to new range
//
// note		Ranges can be reversed to invert the scaling.
//
// note		For reasonable results, all arguments should be floating point.
//		However, integers will work to some extent.
//
// note		Values to be rescaled which are outside the old range will be
//		extrapolated linearly outside of the new range.
//-----------------------------------------------------------------------------
#define rescale0(na,nz,oz,v) ({							\
	__typeof__(na)	libh__n;						\
	__typeof__(oz)	libh__o;						\
	__typeof__(v)	libh__v;						\
	libh__n = (na);								\
	libh__v = ( (nz) - libh__n ) * (v);					\
	libh__o = (oz);								\
	( libh__v + ( libh__n * libh__o ) ) / libh__o;				\
})

__FMACRO_END__

