Empirical
fixed.h
Go to the documentation of this file.
1 // This file is part of Empirical, https://github.com/mercere99/Empirical/, and is
2 // Copyright (C) Michigan State University, 2015. It is licensed
3 // under the MIT Software license; see doc/LICENSE
4 
5 #ifndef EMP_FIXED_H
6 #define EMP_FIXED_H
7 
9 //
10 // A comprehensive (ideally) fixed-point number representation.
11 //
12 // Type-name: emp::fixed
13 //
14 // Representation: sign (1 bit), int value (21 bits), frac value (10 bits)
15 // Max value: 2097151.999
16 // Min value: -2097152.999 (@CAO or .000?)
17 //
18 
19 #include <iostream>
20 
21 namespace emp {
22 
23  template <int FRAC_BITS=10> class fixed {
24  private:
25  int value;
26  static const int int_bits = 31 - FRAC_BITS;
27 
28  // Private constructor to allow first direct setting of internal value
29  fixed(int in_value, bool) : value(in_value) { ; }
30  public:
31  fixed() : value(0) { ; }
32  fixed(const fixed & in_value) : value (in_value.value) { ; }
33  fixed(int in_value) : value(in_value << FRAC_BITS) { ; }
34  fixed(double in_value) : value(in_value * (1 << FRAC_BITS)) { ; }
35  ~fixed() { ; }
36 
37  int bits() const { return value; }
38  int AsInt() const { return value >> FRAC_BITS; }
39  double AsDouble() const { return ((double) value) / ((double) (1 << FRAC_BITS)); }
40 
41  fixed & operator=(const fixed & other) { value = other.value; return *this; }
42  fixed & operator=(int other) { value = other << FRAC_BITS; return *this; }
43  fixed & operator=(double other) { value = other * (1 << FRAC_BITS); return *this; }
44 
45  fixed & operator+=(const fixed & rhs) { value += rhs.value; return *this; }
46  fixed & operator-=(const fixed & rhs) { value -= rhs.value; return *this; }
47  fixed & operator*=(const fixed & rhs) {
48  // Take advantage of (a+b)*(c+d) = ac+ad+bc+bd. Since bd is too low precision: b*c + a*(c+d)
49  const int frac_mask = (1 << FRAC_BITS) - 1;
50  value = (value & frac_mask) * (rhs.value >> FRAC_BITS) + (value >> FRAC_BITS) * rhs.value
51  + ((value & frac_mask) * (rhs.value & frac_mask) >> FRAC_BITS);
52  return *this;
53  }
54  fixed & operator/=(const fixed & rhs) {
55  // @CAO can we take advantage of (a+b)/c = a/c + b/c
56  value = (((long) value) << FRAC_BITS) / rhs.value;
57  return *this;
58  }
59 
60  fixed & operator++() { value += (1 << FRAC_BITS); }
61  fixed operator++(int) { int old_val = value; operator++(); return fixed(old_val); }
62  fixed & operator--() { value -= (1 << FRAC_BITS); }
63  fixed operator--(int) { int old_val = value; operator--(); return fixed(old_val); }
64 
65  friend fixed operator+(const fixed & lhs, const fixed & rhs) {
66  return fixed(lhs.value + rhs.value, true);
67  }
68  friend fixed operator-(const fixed & lhs, const fixed & rhs) {
69  return fixed(lhs.value - rhs.value, true);
70  }
71  friend fixed operator*(const fixed & lhs, const fixed & rhs) {
72  // Take advantage of (a+b)*(c+d) = ac+ad+bc+bd. Since bd is too low precision: b*c + a*(c+d)
73  const int frac_mask = (1 << FRAC_BITS) - 1;
74  const int new_value = (lhs.value & frac_mask) * (rhs.value >> FRAC_BITS)
75  + (lhs.value >> FRAC_BITS) * rhs.value
76  + ((lhs.value & frac_mask) * (rhs.value & frac_mask) >> FRAC_BITS);
77  return fixed(new_value, true);
78  }
79  friend fixed operator/(const fixed & lhs, const fixed & rhs) {
80  // @CAO can we take advantage of (a+b)/c = a/c + b/c
81  const int new_value = (((long) lhs.value) << FRAC_BITS) / rhs.value;
82  return fixed(new_value, true);
83  }
84 
85  friend bool operator==(const fixed & lhs, const fixed & rhs)
86  { return lhs.value == rhs.value; }
87  friend bool operator!=(const fixed & lhs, const fixed & rhs)
88  { return lhs.value != rhs.value; }
89  friend bool operator< (const fixed & lhs, const fixed & rhs)
90  { return lhs.value < rhs.value; }
91  friend bool operator<=(const fixed & lhs, const fixed & rhs)
92  { return lhs.value <= rhs.value; }
93  friend bool operator> (const fixed & lhs, const fixed & rhs)
94  { return lhs.value > rhs.value; }
95  friend bool operator>=(const fixed & lhs, const fixed & rhs)
96  { return lhs.value >= rhs.value; }
97 
98  };
99 
100 
101 };
102 
103 // Overload istream and ostream to work with fixed.
104 template <int FRAC_BITS> std::ostream & operator<<(std::ostream & os,
105  const emp::fixed<FRAC_BITS> & input) {
106  return os << input.AsDouble();
107 }
108 
109 template <int FRAC_BITS> std::istream & operator>>(std::istream & is,
110  emp::fixed<FRAC_BITS> & input) {
111  double tmp_val;
112  is >> tmp_val;
113  input = tmp_val;
114  return is;
115 }
116 
117 #endif
fixed(const fixed &in_value)
Definition: fixed.h:32
~fixed()
Definition: fixed.h:35
friend bool operator<=(const fixed &lhs, const fixed &rhs)
Definition: fixed.h:91
fixed & operator=(const fixed &other)
Definition: fixed.h:41
friend bool operator==(const fixed &lhs, const fixed &rhs)
Definition: fixed.h:85
friend bool operator>=(const fixed &lhs, const fixed &rhs)
Definition: fixed.h:95
friend bool operator>(const fixed &lhs, const fixed &rhs)
Definition: fixed.h:93
friend fixed operator+(const fixed &lhs, const fixed &rhs)
Definition: fixed.h:65
fixed operator--(int)
Definition: fixed.h:63
fixed()
Definition: fixed.h:31
Definition: fixed.h:23
fixed & operator--()
Definition: fixed.h:62
std::istream & operator>>(std::istream &is, emp::Ptr< T > &ptr)
Definition: Ptr.h:808
fixed & operator+=(const fixed &rhs)
Definition: fixed.h:45
fixed(double in_value)
Definition: fixed.h:34
int bits() const
Definition: fixed.h:37
friend fixed operator*(const fixed &lhs, const fixed &rhs)
Definition: fixed.h:71
fixed & operator=(double other)
Definition: fixed.h:43
int AsInt() const
Definition: fixed.h:38
std::ostream & operator<<(std::ostream &out, const emp::Ptr< T > &ptr)
Definition: Ptr.h:800
friend bool operator!=(const fixed &lhs, const fixed &rhs)
Definition: fixed.h:87
fixed & operator-=(const fixed &rhs)
Definition: fixed.h:46
fixed & operator=(int other)
Definition: fixed.h:42
friend fixed operator/(const fixed &lhs, const fixed &rhs)
Definition: fixed.h:79
fixed & operator/=(const fixed &rhs)
Definition: fixed.h:54
fixed & operator*=(const fixed &rhs)
Definition: fixed.h:47
friend bool operator<(const fixed &lhs, const fixed &rhs)
Definition: fixed.h:89
If we are in emscripten, make sure to include the header.
Definition: array.h:37
fixed & operator++()
Definition: fixed.h:60
double AsDouble() const
Definition: fixed.h:39
friend fixed operator-(const fixed &lhs, const fixed &rhs)
Definition: fixed.h:68
fixed operator++(int)
Definition: fixed.h:61
fixed(int in_value)
Definition: fixed.h:33