Fixed.h 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687
  1. #ifndef MANDEL_FIXED128_H
  2. #define MANDEL_FIXED128_H
  3. #include <cinttypes>
  4. #include <cmath>
  5. #include <utility>
  6. #include <array>
  7. #include <vector>
  8. #include <boost/multiprecision/cpp_int.hpp>
  9. #include <boost/multiprecision/cpp_bin_float.hpp>
  10. struct Fixed512
  11. {
  12. using Once = boost::multiprecision::int512_t;
  13. using Twice = boost::multiprecision::int1024_t;
  14. Once body;
  15. inline explicit Fixed512(const Once& body) :
  16. body{ body }
  17. {}
  18. using Float256 = boost::multiprecision::number<
  19. boost::multiprecision::backends::cpp_bin_float<
  20. 240, boost::multiprecision::backends::digit_base_2, void, boost::int16_t, -16382, 16383>,
  21. boost::multiprecision::et_off>;
  22. using Float512 = boost::multiprecision::number<
  23. boost::multiprecision::backends::cpp_bin_float<
  24. 496, boost::multiprecision::backends::digit_base_2, void, boost::int16_t, -16382, 16383>,
  25. boost::multiprecision::et_off>;
  26. inline Fixed512(const Float256& val)
  27. {
  28. body = Once{ val * boost::multiprecision::pow(Float256{ 2 }, 512 - 32) };
  29. }
  30. inline Fixed512(const Float512& val)
  31. {
  32. body = Once{ val * boost::multiprecision::pow(Float512{ 2 }, 512 - 32) };
  33. }
  34. inline Fixed512(double val)
  35. {
  36. body = Once{ boost::multiprecision::pow(Float256{ 2 }, 512 - 32) * val };
  37. }
  38. inline operator Float256(void) const {
  39. return boost::multiprecision::pow(Float256{ 0.5 }, 512 - 32) * Float256{ body };
  40. }
  41. inline operator Float512(void) const {
  42. return boost::multiprecision::pow(Float512{ 0.5 }, 512 - 32) * Float512{ body };
  43. }
  44. inline Fixed512& operator += (const Fixed512& other) {
  45. body += other.body;
  46. return *this;
  47. }
  48. inline Fixed512 operator + (const Fixed512& other) const {
  49. return Fixed512{ body + other.body };
  50. }
  51. inline Fixed512& operator -= (const Fixed512& other) {
  52. body -= other.body;
  53. return *this;
  54. }
  55. inline Fixed512 operator - (const Fixed512& other) const {
  56. return Fixed512{ body - other.body };
  57. }
  58. inline Fixed512 operator * (const Fixed512& other) const {
  59. auto prod = Twice{ this->body } * other.body;
  60. return Fixed512{ Once{ prod >> (512 - 32) } };
  61. }
  62. inline Fixed512& operator *= (const Fixed512& other) {
  63. auto prod = Twice{ this->body } * other.body;
  64. body = Once{ prod >> (512 - 64) };
  65. return *this;
  66. }
  67. inline bool operator > (const Fixed512& other) {
  68. return this->body > other.body;
  69. }
  70. };
  71. struct Fixed128
  72. {
  73. uint64_t upper;
  74. uint64_t lower;
  75. Fixed128(const Fixed128&) = default;
  76. ~Fixed128() = default;
  77. inline Fixed128(uint64_t upper, uint64_t lower) :
  78. upper{ upper }, lower{ lower }
  79. {
  80. }
  81. inline Fixed128(uint32_t a, uint32_t b, uint32_t c, uint32_t d) :
  82. upper{ (uint64_t(a) << 32) | b }, lower{ (uint64_t(c) << 32) | d }
  83. {
  84. }
  85. inline Fixed128(double x)
  86. {
  87. const double twoToThe32 = double(0x100000000ULL);
  88. upper = uint64_t(int64_t(x * twoToThe32));
  89. double remainder = x - double(upper) / twoToThe32;
  90. lower = uint64_t(int64_t(remainder * twoToThe32 * twoToThe32 * twoToThe32));
  91. /*int integerPart = ::floor(x);
  92. double fractionalPart = x - integerPart;
  93. upper = int64_t(integerPart) << 32;
  94. upper |= uint64_t(fractionalPart * (1ULL << 32)) & 0xFFFFFFFFULL;
  95. lower = 0;// uint64_t(fractionalPart * (1ULL << 32) * (1ULL << 63) * 2);*/
  96. }
  97. inline Fixed128 operator + (const Fixed128& other) const {
  98. uint64_t lowerAdded = lower + other.lower;
  99. uint64_t upperAdded = upper + other.upper + (lowerAdded < lower);
  100. return Fixed128{ upperAdded, lowerAdded };
  101. }
  102. inline Fixed128& operator +=(const Fixed128& other) {
  103. uint64_t lowerAdded = lower + other.lower;
  104. upper += other.upper + (lowerAdded < lower);
  105. lower = lowerAdded;
  106. return *this;
  107. }
  108. inline Fixed128 operator - (const Fixed128& other) const {
  109. uint64_t lowerSubbed = lower - other.lower;
  110. uint64_t upperSubbed = upper - other.upper - (lowerSubbed > lower);
  111. return Fixed128{ upperSubbed, lowerSubbed };
  112. }
  113. inline Fixed128 operator - (void) const {
  114. return this->operator~() + Fixed128{ 0, 0, 0, 1 };
  115. }
  116. //private:
  117. static inline std::pair<uint64_t, uint64_t> mul64(int64_t a, int64_t b) {
  118. int32_t aa[2] = { int32_t(a >> 32), int32_t(a & 0xFFFFFFFF) };
  119. int32_t bb[2] = { int32_t(b >> 32), int32_t(b & 0xFFFFFFFF) };
  120. int32_t res[4];
  121. int64_t temp = int64_t(aa[1]) * bb[1];
  122. res[3] = temp & 0xFFFFFFFF;
  123. int32_t carry = temp >> 32;
  124. temp = int64_t(aa[0]) * bb[1] + int64_t(aa[1]) * bb[0] + carry;
  125. res[2] = temp & 0xFFFFFFFF;
  126. carry = temp >> 32;
  127. temp = int64_t(aa[0]) * bb[0] + carry;
  128. res[1] = temp & 0xFFFFFFFF;
  129. res[0] = temp >> 32;
  130. return std::make_pair(uint64_t((int64_t(res[0]) << 32) | res[1]), uint64_t((int64_t(res[2]) << 32) | res[3]));
  131. }
  132. static inline std::pair<uint64_t, uint64_t> mulu64(uint64_t a, uint64_t b) {
  133. uint32_t aa[2] = { uint32_t(a >> 32), uint32_t(a & 0xFFFFFFFF) };
  134. uint32_t bb[2] = { uint32_t(b >> 32), uint32_t(b & 0xFFFFFFFF) };
  135. uint32_t res[4];
  136. uint64_t temp = uint64_t(aa[1]) * bb[1];
  137. res[3] = temp & 0xFFFFFFFF;
  138. uint32_t carry = temp >> 32;
  139. temp = uint64_t(aa[0]) * bb[1] + uint64_t(aa[1]) * bb[0] + carry;
  140. res[2] = temp & 0xFFFFFFFF;
  141. carry = temp >> 32;
  142. temp = uint64_t(aa[0]) * bb[0] + carry;
  143. res[1] = temp & 0xFFFFFFFF;
  144. res[0] = temp >> 32;
  145. return std::make_pair((uint64_t(res[0]) << 32) | res[1], (uint64_t(res[2]) << 32) | res[3] );
  146. }
  147. public:
  148. inline Fixed128 operator * (const Fixed128& other) const {
  149. if (this->operator!=(Fixed128{ 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF }) && isNegative()) {
  150. return -(other * this->operator-());
  151. }
  152. if (other.isNegative()) {
  153. return -((-other) * (*this));
  154. }
  155. auto [uuc, uu] = mulu64(upper, other.upper);
  156. auto [ulc, ul] = mulu64(upper, other.lower);
  157. auto [luc, lu] = mulu64(lower, other.upper);
  158. auto [llc, ll] = mulu64(lower, other.lower);
  159. uint64_t res[4] = { 0, 0, 0, 0 };
  160. res[3] = ll;
  161. res[2] += lu;
  162. res[2] += ul;
  163. if (res[2] < ul)
  164. res[1]++;
  165. res[2] += llc;
  166. if (res[2] < llc)
  167. res[1]++;
  168. res[1] += uu;
  169. if (res[1] < uu)
  170. res[0]++;
  171. res[1] += ulc;
  172. if (res[1] < ulc)
  173. res[0]++;
  174. res[1] += luc;
  175. if (res[1] < luc)
  176. res[0]++;
  177. res[0] += uuc;
  178. return Fixed128{ uint32_t(res[0] & 0xFFFFFFFF), uint32_t(int64_t(res[1]) >> 32), uint32_t(res[1] & 0xFFFFFFFF), uint32_t(int64_t(res[2]) >> 32) };
  179. /*if (isNegative()) {
  180. return -(this->operator-() * other);
  181. }
  182. if (other.isNegative()) {
  183. return -(*this * (-other));
  184. }
  185. bool otherNegative = other.isNegative();
  186. uint32_t quarters[4] = {
  187. (upper >> 32) & 0xFFFFFFFF,
  188. upper & 0xFFFFFFFF,
  189. (lower >> 32) & 0xFFFFFFFF,
  190. lower & 0xFFFFFFFF
  191. };
  192. auto [a, ra] = other.mul(quarters[0]);
  193. auto [b, rb] = other.mul(quarters[1]);
  194. auto [c, rc] = other.mul(quarters[2]);
  195. auto [d, rd] = other.mul(quarters[3]);
  196. b.arshift(1);
  197. c.arshift(2);
  198. d.arshift(3);
  199. Fixed128 carries = { uint32_t(rb), uint32_t(rc), uint32_t(rd), 0 };
  200. Fixed128 result = a + b + c + d + carries;
  201. return result;*/
  202. }
  203. inline std::pair<Fixed128, uint32_t> mul(uint32_t factor) const {
  204. uint32_t quarters[4] = {
  205. uint32_t(upper >> 32) & 0xFFFFFFFF,
  206. uint32_t(upper) & 0xFFFFFFFF,
  207. uint32_t(lower >> 32) & 0xFFFFFFFF,
  208. uint32_t(lower) & 0xFFFFFFFF
  209. };
  210. uint32_t newQ[4];
  211. uint32_t carry = 0;
  212. for (int i = 3; i >= 0; i--) {
  213. int64_t prod = int64_t(quarters[i]) * factor + carry;
  214. newQ[i] = prod & 0xFFFFFFFF;
  215. carry = prod >> 32;
  216. }
  217. /* newQ[i] = quarters[i] * factor;
  218. uint64_t tempLower = newQ[3];
  219. uint64_t newLower = tempLower + (newQ[2] << 32);
  220. uint64_t newUpper = (newQ[2] >> 32) + newQ[1] + (newQ[0] << 32) + (newLower < tempLower ? 1 : 0);*/
  221. return std::make_pair(Fixed128{ newQ[0], newQ[1], newQ[2], newQ[3] }, carry);
  222. }
  223. /*
  224. inline void arshift(int fac32) {
  225. uint32_t temp = 0;
  226. switch (fac32) {
  227. case 0:
  228. return;
  229. case 1:
  230. temp = upper & 0xFFFFFFFF;
  231. upper = uint64_t(int64_t(upper) >> 32);
  232. lower >>= 32;
  233. lower |= uint64_t(temp) << 32;
  234. case 2:
  235. lower = upper;
  236. upper = uint64_t(int64_t(upper) >> 63);
  237. case 3:
  238. lower = uint64_t(int64_t(upper) >> 32);
  239. upper = uint64_t(int64_t(upper) >> 63);
  240. default:
  241. lower = uint64_t(int64_t(upper) >> 63);
  242. upper = uint64_t(int64_t(upper) >> 63);
  243. }
  244. }*/
  245. /*
  246. inline Fixed128 operator * (const Fixed128& other) const {
  247. int32_t quarters[4] = {
  248. (upper >> 32) & 0xFFFFFFFF,
  249. upper & 0xFFFFFFFF,
  250. (lower >> 32) & 0xFFFFFFFF,
  251. lower & 0xFFFFFFFF
  252. };
  253. int32_t otherQuarters[4] = {
  254. (other.upper >> 32) & 0xFFFFFFFF,
  255. other.upper & 0xFFFFFFFF,
  256. (other.lower >> 32) & 0xFFFFFFFF,
  257. other.lower & 0xFFFFFFFF
  258. };
  259. int64_t prods[4][4];
  260. for (int i = 0; i < 4; i++) {
  261. for (int j = 0; j < 4 && j + i < 5; j++) {
  262. if (i == 0 || j == 0)
  263. prods[i][j] = int64_t(quarters[i]) * int64_t(otherQuarters[j]);
  264. else
  265. prods[i][j] = uint64_t(uint32_t(quarters[i])) * uint64_t(uint32_t(otherQuarters[j]));
  266. }
  267. }
  268. Fixed128 ret = { 0, 0 };
  269. for (int i = 0; i < 4; i++) {
  270. for (int j = 0; j < 4 && j + i < 5; j++) {
  271. if (i == 0 || j == 0)
  272. ret.addSigned(prods[i][j], i + j);
  273. else
  274. ret.add(prods[i][j], i + j);
  275. }
  276. }
  277. return ret;
  278. /*
  279. int64_t x00 = int64_t(quarters[0]) * int64_t(otherQuarters[0]);
  280. int64_t x01 = int64_t(quarters[0]) * int64_t(otherQuarters[1]);
  281. int64_t x02 = int64_t(quarters[0]) * int64_t(otherQuarters[2]);
  282. int64_t x03 = int64_t(quarters[0]) * int64_t(otherQuarters[3]);
  283. int64_t x10 = int64_t(quarters[1]) * int64_t(otherQuarters[0]);
  284. int64_t x11 = int64_t(quarters[1]) * int64_t(otherQuarters[1]);
  285. int64_t x12 = int64_t(quarters[1]) * int64_t(otherQuarters[2]);
  286. int64_t x13 = int64_t(quarters[1]) * int64_t(otherQuarters[3]);
  287. int64_t x20 = int64_t(quarters[2]) * int64_t(otherQuarters[0]);
  288. int64_t x21 = int64_t(quarters[2]) * int64_t(otherQuarters[1]);
  289. int64_t x22 = int64_t(quarters[2]) * int64_t(otherQuarters[2]);
  290. int64_t x30 = int64_t(quarters[3]) * int64_t(otherQuarters[0]);
  291. int64_t x31 = int64_t(quarters[3]) * int64_t(otherQuarters[1]);
  292. Fixed128 ret = { 0, 0 };
  293. /*uint32_t newQuarters[4] = {
  294. x00,
  295. x01 + x10,
  296. x02 + x11 + x20,
  297. x03 + x12 + x21 + x30,
  298. };*//*
  299. ret.add(x00, 0);
  300. ret.add(x01 + x10, 1);
  301. ret.add(x02 + x11 + x20, 2);
  302. ret.add(x03 + x12 + x21 + x30, 3);
  303. ret.add(x13 + x22 + x31, 4);
  304. return ret;*/
  305. /*}*/
  306. private:
  307. inline void add(uint64_t val, int b32offset) {
  308. switch (b32offset) {
  309. case 0:
  310. upper += val << 32;
  311. return;
  312. case 1:
  313. upper += val;
  314. return;
  315. case 2:
  316. upper += val >> 32;
  317. lower += val << 32;
  318. return;
  319. case 3: {
  320. uint64_t newLower = lower + val;
  321. if (newLower < lower) upper++;
  322. lower = newLower;
  323. return;
  324. }
  325. case 4:
  326. uint64_t newLower = lower + (val >> 32);
  327. if (lower > newLower) upper++;
  328. lower += newLower;
  329. return;
  330. }
  331. }
  332. inline void addSigned(int64_t val, int b32offset) {
  333. switch (b32offset) {
  334. case 0:
  335. upper += val << 32;
  336. return;
  337. case 1:
  338. upper += val;
  339. return;
  340. case 2:
  341. upper += val >> 32;
  342. lower += val << 32;
  343. return;
  344. case 3:
  345. lower += val;
  346. if (val < 0) upper--;
  347. return;
  348. case 4: {
  349. uint64_t newLower = lower + (val >> 32);
  350. if (lower > newLower) upper++;
  351. lower = newLower;
  352. return;
  353. }
  354. default:
  355. if (val < 0) {
  356. if (lower == 0) upper--;
  357. lower--;
  358. }
  359. return;
  360. }
  361. }
  362. public:
  363. inline Fixed128 operator / (const Fixed128& other) {
  364. if (this->operator!=(Fixed128{ 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF }) && isNegative()) {
  365. return -((-(*this)) / other);
  366. }
  367. if (other != Fixed128{ 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF } && other.isNegative()) {
  368. return -((*this) / (-other));
  369. }
  370. using u256 = std::array<uint64_t, 4>;
  371. u256 bigDividend = { upper, lower, 0, 0 };
  372. u256 bigDivisor = { 0, 0, other.upper, other.lower };
  373. auto twice = [] (u256& x) {
  374. bool carry = false;
  375. for (int i = 3; i >= 0; i--) {
  376. bool oldCarry = carry;
  377. carry = x[i] & 0x1000000000000000ULL;
  378. x[i] <<= 1;
  379. if (oldCarry) x[i] ++;
  380. }
  381. };
  382. auto geq = [] (const u256& a, const u256& b) -> bool {
  383. for (int i = 0; i < 4; i++) {
  384. if (a[i] > b[i])
  385. return true;
  386. if (a[i] < b[i])
  387. return false;
  388. }
  389. return true;
  390. };
  391. auto sub = [] (u256& a, const u256& b) -> bool {
  392. bool carry = false;
  393. for (int i = 3; i >= 0; i--) {
  394. uint64_t oldA = a[i];
  395. a[i] -= b[i];
  396. carry = oldA < a[i];
  397. }
  398. return carry;
  399. };
  400. auto add = [] (u256& a, const u256& b) -> bool {
  401. bool carry = false;
  402. for (int i = 3; i >= 0; i--) {
  403. uint64_t oldA = a[i];
  404. a[i] += b[i];
  405. carry = oldA > a[i];
  406. }
  407. return carry;
  408. };
  409. u256 growingCount = { 0, 0, 0, 1 };
  410. u256 quotient = { 0, 0, 0, 0 };
  411. std::vector<u256> growingStack = { bigDivisor };
  412. while (true) {
  413. u256 beforeSub = bigDividend;
  414. const u256& gr = growingStack[growingStack.size() - 1];
  415. if (!sub(bigDividend, gr)) {
  416. add(quotient, growingCount);
  417. u256 tw = gr; twice(tw);
  418. growingStack.push_back(tw);
  419. }
  420. else if (geq(bigDivisor, bigDividend)) {
  421. break;
  422. }
  423. else {
  424. bigDividend = beforeSub;
  425. growingStack.pop_back();
  426. }
  427. }
  428. return Fixed128{ quotient[2], quotient[3] };
  429. }
  430. bool isNegative(void) const {
  431. return upper >> 63;
  432. }
  433. operator double(void) const {
  434. const int64_t twoToThe32 = 0x100000000ULL;
  435. return double(int64_t(upper)) / twoToThe32 + int64_t(lower) / twoToThe32 / twoToThe32 / twoToThe32;
  436. }
  437. inline Fixed128 operator ~ (void) const {
  438. return Fixed128{ ~upper, ~lower };
  439. }
  440. inline bool operator == (const Fixed128& other) const {
  441. return upper == other.upper && lower == other.lower;
  442. }
  443. inline bool operator != (const Fixed128& other) const {
  444. return !operator==(other);
  445. }
  446. inline bool operator < (const Fixed128& other) const {
  447. return upper < other.upper || (upper == other.upper && lower < other.lower);
  448. }
  449. inline bool operator <= (const Fixed128& other) const {
  450. return operator<(other) || operator==(other);
  451. }
  452. inline bool operator > (const Fixed128& other) const {
  453. return upper > other.upper || (upper == other.upper && lower > other.lower);
  454. }
  455. inline bool operator >= (const Fixed128& other) const {
  456. return operator>(other) || operator==(other);
  457. }
  458. };
  459. struct Fixed64
  460. {
  461. bool sign;
  462. uint64_t bits;
  463. Fixed64(const Fixed64&) = default;
  464. ~Fixed64() = default;
  465. inline Fixed64(uint64_t bits, bool /* dummy */) :
  466. bits{ bits }
  467. {
  468. }
  469. inline Fixed64(double x)
  470. {
  471. if (x < 0) {
  472. sign = true;
  473. x *= -1;
  474. }
  475. else {
  476. sign = false;
  477. }
  478. int integerPart = int(x);
  479. double fractionalPart = x - integerPart;
  480. bits = uint64_t(integerPart) << 32;
  481. bits |= uint64_t(fractionalPart * (1ULL << 32)) & 0xFFFFFFFF;
  482. }
  483. inline Fixed64 operator + (const Fixed64& other) {
  484. return Fixed64{ bits + other.bits, true };
  485. }
  486. inline Fixed64& operator +=(const Fixed64& other) {
  487. bits += other.bits;
  488. return *this;
  489. }
  490. inline Fixed64 operator - (const Fixed64& other) {
  491. return Fixed64{ bits - other.bits, true };
  492. }
  493. inline Fixed64 operator * (const Fixed64& other) {
  494. /*int32_t upper = bits >> 32;
  495. uint32_t lower = uint32_t(bits & 0xFFFFFFFF);
  496. int64_t upup = int64_t(upper) * int64_t(upper);
  497. int64_t loup = int64_t(upper) * int64_t(lower);
  498. int64_t lolo = int64_t(lower) * int64_t(lower);
  499. int32_t newUp = upup & 0xFFFFFFFF + (loup >> 32);
  500. int32_t newLo = loup & 0xFFFFFFFF + (lolo >> 32);*/
  501. double d = int32_t(bits >> 32) + double(uint32_t(bits)) / (1ULL << 32);
  502. double od = int32_t(other.bits >> 32) + double(uint32_t(other.bits)) / (1ULL << 32);
  503. return d * od * ((other.sign != sign) ? -1 : 1);
  504. //return Fixed64{ (uint64_t(newUp) << 32) | newLo, true };
  505. }
  506. inline bool operator == (const Fixed64& other) {
  507. return bits == other.bits;
  508. }
  509. inline bool operator != (const Fixed64& other) {
  510. return !operator==(other);
  511. }
  512. inline bool operator < (const Fixed64& other) {
  513. return bits < other.bits;
  514. }
  515. inline bool operator <= (const Fixed64& other) {
  516. return operator<(other) || operator==(other);
  517. }
  518. inline bool operator > (const Fixed64& other) {
  519. return bits > other.bits;
  520. }
  521. inline bool operator >= (const Fixed64& other) {
  522. return operator>(other) || operator==(other);
  523. }
  524. };
  525. struct Fixed32
  526. {
  527. int32_t bits;
  528. Fixed32(const Fixed32&) = default;
  529. ~Fixed32() = default;
  530. inline Fixed32(int32_t bits, bool dummy) :
  531. bits{ bits }
  532. {
  533. }
  534. inline Fixed32(double x)
  535. {
  536. int integerPart = int(::floor(x));
  537. double fractionalPart = x - integerPart;
  538. /*if (x < 0) {
  539. integerPart--;
  540. fractionalPart = 1.0 - fractionalPart;
  541. }*/
  542. bits = int32_t(integerPart) << 16;
  543. bits |= uint32_t(fractionalPart * (1ULL << 16)) & 0xFFFF;
  544. }
  545. inline Fixed32 operator + (const Fixed32& other) {
  546. return Fixed32{ bits + other.bits, true };
  547. }
  548. inline Fixed32& operator +=(const Fixed32& other) {
  549. bits += other.bits;
  550. return *this;
  551. }
  552. inline Fixed32 operator - (const Fixed32& other) {
  553. return Fixed32{ bits - other.bits, true };
  554. }
  555. inline Fixed32 operator * (const Fixed32& other) {
  556. int64_t prod = int64_t(bits) * int64_t(other.bits);
  557. return Fixed32{ int32_t(prod >> 16), true };
  558. //return Fixed32{ (uint64_t(newUp) << 32) | newLo, true };
  559. }
  560. inline bool operator == (const Fixed32& other) {
  561. return bits == other.bits;
  562. }
  563. inline bool operator != (const Fixed32& other) {
  564. return !operator==(other);
  565. }
  566. inline bool operator < (const Fixed32& other) {
  567. return bits < other.bits;
  568. }
  569. inline bool operator <= (const Fixed32& other) {
  570. return operator<(other) || operator==(other);
  571. }
  572. inline bool operator > (const Fixed32& other) {
  573. return bits > other.bits;
  574. }
  575. inline bool operator >= (const Fixed32& other) {
  576. return operator>(other) || operator==(other);
  577. }
  578. };
  579. #endif // MANDEL_FIXED128_H