#### /math/integer.d

http://github.com/wilkie/djehuty
D | 171 lines | 127 code | 30 blank | 14 comment | 17 complexity | cc155e9531e002e4b3e6e8cae843d223 MD5 | raw file
```  1/*
2 * integer.d
3 *
4 * This module implements a flexible integer type.
5 *
6 * Author: Dave Wilkinson
7 * Originated: August 11th, 2009
8 *
9 */
10
11module math.integer;
12
13import core.string;
14import core.definitions;
15
16// Description: This class represents an integer value.
17class Integer {
18	this() {
19		_value = [0];
20	}
21
22	this(ulong value, ulong[] values...) {
23		_value = values.reverse ~ [value];
24	}
25
26	this(Integer i) {
27		_value = i._value.dup;
28		_negative = i._negative;
29	}
30
32		Integer ret = new Integer(this);
33		ret += i;
34		return ret;
35	}
36
38		Integer ret = new Integer(this);
39		ret += i;
40		return ret;
41	}
42
43	void add(Integer i, bool suppressCarry = false) {
44		uint idx;
45		ulong sum;
46		bool carry;
47		for ( ; idx < _value.length; idx++) {
48			if (idx >= i._value.length) {
49				sum = _value[idx];
50			}
51			else {
52				sum = _value[idx] + i._value[idx];
53			}
54
55			if (carry) {
56				sum++;
57				carry = false;
58			}
59
60			if (sum < _value[idx]) {
61				// overflow
62				carry = true;
63			}
64
65			_value[idx] = sum;
66		}
67
68		for ( ; idx < i._value.length; idx++) {
69			sum = i._value[idx];
70
71			if (carry) {
72				sum++;
73				carry = false;
74			}
75
76			if (sum < i._value[idx]) {
77				// overflow
78				carry = true;
79			}
80
81			_value ~= [sum];
82		}
83
84		if (carry && !suppressCarry) {
85			_value ~= [1];
86		}
87	}
88
91	}
92
94		bool carry;
95
96		if (_value.length == 0) {
97			_value = [i];
98			return;
99		}
100
101		foreach (size_t idx, value; _value) {
102			ulong newValue = value + i;
103			if (newValue < value) {
104				_value[idx] = newValue;
105				carry = true;
106				return;
107			}
108			_value[idx] = newValue;
109		}
110
111		if (carry) {
112			_value ~= [1];
113		}
114	}
115
116	Integer opSub(Integer i) {
117		Integer ret = new Integer(this);
118		ret -= i;
119		return ret;
120	}
121
122	void opSubAssign(Integer i) {
123		// two's complement
124		i = ~i;
125		i += 1;
126
129	}
130
131	Integer opCom() {
132		Integer ret = new Integer(this);
133		foreach(ref value; ret._value) {
134			value = ~value;
135		}
136		return ret;
137	}
138
139	Integer opNeg() {
140		Integer ret = new Integer(this);
141		ret = ~ret;
142		ret += 1;
143		return ret;
144	}
145
146	size_t length() {
147		if (_value.length == 0) {
148			return 0;
149		}
150		return cast(size_t)((_value.length * 64) - (64 - _bitoffset));
151	}
152
153	string toString() {
154		string ret;
155		foreach_reverse(value; _value) {
156			string section = "{x}".format(value);
157			int zeroLength = 16 - section.length;
158			if (ret !is null) {
159				ret ~= "0000000000000000"c[0..zeroLength];
160			}
161			ret ~= section;
162		}
163		return ret;
164	}
165
166private:
167
168	ulong[] _value;
169	ulong _bitoffset;
170	bool _negative;
171}
```