Jakowlew

Rational<T>

Dec 5th, 2020
749
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #ifndef CUMMAS_RATIONAL_H
  2. #define CUMMAS_RATIONAL_H
  3.  
  4. #include <iostream>
  5. #include <cmath>
  6. #include <string>
  7. #include <sstream>
  8. #include <random>
  9. #include <type_traits>
  10.  
  11. #include <common.cuh>
  12.  
  13. template <typename T>
  14. class Rational
  15. {
  16. public:
  17.     constexpr __host__ __device__ Rational() = default;
  18.     constexpr __host__ __device__ Rational(
  19.         T num /*= static_cast<T>(0)*/,
  20.         T den/* = static_cast<T>(1)*/) noexcept:
  21.         num{num},
  22.         den{den}
  23.     {
  24.         static_assert(std::is_integral_v<T> && std::is_signed_v<T>, "Underlying type must be of integral type");
  25.         Make();
  26.     }
  27.  
  28.     constexpr __host__ __device__ void Make() noexcept
  29.     {
  30.         // See https://godbolt.org/z/jeK5z7 for optimisations
  31.         // make5 is significally faster (no conditionals),
  32.         // but relies on the fact that last bit is a sign bit
  33.         if (den < 0)
  34.         {
  35.             num = -num;
  36.             den = -den;
  37.         }
  38.     }
  39.  
  40.     #pragma region operators
  41.     template <typename T>
  42.     friend std::ostream& operator << (std::ostream& , Rational<T> const&) noexcept;
  43.     template <typename T>
  44.     friend std::istream& operator >> (std::istream& , Rational<T>&) noexcept;
  45.    
  46.     template <typename T>
  47.     constexpr __host__ __device__ friend Rational<T> const operator + (Rational<T> const& lhs, Rational<T> const& rhs) noexcept;
  48.     template <typename T>
  49.     constexpr __host__ __device__ friend Rational<T> const operator - (Rational<T> const&, Rational<T> const&) noexcept;
  50.     template <typename T>
  51.     constexpr __host__ __device__ friend Rational<T> const operator* (Rational<T> const&, Rational<T> const&) noexcept;
  52.     template <typename T>
  53.     constexpr __host__ __device__ friend Rational<T> const operator/ (Rational<T> const&, Rational<T> const&) noexcept;
  54.    
  55.    
  56.     template <typename T>
  57.     constexpr __host__ __device__ friend bool operator < (Rational<T> const&, Rational<T> const&) noexcept;
  58.     template <typename T>
  59.     constexpr __host__ __device__ friend bool operator == (Rational<T> const&, Rational<T> const&) noexcept;
  60.     template <typename T>
  61.     constexpr __host__ __device__ friend bool operator > (Rational<T> const&, Rational<T> const&) noexcept;
  62.     template <typename T>
  63.     constexpr __host__ __device__ friend bool operator <= (Rational<T> const&, Rational<T> const&) noexcept;
  64.     template <typename T>
  65.     constexpr __host__ __device__ friend bool operator >= (Rational<T> const&, Rational<T> const&) noexcept;
  66.     template <typename T>
  67.     constexpr __host__ __device__ friend bool operator != (Rational<T> const&, Rational<T> const&) noexcept;
  68.     #pragma endregion
  69.  
  70.     template <typename T>
  71.     constexpr __host__ __device__ friend Rational<T> const fabs (Rational<T> const&) noexcept;
  72.     template <typename T>
  73.     constexpr __host__ __device__ friend Rational<T> const gcd (Rational<T> const&) noexcept;
  74.     template <typename T>
  75.     __host__ friend Rational<T> const random(Rational<T> const&) noexcept;
  76. private:
  77.     int num, den;
  78. };
  79.  
  80. #pragma region constants
  81. template <typename T>
  82. struct Id<Rational<T>>
  83. {
  84.     constexpr static Rational<T> value{Rational<T>{1, 1}};
  85. };
  86.  
  87. template <typename T>
  88. struct Zero<Rational<T>>
  89. {
  90.     constexpr static Rational<T> value{Rational<T>{0, 1}};
  91. };
  92.  
  93. template <typename T>
  94. struct mId<Rational<T>>
  95. {
  96.     constexpr static Rational<T> value{Rational<T>{-1, 1}};
  97. };
  98. #pragma endregion
  99.  
  100. #pragma region operators
  101. template <typename T>
  102. [[nodiscard]] constexpr __host__ __device__ Rational<T> const gcd (Rational<T> const& lhs) noexcept
  103. {
  104.     if (lhs.num==0)
  105.         return Rational<T>(0, 1);
  106.     int a=abs(lhs.num);
  107.     int b=abs(lhs.den);
  108.     while (a != b)
  109.     {
  110.         if (a > b)
  111.         {
  112.             int tmp = a;
  113.             a = b;
  114.             b = tmp;
  115.         }
  116.         b = b - a;
  117.     }
  118.  
  119.     return Rational<T>(lhs.num/a, lhs.den/a);
  120. }
  121.  
  122. template <typename T>
  123. [[nodiscard]] std::ostream& operator <<(std::ostream& ost, Rational<T> const& r) noexcept
  124. {
  125.     return ost << r.num << '/' << r.den;
  126. }
  127.  
  128. template <typename T>
  129. [[nodiscard]] std::istream& operator>>(std::istream& ist, Rational<T>& r) noexcept// e.g. (5, -2)
  130. {
  131.     std::string s;
  132.     std::getline(ist, s, ')');
  133.     std::string::size_type ind;
  134.     while((ind = s.find_first_of("(,)")) != std::string::npos)
  135.         s.replace(ind, 1, 1, ' ');
  136.     std::istringstream iss(s);
  137.     iss >> r.num >> r.den;
  138.     r.Make();
  139.     return ist;
  140. }
  141.  
  142. template <typename T>
  143. [[nodiscard]] __host__ Rational<T> const random(Rational<T> const& lhs) noexcept
  144. {
  145.     std::random_device random_device; // Entropy source
  146.     std::mt19937 generator(random_device());
  147.     std::uniform_int_distribution<> distribution(lhs.num, lhs.den);
  148.     return gcd(Rational<T>(distribution(generator), 1));
  149. }
  150.  
  151. template <typename T>
  152. [[nodiscard]] constexpr __host__ __device__ Rational<T> const fabs (Rational<T> const& lhs) noexcept
  153. {
  154.     return gcd(Rational<T>(abs(lhs.num), abs(lhs.den)));
  155. }
  156.  
  157. template <typename T>
  158. [[nodiscard]] constexpr __host__ __device__ Rational<T> const operator + (Rational<T> const& lhs, Rational<T> const& rhs) noexcept
  159. {
  160.     return gcd(Rational<T>(lhs.num * rhs.den + rhs.num * lhs.den, lhs.den * rhs.den));
  161. }
  162.  
  163. template <typename T>
  164. [[nodiscard]] constexpr __host__ __device__ Rational<T> const operator - (Rational<T> const& lhs, Rational<T> const& rhs) noexcept
  165. {
  166.     return gcd(lhs + Rational<T>(-rhs.num, rhs.den));
  167. }
  168.  
  169. template <typename T>
  170. [[nodiscard]] constexpr __host__ __device__ Rational<T> const operator * (Rational<T> const& lhs, Rational<T> const& rhs) noexcept
  171. {
  172.     return gcd(Rational<T>(lhs.num * rhs.num, lhs.den * rhs.den));
  173. }
  174.  
  175. template <typename T>
  176. [[nodiscard]] constexpr __host__ __device__ Rational<T> const operator / (Rational<T> const& lhs, Rational<T> const& rhs) noexcept
  177. {
  178.     return gcd(lhs * Rational<T>(rhs.den, rhs.num));
  179. }
  180.  
  181. template <typename T>
  182. [[nodiscard]] constexpr __host__ __device__ bool operator < (Rational<T> const& lhs, Rational<T> const& rhs) noexcept
  183. {
  184.     return double(lhs.num) / lhs.den < double(rhs.num) / rhs.den;
  185. }
  186.  
  187. template <typename T>
  188. [[nodiscard]] constexpr __host__ __device__ bool operator == (Rational<T> const& lhs, Rational<T> const& rhs) noexcept
  189. {
  190.     return !(lhs < rhs || rhs < lhs);
  191. }
  192.  
  193. template <typename T>
  194. [[nodiscard]] constexpr __host__ __device__ bool operator != (Rational<T> const& lhs, Rational<T> const& rhs) noexcept
  195. {
  196.     return (lhs < rhs || rhs < lhs);
  197. }
  198.  
  199. template <typename T>
  200. [[nodiscard]] constexpr __host__ __device__ bool operator> (Rational<T> const& lhs, Rational<T> const& rhs) noexcept
  201. {
  202.     return rhs < lhs;
  203. }
  204.  
  205. template <typename T>
  206. [[nodiscard]] constexpr __host__ __device__ bool operator<= (Rational<T> const& lhs, Rational<T> const& rhs) noexcept
  207. {
  208.     return !(rhs < lhs);
  209. }
  210.  
  211. template <typename T>
  212. [[nodiscard]] constexpr __host__ __device__ bool operator>= (Rational<T> const& lhs, Rational<T> const& rhs) noexcept
  213. {
  214.     return !(lhs < rhs);
  215. }
  216. #pragma endregion
  217.  
  218. #endif // CUMMAS_Rational<T>_H
  219.  
RAW Paste Data