78 lines
2.4 KiB
C
78 lines
2.4 KiB
C
|
#ifndef _REAL_FIX_H
|
||
|
#define _REAL_FIX_H
|
||
|
#include <stdint.h>
|
||
|
namespace FIX {
|
||
|
static constexpr int iround (const double d) { return d > 0.0 ? int (d + 0.5) : int (d - 0.5); }
|
||
|
/**
|
||
|
* @class real
|
||
|
* @brief Aritmetika v pevné řádové čárce.
|
||
|
*
|
||
|
* Není to moc přesné, ale bez float koprocesoru to postačí.
|
||
|
* A není to kompletní, jen pro výpočet polynomu, zde to stačí.
|
||
|
*/
|
||
|
struct real {
|
||
|
int32_t x; // necháme veřejné
|
||
|
/**
|
||
|
* @brief Konstruktor z double
|
||
|
* @param _x double
|
||
|
*/
|
||
|
explicit constexpr real (const double _x) : x (iround (_x)) {}
|
||
|
/**
|
||
|
* @brief Konstruktor z celého čísla, přímo nepoužívat - explicitní převod from_int()
|
||
|
* Ono se to trochu pere s tím double.
|
||
|
* @param _x integer
|
||
|
*/
|
||
|
explicit constexpr real (const int32_t _x) : x (_x) {}
|
||
|
/**
|
||
|
* @brief Kopírovací konstruktor
|
||
|
*/
|
||
|
explicit constexpr real () : x (0) {}
|
||
|
// stačí přetížit jen některé operátory, výpočet je dělán poměrně úsporně
|
||
|
|
||
|
real operator+ (const real & r) const {
|
||
|
return real (x + r.x);
|
||
|
}
|
||
|
real operator- (const real & r) const {
|
||
|
return real (x - r.x);
|
||
|
}
|
||
|
|
||
|
bool operator< (const real & r) const {
|
||
|
return x < r.x;
|
||
|
}
|
||
|
bool operator>= (const real & r) const {
|
||
|
return x >= r.x;
|
||
|
}
|
||
|
real & operator+= (const real & r) {
|
||
|
x += r.x;
|
||
|
return * this;
|
||
|
}
|
||
|
// Pouze pro výpisy - zachová formátovou specifikaci pro FLT
|
||
|
double operator+ () const {
|
||
|
return double (x);
|
||
|
}
|
||
|
};
|
||
|
// Násobení s posunem zde používá "plovoucí" posun, jinak to nejde.
|
||
|
static void mull (real & res, const real & r, const int sl = 0) {
|
||
|
const int64_t result = (int64_t)(res.x) * (int64_t)(r.x);
|
||
|
#ifdef __linux__
|
||
|
// Check overflow
|
||
|
const uint64_t u = result < 0 ? -result : +result;
|
||
|
const uint32_t o = u >> (sl + 32);
|
||
|
if (o) {fprintf (stderr, "Overflow 0x%X\n", o); // Není to dokonalé, ale alespoň něco
|
||
|
// Šla by vyhodit výjimka a backtrace zjistit proč a hlavně kde.
|
||
|
throw ("overflow exception"); }
|
||
|
#endif
|
||
|
res.x = result >> sl;
|
||
|
}
|
||
|
//! Vytvoří double z real
|
||
|
static constexpr double from_real (const real & r) {
|
||
|
const double a = 1.0 / double (1ull << 16);
|
||
|
return a * double(r.x);
|
||
|
}
|
||
|
static constexpr real to_real (const double x, const int sh) {
|
||
|
const double a = double (1ull << sh);
|
||
|
return real (a * x);
|
||
|
}
|
||
|
}; // end of namespace FIX
|
||
|
#endif // _REAL_FIX_H
|