Vcsn  2.0
Be Rational
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
q.hh
Go to the documentation of this file.
1 #ifndef VCSN_WEIGHTSET_Q_HH
2 # define VCSN_WEIGHTSET_Q_HH
3 
4 # include <string>
5 # include <ostream>
6 
7 # include <vcsn/core/join.hh>
8 # include <vcsn/misc/hash.hh>
9 # include <vcsn/misc/math.hh>
10 # include <vcsn/misc/raise.hh>
11 # include <vcsn/misc/star_status.hh>
12 # include <vcsn/misc/stream.hh> // eat
13 # include <vcsn/weightset/b.hh>
14 # include <vcsn/weightset/fwd.hh>
16 # include <vcsn/weightset/z.hh>
17 
18 namespace vcsn
19 {
20  namespace detail
21  {
22  class q_impl
23  {
24  public:
25  using self_type = q;
26 
27  static std::string sname()
28  {
29  return "q";
30  }
31 
32  std::string vname(bool = true) const
33  {
34  return sname();
35  }
36 
38  static q make(std::istream& is)
39  {
40  eat(is, sname());
41  return {};
42  }
43 
44  struct value_t
45  {
46  value_t(int n = 0, unsigned d = 1)
47  : num(n)
48  , den(d)
49  {}
50 
53  {
54  int gc = gcd(abs(num), den);
55  num /= gc;
56  den /= gc;
57  return *this;
58  }
59 
60  int num;
61  unsigned int den;
62  };
63 
64  static unsigned int abs(int a)
65  {
66  return a < 0 ? -a : a;
67  }
68 
69  static value_t zero()
70  {
71  return value_t{0, 1};
72  }
73 
74  static value_t one()
75  {
76  return value_t{1, 1};
77  }
78 
79  static value_t add(const value_t l, const value_t r)
80  {
81  unsigned int cm = lcm(l.den, abs(r.den));
82  return value_t{l.num * int (cm / l.den) + r.num * int (cm / r.den),
83  cm}.reduce();
84  }
85 
86  static value_t sub(const value_t l, const value_t r)
87  {
88  unsigned int cm = lcm(l.den, abs(r.den));
89  return value_t{l.num * int (cm / l.den) - r.num * int (cm / r.den),
90  cm}.reduce();
91  }
92 
93  static value_t mul(const value_t l, const value_t r)
94  {
95  return value_t{l.num * r.num, l.den * r.den}.reduce();
96  }
97 
98  static value_t
99  rdiv(const value_t l, const value_t r)
100  {
101  require(!is_zero(r), "div: division by zero");
102  if (0 < r.num)
103  return value_t{l.num * int(r.den), l.den * r.num}.reduce();
104  else
105  return value_t{-l.num * int(r.den), l.den * -r.num}.reduce();
106  }
107 
108  static value_t
109  ldiv(const value_t l, const value_t r)
110  {
111  return rdiv(r, l);
112  }
113 
114  value_t star(const value_t v) const
115  {
116  // Bad casting when v.den is too big
117  if (abs(v.num) < v.den)
118  // No need to reduce: numerator and denominators are primes.
119  return {int(v.den), v.den - v.num};
120  else
121  raise(sname(), ": star: invalid value: ", to_string(*this, v));
122  }
123 
124  static bool is_special(const value_t) // C++11: cannot be constexpr.
125  {
126  return false;
127  }
128 
129  static bool is_zero(const value_t v)
130  {
131  return v.num == 0;
132  }
133 
134  static bool is_one(const value_t v)
135  {
136  // All values are normalized.
137  return v.num == 1 && v.den == 1;
138  }
139 
140  static bool equals(const value_t l, const value_t r)
141  {
142  return l.num == r.num && l.den == r.den;
143  }
144 
146  static bool less_than(value_t lhs, value_t rhs)
147  {
148  return lhs.num * rhs.den < rhs.num * lhs.den;
149  }
150 
151  static constexpr bool is_commutative() { return true; }
152 
153  static constexpr bool show_one() { return false; }
154  static constexpr star_status_t star_status() { return star_status_t::ABSVAL; }
155 
156  static value_t
157  abs(const value_t v)
158  {
159  return v.num < 0 ? (value_t{-v.num, v.den}) : v;
160  }
161 
162  static value_t
164  {
165  return v;
166  }
167 
168  static size_t hash(value_t v)
169  {
170  size_t res = 0;
171  std::hash_combine(res, hash_value(v.num));
172  std::hash_combine(res, hash_value(v.den));
173  return res;
174  }
175 
176  static value_t
178  {
179  return v;
180  }
181 
182  static value_t
183  conv(z, z::value_t v)
184  {
185  return {v, 1};
186  }
187 
188  static value_t
189  conv(b, b::value_t v)
190  {
191  return {v, 1};
192  }
193 
194  static value_t
195  conv(std::istream& i)
196  {
197  int num;
198  if (! (i >> num))
199  vcsn::fail_reading(i, sname() + ": invalid numerator");
200 
201  // If we have a slash after the numerator then we have a
202  // denominator as well.
203  char maybe_slash;
204  if ((maybe_slash = i.peek()) != '/')
205  return value_t{num, 1};
206  vcsn::eat(i, '/');
207 
208  // operator>> with an istream and an unsigned int silently
209  // mangles a negative number into its two's complement
210  // representation as a positive number.
211  if (i.peek() == '-')
212  {
213  num = - num;
214  vcsn::eat(i, '-');
215  }
216 
217  unsigned int den;
218  if (i >> den)
219  {
220  // Make sure our rational respects our constraints.
221  require(den, sname(), ": zero denominator");
222  return value_t{num, den}.reduce();
223  }
224  else
225  vcsn::fail_reading(i, sname() + ": invalid denominator");
226  }
227 
228  static std::ostream&
229  print(const value_t v, std::ostream& o,
230  symbol format = symbol{"text"})
231  {
232  if (format == "latex")
233  {
234  if (v.den == 1)
235  o << v.num;
236  else
237  o << "\\frac{" << v.num << "}{" << v.den << '}';
238  }
239  else
240  {
241  o << v.num;
242  if (v.den != 1)
243  o << '/' << v.den;
244  }
245  return o;
246  }
247 
248  std::ostream&
249  print_set(std::ostream& o, symbol format = symbol{"text"}) const
250  {
251  if (format == "latex")
252  o << "\\mathbb{Q}";
253  else if (format == "text")
254  o << vname();
255  else
256  raise("invalid format: ", format);
257  return o;
258  }
259  };
260 
261  /*-------.
262  | join. |
263  `-------*/
264 
265  VCSN_JOIN_SIMPLE(b, q);
266  VCSN_JOIN_SIMPLE(z, q);
267  VCSN_JOIN_SIMPLE(q, q);
268  }
269 }
270 
271 #endif // !VCSN_WEIGHTSET_Q_HH
static unsigned int abs(int a)
Definition: q.hh:64
static constexpr bool is_commutative()
Definition: q.hh:151
static value_t one()
Definition: q.hh:74
ATTRIBUTE_PURE unsigned int lcm(unsigned int a, unsigned int b)
Definition: math.hh:29
static q make(std::istream &is)
Build from the description in is.
Definition: q.hh:38
value_t & reduce()
Put it in normal form.
Definition: q.hh:52
static constexpr bool show_one()
Definition: q.hh:153
static bool equals(const value_t l, const value_t r)
Definition: q.hh:140
static size_t hash(value_t v)
Definition: q.hh:168
ATTRIBUTE_PURE unsigned int gcd(unsigned int a, unsigned int b)
Definition: math.hh:14
static bool is_zero(const value_t v)
Definition: q.hh:129
boost::flyweight< std::string, boost::flyweights::no_tracking > symbol
An internalized string.
Definition: symbol.hh:24
variadic_mul_mixin< detail::b_impl > b
Definition: fwd.hh:38
static constexpr star_status_t star_status()
Definition: q.hh:154
variadic_mul_mixin< detail::q_impl > q
Definition: fwd.hh:40
unsigned int den
Definition: q.hh:61
std::ostream & print_set(std::ostream &o, symbol format=symbol{"text"}) const
Definition: q.hh:249
value_t star(const value_t v) const
Definition: q.hh:114
std::size_t hash_value(const T &v)
Definition: hash.hh:61
static value_t conv(b, b::value_t v)
Definition: q.hh:189
static std::ostream & print(const value_t v, std::ostream &o, symbol format=symbol{"text"})
Definition: q.hh:229
static bool is_one(const value_t v)
Definition: q.hh:134
static std::string sname()
Definition: q.hh:27
variadic_mul_mixin< detail::z_impl > z
Definition: fwd.hh:43
static bool less_than(value_t lhs, value_t rhs)
Whether lhs < rhs.
Definition: q.hh:146
static value_t abs(const value_t v)
Definition: q.hh:157
static value_t conv(z, z::value_t v)
Definition: q.hh:183
value_t(int n=0, unsigned d=1)
Definition: q.hh:46
static value_t ldiv(const value_t l, const value_t r)
Definition: q.hh:109
static value_t sub(const value_t l, const value_t r)
Definition: q.hh:86
std::string vname(bool=true) const
Definition: q.hh:32
std::istringstream is
The input stream: the specification to translate.
Definition: translate.cc:329
star_status_t
Definition: star_status.hh:6
static value_t add(const value_t l, const value_t r)
Definition: q.hh:79
Provide a variadic mul on top of a binary mul(), and one().
Definition: fwd.hh:36
static value_t mul(const value_t l, const value_t r)
Definition: q.hh:93
VCSN_JOIN_SIMPLE(b, b)
static value_t zero()
Definition: q.hh:69
char eat(std::istream &is, char c)
Check lookahead character and advance.
Definition: stream.cc:37
static bool is_special(const value_t)
Definition: q.hh:124
ATTRIBUTE_NORETURN void fail_reading(std::istream &is, std::string explanation)
Throw an exception after failing to read from is.
Definition: stream.cc:107
static value_t rdiv(const value_t l, const value_t r)
Definition: q.hh:99
static value_t conv(self_type, value_t v)
Definition: q.hh:177
void require(bool b, Args &&...args)
If b is not verified, raise an error with args as message.
Definition: raise.hh:39
static value_t transpose(const value_t v)
Definition: q.hh:163
static value_t conv(std::istream &i)
Definition: q.hh:195
std::string to_string(direction d)
Conversion to string.
Definition: direction.cc:7