1310 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/ADT/APFixedPoint.h"10#include "llvm/ADT/APFloat.h"11#include "llvm/ADT/APSInt.h"12#include "gtest/gtest.h"13 14using llvm::APFixedPoint;15using llvm::APFloat;16using llvm::APInt;17using llvm::APSInt;18using llvm::FixedPointSemantics;19 20namespace {21 22FixedPointSemantics Saturated(FixedPointSemantics Sema) {23 Sema.setSaturated(true);24 return Sema;25}26 27FixedPointSemantics getSAccumSema() {28 return FixedPointSemantics(/*width=*/16, /*scale=*/7, /*isSigned=*/true,29 /*isSaturated=*/false,30 /*hasUnsignedPadding=*/false);31}32 33FixedPointSemantics getAccumSema() {34 return FixedPointSemantics(/*width=*/32, /*scale=*/15, /*isSigned=*/true,35 /*isSaturated=*/false,36 /*hasUnsignedPadding=*/false);37}38 39FixedPointSemantics getLAccumSema() {40 return FixedPointSemantics(/*width=*/64, /*scale=*/31, /*isSigned=*/true,41 /*isSaturated=*/false,42 /*hasUnsignedPadding=*/false);43}44 45FixedPointSemantics getSFractSema() {46 return FixedPointSemantics(/*width=*/8, /*scale=*/7, /*isSigned=*/true,47 /*isSaturated=*/false,48 /*hasUnsignedPadding=*/false);49}50 51FixedPointSemantics getFractSema() {52 return FixedPointSemantics(/*width=*/16, /*scale=*/15, /*isSigned=*/true,53 /*isSaturated=*/false,54 /*hasUnsignedPadding=*/false);55}56 57FixedPointSemantics getLFractSema() {58 return FixedPointSemantics(/*width=*/32, /*scale=*/31, /*isSigned=*/true,59 /*isSaturated=*/false,60 /*hasUnsignedPadding=*/false);61}62 63FixedPointSemantics getUSAccumSema() {64 return FixedPointSemantics(/*width=*/16, /*scale=*/8, /*isSigned=*/false,65 /*isSaturated=*/false,66 /*hasUnsignedPadding=*/false);67}68 69FixedPointSemantics getUAccumSema() {70 return FixedPointSemantics(/*width=*/32, /*scale=*/16, /*isSigned=*/false,71 /*isSaturated=*/false,72 /*hasUnsignedPadding=*/false);73}74 75FixedPointSemantics getULAccumSema() {76 return FixedPointSemantics(/*width=*/64, /*scale=*/32, /*isSigned=*/false,77 /*isSaturated=*/false,78 /*hasUnsignedPadding=*/false);79}80 81FixedPointSemantics getUSFractSema() {82 return FixedPointSemantics(/*width=*/8, /*scale=*/8, /*isSigned=*/false,83 /*isSaturated=*/false,84 /*hasUnsignedPadding=*/false);85}86 87FixedPointSemantics getUFractSema() {88 return FixedPointSemantics(/*width=*/16, /*scale=*/16, /*isSigned=*/false,89 /*isSaturated=*/false,90 /*hasUnsignedPadding=*/false);91}92 93FixedPointSemantics getULFractSema() {94 return FixedPointSemantics(/*width=*/32, /*scale=*/32, /*isSigned=*/false,95 /*isSaturated=*/false,96 /*hasUnsignedPadding=*/false);97}98 99FixedPointSemantics getPadUSAccumSema() {100 return FixedPointSemantics(/*width=*/16, /*scale=*/7, /*isSigned=*/false,101 /*isSaturated=*/false,102 /*hasUnsignedPadding=*/true);103}104 105FixedPointSemantics getPadUAccumSema() {106 return FixedPointSemantics(/*width=*/32, /*scale=*/15, /*isSigned=*/false,107 /*isSaturated=*/false,108 /*hasUnsignedPadding=*/true);109}110 111FixedPointSemantics getPadULAccumSema() {112 return FixedPointSemantics(/*width=*/64, /*scale=*/31, /*isSigned=*/false,113 /*isSaturated=*/false,114 /*hasUnsignedPadding=*/true);115}116 117FixedPointSemantics getPadUSFractSema() {118 return FixedPointSemantics(/*width=*/8, /*scale=*/7, /*isSigned=*/false,119 /*isSaturated=*/false,120 /*hasUnsignedPadding=*/true);121}122 123FixedPointSemantics getPadUFractSema() {124 return FixedPointSemantics(/*width=*/16, /*scale=*/15, /*isSigned=*/false,125 /*isSaturated=*/false,126 /*hasUnsignedPadding=*/true);127}128 129FixedPointSemantics getPadULFractSema() {130 return FixedPointSemantics(/*width=*/32, /*scale=*/31, /*isSigned=*/false,131 /*isSaturated=*/false,132 /*hasUnsignedPadding=*/true);133}134 135FixedPointSemantics getU8Neg10() {136 return FixedPointSemantics(/*width=*/8, /*lsb=*/FixedPointSemantics::Lsb{-10},137 /*isSigned=*/false,138 /*isSaturated=*/false,139 /*hasUnsignedPadding=*/false);140}141 142FixedPointSemantics getS16Neg18() {143 return FixedPointSemantics(/*width=*/16,144 /*lsb=*/FixedPointSemantics::Lsb{-18},145 /*isSigned=*/true,146 /*isSaturated=*/false,147 /*hasUnsignedPadding=*/false);148}149 150FixedPointSemantics getU8Pos4() {151 return FixedPointSemantics(/*width=*/8, /*lsb=*/FixedPointSemantics::Lsb{4},152 /*isSigned=*/false,153 /*isSaturated=*/false,154 /*hasUnsignedPadding=*/false);155}156 157FixedPointSemantics getS32Pos2() {158 return FixedPointSemantics(/*width=*/32, /*lsb=*/FixedPointSemantics::Lsb{2},159 /*isSigned=*/true,160 /*isSaturated=*/false,161 /*hasUnsignedPadding=*/false);162}163 164void CheckUnpaddedMax(const FixedPointSemantics &Sema) {165 ASSERT_EQ(APFixedPoint::getMax(Sema).getValue(),166 APSInt::getMaxValue(Sema.getWidth(), !Sema.isSigned()));167}168 169void CheckPaddedMax(const FixedPointSemantics &Sema) {170 ASSERT_EQ(APFixedPoint::getMax(Sema).getValue(),171 APSInt::getMaxValue(Sema.getWidth(), !Sema.isSigned()) >> 1);172}173 174void CheckMin(const FixedPointSemantics &Sema) {175 ASSERT_EQ(APFixedPoint::getMin(Sema).getValue(),176 APSInt::getMinValue(Sema.getWidth(), !Sema.isSigned()));177}178 179TEST(FixedPointTest, getMax) {180 CheckUnpaddedMax(getSAccumSema());181 CheckUnpaddedMax(getAccumSema());182 CheckUnpaddedMax(getLAccumSema());183 CheckUnpaddedMax(getUSAccumSema());184 CheckUnpaddedMax(getUAccumSema());185 CheckUnpaddedMax(getULAccumSema());186 CheckUnpaddedMax(getSFractSema());187 CheckUnpaddedMax(getFractSema());188 CheckUnpaddedMax(getLFractSema());189 CheckUnpaddedMax(getUSFractSema());190 CheckUnpaddedMax(getUFractSema());191 CheckUnpaddedMax(getULFractSema());192 CheckUnpaddedMax(getU8Neg10());193 CheckUnpaddedMax(getS16Neg18());194 CheckUnpaddedMax(getU8Pos4());195 CheckUnpaddedMax(getS32Pos2());196 197 CheckPaddedMax(getPadUSAccumSema());198 CheckPaddedMax(getPadUAccumSema());199 CheckPaddedMax(getPadULAccumSema());200 CheckPaddedMax(getPadUSFractSema());201 CheckPaddedMax(getPadUFractSema());202 CheckPaddedMax(getPadULFractSema());203}204 205TEST(FixedPointTest, getMin) {206 CheckMin(getSAccumSema());207 CheckMin(getAccumSema());208 CheckMin(getLAccumSema());209 CheckMin(getUSAccumSema());210 CheckMin(getUAccumSema());211 CheckMin(getULAccumSema());212 CheckMin(getSFractSema());213 CheckMin(getFractSema());214 CheckMin(getLFractSema());215 CheckMin(getUSFractSema());216 CheckMin(getUFractSema());217 CheckMin(getULFractSema());218 CheckMin(getU8Neg10());219 CheckMin(getS16Neg18());220 CheckMin(getU8Pos4());221 CheckMin(getS32Pos2());222 223 CheckMin(getPadUSAccumSema());224 CheckMin(getPadUAccumSema());225 CheckMin(getPadULAccumSema());226 CheckMin(getPadUSFractSema());227 CheckMin(getPadUFractSema());228 CheckMin(getPadULFractSema());229}230 231int64_t relativeShr(int64_t Int, int64_t Shift) {232 return (Shift > 0) ? Int >> Shift : Int << -Shift;233}234 235void CheckIntPart(const FixedPointSemantics &Sema, int64_t IntPart) {236 int64_t FullFactPart =237 (Sema.getLsbWeight() > 0) ? 0 : (1ULL << (-Sema.getLsbWeight() - 1));238 239 // Value with a fraction240 APFixedPoint ValWithFract(241 APInt(Sema.getWidth(),242 relativeShr(IntPart, Sema.getLsbWeight()) + FullFactPart,243 Sema.isSigned(), /*implicitTrunc=*/true),244 Sema);245 ASSERT_EQ(ValWithFract.getIntPart(), IntPart);246 247 // Just fraction248 APFixedPoint JustFract(APInt(Sema.getWidth(), FullFactPart, Sema.isSigned(),249 /*implicitTrunc=*/true),250 Sema);251 ASSERT_EQ(JustFract.getIntPart(), 0);252 253 // Whole number254 APFixedPoint WholeNum(APInt(Sema.getWidth(),255 relativeShr(IntPart, Sema.getLsbWeight()),256 Sema.isSigned(), /*implicitTrunc=*/true),257 Sema);258 ASSERT_EQ(WholeNum.getIntPart(), IntPart);259 260 // Negative261 if (Sema.isSigned()) {262 APFixedPoint Negative(APInt(Sema.getWidth(),263 relativeShr(IntPart, Sema.getLsbWeight()),264 Sema.isSigned(), /*implicitTrunc=*/true),265 Sema);266 ASSERT_EQ(Negative.getIntPart(), IntPart);267 }268}269 270void CheckIntPartMin(const FixedPointSemantics &Sema, int64_t Expected) {271 EXPECT_TRUE(APSInt::compareValues(APFixedPoint::getMin(Sema).getIntPart(),272 APSInt::get(Expected)) == 0);273}274 275void CheckIntPartMax(const FixedPointSemantics &Sema, uint64_t Expected) {276 EXPECT_TRUE(APSInt::compareValues(APFixedPoint::getMax(Sema).getIntPart(),277 APSInt::getUnsigned(Expected)) == 0);278}279 280void CheckIntPartRes(const FixedPointSemantics &Sema, int64_t Representation,281 uint64_t Result) {282 APFixedPoint Val(Representation, Sema);283 ASSERT_EQ(Val.getIntPart().getZExtValue(), Result) ;284}285 286TEST(FixedPoint, getIntPart) {287 // Normal values288 CheckIntPart(getSAccumSema(), 2);289 CheckIntPart(getAccumSema(), 2);290 CheckIntPart(getLAccumSema(), 2);291 CheckIntPart(getUSAccumSema(), 2);292 CheckIntPart(getUAccumSema(), 2);293 CheckIntPart(getULAccumSema(), 2);294 CheckIntPart(getU8Pos4(), 32);295 CheckIntPart(getS32Pos2(), 32);296 297 // Zero298 CheckIntPart(getSAccumSema(), 0);299 CheckIntPart(getAccumSema(), 0);300 CheckIntPart(getLAccumSema(), 0);301 CheckIntPart(getUSAccumSema(), 0);302 CheckIntPart(getUAccumSema(), 0);303 CheckIntPart(getULAccumSema(), 0);304 305 CheckIntPart(getSFractSema(), 0);306 CheckIntPart(getFractSema(), 0);307 CheckIntPart(getLFractSema(), 0);308 CheckIntPart(getUSFractSema(), 0);309 CheckIntPart(getUFractSema(), 0);310 CheckIntPart(getULFractSema(), 0);311 312 CheckIntPart(getS16Neg18(), 0);313 CheckIntPart(getU8Neg10(), 0);314 CheckIntPart(getU8Pos4(), 0);315 CheckIntPart(getS32Pos2(), 0);316 317 // Min318 CheckIntPartMin(getSAccumSema(), -256);319 CheckIntPartMin(getAccumSema(), -65536);320 CheckIntPartMin(getLAccumSema(), -4294967296);321 322 CheckIntPartMin(getSFractSema(), -1);323 CheckIntPartMin(getFractSema(), -1);324 CheckIntPartMin(getLFractSema(), -1);325 326 CheckIntPartMin(getS32Pos2(), -8589934592);327 328 // Max329 CheckIntPartMax(getSAccumSema(), 255);330 CheckIntPartMax(getAccumSema(), 65535);331 CheckIntPartMax(getLAccumSema(), 4294967295);332 CheckIntPartMax(getUSAccumSema(), 255);333 CheckIntPartMax(getUAccumSema(), 65535);334 CheckIntPartMax(getULAccumSema(), 4294967295);335 336 CheckIntPartMax(getU8Pos4(), 255 << 4);337 CheckIntPartMax(getS32Pos2(), 2147483647ull << 2);338 339 CheckIntPartMax(getSFractSema(), 0);340 CheckIntPartMax(getFractSema(), 0);341 CheckIntPartMax(getLFractSema(), 0);342 CheckIntPartMax(getUSFractSema(), 0);343 CheckIntPartMax(getUFractSema(), 0);344 CheckIntPartMax(getULFractSema(), 0);345 346 // Padded347 // Normal Values348 CheckIntPart(getPadUSAccumSema(), 2);349 CheckIntPart(getPadUAccumSema(), 2);350 CheckIntPart(getPadULAccumSema(), 2);351 352 // Zero353 CheckIntPart(getPadUSAccumSema(), 0);354 CheckIntPart(getPadUAccumSema(), 0);355 CheckIntPart(getPadULAccumSema(), 0);356 357 CheckIntPart(getPadUSFractSema(), 0);358 CheckIntPart(getPadUFractSema(), 0);359 CheckIntPart(getPadULFractSema(), 0);360 361 // Max362 CheckIntPartMax(getPadUSAccumSema(), 255);363 CheckIntPartMax(getPadUAccumSema(), 65535);364 CheckIntPartMax(getPadULAccumSema(), 4294967295);365 366 CheckIntPartMax(getPadUSFractSema(), 0);367 CheckIntPartMax(getPadUFractSema(), 0);368 CheckIntPartMax(getPadULFractSema(), 0);369 370 // Rounded Towards Zero371 CheckIntPartRes(getSFractSema(), -127, 0);372 CheckIntPartRes(getFractSema(), -32767, 0);373 CheckIntPartRes(getLFractSema(), -2147483647, 0);374 CheckIntPartRes(getS16Neg18(), -32768, 0);375}376 377TEST(FixedPoint, compare) {378 // Equality379 // With fractional part (2.5)380 // Across sizes381 ASSERT_EQ(APFixedPoint(320, getSAccumSema()),382 APFixedPoint(81920, getAccumSema()));383 ASSERT_EQ(APFixedPoint(320, getSAccumSema()),384 APFixedPoint(5368709120, getLAccumSema()));385 ASSERT_EQ(APFixedPoint(0, getSAccumSema()), APFixedPoint(0, getLAccumSema()));386 387 ASSERT_EQ(APFixedPoint(0, getS16Neg18()), APFixedPoint(0, getU8Neg10()));388 ASSERT_EQ(APFixedPoint(256, getS16Neg18()), APFixedPoint(1, getU8Neg10()));389 ASSERT_EQ(APFixedPoint(32512, getS16Neg18()),390 APFixedPoint(127, getU8Neg10()));391 ASSERT_EQ(APFixedPoint(4, getS32Pos2()), APFixedPoint(1, getU8Pos4()));392 ASSERT_EQ(APFixedPoint(1020, getS32Pos2()), APFixedPoint(255, getU8Pos4()));393 394 // Across types (0.5)395 ASSERT_EQ(APFixedPoint(64, getSAccumSema()),396 APFixedPoint(64, getSFractSema()));397 ASSERT_EQ(APFixedPoint(16384, getAccumSema()),398 APFixedPoint(16384, getFractSema()));399 ASSERT_EQ(APFixedPoint(1073741824, getLAccumSema()),400 APFixedPoint(1073741824, getLFractSema()));401 402 // Across widths and types (0.5)403 ASSERT_EQ(APFixedPoint(64, getSAccumSema()),404 APFixedPoint(16384, getFractSema()));405 ASSERT_EQ(APFixedPoint(64, getSAccumSema()),406 APFixedPoint(1073741824, getLFractSema()));407 408 // Across saturation409 ASSERT_EQ(APFixedPoint(320, getSAccumSema()),410 APFixedPoint(81920, Saturated(getAccumSema())));411 412 // Across signs413 ASSERT_EQ(APFixedPoint(320, getSAccumSema()),414 APFixedPoint(640, getUSAccumSema()));415 ASSERT_EQ(APFixedPoint(-320, getSAccumSema()),416 APFixedPoint(-81920, getAccumSema()));417 418 // Across padding419 ASSERT_EQ(APFixedPoint(320, getSAccumSema()),420 APFixedPoint(320, getPadUSAccumSema()));421 ASSERT_EQ(APFixedPoint(640, getUSAccumSema()),422 APFixedPoint(320, getPadUSAccumSema()));423 424 // Less than425 ASSERT_LT(APFixedPoint(-1, getSAccumSema()), APFixedPoint(0, getAccumSema()));426 ASSERT_LT(APFixedPoint(-1, getSAccumSema()),427 APFixedPoint(0, getUAccumSema()));428 ASSERT_LT(APFixedPoint(0, getSAccumSema()), APFixedPoint(1, getAccumSema()));429 ASSERT_LT(APFixedPoint(0, getSAccumSema()), APFixedPoint(1, getUAccumSema()));430 ASSERT_LT(APFixedPoint(0, getUSAccumSema()), APFixedPoint(1, getAccumSema()));431 ASSERT_LT(APFixedPoint(0, getUSAccumSema()),432 APFixedPoint(1, getUAccumSema()));433 ASSERT_LT(APFixedPoint(65280, getS16Neg18()),434 APFixedPoint(255, getU8Neg10()));435 436 // Greater than437 ASSERT_GT(APFixedPoint(0, getAccumSema()), APFixedPoint(-1, getSAccumSema()));438 ASSERT_GT(APFixedPoint(0, getUAccumSema()),439 APFixedPoint(-1, getSAccumSema()));440 ASSERT_GT(APFixedPoint(1, getAccumSema()), APFixedPoint(0, getSAccumSema()));441 ASSERT_GT(APFixedPoint(1, getUAccumSema()), APFixedPoint(0, getSAccumSema()));442 ASSERT_GT(APFixedPoint(1, getAccumSema()), APFixedPoint(0, getUSAccumSema()));443 ASSERT_GT(APFixedPoint(1, getUAccumSema()),444 APFixedPoint(0, getUSAccumSema()));445}446 447// Check that a fixed point value in one sema is the same in another sema448void CheckUnsaturatedConversion(FixedPointSemantics Src,449 FixedPointSemantics Dst, int64_t TestVal) {450 int64_t ScaledVal = TestVal;451 bool IsNegative = ScaledVal < 0;452 if (IsNegative)453 ScaledVal = -ScaledVal;454 455 if (Dst.getLsbWeight() < Src.getLsbWeight()) {456 ScaledVal <<= (Src.getLsbWeight() - Dst.getLsbWeight());457 } else {458 ScaledVal >>= (Dst.getLsbWeight() - Src.getLsbWeight());459 }460 461 if (IsNegative)462 ScaledVal = -ScaledVal;463 464 APFixedPoint Fixed(TestVal, Src);465 APFixedPoint Expected(ScaledVal, Dst);466 ASSERT_EQ(Fixed.convert(Dst), Expected);467}468 469// Check the value in a given fixed point sema overflows to the saturated min470// for another sema471void CheckSaturatedConversionMin(FixedPointSemantics Src,472 FixedPointSemantics Dst, int64_t TestVal) {473 APFixedPoint Fixed(TestVal, Src);474 ASSERT_EQ(Fixed.convert(Dst), APFixedPoint::getMin(Dst));475}476 477// Check the value in a given fixed point sema overflows to the saturated max478// for another sema479void CheckSaturatedConversionMax(FixedPointSemantics Src,480 FixedPointSemantics Dst, int64_t TestVal) {481 APFixedPoint Fixed(TestVal, Src);482 ASSERT_EQ(Fixed.convert(Dst), APFixedPoint::getMax(Dst));483}484 485// Check one signed _Accum sema converted to other sema for different values.486void CheckSignedAccumConversionsAgainstOthers(FixedPointSemantics Src,487 int64_t OneVal) {488 int64_t NormalVal = (OneVal * 2) + (OneVal / 2); // 2.5489 int64_t HalfVal = (OneVal / 2); // 0.5490 491 // +Accums to Accums492 CheckUnsaturatedConversion(Src, getSAccumSema(), NormalVal);493 CheckUnsaturatedConversion(Src, getAccumSema(), NormalVal);494 CheckUnsaturatedConversion(Src, getLAccumSema(), NormalVal);495 CheckUnsaturatedConversion(Src, getUSAccumSema(), NormalVal);496 CheckUnsaturatedConversion(Src, getUAccumSema(), NormalVal);497 CheckUnsaturatedConversion(Src, getULAccumSema(), NormalVal);498 CheckUnsaturatedConversion(Src, getPadUSAccumSema(), NormalVal);499 CheckUnsaturatedConversion(Src, getPadUAccumSema(), NormalVal);500 CheckUnsaturatedConversion(Src, getPadULAccumSema(), NormalVal);501 502 // -Accums to Accums503 CheckUnsaturatedConversion(Src, getSAccumSema(), -NormalVal);504 CheckUnsaturatedConversion(Src, getAccumSema(), -NormalVal);505 CheckUnsaturatedConversion(Src, getLAccumSema(), -NormalVal);506 CheckSaturatedConversionMin(Src, Saturated(getUSAccumSema()), -NormalVal);507 CheckSaturatedConversionMin(Src, Saturated(getUAccumSema()), -NormalVal);508 CheckSaturatedConversionMin(Src, Saturated(getULAccumSema()), -NormalVal);509 CheckSaturatedConversionMin(Src, Saturated(getPadUSAccumSema()), -NormalVal);510 CheckSaturatedConversionMin(Src, Saturated(getPadUAccumSema()), -NormalVal);511 CheckSaturatedConversionMin(Src, Saturated(getPadULAccumSema()), -NormalVal);512 513 // +Accums to Fracts514 CheckUnsaturatedConversion(Src, getSFractSema(), HalfVal);515 CheckUnsaturatedConversion(Src, getFractSema(), HalfVal);516 CheckUnsaturatedConversion(Src, getLFractSema(), HalfVal);517 CheckUnsaturatedConversion(Src, getUSFractSema(), HalfVal);518 CheckUnsaturatedConversion(Src, getUFractSema(), HalfVal);519 CheckUnsaturatedConversion(Src, getULFractSema(), HalfVal);520 CheckUnsaturatedConversion(Src, getPadUSFractSema(), HalfVal);521 CheckUnsaturatedConversion(Src, getPadUFractSema(), HalfVal);522 CheckUnsaturatedConversion(Src, getPadULFractSema(), HalfVal);523 524 // -Accums to Fracts525 CheckUnsaturatedConversion(Src, getSFractSema(), -HalfVal);526 CheckUnsaturatedConversion(Src, getFractSema(), -HalfVal);527 CheckUnsaturatedConversion(Src, getLFractSema(), -HalfVal);528 CheckSaturatedConversionMin(Src, Saturated(getUSFractSema()), -HalfVal);529 CheckSaturatedConversionMin(Src, Saturated(getUFractSema()), -HalfVal);530 CheckSaturatedConversionMin(Src, Saturated(getULFractSema()), -HalfVal);531 CheckSaturatedConversionMin(Src, Saturated(getPadUSFractSema()), -HalfVal);532 CheckSaturatedConversionMin(Src, Saturated(getPadUFractSema()), -HalfVal);533 CheckSaturatedConversionMin(Src, Saturated(getPadULFractSema()), -HalfVal);534 535 // 0 to Accums536 CheckUnsaturatedConversion(Src, getSAccumSema(), 0);537 CheckUnsaturatedConversion(Src, getAccumSema(), 0);538 CheckUnsaturatedConversion(Src, getLAccumSema(), 0);539 CheckUnsaturatedConversion(Src, getUSAccumSema(), 0);540 CheckUnsaturatedConversion(Src, getUAccumSema(), 0);541 CheckUnsaturatedConversion(Src, getULAccumSema(), 0);542 CheckUnsaturatedConversion(Src, getPadUSAccumSema(), 0);543 CheckUnsaturatedConversion(Src, getPadUAccumSema(), 0);544 CheckUnsaturatedConversion(Src, getPadULAccumSema(), 0);545 546 // 0 to Fracts547 CheckUnsaturatedConversion(Src, getSFractSema(), 0);548 CheckUnsaturatedConversion(Src, getFractSema(), 0);549 CheckUnsaturatedConversion(Src, getLFractSema(), 0);550 CheckUnsaturatedConversion(Src, getUSFractSema(), 0);551 CheckUnsaturatedConversion(Src, getUFractSema(), 0);552 CheckUnsaturatedConversion(Src, getULFractSema(), 0);553 CheckUnsaturatedConversion(Src, getPadUSFractSema(), 0);554 CheckUnsaturatedConversion(Src, getPadUFractSema(), 0);555 CheckUnsaturatedConversion(Src, getPadULFractSema(), 0);556}557 558// Check one unsigned _Accum sema converted to other sema for different559// values.560void CheckUnsignedAccumConversionsAgainstOthers(FixedPointSemantics Src,561 int64_t OneVal) {562 int64_t NormalVal = (OneVal * 2) + (OneVal / 2); // 2.5563 int64_t HalfVal = (OneVal / 2); // 0.5564 565 // +UAccums to Accums566 CheckUnsaturatedConversion(Src, getSAccumSema(), NormalVal);567 CheckUnsaturatedConversion(Src, getAccumSema(), NormalVal);568 CheckUnsaturatedConversion(Src, getLAccumSema(), NormalVal);569 CheckUnsaturatedConversion(Src, getUSAccumSema(), NormalVal);570 CheckUnsaturatedConversion(Src, getUAccumSema(), NormalVal);571 CheckUnsaturatedConversion(Src, getULAccumSema(), NormalVal);572 CheckUnsaturatedConversion(Src, getPadUSAccumSema(), NormalVal);573 CheckUnsaturatedConversion(Src, getPadUAccumSema(), NormalVal);574 CheckUnsaturatedConversion(Src, getPadULAccumSema(), NormalVal);575 576 // +UAccums to Fracts577 CheckUnsaturatedConversion(Src, getSFractSema(), HalfVal);578 CheckUnsaturatedConversion(Src, getFractSema(), HalfVal);579 CheckUnsaturatedConversion(Src, getLFractSema(), HalfVal);580 CheckUnsaturatedConversion(Src, getUSFractSema(), HalfVal);581 CheckUnsaturatedConversion(Src, getUFractSema(), HalfVal);582 CheckUnsaturatedConversion(Src, getULFractSema(), HalfVal);583 CheckUnsaturatedConversion(Src, getPadUSFractSema(), HalfVal);584 CheckUnsaturatedConversion(Src, getPadUFractSema(), HalfVal);585 CheckUnsaturatedConversion(Src, getPadULFractSema(), HalfVal);586}587 588TEST(FixedPoint, AccumConversions) {589 // Normal conversions590 CheckSignedAccumConversionsAgainstOthers(getSAccumSema(), 128);591 CheckUnsignedAccumConversionsAgainstOthers(getUSAccumSema(), 256);592 CheckSignedAccumConversionsAgainstOthers(getAccumSema(), 32768);593 CheckUnsignedAccumConversionsAgainstOthers(getUAccumSema(), 65536);594 CheckSignedAccumConversionsAgainstOthers(getLAccumSema(), 2147483648);595 CheckUnsignedAccumConversionsAgainstOthers(getULAccumSema(), 4294967296);596 597 CheckUnsignedAccumConversionsAgainstOthers(getPadUSAccumSema(), 128);598 CheckUnsignedAccumConversionsAgainstOthers(getPadUAccumSema(), 32768);599 CheckUnsignedAccumConversionsAgainstOthers(getPadULAccumSema(), 2147483648);600}601 602TEST(FixedPoint, AccumConversionOverflow) {603 // To SAccum max limit (65536)604 CheckSaturatedConversionMax(getLAccumSema(), Saturated(getAccumSema()),605 140737488355328);606 CheckSaturatedConversionMax(getLAccumSema(), Saturated(getUAccumSema()),607 140737488355328);608 CheckSaturatedConversionMax(getLAccumSema(), Saturated(getPadUAccumSema()),609 140737488355328);610 CheckSaturatedConversionMax(getULAccumSema(), Saturated(getAccumSema()),611 281474976710656);612 CheckSaturatedConversionMax(getULAccumSema(), Saturated(getUAccumSema()),613 281474976710656);614 CheckSaturatedConversionMax(getULAccumSema(), Saturated(getPadUAccumSema()),615 281474976710656);616 617 CheckSaturatedConversionMax(getPadULAccumSema(), Saturated(getAccumSema()),618 140737488355328);619 CheckSaturatedConversionMax(getPadULAccumSema(), Saturated(getUAccumSema()),620 140737488355328);621 CheckSaturatedConversionMax(getPadULAccumSema(),622 Saturated(getPadUAccumSema()), 140737488355328);623 624 // To SAccum min limit (-65536)625 CheckSaturatedConversionMin(getLAccumSema(), Saturated(getAccumSema()),626 -140737488355328);627 CheckSaturatedConversionMin(getLAccumSema(), Saturated(getUAccumSema()),628 -140737488355328);629 CheckSaturatedConversionMin(getLAccumSema(), Saturated(getPadUAccumSema()),630 -140737488355328);631}632 633TEST(FixedPoint, SAccumConversionOverflow) {634 // To SAccum max limit (256)635 CheckSaturatedConversionMax(getAccumSema(), Saturated(getSAccumSema()),636 8388608);637 CheckSaturatedConversionMax(getAccumSema(), Saturated(getUSAccumSema()),638 8388608);639 CheckSaturatedConversionMax(getAccumSema(), Saturated(getPadUSAccumSema()),640 8388608);641 CheckSaturatedConversionMax(getUAccumSema(), Saturated(getSAccumSema()),642 16777216);643 CheckSaturatedConversionMax(getUAccumSema(), Saturated(getUSAccumSema()),644 16777216);645 CheckSaturatedConversionMax(getUAccumSema(), Saturated(getPadUSAccumSema()),646 16777216);647 CheckSaturatedConversionMax(getLAccumSema(), Saturated(getSAccumSema()),648 549755813888);649 CheckSaturatedConversionMax(getLAccumSema(), Saturated(getUSAccumSema()),650 549755813888);651 CheckSaturatedConversionMax(getLAccumSema(), Saturated(getPadUSAccumSema()),652 549755813888);653 CheckSaturatedConversionMax(getULAccumSema(), Saturated(getSAccumSema()),654 1099511627776);655 CheckSaturatedConversionMax(getULAccumSema(), Saturated(getUSAccumSema()),656 1099511627776);657 CheckSaturatedConversionMax(getULAccumSema(), Saturated(getPadUSAccumSema()),658 1099511627776);659 660 CheckSaturatedConversionMax(getPadUAccumSema(), Saturated(getSAccumSema()),661 8388608);662 CheckSaturatedConversionMax(getPadUAccumSema(), Saturated(getUSAccumSema()),663 8388608);664 CheckSaturatedConversionMax(getPadUAccumSema(),665 Saturated(getPadUSAccumSema()), 8388608);666 CheckSaturatedConversionMax(getPadULAccumSema(), Saturated(getSAccumSema()),667 549755813888);668 CheckSaturatedConversionMax(getPadULAccumSema(), Saturated(getUSAccumSema()),669 549755813888);670 CheckSaturatedConversionMax(getPadULAccumSema(),671 Saturated(getPadUSAccumSema()), 549755813888);672 673 // To SAccum min limit (-256)674 CheckSaturatedConversionMin(getAccumSema(), Saturated(getSAccumSema()),675 -8388608);676 CheckSaturatedConversionMin(getAccumSema(), Saturated(getUSAccumSema()),677 -8388608);678 CheckSaturatedConversionMin(getAccumSema(), Saturated(getPadUSAccumSema()),679 -8388608);680 CheckSaturatedConversionMin(getLAccumSema(), Saturated(getSAccumSema()),681 -549755813888);682 CheckSaturatedConversionMin(getLAccumSema(), Saturated(getUSAccumSema()),683 -549755813888);684 CheckSaturatedConversionMin(getLAccumSema(), Saturated(getPadUSAccumSema()),685 -549755813888);686}687 688TEST(FixedPoint, GetValueSignAfterConversion) {689 APFixedPoint Fixed(255 << 7, getSAccumSema());690 ASSERT_TRUE(Fixed.getValue().isSigned());691 APFixedPoint UFixed = Fixed.convert(getUSAccumSema());692 ASSERT_TRUE(UFixed.getValue().isUnsigned());693 ASSERT_EQ(UFixed.getValue(), APSInt::getUnsigned(255 << 8).extOrTrunc(16));694}695 696TEST(FixedPoint, ModularWrapAround) {697 // Positive to negative698 APFixedPoint Val = APFixedPoint(1ULL << 7, getSAccumSema());699 ASSERT_EQ(Val.convert(getLFractSema()).getValue(), -(1ULL << 31));700 701 Val = APFixedPoint(1ULL << 23, getAccumSema());702 ASSERT_EQ(Val.convert(getSAccumSema()).getValue(), -(1ULL << 15));703 704 Val = APFixedPoint(1ULL << 47, getLAccumSema());705 ASSERT_EQ(Val.convert(getAccumSema()).getValue(), -(1ULL << 31));706 707 // Negative to positive708 Val = APFixedPoint(/*-1.5*/ -192, getSAccumSema());709 ASSERT_EQ(Val.convert(getLFractSema()).getValue(), 1ULL << 30);710 711 Val = APFixedPoint(-(257 << 15), getAccumSema());712 ASSERT_EQ(Val.convert(getSAccumSema()).getValue(), 255 << 7);713 714 Val = APFixedPoint(-(65537ULL << 31), getLAccumSema());715 ASSERT_EQ(Val.convert(getAccumSema()).getValue(), 65535 << 15);716 717 // Signed to unsigned718 Val = APFixedPoint(-(1 << 7), getSAccumSema());719 ASSERT_EQ(Val.convert(getUSAccumSema()).getValue(), 255 << 8);720 721 Val = APFixedPoint(-(1 << 15), getAccumSema());722 ASSERT_EQ(Val.convert(getUAccumSema()).getValue(), 65535ULL << 16);723 724 Val = APFixedPoint(-(1ULL << 31), getLAccumSema());725 ASSERT_EQ(Val.convert(getULAccumSema()).getValue().getZExtValue(),726 4294967295ULL << 32);727}728 729enum OvfKind { MinSat, MaxSat };730 731void CheckFloatToFixedConversion(APFloat &Val, const FixedPointSemantics &Sema,732 int64_t ExpectedNonSat) {733 bool Ovf;734 ASSERT_EQ(APFixedPoint::getFromFloatValue(Val, Sema, &Ovf).getValue(),735 ExpectedNonSat);736 ASSERT_EQ(Ovf, false);737 ASSERT_EQ(738 APFixedPoint::getFromFloatValue(Val, Saturated(Sema), &Ovf).getValue(),739 ExpectedNonSat);740 ASSERT_EQ(Ovf, false);741}742 743void CheckFloatToFixedConversion(APFloat &Val, const FixedPointSemantics &Sema,744 OvfKind ExpectedOvf) {745 bool Ovf;746 (void)APFixedPoint::getFromFloatValue(Val, Sema, &Ovf);747 ASSERT_EQ(Ovf, true);748 ASSERT_EQ(749 APFixedPoint::getFromFloatValue(Val, Saturated(Sema), &Ovf).getValue(),750 (ExpectedOvf == MinSat ? APFixedPoint::getMin(Sema)751 : APFixedPoint::getMax(Sema))752 .getValue());753 ASSERT_EQ(Ovf, false);754}755 756TEST(FixedPoint, toString) {757 ASSERT_EQ(APFixedPoint::getMax(getS16Neg18()).toString(),758 "0.124996185302734375");759 ASSERT_EQ(APFixedPoint::getMin(getS16Neg18())760 .add(APFixedPoint(1, getS16Neg18()))761 .toString(),762 "-0.124996185302734375");763 ASSERT_EQ(APFixedPoint::getMin(getS16Neg18()).toString(), "-0.125");764 ASSERT_EQ(APFixedPoint::getMax(getU8Neg10()).toString(), "0.2490234375");765 ASSERT_EQ(APFixedPoint::getMin(getU8Neg10()).toString(), "0.0");766 ASSERT_EQ(APFixedPoint::getMax(getS32Pos2()).toString(), "8589934588.0");767 ASSERT_EQ(APFixedPoint::getMin(getS32Pos2())768 .add(APFixedPoint(1, getS32Pos2()))769 .toString(),770 "-8589934588.0");771 ASSERT_EQ(APFixedPoint::getMin(getS32Pos2()).toString(), "-8589934592.0");772 ASSERT_EQ(APFixedPoint::getMax(getU8Pos4()).toString(), "4080.0");773 ASSERT_EQ(APFixedPoint::getMin(getU8Pos4()).toString(), "0.0");774}775 776TEST(FixedPoint, FloatToFixed) {777 APFloat Val(0.0f);778 779 // Simple exact fraction780 Val = APFloat(0.75f);781 CheckFloatToFixedConversion(Val, getSAccumSema(), 3ULL << 5);782 CheckFloatToFixedConversion(Val, getAccumSema(), 3ULL << 13);783 CheckFloatToFixedConversion(Val, getLAccumSema(), 3ULL << 29);784 785 CheckFloatToFixedConversion(Val, getUSAccumSema(), 3ULL << 6);786 CheckFloatToFixedConversion(Val, getUAccumSema(), 3ULL << 14);787 CheckFloatToFixedConversion(Val, getULAccumSema(), 3ULL << 30);788 789 CheckFloatToFixedConversion(Val, getSFractSema(), 3ULL << 5);790 CheckFloatToFixedConversion(Val, getFractSema(), 3ULL << 13);791 CheckFloatToFixedConversion(Val, getLFractSema(), 3ULL << 29);792 793 CheckFloatToFixedConversion(Val, getUSFractSema(), 3ULL << 6);794 CheckFloatToFixedConversion(Val, getUFractSema(), 3ULL << 14);795 CheckFloatToFixedConversion(Val, getULFractSema(), 3ULL << 30);796 797 CheckFloatToFixedConversion(Val, getU8Neg10(), MaxSat);798 CheckFloatToFixedConversion(Val, getU8Pos4(), 0);799 CheckFloatToFixedConversion(Val, getS16Neg18(), MaxSat);800 CheckFloatToFixedConversion(Val, getS32Pos2(), 0);801 802 // Simple negative exact fraction803 Val = APFloat(-0.75f);804 CheckFloatToFixedConversion(Val, getSAccumSema(), -3ULL << 5);805 CheckFloatToFixedConversion(Val, getAccumSema(), -3ULL << 13);806 CheckFloatToFixedConversion(Val, getLAccumSema(), -3ULL << 29);807 808 CheckFloatToFixedConversion(Val, getUSAccumSema(), MinSat);809 CheckFloatToFixedConversion(Val, getUAccumSema(), MinSat);810 CheckFloatToFixedConversion(Val, getULAccumSema(), MinSat);811 812 CheckFloatToFixedConversion(Val, getSFractSema(), -3ULL << 5);813 CheckFloatToFixedConversion(Val, getFractSema(), -3ULL << 13);814 CheckFloatToFixedConversion(Val, getLFractSema(), -3ULL << 29);815 816 CheckFloatToFixedConversion(Val, getUSFractSema(), MinSat);817 CheckFloatToFixedConversion(Val, getUFractSema(), MinSat);818 CheckFloatToFixedConversion(Val, getULFractSema(), MinSat);819 820 CheckFloatToFixedConversion(Val, getU8Neg10(), MinSat);821 CheckFloatToFixedConversion(Val, getU8Pos4(), 0);822 CheckFloatToFixedConversion(Val, getS16Neg18(), MinSat);823 CheckFloatToFixedConversion(Val, getS32Pos2(), 0);824 825 // Highly precise fraction826 Val = APFloat(0.999999940395355224609375f);827 CheckFloatToFixedConversion(Val, getSAccumSema(), 0x7FULL);828 CheckFloatToFixedConversion(Val, getAccumSema(), 0x7FFFULL);829 CheckFloatToFixedConversion(Val, getLAccumSema(), 0xFFFFFFULL << 7);830 831 CheckFloatToFixedConversion(Val, getUSAccumSema(), 0xFFULL);832 CheckFloatToFixedConversion(Val, getUAccumSema(), 0xFFFFULL);833 CheckFloatToFixedConversion(Val, getULAccumSema(), 0xFFFFFFULL << 8);834 835 CheckFloatToFixedConversion(Val, getSFractSema(), 0x7FULL);836 CheckFloatToFixedConversion(Val, getFractSema(), 0x7FFFULL);837 CheckFloatToFixedConversion(Val, getLFractSema(), 0xFFFFFFULL << 7);838 839 CheckFloatToFixedConversion(Val, getUSFractSema(), 0xFFULL);840 CheckFloatToFixedConversion(Val, getUFractSema(), 0xFFFFULL);841 CheckFloatToFixedConversion(Val, getULFractSema(), 0xFFFFFFULL << 8);842 843 CheckFloatToFixedConversion(Val, getU8Neg10(), MaxSat);844 CheckFloatToFixedConversion(Val, getU8Pos4(), 0);845 CheckFloatToFixedConversion(Val, getS16Neg18(), MaxSat);846 CheckFloatToFixedConversion(Val, getS32Pos2(), 0);847 848 // Integral and fraction849 Val = APFloat(17.99609375f);850 CheckFloatToFixedConversion(Val, getSAccumSema(), 0x11FFULL >> 1);851 CheckFloatToFixedConversion(Val, getAccumSema(), 0x11FFULL << 7);852 CheckFloatToFixedConversion(Val, getLAccumSema(), 0x11FFULL << 23);853 854 CheckFloatToFixedConversion(Val, getUSAccumSema(), 0x11FFULL);855 CheckFloatToFixedConversion(Val, getUAccumSema(), 0x11FFULL << 8);856 CheckFloatToFixedConversion(Val, getULAccumSema(), 0x11FFULL << 24);857 858 CheckFloatToFixedConversion(Val, getSFractSema(), MaxSat);859 CheckFloatToFixedConversion(Val, getFractSema(), MaxSat);860 CheckFloatToFixedConversion(Val, getLFractSema(), MaxSat);861 862 CheckFloatToFixedConversion(Val, getUSFractSema(), MaxSat);863 CheckFloatToFixedConversion(Val, getUFractSema(), MaxSat);864 CheckFloatToFixedConversion(Val, getULFractSema(), MaxSat);865 866 CheckFloatToFixedConversion(Val, getU8Neg10(), MaxSat);867 CheckFloatToFixedConversion(Val, getU8Pos4(), 1);868 CheckFloatToFixedConversion(Val, getS16Neg18(), MaxSat);869 CheckFloatToFixedConversion(Val, getS32Pos2(), 1 << 2);870 871 // Negative integral and fraction872 Val = APFloat(-17.99609375f);873 CheckFloatToFixedConversion(Val, getSAccumSema(), -0x11FELL >> 1);874 CheckFloatToFixedConversion(Val, getAccumSema(), -0x11FFULL << 7);875 CheckFloatToFixedConversion(Val, getLAccumSema(), -0x11FFULL << 23);876 877 CheckFloatToFixedConversion(Val, getUSAccumSema(), MinSat);878 CheckFloatToFixedConversion(Val, getUAccumSema(), MinSat);879 CheckFloatToFixedConversion(Val, getULAccumSema(), MinSat);880 881 CheckFloatToFixedConversion(Val, getSFractSema(), MinSat);882 CheckFloatToFixedConversion(Val, getFractSema(), MinSat);883 CheckFloatToFixedConversion(Val, getLFractSema(), MinSat);884 885 CheckFloatToFixedConversion(Val, getUSFractSema(), MinSat);886 CheckFloatToFixedConversion(Val, getUFractSema(), MinSat);887 CheckFloatToFixedConversion(Val, getULFractSema(), MinSat);888 889 CheckFloatToFixedConversion(Val, getU8Neg10(), MinSat);890 CheckFloatToFixedConversion(Val, getU8Pos4(), MinSat);891 CheckFloatToFixedConversion(Val, getS16Neg18(), MinSat);892 CheckFloatToFixedConversion(Val, getS32Pos2(), -4);893 894 // Very large value895 Val = APFloat(1.0e38f);896 CheckFloatToFixedConversion(Val, getSAccumSema(), MaxSat);897 CheckFloatToFixedConversion(Val, getAccumSema(), MaxSat);898 CheckFloatToFixedConversion(Val, getLAccumSema(), MaxSat);899 900 CheckFloatToFixedConversion(Val, getUSAccumSema(), MaxSat);901 CheckFloatToFixedConversion(Val, getUAccumSema(), MaxSat);902 CheckFloatToFixedConversion(Val, getULAccumSema(), MaxSat);903 904 CheckFloatToFixedConversion(Val, getSFractSema(), MaxSat);905 CheckFloatToFixedConversion(Val, getFractSema(), MaxSat);906 CheckFloatToFixedConversion(Val, getLFractSema(), MaxSat);907 908 CheckFloatToFixedConversion(Val, getUSFractSema(), MaxSat);909 CheckFloatToFixedConversion(Val, getUFractSema(), MaxSat);910 CheckFloatToFixedConversion(Val, getULFractSema(), MaxSat);911 912 CheckFloatToFixedConversion(Val, getU8Neg10(), MaxSat);913 CheckFloatToFixedConversion(Val, getU8Pos4(), MaxSat);914 CheckFloatToFixedConversion(Val, getS16Neg18(), MaxSat);915 CheckFloatToFixedConversion(Val, getS32Pos2(), MaxSat);916 917 // Very small value918 Val = APFloat(1.0e-38f);919 CheckFloatToFixedConversion(Val, getSAccumSema(), 0);920 CheckFloatToFixedConversion(Val, getAccumSema(), 0);921 CheckFloatToFixedConversion(Val, getLAccumSema(), 0);922 923 CheckFloatToFixedConversion(Val, getUSAccumSema(), 0);924 CheckFloatToFixedConversion(Val, getUAccumSema(), 0);925 CheckFloatToFixedConversion(Val, getULAccumSema(), 0);926 927 CheckFloatToFixedConversion(Val, getSFractSema(), 0);928 CheckFloatToFixedConversion(Val, getFractSema(), 0);929 CheckFloatToFixedConversion(Val, getLFractSema(), 0);930 931 CheckFloatToFixedConversion(Val, getUSFractSema(), 0);932 CheckFloatToFixedConversion(Val, getUFractSema(), 0);933 CheckFloatToFixedConversion(Val, getULFractSema(), 0);934 935 CheckFloatToFixedConversion(Val, getU8Neg10(), 0);936 CheckFloatToFixedConversion(Val, getU8Pos4(), 0);937 CheckFloatToFixedConversion(Val, getS16Neg18(), 0);938 CheckFloatToFixedConversion(Val, getS32Pos2(), 0);939 940 // Half conversion941 Val = APFloat(0.99951171875f);942 bool Ignored;943 Val.convert(APFloat::IEEEhalf(), APFloat::rmNearestTiesToEven, &Ignored);944 945 CheckFloatToFixedConversion(Val, getSAccumSema(), 0x7FULL);946 CheckFloatToFixedConversion(Val, getAccumSema(), 0x7FFULL << 4);947 CheckFloatToFixedConversion(Val, getLAccumSema(), 0x7FFULL << 20);948 949 CheckFloatToFixedConversion(Val, getUSAccumSema(), 0xFFULL);950 CheckFloatToFixedConversion(Val, getUAccumSema(), 0xFFEULL << 4);951 CheckFloatToFixedConversion(Val, getULAccumSema(), 0xFFEULL << 20);952 953 CheckFloatToFixedConversion(Val, getSFractSema(), 0x7FULL);954 CheckFloatToFixedConversion(Val, getFractSema(), 0x7FFULL << 4);955 CheckFloatToFixedConversion(Val, getLFractSema(), 0x7FFULL << 20);956 957 CheckFloatToFixedConversion(Val, getUSFractSema(), 0xFFULL);958 CheckFloatToFixedConversion(Val, getUFractSema(), 0xFFEULL << 4);959 CheckFloatToFixedConversion(Val, getULFractSema(), 0xFFEULL << 20);960 961 CheckFloatToFixedConversion(Val, getU8Neg10(), MaxSat);962 CheckFloatToFixedConversion(Val, getU8Pos4(), 0);963 CheckFloatToFixedConversion(Val, getS16Neg18(), MaxSat);964 CheckFloatToFixedConversion(Val, getS32Pos2(), 0);965 966 Val = APFloat(0.124996185302734375);967 CheckFloatToFixedConversion(Val, getU8Neg10(), 0x7f);968 CheckFloatToFixedConversion(Val, getU8Pos4(), 0);969 CheckFloatToFixedConversion(Val, getS16Neg18(), 0x7fff);970 CheckFloatToFixedConversion(Val, getS32Pos2(), 0);971 972 Val = APFloat(-0.124996185302734375);973 CheckFloatToFixedConversion(Val, getU8Neg10(), MinSat);974 CheckFloatToFixedConversion(Val, getU8Pos4(), 0);975 CheckFloatToFixedConversion(Val, getS16Neg18(), -0x7fff);976 CheckFloatToFixedConversion(Val, getS32Pos2(), 0);977}978 979void CheckFixedToFloatConversion(int64_t Val, const FixedPointSemantics &Sema,980 float Result) {981 APFixedPoint FXVal(Val, Sema);982 APFloat APRes(Result);983 ASSERT_EQ(FXVal.convertToFloat(APFloat::IEEEsingle()), APRes);984}985 986void CheckFixedToHalfConversion(int64_t Val, const FixedPointSemantics &Sema,987 float Result) {988 APFixedPoint FXVal(Val, Sema);989 APFloat APRes(Result);990 bool Ignored;991 APRes.convert(APFloat::IEEEhalf(), APFloat::rmNearestTiesToEven, &Ignored);992 ASSERT_EQ(FXVal.convertToFloat(APFloat::IEEEhalf()), APRes);993}994 995TEST(FixedPoint, FixedToFloat) {996 int64_t Val = 0x1ULL;997 CheckFixedToFloatConversion(Val, getSAccumSema(), 0.0078125f);998 CheckFixedToFloatConversion(Val, getFractSema(), 0.000030517578125f);999 CheckFixedToFloatConversion(Val, getAccumSema(), 0.000030517578125f);1000 CheckFixedToFloatConversion(Val, getLFractSema(),1001 0.0000000004656612873077392578125f);1002 1003 CheckFixedToFloatConversion(Val, getUSAccumSema(), 0.00390625f);1004 CheckFixedToFloatConversion(Val, getUFractSema(), 0.0000152587890625f);1005 CheckFixedToFloatConversion(Val, getUAccumSema(), 0.0000152587890625f);1006 CheckFixedToFloatConversion(Val, getULFractSema(),1007 0.00000000023283064365386962890625f);1008 1009 CheckFixedToFloatConversion(Val, getU8Neg10(), 0.0009765625f);1010 CheckFixedToFloatConversion(Val, getU8Pos4(), 16.0f);1011 CheckFixedToFloatConversion(Val, getS16Neg18(), 0.000003814697265625f);1012 CheckFixedToFloatConversion(Val, getS32Pos2(), 4.0f);1013 1014 Val = 0x7FULL;1015 CheckFixedToFloatConversion(Val, getSAccumSema(), 0.9921875f);1016 CheckFixedToFloatConversion(Val, getFractSema(), 0.003875732421875f);1017 CheckFixedToFloatConversion(Val, getAccumSema(), 0.003875732421875f);1018 CheckFixedToFloatConversion(Val, getLFractSema(),1019 0.0000000591389834880828857421875f);1020 1021 CheckFixedToFloatConversion(Val, getUSAccumSema(), 0.49609375f);1022 CheckFixedToFloatConversion(Val, getUFractSema(), 0.0019378662109375f);1023 CheckFixedToFloatConversion(Val, getUAccumSema(), 0.0019378662109375f);1024 CheckFixedToFloatConversion(Val, getULFractSema(),1025 0.00000002956949174404144287109375f);1026 1027 CheckFixedToFloatConversion(Val, getU8Neg10(), 0.1240234375f);1028 CheckFixedToFloatConversion(Val, getU8Pos4(), 2032.0f);1029 CheckFixedToFloatConversion(Val, getS16Neg18(), 0.000484466552734375f);1030 CheckFixedToFloatConversion(Val, getS32Pos2(), 508.0f);1031 1032 Val = -0x1ULL;1033 CheckFixedToFloatConversion(Val, getSAccumSema(), -0.0078125f);1034 CheckFixedToFloatConversion(Val, getFractSema(), -0.000030517578125f);1035 CheckFixedToFloatConversion(Val, getAccumSema(), -0.000030517578125f);1036 CheckFixedToFloatConversion(Val, getLFractSema(),1037 -0.0000000004656612873077392578125f);1038 1039 CheckFixedToFloatConversion(Val, getU8Neg10(), 0.249023437f);1040 CheckFixedToFloatConversion(Val, getU8Pos4(), 4080.0f);1041 CheckFixedToFloatConversion(Val, getS16Neg18(), -0.000003814697265625f);1042 CheckFixedToFloatConversion(Val, getS32Pos2(), -4.0f);1043 1044 CheckFixedToFloatConversion(-0x80ULL, getSAccumSema(), -1.0f);1045 CheckFixedToFloatConversion(-0x8000ULL, getFractSema(), -1.0f);1046 CheckFixedToFloatConversion(-0x8000ULL, getAccumSema(), -1.0f);1047 CheckFixedToFloatConversion(-0x80000000ULL, getLFractSema(), -1.0f);1048 1049 Val = 0xAFAULL;1050 CheckFixedToFloatConversion(Val, getSAccumSema(), 21.953125f);1051 CheckFixedToFloatConversion(Val, getFractSema(), 0.08575439453125f);1052 CheckFixedToFloatConversion(Val, getAccumSema(), 0.08575439453125f);1053 CheckFixedToFloatConversion(Val, getLFractSema(),1054 0.000001308508217334747314453125f);1055 1056 CheckFixedToFloatConversion(Val, getUSAccumSema(), 10.9765625f);1057 CheckFixedToFloatConversion(Val, getUFractSema(), 0.042877197265625f);1058 CheckFixedToFloatConversion(Val, getUAccumSema(), 0.042877197265625f);1059 CheckFixedToFloatConversion(Val, getULFractSema(),1060 0.0000006542541086673736572265625f);1061 1062 CheckFixedToFloatConversion(Val, getS16Neg18(), 0.01071929931640625f);1063 CheckFixedToFloatConversion(Val, getS32Pos2(), 11240.0f);1064 1065 Val = -0xAFAULL;1066 CheckFixedToFloatConversion(Val, getSAccumSema(), -21.953125f);1067 CheckFixedToFloatConversion(Val, getFractSema(), -0.08575439453125f);1068 CheckFixedToFloatConversion(Val, getAccumSema(), -0.08575439453125f);1069 CheckFixedToFloatConversion(Val, getLFractSema(),1070 -0.000001308508217334747314453125f);1071 1072 CheckFixedToFloatConversion(Val, getS16Neg18(), -0.01071929931640625f);1073 CheckFixedToFloatConversion(Val, getS32Pos2(), -11240.0f);1074 1075 Val = 0x40000080ULL;1076 CheckFixedToFloatConversion(Val, getAccumSema(), 32768.00390625f);1077 CheckFixedToFloatConversion(Val, getLFractSema(),1078 0.500000059604644775390625f);1079 1080 CheckFixedToFloatConversion(Val, getUAccumSema(), 16384.001953125f);1081 CheckFixedToFloatConversion(Val, getULFractSema(),1082 0.2500000298023223876953125f);1083 1084 CheckFixedToFloatConversion(Val, getS32Pos2(), 4294967808.0f);1085 1086 Val = 0x40000040ULL;1087 CheckFixedToFloatConversion(Val, getAccumSema(), 32768.0f);1088 CheckFixedToFloatConversion(Val, getLFractSema(), 0.5f);1089 1090 CheckFixedToFloatConversion(Val, getUAccumSema(), 16384.0f);1091 CheckFixedToFloatConversion(Val, getULFractSema(), 0.25f);1092 1093 CheckFixedToFloatConversion(Val, getS32Pos2(), 4294967552.0f);1094 1095 Val = 0x7FF0ULL;1096 CheckFixedToHalfConversion(Val, getAccumSema(), 0.99951171875f);1097 CheckFixedToHalfConversion(Val, getLFractSema(), 0.000015251338481903076171875f);1098 1099 CheckFixedToHalfConversion(Val, getUAccumSema(), 0.499755859375f);1100 CheckFixedToHalfConversion(Val, getULFractSema(), 0.0000076256692409515380859375f);1101 1102 CheckFixedToFloatConversion(Val, getS32Pos2(), 131008.0f);1103}1104 1105void CheckAdd(const APFixedPoint &Lhs, const APFixedPoint &Rhs,1106 const APFixedPoint &Res) {1107 bool Overflow = false;1108 APFixedPoint Result = Lhs.add(Rhs, &Overflow);1109 ASSERT_FALSE(Overflow);1110 ASSERT_EQ(Result.getSemantics(), Res.getSemantics());1111 ASSERT_EQ(Result, Res);1112}1113 1114void CheckAddOverflow(const APFixedPoint &Lhs, const APFixedPoint &Rhs) {1115 bool Overflow = false;1116 APFixedPoint Result = Lhs.add(Rhs, &Overflow);1117 ASSERT_TRUE(Overflow);1118}1119 1120TEST(FixedPoint, add) {1121 CheckAdd(APFixedPoint(1, getS32Pos2()), APFixedPoint(1, getS32Pos2()),1122 APFixedPoint(2, getS32Pos2()));1123 CheckAdd(APFixedPoint(1, getS16Neg18()), APFixedPoint(1, getS16Neg18()),1124 APFixedPoint(2, getS16Neg18()));1125 CheckAdd(APFixedPoint(1, getU8Neg10()), APFixedPoint(1, getU8Neg10()),1126 APFixedPoint(2, getU8Neg10()));1127 CheckAdd(APFixedPoint(1, getU8Pos4()), APFixedPoint(1, getU8Pos4()),1128 APFixedPoint(2, getU8Pos4()));1129 1130 CheckAdd(APFixedPoint(11, getS32Pos2()), APFixedPoint(1, getS32Pos2()),1131 APFixedPoint(12, getS32Pos2()));1132 CheckAdd(APFixedPoint(11, getS16Neg18()), APFixedPoint(1, getS16Neg18()),1133 APFixedPoint(12, getS16Neg18()));1134 CheckAdd(APFixedPoint(11, getU8Neg10()), APFixedPoint(1, getU8Neg10()),1135 APFixedPoint(12, getU8Neg10()));1136 CheckAdd(APFixedPoint(11, getU8Pos4()), APFixedPoint(1, getU8Pos4()),1137 APFixedPoint(12, getU8Pos4()));1138 1139 CheckAdd(APFixedPoint(11, getS32Pos2()), APFixedPoint(1, getS16Neg18()),1140 APFixedPoint(11534337,1141 FixedPointSemantics(52, FixedPointSemantics::Lsb{-18},1142 true, false, false)));1143 CheckAdd(1144 APFixedPoint(11, getU8Neg10()), APFixedPoint(-9472, getS16Neg18()),1145 APFixedPoint(-6656, FixedPointSemantics(17, FixedPointSemantics::Lsb{-18},1146 true, false, false)));1147 CheckAddOverflow(1148 APFixedPoint::getMax(getU8Neg10()), APFixedPoint::getMax(getS16Neg18()));1149 CheckAdd(APFixedPoint::getMin(getU8Neg10()),1150 APFixedPoint::getMin(getS16Neg18()),1151 APFixedPoint::getMin(getS16Neg18())1152 .convert(FixedPointSemantics(17, FixedPointSemantics::Lsb{-18},1153 true, false, false)));1154 CheckAddOverflow(APFixedPoint::getMin(getS32Pos2()),1155 APFixedPoint::getMin(getS16Neg18()));1156}1157 1158void CheckMul(const APFixedPoint &Lhs, const APFixedPoint &Rhs,1159 const APFixedPoint &Res) {1160 bool Overflow = false;1161 APFixedPoint Result = Lhs.mul(Rhs, &Overflow);1162 ASSERT_FALSE(Overflow);1163 ASSERT_EQ(Result.getSemantics(), Res.getSemantics());1164 ASSERT_EQ(Result, Res);1165}1166 1167void CheckMulOverflow(const APFixedPoint &Lhs, const APFixedPoint &Rhs) {1168 bool Overflow = false;1169 APFixedPoint Result = Lhs.mul(Rhs, &Overflow);1170 ASSERT_TRUE(Overflow);1171}1172 1173TEST(FixedPoint, mul) {1174 CheckMul(APFixedPoint(1, getS32Pos2()), APFixedPoint(1, getS32Pos2()),1175 APFixedPoint(4, getS32Pos2()));1176 CheckMul(APFixedPoint(1, getS16Neg18()), APFixedPoint(1, getS16Neg18()),1177 APFixedPoint(0, getS16Neg18()));1178 CheckMul(APFixedPoint(1, getU8Neg10()), APFixedPoint(1, getU8Neg10()),1179 APFixedPoint(0, getU8Neg10()));1180 CheckMul(APFixedPoint(1, getU8Pos4()), APFixedPoint(1, getU8Pos4()),1181 APFixedPoint(16, getU8Pos4()));1182 1183 CheckMul(APFixedPoint(11, getS32Pos2()), APFixedPoint(1, getS32Pos2()),1184 APFixedPoint(44, getS32Pos2()));1185 CheckMul(APFixedPoint(11, getS16Neg18()), APFixedPoint(1, getS16Neg18()),1186 APFixedPoint(0, getS16Neg18()));1187 CheckMul(APFixedPoint(11, getU8Neg10()), APFixedPoint(1, getU8Neg10()),1188 APFixedPoint(0, getU8Neg10()));1189 CheckMul(APFixedPoint(11, getU8Pos4()), APFixedPoint(1, getU8Pos4()),1190 APFixedPoint(176, getU8Pos4()));1191 1192 CheckMul(APFixedPoint(512, getS16Neg18()), APFixedPoint(512, getS16Neg18()),1193 APFixedPoint(1, getS16Neg18()));1194 CheckMul(APFixedPoint(32, getU8Neg10()), APFixedPoint(32, getU8Neg10()),1195 APFixedPoint(1, getU8Neg10()));1196 1197 CheckMul(APFixedPoint(11, getS32Pos2()), APFixedPoint(1, getS16Neg18()),1198 APFixedPoint(44,1199 FixedPointSemantics(52, FixedPointSemantics::Lsb{-18},1200 true, false, false)));1201 CheckMul(1202 APFixedPoint(11, getU8Neg10()), APFixedPoint(-9472, getS16Neg18()),1203 APFixedPoint(-102, FixedPointSemantics(17, FixedPointSemantics::Lsb{-18},1204 true, false, false)));1205 CheckMul(1206 APFixedPoint::getMax(getU8Neg10()), APFixedPoint::getMax(getS16Neg18()),1207 APFixedPoint(8159, FixedPointSemantics(17, FixedPointSemantics::Lsb{-18},1208 true, false, false)));1209 CheckMul(1210 APFixedPoint::getMin(getU8Neg10()), APFixedPoint::getMin(getS16Neg18()),1211 APFixedPoint(0, FixedPointSemantics(17, FixedPointSemantics::Lsb{-18},1212 true, false, false)));1213 CheckMul(APFixedPoint::getMin(getS32Pos2()),1214 APFixedPoint::getMin(getS16Neg18()),1215 APFixedPoint(281474976710656,1216 FixedPointSemantics(52, FixedPointSemantics::Lsb{-18},1217 true, false, false)));1218 CheckMulOverflow(APFixedPoint::getMax(getS32Pos2()), APFixedPoint::getMax(getU8Pos4()));1219 CheckMulOverflow(APFixedPoint::getMin(getS32Pos2()), APFixedPoint::getMax(getU8Pos4()));1220}1221 1222void CheckDiv(const APFixedPoint &Lhs, const APFixedPoint &Rhs,1223 const APFixedPoint &Expected) {1224 bool Overflow = false;1225 APFixedPoint Result = Lhs.div(Rhs, &Overflow);1226 ASSERT_FALSE(Overflow);1227 ASSERT_EQ(Result.getSemantics(), Expected.getSemantics());1228 ASSERT_EQ(Result, Expected);1229}1230 1231void CheckDivOverflow(const APFixedPoint &Lhs, const APFixedPoint &Rhs) {1232 bool Overflow = false;1233 APFixedPoint Result = Lhs.div(Rhs, &Overflow);1234 ASSERT_TRUE(Overflow);1235}1236 1237TEST(FixedPoint, div) {1238 CheckDiv(APFixedPoint(1, getS32Pos2()), APFixedPoint(1, getS32Pos2()),1239 APFixedPoint(0, getS32Pos2()));1240 CheckDivOverflow(APFixedPoint(1, getS16Neg18()), APFixedPoint(1, getS16Neg18()));1241 CheckDivOverflow(APFixedPoint(1, getU8Neg10()), APFixedPoint(1, getU8Neg10()));1242 CheckDiv(APFixedPoint(1, getU8Pos4()), APFixedPoint(1, getU8Pos4()),1243 APFixedPoint(0, getU8Pos4()));1244 1245 CheckDiv(APFixedPoint(11, getS32Pos2()), APFixedPoint(1, getS32Pos2()),1246 APFixedPoint(2, getS32Pos2()));1247 CheckDiv(APFixedPoint(11, getU8Pos4()), APFixedPoint(1, getU8Pos4()),1248 APFixedPoint(0, getU8Pos4()));1249 1250 CheckDiv(APFixedPoint(11, getS32Pos2()), APFixedPoint(1, getS16Neg18()),1251 APFixedPoint(3023656976384,1252 FixedPointSemantics(52, FixedPointSemantics::Lsb{-18},1253 true, false, false)));1254 CheckDiv(APFixedPoint(11, getU8Neg10()), APFixedPoint(-11264, getS16Neg18()),1255 APFixedPoint::getMin(FixedPointSemantics(1256 17, FixedPointSemantics::Lsb{-18}, true, false, false)));1257 CheckDiv(APFixedPoint(11, getU8Neg10()), APFixedPoint(11265, getS16Neg18()),1258 APFixedPoint(0xfffa,1259 FixedPointSemantics(17, FixedPointSemantics::Lsb{-18},1260 true, false, false)));1261 CheckDivOverflow(APFixedPoint(11, getU8Neg10()),1262 APFixedPoint(11264, getS16Neg18()));1263 1264 CheckDivOverflow(APFixedPoint(11, getU8Neg10()),1265 APFixedPoint(-9472, getS16Neg18()));1266 CheckDivOverflow(APFixedPoint::getMax(getU8Neg10()),1267 APFixedPoint::getMax(getS16Neg18()));1268 CheckDiv(1269 APFixedPoint::getMin(getU8Neg10()), APFixedPoint::getMin(getS16Neg18()),1270 APFixedPoint(0, FixedPointSemantics(17, FixedPointSemantics::Lsb{-18},1271 true, false, false)));1272 CheckDiv(1273 APFixedPoint(1, getU8Neg10()), APFixedPoint::getMin(getS16Neg18()),1274 APFixedPoint(-2048, FixedPointSemantics(17, FixedPointSemantics::Lsb{-18},1275 true, false, false)));1276}1277 1278TEST(FixedPoint, semanticsSerialization) {1279 auto roundTrip = [](FixedPointSemantics FPS) -> bool {1280 uint32_t I = FPS.toOpaqueInt();1281 FixedPointSemantics FPS2 = FixedPointSemantics::getFromOpaqueInt(I);1282 return FPS == FPS2;1283 };1284 1285 ASSERT_TRUE(roundTrip(getS32Pos2()));1286 ASSERT_TRUE(roundTrip(getU8Pos4()));1287 ASSERT_TRUE(roundTrip(getS16Neg18()));1288 ASSERT_TRUE(roundTrip(getU8Neg10()));1289 ASSERT_TRUE(roundTrip(getPadULFractSema()));1290 ASSERT_TRUE(roundTrip(getPadUFractSema()));1291 ASSERT_TRUE(roundTrip(getPadUSFractSema()));1292 ASSERT_TRUE(roundTrip(getPadULAccumSema()));1293 ASSERT_TRUE(roundTrip(getPadUAccumSema()));1294 ASSERT_TRUE(roundTrip(getPadUSAccumSema()));1295 ASSERT_TRUE(roundTrip(getULFractSema()));1296 ASSERT_TRUE(roundTrip(getUFractSema()));1297 ASSERT_TRUE(roundTrip(getUSFractSema()));1298 ASSERT_TRUE(roundTrip(getULAccumSema()));1299 ASSERT_TRUE(roundTrip(getUAccumSema()));1300 ASSERT_TRUE(roundTrip(getUSAccumSema()));1301 ASSERT_TRUE(roundTrip(getLFractSema()));1302 ASSERT_TRUE(roundTrip(getFractSema()));1303 ASSERT_TRUE(roundTrip(getSFractSema()));1304 ASSERT_TRUE(roundTrip(getLAccumSema()));1305 ASSERT_TRUE(roundTrip(getAccumSema()));1306 ASSERT_TRUE(roundTrip(getSAccumSema()));1307}1308 1309} // namespace1310