// Copyright 1999
// College of Computer Science
// Northeastern University Boston MA 02115

// This software may be used for educational purposes as long as this copyright
// notice is retained at the top of all files

// Should this software be modified, the words "Modified from Original" must be
// included as a comment below this notice

// All publication rights are retained.  This software or its documentation may
// not be published in any media either in whole or in part.

///////////////////////////////////////////////////////////////////////////////

//	Scale.h

///////////////////////////////////////////////////////////////////////////////

#ifndef SCALE_H_
#define SCALE_H_

#include "MathUtil.h"


// abstract base class for scale operation

class EXPORT Scale {
	// no data in this abstract base class
	
public:
	// a scale class must have an operator() that takes a double to a short
	virtual short operator() (double) const = 0;
	
	// a scale class must have an inverse function to its operator()
	virtual double Inverse(short) const = 0;
};


// class to define a linear scale function

class EXPORT LinearScale : public Scale {
	// scaling transform:  t ---> round(factor * t + offset)
	// force factor to be non-zero
	
	double factor;		// scale factor
	double offset;		// scale offset
	
public:
	// set functions

	// set: supply factor and offset
	LinearScale& Set(double Factor, double Offset) {
		// set values
		factor = Factor;
		offset = Offset;
		
		// force factor to be non-zero
		if (factor == 0) factor = 1;

		return *this;
	};
	
	// set: map interval a, b to ia, ib
	LinearScale& Set(double a, double b, short ia, short ib);
	
	
	// constructors
	
	// default
	LinearScale() : factor(1), offset(0) { };
	
	// supply factor and offset
	LinearScale(double Factor, double Offset)
		{ Set(Factor, Offset); };
	
	// map interval a, b to ia, ib
	LinearScale(double a, double b, short ia, short ib)
		{ Set(a, b, ia, ib); };
	
	
	// scaling transform operator
	short operator() (double t) const {
		return SafeRoundToShort(factor * t + offset);
	};
	
	// scaling inverse transform operator
	double Inverse(short s) const {
		return (double(s) - offset) / factor;
	};
};


// class to define a log-linear scale function

class EXPORT LogScale : public Scale {
	// scaling transform:  t ---> S(log(t))  where
	// 		S is a linear scale
	//		log is the C library natural logarithm
	
	LinearScale S;

public:
	// set functions

	// set: supply factor and offset
	LogScale& Set(double Factor, double Offset) {
		S.Set(Factor, Offset);

		return *this;
	};
	
	// set: map interval a, b to ia, ib
	LogScale& Set(double a, double b, short ia, short ib);
	
	
	// constructors
	
	// default
	LogScale() : S() { };
	
	// supply factor and offset
	LogScale(double Factor, double Offset) : S(Factor, Offset) { };
	
	// map interval a, b to ia, ib
	LogScale(double a, double b, short ia, short ib)
		{ Set(a, b, ia, ib); };
	
	
	// scaling transform operator
	short operator() (double t) const {
		// error if t <= 0 since logarithm is invalid
		if (t <= 0)
			throw string("LogScale transform passed number <= 0");

		// if ok then take logarithm and apply linear scale S
		return S(log(t));
	};

	// scaling inverse transform operator
	double Inverse(short s) const { return exp(S.Inverse(s)); };
};
	

#endif // SCALE_H_