PageRenderTime 36ms CodeModel.GetById 12ms app.highlight 20ms RepoModel.GetById 1ms app.codeStats 0ms

/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
 31	Integer opAdd(Integer i) {
 32		Integer ret = new Integer(this);
 33		ret += i;
 34		return ret;
 35	}
 36
 37	Integer opAdd(long i) {
 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
 89	void opAddAssign(Integer i) {
 90		add(i);
 91	}
 92
 93	void opAddAssign(long i) {
 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
127		// add
128		add(i, true);
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}