Simpatico  v1.10
Rational.h
1 #ifndef UTIL_RATIONAL_H
2 #define UTIL_RATIONAL_H
3 
4 /*
5 * Util Package - C++ Utilities for Scientific Computation
6 *
7 * Copyright 2010 - 2017, The Regents of the University of Minnesota
8 * Distributed under the terms of the GNU General Public License.
9 */
10 
11 #include "gcd.h"
12 #include <util/global.h>
13 
14 #ifdef UTIL_MPI
15 #include <util/mpi/MpiTraits.h>
16 #endif
17 
18 #include <iostream>
19 
20 namespace Util
21 {
22 
33  class Rational
34  {
35 
36  public:
37 
39 
40 
44  Rational();
45 
54  Rational(int num, int den);
55 
63  Rational(int number);
64 
70  Rational(Rational const & v);
71 
76  {}
77 
79 
80 
86  Rational & operator = (Rational const & other);
87 
95  Rational & operator = (int other);
96 
98 
100 
108  Rational & operator += (Rational const & a);
109 
117  Rational & operator += (int a);
118 
126  Rational & operator -= (Rational const & a);
127 
135  Rational & operator -= (int);
136 
144  Rational & operator *= (Rational const & a);
145 
153  Rational & operator *= (int a);
154 
162  Rational & operator /= (Rational const & a);
163 
171  Rational & operator /= (int a);
172 
174 
176 
180  int num() const;
181 
185  int den() const;
186 
192  operator double () const;
193 
195 
202  template <class Archive>
203  void serialize(Archive & ar, const unsigned int version);
204 
205  #ifdef UTIL_MPI
206 
209  static void commitMpiType();
210  #endif
211 
213 
214  private:
215 
219  int num_;
220 
224  int den_;
225 
229  void reduce();
230 
231  //friends:
232 
233  friend Rational operator + (Rational const & a, Rational const & b);
234  friend Rational operator + (Rational const & a, int b);
235 
236  friend Rational operator - (Rational const & a, Rational const & b);
237  friend Rational operator - (Rational const & a, int b);
238  friend Rational operator - (int b, Rational const & a);
239 
240  friend Rational operator * (Rational const & a, Rational const & b);
241  friend Rational operator * (Rational const & a, int b);
242 
243  friend Rational operator / (Rational const & a, Rational const & b);
244  friend Rational operator / (Rational const & a, int b);
245  friend Rational operator / (int b, Rational const & a);
246 
247  friend bool operator == (Rational const & a, Rational const & b);
248  friend bool operator == (Rational const & a, int b);
249 
250  // Unary negation operation
251  friend Rational operator - (Rational const & a);
252 
253  #if 0
254  friend
255  std::istream & operator >> (std::istream & in, Rational & rational);
256  #endif
257 
258  friend
259  std::ostream & operator << (std::ostream& out, Rational const & rational);
260 
261  };
262 
263 
264 
265  // Inline methods
266 
267  /*
268  * Default constructor
269  */
270  inline
272  : num_(0),
273  den_(1)
274  { reduce(); }
275 
276  /*
277  * Constructor from numerator and denominator.
278  */
279  inline
281  : num_(num),
282  den_(den)
283  { reduce(); }
284 
285  /*
286  * Constructor from integer.
287  */
288  inline
289  Rational::Rational(int number)
290  : num_(number),
291  den_(1)
292  {}
293 
294  /*
295  * Copy constructor
296  */
297  inline
299  : num_(other.num_),
300  den_(other.den_)
301  {}
302 
303  /*
304  * Assignment from another rational.
305  */
306  inline
308  {
309  num_ = other.num_;
310  den_ = other.den_;
311  return *this;
312  }
313 
314  /*
315  * Assignment from integer.
316  */
317  inline
319  {
320  num_ = other;
321  den_ = 1;
322  return *this;
323  }
324 
325  // Inline arithmetic assignment operators
326 
327  /*
328  * Addition assignment operator : add b to this.
329  */
330  inline
332  {
333  num_ = num_*a.den_ + a.num_*den_;
334  den_ = den_*a.den_;
335  reduce();
336  return *this;
337  }
338 
339  /*
340  * Addition assignment operator : add integer to this.
341  */
342  inline
344  {
345  num_ += a*den_;
346  reduce();
347  return *this;
348  }
349 
350  /*
351  * Subtraction assignment operator : subtract a from this.
352  */
353  inline
355  {
356  num_ = num_*a.den_ - a.num_*den_;
357  den_ = den_*a.den_;
358  reduce();
359  return *this;
360  }
361 
362  /*
363  * Subtraction assignment operator : subtract integer from this.
364  */
365  inline
367  {
368  num_ -= a*den_;
369  reduce();
370  return *this;
371  }
372 
373  /*
374  * Multipication assignment operator : multiply this by a.
375  */
376  inline
378  {
379  num_ *= a.num_;
380  den_ *= a.den_;
381  reduce();
382  return *this;
383  }
384 
385  /*
386  * Multipication assignment operator : multiply this by a.
387  */
388  inline
390  {
391  num_ *= a;
392  reduce();
393  return *this;
394  }
395 
396  /*
397  * Division assignment operator : divide this by rational.
398  */
399  inline
401  {
402  if (a.num_ == 0) {
403  UTIL_THROW("Attempt to divide by zero Rational");
404  }
405  num_ = num_*a.den_;
406  den_ = den_*a.num_;
407  reduce();
408  return *this;
409  }
410 
411  /*
412  * Division assignment operator : divide this by rational.
413  */
414  inline
416  {
417  if (a == 0) {
418  UTIL_THROW("Attempt to divide Rational by zero integer");
419  }
420  den_ *= a;
421  reduce();
422  return *this;
423  }
424 
425  // Accessors
426 
427  /*
428  * Return numerator.
429  */
430  inline
431  int Rational::num() const
432  { return num_; }
433 
434  /*
435  * Return denominator.
436  */
437  inline
438  int Rational::den() const
439  { return den_; }
440 
441  /*
442  * Cast to double operator.
443  */
444  inline
445  Rational::operator double () const
446  { return double(num_)/double(den_); }
447 
448  // Miscellaneous member functions
449 
450  /*
451  * Serialize to/from an archive.
452  */
453  template <class Archive>
454  inline void Rational::serialize(Archive & ar, const unsigned int version)
455  {
456  ar & den_;
457  ar & num_;
458  }
459 
460  /*
461  * Reduce rational number to standard reduced form (private).
462  */
463  inline
464  void Rational::reduce ()
465  {
466  UTIL_CHECK(den_ != 0);
467  if (num_ == 0) {
468  den_ = 1;
469  } else {
470  if (den_ < 0) {
471  den_ *= -1;
472  num_ *= -1;
473  }
474  int c = gcd(num_, den_);
475  num_ /= c;
476  den_ /= c;
477  }
478  }
479 
480  // Friend functions for binary arithmetic operations
481 
489  inline
490  Rational operator + (Rational const & a, Rational const & b)
491  {
492  int num = a.num_*b.den_ + b.num_*a.den_;
493  int den = a.den_*b.den_;
494  return Rational(num, den);
495  }
496 
504  inline
505  Rational operator + (Rational const & a, int b)
506  {
507  int num = a.num_ + b*a.den_;
508  return Rational(num, a.den_);
509  }
510 
518  inline
519  Rational operator + (int b, Rational const & a)
520  { return (a + b); }
521 
529  inline
530  Rational operator - (Rational const & a, Rational const & b)
531  {
532  int num = a.num_*b.den_ - b.num_*a.den_;
533  int den = a.den_*b.den_;
534  return Rational(num, den);
535  }
536 
544  inline
545  Rational operator - (Rational const & a, int b)
546  {
547  int num = a.num_ - b*a.den_;
548  return Rational(num, a.den_);
549  }
550 
558  inline
559  Rational operator - (int b, Rational const & a)
560  {
561  int num = b*a.den_ - a.num_;
562  return Rational(num, a.den_);
563  }
564 
572  inline
573  Rational operator * (Rational const & a, Rational const & b)
574  {
575  int num = a.num_*b.num_;
576  int den = a.den_*b.den_;
577  return Rational(num, den);
578  }
579 
587  inline
588  Rational operator * (Rational const & a, int b)
589  { return Rational(b*a.num_, a.den_); }
590 
598  inline
599  Rational operator * (int b, Rational const & a)
600  { return a*b; }
601 
609  inline
610  Rational operator / (Rational const & a, Rational const & b)
611  {
612  if (b.num_ == 0) {
613  UTIL_THROW("Attempt to divide by zero Rational");
614  }
615  int num = a.num_*b.den_;
616  int den = a.den_*b.num_;
617  return Rational(num, den);
618  }
619 
627  inline
628  Rational operator / (Rational const & a, int b)
629  {
630  if (b == 0) {
631  UTIL_THROW("Attempt to divide Rational by zero integer");
632  }
633  return Rational(a.num_, a.den_*b);
634  }
635 
643  inline
644  Rational operator / (int b, Rational const & a)
645  {
646  if (a.num_ == 0) {
647  UTIL_THROW("Attempt to divide integer by zero Rational");
648  }
649  return Rational(b*a.den_, a.num_);
650  }
651 
652  // Unary arithmetic operators
653 
660  inline
662  { return Rational(-a.num_, a.den_); }
663 
665 
673  inline
674  bool operator == (Rational const & a, Rational const & b)
675  { return ((a.num_ == b.num_) && (a.den_ == b.den_)); }
676 
684  inline bool operator == (Rational const & a, int b)
685  { return ((a.num_ == b) && (a.den_ == 1)); }
686 
694  inline bool operator == (int b, Rational const & a)
695  { return (a == b); }
696 
698 
706  inline bool operator != (Rational const & a, Rational const & b)
707  { return !(a == b); }
708 
716  inline bool operator != (Rational const & a, int b)
717  { return !(a == b); }
718 
726  inline bool operator != (int b, Rational const & a)
727  { return !(a == b); }
728 
729  // Miscellaneous global functions.
730 
739  std::ostream& operator << (std::ostream& out, Rational const & rational);
740 
741  #ifdef UTIL_MPI
742 
745  template <>
747  {
748  public:
749  static MPI::Datatype type;
750  static bool hasType;
751  };
752  #endif
753 
754 }
755 #endif
friend Rational operator+(Rational const &a, Rational const &b)
Compute sum of two rationals.
Definition: Rational.h:490
friend Rational operator*(Rational const &a, Rational const &b)
Compute product of rationals.
Definition: Rational.h:573
friend Rational operator/(Rational const &a, Rational const &b)
Compute quotient of two rationals.
Definition: Rational.h:610
Rational & operator*=(Rational const &a)
Multiply this rational by another.
Definition: Rational.h:377
Rational()
Default constructor.
Definition: Rational.h:271
int den() const
Return denominator.
Definition: Rational.h:438
File containing preprocessor macros for error handling.
int gcd(int a, int b)
Compute greatest common divisor (gcd) of two integers.
Definition: gcd.h:30
void serialize(Archive &ar, const unsigned int version)
Serialize to/from an archive.
Definition: Rational.h:454
~Rational()
Destructor.
Definition: Rational.h:75
#define UTIL_THROW(msg)
Macro for throwing an Exception, reporting function, file and line number.
Definition: global.h:51
std::istream & operator>>(std::istream &in, Pair< Data > &pair)
Input a Pair from an istream.
Definition: Pair.h:44
Rational & operator-=(Rational const &a)
Subtract another rational from this one.
Definition: Rational.h:354
Utility classes for scientific computation.
Definition: accumulators.mod:1
Default MpiTraits class.
Definition: MpiTraits.h:39
friend bool operator==(Rational const &a, Rational const &b)
Equality operators.
Definition: Rational.h:674
static bool hasType
Is the MPI type initialized?
Definition: Rational.h:750
Rational & operator=(Rational const &other)
Copy assignment from another Rational.
Definition: Rational.h:307
Rational & operator+=(Rational const &a)
Add another rational to this one.
Definition: Rational.h:331
#define UTIL_CHECK(condition)
Assertion macro suitable for serial or parallel production code.
Definition: global.h:68
static void commitMpiType()
Commit MPI datatype MpiTraits<Rational>::type.
Rational & operator/=(Rational const &a)
Divide this rational by another.
Definition: Rational.h:400
int num() const
Return numerator.
Definition: Rational.h:431
friend Rational operator-(Rational const &a, Rational const &b)
Compute difference of rationals.
Definition: Rational.h:530
A Rational number (a ratio of integers).
Definition: Rational.h:33
friend std::ostream & operator<<(std::ostream &out, Rational const &rational)
Output stream inserter for a Rational.
Definition: Rational.cpp:16
static MPI::Datatype type
MPI Datatype.
Definition: Rational.h:749
bool operator!=(const PointSymmetry &A, const PointSymmetry &B)
Are two PointSymmetry objects not equivalent?