#### /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
42
44		Fixed ret = new Fixed(_whole, _scale);
45		ret += fixed;
46		return ret;
47	}
48
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}
```