/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. module math.fixed;
  11. import djehuty;
  12. // Description: This class provides a fixed point arithmetic type.
  13. class Fixed {
  14. this(long whole, long scale) {
  15. _whole = whole;
  16. _scale = scale;
  17. }
  18. this(double value) {
  19. string val = toStr(value);
  20. int pos = val.find(".");
  21. if (pos >= 0) {
  22. _scale = val.length - pos - 1;
  23. val = val[0..pos] ~ val[pos+1..$];
  24. }
  25. else {
  26. if (val == "inf" || val == "nan") {
  27. throw new Exception("Invalid Input");
  28. }
  29. _scale = 0;
  30. }
  31. val.nextInt(_whole);
  32. }
  33. // Operator Overloads
  34. Fixed opAdd(Fixed fixed) {
  35. Fixed ret = new Fixed(_whole, _scale);
  36. ret += fixed;
  37. return ret;
  38. }
  39. void opAddAssign(Fixed fixed) {
  40. while(fixed._scale > _scale) {
  41. _whole *= 10;
  42. _scale++;
  43. }
  44. long operand_whole = fixed._whole;
  45. long operand_scale = fixed._scale;
  46. while(_scale > operand_scale) {
  47. operand_whole *= 10;
  48. operand_scale++;
  49. }
  50. _whole += operand_whole;
  51. }
  52. string toString() {
  53. string ret;
  54. string part = toStr(_whole);
  55. if (part.length <= _scale) {
  56. ret = "0.";
  57. ret ~= part;
  58. }
  59. else {
  60. ret = part[0..cast(size_t)(part.length - _scale)].dup;
  61. ret ~= ".";
  62. ret ~= part[cast(size_t)(part.length - _scale)..part.length];
  63. }
  64. return ret;
  65. }
  66. Fixed opSub(Fixed fixed) {
  67. Fixed ret = new Fixed(_whole, _scale);
  68. ret -= fixed;
  69. return ret;
  70. }
  71. void opSubAssign(Fixed fixed) {
  72. while(fixed._scale > _scale) {
  73. _whole *= 10;
  74. _scale++;
  75. }
  76. long operand_whole = fixed._whole;
  77. long operand_scale = fixed._scale;
  78. while(_scale > operand_scale) {
  79. operand_whole *= 10;
  80. operand_scale++;
  81. }
  82. _whole -= operand_whole;
  83. }
  84. Fixed opMul(Fixed fixed) {
  85. Fixed ret = new Fixed(_whole, _scale);
  86. ret *= fixed;
  87. return ret;
  88. }
  89. void opMulAssign(Fixed fixed) {
  90. _whole *= fixed._whole;
  91. _scale += fixed._scale;
  92. }
  93. Fixed opDiv(Fixed fixed) {
  94. Fixed ret = new Fixed(_whole, _scale);
  95. ret /= fixed;
  96. return ret;
  97. }
  98. void opDivAssign(Fixed fixed) {
  99. long argmax_scale = _scale;
  100. if (fixed._scale > _scale) {
  101. argmax_scale = fixed._scale;
  102. }
  103. long argmax_scale_sq = argmax_scale * argmax_scale;
  104. argmax_scale_sq *= 2;
  105. _scale = argmax_scale_sq;
  106. while (argmax_scale_sq > 0) {
  107. _whole *= 10;
  108. argmax_scale_sq--;
  109. }
  110. _whole /= fixed._whole;
  111. }
  112. protected:
  113. long _whole;
  114. long _scale;
  115. }