/ ex02 / Fixed.cpp
Fixed.cpp
  1  #include "Fixed.hpp"
  2  #include <cmath>
  3  
  4  Fixed::Fixed() : _value(0) {
  5    // Default constructor
  6  #ifdef FIXED_DEBUG
  7    std::cout << "Default constructor called" << std::endl;
  8  #endif
  9  }
 10  
 11  Fixed::Fixed(const Fixed &other) : _value(other._value) {
 12  #ifdef FIXED_DEBUG
 13    std::cout << "Copy constructor called" << std::endl;
 14  #endif
 15  }
 16  
 17  Fixed::Fixed(const int &other) : _value(other << _fractionalBits) {
 18  #ifdef FIXED_DEBUG
 19    std::cout << "Int constructor called" << std::endl;
 20  #endif
 21  }
 22  
 23  Fixed::Fixed(const float &other) {
 24    // Use roundf to convert the float into the fixed-point representation
 25    // by multiplying by 2^_fractionalBits and rounding to nearest.
 26    _value = static_cast<int>(
 27        roundf(other * static_cast<float>(1 << _fractionalBits)));
 28  
 29  #ifdef FIXED_DEBUG
 30    std::cout << "Float constructor called" << std::endl;
 31  #endif
 32  }
 33  
 34  Fixed &Fixed::operator=(const Fixed &other) {
 35    if (this != &other) {
 36      _value = other._value;
 37    }
 38  #ifdef FIXED_DEBUG
 39    std::cout << "Copy assignment operator called" << std::endl;
 40  #endif
 41    return *this;
 42  }
 43  
 44  Fixed::~Fixed() {
 45  #ifdef FIXED_DEBUG
 46    std::cout << "Destructor called" << std::endl;
 47  #endif
 48  }
 49  
 50  std::ostream &operator<<(std::ostream &os, const Fixed &obj) {
 51    os << obj.toFloat();
 52    return os;
 53  }
 54  
 55  bool Fixed::operator>(const Fixed &other) const {
 56    return _value > other._value;
 57  }
 58  
 59  bool Fixed::operator<(const Fixed &other) const {
 60    return _value < other._value;
 61  }
 62  
 63  bool Fixed::operator>=(const Fixed &other) const {
 64    return _value >= other._value;
 65  }
 66  
 67  bool Fixed::operator<=(const Fixed &other) const {
 68    return _value <= other._value;
 69  }
 70  
 71  bool Fixed::operator==(const Fixed &other) const {
 72    return _value == other._value;
 73  }
 74  
 75  bool Fixed::operator!=(const Fixed &other) const {
 76    return _value != other._value;
 77  }
 78  
 79  Fixed Fixed::operator+(const Fixed &other) const {
 80    // We find wich of the two values has more fractional bits
 81    // and we align the other value to that before adding
 82    Fixed result;
 83  
 84    int selfFracBits = getFractionalBits();
 85    int otherFracBits = other.getFractionalBits();
 86  
 87    if (selfFracBits >= otherFracBits) {
 88      result._value = _value + (other._value << (selfFracBits - otherFracBits));
 89    } else {
 90      result._value = (_value << (otherFracBits - selfFracBits)) + other._value;
 91    }
 92  
 93    return result;
 94  }
 95  
 96  Fixed Fixed::operator-(const Fixed &other) const {
 97    // We find wich of the two values has more fractional bits
 98    // and we align the other value to that before subtracting
 99    Fixed result;
100  
101    int selfFracBits = getFractionalBits();
102    int otherFracBits = other.getFractionalBits();
103  
104    if (selfFracBits >= otherFracBits) {
105      result._value = _value - (other._value << (selfFracBits - otherFracBits));
106    } else {
107      result._value = (_value << (otherFracBits - selfFracBits)) - other._value;
108    }
109  
110    return result;
111  }
112  
113  Fixed Fixed::operator*(const Fixed &other) const {
114    // Multiply two fixed-point values.
115    // Use 64-bit intermediate to avoid overflow during multiplication,
116    // then shift back by fractional bits. Add rounding for nearest.
117    Fixed result;
118  
119    int fb = getFractionalBits();
120    int64_t prod =
121        static_cast<int64_t>(_value) * static_cast<int64_t>(other._value);
122  
123    // Rounding: add 0.5 in fixed-point (1 << (fb-1)) for positive values,
124    // subtract for negative to round toward nearest.
125    int64_t rounding =
126        (prod >= 0) ? (int64_t(1) << (fb - 1)) : -(int64_t(1) << (fb - 1));
127  
128    prod = (prod + rounding) >> fb;
129  
130    result._value = static_cast<int>(prod);
131    return result;
132  }
133  
134  Fixed Fixed::operator/(const Fixed &other) const {
135    // Divide two fixed-point values.
136    // Use 64-bit intermediate to avoid overflow during shifting,
137    // then shift back by fractional bits. Add rounding for nearest.
138    Fixed result;
139  
140    int fb = getFractionalBits();
141    if (other._value == 0) {
142      std::cerr << "Error: Division by zero in Fixed::operator/" << std::endl;
143      result._value = 0;
144      return result;
145    }
146  
147    int64_t dividend = (static_cast<int64_t>(_value) << fb);
148    int64_t divisor = static_cast<int64_t>(other._value);
149  
150    // Rounding: add half the divisor for positive values,
151    // subtract for negative to round toward nearest.
152    int64_t rounding = (dividend >= 0) ? (divisor / 2) : -(divisor / 2);
153  
154    dividend += rounding;
155  
156    int64_t quot = dividend / divisor;
157  
158    result._value = static_cast<int>(quot);
159    return result;
160  }
161  
162  Fixed &Fixed::operator++() {
163    int new_value = _value + (1 << _fractionalBits);
164    _value = new_value;
165    return *this;
166  }
167  
168  Fixed Fixed::operator++(int) {
169    // Postfix increment
170    Fixed temp = *this;
171    _value += (1 << _fractionalBits);
172    return temp;
173  }
174  
175  Fixed &Fixed::operator--() {
176    // Prefix decrement: subtract one unit in fixed-point (1 << fractional bits)
177    _value -= (1 << _fractionalBits);
178    return *this;
179  }
180  
181  Fixed Fixed::operator--(int) {
182    // Postfix decrement
183    Fixed temp = *this;
184    _value -= (1 << _fractionalBits);
185    return temp;
186  }
187  
188  float Fixed::toFloat() const {
189    return static_cast<float>(_value) / (1 << _fractionalBits);
190  }
191  
192  Fixed &Fixed::min(Fixed &a, Fixed &b) { return (a < b) ? a : b; }
193  
194  const Fixed &Fixed::min(const Fixed &a, const Fixed &b) {
195    return (a < b) ? a : b;
196  }
197  
198  Fixed &Fixed::max(Fixed &a, Fixed &b) { return (a > b) ? a : b; }
199  
200  const Fixed &Fixed::max(const Fixed &a, const Fixed &b) {
201    return (a > b) ? a : b;
202  }
203  
204  int Fixed::getRawBits() const { return _value; }
205  
206  int Fixed::getFractionalBits() { return _fractionalBits; }