PageRenderTime 64ms CodeModel.GetById 28ms app.highlight 30ms RepoModel.GetById 2ms app.codeStats 0ms

/math/fixed.d

http://github.com/wilkie/djehuty
D | 143 lines | 104 code | 28 blank | 11 comment | 10 complexity | 2e9ad3386a0bbb910638037ab2509792 MD5 | raw file
  1/*
  2 * fixed.d
  3 *
  4 * This module implements a fixed point type.
  5 *
  6 * Author: Dave Wilkinson
  7 * Originated: August 11th, 2009
  8 *
  9 */
 10
 11module math.fixed;
 12
 13import djehuty;
 14
 15// Description: This class provides a fixed point arithmetic type.
 16class Fixed {
 17
 18	this(long whole, long scale) {
 19		_whole = whole;
 20		_scale = scale;
 21	}
 22
 23	this(double value) {
 24		string val = toStr(value);
 25		int pos = val.find(".");
 26
 27		if (pos >= 0) {
 28			_scale = val.length - pos - 1;
 29			val = val[0..pos] ~ val[pos+1..$];
 30		}
 31		else {
 32			if (val == "inf" || val == "nan") {
 33				throw new Exception("Invalid Input");
 34			}
 35			_scale = 0;
 36		}
 37
 38		val.nextInt(_whole);
 39	}
 40
 41	// Operator Overloads
 42
 43	Fixed opAdd(Fixed fixed) {
 44		Fixed ret = new Fixed(_whole, _scale);
 45		ret += fixed;
 46		return ret;
 47	}
 48
 49	void opAddAssign(Fixed fixed) {
 50		while(fixed._scale > _scale) {
 51			_whole *= 10;
 52			_scale++;
 53		}
 54
 55		long operand_whole = fixed._whole;
 56		long operand_scale = fixed._scale;
 57		while(_scale > operand_scale) {
 58			operand_whole *= 10;
 59			operand_scale++;
 60		}
 61
 62		_whole += operand_whole;
 63	}
 64
 65	string toString() {
 66		string ret;
 67		string part = toStr(_whole);
 68
 69		if (part.length <= _scale) {
 70			ret = "0.";
 71			ret ~= part;
 72		}
 73		else {
 74			ret = part[0..cast(size_t)(part.length - _scale)].dup;
 75			ret ~= ".";
 76			ret ~= part[cast(size_t)(part.length - _scale)..part.length];
 77		}
 78
 79		return ret;
 80	}
 81
 82	Fixed opSub(Fixed fixed) {
 83		Fixed ret = new Fixed(_whole, _scale);
 84		ret -= fixed;
 85		return ret;
 86	}
 87
 88	void opSubAssign(Fixed fixed) {
 89		while(fixed._scale > _scale) {
 90			_whole *= 10;
 91			_scale++;
 92		}
 93
 94		long operand_whole = fixed._whole;
 95		long operand_scale = fixed._scale;
 96		while(_scale > operand_scale) {
 97			operand_whole *= 10;
 98			operand_scale++;
 99		}
100
101		_whole -= operand_whole;
102	}
103
104	Fixed opMul(Fixed fixed) {
105		Fixed ret = new Fixed(_whole, _scale);
106		ret *= fixed;
107		return ret;
108	}
109
110	void opMulAssign(Fixed fixed) {
111		_whole *= fixed._whole;
112		_scale += fixed._scale;
113	}
114
115	Fixed opDiv(Fixed fixed) {
116		Fixed ret = new Fixed(_whole, _scale);
117		ret /= fixed;
118		return ret;
119	}
120
121	void opDivAssign(Fixed fixed) {
122		long argmax_scale = _scale;
123
124		if (fixed._scale > _scale) {
125			argmax_scale = fixed._scale;
126		}
127
128		long argmax_scale_sq = argmax_scale * argmax_scale;
129		argmax_scale_sq *= 2;
130
131		_scale = argmax_scale_sq;
132		
133		while (argmax_scale_sq > 0) {
134			_whole *= 10;
135			argmax_scale_sq--;
136		}
137		_whole /= fixed._whole;
138	}
139
140protected:
141	long _whole;
142	long _scale;
143}