/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. module math.integer;
  11. import core.string;
  12. import core.definitions;
  13. // Description: This class represents an integer value.
  14. class Integer {
  15. this() {
  16. _value = [0];
  17. }
  18. this(ulong value, ulong[] values...) {
  19. _value = values.reverse ~ [value];
  20. }
  21. this(Integer i) {
  22. _value = i._value.dup;
  23. _negative = i._negative;
  24. }
  25. Integer opAdd(Integer i) {
  26. Integer ret = new Integer(this);
  27. ret += i;
  28. return ret;
  29. }
  30. Integer opAdd(long i) {
  31. Integer ret = new Integer(this);
  32. ret += i;
  33. return ret;
  34. }
  35. void add(Integer i, bool suppressCarry = false) {
  36. uint idx;
  37. ulong sum;
  38. bool carry;
  39. for ( ; idx < _value.length; idx++) {
  40. if (idx >= i._value.length) {
  41. sum = _value[idx];
  42. }
  43. else {
  44. sum = _value[idx] + i._value[idx];
  45. }
  46. if (carry) {
  47. sum++;
  48. carry = false;
  49. }
  50. if (sum < _value[idx]) {
  51. // overflow
  52. carry = true;
  53. }
  54. _value[idx] = sum;
  55. }
  56. for ( ; idx < i._value.length; idx++) {
  57. sum = i._value[idx];
  58. if (carry) {
  59. sum++;
  60. carry = false;
  61. }
  62. if (sum < i._value[idx]) {
  63. // overflow
  64. carry = true;
  65. }
  66. _value ~= [sum];
  67. }
  68. if (carry && !suppressCarry) {
  69. _value ~= [1];
  70. }
  71. }
  72. void opAddAssign(Integer i) {
  73. add(i);
  74. }
  75. void opAddAssign(long i) {
  76. bool carry;
  77. if (_value.length == 0) {
  78. _value = [i];
  79. return;
  80. }
  81. foreach (size_t idx, value; _value) {
  82. ulong newValue = value + i;
  83. if (newValue < value) {
  84. _value[idx] = newValue;
  85. carry = true;
  86. return;
  87. }
  88. _value[idx] = newValue;
  89. }
  90. if (carry) {
  91. _value ~= [1];
  92. }
  93. }
  94. Integer opSub(Integer i) {
  95. Integer ret = new Integer(this);
  96. ret -= i;
  97. return ret;
  98. }
  99. void opSubAssign(Integer i) {
  100. // two's complement
  101. i = ~i;
  102. i += 1;
  103. // add
  104. add(i, true);
  105. }
  106. Integer opCom() {
  107. Integer ret = new Integer(this);
  108. foreach(ref value; ret._value) {
  109. value = ~value;
  110. }
  111. return ret;
  112. }
  113. Integer opNeg() {
  114. Integer ret = new Integer(this);
  115. ret = ~ret;
  116. ret += 1;
  117. return ret;
  118. }
  119. size_t length() {
  120. if (_value.length == 0) {
  121. return 0;
  122. }
  123. return cast(size_t)((_value.length * 64) - (64 - _bitoffset));
  124. }
  125. string toString() {
  126. string ret;
  127. foreach_reverse(value; _value) {
  128. string section = "{x}".format(value);
  129. int zeroLength = 16 - section.length;
  130. if (ret !is null) {
  131. ret ~= "0000000000000000"c[0..zeroLength];
  132. }
  133. ret ~= section;
  134. }
  135. return ret;
  136. }
  137. private:
  138. ulong[] _value;
  139. ulong _bitoffset;
  140. bool _negative;
  141. }