blob: c9964ed67f7d6a77b19533e3098b75a46f3de954 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you 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.
#include <gtest/gtest.h>
#include <limits>
#include "vec/common/arithmetic_overflow.h"
#include "vec/core/types.h"
#include "vec/io/io_helper.h"
namespace doris::vectorized {
struct CheckOverFlowTest : public testing::Test {
void SetUp() override {
// This function is called before each test.
}
void TearDown() override {
// This function is called after each test.
}
Int128 to_i128(std::string str) {
StringRef str_ref(str.data(), str.size());
Int128 val;
EXPECT_TRUE(try_read_int_text(val, str_ref));
return val;
};
wide::Int256 to_i256(std::string str) { return wide::Int256::_impl::from_str(str.c_str()); };
};
TEST_F(CheckOverFlowTest, test_overflow_int128) {
{
Int128 a = to_i128("-15687000000000000000000");
Int128 b = to_i128("11000000000000000");
Int128 c;
EXPECT_TRUE(common::mul_overflow(a, b, c));
}
{
Int128 a = to_i128("-15687000000000000000000");
Int128 b = to_i128("-11000000000000000");
Int128 c;
EXPECT_TRUE(common::mul_overflow(a, b, c));
}
{
Int128 a = to_i128("1000");
Int128 b = to_i128("12000");
Int128 c;
EXPECT_FALSE(common::mul_overflow(a, b, c));
}
}
TEST_F(CheckOverFlowTest, test_overflow_int256) {
{
wide::Int256 a =
to_i256("-11579208923731619542357098500868790785326998466564056403945758400791");
wide::Int256 b = to_i256("1157920892373161954235709850086879078532699846656405640394575");
wide::Int256 c;
EXPECT_TRUE(common::mul_overflow(a, b, c));
}
{
wide::Int256 a = to_i256("-1157920892373161954235709850086879078532699846656405640394");
wide::Int256 b = to_i256("-1157920892373161954235709850086879078532699846656405640394");
wide::Int256 c;
EXPECT_TRUE(common::mul_overflow(a, b, c));
}
{
wide::Int256 a = to_i256("1000");
wide::Int256 b = to_i256("12000");
wide::Int256 c;
EXPECT_FALSE(common::mul_overflow(a, b, c));
}
// max int256, 77 decimal digits:
// >>> 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
// 57896044618658097711785492504343953926634992332820282019728792003956564819967
// no overflow
std::vector<std::tuple<std::string, std::string, std::string>> test_input_data = {
{"-57896044618658097711785492504343953926634992332820282019728792003956564819968", "0",
"0"},
{"-57896044618658097711785492504343953926634992332820282019728792003956564819968", "1",
"-57896044618658097711785492504343953926634992332820282019728792003956564819968"},
{"57896044618658097711785492504343953926634992332820282019728792003956564819967", "0",
"0"},
{"57896044618658097711785492504343953926634992332820282019728792003956564819967", "1",
"57896044618658097711785492504343953926634992332820282019728792003956564819967"},
{"57896044618658097711785492504343953926634992332820282019728792003956564819967", "-1",
"-57896044618658097711785492504343953926634992332820282019728792003956564819967"},
{"-57896044618658097711785492504343953926634992332820282019728792003956564819967", "0",
"0"},
{"-57896044618658097711785492504343953926634992332820282019728792003956564819967", "1",
"-57896044618658097711785492504343953926634992332820282019728792003956564819967"},
{"-57896044618658097711785492504343953926634992332820282019728792003956564819967", "-1",
"57896044618658097711785492504343953926634992332820282019728792003956564819967"},
{"28948022309329048855892746252171976963317496166410141009864396001978282409983", "2",
"57896044618658097711785492504343953926634992332820282019728792003956564819966"},
{"28948022309329048855892746252171976963317496166410141009864396001978282409983", "-2",
"-57896044618658097711785492504343953926634992332820282019728792003956564819966"},
{"-28948022309329048855892746252171976963317496166410141009864396001978282409983", "2",
"-57896044618658097711785492504343953926634992332820282019728792003956564819966"},
{"-28948022309329048855892746252171976963317496166410141009864396001978282409983", "-2",
"57896044618658097711785492504343953926634992332820282019728792003956564819966"},
{"28948022309329048855892746252171976963317496166410141009864396001978282409984", "-2",
"-57896044618658097711785492504343953926634992332820282019728792003956564819968"},
{"-28948022309329048855892746252171976963317496166410141009864396001978282409984", "2",
"-57896044618658097711785492504343953926634992332820282019728792003956564819968"},
{"9999999999999999999999999999999999999999999999999999999999999999999999999999", "2",
"19999999999999999999999999999999999999999999999999999999999999999999999999998"},
{"9999999999999999999999999999999999999999999999999999999999999999999999999999", "-2",
"-19999999999999999999999999999999999999999999999999999999999999999999999999998"},
{"-9999999999999999999999999999999999999999999999999999999999999999999999999999", "2",
"-19999999999999999999999999999999999999999999999999999999999999999999999999998"},
{"-9999999999999999999999999999999999999999999999999999999999999999999999999999", "-2",
"19999999999999999999999999999999999999999999999999999999999999999999999999998"},
{"9999999999999999999999999999999999999999999999999999999999999999999999999999", "5",
"49999999999999999999999999999999999999999999999999999999999999999999999999995"},
{"9999999999999999999999999999999999999999999999999999999999999999999999999999", "-5",
"-49999999999999999999999999999999999999999999999999999999999999999999999999995"},
{"-9999999999999999999999999999999999999999999999999999999999999999999999999999", "5",
"-49999999999999999999999999999999999999999999999999999999999999999999999999995"},
{"-9999999999999999999999999999999999999999999999999999999999999999999999999999", "-5",
"49999999999999999999999999999999999999999999999999999999999999999999999999995"},
{"5000000000000000000000000000000000000000000000000000000000000000000000000000", "2",
"10000000000000000000000000000000000000000000000000000000000000000000000000000"},
{"5000000000000000000000000000000000000000000000000000000000000000000000000000", "-2",
"-10000000000000000000000000000000000000000000000000000000000000000000000000000"},
{"-5000000000000000000000000000000000000000000000000000000000000000000000000000", "2",
"-10000000000000000000000000000000000000000000000000000000000000000000000000000"},
{"-5000000000000000000000000000000000000000000000000000000000000000000000000000", "-2",
"10000000000000000000000000000000000000000000000000000000000000000000000000000"},
{"240615969168004511545033772477625056927", "240615969168004511545033772477625056927",
"57896044618658097711785492504343953926579659927927152379400772292519990683329"},
{"240615969168004511545033772477625056927", "-240615969168004511545033772477625056927",
"-57896044618658097711785492504343953926579659927927152379400772292519990683329"},
{"-240615969168004511545033772477625056927", "240615969168004511545033772477625056927",
"-57896044618658097711785492504343953926579659927927152379400772292519990683329"},
{"-240615969168004511545033772477625056927", "-240615969168004511545033772477625056927",
"57896044618658097711785492504343953926579659927927152379400772292519990683329"},
};
for (const auto& [input1, input2, expected_str] : test_input_data) {
// std::cout << "-------Testing multiplication: " << input1 << " * " << input2 << " = "
// << expected_str << std::endl;
wide::Int256 i1 = wide::Int256::_impl::from_str(input1.c_str());
wide::Int256 i2 = wide::Int256::_impl::from_str(input2.c_str());
wide::Int256 expect_result = wide::Int256::_impl::from_str(expected_str.c_str());
// std::cout << "Testing multiplication as int256: " << wide::to_string(i1) << " * "
// << wide::to_string(i2) << " = " << wide::to_string(expect_result) << std::endl;
wide::Int256 mul_res = 0;
bool overflow = common::mul_overflow(i1, i2, mul_res);
EXPECT_FALSE(overflow);
EXPECT_EQ(mul_res, expect_result);
std::string str_output = wide::to_string(mul_res);
EXPECT_EQ(str_output, expected_str);
overflow = common::mul_overflow(i2, i1, mul_res);
EXPECT_FALSE(overflow);
EXPECT_EQ(mul_res, expect_result);
str_output = wide::to_string(mul_res);
EXPECT_EQ(str_output, expected_str);
}
std::vector<std::tuple<std::string, std::string>> test_input_data_overflow = {
{"-57896044618658097711785492504343953926634992332820282019728792003956564819968", "2"},
{"-57896044618658097711785492504343953926634992332820282019728792003956564819968",
"-2"},
{"-57896044618658097711785492504343953926634992332820282019728792003956564819968",
"99999999"},
{"-57896044618658097711785492504343953926634992332820282019728792003956564819968",
"-99999999"},
{"-57896044618658097711785492504343953926634992332820282019728792003956564819968",
"57896044618658097711785492504343953926634992332820282019728792003956564819967"},
{"-57896044618658097711785492504343953926634992332820282019728792003956564819968",
"-57896044618658097711785492504343953926634992332820282019728792003956564819967"},
{"-57896044618658097711785492504343953926634992332820282019728792003956564819968",
"-57896044618658097711785492504343953926634992332820282019728792003956564819968"},
{"57896044618658097711785492504343953926634992332820282019728792003956564819967", "2"},
{"57896044618658097711785492504343953926634992332820282019728792003956564819967", "-2"},
{"57896044618658097711785492504343953926634992332820282019728792003956564819967",
"99999999999999999999999999999999999"},
{"57896044618658097711785492504343953926634992332820282019728792003956564819967",
"-99999999999999999999999999999999999"},
{"57896044618658097711785492504343953926634992332820282019728792003956564819967",
"57896044618658097711785492504343953926634992332820282019728792003956564819967"},
{"57896044618658097711785492504343953926634992332820282019728792003956564819967",
"-57896044618658097711785492504343953926634992332820282019728792003956564819967"},
{"-57896044618658097711785492504343953926634992332820282019728792003956564819967", "2"},
{"-57896044618658097711785492504343953926634992332820282019728792003956564819967",
"-2"},
{"-57896044618658097711785492504343953926634992332820282019728792003956564819967",
"99999999999999999999999999999999999"},
{"-57896044618658097711785492504343953926634992332820282019728792003956564819967",
"-99999999999999999999999999999999999"},
{"-57896044618658097711785492504343953926634992332820282019728792003956564819967",
"57896044618658097711785492504343953926634992332820282019728792003956564819967"},
{"-57896044618658097711785492504343953926634992332820282019728792003956564819967",
"-57896044618658097711785492504343953926634992332820282019728792003956564819967"},
{"28948022309329048855892746252171976963317496166410141009864396001978282409984", "2"},
{"28948022309329048855892746252171976963317496166410141009864396001978282409984", "3"},
{"-28948022309329048855892746252171976963317496166410141009864396001978282409984", "3"},
{"-28948022309329048855892746252171976963317496166410141009864396001978282409984",
"-3"},
{"-28948022309329048855892746252171976963317496166410141009864396001978282409984",
"-2"},
{"99999999999999999999999999999999999", "999999999999999999999999999999999999999999"},
{"-99999999999999999999999999999999999", "999999999999999999999999999999999999999999"},
{"99999999999999999999999999999999999", "-999999999999999999999999999999999999999999"},
{"-99999999999999999999999999999999999", "-999999999999999999999999999999999999999999"},
};
for (const auto& [input1, input2] : test_input_data_overflow) {
wide::Int256 i1 = wide::Int256::_impl::from_str(input1.c_str());
wide::Int256 i2 = wide::Int256::_impl::from_str(input2.c_str());
// wide::Int256 mul_res_direct = i1 * i2;
// std::cout << "multiplication res as int256: " << wide::to_string(i1) << " * "
// << wide::to_string(i2) << " = " << wide::to_string(mul_res_direct) << std::endl;
wide::Int256 mul_res;
bool overflow = common::mul_overflow(i1, i2, mul_res);
EXPECT_TRUE(overflow);
overflow = common::mul_overflow(i2, i1, mul_res);
EXPECT_TRUE(overflow);
}
}
} // namespace doris::vectorized