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