brintos

brintos / llvm-project-archived public Read only

0
0
Text · 54.6 KiB · b71c5e1 Raw
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