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