FixedPointTest.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644
  1. //===- unittests/Basic/FixedPointTest.cpp -- fixed point number tests -----===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "clang/Basic/FixedPoint.h"
  9. #include "llvm/ADT/APSInt.h"
  10. #include "gtest/gtest.h"
  11. using clang::APFixedPoint;
  12. using clang::FixedPointSemantics;
  13. using llvm::APInt;
  14. using llvm::APSInt;
  15. namespace {
  16. FixedPointSemantics Saturated(FixedPointSemantics Sema) {
  17. Sema.setSaturated(true);
  18. return Sema;
  19. }
  20. FixedPointSemantics getSAccumSema() {
  21. return FixedPointSemantics(/*width=*/16, /*scale=*/7, /*isSigned=*/true,
  22. /*isSaturated=*/false,
  23. /*hasUnsignedPadding=*/false);
  24. }
  25. FixedPointSemantics getAccumSema() {
  26. return FixedPointSemantics(/*width=*/32, /*scale=*/15, /*isSigned=*/true,
  27. /*isSaturated=*/false,
  28. /*hasUnsignedPadding=*/false);
  29. }
  30. FixedPointSemantics getLAccumSema() {
  31. return FixedPointSemantics(/*width=*/64, /*scale=*/31, /*isSigned=*/true,
  32. /*isSaturated=*/false,
  33. /*hasUnsignedPadding=*/false);
  34. }
  35. FixedPointSemantics getSFractSema() {
  36. return FixedPointSemantics(/*width=*/8, /*scale=*/7, /*isSigned=*/true,
  37. /*isSaturated=*/false,
  38. /*hasUnsignedPadding=*/false);
  39. }
  40. FixedPointSemantics getFractSema() {
  41. return FixedPointSemantics(/*width=*/16, /*scale=*/15, /*isSigned=*/true,
  42. /*isSaturated=*/false,
  43. /*hasUnsignedPadding=*/false);
  44. }
  45. FixedPointSemantics getLFractSema() {
  46. return FixedPointSemantics(/*width=*/32, /*scale=*/31, /*isSigned=*/true,
  47. /*isSaturated=*/false,
  48. /*hasUnsignedPadding=*/false);
  49. }
  50. FixedPointSemantics getUSAccumSema() {
  51. return FixedPointSemantics(/*width=*/16, /*scale=*/8, /*isSigned=*/false,
  52. /*isSaturated=*/false,
  53. /*hasUnsignedPadding=*/false);
  54. }
  55. FixedPointSemantics getUAccumSema() {
  56. return FixedPointSemantics(/*width=*/32, /*scale=*/16, /*isSigned=*/false,
  57. /*isSaturated=*/false,
  58. /*hasUnsignedPadding=*/false);
  59. }
  60. FixedPointSemantics getULAccumSema() {
  61. return FixedPointSemantics(/*width=*/64, /*scale=*/32, /*isSigned=*/false,
  62. /*isSaturated=*/false,
  63. /*hasUnsignedPadding=*/false);
  64. }
  65. FixedPointSemantics getUSFractSema() {
  66. return FixedPointSemantics(/*width=*/8, /*scale=*/8, /*isSigned=*/false,
  67. /*isSaturated=*/false,
  68. /*hasUnsignedPadding=*/false);
  69. }
  70. FixedPointSemantics getUFractSema() {
  71. return FixedPointSemantics(/*width=*/16, /*scale=*/16, /*isSigned=*/false,
  72. /*isSaturated=*/false,
  73. /*hasUnsignedPadding=*/false);
  74. }
  75. FixedPointSemantics getULFractSema() {
  76. return FixedPointSemantics(/*width=*/32, /*scale=*/32, /*isSigned=*/false,
  77. /*isSaturated=*/false,
  78. /*hasUnsignedPadding=*/false);
  79. }
  80. FixedPointSemantics getPadUSAccumSema() {
  81. return FixedPointSemantics(/*width=*/16, /*scale=*/7, /*isSigned=*/false,
  82. /*isSaturated=*/false,
  83. /*hasUnsignedPadding=*/true);
  84. }
  85. FixedPointSemantics getPadUAccumSema() {
  86. return FixedPointSemantics(/*width=*/32, /*scale=*/15, /*isSigned=*/false,
  87. /*isSaturated=*/false,
  88. /*hasUnsignedPadding=*/true);
  89. }
  90. FixedPointSemantics getPadULAccumSema() {
  91. return FixedPointSemantics(/*width=*/64, /*scale=*/31, /*isSigned=*/false,
  92. /*isSaturated=*/false,
  93. /*hasUnsignedPadding=*/true);
  94. }
  95. FixedPointSemantics getPadUSFractSema() {
  96. return FixedPointSemantics(/*width=*/8, /*scale=*/7, /*isSigned=*/false,
  97. /*isSaturated=*/false,
  98. /*hasUnsignedPadding=*/true);
  99. }
  100. FixedPointSemantics getPadUFractSema() {
  101. return FixedPointSemantics(/*width=*/16, /*scale=*/15, /*isSigned=*/false,
  102. /*isSaturated=*/false,
  103. /*hasUnsignedPadding=*/true);
  104. }
  105. FixedPointSemantics getPadULFractSema() {
  106. return FixedPointSemantics(/*width=*/32, /*scale=*/31, /*isSigned=*/false,
  107. /*isSaturated=*/false,
  108. /*hasUnsignedPadding=*/true);
  109. }
  110. void CheckUnpaddedMax(const FixedPointSemantics &Sema) {
  111. ASSERT_EQ(APFixedPoint::getMax(Sema).getValue(),
  112. APSInt::getMaxValue(Sema.getWidth(), !Sema.isSigned()));
  113. }
  114. void CheckPaddedMax(const FixedPointSemantics &Sema) {
  115. ASSERT_EQ(APFixedPoint::getMax(Sema).getValue(),
  116. APSInt::getMaxValue(Sema.getWidth(), !Sema.isSigned()) >> 1);
  117. }
  118. void CheckMin(const FixedPointSemantics &Sema) {
  119. ASSERT_EQ(APFixedPoint::getMin(Sema).getValue(),
  120. APSInt::getMinValue(Sema.getWidth(), !Sema.isSigned()));
  121. }
  122. TEST(FixedPointTest, getMax) {
  123. CheckUnpaddedMax(getSAccumSema());
  124. CheckUnpaddedMax(getAccumSema());
  125. CheckUnpaddedMax(getLAccumSema());
  126. CheckUnpaddedMax(getUSAccumSema());
  127. CheckUnpaddedMax(getUAccumSema());
  128. CheckUnpaddedMax(getULAccumSema());
  129. CheckUnpaddedMax(getSFractSema());
  130. CheckUnpaddedMax(getFractSema());
  131. CheckUnpaddedMax(getLFractSema());
  132. CheckUnpaddedMax(getUSFractSema());
  133. CheckUnpaddedMax(getUFractSema());
  134. CheckUnpaddedMax(getULFractSema());
  135. CheckPaddedMax(getPadUSAccumSema());
  136. CheckPaddedMax(getPadUAccumSema());
  137. CheckPaddedMax(getPadULAccumSema());
  138. CheckPaddedMax(getPadUSFractSema());
  139. CheckPaddedMax(getPadUFractSema());
  140. CheckPaddedMax(getPadULFractSema());
  141. }
  142. TEST(FixedPointTest, getMin) {
  143. CheckMin(getSAccumSema());
  144. CheckMin(getAccumSema());
  145. CheckMin(getLAccumSema());
  146. CheckMin(getUSAccumSema());
  147. CheckMin(getUAccumSema());
  148. CheckMin(getULAccumSema());
  149. CheckMin(getSFractSema());
  150. CheckMin(getFractSema());
  151. CheckMin(getLFractSema());
  152. CheckMin(getUSFractSema());
  153. CheckMin(getUFractSema());
  154. CheckMin(getULFractSema());
  155. CheckMin(getPadUSAccumSema());
  156. CheckMin(getPadUAccumSema());
  157. CheckMin(getPadULAccumSema());
  158. CheckMin(getPadUSFractSema());
  159. CheckMin(getPadUFractSema());
  160. CheckMin(getPadULFractSema());
  161. }
  162. void CheckIntPart(const FixedPointSemantics &Sema, int64_t IntPart) {
  163. unsigned Scale = Sema.getScale();
  164. // Value with a fraction
  165. APFixedPoint ValWithFract(APInt(Sema.getWidth(),
  166. (IntPart << Scale) + (1ULL << (Scale - 1)),
  167. Sema.isSigned()),
  168. Sema);
  169. ASSERT_EQ(ValWithFract.getIntPart(), IntPart);
  170. // Just fraction
  171. APFixedPoint JustFract(
  172. APInt(Sema.getWidth(), (1ULL << (Scale - 1)), Sema.isSigned()), Sema);
  173. ASSERT_EQ(JustFract.getIntPart(), 0);
  174. // Whole number
  175. APFixedPoint WholeNum(
  176. APInt(Sema.getWidth(), (IntPart << Scale), Sema.isSigned()), Sema);
  177. ASSERT_EQ(WholeNum.getIntPart(), IntPart);
  178. // Negative
  179. if (Sema.isSigned()) {
  180. APFixedPoint Negative(
  181. APInt(Sema.getWidth(), (IntPart << Scale), Sema.isSigned()), Sema);
  182. ASSERT_EQ(Negative.getIntPart(), IntPart);
  183. }
  184. }
  185. void CheckIntPartMin(const FixedPointSemantics &Sema, int64_t Expected) {
  186. ASSERT_EQ(APFixedPoint::getMin(Sema).getIntPart(), Expected);
  187. }
  188. void CheckIntPartMax(const FixedPointSemantics &Sema, uint64_t Expected) {
  189. ASSERT_EQ(APFixedPoint::getMax(Sema).getIntPart(), Expected);
  190. }
  191. TEST(FixedPoint, getIntPart) {
  192. // Normal values
  193. CheckIntPart(getSAccumSema(), 2);
  194. CheckIntPart(getAccumSema(), 2);
  195. CheckIntPart(getLAccumSema(), 2);
  196. CheckIntPart(getUSAccumSema(), 2);
  197. CheckIntPart(getUAccumSema(), 2);
  198. CheckIntPart(getULAccumSema(), 2);
  199. // Zero
  200. CheckIntPart(getSAccumSema(), 0);
  201. CheckIntPart(getAccumSema(), 0);
  202. CheckIntPart(getLAccumSema(), 0);
  203. CheckIntPart(getUSAccumSema(), 0);
  204. CheckIntPart(getUAccumSema(), 0);
  205. CheckIntPart(getULAccumSema(), 0);
  206. CheckIntPart(getSFractSema(), 0);
  207. CheckIntPart(getFractSema(), 0);
  208. CheckIntPart(getLFractSema(), 0);
  209. CheckIntPart(getUSFractSema(), 0);
  210. CheckIntPart(getUFractSema(), 0);
  211. CheckIntPart(getULFractSema(), 0);
  212. // Min
  213. CheckIntPartMin(getSAccumSema(), -256);
  214. CheckIntPartMin(getAccumSema(), -65536);
  215. CheckIntPartMin(getLAccumSema(), -4294967296);
  216. CheckIntPartMin(getSFractSema(), -1);
  217. CheckIntPartMin(getFractSema(), -1);
  218. CheckIntPartMin(getLFractSema(), -1);
  219. // Max
  220. CheckIntPartMax(getSAccumSema(), 255);
  221. CheckIntPartMax(getAccumSema(), 65535);
  222. CheckIntPartMax(getLAccumSema(), 4294967295);
  223. CheckIntPartMax(getUSAccumSema(), 255);
  224. CheckIntPartMax(getUAccumSema(), 65535);
  225. CheckIntPartMax(getULAccumSema(), 4294967295);
  226. CheckIntPartMax(getSFractSema(), 0);
  227. CheckIntPartMax(getFractSema(), 0);
  228. CheckIntPartMax(getLFractSema(), 0);
  229. CheckIntPartMax(getUSFractSema(), 0);
  230. CheckIntPartMax(getUFractSema(), 0);
  231. CheckIntPartMax(getULFractSema(), 0);
  232. // Padded
  233. // Normal Values
  234. CheckIntPart(getPadUSAccumSema(), 2);
  235. CheckIntPart(getPadUAccumSema(), 2);
  236. CheckIntPart(getPadULAccumSema(), 2);
  237. // Zero
  238. CheckIntPart(getPadUSAccumSema(), 0);
  239. CheckIntPart(getPadUAccumSema(), 0);
  240. CheckIntPart(getPadULAccumSema(), 0);
  241. CheckIntPart(getPadUSFractSema(), 0);
  242. CheckIntPart(getPadUFractSema(), 0);
  243. CheckIntPart(getPadULFractSema(), 0);
  244. // Max
  245. CheckIntPartMax(getPadUSAccumSema(), 255);
  246. CheckIntPartMax(getPadUAccumSema(), 65535);
  247. CheckIntPartMax(getPadULAccumSema(), 4294967295);
  248. CheckIntPartMax(getPadUSFractSema(), 0);
  249. CheckIntPartMax(getPadUFractSema(), 0);
  250. CheckIntPartMax(getPadULFractSema(), 0);
  251. }
  252. TEST(FixedPoint, compare) {
  253. // Equality
  254. // With fractional part (2.5)
  255. // Across sizes
  256. ASSERT_EQ(APFixedPoint(320, getSAccumSema()),
  257. APFixedPoint(81920, getAccumSema()));
  258. ASSERT_EQ(APFixedPoint(320, getSAccumSema()),
  259. APFixedPoint(5368709120, getLAccumSema()));
  260. ASSERT_EQ(APFixedPoint(0, getSAccumSema()), APFixedPoint(0, getLAccumSema()));
  261. // Across types (0.5)
  262. ASSERT_EQ(APFixedPoint(64, getSAccumSema()),
  263. APFixedPoint(64, getSFractSema()));
  264. ASSERT_EQ(APFixedPoint(16384, getAccumSema()),
  265. APFixedPoint(16384, getFractSema()));
  266. ASSERT_EQ(APFixedPoint(1073741824, getLAccumSema()),
  267. APFixedPoint(1073741824, getLFractSema()));
  268. // Across widths and types (0.5)
  269. ASSERT_EQ(APFixedPoint(64, getSAccumSema()),
  270. APFixedPoint(16384, getFractSema()));
  271. ASSERT_EQ(APFixedPoint(64, getSAccumSema()),
  272. APFixedPoint(1073741824, getLFractSema()));
  273. // Across saturation
  274. ASSERT_EQ(APFixedPoint(320, getSAccumSema()),
  275. APFixedPoint(81920, Saturated(getAccumSema())));
  276. // Across signs
  277. ASSERT_EQ(APFixedPoint(320, getSAccumSema()),
  278. APFixedPoint(640, getUSAccumSema()));
  279. ASSERT_EQ(APFixedPoint(-320, getSAccumSema()),
  280. APFixedPoint(-81920, getAccumSema()));
  281. // Across padding
  282. ASSERT_EQ(APFixedPoint(320, getSAccumSema()),
  283. APFixedPoint(320, getPadUSAccumSema()));
  284. ASSERT_EQ(APFixedPoint(640, getUSAccumSema()),
  285. APFixedPoint(320, getPadUSAccumSema()));
  286. // Less than
  287. ASSERT_LT(APFixedPoint(-1, getSAccumSema()), APFixedPoint(0, getAccumSema()));
  288. ASSERT_LT(APFixedPoint(-1, getSAccumSema()),
  289. APFixedPoint(0, getUAccumSema()));
  290. ASSERT_LT(APFixedPoint(0, getSAccumSema()), APFixedPoint(1, getAccumSema()));
  291. ASSERT_LT(APFixedPoint(0, getSAccumSema()), APFixedPoint(1, getUAccumSema()));
  292. ASSERT_LT(APFixedPoint(0, getUSAccumSema()), APFixedPoint(1, getAccumSema()));
  293. ASSERT_LT(APFixedPoint(0, getUSAccumSema()),
  294. APFixedPoint(1, getUAccumSema()));
  295. // Greater than
  296. ASSERT_GT(APFixedPoint(0, getAccumSema()), APFixedPoint(-1, getSAccumSema()));
  297. ASSERT_GT(APFixedPoint(0, getUAccumSema()),
  298. APFixedPoint(-1, getSAccumSema()));
  299. ASSERT_GT(APFixedPoint(1, getAccumSema()), APFixedPoint(0, getSAccumSema()));
  300. ASSERT_GT(APFixedPoint(1, getUAccumSema()), APFixedPoint(0, getSAccumSema()));
  301. ASSERT_GT(APFixedPoint(1, getAccumSema()), APFixedPoint(0, getUSAccumSema()));
  302. ASSERT_GT(APFixedPoint(1, getUAccumSema()),
  303. APFixedPoint(0, getUSAccumSema()));
  304. }
  305. // Check that a fixed point value in one sema is the same in another sema
  306. void CheckUnsaturatedConversion(FixedPointSemantics Src,
  307. FixedPointSemantics Dst, int64_t TestVal) {
  308. int64_t ScaledVal = TestVal;
  309. bool IsNegative = ScaledVal < 0;
  310. if (IsNegative)
  311. ScaledVal = -ScaledVal;
  312. if (Dst.getScale() > Src.getScale()) {
  313. ScaledVal <<= (Dst.getScale() - Src.getScale());
  314. } else {
  315. ScaledVal >>= (Src.getScale() - Dst.getScale());
  316. }
  317. if (IsNegative)
  318. ScaledVal = -ScaledVal;
  319. APFixedPoint Fixed(TestVal, Src);
  320. APFixedPoint Expected(ScaledVal, Dst);
  321. ASSERT_EQ(Fixed.convert(Dst), Expected);
  322. }
  323. // Check the value in a given fixed point sema overflows to the saturated min
  324. // for another sema
  325. void CheckSaturatedConversionMin(FixedPointSemantics Src,
  326. FixedPointSemantics Dst, int64_t TestVal) {
  327. APFixedPoint Fixed(TestVal, Src);
  328. ASSERT_EQ(Fixed.convert(Dst), APFixedPoint::getMin(Dst));
  329. }
  330. // Check the value in a given fixed point sema overflows to the saturated max
  331. // for another sema
  332. void CheckSaturatedConversionMax(FixedPointSemantics Src,
  333. FixedPointSemantics Dst, int64_t TestVal) {
  334. APFixedPoint Fixed(TestVal, Src);
  335. ASSERT_EQ(Fixed.convert(Dst), APFixedPoint::getMax(Dst));
  336. }
  337. // Check one signed _Accum sema converted to other sema for different values.
  338. void CheckSignedAccumConversionsAgainstOthers(FixedPointSemantics Src,
  339. int64_t OneVal) {
  340. int64_t NormalVal = (OneVal * 2) + (OneVal / 2); // 2.5
  341. int64_t HalfVal = (OneVal / 2); // 0.5
  342. // +Accums to Accums
  343. CheckUnsaturatedConversion(Src, getSAccumSema(), NormalVal);
  344. CheckUnsaturatedConversion(Src, getAccumSema(), NormalVal);
  345. CheckUnsaturatedConversion(Src, getLAccumSema(), NormalVal);
  346. CheckUnsaturatedConversion(Src, getUSAccumSema(), NormalVal);
  347. CheckUnsaturatedConversion(Src, getUAccumSema(), NormalVal);
  348. CheckUnsaturatedConversion(Src, getULAccumSema(), NormalVal);
  349. CheckUnsaturatedConversion(Src, getPadUSAccumSema(), NormalVal);
  350. CheckUnsaturatedConversion(Src, getPadUAccumSema(), NormalVal);
  351. CheckUnsaturatedConversion(Src, getPadULAccumSema(), NormalVal);
  352. // -Accums to Accums
  353. CheckUnsaturatedConversion(Src, getSAccumSema(), -NormalVal);
  354. CheckUnsaturatedConversion(Src, getAccumSema(), -NormalVal);
  355. CheckUnsaturatedConversion(Src, getLAccumSema(), -NormalVal);
  356. CheckSaturatedConversionMin(Src, Saturated(getUSAccumSema()), -NormalVal);
  357. CheckSaturatedConversionMin(Src, Saturated(getUAccumSema()), -NormalVal);
  358. CheckSaturatedConversionMin(Src, Saturated(getULAccumSema()), -NormalVal);
  359. CheckSaturatedConversionMin(Src, Saturated(getPadUSAccumSema()), -NormalVal);
  360. CheckSaturatedConversionMin(Src, Saturated(getPadUAccumSema()), -NormalVal);
  361. CheckSaturatedConversionMin(Src, Saturated(getPadULAccumSema()), -NormalVal);
  362. // +Accums to Fracts
  363. CheckUnsaturatedConversion(Src, getSFractSema(), HalfVal);
  364. CheckUnsaturatedConversion(Src, getFractSema(), HalfVal);
  365. CheckUnsaturatedConversion(Src, getLFractSema(), HalfVal);
  366. CheckUnsaturatedConversion(Src, getUSFractSema(), HalfVal);
  367. CheckUnsaturatedConversion(Src, getUFractSema(), HalfVal);
  368. CheckUnsaturatedConversion(Src, getULFractSema(), HalfVal);
  369. CheckUnsaturatedConversion(Src, getPadUSFractSema(), HalfVal);
  370. CheckUnsaturatedConversion(Src, getPadUFractSema(), HalfVal);
  371. CheckUnsaturatedConversion(Src, getPadULFractSema(), HalfVal);
  372. // -Accums to Fracts
  373. CheckUnsaturatedConversion(Src, getSFractSema(), -HalfVal);
  374. CheckUnsaturatedConversion(Src, getFractSema(), -HalfVal);
  375. CheckUnsaturatedConversion(Src, getLFractSema(), -HalfVal);
  376. CheckSaturatedConversionMin(Src, Saturated(getUSFractSema()), -HalfVal);
  377. CheckSaturatedConversionMin(Src, Saturated(getUFractSema()), -HalfVal);
  378. CheckSaturatedConversionMin(Src, Saturated(getULFractSema()), -HalfVal);
  379. CheckSaturatedConversionMin(Src, Saturated(getPadUSFractSema()), -HalfVal);
  380. CheckSaturatedConversionMin(Src, Saturated(getPadUFractSema()), -HalfVal);
  381. CheckSaturatedConversionMin(Src, Saturated(getPadULFractSema()), -HalfVal);
  382. // 0 to Accums
  383. CheckUnsaturatedConversion(Src, getSAccumSema(), 0);
  384. CheckUnsaturatedConversion(Src, getAccumSema(), 0);
  385. CheckUnsaturatedConversion(Src, getLAccumSema(), 0);
  386. CheckUnsaturatedConversion(Src, getUSAccumSema(), 0);
  387. CheckUnsaturatedConversion(Src, getUAccumSema(), 0);
  388. CheckUnsaturatedConversion(Src, getULAccumSema(), 0);
  389. CheckUnsaturatedConversion(Src, getPadUSAccumSema(), 0);
  390. CheckUnsaturatedConversion(Src, getPadUAccumSema(), 0);
  391. CheckUnsaturatedConversion(Src, getPadULAccumSema(), 0);
  392. // 0 to Fracts
  393. CheckUnsaturatedConversion(Src, getSFractSema(), 0);
  394. CheckUnsaturatedConversion(Src, getFractSema(), 0);
  395. CheckUnsaturatedConversion(Src, getLFractSema(), 0);
  396. CheckUnsaturatedConversion(Src, getUSFractSema(), 0);
  397. CheckUnsaturatedConversion(Src, getUFractSema(), 0);
  398. CheckUnsaturatedConversion(Src, getULFractSema(), 0);
  399. CheckUnsaturatedConversion(Src, getPadUSFractSema(), 0);
  400. CheckUnsaturatedConversion(Src, getPadUFractSema(), 0);
  401. CheckUnsaturatedConversion(Src, getPadULFractSema(), 0);
  402. }
  403. // Check one unsigned _Accum sema converted to other sema for different
  404. // values.
  405. void CheckUnsignedAccumConversionsAgainstOthers(FixedPointSemantics Src,
  406. int64_t OneVal) {
  407. int64_t NormalVal = (OneVal * 2) + (OneVal / 2); // 2.5
  408. int64_t HalfVal = (OneVal / 2); // 0.5
  409. // +UAccums to Accums
  410. CheckUnsaturatedConversion(Src, getSAccumSema(), NormalVal);
  411. CheckUnsaturatedConversion(Src, getAccumSema(), NormalVal);
  412. CheckUnsaturatedConversion(Src, getLAccumSema(), NormalVal);
  413. CheckUnsaturatedConversion(Src, getUSAccumSema(), NormalVal);
  414. CheckUnsaturatedConversion(Src, getUAccumSema(), NormalVal);
  415. CheckUnsaturatedConversion(Src, getULAccumSema(), NormalVal);
  416. CheckUnsaturatedConversion(Src, getPadUSAccumSema(), NormalVal);
  417. CheckUnsaturatedConversion(Src, getPadUAccumSema(), NormalVal);
  418. CheckUnsaturatedConversion(Src, getPadULAccumSema(), NormalVal);
  419. // +UAccums to Fracts
  420. CheckUnsaturatedConversion(Src, getSFractSema(), HalfVal);
  421. CheckUnsaturatedConversion(Src, getFractSema(), HalfVal);
  422. CheckUnsaturatedConversion(Src, getLFractSema(), HalfVal);
  423. CheckUnsaturatedConversion(Src, getUSFractSema(), HalfVal);
  424. CheckUnsaturatedConversion(Src, getUFractSema(), HalfVal);
  425. CheckUnsaturatedConversion(Src, getULFractSema(), HalfVal);
  426. CheckUnsaturatedConversion(Src, getPadUSFractSema(), HalfVal);
  427. CheckUnsaturatedConversion(Src, getPadUFractSema(), HalfVal);
  428. CheckUnsaturatedConversion(Src, getPadULFractSema(), HalfVal);
  429. }
  430. TEST(FixedPoint, AccumConversions) {
  431. // Normal conversions
  432. CheckSignedAccumConversionsAgainstOthers(getSAccumSema(), 128);
  433. CheckUnsignedAccumConversionsAgainstOthers(getUSAccumSema(), 256);
  434. CheckSignedAccumConversionsAgainstOthers(getAccumSema(), 32768);
  435. CheckUnsignedAccumConversionsAgainstOthers(getUAccumSema(), 65536);
  436. CheckSignedAccumConversionsAgainstOthers(getLAccumSema(), 2147483648);
  437. CheckUnsignedAccumConversionsAgainstOthers(getULAccumSema(), 4294967296);
  438. CheckUnsignedAccumConversionsAgainstOthers(getPadUSAccumSema(), 128);
  439. CheckUnsignedAccumConversionsAgainstOthers(getPadUAccumSema(), 32768);
  440. CheckUnsignedAccumConversionsAgainstOthers(getPadULAccumSema(), 2147483648);
  441. }
  442. TEST(FixedPoint, AccumConversionOverflow) {
  443. // To SAccum max limit (65536)
  444. CheckSaturatedConversionMax(getLAccumSema(), Saturated(getAccumSema()),
  445. 140737488355328);
  446. CheckSaturatedConversionMax(getLAccumSema(), Saturated(getUAccumSema()),
  447. 140737488355328);
  448. CheckSaturatedConversionMax(getLAccumSema(), Saturated(getPadUAccumSema()),
  449. 140737488355328);
  450. CheckSaturatedConversionMax(getULAccumSema(), Saturated(getAccumSema()),
  451. 281474976710656);
  452. CheckSaturatedConversionMax(getULAccumSema(), Saturated(getUAccumSema()),
  453. 281474976710656);
  454. CheckSaturatedConversionMax(getULAccumSema(), Saturated(getPadUAccumSema()),
  455. 281474976710656);
  456. CheckSaturatedConversionMax(getPadULAccumSema(), Saturated(getAccumSema()),
  457. 140737488355328);
  458. CheckSaturatedConversionMax(getPadULAccumSema(), Saturated(getUAccumSema()),
  459. 140737488355328);
  460. CheckSaturatedConversionMax(getPadULAccumSema(),
  461. Saturated(getPadUAccumSema()), 140737488355328);
  462. // To SAccum min limit (-65536)
  463. CheckSaturatedConversionMin(getLAccumSema(), Saturated(getAccumSema()),
  464. -140737488355328);
  465. CheckSaturatedConversionMin(getLAccumSema(), Saturated(getUAccumSema()),
  466. -140737488355328);
  467. CheckSaturatedConversionMin(getLAccumSema(), Saturated(getPadUAccumSema()),
  468. -140737488355328);
  469. }
  470. TEST(FixedPoint, SAccumConversionOverflow) {
  471. // To SAccum max limit (256)
  472. CheckSaturatedConversionMax(getAccumSema(), Saturated(getSAccumSema()),
  473. 8388608);
  474. CheckSaturatedConversionMax(getAccumSema(), Saturated(getUSAccumSema()),
  475. 8388608);
  476. CheckSaturatedConversionMax(getAccumSema(), Saturated(getPadUSAccumSema()),
  477. 8388608);
  478. CheckSaturatedConversionMax(getUAccumSema(), Saturated(getSAccumSema()),
  479. 16777216);
  480. CheckSaturatedConversionMax(getUAccumSema(), Saturated(getUSAccumSema()),
  481. 16777216);
  482. CheckSaturatedConversionMax(getUAccumSema(), Saturated(getPadUSAccumSema()),
  483. 16777216);
  484. CheckSaturatedConversionMax(getLAccumSema(), Saturated(getSAccumSema()),
  485. 549755813888);
  486. CheckSaturatedConversionMax(getLAccumSema(), Saturated(getUSAccumSema()),
  487. 549755813888);
  488. CheckSaturatedConversionMax(getLAccumSema(), Saturated(getPadUSAccumSema()),
  489. 549755813888);
  490. CheckSaturatedConversionMax(getULAccumSema(), Saturated(getSAccumSema()),
  491. 1099511627776);
  492. CheckSaturatedConversionMax(getULAccumSema(), Saturated(getUSAccumSema()),
  493. 1099511627776);
  494. CheckSaturatedConversionMax(getULAccumSema(), Saturated(getPadUSAccumSema()),
  495. 1099511627776);
  496. CheckSaturatedConversionMax(getPadUAccumSema(), Saturated(getSAccumSema()),
  497. 8388608);
  498. CheckSaturatedConversionMax(getPadUAccumSema(), Saturated(getUSAccumSema()),
  499. 8388608);
  500. CheckSaturatedConversionMax(getPadUAccumSema(),
  501. Saturated(getPadUSAccumSema()), 8388608);
  502. CheckSaturatedConversionMax(getPadULAccumSema(), Saturated(getSAccumSema()),
  503. 549755813888);
  504. CheckSaturatedConversionMax(getPadULAccumSema(), Saturated(getUSAccumSema()),
  505. 549755813888);
  506. CheckSaturatedConversionMax(getPadULAccumSema(),
  507. Saturated(getPadUSAccumSema()), 549755813888);
  508. // To SAccum min limit (-256)
  509. CheckSaturatedConversionMin(getAccumSema(), Saturated(getSAccumSema()),
  510. -8388608);
  511. CheckSaturatedConversionMin(getAccumSema(), Saturated(getUSAccumSema()),
  512. -8388608);
  513. CheckSaturatedConversionMin(getAccumSema(), Saturated(getPadUSAccumSema()),
  514. -8388608);
  515. CheckSaturatedConversionMin(getLAccumSema(), Saturated(getSAccumSema()),
  516. -549755813888);
  517. CheckSaturatedConversionMin(getLAccumSema(), Saturated(getUSAccumSema()),
  518. -549755813888);
  519. CheckSaturatedConversionMin(getLAccumSema(), Saturated(getPadUSAccumSema()),
  520. -549755813888);
  521. }
  522. TEST(FixedPoint, GetValueSignAfterConversion) {
  523. APFixedPoint Fixed(255 << 7, getSAccumSema());
  524. ASSERT_TRUE(Fixed.getValue().isSigned());
  525. APFixedPoint UFixed = Fixed.convert(getUSAccumSema());
  526. ASSERT_TRUE(UFixed.getValue().isUnsigned());
  527. ASSERT_EQ(UFixed.getValue(), APSInt::getUnsigned(255 << 8).extOrTrunc(16));
  528. }
  529. TEST(FixedPoint, ModularWrapAround) {
  530. // Positive to negative
  531. APFixedPoint Val = APFixedPoint(1ULL << 7, getSAccumSema());
  532. ASSERT_EQ(Val.convert(getLFractSema()).getValue(), -(1ULL << 31));
  533. Val = APFixedPoint(1ULL << 23, getAccumSema());
  534. ASSERT_EQ(Val.convert(getSAccumSema()).getValue(), -(1ULL << 15));
  535. Val = APFixedPoint(1ULL << 47, getLAccumSema());
  536. ASSERT_EQ(Val.convert(getAccumSema()).getValue(), -(1ULL << 31));
  537. // Negative to positive
  538. Val = APFixedPoint(/*-1.5*/ -192, getSAccumSema());
  539. ASSERT_EQ(Val.convert(getLFractSema()).getValue(), 1ULL << 30);
  540. Val = APFixedPoint(-(257 << 15), getAccumSema());
  541. ASSERT_EQ(Val.convert(getSAccumSema()).getValue(), 255 << 7);
  542. Val = APFixedPoint(-(65537ULL << 31), getLAccumSema());
  543. ASSERT_EQ(Val.convert(getAccumSema()).getValue(), 65535 << 15);
  544. // Signed to unsigned
  545. Val = APFixedPoint(-(1 << 7), getSAccumSema());
  546. ASSERT_EQ(Val.convert(getUSAccumSema()).getValue(), 255 << 8);
  547. Val = APFixedPoint(-(1 << 15), getAccumSema());
  548. ASSERT_EQ(Val.convert(getUAccumSema()).getValue(), 65535ULL << 16);
  549. Val = APFixedPoint(-(1ULL << 31), getLAccumSema());
  550. ASSERT_EQ(Val.convert(getULAccumSema()).getValue().getZExtValue(),
  551. 4294967295ULL << 32);
  552. }
  553. } // namespace