FixedPoint.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. 
  2. // zlib open source license
  3. //
  4. // Copyright (c) 2019 David Forsgren Piuva
  5. //
  6. // This software is provided 'as-is', without any express or implied
  7. // warranty. In no event will the authors be held liable for any damages
  8. // arising from the use of this software.
  9. //
  10. // Permission is granted to anyone to use this software for any purpose,
  11. // including commercial applications, and to alter it and redistribute it
  12. // freely, subject to the following restrictions:
  13. //
  14. // 1. The origin of this software must not be misrepresented; you must not
  15. // claim that you wrote the original software. If you use this software
  16. // in a product, an acknowledgment in the product documentation would be
  17. // appreciated but is not required.
  18. //
  19. // 2. Altered source versions must be plainly marked as such, and must not be
  20. // misrepresented as being the original software.
  21. //
  22. // 3. This notice may not be removed or altered from any source
  23. // distribution.
  24. #include "FixedPoint.h"
  25. #include <cmath> // Only use the methods guaranteed to be exact, unless an approximation is requested
  26. using namespace dsr;
  27. /* This sum of 0.9999999999999999999 explains why including the 20:th decimal would cause overflow from rounding to closest.
  28. 16602069666338596454 + 1660206966633859645 // 0.9 + 0.09
  29. 18262276632972456099 + 166020696663385965 // 0.99 + 0.009
  30. 18428297329635842064 + 16602069666338596 // 0.999 + 0.0009
  31. 18444899399302180660 + 1660206966633860 // 0.9999 + 0.00009
  32. 18446559606268814520 + 166020696663386 // 0.99999 + 0.000009
  33. 18446725626965477906 + 16602069666339 // 0.999999 + 0.0000009
  34. 18446742229035144245 + 1660206966634 // 0.9999999 + 0.00000009
  35. 18446743889242110879 + 166020696663 // 0.99999999 + 0.000000009
  36. 18446744055262807542 + 16602069666 // 0.999999999 + 0.0000000009
  37. 18446744071864877208 + 1660206967 // 0.9999999999 + 0.00000000009
  38. 18446744073525084175 + 166020697 // 0.99999999999 + 0.000000000009
  39. 18446744073691104872 + 16602070 // 0.999999999999 + 0.0000000000009
  40. 18446744073707706942 + 1660207 // 0.9999999999999 + 0.00000000000009
  41. 18446744073709367149 + 166021 // 0.99999999999999 + 0.000000000000009
  42. 18446744073709533170 + 16602 // 0.999999999999999 + 0.0000000000000009
  43. 18446744073709549772 + 1660 // 0.9999999999999999 + 0.00000000000000009
  44. 18446744073709551432 + 166 // 0.99999999999999999 + 0.000000000000000009
  45. 18446744073709551598 + 17 // 0.999999999999999999 + 0.0000000000000000009
  46. 18446744073709551615 // 0.9999999999999999999
  47. 18446744073709551616 // 1.0
  48. */
  49. // Including the 20:th decimal would cause overflow from rounding to closest.
  50. const int maxDecimals = 19;
  51. // Each group of 9 values contains the digit fractions for a certain location
  52. static const uint64_t decimalFractions64[maxDecimals * 9] = {
  53. // Calculated using the Wolfram expression "round(18446744073709551616 * 1 / 10)" et cetera...
  54. UINT64_C( 1844674407370955162), // 2^64 * 0.1
  55. UINT64_C( 3689348814741910323), // 2^64 * 0.2
  56. UINT64_C( 5534023222112865485), // 2^64 * 0.3
  57. UINT64_C( 7378697629483820646), // 2^64 * 0.4
  58. UINT64_C( 9223372036854775808), // 2^64 * 0.5
  59. UINT64_C(11068046444225730970), // 2^64 * 0.6
  60. UINT64_C(12912720851596686131), // 2^64 * 0.7
  61. UINT64_C(14757395258967641293), // 2^64 * 0.8
  62. UINT64_C(16602069666338596454), // 2^64 * 0.9
  63. UINT64_C( 184467440737095516), // 2^64 * 0.01
  64. UINT64_C( 368934881474191032), // 2^64 * 0.02
  65. UINT64_C( 553402322211286548), // 2^64 * 0.03
  66. UINT64_C( 737869762948382065), // 2^64 * 0.04
  67. UINT64_C( 922337203685477581), // 2^64 * 0.05
  68. UINT64_C(1106804644422573097), // 2^64 * 0.06
  69. UINT64_C(1291272085159668613), // 2^64 * 0.07
  70. UINT64_C(1475739525896764129), // 2^64 * 0.08
  71. UINT64_C(1660206966633859645), // 2^64 * 0.09
  72. UINT64_C( 18446744073709552), // 2^64 * 0.001
  73. UINT64_C( 36893488147419103), // 2^64 * 0.002
  74. UINT64_C( 55340232221128655), // 2^64 * 0.003
  75. UINT64_C( 73786976294838206), // 2^64 * 0.004
  76. UINT64_C( 92233720368547758), // 2^64 * 0.005
  77. UINT64_C(110680464442257310), // 2^64 * 0.006
  78. UINT64_C(129127208515966861), // 2^64 * 0.007
  79. UINT64_C(147573952589676413), // 2^64 * 0.008
  80. UINT64_C(166020696663385965), // 2^64 * 0.009
  81. UINT64_C( 1844674407370955), // 2^64 * 0.0001
  82. UINT64_C( 3689348814741910), // 2^64 * 0.0002
  83. UINT64_C( 5534023222112865), // 2^64 * 0.0003
  84. UINT64_C( 7378697629483821), // 2^64 * 0.0004
  85. UINT64_C( 9223372036854776), // 2^64 * 0.0005
  86. UINT64_C(11068046444225731), // 2^64 * 0.0006
  87. UINT64_C(12912720851596686), // 2^64 * 0.0007
  88. UINT64_C(14757395258967641), // 2^64 * 0.0008
  89. UINT64_C(16602069666338596), // 2^64 * 0.0009
  90. UINT64_C( 184467440737096), // 2^64 * 0.00001
  91. UINT64_C( 368934881474191), // 2^64 * 0.00002
  92. UINT64_C( 553402322211287), // 2^64 * 0.00003
  93. UINT64_C( 737869762948382), // 2^64 * 0.00004
  94. UINT64_C( 922337203685478), // 2^64 * 0.00005
  95. UINT64_C(1106804644422573), // 2^64 * 0.00006
  96. UINT64_C(1291272085159669), // 2^64 * 0.00007
  97. UINT64_C(1475739525896764), // 2^64 * 0.00008
  98. UINT64_C(1660206966633860), // 2^64 * 0.00009
  99. UINT64_C( 18446744073710), // 2^64 * 0.000001
  100. UINT64_C( 36893488147419), // 2^64 * 0.000002
  101. UINT64_C( 55340232221129), // 2^64 * 0.000003
  102. UINT64_C( 73786976294838), // 2^64 * 0.000004
  103. UINT64_C( 92233720368548), // 2^64 * 0.000005
  104. UINT64_C(110680464442257), // 2^64 * 0.000006
  105. UINT64_C(129127208515967), // 2^64 * 0.000007
  106. UINT64_C(147573952589676), // 2^64 * 0.000008
  107. UINT64_C(166020696663386), // 2^64 * 0.000009
  108. UINT64_C( 1844674407371), // 2^64 * 0.0000001
  109. UINT64_C( 3689348814742), // 2^64 * 0.0000002
  110. UINT64_C( 5534023222113), // 2^64 * 0.0000003
  111. UINT64_C( 7378697629484), // 2^64 * 0.0000004
  112. UINT64_C( 9223372036855), // 2^64 * 0.0000005
  113. UINT64_C(11068046444226), // 2^64 * 0.0000006
  114. UINT64_C(12912720851597), // 2^64 * 0.0000007
  115. UINT64_C(14757395258968), // 2^64 * 0.0000008
  116. UINT64_C(16602069666339), // 2^64 * 0.0000009
  117. UINT64_C( 184467440737), // 2^64 * 0.00000001
  118. UINT64_C( 368934881474), // 2^64 * 0.00000002
  119. UINT64_C( 553402322211), // 2^64 * 0.00000003
  120. UINT64_C( 737869762948), // 2^64 * 0.00000004
  121. UINT64_C( 922337203685), // 2^64 * 0.00000005
  122. UINT64_C(1106804644423), // 2^64 * 0.00000006
  123. UINT64_C(1291272085160), // 2^64 * 0.00000007
  124. UINT64_C(1475739525897), // 2^64 * 0.00000008
  125. UINT64_C(1660206966634), // 2^64 * 0.00000009
  126. UINT64_C( 18446744074), // 2^64 * 0.000000001
  127. UINT64_C( 36893488147), // 2^64 * 0.000000002
  128. UINT64_C( 55340232221), // 2^64 * 0.000000003
  129. UINT64_C( 73786976295), // 2^64 * 0.000000004
  130. UINT64_C( 92233720369), // 2^64 * 0.000000005
  131. UINT64_C(110680464442), // 2^64 * 0.000000006
  132. UINT64_C(129127208516), // 2^64 * 0.000000007
  133. UINT64_C(147573952590), // 2^64 * 0.000000008
  134. UINT64_C(166020696663), // 2^64 * 0.000000009
  135. UINT64_C( 1844674407), // 2^64 * 0.0000000001
  136. UINT64_C( 3689348815), // 2^64 * 0.0000000002
  137. UINT64_C( 5534023222), // 2^64 * 0.0000000003
  138. UINT64_C( 7378697629), // 2^64 * 0.0000000004
  139. UINT64_C( 9223372037), // 2^64 * 0.0000000005
  140. UINT64_C(11068046444), // 2^64 * 0.0000000006
  141. UINT64_C(12912720852), // 2^64 * 0.0000000007
  142. UINT64_C(14757395259), // 2^64 * 0.0000000008
  143. UINT64_C(16602069666), // 2^64 * 0.0000000009
  144. UINT64_C( 184467441), // 2^64 * 0.00000000001
  145. UINT64_C( 368934881), // 2^64 * 0.00000000002
  146. UINT64_C( 553402322), // 2^64 * 0.00000000003
  147. UINT64_C( 737869763), // 2^64 * 0.00000000004
  148. UINT64_C( 922337204), // 2^64 * 0.00000000005
  149. UINT64_C(1106804644), // 2^64 * 0.00000000006
  150. UINT64_C(1291272085), // 2^64 * 0.00000000007
  151. UINT64_C(1475739526), // 2^64 * 0.00000000008
  152. UINT64_C(1660206967), // 2^64 * 0.00000000009
  153. UINT64_C( 18446744), // 2^64 * 0.000000000001
  154. UINT64_C( 36893488), // 2^64 * 0.000000000002
  155. UINT64_C( 55340232), // 2^64 * 0.000000000003
  156. UINT64_C( 73786976), // 2^64 * 0.000000000004
  157. UINT64_C( 92233720), // 2^64 * 0.000000000005
  158. UINT64_C(110680464), // 2^64 * 0.000000000006
  159. UINT64_C(129127209), // 2^64 * 0.000000000007
  160. UINT64_C(147573953), // 2^64 * 0.000000000008
  161. UINT64_C(166020697), // 2^64 * 0.000000000009
  162. UINT64_C( 1844674), // 2^64 * 0.0000000000001
  163. UINT64_C( 3689349), // 2^64 * 0.0000000000002
  164. UINT64_C( 5534023), // 2^64 * 0.0000000000003
  165. UINT64_C( 7378698), // 2^64 * 0.0000000000004
  166. UINT64_C( 9223372), // 2^64 * 0.0000000000005
  167. UINT64_C(11068046), // 2^64 * 0.0000000000006
  168. UINT64_C(12912721), // 2^64 * 0.0000000000007
  169. UINT64_C(14757395), // 2^64 * 0.0000000000008
  170. UINT64_C(16602070), // 2^64 * 0.0000000000009
  171. UINT64_C( 184467), // 2^64 * 0.00000000000001
  172. UINT64_C( 368935), // 2^64 * 0.00000000000002
  173. UINT64_C( 553402), // 2^64 * 0.00000000000003
  174. UINT64_C( 737870), // 2^64 * 0.00000000000004
  175. UINT64_C( 922337), // 2^64 * 0.00000000000005
  176. UINT64_C(1106805), // 2^64 * 0.00000000000006
  177. UINT64_C(1291272), // 2^64 * 0.00000000000007
  178. UINT64_C(1475740), // 2^64 * 0.00000000000008
  179. UINT64_C(1660207), // 2^64 * 0.00000000000009
  180. UINT64_C( 18447), // 2^64 * 0.000000000000001
  181. UINT64_C( 36893), // 2^64 * 0.000000000000002
  182. UINT64_C( 55340), // 2^64 * 0.000000000000003
  183. UINT64_C( 73787), // 2^64 * 0.000000000000004
  184. UINT64_C( 92234), // 2^64 * 0.000000000000005
  185. UINT64_C(110680), // 2^64 * 0.000000000000006
  186. UINT64_C(129127), // 2^64 * 0.000000000000007
  187. UINT64_C(147574), // 2^64 * 0.000000000000008
  188. UINT64_C(166021), // 2^64 * 0.000000000000009
  189. UINT64_C( 1845), // 2^64 * 0.0000000000000001
  190. UINT64_C( 3689), // 2^64 * 0.0000000000000002
  191. UINT64_C( 5534), // 2^64 * 0.0000000000000003
  192. UINT64_C( 7379), // 2^64 * 0.0000000000000004
  193. UINT64_C( 9223), // 2^64 * 0.0000000000000005
  194. UINT64_C(11068), // 2^64 * 0.0000000000000006
  195. UINT64_C(12913), // 2^64 * 0.0000000000000007
  196. UINT64_C(14757), // 2^64 * 0.0000000000000008
  197. UINT64_C(16602), // 2^64 * 0.0000000000000009
  198. UINT64_C( 184), // 2^64 * 0.00000000000000001
  199. UINT64_C( 369), // 2^64 * 0.00000000000000002
  200. UINT64_C( 553), // 2^64 * 0.00000000000000003
  201. UINT64_C( 738), // 2^64 * 0.00000000000000004
  202. UINT64_C( 922), // 2^64 * 0.00000000000000005
  203. UINT64_C(1107), // 2^64 * 0.00000000000000006
  204. UINT64_C(1291), // 2^64 * 0.00000000000000007
  205. UINT64_C(1476), // 2^64 * 0.00000000000000008
  206. UINT64_C(1660), // 2^64 * 0.00000000000000009
  207. UINT64_C( 18), // 2^64 * 0.000000000000000001
  208. UINT64_C( 37), // 2^64 * 0.000000000000000002
  209. UINT64_C( 55), // 2^64 * 0.000000000000000003
  210. UINT64_C( 74), // 2^64 * 0.000000000000000004
  211. UINT64_C( 92), // 2^64 * 0.000000000000000005
  212. UINT64_C(111), // 2^64 * 0.000000000000000006
  213. UINT64_C(129), // 2^64 * 0.000000000000000007
  214. UINT64_C(148), // 2^64 * 0.000000000000000008
  215. UINT64_C(166), // 2^64 * 0.000000000000000009
  216. UINT64_C( 2), // 2^64 * 0.0000000000000000001
  217. UINT64_C( 4), // 2^64 * 0.0000000000000000002
  218. UINT64_C( 6), // 2^64 * 0.0000000000000000003
  219. UINT64_C( 7), // 2^64 * 0.0000000000000000004
  220. UINT64_C( 9), // 2^64 * 0.0000000000000000005
  221. UINT64_C(11), // 2^64 * 0.0000000000000000006
  222. UINT64_C(13), // 2^64 * 0.0000000000000000007
  223. UINT64_C(15), // 2^64 * 0.0000000000000000008
  224. UINT64_C(17), // 2^64 * 0.0000000000000000009
  225. };
  226. // Index 0 returns 0.1 in the 64-bit fraction system
  227. // Index 1 represents 0.01, et cetera
  228. static const uint64_t getDecimalFraction64(int decimalPosition, int digit) {
  229. if (decimalPosition < 0 || decimalPosition >= maxDecimals || digit < 1 || digit > 9) {
  230. return 0;
  231. } else {
  232. return decimalFractions64[(decimalPosition * 9) + (digit - 1)];
  233. }
  234. }
  235. FixedPoint::FixedPoint() : mantissa(0) {}
  236. FixedPoint::FixedPoint(int64_t newMantissa) {
  237. clampForInt32(newMantissa);
  238. this->mantissa = newMantissa;
  239. }
  240. FixedPoint FixedPoint::fromWhole(int64_t wholeInteger) {
  241. clampForSaturatedWhole(wholeInteger);
  242. return FixedPoint(wholeInteger * 65536); // Does this need to saturate again?
  243. }
  244. FixedPoint FixedPoint::fromMantissa(int64_t mantissa) {
  245. return FixedPoint(mantissa);
  246. }
  247. FixedPoint FixedPoint::fromText(const ReadableString& text) {
  248. ReadableString content = string_removeOuterWhiteSpace(text);
  249. bool isSigned = string_findFirst(content, U'-') > -1; // Should also be last
  250. int decimal = string_findFirst(content, U'.');
  251. int colon = string_findFirst(content, U':');
  252. int64_t result = 0;
  253. if (decimal > -1 && colon == -1) {
  254. // Floating-point decimal
  255. // TODO: Give warnings for incorrect whole integers
  256. int64_t wholeInteger = string_toInteger(string_before(content, decimal));
  257. ReadableString decimals = string_after(content, decimal);
  258. uint64_t fraction = 0; // Extra high precision for accumulation
  259. for (int i = 0; i < string_length(decimals); i++) {
  260. DsrChar digit = decimals[i];
  261. if (digit >= U'1' && digit <= U'9') {
  262. fraction += getDecimalFraction64(i, digit - U'0');
  263. } // else if (digit != U'0') // TODO: Give warnings for any non-digit characters.
  264. }
  265. // Truncate the fraction down to 32-bits before safely rounding to closest 16-bit fraction
  266. int64_t signedFraction = ((fraction >> 32) + 32768) >> 16; // Convert to closest 16-bit fraction
  267. if (isSigned) { signedFraction = -signedFraction; }
  268. result = (wholeInteger * 65536) + signedFraction; // Does this need to saturate again?
  269. } else if (decimal == -1 && colon > -1) {
  270. // Whole integer and 16-bit fraction
  271. // TODO: Give warnings for incorrect integers
  272. int64_t wholeInteger = string_toInteger(string_before(content, colon));
  273. int64_t fraction = string_toInteger(string_after(content, colon));
  274. clampForSaturatedWhole(wholeInteger);
  275. if (isSigned) { fraction = -fraction; }
  276. result = (wholeInteger * 65536) + fraction;
  277. } else if (decimal == -1 && colon == -1) {
  278. // Whole
  279. int64_t wholeInteger = string_toInteger(content);
  280. clampForSaturatedWhole(wholeInteger);
  281. result = wholeInteger * 65536; // Does this need to saturate again?
  282. } // TODO: Give a warning if both . and : is used!
  283. return FixedPoint(result);
  284. }
  285. FixedPoint FixedPoint::zero() {
  286. return FixedPoint(0);
  287. }
  288. FixedPoint FixedPoint::epsilon() {
  289. return FixedPoint(1);
  290. }
  291. FixedPoint FixedPoint::half() {
  292. return FixedPoint(32768);
  293. }
  294. FixedPoint FixedPoint::one() {
  295. return FixedPoint(65536);
  296. }
  297. int32_t dsr::fixedPoint_round(const FixedPoint& value) {
  298. int64_t mantissa = value.getMantissa();
  299. int32_t offset = mantissa >= 0 ? 32768 : -32768;
  300. return (mantissa + offset) / 65536;
  301. }
  302. double dsr::fixedPoint_approximate(const FixedPoint& value) {
  303. return ((double)value.getMantissa()) * (1.0 / 65536.0);
  304. }
  305. String& dsr::string_toStreamIndented(String& target, const FixedPoint& value, const ReadableString& indentation) {
  306. // TODO: Make own fixed-point serialization which cannot resort to scientific notation
  307. string_append(target, indentation, fixedPoint_approximate(value));
  308. return target;
  309. }
  310. FixedPoint dsr::fixedPoint_min(const FixedPoint &left, const FixedPoint &right) {
  311. int64_t result = left.getMantissa();
  312. int64_t other = right.getMantissa();
  313. if (other < result) result = other;
  314. return FixedPoint(result);
  315. }
  316. FixedPoint dsr::fixedPoint_max(const FixedPoint &left, const FixedPoint &right) {
  317. int64_t result = left.getMantissa();
  318. int64_t other = right.getMantissa();
  319. if (other > result) result = other;
  320. return FixedPoint(result);
  321. }
  322. FixedPoint dsr::fixedPoint_divide(const FixedPoint &left, const FixedPoint &right) {
  323. int64_t mantissa = 0;
  324. if (right.getMantissa() == 0) {
  325. if (left.getMantissa() > 0) {
  326. mantissa = 2147483647; // Saturate from positive infinity
  327. } else if (left.getMantissa() < 0) {
  328. mantissa = -2147483648; // Saturate from negative infinity
  329. }
  330. } else {
  331. mantissa = (left.getMantissa() * 65536) / right.getMantissa();
  332. }
  333. return FixedPoint(mantissa);
  334. }
  335. FixedPoint dsr::fixedPoint_divide(const FixedPoint &left, int64_t right) {
  336. int64_t mantissa = 0;
  337. if (right == 0) {
  338. if (left.getMantissa() > 0) {
  339. mantissa = 2147483647; // Saturate from positive infinity
  340. } else if (left.getMantissa() < 0) {
  341. mantissa = -2147483648; // Saturate from negative infinity
  342. }
  343. } else {
  344. mantissa = left.getMantissa() / right;
  345. }
  346. return FixedPoint(mantissa);
  347. }
  348. // 48-bit to 24-bit unsigned integer square root.
  349. // Returns the root of square rounded down.
  350. static uint64_t integer_squareRoot_U48(uint64_t square) {
  351. // Even thou a double is used, the C++ standard guarantees exact results.
  352. // Source: https://en.cppreference.com/w/cpp/numeric/math/sqrt
  353. // "std::sqrt is required by the IEEE standard to be exact.
  354. // The only other operations required to be exact are the arithmetic
  355. // operators and the function std::fma. After rounding to the return
  356. // type (using default rounding mode), the result of std::sqrt is
  357. // indistinguishable from the infinitely precise result.
  358. // In other words, the error is less than 0.5 ulp."
  359. return (uint64_t)(std::sqrt((double)square));
  360. }
  361. FixedPoint dsr::fixedPoint_squareRoot(const FixedPoint& value) {
  362. int64_t mantissa = value.getMantissa();
  363. if (mantissa <= 0) {
  364. // The real part of 0 + i * sqrt(value) is always zero
  365. return FixedPoint(0);
  366. } else {
  367. return FixedPoint(integer_squareRoot_U48(((uint64_t)mantissa) << 16));
  368. }
  369. }