diff --git a/ets2panda/checker/ETSAnalyzer.cpp b/ets2panda/checker/ETSAnalyzer.cpp index bf673fc5f44375a1eabf622c5891fb09a525df53..356ba7369495fb8043a4933f2b4a384eae6e6eeb 100644 --- a/ets2panda/checker/ETSAnalyzer.cpp +++ b/ets2panda/checker/ETSAnalyzer.cpp @@ -1515,17 +1515,17 @@ checker::Type *ETSAnalyzer::Check(ir::UnaryExpression *expr) const break; } case lexer::TokenType::PUNCTUATOR_TILDE: { - if (operand_type == nullptr || !operand_type->HasTypeFlag(checker::TypeFlag::ETS_INTEGRAL)) { - checker->ThrowTypeError("Bad operand type, the type of the operand must be integral type.", + if (operand_type == nullptr || !operand_type->HasTypeFlag(checker::TypeFlag::ETS_NUMERIC)) { + checker->ThrowTypeError("Bad operand type, the type of the operand must be numeric type.", expr->Argument()->Start()); } if (operand_type->HasTypeFlag(checker::TypeFlag::CONSTANT)) { - expr->SetTsType(checker->BitwiseNegateIntegralType(operand_type, expr)); + expr->SetTsType(checker->BitwiseNegateNumericType(operand_type, expr)); break; } - expr->SetTsType(operand_type); + expr->SetTsType(checker->SelectGlobalIntegerTypeForNumeric(operand_type)); break; } case lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK: { diff --git a/ets2panda/checker/ETSchecker.cpp b/ets2panda/checker/ETSchecker.cpp index 4144da1ef35b883dced383245d7f619cea334c73..72a71f62d00afc31b7aedeadbacba2345813a3cf 100644 --- a/ets2panda/checker/ETSchecker.cpp +++ b/ets2panda/checker/ETSchecker.cpp @@ -334,4 +334,19 @@ void ETSChecker::HandleUpdatedCallExpressionNode(ir::CallExpression *call_expr) VarBinder()->AsETSBinder()->HandleCustomNodes(call_expr); } +Type *ETSChecker::SelectGlobalIntegerTypeForNumeric(Type *type) +{ + switch (ETSType(type)) { + case checker::TypeFlag::FLOAT: { + return GlobalIntType(); + } + case checker::TypeFlag::DOUBLE: { + return GlobalLongType(); + } + default: { + return type; + } + } +} + } // namespace panda::es2panda::checker diff --git a/ets2panda/checker/ETSchecker.h b/ets2panda/checker/ETSchecker.h index 9ed89b1c81af72a456d66b9069bef2c019f8e6d9..9a9835ca6ac823434b46d81542445cd1c0fae1f3 100644 --- a/ets2panda/checker/ETSchecker.h +++ b/ets2panda/checker/ETSchecker.h @@ -30,6 +30,7 @@ #include "ir/ts/tsTypeParameterInstantiation.h" #include "util/enumbitops.h" #include "util/ustring.h" +#include "utils/bit_utils.h" #include "checker/resolveResult.h" #include "macros.h" @@ -38,6 +39,7 @@ #include #include #include +#include namespace panda::es2panda::varbinder { class VarBinder; @@ -208,7 +210,7 @@ public: // Arithmetic Type *NegateNumericType(Type *type, ir::Expression *node); - Type *BitwiseNegateIntegralType(Type *type, ir::Expression *node); + Type *BitwiseNegateNumericType(Type *type, ir::Expression *node); std::tuple CheckBinaryOperator(ir::Expression *left, ir::Expression *right, ir::Expression *expr, lexer::TokenType operation_type, lexer::SourcePosition pos, bool force_promotion = false); @@ -248,6 +250,7 @@ public: checker::Type *CheckBinaryOperatorNullishCoalescing(ir::Expression *right, lexer::SourcePosition pos, checker::Type *left_type, checker::Type *right_type); Type *HandleArithmeticOperationOnTypes(Type *left, Type *right, lexer::TokenType operation_type); + Type *HandleBitwiseOperationOnTypes(Type *left, Type *right, lexer::TokenType operation_type); void FlagExpressionWithUnboxing(Type *type, Type *unboxed_type, ir::Expression *type_expression); template Type *PerformArithmeticOperationOnTypes(Type *left, Type *right, lexer::TokenType operation_type); @@ -503,6 +506,7 @@ public: bool ExtensionETSFunctionType(checker::Type *type); void ValidateTupleMinElementSize(ir::ArrayExpression *array_expr, ETSTupleType *tuple); void ModifyPreferredType(ir::ArrayExpression *array_expr, Type *new_preferred_type); + Type *SelectGlobalIntegerTypeForNumeric(Type *type); // Exception ETSObjectType *CheckExceptionOrErrorType(checker::Type *type, lexer::SourcePosition pos); @@ -629,8 +633,8 @@ private: template UType HandleModulo(UType left_value, UType right_value); - template - UType HandleBitWiseArithmetic(UType left_value, UType right_value, lexer::TokenType operation_type); + template + Type *HandleBitWiseArithmetic(Type *left_value, Type *right_value, lexer::TokenType operation_type); template typename TargetType::UType GetOperand(Type *type); diff --git a/ets2panda/checker/ets/arithmetic.cpp b/ets2panda/checker/ets/arithmetic.cpp index 113250d258901f0a1346bad7a331f83ec031e798..ad1ee8579bc2d5cab30cee9d89d436bc9404229d 100644 --- a/ets2panda/checker/ets/arithmetic.cpp +++ b/ets2panda/checker/ets/arithmetic.cpp @@ -68,7 +68,7 @@ Type *ETSChecker::NegateNumericType(Type *type, ir::Expression *node) return result; } -Type *ETSChecker::BitwiseNegateIntegralType(Type *type, ir::Expression *node) +Type *ETSChecker::BitwiseNegateNumericType(Type *type, ir::Expression *node) { ASSERT(type->HasTypeFlag(TypeFlag::CONSTANT | TypeFlag::ETS_INTEGRAL)); @@ -97,6 +97,16 @@ Type *ETSChecker::BitwiseNegateIntegralType(Type *type, ir::Expression *node) result = CreateLongType(static_cast(~static_cast(type->AsLongType()->GetValue()))); break; } + case TypeFlag::FLOAT: { + result = CreateIntType( + ~static_cast(CastFloatToInt(type->AsFloatType()->GetValue()))); + break; + } + case TypeFlag::DOUBLE: { + result = CreateLongType( + ~static_cast(CastFloatToInt(type->AsDoubleType()->GetValue()))); + break; + } default: { UNREACHABLE(); } @@ -200,13 +210,13 @@ checker::Type *ETSChecker::CheckBinaryOperatorShift(ir::Expression *left, ir::Ex FlagExpressionWithUnboxing(left_type, unboxed_l, left); FlagExpressionWithUnboxing(right_type, unboxed_r, right); - if (promoted_left_type == nullptr || !promoted_left_type->HasTypeFlag(checker::TypeFlag::ETS_INTEGRAL) || - promoted_right_type == nullptr || !promoted_right_type->HasTypeFlag(checker::TypeFlag::ETS_INTEGRAL)) { - ThrowTypeError("Bad operand type, the types of the operands must be integral type.", pos); + if (promoted_left_type == nullptr || !promoted_left_type->HasTypeFlag(checker::TypeFlag::ETS_NUMERIC) || + promoted_right_type == nullptr || !promoted_right_type->HasTypeFlag(checker::TypeFlag::ETS_NUMERIC)) { + ThrowTypeError("Bad operand type, the types of the operands must be numeric type.", pos); } if (promoted_left_type->HasTypeFlag(TypeFlag::CONSTANT) && promoted_right_type->HasTypeFlag(TypeFlag::CONSTANT)) { - return HandleArithmeticOperationOnTypes(promoted_left_type, promoted_right_type, operation_type); + return HandleBitwiseOperationOnTypes(promoted_left_type, promoted_right_type, operation_type); } switch (ETSType(promoted_left_type)) { @@ -219,10 +229,12 @@ checker::Type *ETSChecker::CheckBinaryOperatorShift(ir::Expression *left, ir::Ex case TypeFlag::CHAR: { return GlobalCharType(); } - case TypeFlag::INT: { + case TypeFlag::INT: + case TypeFlag::FLOAT: { return GlobalIntType(); } - case TypeFlag::LONG: { + case TypeFlag::LONG: + case TypeFlag::DOUBLE: { return GlobalLongType(); } default: { @@ -249,20 +261,20 @@ checker::Type *ETSChecker::CheckBinaryOperatorBitwise(ir::Expression *left, ir:: } auto [promotedType, bothConst] = - ApplyBinaryOperatorPromotion(unboxed_l, unboxed_r, TypeFlag::ETS_INTEGRAL, !is_equal_op); + ApplyBinaryOperatorPromotion(unboxed_l, unboxed_r, TypeFlag::ETS_NUMERIC, !is_equal_op); FlagExpressionWithUnboxing(left_type, unboxed_l, left); FlagExpressionWithUnboxing(right_type, unboxed_r, right); if (promotedType == nullptr && !bothConst) { - ThrowTypeError("Bad operand type, the types of the operands must be integral type.", pos); + ThrowTypeError("Bad operand type, the types of the operands must be numeric type.", pos); } if (bothConst) { - return HandleArithmeticOperationOnTypes(left_type, right_type, operation_type); + return HandleBitwiseOperationOnTypes(left_type, right_type, operation_type); } - return promotedType; + return SelectGlobalIntegerTypeForNumeric(promotedType); } checker::Type *ETSChecker::CheckBinaryOperatorLogical(ir::Expression *left, ir::Expression *right, ir::Expression *expr, @@ -606,6 +618,26 @@ Type *ETSChecker::HandleArithmeticOperationOnTypes(Type *left, Type *right, lexe return PerformArithmeticOperationOnTypes(left, right, operation_type); } +Type *ETSChecker::HandleBitwiseOperationOnTypes(Type *left, Type *right, lexer::TokenType operation_type) +{ + ASSERT(left->HasTypeFlag(TypeFlag::CONSTANT | TypeFlag::ETS_NUMERIC) && + right->HasTypeFlag(TypeFlag::CONSTANT | TypeFlag::ETS_NUMERIC)); + + if (left->IsDoubleType() || right->IsDoubleType()) { + return HandleBitWiseArithmetic(left, right, operation_type); + } + + if (left->IsFloatType() || right->IsFloatType()) { + return HandleBitWiseArithmetic(left, right, operation_type); + } + + if (left->IsLongType() || right->IsLongType()) { + return HandleBitWiseArithmetic(left, right, operation_type); + } + + return HandleBitWiseArithmetic(left, right, operation_type); +} + void ETSChecker::FlagExpressionWithUnboxing(Type *type, Type *unboxed_type, ir::Expression *type_expression) { if (type->IsETSObjectType() && (unboxed_type != nullptr)) { diff --git a/ets2panda/checker/ets/arithmetic.h b/ets2panda/checker/ets/arithmetic.h index 0eb9a9792986862aa336fb6fd436f3af3e9bb80e..c521113a21ddcf682135aab521eeb37ce1408810 100644 --- a/ets2panda/checker/ets/arithmetic.h +++ b/ets2panda/checker/ets/arithmetic.h @@ -17,7 +17,6 @@ #define ES2PANDA_COMPILER_CHECKER_ETS_ARITHMETIC_H #include "checker/ETSchecker.h" -#include "checker/types/ets/etsBooleanType.h" namespace panda::es2panda::checker { @@ -137,7 +136,7 @@ Type *ETSChecker::PerformArithmeticOperationOnTypes(Type *left, Type *right, lex break; } default: { - result = HandleBitWiseArithmetic(left_value, right_value, operation_type); + UNREACHABLE(); } } @@ -172,63 +171,69 @@ inline DoubleType::UType panda::es2panda::checker::ETSChecker::HandleModulo -UType ETSChecker::HandleBitWiseArithmetic(UType left_value, UType right_value, lexer::TokenType operation_type) +template +inline IntegerUType CastIfFloat(FloatOrIntegerUType num) +{ + if constexpr (std::is_floating_point_v) { + return CastFloatToInt(num); + } else { + return num; + } +} + +template +Type *ETSChecker::HandleBitWiseArithmetic(Type *left, Type *right, lexer::TokenType operation_type) { - using UnsignedType = std::make_unsigned_t; - auto unsigned_left_value = static_cast(left_value); - auto unsigned_right_value = static_cast(right_value); - size_t mask = std::numeric_limits::digits - 1U; - size_t shift = static_cast(unsigned_right_value) & mask; + using IntegerUType = typename IntegerType::UType; + using UnsignedUType = std::make_unsigned_t; + + UnsignedUType result = 0; + UnsignedUType unsigned_left_value = CastIfFloat(GetOperand(left)); + UnsignedUType unsigned_right_value = CastIfFloat(GetOperand(right)); + + auto mask = std::numeric_limits::digits - 1U; + auto shift = unsigned_right_value & mask; switch (operation_type) { case lexer::TokenType::PUNCTUATOR_BITWISE_AND: case lexer::TokenType::PUNCTUATOR_BITWISE_AND_EQUAL: { - return unsigned_left_value & unsigned_right_value; + result = unsigned_left_value & unsigned_right_value; + break; } case lexer::TokenType::PUNCTUATOR_BITWISE_OR: case lexer::TokenType::PUNCTUATOR_BITWISE_OR_EQUAL: { - return unsigned_left_value | unsigned_right_value; + result = unsigned_left_value | unsigned_right_value; + break; } case lexer::TokenType::PUNCTUATOR_BITWISE_XOR: case lexer::TokenType::PUNCTUATOR_BITWISE_XOR_EQUAL: { - return unsigned_left_value ^ unsigned_right_value; + result = unsigned_left_value ^ unsigned_right_value; + break; } case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT: case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT_EQUAL: { - static_assert(sizeof(UType) == 4 || sizeof(UType) == 8); - return unsigned_left_value << shift; + static_assert(sizeof(UnsignedUType) == 4 || sizeof(UnsignedUType) == 8); + result = unsigned_left_value << shift; + break; } case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT: case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT_EQUAL: { - static_assert(sizeof(UType) == 4 || sizeof(UType) == 8); - return left_value >> shift; // NOLINT(hicpp-signed-bitwise) + static_assert(sizeof(IntegerUType) == 4 || sizeof(IntegerUType) == 8); + result = static_cast(unsigned_left_value) >> shift; // NOLINT(hicpp-signed-bitwise) + break; } case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT: case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT_EQUAL: { - static_assert(sizeof(UType) == 4 || sizeof(UType) == 8); - return unsigned_left_value >> shift; + static_assert(sizeof(UnsignedUType) == 4 || sizeof(UnsignedUType) == 8); + result = unsigned_left_value >> shift; + break; } default: { UNREACHABLE(); } } -} - -template <> -inline FloatType::UType ETSChecker::HandleBitWiseArithmetic( - [[maybe_unused]] FloatType::UType left_value, [[maybe_unused]] FloatType::UType right_value, - [[maybe_unused]] lexer::TokenType operation_type) -{ - return 0.0; -} -template <> -inline DoubleType::UType ETSChecker::HandleBitWiseArithmetic( - [[maybe_unused]] DoubleType::UType left_value, [[maybe_unused]] DoubleType::UType right_value, - [[maybe_unused]] lexer::TokenType operation_type) -{ - return 0.0; + return Allocator()->New(result); } } // namespace panda::es2panda::checker diff --git a/ets2panda/compiler/core/ETSCompiler.cpp b/ets2panda/compiler/core/ETSCompiler.cpp index de21cbc011f95ba968be23e83fbb8290d0cdf323..0129b0097193083d2e293fa3ae83afe976ea3ce0 100644 --- a/ets2panda/compiler/core/ETSCompiler.cpp +++ b/ets2panda/compiler/core/ETSCompiler.cpp @@ -525,8 +525,7 @@ void ETSCompiler::Compile(const ir::BinaryExpression *expr) const etsg->ApplyConversionAndStoreAccumulator(expr->Left(), lhs, expr->OperationType()); expr->Right()->Compile(etsg); etsg->ApplyConversion(expr->Right(), expr->OperationType()); - if (expr->OperatorType() >= lexer::TokenType::PUNCTUATOR_LEFT_SHIFT && - expr->OperatorType() <= lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT) { + if (expr->OperationType()->IsIntType()) { etsg->ApplyCast(expr->Right(), expr->OperationType()); } @@ -1037,7 +1036,13 @@ void ETSCompiler::Compile(const ir::UnaryExpression *expr) const if (!etsg->TryLoadConstantExpression(expr->Argument())) { expr->Argument()->Compile(etsg); } + etsg->ApplyConversion(expr->Argument(), nullptr); + + if (expr->OperatorType() == lexer::TokenType::PUNCTUATOR_TILDE) { + etsg->ApplyCast(expr->Argument(), expr->TsType()); + } + etsg->Unary(expr, expr->OperatorType()); } diff --git a/ets2panda/test/runtime/ets/BitwiseOperationsOnFloat.ets b/ets2panda/test/runtime/ets/BitwiseOperationsOnFloat.ets new file mode 100644 index 0000000000000000000000000000000000000000..816928325c8749a9a27469d3161a1d996577f7a9 --- /dev/null +++ b/ets2panda/test/runtime/ets/BitwiseOperationsOnFloat.ets @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +function And(a: double, b: double): long { + return a & b +} + +function Or(a: double, b: double): long { + return a | b +} + +function Xor(a: double, b: double): long { + return a ^ b +} + +function LeftShift(a: double, b: double): long { + return a << b +} + +function RightShift(a: double, b: double): long { + return a >> b +} + +function UnsignedRightShift(a: double, b: double): long { + return a >>> b +} + +function Inversion(a: double): long { + return ~a; +} + +function main(): void { + /* ---- Compile time tests ---- */ + + // Testing "and" operator: + assert (542.910991 & -1903.2040221) == 16 + assert (-542.910991 & 1903.2040221) == 1378 + assert (-542.910991 & -1903.2040221) == -1920 + assert (9E120 & 56.75) == 56 + assert (0.0 & 0.0) == 0 + assert (NaN & 42.131330352) == 0 + assert (-NaN & -23432.34110144432) == 0 + assert (Infinity & -94.24445985981884) == 9223372036854775714 + assert (-Infinity & 94.24445985981884) == 0 + + // Testing "or" operator: + assert (542.910991 | 1903.2040221) == 1919 + assert (542.910991 | -1903.2040221) == -1377 + assert (-542.910991 | 1903.2040221) == -17 + assert (-542.910991 | -1903.2040221) == -525 + assert (9E120 | 0) == 9223372036854775807 + assert (824E3 | 21.018763) == 824021 + assert (1.0 | 0.1) == 1 + assert (NaN | 0.2) == 0 + assert (-NaN | 0.3) == 0 + assert (Infinity | 0.4) == 9223372036854775807 + assert (-Infinity | 0.5) == -9223372036854775808 + + // Testing "xor" operator: + assert (542.910991 ^ 1903.2040221) == 1393 + assert (542.910991 ^ -1903.2040221) == -1393 + assert (-542.910991 ^ 1903.2040221) == -1395 + assert (-542.910991 ^ -1903.2040221) == 1395 + assert (49509.2348100001 ^ 49509.2348100001) == 0 + assert (9E120 ^ 1.2) == 9223372036854775806 + assert (824E3 ^ 21.018763) == 824021 + assert (NaN ^ 99854258.24) == 99854258 + assert (-NaN ^ 30483040.293244) == 30483040 + assert (Infinity ^ 1.2) == 9223372036854775806 + assert (-Infinity ^ 10049329.80001) == -9223372036844726479 + + // Testing "left shift" operator: + assert (1E-100 << 0.0) == 0 + assert (0.00003 << 12.13) == 0 + assert (42.109 << 0.0120939) == 42 + assert (1.409240940 << 17.3) == 131072 + assert (4342435.309421 << 3.1) == 34739480 + assert (9010034745.3449093132 << 7.000000000001) == 1153284447360 + assert (-423.14981 << 20.32) == -443547648 + assert (500.13 << 128.3440) == 500 + assert (500.45 << 121.10000002) == -1729382256910270464 + assert (NaN << 330.3911) == 0 + assert (-NaN << 12.91213) == 0 + assert (Infinity << 1.0092) == -2 + assert (-Infinity << 1.0092) == 0 + assert (-52242.2301 << -8.7) == -1297036692682702848 + assert (52242.2301 << -8.7) == 1297036692682702848 + + // Testing "right shift" operator: + assert (1E-100 >> 0.0) == 0 + assert (0.00003 >> 12.13) == 0 + assert (42.109 >> 0.0120939) == 42 + assert (1.409240940 >> 17.3) == 0 + assert (4342435.309421 >> 3.1) == 542804 + assert (9010034.3449093132 >> 3.000000000001) == 1126254 + assert (-4599090490.24 >> 11) == -2245650 + assert (500.13 >> 128.3440) == 500 + assert (500.45 >> 121.10000002) == 0 + assert (NaN >> 11.000003) == 0 + assert (-NaN >> 7.912130001) == 0 + assert (Infinity >> 61) == 3 + assert (-Infinity >> 61) == -4 + assert (132090941883.34343 >> -32.2) == 30 + assert (-132090941883.34343 >> -32.2) == -31 + + // Testing "unsigned right shift" operator: + assert (1E-100 >>> 0.0) == 0 + assert (0.00003 >>> 12.13) == 0 + assert (42.109 >>> 0.0120939) == 42 + assert (1.409240940 >>> 17.3) == 0 + assert (4342435.309421 >>> 3.1) == 542804 + assert (9010034.3449093132 >>> 3.000000000001) == 1126254 + assert (-4599090490.24 >>> 11) == 9007199252495342 + assert (500.13 >>> 128.3440) == 500 + assert (500.45 >>> 121.10000002) == 0 + assert (NaN >>> 11.000003) == 0 + assert (-NaN >>> 7.912130001) == 0 + assert (Infinity >>> 61.8) == 3 + assert (-Infinity >>> 61.8) == 4 + assert (132090941883.34343 >>> -32.2) == 30 + assert (-132090941883.34343 >>> -32.2) == 4294967265 + + // Testing "bitwise complement" operator + assert ~0 == -1 + assert ~0.000034 == -1 + assert ~39530.93 == -39531 + assert ~93718001.5424230894 == -93718002 + assert ~Infinity == -9223372036854775808 + assert ~-Infinity == 9223372036854775807 + assert ~NaN == -1 + assert ~-NaN == -1 + assert ~1E210 == -9223372036854775808 + assert ~-1E210 == 9223372036854775807 + assert ~56E5 == -5600001 + assert ~-56E5 == 5599999 + + /* ---- Run time tests ---- */ + + // Testing "and" operator: + assert And(542.910991, -1903.2040221) == 16 + assert And(-542.910991, 1903.2040221) == 1378 + assert And(-542.910991, -1903.2040221) == -1920 + assert And(9E120, 56.75) == 56 + assert And(0.0, 0.0) == 0 + assert And(NaN, 42.131330352) == 0 + assert And(-NaN, -23432.34110144432) == 0 + assert And(Infinity, -94.24445985981884) == 9223372036854775714 + assert And(-Infinity, 94.24445985981884) == 0 + + // Testing "or" operator: + assert Or(542.910991, 1903.2040221) == 1919 + assert Or(542.910991, -1903.2040221) == -1377 + assert Or(-542.910991, 1903.2040221) == -17 + assert Or(-542.910991, -1903.2040221) == -525 + assert Or(9E120, 0) == 9223372036854775807 + assert Or(824E3, 21.018763) == 824021 + assert Or(1.0, 0.1) == 1 + assert Or(NaN, 0.2) == 0 + assert Or(-NaN, 0.3) == 0 + assert Or(Infinity, 0.4) == 9223372036854775807 + assert Or(-Infinity, 0.5) == -9223372036854775808 + + // Testing "xor" operator: + assert Xor(542.910991, 1903.2040221) == 1393 + assert Xor(542.910991, -1903.2040221) == -1393 + assert Xor(-542.910991, 1903.2040221) == -1395 + assert Xor(-542.910991, -1903.2040221) == 1395 + assert Xor(49509.2348100001, 49509.2348100001) == 0 + assert Xor(9E120, 1.2) == 9223372036854775806 + assert Xor(824E3, 21.018763) == 824021 + assert Xor(NaN, 99854258.24) == 99854258 + assert Xor(-NaN, 30483040.293244) == 30483040 + assert Xor(Infinity, 1.2) == 9223372036854775806 + assert Xor(-Infinity, 10049329.80001) == -9223372036844726479 + + // Testing "left shift" operator: + assert LeftShift(1E-100, 0.0) == 0 + assert LeftShift(0.00003, 12.13) == 0 + assert LeftShift(42.109, 0.0120939) == 42 + assert LeftShift(1.409240940, 17.3) == 131072 + assert LeftShift(4342435.309421, 3.1) == 34739480 + assert LeftShift(9010034745.3449093132, 7.000000000001) == 1153284447360 + assert LeftShift(-423.14981, 20.32) == -443547648 + assert LeftShift(500.13, 128.3440) == 500 + assert LeftShift(500.45, 121.10000002) == -1729382256910270464 + assert LeftShift(NaN, 330.3911) == 0 + assert LeftShift(-NaN, 12.91213) == 0 + assert LeftShift(Infinity, 1.0092) == -2 + assert LeftShift(-Infinity, 1.0092) == 0 + assert LeftShift(-52242.2301, -8.7) == -1297036692682702848 + assert LeftShift(52242.2301,-8.7) == 1297036692682702848 + + // Testing "right shift" operator: + assert RightShift(1E-100, 0.0) == 0 + assert RightShift(0.00003, 12.13) == 0 + assert RightShift(42.109, 0.0120939) == 42 + assert RightShift(1.409240940, 17.3) == 0 + assert RightShift(4342435.309421, 3.1) == 542804 + assert RightShift(9010034.3449093132, 3.000000000001) == 1126254 + assert RightShift(-4599090490.24, 11) == -2245650 + assert RightShift(500.13, 128.3440) == 500 + assert RightShift(500.45, 121.10000002) == 0 + assert RightShift(NaN, 11.000003) == 0 + assert RightShift(-NaN, 7.912130001) == 0 + assert RightShift(Infinity, 61) == 3 + assert RightShift(-Infinity, 61) == -4 + assert RightShift(132090941883.34343, -32.2) == 30 + assert RightShift(-132090941883.34343, -32.2) == -31 + + // Testing "unsigned right shift" operator: + assert UnsignedRightShift(1E-100, 0.0) == 0 + assert UnsignedRightShift(0.00003,12.13) == 0 + assert UnsignedRightShift(42.109, 0.0120939) == 42 + assert UnsignedRightShift(1.409240940, 17.3) == 0 + assert UnsignedRightShift(4342435.309421, 3.1) == 542804 + assert UnsignedRightShift(9010034.3449093132, 3.000000000001) == 1126254 + assert UnsignedRightShift(-4599090490.24, 11) == 9007199252495342 + assert UnsignedRightShift(500.13, 128.3440) == 500 + assert UnsignedRightShift(500.45, 121.10000002) == 0 + assert UnsignedRightShift(NaN, 11.000003) == 0 + assert UnsignedRightShift(-NaN, 7.912130001) == 0 + assert UnsignedRightShift(Infinity, 61.8) == 3 + assert UnsignedRightShift(-Infinity, 61.8) == 4 + assert UnsignedRightShift(132090941883.34343, -32.2) == 30 + assert UnsignedRightShift(-132090941883.34343, -32.2) == 4294967265 + + // Testing "bitwise complement" operator + assert Inversion(0) == -1 + assert Inversion(0.000034) == -1 + assert Inversion(39530.93) == -39531 + assert Inversion(93718001.5424230894) == -93718002 + assert Inversion(Infinity) == -9223372036854775808 + assert Inversion(-Infinity) == 9223372036854775807 + assert Inversion(NaN) == -1 + assert Inversion(-NaN) == -1 + assert Inversion(1E210) == -9223372036854775808 + assert Inversion(-1E210) == 9223372036854775807 + assert Inversion(56E5) == -5600001 + assert Inversion(-56E5) == 5599999 +}