/* ************************************************************************** */
/*                                                                            */
/*                                                        :::      ::::::::   */
/*   Fixed.cpp                                          :+:      :+:    :+:   */
/*                                                    +:+ +:+         +:+     */
/*   By: narnaud <narnaud@student.42.fr>            +#+  +:+       +#+        */
/*                                                +#+#+#+#+#+   +#+           */
/*   Created: 2022/06/20 10:07:44 by narnaud           #+#    #+#             */
/*   Updated: 2022/06/23 10:41:09 by narnaud          ###   ########.fr       */
/*                                                                            */
/* ************************************************************************** */

#include "Fixed.hpp"

const int	Fixed::_fract_bits = 8;

Fixed::Fixed (void) {
	_raw_bits = 0;
}

Fixed::Fixed (const int init_int) {
	_raw_bits = init_int * (1 << _fract_bits);
}

Fixed::Fixed (const float init_float) {
	_raw_bits = std::roundf(init_float * (1 << _fract_bits));
}

Fixed::Fixed (Fixed const & src) {
	_raw_bits = src.getRawBits();
}

Fixed::~Fixed (void) {
}

int	Fixed::getRawBits(void) const {
	return (_raw_bits);
}

void Fixed::setRawBits(int const raw) {
	_raw_bits = raw;
}

float	Fixed::toFloat(void) const {
	return ((float)((float)_raw_bits / (float)(1 << _fract_bits)));
}

int	Fixed::toInt(void) const {
	return ((int)((float)_raw_bits / (float)(1 << _fract_bits)));
}

Fixed & Fixed::operator= (Fixed const & src) {
	_raw_bits = src.getRawBits();
	return (*this);
}

Fixed	Fixed::operator+ (Fixed const & src) {
	return (Fixed(_raw_bits + src.getRawBits()));
}

Fixed	Fixed::operator- (Fixed const & src) {
	return (Fixed(_raw_bits - src.getRawBits()));
}

Fixed	Fixed::operator * (Fixed const & src) {
	return (Fixed(this->toFloat() * src.toFloat()));
}

Fixed	Fixed::operator / (Fixed const & src) {
	return (Fixed(this->toFloat() / src.toFloat()));
}

Fixed	& Fixed::operator++ (void) {
	_raw_bits++;
	return (*this);
}

Fixed	& Fixed::operator-- (void) {
	_raw_bits--;
	return (*this);
}
Fixed	Fixed::operator++ (int) {
	Fixed ret;
	ret.setRawBits(_raw_bits++);
	return (ret);
}

Fixed	Fixed::operator-- (int) {
	Fixed ret;
	ret.setRawBits(_raw_bits++);
	return (ret);
}

bool	Fixed::operator< (Fixed const & src) {
	return (_raw_bits < src.getRawBits());
}

bool	Fixed::operator> (Fixed const & src) {
	return (_raw_bits > src.getRawBits());
}

bool	Fixed::operator<= (Fixed const & src) {
	return (_raw_bits <= src.getRawBits());
}

bool	Fixed::operator>= (Fixed const & src) {
	return (_raw_bits >= src.getRawBits());
}

bool	Fixed::operator== (Fixed const & src) {
	return (_raw_bits == src.getRawBits());
}

bool	Fixed::operator!= (Fixed const & src) {
	return (_raw_bits != src.getRawBits());
}

std::ostream & operator << (std::ostream &out, const Fixed &f){
	out << f.toFloat();
	return (out);
}

Fixed & Fixed::min(Fixed & a, Fixed & b) {
	if (a < b)
		return (a);
	else
		return (b);
}

Fixed & Fixed::max(Fixed & a, Fixed & b) {
	if (a > b)
		return (a);
	else
		return (b);
}

const Fixed & Fixed::min(Fixed const & a, Fixed const & b){
	if (a.getRawBits() < b.getRawBits())
		return (a);
	else
		return (b);
}

const Fixed & Fixed::max(Fixed const & a, Fixed const & b){
	if (a.getRawBits() > b.getRawBits())
		return (a);
	else
		return (b);
}