this repo has no description
at trunk 1035 lines 40 kB view raw
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) 2#include "float-builtins.h" 3 4#include <limits> 5 6#include "gtest/gtest.h" 7 8#include "builtins.h" 9#include "handles.h" 10#include "int-builtins.h" 11#include "objects.h" 12#include "runtime.h" 13#include "test-utils.h" 14 15namespace py { 16namespace testing { 17 18using FloatBuiltinsTest = testing::RuntimeFixture; 19 20TEST(FloatBuiltinsTestNoFixture, 21 DecodeDoubleWithPositiveDoubleReturnsIsNegFalse) { 22 double input = 100.0; 23 bool is_neg; 24 int exp; 25 int64_t mantissa; 26 decodeDouble(input, &is_neg, &exp, &mantissa); 27 EXPECT_EQ(is_neg, false); 28} 29 30TEST(FloatBuiltinsTestNoFixture, 31 DecodeDoubleWithNegativeDoubleReturnsIsNegTrue) { 32 double input = -100.0; 33 bool is_neg; 34 int exp; 35 int64_t mantissa; 36 decodeDouble(input, &is_neg, &exp, &mantissa); 37 EXPECT_EQ(is_neg, true); 38} 39 40TEST(FloatBuiltinsTestNoFixture, 41 DecodeDoubleWithMaximumExponentReturnsCorrectValue) { 42 double input = std::strtod("0x1.0p+1024", nullptr); 43 bool is_neg; 44 int exp; 45 int64_t mantissa; 46 decodeDouble(input, &is_neg, &exp, &mantissa); 47 EXPECT_EQ(exp, 1024); 48} 49 50TEST(FloatBuiltinsTestNoFixture, 51 DecodeDoubleWithMinimumExponentReturnsCorrectValue) { 52 double input = std::strtod("0x1.0p-1023", nullptr); 53 bool is_neg; 54 int exp; 55 int64_t mantissa; 56 decodeDouble(input, &is_neg, &exp, &mantissa); 57 EXPECT_EQ(exp, -1023); 58} 59 60TEST(FloatBuiltinsTestNoFixture, DecodeDoubleWithMantissaReturnsCorrectValue) { 61 double input = std::strtod("0x1.29ef685b3f6fbp+52", nullptr); 62 bool is_neg; 63 int exp; 64 int64_t mantissa; 65 decodeDouble(input, &is_neg, &exp, &mantissa); 66 EXPECT_EQ(mantissa, 0x29ef685b3f6fb); 67} 68 69TEST_F(FloatBuiltinsTest, DunderMulWithDoubleReturnsDouble) { 70 HandleScope scope(thread_); 71 Float left(&scope, runtime_->newFloat(2.0)); 72 Float right(&scope, runtime_->newFloat(1.5)); 73 Object result(&scope, runBuiltin(METH(float, __mul__), left, right)); 74 EXPECT_TRUE(isFloatEqualsDouble(*result, 3.0)); 75} 76 77TEST_F(FloatBuiltinsTest, DunderMulWithSmallIntReturnsDouble) { 78 HandleScope scope(thread_); 79 Float left(&scope, runtime_->newFloat(2.5)); 80 Int right(&scope, runtime_->newInt(1)); 81 Object result(&scope, runBuiltin(METH(float, __mul__), left, right)); 82 EXPECT_TRUE(isFloatEqualsDouble(*result, 2.5)); 83} 84 85TEST_F(FloatBuiltinsTest, DunderMulWithNonFloatSelfRaisesTypeError) { 86 HandleScope scope(thread_); 87 Object left(&scope, NoneType::object()); 88 Float right(&scope, runtime_->newFloat(1.0)); 89 Object result(&scope, runBuiltin(METH(float, __mul__), left, right)); 90 EXPECT_TRUE(raised(*result, LayoutId::kTypeError)); 91} 92 93TEST_F(FloatBuiltinsTest, DunderMulWithNonFloatOtherReturnsNotImplemented) { 94 HandleScope scope(thread_); 95 Float left(&scope, runtime_->newFloat(1.0)); 96 Object right(&scope, NoneType::object()); 97 Object result(&scope, runBuiltin(METH(float, __mul__), left, right)); 98 EXPECT_TRUE(result.isNotImplementedType()); 99} 100 101TEST_F(FloatBuiltinsTest, DunderNeWithInequalFloatsReturnsTrue) { 102 ASSERT_FALSE( 103 runFromCStr(runtime_, "result = float.__ne__(12.2, 2.12)").isError()); 104 EXPECT_EQ(mainModuleAt(runtime_, "result"), Bool::trueObj()); 105} 106 107TEST_F(FloatBuiltinsTest, DunderNeWithEqualFloatIntReturnsFalse) { 108 ASSERT_FALSE( 109 runFromCStr(runtime_, "result = float.__ne__(34.0, 34)").isError()); 110 EXPECT_EQ(mainModuleAt(runtime_, "result"), Bool::falseObj()); 111} 112 113TEST_F(FloatBuiltinsTest, DunderNeWithStringReturnsNotImplemented) { 114 ASSERT_FALSE( 115 runFromCStr(runtime_, "result = float.__ne__(5.5, '')").isError()); 116 EXPECT_TRUE(mainModuleAt(runtime_, "result").isNotImplementedType()); 117} 118 119TEST_F(FloatBuiltinsTest, DunderAbsZeroReturnsZero) { 120 HandleScope scope(thread_); 121 Float self(&scope, runtime_->newFloat(0.0)); 122 Object result(&scope, runBuiltin(METH(float, __abs__), self)); 123 EXPECT_TRUE(isFloatEqualsDouble(*result, 0.0)); 124} 125 126TEST_F(FloatBuiltinsTest, DunderAbsNegativeReturnsPositive) { 127 HandleScope scope(thread_); 128 Float self(&scope, runtime_->newFloat(-1234.0)); 129 Object result(&scope, runBuiltin(METH(float, __abs__), self)); 130 EXPECT_TRUE(isFloatEqualsDouble(*result, 1234.0)); 131} 132 133TEST_F(FloatBuiltinsTest, DunderAbsPositiveReturnsPositive) { 134 HandleScope scope(thread_); 135 Float self(&scope, runtime_->newFloat(5678.0)); 136 Object result(&scope, runBuiltin(METH(float, __abs__), self)); 137 EXPECT_TRUE(isFloatEqualsDouble(*result, 5678.0)); 138} 139 140TEST_F(FloatBuiltinsTest, BinaryAddDouble) { 141 HandleScope scope(thread_); 142 143 ASSERT_FALSE(runFromCStr(runtime_, R"( 144a = 2.0 145b = 1.5 146c = a + b 147)") 148 .isError()); 149 150 Object c(&scope, mainModuleAt(runtime_, "c")); 151 EXPECT_TRUE(isFloatEqualsDouble(*c, 3.5)); 152} 153 154TEST_F(FloatBuiltinsTest, BinaryAddSmallInt) { 155 HandleScope scope(thread_); 156 157 ASSERT_FALSE(runFromCStr(runtime_, R"( 158a = 2.5 159b = 1 160c = a + b 161)") 162 .isError()); 163 164 Object c(&scope, mainModuleAt(runtime_, "c")); 165 EXPECT_TRUE(isFloatEqualsDouble(*c, 3.5)); 166} 167 168TEST_F(FloatBuiltinsTest, AddWithNonFloatOtherRaisesTypeError) { 169 const char* src = R"( 1701.0 + None 171)"; 172 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, src), LayoutId::kTypeError, 173 "float.__add__(NoneType) is not supported")); 174} 175 176TEST_F(FloatBuiltinsTest, DunderAddWithFloatSubclassReturnsFloatSum) { 177 HandleScope scope(thread_); 178 EXPECT_FALSE(runFromCStr(runtime_, R"( 179class SubFloat(float): 180 pass 181 182left = SubFloat(1.0) 183right = SubFloat(2.0) 184)") 185 .isError()); 186 Object left(&scope, mainModuleAt(runtime_, "left")); 187 Object right(&scope, mainModuleAt(runtime_, "right")); 188 Object result(&scope, runBuiltin(METH(float, __add__), left, right)); 189 EXPECT_TRUE(isFloatEqualsDouble(*result, 3.0)); 190} 191 192TEST_F(FloatBuiltinsTest, DunderBoolWithZeroReturnsFalse) { 193 HandleScope scope(thread_); 194 Float self(&scope, runtime_->newFloat(0.0)); 195 Object result(&scope, runBuiltin(METH(float, __bool__), self)); 196 EXPECT_EQ(*result, Bool::falseObj()); 197} 198 199TEST_F(FloatBuiltinsTest, DunderBoolWithNonZeroReturnsTrue) { 200 HandleScope scope(thread_); 201 Float self(&scope, runtime_->newFloat(1234.0)); 202 Object result(&scope, runBuiltin(METH(float, __bool__), self)); 203 EXPECT_EQ(*result, Bool::trueObj()); 204} 205 206TEST_F(FloatBuiltinsTest, DunderTrueDivWithDoubleReturnsDouble) { 207 HandleScope scope(thread_); 208 Float left(&scope, runtime_->newFloat(3.0)); 209 Float right(&scope, runtime_->newFloat(2.0)); 210 Object result(&scope, runBuiltin(METH(float, __truediv__), left, right)); 211 EXPECT_TRUE(isFloatEqualsDouble(*result, 1.5)); 212} 213 214TEST_F(FloatBuiltinsTest, DunderTrueDivWithSmallIntReturnsDouble) { 215 HandleScope scope(thread_); 216 Float left(&scope, runtime_->newFloat(3.0)); 217 Int right(&scope, runtime_->newInt(2)); 218 Object result(&scope, runBuiltin(METH(float, __truediv__), left, right)); 219 EXPECT_TRUE(isFloatEqualsDouble(*result, 1.5)); 220} 221 222TEST_F(FloatBuiltinsTest, DunderTrueDivWithNonFloatSelfRaisesTypeError) { 223 HandleScope scope(thread_); 224 Object left(&scope, NoneType::object()); 225 Float right(&scope, runtime_->newFloat(1.0)); 226 Object result(&scope, runBuiltin(METH(float, __truediv__), left, right)); 227 EXPECT_TRUE(raised(*result, LayoutId::kTypeError)); 228} 229 230TEST_F(FloatBuiltinsTest, DunderTrueDivWithNonFloatOtherReturnsNotImplemented) { 231 HandleScope scope(thread_); 232 Float left(&scope, runtime_->newFloat(1.0)); 233 Object right(&scope, NoneType::object()); 234 Object result(&scope, runBuiltin(METH(float, __truediv__), left, right)); 235 EXPECT_TRUE(result.isNotImplementedType()); 236} 237 238TEST_F(FloatBuiltinsTest, DunderTrueDivWithZeroFloatRaisesZeroDivisionError) { 239 HandleScope scope(thread_); 240 Float left(&scope, runtime_->newFloat(1.0)); 241 Float right(&scope, runtime_->newFloat(0.0)); 242 Object result(&scope, runBuiltin(METH(float, __truediv__), left, right)); 243 EXPECT_TRUE(raised(*result, LayoutId::kZeroDivisionError)); 244} 245 246TEST_F(FloatBuiltinsTest, 247 DunderTrueDivWithZeroSmallIntRaisesZeroDivisionError) { 248 HandleScope scope(thread_); 249 Float left(&scope, runtime_->newFloat(1.0)); 250 Int right(&scope, runtime_->newInt(0)); 251 Object result(&scope, runBuiltin(METH(float, __truediv__), left, right)); 252 EXPECT_TRUE(raised(*result, LayoutId::kZeroDivisionError)); 253} 254 255TEST_F(FloatBuiltinsTest, DunderTrueDivWithZeroBoolRaisesZeroDivisionError) { 256 HandleScope scope(thread_); 257 Float left(&scope, runtime_->newFloat(1.0)); 258 Bool right(&scope, RawBool::falseObj()); 259 Object result(&scope, runBuiltin(METH(float, __truediv__), left, right)); 260 EXPECT_TRUE(raised(*result, LayoutId::kZeroDivisionError)); 261} 262 263TEST_F(FloatBuiltinsTest, DunderRtruedivWithDoubleReturnsDouble) { 264 HandleScope scope(thread_); 265 Float left(&scope, runtime_->newFloat(2.0)); 266 Float right(&scope, runtime_->newFloat(3.0)); 267 Object result(&scope, runBuiltin(METH(float, __rtruediv__), left, right)); 268 EXPECT_TRUE(isFloatEqualsDouble(*result, 1.5)); 269} 270 271TEST_F(FloatBuiltinsTest, DunderRtruedivWithSmallIntReturnsDouble) { 272 HandleScope scope(thread_); 273 Float left(&scope, runtime_->newFloat(2.0)); 274 Int right(&scope, runtime_->newInt(3)); 275 Object result(&scope, runBuiltin(METH(float, __rtruediv__), left, right)); 276 EXPECT_TRUE(isFloatEqualsDouble(*result, 1.5)); 277} 278 279TEST_F(FloatBuiltinsTest, DunderRtruedivWithNonFloatSelfRaisesTypeError) { 280 HandleScope scope(thread_); 281 Object left(&scope, NoneType::object()); 282 Float right(&scope, runtime_->newFloat(1.0)); 283 Object result(&scope, runBuiltin(METH(float, __rtruediv__), left, right)); 284 EXPECT_TRUE(raised(*result, LayoutId::kTypeError)); 285} 286 287TEST_F(FloatBuiltinsTest, 288 DunderRtruedivWithNonFloatOtherReturnsNotImplemented) { 289 HandleScope scope(thread_); 290 Float left(&scope, runtime_->newFloat(1.0)); 291 Object right(&scope, NoneType::object()); 292 Object result(&scope, runBuiltin(METH(float, __rtruediv__), left, right)); 293 EXPECT_TRUE(result.isNotImplementedType()); 294} 295 296TEST_F(FloatBuiltinsTest, DunderRtruedivWithZeroFloatRaisesZeroDivisionError) { 297 HandleScope scope(thread_); 298 Float left(&scope, runtime_->newFloat(0.0)); 299 Float right(&scope, runtime_->newFloat(1.0)); 300 Object result(&scope, runBuiltin(METH(float, __rtruediv__), left, right)); 301 EXPECT_TRUE(raised(*result, LayoutId::kZeroDivisionError)); 302} 303 304TEST_F(FloatBuiltinsTest, BinarySubtractDouble) { 305 HandleScope scope(thread_); 306 307 ASSERT_FALSE(runFromCStr(runtime_, R"( 308a = 2.0 309b = 1.5 310c = a - b 311)") 312 .isError()); 313 314 Object c(&scope, mainModuleAt(runtime_, "c")); 315 EXPECT_TRUE(isFloatEqualsDouble(*c, 0.5)); 316} 317 318TEST_F(FloatBuiltinsTest, BinarySubtractSmallInt) { 319 HandleScope scope(thread_); 320 321 ASSERT_FALSE(runFromCStr(runtime_, R"( 322a = 2.5 323b = 1 324c = a - b 325)") 326 .isError()); 327 328 Object c(&scope, mainModuleAt(runtime_, "c")); 329 EXPECT_TRUE(isFloatEqualsDouble(*c, 1.5)); 330} 331 332TEST_F(FloatBuiltinsTest, FloatSubclassKeepsFloatInMro) { 333 const char* src = R"( 334class Test(float): 335 pass 336)"; 337 HandleScope scope(thread_); 338 ASSERT_FALSE(runFromCStr(runtime_, src).isError()); 339 Object value(&scope, mainModuleAt(runtime_, "Test")); 340 ASSERT_TRUE(value.isType()); 341 342 Type type(&scope, *value); 343 ASSERT_TRUE(type.mro().isTuple()); 344 345 Tuple mro(&scope, type.mro()); 346 ASSERT_EQ(mro.length(), 3); 347 EXPECT_EQ(mro.at(0), *type); 348 EXPECT_EQ(mro.at(1), runtime_->typeAt(LayoutId::kFloat)); 349 EXPECT_EQ(mro.at(2), runtime_->typeAt(LayoutId::kObject)); 350} 351 352TEST_F(FloatBuiltinsTest, PowFloatAndFloat) { 353 ASSERT_FALSE(runFromCStr(runtime_, R"( 354base = 2.0 355x = base ** 4.0 356)") 357 .isError()); 358 EXPECT_TRUE(isFloatEqualsDouble(mainModuleAt(runtime_, "x"), 16.0)); 359} 360 361TEST_F(FloatBuiltinsTest, PowFloatAndInt) { 362 ASSERT_FALSE(runFromCStr(runtime_, R"( 363base = 2.0 364x = base ** 4 365)") 366 .isError()); 367 EXPECT_TRUE(isFloatEqualsDouble(mainModuleAt(runtime_, "x"), 16.0)); 368} 369 370TEST_F(FloatBuiltinsTest, InplacePowFloatAndFloat) { 371 ASSERT_FALSE(runFromCStr(runtime_, R"( 372x = 2.0 373x **= 4.0 374)") 375 .isError()); 376 EXPECT_TRUE(isFloatEqualsDouble(mainModuleAt(runtime_, "x"), 16.0)); 377} 378 379TEST_F(FloatBuiltinsTest, InplacePowFloatAndInt) { 380 ASSERT_FALSE(runFromCStr(runtime_, R"( 381x = 2.0 382x **= 4 383)") 384 .isError()); 385 EXPECT_TRUE(isFloatEqualsDouble(mainModuleAt(runtime_, "x"), 16.0)); 386} 387 388TEST_F(FloatBuiltinsTest, SubWithNonFloatOtherRaisesTypeError) { 389 const char* src = R"( 3901.0 - None 391)"; 392 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, src), LayoutId::kTypeError, 393 "float.__sub__(NoneType) is not supported")); 394} 395 396TEST_F(FloatBuiltinsTest, DunderEqWithFloatsReturnsBool) { 397 HandleScope scope(thread_); 398 Object nan(&scope, runtime_->newFloat(kDoubleNaN)); 399 Object f0(&scope, runtime_->newFloat(1.0)); 400 Object f1(&scope, runtime_->newFloat(-42.5)); 401 Object zero(&scope, runtime_->newFloat(0.0)); 402 Object neg_zero(&scope, runtime_->newFloat(-0.0)); 403 Object null(&scope, runtime_->newInt(0)); 404 EXPECT_EQ(runBuiltin(METH(float, __eq__), f0, f0), Bool::trueObj()); 405 EXPECT_EQ(runBuiltin(METH(float, __eq__), f0, f1), Bool::falseObj()); 406 EXPECT_EQ(runBuiltin(METH(float, __eq__), nan, nan), Bool::falseObj()); 407 EXPECT_EQ(runBuiltin(METH(float, __eq__), zero, neg_zero), Bool::trueObj()); 408 EXPECT_EQ(runBuiltin(METH(float, __eq__), neg_zero, null), Bool::trueObj()); 409} 410 411TEST_F(FloatBuiltinsTest, DunderEqWithIntSubclassReturnsBool) { 412 HandleScope scope(thread_); 413 ASSERT_FALSE(runFromCStr(runtime_, R"( 414class C(int): pass 415zero = C() 416one = C(1) 417two = C(2) 418)") 419 .isError()); 420 Object self(&scope, runtime_->newFloat(1.0)); 421 Object zero(&scope, mainModuleAt(runtime_, "zero")); 422 Object one(&scope, mainModuleAt(runtime_, "one")); 423 Object two(&scope, mainModuleAt(runtime_, "two")); 424 EXPECT_EQ(runBuiltin(METH(float, __eq__), self, zero), Bool::falseObj()); 425 EXPECT_EQ(runBuiltin(METH(float, __eq__), self, one), Bool::trueObj()); 426 EXPECT_EQ(runBuiltin(METH(float, __eq__), self, two), Bool::falseObj()); 427} 428 429TEST_F(FloatBuiltinsTest, DunderEqWithSmallIntExactReturnsBool) { 430 HandleScope scope(thread_); 431 Object float0(&scope, runtime_->newFloat(31.0)); 432 Object float1(&scope, runtime_->newFloat(31.125)); 433 Object int0(&scope, runtime_->newFloat(31)); 434 EXPECT_EQ(runBuiltin(METH(float, __eq__), float0, int0), Bool::trueObj()); 435 EXPECT_EQ(runBuiltin(METH(float, __eq__), float1, int0), Bool::falseObj()); 436 word mantissa_max = (word{1} << (kDoubleMantissaBits + 1)) - 1; 437 Object max_float(&scope, 438 runtime_->newFloat(static_cast<double>(mantissa_max))); 439 Object max_int(&scope, runtime_->newFloat(mantissa_max)); 440 EXPECT_EQ(runBuiltin(METH(float, __eq__), max_float, max_int), 441 Bool::trueObj()); 442 Object neg_max_float(&scope, 443 runtime_->newFloat(static_cast<double>(-mantissa_max))); 444 Object neg_max_int(&scope, runtime_->newInt(-mantissa_max)); 445 EXPECT_EQ(runBuiltin(METH(float, __eq__), neg_max_float, neg_max_int), 446 Bool::trueObj()); 447 448 word big0 = word(1) << (kDoubleMantissaBits + 2); 449 ASSERT_EQ(static_cast<double>(big0), static_cast<double>(big0) + 1.0); 450 Object big0_float(&scope, runtime_->newFloat(static_cast<double>(big0))); 451 Int big0_int(&scope, runtime_->newInt(big0)); 452 EXPECT_EQ(runBuiltin(METH(float, __eq__), big0_float, big0_int), 453 Bool::trueObj()); 454 455 word big1 = (word(1) << (kDoubleMantissaBits + 1)) | (word(1) << 11); 456 ASSERT_EQ(static_cast<double>(big1), static_cast<double>(big1) + 1.0); 457 Object big1_float(&scope, runtime_->newFloat(static_cast<double>(big1))); 458 Int big1_int(&scope, runtime_->newInt(big1)); 459 EXPECT_EQ(runBuiltin(METH(float, __eq__), big1_float, big1_int), 460 Bool::trueObj()); 461} 462 463TEST_F(FloatBuiltinsTest, DunderEqWithSmallIntInexactReturnsFalse) { 464 HandleScope scope(thread_); 465 word big = (word(1) << (kDoubleMantissaBits + 4)) + 3; 466 ASSERT_EQ(static_cast<double>(big), static_cast<double>(big) + 3.0); 467 Object big_float(&scope, runtime_->newFloat(static_cast<double>(big))); 468 Int big_int(&scope, runtime_->newInt(big)); 469 EXPECT_EQ(runBuiltin(METH(float, __eq__), big_float, big_int), 470 Bool::falseObj()); 471} 472 473TEST_F(FloatBuiltinsTest, DunderEqWithLargeIntExactReturnsTrue) { 474 HandleScope scope(thread_); 475 const uword digits[] = {0, 1}; 476 Object int0(&scope, runtime_->newLargeIntWithDigits(digits)); 477 Object float0(&scope, runtime_->newFloat(std::strtod("0x1p64", nullptr))); 478 EXPECT_EQ(runBuiltin(METH(float, __eq__), float0, int0), Bool::trueObj()); 479} 480 481TEST_F(FloatBuiltinsTest, DunderEqWithLargeIntInexactReturnsFalse) { 482 HandleScope scope(thread_); 483 const uword digits[] = {0x800, 1}; 484 Object int0(&scope, runtime_->newLargeIntWithDigits(digits)); 485 Object float0(&scope, runtime_->newFloat(std::strtod("0x1p64", nullptr))); 486 ASSERT_EQ(Float::cast(runBuiltin(METH(int, __float__), int0)).value(), 487 Float::cast(*float0).value()); 488 EXPECT_EQ(runBuiltin(METH(float, __eq__), float0, int0), Bool::falseObj()); 489} 490 491TEST_F(FloatBuiltinsTest, DunderEqWithNonFiniteFloatIntReturnsFalse) { 492 HandleScope scope(thread_); 493 Object nan(&scope, runtime_->newFloat(kDoubleNaN)); 494 Object inf(&scope, 495 runtime_->newFloat(std::numeric_limits<double>::infinity())); 496 Object int0(&scope, runtime_->newInt(7)); 497 uword digits[100] = {}; 498 digits[99] = 1; 499 Object int1(&scope, runtime_->newLargeIntWithDigits(digits)); 500 EXPECT_EQ(runBuiltin(METH(float, __eq__), nan, int0), Bool::falseObj()); 501 EXPECT_EQ(runBuiltin(METH(float, __eq__), inf, int0), Bool::falseObj()); 502 EXPECT_EQ(runBuiltin(METH(float, __eq__), nan, int1), Bool::falseObj()); 503 EXPECT_EQ(runBuiltin(METH(float, __eq__), inf, int1), Bool::falseObj()); 504} 505 506TEST_F(FloatBuiltinsTest, DunderEqWithFloatOverflowingIntReturnsFalse) { 507 HandleScope scope(thread_); 508 Object float0(&scope, runtime_->newFloat(8.25)); 509 uword digits[100] = {}; 510 digits[99] = 1; 511 Object int0(&scope, runtime_->newLargeIntWithDigits(digits)); 512 EXPECT_EQ(runBuiltin(METH(float, __eq__), float0, int0), Bool::falseObj()); 513} 514 515TEST_F(FloatBuiltinsTest, DunderFloatWithFloatLiteralReturnsSameObject) { 516 HandleScope scope(thread_); 517 518 ASSERT_FALSE(runFromCStr(runtime_, "a = (7.0).__float__()").isError()); 519 Object a(&scope, mainModuleAt(runtime_, "a")); 520 EXPECT_TRUE(isFloatEqualsDouble(*a, 7.0)); 521} 522 523TEST_F(FloatBuiltinsTest, DunderFloatFromFloatClassReturnsSameValue) { 524 HandleScope scope(thread_); 525 526 Float a_float(&scope, runtime_->newFloat(7.0)); 527 Object a(&scope, runBuiltin(METH(float, __float__), a_float)); 528 EXPECT_TRUE(isFloatEqualsDouble(*a, 7.0)); 529} 530 531TEST_F(FloatBuiltinsTest, DunderFloatWithFloatSubclassReturnsSameValue) { 532 HandleScope scope(thread_); 533 534 ASSERT_FALSE(runFromCStr(runtime_, R"( 535class FloatSub(float): 536 pass 537a = FloatSub(1.0).__float__())") 538 .isError()); 539 Object a(&scope, mainModuleAt(runtime_, "a")); 540 EXPECT_TRUE(isFloatEqualsDouble(*a, 1.0)); 541} 542 543TEST_F(FloatBuiltinsTest, DunderFloatWithNonFloatReturnsError) { 544 HandleScope scope(thread_); 545 546 Int i(&scope, runtime_->newInt(1)); 547 Object i_res(&scope, runBuiltin(METH(float, __float__), i)); 548 EXPECT_TRUE(raised(*i_res, LayoutId::kTypeError)); 549} 550 551TEST_F(FloatBuiltinsTest, DunderGeWithFloatReturnsBool) { 552 HandleScope scope(thread_); 553 Object float0(&scope, runtime_->newFloat(1.7)); 554 Object float1(&scope, runtime_->newFloat(0.2)); 555 EXPECT_EQ(runBuiltin(METH(float, __ge__), float0, float1), Bool::trueObj()); 556 EXPECT_EQ(runBuiltin(METH(float, __ge__), float0, float0), Bool::trueObj()); 557 EXPECT_EQ(runBuiltin(METH(float, __ge__), float1, float0), Bool::falseObj()); 558} 559 560TEST_F(FloatBuiltinsTest, DunderGeWithIntSelfNanReturnsFalse) { 561 HandleScope scope(thread_); 562 Object left(&scope, runtime_->newFloat(kDoubleNaN)); 563 const uword digits[] = {0, 1}; 564 Object right(&scope, runtime_->newLargeIntWithDigits(digits)); 565 EXPECT_EQ(runBuiltin(METH(float, __ge__), left, right), Bool::falseObj()); 566} 567 568TEST_F(FloatBuiltinsTest, DunderGeWithNonFloatReturnsNotImplemented) { 569 HandleScope scope(thread_); 570 Object left(&scope, runtime_->newFloat(0.0)); 571 Object right(&scope, Str::empty()); 572 EXPECT_TRUE( 573 runBuiltin(METH(float, __ge__), left, right).isNotImplementedType()); 574} 575 576TEST_F(FloatBuiltinsTest, DunderGeWithSmallIntReturnsBool) { 577 HandleScope scope(thread_); 578 Object float0(&scope, runtime_->newFloat(5.0)); 579 Object int0(&scope, runtime_->newInt(4)); 580 Object int1(&scope, runtime_->newInt(5)); 581 Object int2(&scope, runtime_->newInt(6)); 582 EXPECT_EQ(runBuiltin(METH(float, __ge__), float0, int0), Bool::trueObj()); 583 EXPECT_EQ(runBuiltin(METH(float, __ge__), float0, int1), Bool::trueObj()); 584 EXPECT_EQ(runBuiltin(METH(float, __ge__), float0, int2), Bool::falseObj()); 585} 586 587TEST_F(FloatBuiltinsTest, DunderGeWithSmallIntExactReturnsBool) { 588 HandleScope scope(thread_); 589 Object float0(&scope, runtime_->newFloat(44.)); 590 Object int0(&scope, runtime_->newInt(44)); 591 EXPECT_EQ(runBuiltin(METH(float, __ge__), float0, int0), Bool::trueObj()); 592 Object float1(&scope, runtime_->newFloat(-3.)); 593 Object int1(&scope, runtime_->newInt(1)); 594 EXPECT_EQ(runBuiltin(METH(float, __ge__), float1, int1), Bool::falseObj()); 595 596 Object float2(&scope, runtime_->newFloat(0x20000000000000)); 597 Object int2(&scope, runtime_->newInt(0x20000000000000)); 598 EXPECT_EQ(runBuiltin(METH(float, __ge__), float2, int2), Bool::trueObj()); 599} 600 601TEST_F(FloatBuiltinsTest, DunderGeWithSmallIntInexactReturnsBool) { 602 HandleScope scope(thread_); 603 Object float0(&scope, 604 runtime_->newFloat(static_cast<double>(0x20000000000001))); 605 Object int0(&scope, runtime_->newInt(0x20000000000001)); 606 EXPECT_EQ(runBuiltin(METH(float, __ge__), float0, int0), Bool::falseObj()); 607 Object float1(&scope, 608 runtime_->newFloat(static_cast<double>(0x20000000000003))); 609 Object int1(&scope, runtime_->newInt(0x20000000000003)); 610 EXPECT_EQ(runBuiltin(METH(float, __ge__), float1, int1), Bool::trueObj()); 611 Object float2(&scope, 612 runtime_->newFloat(static_cast<double>(0x100000000000011))); 613 Object int2(&scope, runtime_->newInt(0x100000000000011)); 614 EXPECT_EQ(runBuiltin(METH(float, __ge__), float2, int2), Bool::falseObj()); 615} 616 617TEST_F(FloatBuiltinsTest, DunderGeWithLargeIntDifferingSignReturnsBool) { 618 HandleScope scope(thread_); 619 Object float0(&scope, runtime_->newFloat(-1.0)); 620 const uword digits0[] = {0, 1}; 621 Object int0(&scope, runtime_->newLargeIntWithDigits(digits0)); 622 EXPECT_EQ(runBuiltin(METH(float, __ge__), float0, int0), Bool::falseObj()); 623 Object float1(&scope, runtime_->newFloat(1.0)); 624 const uword digits1[] = {0, kMaxUword}; 625 Object int1(&scope, runtime_->newLargeIntWithDigits(digits1)); 626 EXPECT_EQ(runBuiltin(METH(float, __ge__), float1, int1), Bool::trueObj()); 627} 628 629TEST_F(FloatBuiltinsTest, DunderGeWithLargeIntExactEqualsReturnsTrue) { 630 HandleScope scope(thread_); 631 Object float0(&scope, runtime_->newFloat(std::strtod("0x1p64", nullptr))); 632 const uword digits[] = {0, 1}; 633 Object int0(&scope, runtime_->newLargeIntWithDigits(digits)); 634 EXPECT_EQ(runBuiltin(METH(float, __ge__), float0, int0), Bool::trueObj()); 635} 636 637TEST_F(FloatBuiltinsTest, DunderGeWithLargeIntRoundingDownReturnsFalse) { 638 HandleScope scope(thread_); 639 Object float0(&scope, runtime_->newFloat(std::strtod("0x1p64", nullptr))); 640 const uword digits[] = {1, 1}; 641 Object int0(&scope, runtime_->newLargeIntWithDigits(digits)); 642 ASSERT_EQ(Float::cast(runBuiltin(METH(int, __float__), int0)).value(), 643 Float::cast(*float0).value()); 644 EXPECT_EQ(runBuiltin(METH(float, __ge__), float0, int0), Bool::falseObj()); 645} 646 647TEST_F(FloatBuiltinsTest, DunderGeWithLargeIntRoundingUpReturnsTrue) { 648 HandleScope scope(thread_); 649 Object float0(&scope, runtime_->newFloat(std::strtod("0x1p64", nullptr))); 650 const uword digits[] = {kMaxUword, 0}; 651 Object int0(&scope, runtime_->newLargeIntWithDigits(digits)); 652 ASSERT_EQ(Float::cast(runBuiltin(METH(int, __float__), int0)).value(), 653 Float::cast(*float0).value()); 654 EXPECT_EQ(runBuiltin(METH(float, __ge__), float0, int0), Bool::trueObj()); 655} 656 657TEST_F(FloatBuiltinsTest, DunderGeWithIntSubclassReturnsBool) { 658 HandleScope scope(thread_); 659 ASSERT_FALSE(runFromCStr(runtime_, R"( 660class C(int): pass 661zero = C() 662one = C(1) 663two = C(2) 664)") 665 .isError()); 666 Object self(&scope, runtime_->newFloat(1.0)); 667 Object zero(&scope, mainModuleAt(runtime_, "zero")); 668 Object one(&scope, mainModuleAt(runtime_, "one")); 669 Object two(&scope, mainModuleAt(runtime_, "two")); 670 EXPECT_EQ(runBuiltin(METH(float, __ge__), self, zero), Bool::trueObj()); 671 EXPECT_EQ(runBuiltin(METH(float, __ge__), self, one), Bool::trueObj()); 672 EXPECT_EQ(runBuiltin(METH(float, __ge__), self, two), Bool::falseObj()); 673} 674 675TEST_F(FloatBuiltinsTest, DunderGtWithFloatReturnsBool) { 676 HandleScope scope(thread_); 677 Object float0(&scope, runtime_->newFloat(8.3)); 678 Object float1(&scope, runtime_->newFloat(1.7)); 679 EXPECT_EQ(runBuiltin(METH(float, __gt__), float0, float1), Bool::trueObj()); 680 EXPECT_EQ(runBuiltin(METH(float, __gt__), float0, float0), Bool::falseObj()); 681 EXPECT_EQ(runBuiltin(METH(float, __gt__), float1, float0), Bool::falseObj()); 682} 683 684TEST_F(FloatBuiltinsTest, DunderGtWithIntSelfNanReturnsFalse) { 685 HandleScope scope(thread_); 686 Object left(&scope, runtime_->newFloat(kDoubleNaN)); 687 const uword digits[] = {0, 1}; 688 Object right(&scope, runtime_->newLargeIntWithDigits(digits)); 689 EXPECT_EQ(runBuiltin(METH(float, __gt__), left, right), Bool::falseObj()); 690} 691 692TEST_F(FloatBuiltinsTest, DunderGtWithNonFloatReturnsNotImplemented) { 693 HandleScope scope(thread_); 694 Object left(&scope, runtime_->newFloat(0.0)); 695 Object right(&scope, Str::empty()); 696 EXPECT_TRUE( 697 runBuiltin(METH(float, __gt__), left, right).isNotImplementedType()); 698} 699 700TEST_F(FloatBuiltinsTest, DunderGtWithSmallIntReturnsBool) { 701 HandleScope scope(thread_); 702 Object float0(&scope, runtime_->newFloat(5.0)); 703 Object int0(&scope, runtime_->newInt(4)); 704 Object int1(&scope, runtime_->newInt(5)); 705 EXPECT_EQ(runBuiltin(METH(float, __gt__), float0, int0), Bool::trueObj()); 706 EXPECT_EQ(runBuiltin(METH(float, __gt__), float0, int1), Bool::falseObj()); 707} 708 709TEST_F(FloatBuiltinsTest, DunderGtWithIntSubclassReturnsBool) { 710 HandleScope scope(thread_); 711 ASSERT_FALSE(runFromCStr(runtime_, R"( 712class C(int): pass 713zero = C() 714one = C(1) 715two = C(2) 716)") 717 .isError()); 718 Object self(&scope, runtime_->newFloat(1.0)); 719 Object zero(&scope, mainModuleAt(runtime_, "zero")); 720 Object one(&scope, mainModuleAt(runtime_, "one")); 721 Object two(&scope, mainModuleAt(runtime_, "two")); 722 EXPECT_EQ(runBuiltin(METH(float, __gt__), self, zero), Bool::trueObj()); 723 EXPECT_EQ(runBuiltin(METH(float, __gt__), self, one), Bool::falseObj()); 724 EXPECT_EQ(runBuiltin(METH(float, __gt__), self, two), Bool::falseObj()); 725} 726 727TEST_F(FloatBuiltinsTest, DunderIntWithInfinityRaisesOverflowError) { 728 HandleScope scope(thread_); 729 Object input_obj(&scope, 730 runtime_->newFloat(std::numeric_limits<double>::infinity())); 731 Object result_obj(&scope, runBuiltin(METH(float, __int__), input_obj)); 732 EXPECT_TRUE(raisedWithStr(*result_obj, LayoutId::kOverflowError, 733 "cannot convert float infinity to integer")); 734} 735 736TEST_F(FloatBuiltinsTest, DunderIntWithNaNRaisesOverflowError) { 737 HandleScope scope(thread_); 738 Object input_obj(&scope, runtime_->newFloat(kDoubleNaN)); 739 Object result_obj(&scope, runBuiltin(METH(float, __int__), input_obj)); 740 EXPECT_TRUE(raisedWithStr(*result_obj, LayoutId::kValueError, 741 "cannot convert float NaN to integer")); 742} 743 744TEST_F(FloatBuiltinsTest, DunderIntWithZeroReturnsSmallInt) { 745 HandleScope scope(thread_); 746 Object input_obj(&scope, runtime_->newFloat(0.0)); 747 Object result_obj(&scope, runBuiltin(METH(float, __int__), input_obj)); 748 ASSERT_TRUE(result_obj.isSmallInt()); 749 SmallInt result(&scope, *result_obj); 750 EXPECT_EQ(result.value(), 0); 751} 752 753TEST_F( 754 FloatBuiltinsTest, 755 DunderIntWithNegativeNumOfGreatestMagnitudeFitInWordReturnsLargeIntOfSingleWord) { 756 HandleScope scope(thread_); 757 double input_value = std::strtod("-0x1.0000000000000p+63", nullptr); 758 Object input_obj(&scope, runtime_->newFloat(input_value)); 759 Object result_obj(&scope, runBuiltin(METH(float, __int__), input_obj)); 760 ASSERT_TRUE(result_obj.isLargeInt()); 761 LargeInt result(&scope, *result_obj); 762 EXPECT_TRUE(result.isNegative()); 763 const uword expected_digits[] = {uword{0x8000000000000000}}; 764 EXPECT_TRUE(isIntEqualsDigits(*result, expected_digits)); 765} 766 767TEST_F(FloatBuiltinsTest, DunderIntWithSmallIntMinValueReturnsSmallInt) { 768 HandleScope scope(thread_); 769 double input_value = double{SmallInt::kMinValue}; 770 // Make sure that the converted double value can fit in SmallInt if 771 // it gets converted back to word. 772 EXPECT_EQ(static_cast<word>(input_value), SmallInt::kMinValue); 773 Object input_obj(&scope, runtime_->newFloat(input_value)); 774 Object result_obj(&scope, runBuiltin(METH(float, __int__), input_obj)); 775 EXPECT_TRUE(result_obj.isSmallInt()); 776 SmallInt result(&scope, *result_obj); 777 EXPECT_EQ(result.value(), static_cast<word>(input_value)); 778} 779 780TEST_F(FloatBuiltinsTest, 781 DunderIntWithValueLessThanSmallIntMinValueReturnsLargeInt) { 782 HandleScope scope(thread_); 783 // Due to the truncation error, static_cast<double>(SmallInt::kMinValue - i) 784 // == SmallInt::kMinValue for i ranging from 0 to 512. 785 ASSERT_EQ(static_cast<word>(static_cast<double>(SmallInt::kMinValue - 512)), 786 SmallInt::kMinValue); 787 ASSERT_LT(static_cast<word>(static_cast<double>(SmallInt::kMinValue - 513)), 788 SmallInt::kMinValue - 1); 789 double input_value = static_cast<double>(SmallInt::kMinValue) - 513; 790 Object input_obj(&scope, runtime_->newFloat(input_value)); 791 Object result_obj(&scope, runBuiltin(METH(float, __int__), input_obj)); 792 EXPECT_TRUE(result_obj.isLargeInt()); 793} 794 795TEST_F(FloatBuiltinsTest, DunderIntWithSmallIntMaxValueReturnsSmallInt) { 796 HandleScope scope(thread_); 797 // Due to the truncation error, static_cast<double>(SmallInt::kMaxValue) -i) 798 // == SmallInt::kMaxValue + 1 for i ranging from 0 to 255, which makes them 799 // not fit in SmallInt. 800 ASSERT_EQ(static_cast<word>(static_cast<double>(SmallInt::kMaxValue - 255)), 801 SmallInt::kMaxValue + 1); 802 double input_value = static_cast<double>(SmallInt::kMaxValue - 256); 803 Object input_obj(&scope, runtime_->newFloat(input_value)); 804 Object result_obj(&scope, runBuiltin(METH(float, __int__), input_obj)); 805 EXPECT_TRUE(result_obj.isSmallInt()); 806 SmallInt result(&scope, *result_obj); 807 EXPECT_EQ(result.value(), static_cast<word>(input_value)); 808} 809 810TEST_F(FloatBuiltinsTest, 811 DunderIntWithValueGreaterThanSmallIntMaxValueReturnsLargeInt) { 812 HandleScope scope(thread_); 813 // Due to the truncation error, converting MaxValue to double strictly 814 // increases the value. 815 ASSERT_GT(static_cast<word>(static_cast<double>(SmallInt::kMaxValue)), 816 SmallInt::kMaxValue); 817 // Therefore, this is the smallest double greater than kMaxValue. 818 double input_value = static_cast<double>(SmallInt::kMaxValue); 819 Object input_obj(&scope, runtime_->newFloat(input_value)); 820 Object result_obj(&scope, runBuiltin(METH(float, __int__), input_obj)); 821 EXPECT_TRUE(result_obj.isLargeInt()); 822} 823 824TEST_F(FloatBuiltinsTest, DunderIntWithLargePositiveDoubleReturnsLargeInt) { 825 HandleScope scope(thread_); 826 double input_value = std::strtod("0x1.29ef685b3f6fbp+84", nullptr); 827 Object input_obj(&scope, runtime_->newFloat(input_value)); 828 Object result_obj(&scope, runBuiltin(METH(float, __int__), input_obj)); 829 ASSERT_TRUE(result_obj.isLargeInt()); 830 LargeInt result(&scope, *result_obj); 831 EXPECT_TRUE(result.isPositive()); 832 const uword expected_digits[] = {0x85b3f6fb00000000, 0x129ef6}; 833 EXPECT_TRUE(isIntEqualsDigits(*result, expected_digits)); 834} 835 836TEST_F(FloatBuiltinsTest, DunderIntWithLargeNegativeDoubleReturnsLargeInt) { 837 HandleScope scope(thread_); 838 double input_value = std::strtod("-0x1.29ef685b3f6fbp+84", nullptr); 839 Object input_obj(&scope, runtime_->newFloat(input_value)); 840 Object result_obj(&scope, runBuiltin(METH(float, __int__), input_obj)); 841 ASSERT_TRUE(result_obj.isLargeInt()); 842 LargeInt result(&scope, *result_obj); 843 EXPECT_TRUE(result.isNegative()); 844 // Represented as a two's complement, so 1 is added only to the lowest digit 845 // as long as it doesn't creat a carry. 846 const uword expected_digits[] = {~uword{0x85b3f6fb00000000} + 1, 847 ~uword{0x129ef6}}; 848 EXPECT_TRUE(isIntEqualsDigits(*result, expected_digits)); 849} 850 851TEST_F(FloatBuiltinsTest, DunderLeWithFloatReturnsBool) { 852 HandleScope scope(thread_); 853 Object float0(&scope, runtime_->newFloat(13.1)); 854 Object float1(&scope, runtime_->newFloat(9.4)); 855 EXPECT_EQ(runBuiltin(METH(float, __le__), float0, float1), Bool::falseObj()); 856 EXPECT_EQ(runBuiltin(METH(float, __le__), float0, float0), Bool::trueObj()); 857 EXPECT_EQ(runBuiltin(METH(float, __le__), float1, float0), Bool::trueObj()); 858} 859 860TEST_F(FloatBuiltinsTest, DunderLeWithIntSelfNanReturnsFalse) { 861 HandleScope scope(thread_); 862 Object left(&scope, runtime_->newFloat(kDoubleNaN)); 863 const uword digits[] = {0, 1}; 864 Object right(&scope, runtime_->newLargeIntWithDigits(digits)); 865 EXPECT_EQ(runBuiltin(METH(float, __le__), left, right), Bool::falseObj()); 866} 867 868TEST_F(FloatBuiltinsTest, DunderLeWithNonFloatReturnsNotImplemented) { 869 HandleScope scope(thread_); 870 Object left(&scope, runtime_->newFloat(0.0)); 871 Object right(&scope, Str::empty()); 872 EXPECT_TRUE( 873 runBuiltin(METH(float, __le__), left, right).isNotImplementedType()); 874} 875 876TEST_F(FloatBuiltinsTest, DunderLeWithSmallIntReturnsBool) { 877 HandleScope scope(thread_); 878 Object float0(&scope, runtime_->newFloat(4.0)); 879 Object int0(&scope, runtime_->newInt(4)); 880 Object int1(&scope, runtime_->newInt(3)); 881 EXPECT_EQ(runBuiltin(METH(float, __le__), float0, int0), Bool::trueObj()); 882 EXPECT_EQ(runBuiltin(METH(float, __le__), float0, int1), Bool::falseObj()); 883} 884 885TEST_F(FloatBuiltinsTest, DunderLeWithBoolReturnsBool) { 886 HandleScope scope(thread_); 887 Object float0(&scope, runtime_->newFloat(1.0)); 888 Object b_false(&scope, Bool::falseObj()); 889 Object b_true(&scope, Bool::trueObj()); 890 EXPECT_EQ(runBuiltin(METH(float, __le__), float0, b_false), Bool::falseObj()); 891 EXPECT_EQ(runBuiltin(METH(float, __le__), float0, b_true), Bool::trueObj()); 892} 893 894TEST_F(FloatBuiltinsTest, DunderLeWithIntSubclassReturnsBool) { 895 HandleScope scope(thread_); 896 ASSERT_FALSE(runFromCStr(runtime_, R"( 897class C(int): pass 898zero = C() 899one = C(1) 900two = C(2) 901)") 902 .isError()); 903 Object self(&scope, runtime_->newFloat(1.0)); 904 Object zero(&scope, mainModuleAt(runtime_, "zero")); 905 Object one(&scope, mainModuleAt(runtime_, "one")); 906 Object two(&scope, mainModuleAt(runtime_, "two")); 907 EXPECT_EQ(runBuiltin(METH(float, __le__), self, zero), Bool::falseObj()); 908 EXPECT_EQ(runBuiltin(METH(float, __le__), self, one), Bool::trueObj()); 909 EXPECT_EQ(runBuiltin(METH(float, __le__), self, two), Bool::trueObj()); 910} 911 912TEST_F(FloatBuiltinsTest, DunderLtWithFloatReturnsBool) { 913 HandleScope scope(thread_); 914 Object float0(&scope, runtime_->newFloat(-7.3)); 915 Object float1(&scope, runtime_->newFloat(1.25)); 916 EXPECT_EQ(runBuiltin(METH(float, __lt__), float0, float1), Bool::trueObj()); 917 EXPECT_EQ(runBuiltin(METH(float, __lt__), float0, float0), Bool::falseObj()); 918 EXPECT_EQ(runBuiltin(METH(float, __lt__), float1, float0), Bool::falseObj()); 919} 920 921TEST_F(FloatBuiltinsTest, DunderLtWithIntSelfNanReturnsFalse) { 922 HandleScope scope(thread_); 923 Object left(&scope, runtime_->newFloat(kDoubleNaN)); 924 const uword digits[] = {0, 1}; 925 Object right(&scope, runtime_->newLargeIntWithDigits(digits)); 926 EXPECT_EQ(runBuiltin(METH(float, __lt__), left, right), Bool::falseObj()); 927} 928 929TEST_F(FloatBuiltinsTest, DunderLtWithNonFloatReturnsNotImplemented) { 930 HandleScope scope(thread_); 931 Object left(&scope, runtime_->newFloat(0.0)); 932 Object right(&scope, Str::empty()); 933 EXPECT_TRUE( 934 runBuiltin(METH(float, __lt__), left, right).isNotImplementedType()); 935} 936 937TEST_F(FloatBuiltinsTest, DunderLtWithSmallIntReturnsBool) { 938 HandleScope scope(thread_); 939 Object float0(&scope, runtime_->newFloat(4.5)); 940 Object int0(&scope, runtime_->newInt(4)); 941 Object int1(&scope, runtime_->newInt(5)); 942 EXPECT_EQ(runBuiltin(METH(float, __lt__), float0, int0), Bool::falseObj()); 943 EXPECT_EQ(runBuiltin(METH(float, __lt__), float0, int1), Bool::trueObj()); 944} 945 946TEST_F(FloatBuiltinsTest, DunderLtWithSmallIntExactReturnsBool) { 947 HandleScope scope(thread_); 948 Object float0(&scope, runtime_->newFloat(44.)); 949 Object int0(&scope, runtime_->newInt(44)); 950 EXPECT_EQ(runBuiltin(METH(float, __lt__), float0, int0), Bool::falseObj()); 951 Object float1(&scope, runtime_->newFloat(-3.)); 952 Object int1(&scope, runtime_->newInt(1)); 953 EXPECT_EQ(runBuiltin(METH(float, __lt__), float1, int1), Bool::trueObj()); 954 955 Object float2(&scope, runtime_->newFloat(0x20000000000000)); 956 Object int2(&scope, runtime_->newInt(0x20000000000000)); 957 EXPECT_EQ(runBuiltin(METH(float, __lt__), float2, int2), Bool::falseObj()); 958} 959 960TEST_F(FloatBuiltinsTest, DunderLtWithSmallIntInexactReturnsBool) { 961 HandleScope scope(thread_); 962 Object float0(&scope, 963 runtime_->newFloat(static_cast<double>(0x20000000000001))); 964 Object int0(&scope, runtime_->newInt(0x20000000000001)); 965 EXPECT_EQ(runBuiltin(METH(float, __lt__), float0, int0), Bool::trueObj()); 966 Object float1(&scope, 967 runtime_->newFloat(static_cast<double>(0x20000000000003))); 968 Object int1(&scope, runtime_->newInt(0x20000000000003)); 969 EXPECT_EQ(runBuiltin(METH(float, __lt__), float1, int1), Bool::falseObj()); 970 Object float2(&scope, 971 runtime_->newFloat(static_cast<double>(0x100000000000011))); 972 Object int2(&scope, runtime_->newInt(0x100000000000011)); 973 EXPECT_EQ(runBuiltin(METH(float, __lt__), float2, int2), Bool::trueObj()); 974} 975 976TEST_F(FloatBuiltinsTest, DunderLtWithLargeIntDifferingSignReturnsBool) { 977 HandleScope scope(thread_); 978 Object float0(&scope, runtime_->newFloat(-1.0)); 979 const uword digits0[] = {0, 1}; 980 Object int0(&scope, runtime_->newLargeIntWithDigits(digits0)); 981 EXPECT_EQ(runBuiltin(METH(float, __lt__), float0, int0), Bool::trueObj()); 982 Object float1(&scope, runtime_->newFloat(1.0)); 983 const uword digits1[] = {0, kMaxUword}; 984 Object int1(&scope, runtime_->newLargeIntWithDigits(digits1)); 985 EXPECT_EQ(runBuiltin(METH(float, __lt__), float1, int1), Bool::falseObj()); 986} 987 988TEST_F(FloatBuiltinsTest, DunderLtWithLargeIntExactEqualsReturnsFalse) { 989 HandleScope scope(thread_); 990 Object float0(&scope, runtime_->newFloat(std::strtod("0x1p64", nullptr))); 991 const uword digits[] = {0, 1}; 992 Object int0(&scope, runtime_->newLargeIntWithDigits(digits)); 993 EXPECT_EQ(runBuiltin(METH(float, __lt__), float0, int0), Bool::falseObj()); 994} 995 996TEST_F(FloatBuiltinsTest, DunderLtWithLargeIntRoundingDownReturnsTrue) { 997 HandleScope scope(thread_); 998 Object float0(&scope, runtime_->newFloat(std::strtod("0x1p64", nullptr))); 999 const uword digits[] = {1, 1}; 1000 Object int0(&scope, runtime_->newLargeIntWithDigits(digits)); 1001 ASSERT_EQ(Float::cast(runBuiltin(METH(int, __float__), int0)).value(), 1002 Float::cast(*float0).value()); 1003 EXPECT_EQ(runBuiltin(METH(float, __lt__), float0, int0), Bool::trueObj()); 1004} 1005 1006TEST_F(FloatBuiltinsTest, DunderLtWithLargeIntRoundingUpReturnsFalse) { 1007 HandleScope scope(thread_); 1008 Object float0(&scope, runtime_->newFloat(std::strtod("0x1p64", nullptr))); 1009 const uword digits[] = {kMaxUword, 0}; 1010 Object int0(&scope, runtime_->newLargeIntWithDigits(digits)); 1011 ASSERT_EQ(Float::cast(runBuiltin(METH(int, __float__), int0)).value(), 1012 Float::cast(*float0).value()); 1013 EXPECT_EQ(runBuiltin(METH(float, __lt__), float0, int0), Bool::falseObj()); 1014} 1015 1016TEST_F(FloatBuiltinsTest, DunderLtWithIntSubclassReturnsBool) { 1017 HandleScope scope(thread_); 1018 ASSERT_FALSE(runFromCStr(runtime_, R"( 1019class C(int): pass 1020zero = C() 1021one = C(1) 1022two = C(2) 1023)") 1024 .isError()); 1025 Object self(&scope, runtime_->newFloat(1.0)); 1026 Object zero(&scope, mainModuleAt(runtime_, "zero")); 1027 Object one(&scope, mainModuleAt(runtime_, "one")); 1028 Object two(&scope, mainModuleAt(runtime_, "two")); 1029 EXPECT_EQ(runBuiltin(METH(float, __lt__), self, zero), Bool::falseObj()); 1030 EXPECT_EQ(runBuiltin(METH(float, __lt__), self, one), Bool::falseObj()); 1031 EXPECT_EQ(runBuiltin(METH(float, __lt__), self, two), Bool::trueObj()); 1032} 1033 1034} // namespace testing 1035} // namespace py