An implementation of Q floating point format over C++
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

146 lines
3.2 KiB

пре 6 година
  1. #pragma once
  2. #include <type_traits>
  3. #include <iostream>
  4. #pragma GCC diagnostic push
  5. #pragma GCC diagnostic ignored "-Wnarrowing"
  6. namespace ninefloat{
  7. struct private_t{};
  8. private_t priv;
  9. template<class integer_type, int fractionals>
  10. class Q{
  11. integer_type backend;
  12. static constexpr int degen=fractionals;
  13. constexpr Q (const integer_type value, private_t)
  14. : backend{value}
  15. {{std::cout<<value<< " : "<<backend<<std::endl;}}
  16. public:
  17. template<class srcT>
  18. constexpr Q (const srcT value)
  19. : backend{(integer_type)(value*(1<<degen))}
  20. {std::cout<<value<< " : "<<backend<<std::endl;}
  21. bool constexpr is_negative()
  22. {
  23. return backend&(1<<(sizeof(backend)-1));
  24. }
  25. integer_type constexpr data()
  26. {
  27. return backend;
  28. }
  29. bool constexpr is_positive()
  30. {
  31. return !is_negative();
  32. }
  33. Q constexpr operator+=(const Q& oth)
  34. {
  35. backend+=oth.backend;
  36. return this;
  37. }
  38. Q constexpr operator-=(const Q& oth)
  39. {
  40. backend-=oth.backend;
  41. return this;
  42. }
  43. Q constexpr operator/=(const Q& oth)
  44. {
  45. backend*=1<<Q<integer_type, fractionals>::degen;
  46. backend/=oth.backend;
  47. return this;
  48. }
  49. Q constexpr operator*=(const Q& oth)
  50. {
  51. if constexpr(Q<integer_type, fractionals>::degen%2==0)
  52. {
  53. backend=(backend>>(Q<integer_type, fractionals>::degen/2))*(oth.backend>>(Q<integer_type, fractionals>::degen/2));
  54. }else{
  55. backend=(backend>>(Q<integer_type, fractionals>::degen>>1))*(oth.backend>>((Q<integer_type, fractionals>::degen>>1)+1));
  56. }
  57. return this;
  58. }
  59. Q constexpr operator+(const Q& oth)
  60. {
  61. return Q{backend+oth.backend, priv};
  62. }
  63. Q constexpr operator-(const Q& oth)
  64. {
  65. return Q{backend-oth.backend, priv};
  66. }
  67. Q constexpr operator/(const Q& oth)
  68. {
  69. return Q{(1<<Q<integer_type, fractionals>::degen)*backend/oth.backend, priv};
  70. }
  71. Q constexpr operator*(const Q& oth)
  72. {
  73. if constexpr(Q<integer_type, fractionals>::degen%2==0)
  74. {
  75. return Q{(backend>>(Q<integer_type, fractionals>::degen/2))*(oth.backend>>(Q<integer_type, fractionals>::degen/2)),priv};
  76. }else{
  77. return Q{(backend>>(Q<integer_type, fractionals>::degen>>1))*(oth.backend>>((Q<integer_type, fractionals>::degen>>1)+1)),priv};
  78. }
  79. }
  80. bool constexpr operator==(const Q& oth)
  81. {
  82. return backend == oth.backend;
  83. }
  84. bool constexpr operator!=(const Q& oth)
  85. {
  86. return backend != oth.backend;
  87. }
  88. bool constexpr operator>=(const Q& oth)
  89. {
  90. return backend >= oth.backend;
  91. }
  92. bool constexpr operator<=(const Q& oth)
  93. {
  94. return backend <= oth.backend;
  95. }
  96. bool constexpr operator>(const Q& oth)
  97. {
  98. return backend > oth.backend;
  99. }
  100. bool constexpr operator<(const Q& oth)
  101. {
  102. return backend < oth.backend;
  103. }
  104. constexpr operator float()
  105. {
  106. float n=backend;
  107. n/=(1<<Q<integer_type, fractionals>::degen);
  108. return n;
  109. }
  110. constexpr operator double()
  111. {
  112. double n=backend;
  113. n/=(1<<Q<integer_type, fractionals>::degen);
  114. return n;
  115. }
  116. };
  117. #pragma GCC diagnostic pop
  118. }