fork download
  1. #include <iostream>
  2. #include <cmath>
  3. #include <type_traits>
  4. #include <complex>
  5.  
  6. /* Common metafunctions: */
  7.  
  8. template<typename T>
  9. struct zero;
  10.  
  11. template<typename T>
  12. struct one;
  13.  
  14.  
  15. template<typename LHS , typename RHS>
  16. struct add;
  17.  
  18. template<typename LHS , typename RHS>
  19. struct sub;
  20.  
  21. template<typename LHS , typename RHS>
  22. struct mul;
  23.  
  24.  
  25. template<int base , int exponent>
  26. struct positive_pow : public std::integral_constant<long long int , base * positive_pow<base,exponent-1>::value> {};
  27.  
  28. template<int base>
  29. struct positive_pow<base,0> : public std::integral_constant<long long int,1> {};
  30.  
  31. template<long long int number , int shift>
  32. struct decimal_leftshift : public std::integral_constant<long long int,number * positive_pow<10, shift>::value> {};
  33.  
  34. template<long long int number , int shift>
  35. struct decimal_rightshift : public std::integral_constant<long long int,number / positive_pow<10, shift>::value> {};
  36.  
  37. template<bool CONDITION , int NUMBER , int SHIFT>
  38. struct decimal_shift_chooser
  39. {
  40. using shifter = decimal_leftshift<NUMBER,SHIFT>;
  41. };
  42.  
  43. template<long long NUMBER , int SHIFT>
  44. struct decimal_shift_chooser<false,NUMBER,SHIFT>
  45. {
  46. using shifter = decimal_rightshift<NUMBER,-SHIFT>;
  47. };
  48.  
  49. template<int number , int shift>
  50. struct decimal_shift
  51. {
  52. using shifter = typename decimal_shift_chooser<( shift >= 0 ) , number , shift>::shifter;
  53. static const long long int value = shifter::value;
  54. };
  55.  
  56. /* Fixed-point implementation: */
  57.  
  58. using fpbits = long long int;
  59. using fbcount = unsigned int; //Fractional bits count (Precision)
  60.  
  61. const fbcount DEFAULT_FRACTIONAL_PRECISION = 8;
  62.  
  63. template<fpbits BITS , fbcount PRECISION = DEFAULT_FRACTIONAL_PRECISION>
  64. struct fixed_point
  65. {
  66. operator float()
  67. {
  68. return (float)BITS * std::pow(10.0f,-(float)PRECISION);
  69. };
  70. };
  71.  
  72. template<int mantissa , int exponent = 0> // MANTISSA x 10^EXPONENT
  73. using decimal = fixed_point<decimal_shift<mantissa , DEFAULT_FRACTIONAL_PRECISION + exponent>::value>;
  74.  
  75.  
  76. template<fpbits BITS , fbcount PRECISION>
  77. struct zero<fixed_point<BITS,PRECISION>> : public fixed_point<0,PRECISION> {};
  78.  
  79. template<fpbits BITS , fbcount PRECISION>
  80. struct one<fixed_point<BITS,PRECISION>> : public fixed_point<decimal_leftshift<1,PRECISION>::value,PRECISION> {};
  81.  
  82.  
  83. template<fpbits BITS1 , fpbits BITS2 , fbcount PRECISION>
  84. struct add<fixed_point<BITS1,PRECISION> , fixed_point<BITS2,PRECISION>> : public fixed_point<BITS1+BITS2 , PRECISION> {};
  85.  
  86. template<fpbits BITS1 , fpbits BITS2 , fbcount PRECISION>
  87. struct sub<fixed_point<BITS1,PRECISION> , fixed_point<BITS2,PRECISION>> : public fixed_point<BITS1-BITS2 , PRECISION> {};
  88.  
  89. template<fpbits BITS1 , fpbits BITS2 , fbcount PRECISION>
  90. struct mul<fixed_point<BITS1,PRECISION> , fixed_point<BITS2,PRECISION>> : public fixed_point<decimal_rightshift<BITS1*BITS2,PRECISION>::value , PRECISION> {};
  91.  
  92.  
  93. /* Example: */
  94.  
  95. using pi = decimal<3141592 , -6>; //3141592 x 10^-6 (3,141592)
  96. using pi_2 = mul<pi,decimal<2>>;
  97.  
  98. using a = decimal<1,-3>;
  99. using b = decimal<1,3>;
  100.  
  101. using c = mul<a,b>;
  102. using d = sub<b,a>;
  103. using e = add<a,b>;
  104.  
  105. int main()
  106. {
  107. std::cout << "pi: " << pi() << std::endl;
  108. std::cout << "2*pi: " << pi_2() << std::endl;
  109.  
  110. std::cout << "a: " << a() << std::endl;
  111. std::cout << "b: " << b() << std::endl;
  112. std::cout << "a*b: " << c() << std::endl;
  113. std::cout << "b-a: " << d() << std::endl;
  114. std::cout << "a+b: " << e() << std::endl;
  115. }
Success #stdin #stdout 0s 3296KB
stdin
Standard input is empty
stdout
pi: 3.14159
2*pi: 6.28318
a: 0.001
b: 1000
a*b: 1
b-a: 999.999
a+b: 1000