units
Use physical dimensions at compile-time or run-time.
normalized-pair.hpp
Go to the documentation of this file.
1 /// @file vnix/rat/normalized-pair.hpp
2 /// @brief Definition of vnix::rat::normalized_pair.
3 /// @copyright 2019 Thomas E. Vaughan; all rights reserved.
4 /// @license BSD Three-Clause; see LICENSE.
5 
6 #ifndef VNIX_RAT_NORMALIZED_PAIR_HPP
7 #define VNIX_RAT_NORMALIZED_PAIR_HPP
8 
9 #include <utility> // for pair
10 #include <vnix/gcd.hpp> // for gcd
11 #include <vnix/int-types.hpp> // for int_types
12 
13 namespace vnix {
14 namespace rat {
15 
16 
17 /// Numerator and denominator of a rational number as separate numbers, not
18 /// encoded into the same word.
19 ///
20 /// These separate numbers are guaranteed to be normalized so that they can be
21 /// encoded into a word of type rational_base<NMR_BITS, DNM_BITS>::US.
22 ///
23 /// @tparam NMR_BITS Number of bits for numerator.
24 /// @tparam DNM_BITS Number of bits for denominator.
25 template <unsigned NMR_BITS, unsigned DNM_BITS> class normalized_pair {
26  // Each type used here is big enough to hold both the numerator and the
27  // denominator of the associated rational number. This will work even when
28  // no bits are assigned to the denominator. Otherwise, there are extra bits
29  // that can handle a pair that are initially far from being relatively prime.
30  using types = int_types<NMR_BITS + DNM_BITS>; ///< Working integer-types.
31  using S = typename types::SF; ///< Fastest large-enough signed type.
32  using U = typename types::UF; ///< Fastest large-enough unsigned type.
33 
34  std::pair<S, U> pair_; ///< Normalized numerator and denominator.
35 
36  /// Normalize numerator and denominator.
37  /// @param n Input numerator.
38  /// @param d Input denominator.
39  /// @return Normalized numerator and denominator.
40  constexpr static std::pair<S, U> pair(S n, S d) {
41  U const g = gcd(n, d);
42  if (d < 0) { return {-n / g, -d / g}; }
43  return {n / g, d / g};
44  }
45 
46 public:
47  /// Initialize normalized numerator and denominator for encoding of rational
48  /// number.
49  ///
50  /// Normalization includes making sure that the denominator is positive,
51  /// that the numerator and denominator are relatively prime, and that each
52  /// fits in its allocation of bits within the word.
53  ///
54  /// @param nn Initial numerator.
55  /// @param dd Initial denominator.
56  constexpr normalized_pair(S nn, S dd) : pair_(pair(nn, dd)) {
57  enum {
58  NMAX = U(1) << (NMR_BITS - 1), // maximum magnitude of numerator
59  DMAX = U(1) << (DNM_BITS) // maximum value of denominator
60  };
61  if (dd == 0) { throw "null denominator (division by zero)"; }
62  if (n() >= NMAX) { throw "numerator too large and positive"; }
63  if (n() < -NMAX) { throw "numerator too large and negative"; }
64  if (d() > +DMAX) { throw "denominator too large"; }
65  }
66 
67  constexpr S n() const { return pair_.first; } ///< Normalized numerator.
68  constexpr U d() const { return pair_.second; } ///< Normalized denominator.
69 };
70 
71 
72 } // namespace rat
73 } // namespace vnix
74 
75 #endif // ndef VNIX_RAT_NORMALIZED_PAIR_HPP
constexpr S n() const
Normalized numerator.
Numerator and denominator of a rational number as separate numbers, not encoded into the same word...
constexpr normalized_pair(S nn, S dd)
Initialize normalized numerator and denominator for encoding of rational number.
Smallest integer types for holding certain number of bits.
Definition: int-types.hpp:21
std::pair< S, U > pair_
Normalized numerator and denominator.
Thomas E. Vaughan&#39;s public software.
Definition: rational.hpp:13
constexpr U d() const
Normalized denominator.
Classes and functions supporting a model of a fixed-precision rational number.
Definition: rational.hpp:17