float16_t float16_t::remainder(float16_t denominator) const { llvm::APFloat result = toLLVMAPF(*this); llvm::APFloat rhsAPF = toLLVMAPF(denominator); // FIXME: Ignoring possible exceptions result.remainder(rhsAPF); return toFP16(result); }
float16_t float16_t::divide(float16_t denominator, RoundingMode roundingMode) const { llvm::APFloat result = toLLVMAPF(*this); llvm::APFloat rhsAPF = toLLVMAPF(denominator); // FIXME: Ignoring possible exceptions result.divide(rhsAPF, getLLVMAPFRoundingMode(roundingMode)); return toFP16(result); }
float16_t float16_t::multiply(float16_t rhs, RoundingMode roundingMode) const { llvm::APFloat result = toLLVMAPF(*this); llvm::APFloat rhsAPF = toLLVMAPF(rhs); // FIXME: Ignoring possible exceptions result.multiply(rhsAPF, getLLVMAPFRoundingMode(roundingMode)); return toFP16(result); }
float16_t float16_t::mod(float16_t denominator, RoundingMode roundingMode) const { llvm::APFloat result = toLLVMAPF(*this); llvm::APFloat rhsAPF = toLLVMAPF(denominator); // FIXME: Ignoring possible exceptions // LLVM removed the rounding mode as the operation is always exact. // TODO: change float16_t::mod to no take a rounding mode. result.mod(rhsAPF); return toFP16(result); }
float16_t::operator double() const { llvm::APFloat convertedValue = toLLVMAPF(*this); bool losesInfo = false; // Converting to a more precise type so the rounding mode does not matter, so // just pick any. convertedValue.convert(llvm::APFloat::IEEEdouble, llvm::APFloat::rmNearestTiesToEven, &losesInfo); internal_assert(!losesInfo) << "Unexpected information loss\n"; return convertedValue.convertToDouble(); }
std::string float16_t::to_hex_string() const { // Expected format of result: [-]0xh.hhhp[+-]dd // at most 12 characters are needed for half precision // + 1 for null terminator char buffer[13]; llvm::APFloat repr = toLLVMAPF(*this); // The rounding mode does not matter here when we set hexDigits to 0 which // will give the precise representation. So any rounding mode will do. unsigned count = repr.convertToHexString(buffer, /*hexDigits=*/0, /*upperCase=*/false, llvm::APFloat::rmNearestTiesToEven); internal_assert(count < sizeof(buffer) / sizeof(char)) << "Incorrect buffer size\n"; std::string result(buffer); return result; }
bool float16_t::is_zero() const { llvm::APFloat repr = toLLVMAPF(*this); return repr.isZero(); }
bool float16_t::is_negative() const { llvm::APFloat repr = toLLVMAPF(*this); return repr.isNegative(); }
bool float16_t::is_infinity() const { llvm::APFloat repr = toLLVMAPF(*this); return repr.isInfinity(); }
bool float16_t::is_nan() const { llvm::APFloat repr = toLLVMAPF(*this); return repr.isNaN(); }
std::string float16_t::to_decimal_string(unsigned int significantDigits) const { llvm::APFloat repr = toLLVMAPF(*this); llvm::SmallVector<char, 16> result; repr.toString(result, /*FormatPrecision=*/significantDigits, /*FormatMaxPadding=*/0); return std::string(result.begin(), result.end()); }
bool float16_t::are_unordered(float16_t rhs) const { llvm::APFloat lhsAPF = toLLVMAPF(*this); llvm::APFloat rhsAPF = toLLVMAPF(rhs); return lhsAPF.compare(rhsAPF) == llvm::APFloat::cmpUnordered; }
bool float16_t::operator<(float16_t rhs) const { internal_assert(!this->are_unordered(rhs)) << "Cannot compare unorderable values\n"; llvm::APFloat lhsAPF = toLLVMAPF(*this); llvm::APFloat rhsAPF = toLLVMAPF(rhs); return lhsAPF.compare(rhsAPF) == llvm::APFloat::cmpLessThan; }
bool float16_t::operator==(float16_t rhs) const { llvm::APFloat lhsAPF = toLLVMAPF(*this); llvm::APFloat rhsAPF = toLLVMAPF(rhs); return lhsAPF.compare(rhsAPF) == llvm::APFloat::cmpEqual; }
float16_t float16_t::operator-() const { llvm::APFloat result = toLLVMAPF(*this); result.changeSign(); return toFP16(result); }