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; }