view src/decimal/context.d @ 0:42cf4db6be32

Creation
author Paul (paul.d.anderson@comcast.net)
date Sat, 13 Mar 2010 13:22:25 -0800
parents
children abf9d7974708
line wrap: on
line source

module decimal.context;

import decimal.decimal;
import std.string;

//--------------------------
//
// DecimalContext struct
//
//--------------------------

/**
 * Enumeration of available rounding modes.
 */
public enum Rounding {
	HALF_EVEN,
	HALF_DOWN,
	HALF_UP,
	DOWN,
	UP,
	FLOOR,
	CEILING,
}


// context flags
public enum : ubyte {
 	 CLAMPED           = 0x01,
 	 DIVISION_BY_ZERO  = 0x02,
 	 INEXACT           = 0x04,
 	 INVALID_OPERATION = 0x08,
 	 OVERFLOW          = 0x10,
 	 ROUNDED           = 0x20,
 	 SUBNORMAL         = 0x40,
 	 UNDERFLOW         = 0x80
}
	
/+public:
 	static immutable ubyte CLAMPED           = 0x01;
 	static immutable ubyte DIVISION_BY_ZERO  = 0x02;
 	static immutable ubyte INEXACT           = 0x04;
 	static immutable ubyte INVALID_OPERATION = 0x08;
 	static immutable ubyte OVERFLOW          = 0x10;
 	static immutable ubyte ROUNDED           = 0x20;
 	static immutable ubyte SUBNORMAL         = 0x40;
 	static immutable ubyte UNDERFLOW         = 0x80;+/

/**
 * Context for Decimal mathematic operations
 */
public struct DecimalContext {
	public:
		Rounding mode = Rounding.HALF_EVEN;
		uint precision = 9;
		ubyte traps;
		ubyte flags;
		int eMin = -98;
		int eMax = 99;
	
	const int eTiny() {
		return eMin - (precision - 1);
	}
	
	/// Returns the number of decimal digits in this context.
	const uint dig() {
		return precision;
	}
	
	/// returns the smallest available increment to one in this context
	const Decimal epsilon() {
		return Decimal(1,-precision);
	}
		
	/// Returns the number of binary digits in this context.
	const int mant_dig() {
		return cast(int)(precision/LOG2);
	}

	const int min_exp() {
		return cast(int)(eMin/LOG2);
	}
	
	const int max_exp() {
		return cast(int)(eMax/LOG2);
	}
	
	const int min_10_exp() {
		return eMin;
	}
	
	const int max_10_exp() {
		return eMax;
	}
	
	/// Returns the maximum representable normal value in the current context.
	// TODO: Replace this formula with a single execution when precision or eMax is changed.
	const Decimal max() {
		string cstr = "9." ~ repeat("9", precision-1) ~ "E" ~ format("%d", eMax);
		return Decimal(cstr);
	}
	
	// Returns the minimum representable normal value in the current context.
	const Decimal min_normal() {
		return Decimal(1, eMin);
	}
	
	// Returns the minimum representable subnormal value in the current context.
	const Decimal min() {
		return Decimal(1, eTiny);
	}
	
/+	public const int getPrecision() {
		return precision;
	}
	
	public void setPrecision(int precision) {
		this.precision = precision;
	}+/
	
	const void setFlag(const ubyte flag, const bool value = true) {
		if (value) {
		 context.flags |= flag; 
		}
		else {
		  context.flags &= !flag;
        }
	}
	
	public bool getFlag(const ubyte flag) {
		return (context.flags & flag) == flag;
	}
	
	public void clearFlags() {
		context.flags = 0;
	}
	

};	// end struct DecimalContext

public:
	// default context
	immutable DecimalContext DEFAULT_CONTEXT = DecimalContext();
	
private:
	// context stack
struct ContextStack {
	private:
		DecimalContext[] stack = [ DEFAULT_CONTEXT ];
		uint capacity = 1;
		uint count = 1;

	public void push() {
		if (count >= capacity) {
			capacity *= 2;
			stack.length = capacity;
		}
		count++;
		stack[count-1] = context;
	}
	
	public void pop() {
		if (count == 0) {
			push();
		}
		if (count == 1) {
			context = stack[0];
		}
		else {
			count--;
			context = stack[count-1];
		}
	}
	
} // end struct ContextStack

//--------------------------
//
// Emd of DecimalContext struct
//
//--------------------------