From f5683472b7b389adca4b429a3a180deeae76c65d Mon Sep 17 00:00:00 2001 From: Jianling Zhong Date: Sat, 16 Nov 2024 18:40:56 -0800 Subject: [PATCH 1/4] Add support for runtime ratio object --- .gitignore | 1 + compiler+runtime/CMakeLists.txt | 2 + compiler+runtime/bin/format | 10 + .../cpp/jank/runtime/core/make_box.hpp | 6 + .../include/cpp/jank/runtime/core/math.hpp | 6 + .../include/cpp/jank/runtime/erasure.hpp | 11 + .../include/cpp/jank/runtime/obj/ratio.hpp | 146 +++++ .../include/cpp/jank/runtime/object.hpp | 2 + compiler+runtime/src/cpp/jank/read/parse.cpp | 18 +- .../src/cpp/jank/runtime/core/math.cpp | 175 +++--- .../src/cpp/jank/runtime/obj/number.cpp | 4 +- .../src/cpp/jank/runtime/obj/ratio.cpp | 556 ++++++++++++++++++ compiler+runtime/test/cpp/jank/read/parse.cpp | 15 + .../test/cpp/jank/runtime/obj/ratio.cpp | 401 +++++++++++++ 14 files changed, 1260 insertions(+), 93 deletions(-) create mode 100755 compiler+runtime/bin/format create mode 100644 compiler+runtime/include/cpp/jank/runtime/obj/ratio.hpp create mode 100644 compiler+runtime/src/cpp/jank/runtime/obj/ratio.cpp create mode 100644 compiler+runtime/test/cpp/jank/runtime/obj/ratio.cpp diff --git a/.gitignore b/.gitignore index 3a4f63ba3..702cec83a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ test.jank jank-generated.hpp +.jank-repl-history a.out .jank-native-repl-history .jank-repl-history diff --git a/compiler+runtime/CMakeLists.txt b/compiler+runtime/CMakeLists.txt index b9fc9ed57..88dbd3eb3 100644 --- a/compiler+runtime/CMakeLists.txt +++ b/compiler+runtime/CMakeLists.txt @@ -198,6 +198,7 @@ add_library( src/cpp/jank/runtime/obj/cons.cpp src/cpp/jank/runtime/obj/range.cpp src/cpp/jank/runtime/obj/repeat.cpp + src/cpp/jank/runtime/obj/ratio.cpp src/cpp/jank/runtime/obj/iterator.cpp src/cpp/jank/runtime/obj/lazy_sequence.cpp src/cpp/jank/runtime/obj/chunk_buffer.cpp @@ -444,6 +445,7 @@ if(jank_tests) test/cpp/jank/read/parse.cpp test/cpp/jank/analyze/box.cpp test/cpp/jank/runtime/detail/list_type.cpp + test/cpp/jank/runtime/obj/ratio.cpp test/cpp/jank/jit/processor.cpp ) add_executable(jank::test_exe ALIAS jank_test_exe) diff --git a/compiler+runtime/bin/format b/compiler+runtime/bin/format new file mode 100755 index 000000000..fef24ab2a --- /dev/null +++ b/compiler+runtime/bin/format @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +set -euo pipefail + +git_root=$(git rev-parse --show-toplevel) + +for i in $(git status | grep -E "modified:" | sed 's/modified:\s*//'); do + "$git_root"/compiler+runtime/build/llvm-install/usr/local/bin/clang-format -i "$i" + echo "formatted" "$i" +done diff --git a/compiler+runtime/include/cpp/jank/runtime/core/make_box.hpp b/compiler+runtime/include/cpp/jank/runtime/core/make_box.hpp index 8a4217dda..f99ad28d1 100644 --- a/compiler+runtime/include/cpp/jank/runtime/core/make_box.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/core/make_box.hpp @@ -60,6 +60,12 @@ namespace jank::runtime return make_box(r); } + [[gnu::always_inline, gnu::flatten, gnu::hot]] + inline auto make_box(obj::ratio_data const r) + { + return expect_object(obj::ratio::create(r.numerator, r.denominator)); + } + [[gnu::always_inline, gnu::flatten, gnu::hot]] inline auto make_box(native_persistent_string_view const &s) { diff --git a/compiler+runtime/include/cpp/jank/runtime/core/math.hpp b/compiler+runtime/include/cpp/jank/runtime/core/math.hpp index 260f8ffa6..8cc7d6913 100644 --- a/compiler+runtime/include/cpp/jank/runtime/core/math.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/core/math.hpp @@ -1,12 +1,14 @@ #pragma once #include +#include namespace jank::runtime { object_ptr add(object_ptr l, object_ptr r); object_ptr add(obj::integer_ptr l, object_ptr r); object_ptr add(object_ptr l, obj::integer_ptr r); + object_ptr add(object_ptr l, obj::ratio_ptr r); native_integer add(obj::integer_ptr l, obj::integer_ptr r); native_real add(obj::real_ptr l, obj::real_ptr r); native_real add(obj::real_ptr l, object_ptr r); @@ -25,6 +27,10 @@ namespace jank::runtime object_ptr add(native_integer l, object_ptr r); native_integer add(native_integer l, native_integer r); + obj::ratio_ptr add(obj::ratio_ptr l, obj::ratio_ptr r); + object_ptr add(obj::ratio_ptr l, obj::integer_ptr r); + obj::ratio_ptr add(obj::integer_ptr l, obj::ratio_ptr r); + object_ptr sub(object_ptr l, object_ptr r); object_ptr sub(obj::integer_ptr l, object_ptr r); object_ptr sub(object_ptr l, obj::integer_ptr r); diff --git a/compiler+runtime/include/cpp/jank/runtime/erasure.hpp b/compiler+runtime/include/cpp/jank/runtime/erasure.hpp index 781a73886..4a4007caf 100644 --- a/compiler+runtime/include/cpp/jank/runtime/erasure.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/erasure.hpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -293,6 +294,11 @@ namespace jank::runtime return fn(expect_object(erased), std::forward(args)...); } break; + case object_type::ratio: + { + return fn(expect_object(erased), std::forward(args)...); + } + break; case object_type::native_array_sequence: { return fn(expect_object(erased), std::forward(args)...); @@ -648,6 +654,11 @@ namespace jank::runtime return fn(expect_object(erased), std::forward(args)...); } break; + case object_type::ratio: + { + return fn(expect_object(erased), std::forward(args)...); + } + break; default: return else_fn(); } diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/ratio.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/ratio.hpp new file mode 100644 index 000000000..f01dca2ee --- /dev/null +++ b/compiler+runtime/include/cpp/jank/runtime/obj/ratio.hpp @@ -0,0 +1,146 @@ +#pragma once + +namespace jank::runtime +{ + template <> + struct static_object : gc + { + static constexpr native_bool pointer_free{ true }; + static_object() = default; + static_object(static_object &&) = default; + static_object(static_object const &) = default; + static_object(native_integer const numerator, native_integer const denominator); + + native_real to_real() const; + void simplify(); + + native_integer numerator{}; + native_integer denominator{}; + }; + + namespace obj + { + using ratio_data = static_object; + } + + template <> + struct static_object : gc + { + static constexpr native_bool pointer_free{ true }; + + static_object() = default; + static_object(static_object &&) = default; + static_object(static_object const &) = default; + + static object_ptr create(native_integer const numerator, native_integer const denominator); + /* behavior::object_like */ + native_bool equal(object const &) const; + native_persistent_string to_string() const; + void to_string(fmt::memory_buffer &buff) const; + native_persistent_string to_code_string() const; + native_hash to_hash() const; + + /* behavior::comparable */ + native_integer compare(object const &) const; + + /* behavior::comparable extended */ + native_integer compare(static_object const &) const; + + /* behavior::number_like */ + native_integer to_integer() const; + native_real to_real() const; + + object base{ object_type::ratio }; + obj::ratio_data data{}; + }; + + namespace obj + { + using ratio = static_object; + using ratio_ptr = native_box; + } + + object_ptr operator+(obj::ratio_data l, obj::ratio_data r); + obj::ratio_ptr operator+(obj::integer_ptr l, obj::ratio_data r); + obj::ratio_ptr operator+(obj::ratio_data l, obj::integer_ptr r); + native_real operator+(obj::real_ptr l, obj::ratio_data r); + native_real operator+(obj::ratio_data l, obj::real_ptr r); + native_real operator+(obj::ratio_data l, native_real r); + native_real operator+(native_real l, obj::ratio_data r); + obj::ratio_ptr operator+(obj::ratio_data l, native_integer r); + obj::ratio_ptr operator+(native_integer l, obj::ratio_data r); + object_ptr operator-(obj::ratio_data l, obj::ratio_data r); + obj::ratio_ptr operator-(obj::integer_ptr l, obj::ratio_data r); + obj::ratio_ptr operator-(obj::ratio_data l, obj::integer_ptr r); + native_real operator-(obj::real_ptr l, obj::ratio_data r); + native_real operator-(obj::ratio_data l, obj::real_ptr r); + native_real operator-(obj::ratio_data l, native_real r); + native_real operator-(native_real l, obj::ratio_data r); + obj::ratio_ptr operator-(obj::ratio_data l, native_integer r); + obj::ratio_ptr operator-(native_integer l, obj::ratio_data r); + object_ptr operator/(obj::ratio_data l, obj::ratio_data r); + object_ptr operator/(obj::integer_ptr l, obj::ratio_data r); + obj::ratio_ptr operator/(obj::ratio_data l, obj::integer_ptr r); + native_real operator/(obj::real_ptr l, obj::ratio_data r); + native_real operator/(obj::ratio_data l, obj::real_ptr r); + native_real operator/(obj::ratio_data l, native_real r); + native_real operator/(native_real l, obj::ratio_data r); + obj::ratio_ptr operator/(obj::ratio_data l, native_integer r); + object_ptr operator/(native_integer l, obj::ratio_data r); + object_ptr operator*(obj::ratio_data l, obj::ratio_data r); + object_ptr operator*(obj::integer_ptr l, obj::ratio_data r); + object_ptr operator*(obj::ratio_data l, obj::integer_ptr r); + native_real operator*(obj::real_ptr l, obj::ratio_data r); + native_real operator*(obj::ratio_data l, obj::real_ptr r); + native_real operator*(obj::ratio_data l, native_real r); + native_real operator*(native_real l, obj::ratio_data r); + object_ptr operator*(obj::ratio_data l, native_integer r); + object_ptr operator*(native_integer l, obj::ratio_data r); + native_bool operator==(obj::ratio_data l, obj::ratio_data r); + native_bool operator==(obj::integer_ptr l, obj::ratio_data r); + native_bool operator==(obj::ratio_data l, obj::integer_ptr r); + native_bool operator==(obj::real_ptr l, obj::ratio_data r); + native_bool operator==(obj::ratio_data l, obj::real_ptr r); + native_bool operator==(obj::ratio_data l, native_real r); + native_bool operator==(native_real l, obj::ratio_data r); + native_bool operator==(obj::ratio_data l, native_integer r); + native_bool operator==(native_integer l, obj::ratio_data r); + native_bool operator<(obj::ratio_data l, obj::ratio_data r); + native_bool operator<(obj::integer_ptr l, obj::ratio_data r); + native_bool operator<(obj::ratio_data l, obj::integer_ptr r); + native_bool operator<(obj::real_ptr l, obj::ratio_data r); + native_bool operator<(obj::ratio_data l, obj::real_ptr r); + native_bool operator<(obj::ratio_data l, native_real r); + native_bool operator<(native_real l, obj::ratio_data r); + native_bool operator<(obj::ratio_data l, native_integer r); + native_bool operator<(native_integer l, obj::ratio_data r); + native_bool operator<(native_bool l, obj::ratio_data r); + native_bool operator<=(obj::ratio_data l, obj::ratio_data r); + native_bool operator<=(obj::integer_ptr l, obj::ratio_data r); + native_bool operator<=(obj::ratio_data l, obj::integer_ptr r); + native_bool operator<=(obj::real_ptr l, obj::ratio_data r); + native_bool operator<=(obj::ratio_data l, obj::real_ptr r); + native_bool operator<=(obj::ratio_data l, native_real r); + native_bool operator<=(native_real l, obj::ratio_data r); + native_bool operator<=(obj::ratio_data l, native_integer r); + native_bool operator<=(native_integer l, obj::ratio_data r); + native_bool operator>(obj::ratio_data l, obj::ratio_data r); + native_bool operator>(obj::integer_ptr l, obj::ratio_data r); + native_bool operator>(obj::ratio_data l, obj::integer_ptr r); + native_bool operator>(obj::real_ptr l, obj::ratio_data r); + native_bool operator>(obj::ratio_data l, obj::real_ptr r); + native_bool operator>(obj::ratio_data l, native_real r); + native_bool operator>(native_real l, obj::ratio_data r); + native_bool operator>(obj::ratio_data l, native_integer r); + native_bool operator>(native_integer l, obj::ratio_data r); + native_bool operator>(native_bool l, obj::ratio_data r); + native_bool operator>=(obj::ratio_data l, obj::ratio_data r); + native_bool operator>=(obj::integer_ptr l, obj::ratio_data r); + native_bool operator>=(obj::ratio_data l, obj::integer_ptr r); + native_bool operator>=(obj::real_ptr l, obj::ratio_data r); + native_bool operator>=(obj::ratio_data l, obj::real_ptr r); + native_bool operator>=(obj::ratio_data l, native_real r); + native_bool operator>=(native_real l, obj::ratio_data r); + native_bool operator>=(obj::ratio_data l, native_integer r); + native_bool operator>=(native_integer l, obj::ratio_data r); +} diff --git a/compiler+runtime/include/cpp/jank/runtime/object.hpp b/compiler+runtime/include/cpp/jank/runtime/object.hpp index 1d3d9d064..7e83e6276 100644 --- a/compiler+runtime/include/cpp/jank/runtime/object.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/object.hpp @@ -14,6 +14,8 @@ namespace jank::runtime boolean, integer, real, + ratio, + ratio_data, persistent_string, persistent_string_sequence, diff --git a/compiler+runtime/src/cpp/jank/read/parse.cpp b/compiler+runtime/src/cpp/jank/read/parse.cpp index 341988c43..993e6970e 100644 --- a/compiler+runtime/src/cpp/jank/read/parse.cpp +++ b/compiler+runtime/src/cpp/jank/read/parse.cpp @@ -1,6 +1,7 @@ #include #include +#include #include #include #include @@ -1277,10 +1278,19 @@ namespace jank::read::parse { return err(error{ token.pos, "Divide by zero" }); } - return object_source_info{ make_box(static_cast(ratio_data.numerator) - / ratio_data.denominator), - token, - token }; + auto ratio = obj::ratio::create(ratio_data.numerator, ratio_data.denominator); + if(ratio->type == object_type::ratio) + { + return object_source_info{ expect_object(ratio), token, token }; + } + else if(ratio->type == object_type::integer) + { + return object_source_info{ expect_object(ratio), token, token }; + } + else + { + return err(error{ token.pos, "Internal parsing error" }); + } } processor::object_result processor::parse_real() diff --git a/compiler+runtime/src/cpp/jank/runtime/core/math.cpp b/compiler+runtime/src/cpp/jank/runtime/core/math.cpp index 72aef46a9..5a050d181 100644 --- a/compiler+runtime/src/cpp/jank/runtime/core/math.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/core/math.cpp @@ -3,6 +3,19 @@ namespace jank::runtime { + template + auto to_number(T const &t) + { + if constexpr(std::same_as) + { + return t.to_real(); + } + else + { + return t; + } + } + /* TODO: visit_number_like */ object_ptr add(object_ptr const l, object_ptr const r) { @@ -516,20 +529,11 @@ namespace jank::runtime { return visit_number_like( [](auto const typed_l, auto const r) -> object_ptr { - using L = typename decltype(typed_l)::value_type; - return visit_number_like( [](auto const typed_r, auto const typed_l) -> object_ptr { - using R = typename decltype(typed_r)::value_type; - - if constexpr(std::is_same_v || std::is_same_v) - { - return make_box(std::fmod(typed_l, typed_r->data)); - } - else - { - return make_box(typed_l % typed_r->data); - } + auto typed_l_data = to_number(typed_l); + auto typed_r_data = to_number(typed_r->data); + return make_box(std::fmod(typed_l_data, typed_r_data)); }, r, typed_l->data); @@ -541,14 +545,14 @@ namespace jank::runtime object_ptr inc(object_ptr const l) { return visit_number_like( - [](auto const typed_l) -> object_ptr { return make_box(typed_l->data + 1); }, + [](auto const typed_l) -> object_ptr { return make_box(typed_l->data + 1LL); }, l); } object_ptr dec(object_ptr const l) { return visit_number_like( - [](auto const typed_l) -> object_ptr { return make_box(typed_l->data - 1); }, + [](auto const typed_l) -> object_ptr { return make_box(typed_l->data - 1LL); }, l); } @@ -559,7 +563,7 @@ namespace jank::runtime #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wfloat-equal" { - return typed_l->data == 0; + return typed_l->data == 0LL; } #pragma clang diagnostic pop }, @@ -573,7 +577,7 @@ namespace jank::runtime #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wfloat-equal" { - return typed_l->data > 0; + return typed_l->data > 0LL; } #pragma clang diagnostic pop }, @@ -587,7 +591,7 @@ namespace jank::runtime #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wfloat-equal" { - return typed_l->data < 0; + return typed_l->data < 0LL; } #pragma clang diagnostic pop }, @@ -612,16 +616,15 @@ namespace jank::runtime { return visit_number_like( [](auto const typed_l, auto const r) -> native_bool { - using L = typename decltype(typed_l)::value_type; - return visit_number_like( [](auto const typed_r, auto const typed_l) -> native_bool { - using R = typename decltype(typed_r)::value_type; + auto data_l = to_number(typed_l); + auto data_r = to_number(typed_r->data); - using C = std::common_type_t; + using C = std::common_type_t; #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wfloat-equal" - return static_cast(typed_l) == static_cast(typed_r->data); + return static_cast(data_l) == static_cast(data_r); #pragma clang diagnostic pop }, r, @@ -1071,8 +1074,7 @@ namespace jank::runtime [](auto const typed_l, auto const r) -> object_ptr { return visit_number_like( [](auto const typed_r, auto const typed_l) -> object_ptr { - using C = std::common_type_tdata)>; - return make_box(std::min(static_cast(typed_l), static_cast(typed_r->data))); + return typed_l < typed_r->data ? make_box(typed_l) : make_box(typed_r->data); }, r, typed_l->data); @@ -1085,8 +1087,7 @@ namespace jank::runtime { return visit_number_like( [](auto const typed_r, auto const typed_l) -> object_ptr { - using C = std::common_type_tdata)>; - return make_box(std::min(static_cast(typed_l), static_cast(typed_r->data))); + return typed_l < typed_r->data ? make_box(typed_l) : make_box(typed_r->data); }, r, l->data); @@ -1096,8 +1097,7 @@ namespace jank::runtime { return visit_number_like( [](auto const typed_l, auto const typed_r) -> object_ptr { - using C = std::common_type_tdata), decltype(typed_r)>; - return make_box(std::min(static_cast(typed_l->data), static_cast(typed_r))); + return typed_l->data < typed_r ? make_box(typed_l->data) : make_box(typed_r); }, l, r->data); @@ -1117,8 +1117,9 @@ namespace jank::runtime { return visit_number_like( [](auto const typed_r, auto const typed_l) -> native_real { - using C = std::common_type_tdata)>; - return std::min(static_cast(typed_l), static_cast(typed_r->data)); + auto typed_r_data = to_number(typed_r->data); + using C = std::common_type_t; + return std::min(static_cast(typed_l), static_cast(typed_r_data)); }, r, l->data); @@ -1128,8 +1129,9 @@ namespace jank::runtime { return visit_number_like( [](auto const typed_l, auto const typed_r) -> native_real { - using C = std::common_type_tdata), decltype(typed_r)>; - return std::min(static_cast(typed_l->data), static_cast(typed_r)); + auto typed_l_data = to_number(typed_l->data); + using C = std::common_type_t; + return std::min(static_cast(typed_l_data), static_cast(typed_r)); }, l, r->data); @@ -1149,8 +1151,9 @@ namespace jank::runtime { return visit_number_like( [](auto const typed_l, auto const typed_r) -> native_real { - using C = std::common_type_tdata), decltype(typed_r)>; - return std::min(static_cast(typed_l->data), static_cast(typed_r)); + auto typed_l_data = to_number(typed_l->data); + using C = std::common_type_t; + return std::min(static_cast(typed_l_data), static_cast(typed_r)); }, l, r); @@ -1160,8 +1163,9 @@ namespace jank::runtime { return visit_number_like( [](auto const typed_r, auto const typed_l) -> native_real { - using C = std::common_type_tdata)>; - return std::min(static_cast(typed_l), static_cast(typed_r->data)); + auto typed_r_data = to_number(typed_r->data); + using C = std::common_type_t; + return std::min(static_cast(typed_r_data), static_cast(typed_l)); }, r, l); @@ -1186,8 +1190,7 @@ namespace jank::runtime { return visit_number_like( [](auto const typed_l, auto const typed_r) -> object_ptr { - using C = std::common_type_tdata), decltype(typed_r)>; - return make_box(std::min(static_cast(typed_l->data), static_cast(typed_r))); + return typed_l->data < typed_r ? make_box(typed_l) : make_box(typed_r); }, l, r); @@ -1197,8 +1200,7 @@ namespace jank::runtime { return visit_number_like( [](auto const typed_r, auto const typed_l) -> object_ptr { - using C = std::common_type_tdata)>; - return make_box(std::min(static_cast(typed_l), static_cast(typed_r->data))); + return typed_l < typed_r->data ? make_box(typed_l) : make_box(typed_r); }, r, l); @@ -1215,8 +1217,7 @@ namespace jank::runtime [](auto const typed_l, auto const r) -> object_ptr { return visit_number_like( [](auto const typed_r, auto const typed_l) -> object_ptr { - using C = std::common_type_tdata)>; - return make_box(std::max(static_cast(typed_l), static_cast(typed_r->data))); + return typed_r->data > typed_l ? make_box(typed_r) : make_box(typed_l); }, r, typed_l->data); @@ -1229,8 +1230,7 @@ namespace jank::runtime { return visit_number_like( [](auto const typed_r, auto const typed_l) -> object_ptr { - using C = std::common_type_tdata)>; - return make_box(std::max(static_cast(typed_l), static_cast(typed_r->data))); + return typed_l > typed_r->data ? make_box(typed_l) : make_box(typed_r); }, r, l->data); @@ -1240,8 +1240,7 @@ namespace jank::runtime { return visit_number_like( [](auto const typed_l, auto const typed_r) -> object_ptr { - using C = std::common_type_tdata), decltype(typed_r)>; - return make_box(std::max(static_cast(typed_l->data), static_cast(typed_r))); + return typed_l->data > typed_r ? make_box(typed_l) : make_box(typed_r); }, l, r->data); @@ -1261,8 +1260,9 @@ namespace jank::runtime { return visit_number_like( [](auto const typed_r, auto const typed_l) -> native_real { - using C = std::common_type_tdata)>; - return std::max(static_cast(typed_l), static_cast(typed_r->data)); + auto typed_r_data = to_number(typed_r->data); + using C = std::common_type_t; + return std::max(static_cast(typed_l), static_cast(typed_r_data)); }, r, l->data); @@ -1272,8 +1272,9 @@ namespace jank::runtime { return visit_number_like( [](auto const typed_l, auto const typed_r) -> native_real { - using C = std::common_type_tdata), decltype(typed_r)>; - return std::max(static_cast(typed_l->data), static_cast(typed_r)); + auto typed_l_data = to_number(typed_l->data); + using C = std::common_type_t; + return std::max(static_cast(typed_r), static_cast(typed_l_data)); }, l, r->data); @@ -1293,8 +1294,9 @@ namespace jank::runtime { return visit_number_like( [](auto const typed_l, auto const typed_r) -> native_real { - using C = std::common_type_tdata), decltype(typed_r)>; - return std::max(static_cast(typed_l->data), static_cast(typed_r)); + auto typed_l_data = to_number(typed_l->data); + using C = std::common_type_t; + return std::max(static_cast(typed_r), static_cast(typed_l_data)); }, l, r); @@ -1304,8 +1306,9 @@ namespace jank::runtime { return visit_number_like( [](auto const typed_r, auto const typed_l) -> native_real { - using C = std::common_type_tdata)>; - return std::max(static_cast(typed_l), static_cast(typed_r->data)); + auto typed_r_data = to_number(typed_r->data); + using C = std::common_type_t; + return std::max(static_cast(typed_l), static_cast(typed_r_data)); }, r, l); @@ -1330,8 +1333,7 @@ namespace jank::runtime { return visit_number_like( [](auto const typed_l, auto const typed_r) -> object_ptr { - using C = std::common_type_tdata), decltype(typed_r)>; - return make_box(std::max(static_cast(typed_l->data), static_cast(typed_r))); + return typed_l->data > typed_r ? make_box(typed_l) : make_box(typed_r); }, l, r); @@ -1341,8 +1343,7 @@ namespace jank::runtime { return visit_number_like( [](auto const typed_r, auto const typed_l) -> object_ptr { - using C = std::common_type_tdata)>; - return make_box(std::max(static_cast(typed_l), static_cast(typed_r->data))); + return typed_l > typed_r->data ? make_box(typed_l) : make_box(typed_r); }, r, l); @@ -1357,16 +1358,7 @@ namespace jank::runtime { return visit_number_like( [](auto const typed_l) -> object_ptr { - using T = typename decltype(typed_l)::value_type; - - if constexpr(std::is_same_v) - { - return make_box(std::abs(typed_l->data)); - } - if constexpr(std::is_same_v) - { - return make_box(std::fabs(typed_l->data)); - } + return typed_l->data < 0LL ? make_box(-1LL * typed_l->data) : make_box(typed_l->data); }, l); } @@ -1424,8 +1416,10 @@ namespace jank::runtime [](auto const typed_l, auto const r) -> native_real { return visit_number_like( [](auto const typed_r, auto const typed_l) -> native_real { - using C = std::common_type_tdata)>; - return std::pow(static_cast(typed_l), static_cast(typed_r->data)); + auto typed_r_data = to_number(typed_r->data); + auto typed_l_data = to_number(typed_l); + using C = std::common_type_t; + return std::pow(static_cast(typed_l_data), static_cast(typed_r_data)); }, r, typed_l->data); @@ -1438,8 +1432,10 @@ namespace jank::runtime { return visit_number_like( [](auto const typed_r, auto const typed_l) -> native_real { - using C = std::common_type_tdata)>; - return std::pow(static_cast(typed_l), static_cast(typed_r->data)); + auto typed_r_data = to_number(typed_r->data); + auto typed_l_data = to_number(typed_l); + using C = std::common_type_t; + return std::pow(static_cast(typed_l_data), static_cast(typed_r_data)); }, r, l->data); @@ -1449,8 +1445,9 @@ namespace jank::runtime { return visit_number_like( [](auto const typed_l, auto const typed_r) -> native_real { - using C = std::common_type_tdata), decltype(typed_r)>; - return std::pow(static_cast(typed_l->data), static_cast(typed_r)); + auto typed_l_data = to_number(typed_l->data); + using C = std::common_type_t; + return std::pow(static_cast(typed_l_data), static_cast(typed_r)); }, l, r->data); @@ -1470,8 +1467,9 @@ namespace jank::runtime { return visit_number_like( [](auto const typed_r, auto const typed_l) -> native_real { - using C = std::common_type_tdata)>; - return std::pow(static_cast(typed_l), static_cast(typed_r->data)); + auto typed_r_data = to_number(typed_r->data); + using C = std::common_type_t; + return std::pow(static_cast(typed_l), static_cast(typed_r_data)); }, r, l->data); @@ -1481,8 +1479,9 @@ namespace jank::runtime { return visit_number_like( [](auto const typed_l, auto const typed_r) -> native_real { - using C = std::common_type_tdata), decltype(typed_r)>; - return std::pow(static_cast(typed_l->data), static_cast(typed_r)); + auto typed_l_data = to_number(typed_l->data); + using C = std::common_type_t; + return std::pow(static_cast(typed_l_data), static_cast(typed_r)); }, l, r->data); @@ -1502,8 +1501,9 @@ namespace jank::runtime { return visit_number_like( [](auto const typed_l, auto const typed_r) -> native_real { - using C = std::common_type_tdata), decltype(typed_r)>; - return std::pow(static_cast(typed_l->data), static_cast(typed_r)); + auto typed_l_data = to_number(typed_l->data); + using C = std::common_type_t; + return std::pow(static_cast(typed_l_data), static_cast(typed_r)); }, l, r); @@ -1513,8 +1513,9 @@ namespace jank::runtime { return visit_number_like( [](auto const typed_r, auto const typed_l) -> native_real { - using C = std::common_type_tdata)>; - return std::pow(static_cast(typed_l), static_cast(typed_r->data)); + auto typed_r_data = to_number(typed_r->data); + using C = std::common_type_t; + return std::pow(static_cast(typed_l), static_cast(typed_r_data)); }, r, l); @@ -1539,8 +1540,9 @@ namespace jank::runtime { return visit_number_like( [](auto const typed_l, auto const typed_r) -> native_real { - using C = std::common_type_tdata), decltype(typed_r)>; - return std::pow(static_cast(typed_l->data), static_cast(typed_r)); + auto typed_l_data = to_number(typed_l->data); + using C = std::common_type_t; + return std::pow(static_cast(typed_l_data), static_cast(typed_r)); }, l, r); @@ -1550,8 +1552,9 @@ namespace jank::runtime { return visit_number_like( [](auto const typed_r, auto const typed_l) -> native_real { - using C = std::common_type_tdata)>; - return std::pow(static_cast(typed_l), static_cast(typed_r->data)); + auto typed_r_data = to_number(typed_r->data); + using C = std::common_type_t; + return std::pow(static_cast(typed_l), static_cast(typed_r_data)); }, r, l); diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/number.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/number.cpp index d5ab70b9e..55152b97c 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/number.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/number.cpp @@ -1,10 +1,8 @@ #include -#include -#include - #include #include +#include namespace jank::runtime { diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/ratio.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/ratio.cpp new file mode 100644 index 000000000..781722a29 --- /dev/null +++ b/compiler+runtime/src/cpp/jank/runtime/obj/ratio.cpp @@ -0,0 +1,556 @@ +#include +#include +#include + +namespace jank::runtime +{ + + constexpr native_real EPSILON = std::numeric_limits::epsilon(); + + obj::ratio_data::static_object(native_integer numerator, native_integer denominator) + : numerator{ numerator } + , denominator{ denominator } + { + if(denominator == 0) + { + throw std::invalid_argument("Ratio denominator cannot be zero."); + } + simplify(); + } + + object_ptr obj::ratio::create(native_integer const numerator, native_integer const denominator) + { + auto ratio_data = make_box(numerator, denominator); + if(ratio_data->denominator == 1) + { + return make_box(ratio_data->numerator); + } + auto r(make_box()); + r->data.numerator = ratio_data->numerator; + r->data.denominator = ratio_data->denominator; + return r; + } + + native_real obj::ratio_data::to_real() const + { + return static_cast(numerator) / denominator; + } + + native_real obj::ratio::to_real() const + { + return data.to_real(); + } + + native_integer obj::ratio::to_integer() const + { + return data.numerator / data.denominator; + } + + void obj::ratio_data::simplify() + { + int gcd = std::gcd(numerator, denominator); + numerator /= gcd; + denominator /= gcd; + + if(denominator < 0) + { + numerator = -1 * numerator; + denominator = -1 * denominator; + } + } + + void obj::ratio::to_string(fmt::memory_buffer &buff) const + { + format_to(std::back_inserter(buff), FMT_COMPILE("{}/{}"), data.numerator, data.denominator); + } + + native_persistent_string obj::ratio::to_string() const + { + fmt::memory_buffer buff; + to_string(buff); + return native_persistent_string{ buff.data(), buff.size() }; + } + + native_persistent_string obj::ratio::to_code_string() const + { + return to_string(); + } + + native_hash obj::ratio::to_hash() const + { + return hash::combine(hash::integer(data.numerator), hash::integer(data.denominator)); + } + + native_bool obj::ratio::equal(object const &o) const + { + if(o.type == object_type::integer) + { + auto const i(expect_object(&o)); + return this->data == i->data; + } + + if(o.type == object_type::real) + { + auto const i(expect_object(&o)); + return this->data == i->data; + } + + if(o.type == object_type::ratio) + { + return this == expect_object(&o).data; + } + + return false; + } + + native_integer obj::ratio::compare(object const &o) const + { + return visit_number_like( + [this](auto const typed_o) -> native_integer { + return (data > typed_o->data) - (data < typed_o->data); + }, + [&]() -> native_integer { + throw std::runtime_error{ fmt::format("not comparable: {}", runtime::to_string(&o)) }; + }, + &o); + } + + native_integer obj::ratio::compare(static_object const &o) const + { + return (data > o.data) - (data < o.data); + } + + object_ptr operator+(obj::ratio_data const l, obj::ratio_data const r) + { + native_integer denom = l.denominator * r.denominator; + native_integer num = l.numerator * r.denominator + r.numerator * l.denominator; + return obj::ratio::create(num, denom); + } + + obj::ratio_ptr operator+(obj::integer_ptr l, obj::ratio_data const r) + { + return expect_object(obj::ratio_data(l->data, 1LL) + r); + } + + obj::ratio_ptr operator+(obj::ratio_data const l, obj::integer_ptr r) + { + return r + l; + } + + native_real operator+(obj::real_ptr l, obj::ratio_data const r) + { + return l->data + r.to_real(); + } + + native_real operator+(obj::ratio_data const l, obj::real_ptr r) + { + return l.to_real() + r->data; + } + + native_real operator+(obj::ratio_data const l, native_real r) + { + return l.to_real() + r; + } + + native_real operator+(native_real l, obj::ratio_data const r) + { + return l + r.to_real(); + } + + obj::ratio_ptr operator+(obj::ratio_data const l, native_integer r) + { + return expect_object( + obj::ratio::create(l.numerator + r * l.denominator, l.denominator)); + } + + obj::ratio_ptr operator+(native_integer l, obj::ratio_data const r) + { + return r + l; + } + + object_ptr operator-(obj::ratio_data const l, obj::ratio_data const r) + { + native_integer denom = l.denominator * r.denominator; + native_integer num = l.numerator * r.denominator - r.numerator * l.denominator; + return obj::ratio::create(num, denom); + } + + obj::ratio_ptr operator-(obj::integer_ptr l, obj::ratio_data const r) + { + return expect_object( + obj::ratio::create(l->data * r.denominator - r.numerator, r.denominator)); + } + + obj::ratio_ptr operator-(obj::ratio_data const l, obj::integer_ptr r) + { + return expect_object( + obj::ratio::create(l.numerator - l.denominator * r->data, l.denominator)); + } + + native_real operator-(obj::real_ptr l, obj::ratio_data const r) + { + return l->data - r.to_real(); + } + + native_real operator-(obj::ratio_data const l, obj::real_ptr r) + { + return l.to_real() - r->data; + } + + native_real operator-(obj::ratio_data const l, native_real r) + { + return l.to_real() - r; + } + + native_real operator-(native_real l, obj::ratio_data const r) + { + return l - r.to_real(); + } + + obj::ratio_ptr operator-(obj::ratio_data const l, native_integer r) + { + return expect_object( + obj::ratio::create(l.numerator - r * l.denominator, l.denominator)); + } + + obj::ratio_ptr operator-(native_integer l, obj::ratio_data const r) + { + return expect_object( + obj::ratio::create(l * r.denominator - r.denominator, r.denominator)); + } + + object_ptr operator*(obj::ratio_data const l, obj::ratio_data const r) + { + return obj::ratio::create(l.numerator * r.numerator, l.denominator * r.denominator); + } + + object_ptr operator*(obj::integer_ptr l, obj::ratio_data const r) + { + return obj::ratio_data(l->data, 1LL) * r; + } + + object_ptr operator*(obj::ratio_data const l, obj::integer_ptr r) + { + return l * obj::ratio_data(r->data, 1LL); + } + + native_real operator*(obj::real_ptr l, obj::ratio_data const r) + { + return l->data * r.to_real(); + } + + native_real operator*(obj::ratio_data const l, obj::real_ptr r) + { + return l.to_real() * r->data; + } + + native_real operator*(obj::ratio_data const l, native_real r) + { + return l.to_real() * r; + } + + native_real operator*(native_real l, obj::ratio_data const r) + { + return l * r.to_real(); + } + + object_ptr operator*(obj::ratio_data const l, native_integer r) + { + return l * obj::ratio_data(r, 1LL); + } + + object_ptr operator*(native_integer l, obj::ratio_data const r) + { + return r * l; + } + + object_ptr operator/(obj::ratio_data const l, obj::ratio_data const r) + { + return obj::ratio::create(l.numerator * r.denominator, l.denominator * r.numerator); + } + + object_ptr operator/(obj::integer_ptr l, obj::ratio_data const r) + { + return obj::ratio_data(l->data, 1LL) / r; + } + + obj::ratio_ptr operator/(obj::ratio_data const l, obj::integer_ptr r) + { + return expect_object(l / obj::ratio_data(r->data, 1LL)); + } + + native_real operator/(obj::real_ptr l, obj::ratio_data const r) + { + return l->data / r.to_real(); + } + + native_real operator/(obj::ratio_data const l, obj::real_ptr r) + { + return l.to_real() / r->data; + } + + native_real operator/(obj::ratio_data const l, native_real r) + { + return l.to_real() / r; + } + + native_real operator/(native_real l, obj::ratio_data const r) + { + return l / r.to_real(); + } + + obj::ratio_ptr operator/(obj::ratio_data const l, native_integer r) + { + return l / make_box(r); + } + + object_ptr operator/(native_integer l, obj::ratio_data const r) + { + return obj::ratio_data(l, 1LL) / r; + } + + native_bool operator==(obj::ratio_data const l, obj::ratio_data const r) + { + return l.numerator == r.numerator && l.denominator == r.denominator; + } + + native_bool operator==(obj::integer_ptr l, obj::ratio_data const r) + { + return l->data * r.denominator == r.numerator; + } + + native_bool operator==(obj::ratio_data const l, obj::integer_ptr r) + { + return l.numerator == r->data * l.denominator; + } + + native_bool operator==(obj::real_ptr l, obj::ratio_data const r) + { + return std::fabs(l->data - r) < EPSILON; + } + + native_bool operator==(obj::ratio_data const l, obj::real_ptr r) + { + return r == l; + } + + native_bool operator==(obj::ratio_data const l, native_real r) + { + return std::fabs(l - r) < EPSILON; + } + + native_bool operator==(native_real l, obj::ratio_data const r) + { + return r == l; + } + + native_bool operator==(obj::ratio_data const l, native_integer r) + { + return l.numerator == r * l.denominator; + } + + native_bool operator==(native_integer l, obj::ratio_data const r) + { + return l * r.denominator == r.numerator; + } + + native_bool operator<(obj::ratio_data const l, obj::ratio_data const r) + { + return l.numerator * r.denominator < r.numerator * l.denominator; + } + + native_bool operator<=(obj::ratio_data const l, obj::ratio_data const r) + { + return l.numerator * r.denominator <= r.numerator * l.denominator; + } + + native_bool operator<(obj::integer_ptr l, obj::ratio_data const r) + { + return l->data * r.denominator < r.numerator; + } + + native_bool operator<(obj::ratio_data const l, obj::integer_ptr r) + { + return l.numerator < r->data * l.denominator; + } + + native_bool operator<=(obj::integer_ptr l, obj::ratio_data const r) + { + return l->data * r.denominator <= r.numerator; + } + + native_bool operator<=(obj::ratio_data const l, obj::integer_ptr r) + { + return l.numerator <= r->data * l.denominator; + } + + native_bool operator<(obj::real_ptr l, obj::ratio_data const r) + { + return l->data < r.to_real(); + } + + native_bool operator<(obj::ratio_data const l, obj::real_ptr r) + { + return l.to_real() < r->data; + } + + native_bool operator<=(obj::real_ptr l, obj::ratio_data const r) + { + return l->data <= r.to_real(); + } + + native_bool operator<=(obj::ratio_data const l, obj::real_ptr r) + { + return l.to_real() <= r->data; + } + + native_bool operator<(obj::ratio_data const l, native_real r) + { + return l.to_real() < r; + } + + native_bool operator<(native_real l, obj::ratio_data const r) + { + return l < r.to_real(); + } + + native_bool operator<=(obj::ratio_data const l, native_real r) + { + return l.to_real() <= r; + } + + native_bool operator<=(native_real l, obj::ratio_data const r) + { + return l <= r.to_real(); + } + + native_bool operator<(obj::ratio_data const l, native_integer r) + { + return l.numerator < r * l.denominator; + } + + native_bool operator<(native_integer l, obj::ratio_data const r) + { + return l * r.denominator < r.numerator; + } + + native_bool operator<=(obj::ratio_data const l, native_integer r) + { + return l.numerator <= r * l.denominator; + } + + native_bool operator<=(native_integer l, obj::ratio_data const r) + { + return l * r.denominator <= r.numerator; + } + + native_bool operator>(obj::ratio_data const l, obj::ratio_data const r) + { + return l.numerator * r.denominator > r.numerator * l.denominator; + } + + native_bool operator>(obj::integer_ptr l, obj::ratio_data const r) + { + return l->data * r.denominator > r.numerator; + } + + native_bool operator>(obj::ratio_data const l, obj::integer_ptr r) + { + return l.numerator > r->data * l.denominator; + } + + native_bool operator>(obj::real_ptr l, obj::ratio_data const r) + { + return l->data > r.to_real(); + } + + native_bool operator>(obj::ratio_data const l, obj::real_ptr r) + { + return l.to_real() > r->data; + } + + native_bool operator>(obj::ratio_data const l, native_real r) + { + return l.to_real() > r; + } + + native_bool operator>(native_real l, obj::ratio_data const r) + { + return l > r.to_real(); + } + + native_bool operator>(obj::ratio_data const l, native_integer r) + { + return l.numerator > r * l.denominator; + } + + native_bool operator>(native_integer l, obj::ratio_data const r) + { + return l * r.denominator > r.numerator; + } + + native_bool operator>=(obj::ratio_data const l, obj::ratio_data const r) + { + return l.numerator * r.denominator >= r.numerator * l.denominator; + } + + native_bool operator>=(obj::integer_ptr l, obj::ratio_data const r) + { + return l->data * r.denominator >= r.numerator; + } + + native_bool operator>=(obj::ratio_data const l, obj::integer_ptr r) + { + return l.numerator >= r->data * l.denominator; + } + + native_bool operator>=(obj::real_ptr l, obj::ratio_data const r) + { + return l->data >= r.to_real(); + } + + native_bool operator>=(obj::ratio_data const l, obj::real_ptr r) + { + return l.to_real() >= r->data; + } + + native_bool operator>=(obj::ratio_data const l, native_real r) + { + return l.to_real() >= r; + } + + native_bool operator>=(native_real l, obj::ratio_data const r) + { + return l >= r.to_real(); + } + + native_bool operator>=(obj::ratio_data const l, native_integer r) + { + return l.numerator >= r * l.denominator; + } + + native_bool operator>=(native_integer l, obj::ratio_data const r) + { + return l * r.denominator >= r.numerator; + } + + native_bool operator>(native_bool l, obj::ratio_data const r) + { + return (l ? 1LL : 0LL) > r; + } + + native_bool operator<(native_bool l, obj::ratio_data const r) + { + return (l ? 1LL : 0LL) < r; + } + + native_bool operator>(obj::ratio_data const l, native_bool r) + { + return l > (r ? 1LL : 0LL); + } + + native_bool operator<(obj::ratio_data const l, native_bool r) + { + return l < (r ? 1LL : 0LL); + } +} diff --git a/compiler+runtime/test/cpp/jank/read/parse.cpp b/compiler+runtime/test/cpp/jank/read/parse.cpp index 3cdfa9dbe..199f79d60 100644 --- a/compiler+runtime/test/cpp/jank/read/parse.cpp +++ b/compiler+runtime/test/cpp/jank/read/parse.cpp @@ -71,6 +71,7 @@ namespace jank::read::parse processor p{ lp.begin(), lp.end() }; auto const r(p.next()); CHECK(is_equiv(runtime::mul(r.expect_ok().unwrap().ptr, make_box(10)), make_box(8))); + CHECK(is_equiv(r.expect_ok().unwrap().ptr, obj::ratio::create(4, 5))); CHECK(r.expect_ok().unwrap().start == lex::token{ 0, @@ -87,6 +88,20 @@ namespace jank::read::parse auto const r(p.next()); CHECK(r.is_err()); } + SUBCASE("Parse into an integer") + { + lex::processor lp{ "4/2" }; + processor p{ lp.begin(), lp.end() }; + auto const r(p.next()); + CHECK(r.expect_ok().unwrap().start + == lex::token{ + 0, + 3, + lex::token_kind::ratio, + { .numerator = 4, .denominator = 2 } + }); + CHECK(equal(r.expect_ok().unwrap().ptr, make_box(2))); + } } TEST_CASE("Comments") diff --git a/compiler+runtime/test/cpp/jank/runtime/obj/ratio.cpp b/compiler+runtime/test/cpp/jank/runtime/obj/ratio.cpp new file mode 100644 index 000000000..6d32afec6 --- /dev/null +++ b/compiler+runtime/test/cpp/jank/runtime/obj/ratio.cpp @@ -0,0 +1,401 @@ +#include "jank/runtime/obj/ratio.hpp" +#include +#include + +namespace jank::runtime +{ + TEST_SUITE("ratio_data") + { + TEST_CASE("Ratio Constructor") + { + SUBCASE("Valid Ratio") + { + obj::ratio_data ratio{ 4, 6 }; + CHECK(ratio.numerator == 2); // Simplified + CHECK(ratio.denominator == 3); + } + SUBCASE("Invalid Denominator") + { + CHECK_THROWS_AS(obj::ratio_data(4, 0), std::invalid_argument); + } + } + + TEST_CASE("ToReal Conversion") + { + obj::ratio_data ratio{ 3, 4 }; + CHECK(ratio.to_real() == doctest::Approx(0.75)); + } + + TEST_CASE("Simplify Functionality") + { + obj::ratio_data ratio{ 10, -20 }; + CHECK(ratio.numerator == -1); + CHECK(ratio.denominator == 2); + } + + TEST_CASE("Create Ratio or Integer") + { + SUBCASE("Simplified to Integer") + { + auto ratio_ptr = obj::ratio::create(4, 2); + CHECK(ratio_ptr->type == object_type::integer); + REQUIRE(ratio_ptr != nullptr); + CHECK(expect_object(ratio_ptr)->data == 2); + } + SUBCASE("Remains as Ratio") + { + auto ratio_ptr = obj::ratio::create(3, 4); + auto ratio = expect_object(ratio_ptr); + REQUIRE(ratio != nullptr); + CHECK(ratio->data.numerator == 3); + CHECK(ratio->data.denominator == 4); + CHECK(ratio->to_real() == doctest::Approx(0.75)); + } + } + + TEST_CASE("Arithmetic Operations") + { + obj::ratio_data a{ 1, 2 }, b{ 1, 3 }; + + SUBCASE("Addition") + { + auto result = *expect_object(a + b); + CHECK(result.data.numerator == 5); + CHECK(result.data.denominator == 6); + } + SUBCASE("Subtraction") + { + auto result = *expect_object(a - b); + CHECK(result.data.numerator == 1); + CHECK(result.data.denominator == 6); + } + SUBCASE("Multiplication") + { + auto result = *expect_object(a * b); + CHECK(result.data.numerator == 1); + CHECK(result.data.denominator == 6); + } + + SUBCASE("Division") + { + auto result = *expect_object(a / b); + CHECK(result.data.numerator == 3); + CHECK(result.data.denominator == 2); + } + } + + TEST_CASE("Comparison Operations") + { + obj::ratio_data a{ 1, 2 }, b{ 2, 4 }, c{ 1, 3 }; + + SUBCASE("Equality") + { + CHECK(a == b); + CHECK_FALSE(a == c); + } + SUBCASE("Less Than") + { + CHECK(c < a); + CHECK_FALSE(a < b); + } + SUBCASE("Greater Than") + { + CHECK(a > c); + CHECK_FALSE(c > a); + } + } + + TEST_CASE("Edge Cases and Utility Functions") + { + obj::ratio_data ratio{ 6, -9 }; + + SUBCASE("Simplify on Negative Denominator") + { + CHECK(ratio.numerator == -2); + CHECK(ratio.denominator == 3); + } + SUBCASE("ToString") + { + auto ratio_ptr = obj::ratio::create(3, 4); + auto ratio = expect_object(ratio_ptr); + CHECK(ratio->to_string() == "3/4"); + } + SUBCASE("Hashing") + { + auto ratio1 = expect_object(obj::ratio::create(2, 3)); + auto ratio2 = expect_object(obj::ratio::create(2, 3)); + CHECK(ratio1->to_hash() == ratio2->to_hash()); + } + } + + TEST_CASE("Ratio Interaction with Other Data Types") + { + obj::ratio_data ratio{ 3, 4 }; + + SUBCASE("Addition with Native Integer") + { + auto native_int{ make_box(2LL) }; + auto result = *(ratio + native_int); + auto result2 = *(native_int + ratio); + CHECK(result.data.numerator == 11); + CHECK(result.data.denominator == 4); + CHECK(result2.data.numerator == 11); + CHECK(result2.data.denominator == 4); + } + SUBCASE("Addition with Native Real") + { + auto native_real{ make_box(0.5) }; + auto result = ratio + native_real; + auto result2 = native_real + ratio; + CHECK(result == doctest::Approx(1.25)); + CHECK(result2 == doctest::Approx(1.25)); + } + SUBCASE("Subtraction with Integer Pointer") + { + auto int_ptr = make_box(1); + auto result = ratio - int_ptr; + auto result2 = int_ptr - ratio; + CHECK(result->data.numerator == -1); + CHECK(result->data.denominator == 4); + CHECK(result2->data.numerator == 1); + CHECK(result2->data.denominator == 4); + } + + SUBCASE("Subtraction with Native Real") + { + auto native_real{ make_box(0.25) }; + auto result = ratio - native_real; + auto result2 = native_real - ratio; + CHECK(result == doctest::Approx(0.5)); + CHECK(result2 == doctest::Approx(-0.5)); + } + + SUBCASE("Multiplication with Integer Pointer") + { + auto int_ptr{ make_box(3) }; + auto result = *expect_object(ratio * int_ptr); + auto result2 = *expect_object(int_ptr * ratio); + CHECK(result.data.numerator == 9); + CHECK(result.data.denominator == 4); + CHECK(result2.data.numerator == 9); + CHECK(result2.data.denominator == 4); + } + + SUBCASE("Multiplication with Native Real") + { + auto native_real{ 0.5L }; + auto result = ratio * native_real; + auto result2 = native_real * ratio; + CHECK(result == doctest::Approx(0.375)); + CHECK(result2 == doctest::Approx(0.375)); + } + + SUBCASE("Division with Native Integer") + { + auto native_int{ 2LL }; + auto result = ratio / native_int; + auto result2 = expect_object(native_int / ratio); + CHECK(result->data.numerator == 3); + CHECK(result->data.denominator == 8); + CHECK(result2->data.numerator == 8); + CHECK(result2->data.denominator == 3); + } + + SUBCASE("Division with Native Real") + { + auto native_real{ 0.5L }; + auto result = ratio / native_real; + auto result2 = native_real / ratio; + CHECK(result == doctest::Approx(1.5)); + CHECK(result2 == doctest::Approx(1 / 1.5)); + } + + SUBCASE("Comparison with Integer Pointer") + { + auto int_ptr{ make_box(1LL) }; + CHECK(ratio < int_ptr); + CHECK(ratio != int_ptr); + CHECK(int_ptr > ratio); + CHECK(int_ptr != ratio); + } + + SUBCASE("Comparison with Native Integer") + { + auto native_int{ 1LL }; + CHECK(ratio < native_int); + CHECK(ratio != native_int); + CHECK(native_int > ratio); + CHECK(native_int != ratio); + } + + SUBCASE("Comparison with Native Real") + { + auto native_real{ 0.75L }; + CHECK(ratio == native_real); + CHECK(native_real == ratio); + } + } + + TEST_CASE("Ratio Mixed Arithmetic and Comparisons") + { + obj::ratio_data ratio{ 5, 8 }; + auto native_int{ 3LL }; + auto native_real{ 0.25L }; + + SUBCASE("Complex Arithmetic Chain") + { + auto result = (ratio + native_int)->data - native_real; + CHECK(result == doctest::Approx(3.375)); + } + + SUBCASE("Mixed Comparison") + { + auto real_ptr{ make_box(1.0L) }; + auto int_ptr{ make_box(1LL) }; + + CHECK(ratio < real_ptr); + CHECK(ratio < int_ptr); + CHECK(real_ptr > ratio); + CHECK(int_ptr > ratio); + } + } + + TEST_CASE("Edge Case Interactions") + { + SUBCASE("Ratio Divided by Zero") + { + auto result = obj::ratio_data(1, 2) / 0.0L; + CHECK(std::isinf(result)); + CHECK(result > 0); + CHECK(result == std::numeric_limits::infinity()); + + auto neg_result = expect_object(-1LL * obj::ratio_data(1, 2))->data / 0.0L; + CHECK(std::isinf(neg_result)); + CHECK(neg_result < 0); + CHECK(neg_result == -std::numeric_limits::infinity()); + + CHECK_THROWS_AS((obj::ratio_data(1, 2) / 0LL), std::invalid_argument); + CHECK_THROWS_AS((obj::ratio_data(1, 2) / obj::ratio_data(0, 1)), std::invalid_argument); + } + + SUBCASE("Ratio Multiplied by Negative Integer") + { + auto result = expect_object(obj::ratio_data(2, 3) * -4LL); + CHECK(result->data.numerator == -8); + CHECK(result->data.denominator == 3); + } + } + } + + TEST_SUITE("ratio") + { + obj::ratio_ptr make_ptr(native_integer num, native_integer denom) + { + auto r(make_box()); + r->data.numerator = num; + r->data.denominator = denom; + return r; + } + + TEST_CASE("constructor") + { + auto a = expect_object(obj::ratio::create(3, 4)); + CHECK(a->data.numerator == 3); + CHECK(a->data.denominator == 4); + } + + TEST_CASE("to_real") + { + auto a = make_ptr(3, 4); + CHECK(a->to_real() == 3.0 / 4.0); + } + + TEST_CASE("to_integer") + { + auto a = make_ptr(7, 4); + CHECK(a->to_integer() == 1); + } + + TEST_CASE("to_string") + { + auto a = make_ptr(3, 4); + CHECK(a->to_string() == "3/4"); + } + + + TEST_CASE("compare_less_than") + { + auto a = make_ptr(3, 4); + auto b = make_ptr(5, 4); + CHECK(a->compare(*b) < 0); + } + + TEST_CASE("compare_greater_than") + { + auto a = make_ptr(5, 4); + auto b = make_ptr(3, 4); + CHECK(a->compare(*b) > 0); + } + + TEST_CASE("compare_equal") + { + auto a = make_ptr(3, 4); + auto b = make_ptr(3, 4); + CHECK(a->compare(*b) == 0); + } + + TEST_CASE("is_zero") + { + CHECK(is_zero(make_ptr(0, 1))); + } + + TEST_CASE("is_positive") + { + obj::ratio; + CHECK(is_pos(make_ptr(3, 4))); + } + + TEST_CASE("is_negative") + { + CHECK(is_neg(make_ptr(-3, 4))); + } + + TEST_CASE("is_equivalent") + { + CHECK(is_equiv(make_ptr(3, 4), make_ptr(6, 8))); + } + + TEST_CASE("increment") + { + auto result = expect_object(inc(make_ptr(3, 4))); + CHECK(result->data.numerator == 7); + CHECK(result->data.denominator == 4); + } + + TEST_CASE("decrement") + { + auto result = expect_object(dec(make_ptr(3, 4))); + CHECK(result->data.numerator == -1); + CHECK(result->data.denominator == 4); + } + + TEST_CASE("abs") + { + auto result = expect_object(abs(make_ptr(-3, 4))); + CHECK(result->data.numerator == 3); + CHECK(result->data.denominator == 4); + } + + TEST_CASE("sqrt") + { + auto result = make_ptr(3, 4); + CHECK(sqrt(result) == doctest::Approx(std::sqrt(3.0 / 4.0))); + } + + TEST_CASE("pow") + { + auto a = make_ptr(3, 4); + CHECK(pow(a, a) == doctest::Approx(std::pow(3.0 / 4.0, 3.0 / 4.0))); + } + } +} From a421f444977bab44de70aaabc341fbda0ef850a4 Mon Sep 17 00:00:00 2001 From: Jianling Zhong Date: Tue, 26 Nov 2024 18:13:59 -0800 Subject: [PATCH 2/4] Address comments --- .../cpp/jank/runtime/core/make_box.hpp | 2 +- .../include/cpp/jank/runtime/obj/ratio.hpp | 49 +-- .../include/cpp/jank/runtime/object.hpp | 1 - .../src/cpp/jank/runtime/core/math.cpp | 46 +- .../src/cpp/jank/runtime/obj/ratio.cpp | 241 +++++------ .../test/cpp/jank/runtime/obj/ratio.cpp | 405 +++++++++--------- 6 files changed, 366 insertions(+), 378 deletions(-) diff --git a/compiler+runtime/include/cpp/jank/runtime/core/make_box.hpp b/compiler+runtime/include/cpp/jank/runtime/core/make_box.hpp index f99ad28d1..46de05698 100644 --- a/compiler+runtime/include/cpp/jank/runtime/core/make_box.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/core/make_box.hpp @@ -63,7 +63,7 @@ namespace jank::runtime [[gnu::always_inline, gnu::flatten, gnu::hot]] inline auto make_box(obj::ratio_data const r) { - return expect_object(obj::ratio::create(r.numerator, r.denominator)); + return make_box(r); } [[gnu::always_inline, gnu::flatten, gnu::hot]] diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/ratio.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/ratio.hpp index f01dca2ee..c883a70db 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/ratio.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/ratio.hpp @@ -2,25 +2,17 @@ namespace jank::runtime { - template <> - struct static_object : gc - { - static constexpr native_bool pointer_free{ true }; - static_object() = default; - static_object(static_object &&) = default; - static_object(static_object const &) = default; - static_object(native_integer const numerator, native_integer const denominator); - - native_real to_real() const; - void simplify(); - - native_integer numerator{}; - native_integer denominator{}; - }; - namespace obj { - using ratio_data = static_object; + struct ratio_data + { + ratio_data(native_integer const, native_integer const); + ratio_data(ratio_data const &); + native_real to_real() const; + native_integer to_integer() const; + native_integer numerator{}; + native_integer denominator{}; + }; } template <> @@ -31,8 +23,9 @@ namespace jank::runtime static_object() = default; static_object(static_object &&) = default; static_object(static_object const &) = default; + static_object(obj::ratio_data const &); - static object_ptr create(native_integer const numerator, native_integer const denominator); + static object_ptr create(native_integer const, native_integer const); /* behavior::object_like */ native_bool equal(object const &) const; native_persistent_string to_string() const; @@ -51,7 +44,7 @@ namespace jank::runtime native_real to_real() const; object base{ object_type::ratio }; - obj::ratio_data data{}; + obj::ratio_data data; }; namespace obj @@ -78,15 +71,6 @@ namespace jank::runtime native_real operator-(native_real l, obj::ratio_data r); obj::ratio_ptr operator-(obj::ratio_data l, native_integer r); obj::ratio_ptr operator-(native_integer l, obj::ratio_data r); - object_ptr operator/(obj::ratio_data l, obj::ratio_data r); - object_ptr operator/(obj::integer_ptr l, obj::ratio_data r); - obj::ratio_ptr operator/(obj::ratio_data l, obj::integer_ptr r); - native_real operator/(obj::real_ptr l, obj::ratio_data r); - native_real operator/(obj::ratio_data l, obj::real_ptr r); - native_real operator/(obj::ratio_data l, native_real r); - native_real operator/(native_real l, obj::ratio_data r); - obj::ratio_ptr operator/(obj::ratio_data l, native_integer r); - object_ptr operator/(native_integer l, obj::ratio_data r); object_ptr operator*(obj::ratio_data l, obj::ratio_data r); object_ptr operator*(obj::integer_ptr l, obj::ratio_data r); object_ptr operator*(obj::ratio_data l, obj::integer_ptr r); @@ -96,6 +80,15 @@ namespace jank::runtime native_real operator*(native_real l, obj::ratio_data r); object_ptr operator*(obj::ratio_data l, native_integer r); object_ptr operator*(native_integer l, obj::ratio_data r); + object_ptr operator/(obj::ratio_data l, obj::ratio_data r); + object_ptr operator/(obj::integer_ptr l, obj::ratio_data r); + obj::ratio_ptr operator/(obj::ratio_data l, obj::integer_ptr r); + native_real operator/(obj::real_ptr l, obj::ratio_data r); + native_real operator/(obj::ratio_data l, obj::real_ptr r); + native_real operator/(obj::ratio_data l, native_real r); + native_real operator/(native_real l, obj::ratio_data r); + obj::ratio_ptr operator/(obj::ratio_data l, native_integer r); + object_ptr operator/(native_integer l, obj::ratio_data r); native_bool operator==(obj::ratio_data l, obj::ratio_data r); native_bool operator==(obj::integer_ptr l, obj::ratio_data r); native_bool operator==(obj::ratio_data l, obj::integer_ptr r); diff --git a/compiler+runtime/include/cpp/jank/runtime/object.hpp b/compiler+runtime/include/cpp/jank/runtime/object.hpp index 7e83e6276..fbde946ce 100644 --- a/compiler+runtime/include/cpp/jank/runtime/object.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/object.hpp @@ -15,7 +15,6 @@ namespace jank::runtime integer, real, ratio, - ratio_data, persistent_string, persistent_string_sequence, diff --git a/compiler+runtime/src/cpp/jank/runtime/core/math.cpp b/compiler+runtime/src/cpp/jank/runtime/core/math.cpp index 5a050d181..49837e7cf 100644 --- a/compiler+runtime/src/cpp/jank/runtime/core/math.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/core/math.cpp @@ -531,8 +531,8 @@ namespace jank::runtime [](auto const typed_l, auto const r) -> object_ptr { return visit_number_like( [](auto const typed_r, auto const typed_l) -> object_ptr { - auto typed_l_data = to_number(typed_l); - auto typed_r_data = to_number(typed_r->data); + auto const typed_l_data{ to_number(typed_l) }; + auto const typed_r_data{ to_number(typed_r->data) }; return make_box(std::fmod(typed_l_data, typed_r_data)); }, r, @@ -618,8 +618,8 @@ namespace jank::runtime [](auto const typed_l, auto const r) -> native_bool { return visit_number_like( [](auto const typed_r, auto const typed_l) -> native_bool { - auto data_l = to_number(typed_l); - auto data_r = to_number(typed_r->data); + auto const data_l{ to_number(typed_l) }; + auto const data_r{ to_number(typed_r->data) }; using C = std::common_type_t; #pragma clang diagnostic push @@ -1117,7 +1117,7 @@ namespace jank::runtime { return visit_number_like( [](auto const typed_r, auto const typed_l) -> native_real { - auto typed_r_data = to_number(typed_r->data); + auto const typed_r_data{ to_number(typed_r->data) }; using C = std::common_type_t; return std::min(static_cast(typed_l), static_cast(typed_r_data)); }, @@ -1129,7 +1129,7 @@ namespace jank::runtime { return visit_number_like( [](auto const typed_l, auto const typed_r) -> native_real { - auto typed_l_data = to_number(typed_l->data); + auto const typed_l_data{ to_number(typed_l->data) }; using C = std::common_type_t; return std::min(static_cast(typed_l_data), static_cast(typed_r)); }, @@ -1151,7 +1151,7 @@ namespace jank::runtime { return visit_number_like( [](auto const typed_l, auto const typed_r) -> native_real { - auto typed_l_data = to_number(typed_l->data); + auto const typed_l_data{ to_number(typed_l->data) }; using C = std::common_type_t; return std::min(static_cast(typed_l_data), static_cast(typed_r)); }, @@ -1163,7 +1163,7 @@ namespace jank::runtime { return visit_number_like( [](auto const typed_r, auto const typed_l) -> native_real { - auto typed_r_data = to_number(typed_r->data); + auto const typed_r_data{ to_number(typed_r->data) }; using C = std::common_type_t; return std::min(static_cast(typed_r_data), static_cast(typed_l)); }, @@ -1260,7 +1260,7 @@ namespace jank::runtime { return visit_number_like( [](auto const typed_r, auto const typed_l) -> native_real { - auto typed_r_data = to_number(typed_r->data); + auto const typed_r_data{ to_number(typed_r->data) }; using C = std::common_type_t; return std::max(static_cast(typed_l), static_cast(typed_r_data)); }, @@ -1272,7 +1272,7 @@ namespace jank::runtime { return visit_number_like( [](auto const typed_l, auto const typed_r) -> native_real { - auto typed_l_data = to_number(typed_l->data); + auto const typed_l_data{ to_number(typed_l->data) }; using C = std::common_type_t; return std::max(static_cast(typed_r), static_cast(typed_l_data)); }, @@ -1294,7 +1294,7 @@ namespace jank::runtime { return visit_number_like( [](auto const typed_l, auto const typed_r) -> native_real { - auto typed_l_data = to_number(typed_l->data); + auto const typed_l_data{ to_number(typed_l->data) }; using C = std::common_type_t; return std::max(static_cast(typed_r), static_cast(typed_l_data)); }, @@ -1306,7 +1306,7 @@ namespace jank::runtime { return visit_number_like( [](auto const typed_r, auto const typed_l) -> native_real { - auto typed_r_data = to_number(typed_r->data); + auto const typed_r_data{ to_number(typed_r->data) }; using C = std::common_type_t; return std::max(static_cast(typed_l), static_cast(typed_r_data)); }, @@ -1416,8 +1416,8 @@ namespace jank::runtime [](auto const typed_l, auto const r) -> native_real { return visit_number_like( [](auto const typed_r, auto const typed_l) -> native_real { - auto typed_r_data = to_number(typed_r->data); - auto typed_l_data = to_number(typed_l); + auto const typed_r_data{ to_number(typed_r->data) }; + auto const typed_l_data{ to_number(typed_l) }; using C = std::common_type_t; return std::pow(static_cast(typed_l_data), static_cast(typed_r_data)); }, @@ -1432,8 +1432,8 @@ namespace jank::runtime { return visit_number_like( [](auto const typed_r, auto const typed_l) -> native_real { - auto typed_r_data = to_number(typed_r->data); - auto typed_l_data = to_number(typed_l); + auto const typed_r_data{ to_number(typed_r->data) }; + auto const typed_l_data{ to_number(typed_l) }; using C = std::common_type_t; return std::pow(static_cast(typed_l_data), static_cast(typed_r_data)); }, @@ -1445,7 +1445,7 @@ namespace jank::runtime { return visit_number_like( [](auto const typed_l, auto const typed_r) -> native_real { - auto typed_l_data = to_number(typed_l->data); + auto const typed_l_data{ to_number(typed_l->data) }; using C = std::common_type_t; return std::pow(static_cast(typed_l_data), static_cast(typed_r)); }, @@ -1467,7 +1467,7 @@ namespace jank::runtime { return visit_number_like( [](auto const typed_r, auto const typed_l) -> native_real { - auto typed_r_data = to_number(typed_r->data); + auto const typed_r_data{ to_number(typed_r->data) }; using C = std::common_type_t; return std::pow(static_cast(typed_l), static_cast(typed_r_data)); }, @@ -1479,7 +1479,7 @@ namespace jank::runtime { return visit_number_like( [](auto const typed_l, auto const typed_r) -> native_real { - auto typed_l_data = to_number(typed_l->data); + auto const typed_l_data{ to_number(typed_l->data) }; using C = std::common_type_t; return std::pow(static_cast(typed_l_data), static_cast(typed_r)); }, @@ -1501,7 +1501,7 @@ namespace jank::runtime { return visit_number_like( [](auto const typed_l, auto const typed_r) -> native_real { - auto typed_l_data = to_number(typed_l->data); + auto const typed_l_data{ to_number(typed_l->data) }; using C = std::common_type_t; return std::pow(static_cast(typed_l_data), static_cast(typed_r)); }, @@ -1513,7 +1513,7 @@ namespace jank::runtime { return visit_number_like( [](auto const typed_r, auto const typed_l) -> native_real { - auto typed_r_data = to_number(typed_r->data); + auto const typed_r_data{ to_number(typed_r->data) }; using C = std::common_type_t; return std::pow(static_cast(typed_l), static_cast(typed_r_data)); }, @@ -1540,7 +1540,7 @@ namespace jank::runtime { return visit_number_like( [](auto const typed_l, auto const typed_r) -> native_real { - auto typed_l_data = to_number(typed_l->data); + auto const typed_l_data{ to_number(typed_l->data) }; using C = std::common_type_t; return std::pow(static_cast(typed_l_data), static_cast(typed_r)); }, @@ -1552,7 +1552,7 @@ namespace jank::runtime { return visit_number_like( [](auto const typed_r, auto const typed_l) -> native_real { - auto typed_r_data = to_number(typed_r->data); + auto const typed_r_data{ to_number(typed_r->data) }; using C = std::common_type_t; return std::pow(static_cast(typed_l), static_cast(typed_r_data)); }, diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/ratio.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/ratio.cpp index 781722a29..39624e8a0 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/ratio.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/ratio.cpp @@ -5,9 +5,9 @@ namespace jank::runtime { - constexpr native_real EPSILON = std::numeric_limits::epsilon(); + static constexpr auto epsilon{ std::numeric_limits::epsilon() }; - obj::ratio_data::static_object(native_integer numerator, native_integer denominator) + obj::ratio_data::ratio_data(native_integer const numerator, native_integer const denominator) : numerator{ numerator } , denominator{ denominator } { @@ -15,20 +15,36 @@ namespace jank::runtime { throw std::invalid_argument("Ratio denominator cannot be zero."); } - simplify(); + auto const gcd{ std::gcd(numerator, denominator) }; + this->numerator /= gcd; + this->denominator /= gcd; + + if(denominator < 0) + { + this->numerator = -1 * this->numerator; + this->denominator = -1 * this->denominator; + } + } + + obj::ratio_data::ratio_data(obj::ratio_data const &data) + : numerator{ data.numerator } + , denominator{ data.denominator } + { + } + + obj::ratio::static_object(obj::ratio_data const &data) + : data{ data } + { } object_ptr obj::ratio::create(native_integer const numerator, native_integer const denominator) { - auto ratio_data = make_box(numerator, denominator); - if(ratio_data->denominator == 1) + obj::ratio_data data{ numerator, denominator }; + if(data.denominator == 1) { - return make_box(ratio_data->numerator); + return make_box(data.numerator); } - auto r(make_box()); - r->data.numerator = ratio_data->numerator; - r->data.denominator = ratio_data->denominator; - return r; + return make_box(data); } native_real obj::ratio_data::to_real() const @@ -36,27 +52,19 @@ namespace jank::runtime return static_cast(numerator) / denominator; } - native_real obj::ratio::to_real() const + native_integer obj::ratio_data::to_integer() const { - return data.to_real(); + return numerator / denominator; } - native_integer obj::ratio::to_integer() const + native_real obj::ratio::to_real() const { - return data.numerator / data.denominator; + return data.to_real(); } - void obj::ratio_data::simplify() + native_integer obj::ratio::to_integer() const { - int gcd = std::gcd(numerator, denominator); - numerator /= gcd; - denominator /= gcd; - - if(denominator < 0) - { - numerator = -1 * numerator; - denominator = -1 * denominator; - } + return data.to_integer(); } void obj::ratio::to_string(fmt::memory_buffer &buff) const @@ -85,19 +93,17 @@ namespace jank::runtime { if(o.type == object_type::integer) { - auto const i(expect_object(&o)); - return this->data == i->data; + return data == expect_object(&o)->data; } if(o.type == object_type::real) { - auto const i(expect_object(&o)); - return this->data == i->data; + return data == expect_object(&o)->data; } if(o.type == object_type::ratio) { - return this == expect_object(&o).data; + return data == expect_object(&o)->data; } return false; @@ -122,101 +128,96 @@ namespace jank::runtime object_ptr operator+(obj::ratio_data const l, obj::ratio_data const r) { - native_integer denom = l.denominator * r.denominator; - native_integer num = l.numerator * r.denominator + r.numerator * l.denominator; + auto const denom{ l.denominator * r.denominator }; + auto const num{ l.numerator * r.denominator + r.numerator * l.denominator }; return obj::ratio::create(num, denom); } - obj::ratio_ptr operator+(obj::integer_ptr l, obj::ratio_data const r) + obj::ratio_ptr operator+(obj::integer_ptr const l, obj::ratio_data const r) { - return expect_object(obj::ratio_data(l->data, 1LL) + r); + return l->data + r; } - obj::ratio_ptr operator+(obj::ratio_data const l, obj::integer_ptr r) + obj::ratio_ptr operator+(obj::ratio_data const l, obj::integer_ptr const r) { return r + l; } - native_real operator+(obj::real_ptr l, obj::ratio_data const r) + native_real operator+(obj::real_ptr const l, obj::ratio_data const r) { return l->data + r.to_real(); } - native_real operator+(obj::ratio_data const l, obj::real_ptr r) + native_real operator+(obj::ratio_data const l, obj::real_ptr const r) { return l.to_real() + r->data; } - native_real operator+(obj::ratio_data const l, native_real r) + native_real operator+(obj::ratio_data const l, native_real const r) { return l.to_real() + r; } - native_real operator+(native_real l, obj::ratio_data const r) + native_real operator+(native_real const l, obj::ratio_data const r) { return l + r.to_real(); } - obj::ratio_ptr operator+(obj::ratio_data const l, native_integer r) + obj::ratio_ptr operator+(obj::ratio_data const l, native_integer const r) { - return expect_object( - obj::ratio::create(l.numerator + r * l.denominator, l.denominator)); + return make_box(obj::ratio_data(l.numerator + r * l.denominator, l.denominator)); } - obj::ratio_ptr operator+(native_integer l, obj::ratio_data const r) + obj::ratio_ptr operator+(native_integer const l, obj::ratio_data const r) { return r + l; } object_ptr operator-(obj::ratio_data const l, obj::ratio_data const r) { - native_integer denom = l.denominator * r.denominator; - native_integer num = l.numerator * r.denominator - r.numerator * l.denominator; + auto const denom{ l.denominator * r.denominator }; + auto const num{ l.numerator * r.denominator - r.numerator * l.denominator }; return obj::ratio::create(num, denom); } - obj::ratio_ptr operator-(obj::integer_ptr l, obj::ratio_data const r) + obj::ratio_ptr operator-(obj::integer_ptr const l, obj::ratio_data const r) { - return expect_object( - obj::ratio::create(l->data * r.denominator - r.numerator, r.denominator)); + return l->data - r; } - obj::ratio_ptr operator-(obj::ratio_data const l, obj::integer_ptr r) + obj::ratio_ptr operator-(obj::ratio_data const l, obj::integer_ptr const r) { - return expect_object( - obj::ratio::create(l.numerator - l.denominator * r->data, l.denominator)); + return l - r->data; } - native_real operator-(obj::real_ptr l, obj::ratio_data const r) + native_real operator-(obj::real_ptr const l, obj::ratio_data const r) { return l->data - r.to_real(); } - native_real operator-(obj::ratio_data const l, obj::real_ptr r) + native_real operator-(obj::ratio_data const l, obj::real_ptr const r) { return l.to_real() - r->data; } - native_real operator-(obj::ratio_data const l, native_real r) + native_real operator-(obj::ratio_data const l, native_real const r) { return l.to_real() - r; } - native_real operator-(native_real l, obj::ratio_data const r) + native_real operator-(native_real const l, obj::ratio_data const r) { return l - r.to_real(); } - obj::ratio_ptr operator-(obj::ratio_data const l, native_integer r) + obj::ratio_ptr operator-(obj::ratio_data const l, native_integer const r) { - return expect_object( - obj::ratio::create(l.numerator - r * l.denominator, l.denominator)); + return make_box(obj::ratio_data(l.numerator - r * l.denominator, l.denominator)); } - obj::ratio_ptr operator-(native_integer l, obj::ratio_data const r) + obj::ratio_ptr operator-(native_integer const l, obj::ratio_data const r) { - return expect_object( - obj::ratio::create(l * r.denominator - r.denominator, r.denominator)); + return make_box(obj::ratio_data(l * r.denominator - r.denominator, r.denominator)); } object_ptr operator*(obj::ratio_data const l, obj::ratio_data const r) @@ -224,42 +225,42 @@ namespace jank::runtime return obj::ratio::create(l.numerator * r.numerator, l.denominator * r.denominator); } - object_ptr operator*(obj::integer_ptr l, obj::ratio_data const r) + object_ptr operator*(obj::integer_ptr const l, obj::ratio_data const r) { return obj::ratio_data(l->data, 1LL) * r; } - object_ptr operator*(obj::ratio_data const l, obj::integer_ptr r) + object_ptr operator*(obj::ratio_data const l, obj::integer_ptr const r) { return l * obj::ratio_data(r->data, 1LL); } - native_real operator*(obj::real_ptr l, obj::ratio_data const r) + native_real operator*(obj::real_ptr const l, obj::ratio_data const r) { return l->data * r.to_real(); } - native_real operator*(obj::ratio_data const l, obj::real_ptr r) + native_real operator*(obj::ratio_data const l, obj::real_ptr const r) { return l.to_real() * r->data; } - native_real operator*(obj::ratio_data const l, native_real r) + native_real operator*(obj::ratio_data const l, native_real const r) { return l.to_real() * r; } - native_real operator*(native_real l, obj::ratio_data const r) + native_real operator*(native_real const l, obj::ratio_data const r) { return l * r.to_real(); } - object_ptr operator*(obj::ratio_data const l, native_integer r) + object_ptr operator*(obj::ratio_data const l, native_integer const r) { return l * obj::ratio_data(r, 1LL); } - object_ptr operator*(native_integer l, obj::ratio_data const r) + object_ptr operator*(native_integer const l, obj::ratio_data const r) { return r * l; } @@ -269,42 +270,42 @@ namespace jank::runtime return obj::ratio::create(l.numerator * r.denominator, l.denominator * r.numerator); } - object_ptr operator/(obj::integer_ptr l, obj::ratio_data const r) + object_ptr operator/(obj::integer_ptr const l, obj::ratio_data const r) { return obj::ratio_data(l->data, 1LL) / r; } - obj::ratio_ptr operator/(obj::ratio_data const l, obj::integer_ptr r) + obj::ratio_ptr operator/(obj::ratio_data const l, obj::integer_ptr const r) { - return expect_object(l / obj::ratio_data(r->data, 1LL)); + return l / r->data; } - native_real operator/(obj::real_ptr l, obj::ratio_data const r) + native_real operator/(obj::real_ptr const l, obj::ratio_data const r) { return l->data / r.to_real(); } - native_real operator/(obj::ratio_data const l, obj::real_ptr r) + native_real operator/(obj::ratio_data const l, obj::real_ptr const r) { return l.to_real() / r->data; } - native_real operator/(obj::ratio_data const l, native_real r) + native_real operator/(obj::ratio_data const l, native_real const r) { return l.to_real() / r; } - native_real operator/(native_real l, obj::ratio_data const r) + native_real operator/(native_real const l, obj::ratio_data const r) { return l / r.to_real(); } - obj::ratio_ptr operator/(obj::ratio_data const l, native_integer r) + obj::ratio_ptr operator/(obj::ratio_data const l, native_integer const r) { - return l / make_box(r); + return make_box(obj::ratio_data(l.numerator, l.denominator * r)); } - object_ptr operator/(native_integer l, obj::ratio_data const r) + object_ptr operator/(native_integer const l, obj::ratio_data const r) { return obj::ratio_data(l, 1LL) / r; } @@ -314,42 +315,42 @@ namespace jank::runtime return l.numerator == r.numerator && l.denominator == r.denominator; } - native_bool operator==(obj::integer_ptr l, obj::ratio_data const r) + native_bool operator==(obj::integer_ptr const l, obj::ratio_data const r) { return l->data * r.denominator == r.numerator; } - native_bool operator==(obj::ratio_data const l, obj::integer_ptr r) + native_bool operator==(obj::ratio_data const l, obj::integer_ptr const r) { return l.numerator == r->data * l.denominator; } - native_bool operator==(obj::real_ptr l, obj::ratio_data const r) + native_bool operator==(obj::real_ptr const l, obj::ratio_data const r) { - return std::fabs(l->data - r) < EPSILON; + return std::fabs(l->data - r) < epsilon; } - native_bool operator==(obj::ratio_data const l, obj::real_ptr r) + native_bool operator==(obj::ratio_data const l, obj::real_ptr const r) { return r == l; } - native_bool operator==(obj::ratio_data const l, native_real r) + native_bool operator==(obj::ratio_data const l, native_real const r) { - return std::fabs(l - r) < EPSILON; + return std::fabs(l - r) < epsilon; } - native_bool operator==(native_real l, obj::ratio_data const r) + native_bool operator==(native_real const l, obj::ratio_data const r) { return r == l; } - native_bool operator==(obj::ratio_data const l, native_integer r) + native_bool operator==(obj::ratio_data const l, native_integer const r) { return l.numerator == r * l.denominator; } - native_bool operator==(native_integer l, obj::ratio_data const r) + native_bool operator==(native_integer const l, obj::ratio_data const r) { return l * r.denominator == r.numerator; } @@ -364,82 +365,82 @@ namespace jank::runtime return l.numerator * r.denominator <= r.numerator * l.denominator; } - native_bool operator<(obj::integer_ptr l, obj::ratio_data const r) + native_bool operator<(obj::integer_ptr const l, obj::ratio_data const r) { return l->data * r.denominator < r.numerator; } - native_bool operator<(obj::ratio_data const l, obj::integer_ptr r) + native_bool operator<(obj::ratio_data const l, obj::integer_ptr const r) { return l.numerator < r->data * l.denominator; } - native_bool operator<=(obj::integer_ptr l, obj::ratio_data const r) + native_bool operator<=(obj::integer_ptr const l, obj::ratio_data const r) { return l->data * r.denominator <= r.numerator; } - native_bool operator<=(obj::ratio_data const l, obj::integer_ptr r) + native_bool operator<=(obj::ratio_data const l, obj::integer_ptr const r) { return l.numerator <= r->data * l.denominator; } - native_bool operator<(obj::real_ptr l, obj::ratio_data const r) + native_bool operator<(obj::real_ptr const l, obj::ratio_data const r) { return l->data < r.to_real(); } - native_bool operator<(obj::ratio_data const l, obj::real_ptr r) + native_bool operator<(obj::ratio_data const l, obj::real_ptr const r) { return l.to_real() < r->data; } - native_bool operator<=(obj::real_ptr l, obj::ratio_data const r) + native_bool operator<=(obj::real_ptr const l, obj::ratio_data const r) { return l->data <= r.to_real(); } - native_bool operator<=(obj::ratio_data const l, obj::real_ptr r) + native_bool operator<=(obj::ratio_data const l, obj::real_ptr const r) { return l.to_real() <= r->data; } - native_bool operator<(obj::ratio_data const l, native_real r) + native_bool operator<(obj::ratio_data const l, native_real const r) { return l.to_real() < r; } - native_bool operator<(native_real l, obj::ratio_data const r) + native_bool operator<(native_real const l, obj::ratio_data const r) { return l < r.to_real(); } - native_bool operator<=(obj::ratio_data const l, native_real r) + native_bool operator<=(obj::ratio_data const l, native_real const r) { return l.to_real() <= r; } - native_bool operator<=(native_real l, obj::ratio_data const r) + native_bool operator<=(native_real const l, obj::ratio_data const r) { return l <= r.to_real(); } - native_bool operator<(obj::ratio_data const l, native_integer r) + native_bool operator<(obj::ratio_data const l, native_integer const r) { return l.numerator < r * l.denominator; } - native_bool operator<(native_integer l, obj::ratio_data const r) + native_bool operator<(native_integer const l, obj::ratio_data const r) { return l * r.denominator < r.numerator; } - native_bool operator<=(obj::ratio_data const l, native_integer r) + native_bool operator<=(obj::ratio_data const l, native_integer const r) { return l.numerator <= r * l.denominator; } - native_bool operator<=(native_integer l, obj::ratio_data const r) + native_bool operator<=(native_integer const l, obj::ratio_data const r) { return l * r.denominator <= r.numerator; } @@ -449,42 +450,42 @@ namespace jank::runtime return l.numerator * r.denominator > r.numerator * l.denominator; } - native_bool operator>(obj::integer_ptr l, obj::ratio_data const r) + native_bool operator>(obj::integer_ptr const l, obj::ratio_data const r) { return l->data * r.denominator > r.numerator; } - native_bool operator>(obj::ratio_data const l, obj::integer_ptr r) + native_bool operator>(obj::ratio_data const l, obj::integer_ptr const r) { return l.numerator > r->data * l.denominator; } - native_bool operator>(obj::real_ptr l, obj::ratio_data const r) + native_bool operator>(obj::real_ptr const l, obj::ratio_data const r) { return l->data > r.to_real(); } - native_bool operator>(obj::ratio_data const l, obj::real_ptr r) + native_bool operator>(obj::ratio_data const l, obj::real_ptr const r) { return l.to_real() > r->data; } - native_bool operator>(obj::ratio_data const l, native_real r) + native_bool operator>(obj::ratio_data const l, native_real const r) { return l.to_real() > r; } - native_bool operator>(native_real l, obj::ratio_data const r) + native_bool operator>(native_real const l, obj::ratio_data const r) { return l > r.to_real(); } - native_bool operator>(obj::ratio_data const l, native_integer r) + native_bool operator>(obj::ratio_data const l, native_integer const r) { return l.numerator > r * l.denominator; } - native_bool operator>(native_integer l, obj::ratio_data const r) + native_bool operator>(native_integer const l, obj::ratio_data const r) { return l * r.denominator > r.numerator; } @@ -494,42 +495,42 @@ namespace jank::runtime return l.numerator * r.denominator >= r.numerator * l.denominator; } - native_bool operator>=(obj::integer_ptr l, obj::ratio_data const r) + native_bool operator>=(obj::integer_ptr const l, obj::ratio_data const r) { return l->data * r.denominator >= r.numerator; } - native_bool operator>=(obj::ratio_data const l, obj::integer_ptr r) + native_bool operator>=(obj::ratio_data const l, obj::integer_ptr const r) { return l.numerator >= r->data * l.denominator; } - native_bool operator>=(obj::real_ptr l, obj::ratio_data const r) + native_bool operator>=(obj::real_ptr const l, obj::ratio_data const r) { return l->data >= r.to_real(); } - native_bool operator>=(obj::ratio_data const l, obj::real_ptr r) + native_bool operator>=(obj::ratio_data const l, obj::real_ptr const r) { return l.to_real() >= r->data; } - native_bool operator>=(obj::ratio_data const l, native_real r) + native_bool operator>=(obj::ratio_data const l, native_real const r) { return l.to_real() >= r; } - native_bool operator>=(native_real l, obj::ratio_data const r) + native_bool operator>=(native_real const l, obj::ratio_data const r) { return l >= r.to_real(); } - native_bool operator>=(obj::ratio_data const l, native_integer r) + native_bool operator>=(obj::ratio_data const l, native_integer const r) { return l.numerator >= r * l.denominator; } - native_bool operator>=(native_integer l, obj::ratio_data const r) + native_bool operator>=(native_integer const l, obj::ratio_data const r) { return l * r.denominator >= r.numerator; } diff --git a/compiler+runtime/test/cpp/jank/runtime/obj/ratio.cpp b/compiler+runtime/test/cpp/jank/runtime/obj/ratio.cpp index 6d32afec6..163b71fd0 100644 --- a/compiler+runtime/test/cpp/jank/runtime/obj/ratio.cpp +++ b/compiler+runtime/test/cpp/jank/runtime/obj/ratio.cpp @@ -1,18 +1,20 @@ -#include "jank/runtime/obj/ratio.hpp" -#include #include +#include + +/* This must go last; doctest and glog both define CHECK and family. */ +#include namespace jank::runtime { - TEST_SUITE("ratio_data") + TEST_SUITE("ratio") { TEST_CASE("Ratio Constructor") { SUBCASE("Valid Ratio") { obj::ratio_data ratio{ 4, 6 }; - CHECK(ratio.numerator == 2); // Simplified - CHECK(ratio.denominator == 3); + CHECK_EQ(ratio.numerator, 2); // Simplified + CHECK_EQ(ratio.denominator, 3); } SUBCASE("Invalid Denominator") { @@ -23,33 +25,33 @@ namespace jank::runtime TEST_CASE("ToReal Conversion") { obj::ratio_data ratio{ 3, 4 }; - CHECK(ratio.to_real() == doctest::Approx(0.75)); + CHECK_EQ(ratio.to_real(), doctest::Approx(0.75)); } TEST_CASE("Simplify Functionality") { obj::ratio_data ratio{ 10, -20 }; - CHECK(ratio.numerator == -1); - CHECK(ratio.denominator == 2); + CHECK_EQ(ratio.numerator, -1); + CHECK_EQ(ratio.denominator, 2); } TEST_CASE("Create Ratio or Integer") { SUBCASE("Simplified to Integer") { - auto ratio_ptr = obj::ratio::create(4, 2); - CHECK(ratio_ptr->type == object_type::integer); + auto const ratio_ptr{ obj::ratio::create(4, 2) }; + CHECK_EQ(ratio_ptr->type, object_type::integer); REQUIRE(ratio_ptr != nullptr); - CHECK(expect_object(ratio_ptr)->data == 2); + CHECK_EQ(expect_object(ratio_ptr)->data, 2); } SUBCASE("Remains as Ratio") { - auto ratio_ptr = obj::ratio::create(3, 4); - auto ratio = expect_object(ratio_ptr); + auto const ratio_ptr{ obj::ratio::create(3, 4) }; + auto const ratio{ expect_object(ratio_ptr) }; REQUIRE(ratio != nullptr); - CHECK(ratio->data.numerator == 3); - CHECK(ratio->data.denominator == 4); - CHECK(ratio->to_real() == doctest::Approx(0.75)); + CHECK_EQ(ratio->data.numerator, 3); + CHECK_EQ(ratio->data.denominator, 4); + CHECK_EQ(ratio->to_real(), doctest::Approx(0.75)); } } @@ -59,28 +61,28 @@ namespace jank::runtime SUBCASE("Addition") { - auto result = *expect_object(a + b); - CHECK(result.data.numerator == 5); - CHECK(result.data.denominator == 6); + auto const result{ *expect_object(a + b) }; + CHECK_EQ(result.data.numerator, 5); + CHECK_EQ(result.data.denominator, 6); } SUBCASE("Subtraction") { - auto result = *expect_object(a - b); - CHECK(result.data.numerator == 1); - CHECK(result.data.denominator == 6); + auto const result{ *expect_object(a - b) }; + CHECK_EQ(result.data.numerator, 1); + CHECK_EQ(result.data.denominator, 6); } SUBCASE("Multiplication") { - auto result = *expect_object(a * b); - CHECK(result.data.numerator == 1); - CHECK(result.data.denominator == 6); + auto const result{ *expect_object(a * b) }; + CHECK_EQ(result.data.numerator, 1); + CHECK_EQ(result.data.denominator, 6); } SUBCASE("Division") { - auto result = *expect_object(a / b); - CHECK(result.data.numerator == 3); - CHECK(result.data.denominator == 2); + auto const result{ *expect_object(a / b) }; + CHECK_EQ(result.data.numerator, 3); + CHECK_EQ(result.data.denominator, 2); } } @@ -91,7 +93,7 @@ namespace jank::runtime SUBCASE("Equality") { CHECK(a == b); - CHECK_FALSE(a == c); + CHECK(a != c); } SUBCASE("Less Than") { @@ -111,20 +113,20 @@ namespace jank::runtime SUBCASE("Simplify on Negative Denominator") { - CHECK(ratio.numerator == -2); - CHECK(ratio.denominator == 3); + CHECK_EQ(ratio.numerator, -2); + CHECK_EQ(ratio.denominator, 3); } SUBCASE("ToString") { - auto ratio_ptr = obj::ratio::create(3, 4); - auto ratio = expect_object(ratio_ptr); - CHECK(ratio->to_string() == "3/4"); + auto const ratio_ptr{ obj::ratio::create(3, 4) }; + auto const ratio{ expect_object(ratio_ptr) }; + CHECK_EQ(ratio->to_string(), "3/4"); } SUBCASE("Hashing") { - auto ratio1 = expect_object(obj::ratio::create(2, 3)); - auto ratio2 = expect_object(obj::ratio::create(2, 3)); - CHECK(ratio1->to_hash() == ratio2->to_hash()); + auto const ratio1{ expect_object(obj::ratio::create(2, 3)) }; + auto const ratio2{ expect_object(obj::ratio::create(2, 3)) }; + CHECK_EQ(ratio1->to_hash(), ratio2->to_hash()); } } @@ -134,94 +136,94 @@ namespace jank::runtime SUBCASE("Addition with Native Integer") { - auto native_int{ make_box(2LL) }; - auto result = *(ratio + native_int); - auto result2 = *(native_int + ratio); - CHECK(result.data.numerator == 11); - CHECK(result.data.denominator == 4); - CHECK(result2.data.numerator == 11); - CHECK(result2.data.denominator == 4); + auto const native_int{ make_box(2LL) }; + auto const result{ *(ratio + native_int) }; + auto const result2{ *(native_int + ratio) }; + CHECK_EQ(result.data.numerator, 11); + CHECK_EQ(result.data.denominator, 4); + CHECK_EQ(result2.data.numerator, 11); + CHECK_EQ(result2.data.denominator, 4); } SUBCASE("Addition with Native Real") { - auto native_real{ make_box(0.5) }; - auto result = ratio + native_real; - auto result2 = native_real + ratio; - CHECK(result == doctest::Approx(1.25)); - CHECK(result2 == doctest::Approx(1.25)); + auto const native_real{ make_box(0.5) }; + auto const result{ ratio + native_real }; + auto const result2{ native_real + ratio }; + CHECK_EQ(result, doctest::Approx(1.25)); + CHECK_EQ(result2, doctest::Approx(1.25)); } SUBCASE("Subtraction with Integer Pointer") { - auto int_ptr = make_box(1); - auto result = ratio - int_ptr; - auto result2 = int_ptr - ratio; - CHECK(result->data.numerator == -1); - CHECK(result->data.denominator == 4); - CHECK(result2->data.numerator == 1); - CHECK(result2->data.denominator == 4); + auto const int_ptr{ make_box(1) }; + auto const result{ ratio - int_ptr }; + auto const result2{ int_ptr - ratio }; + CHECK_EQ(result->data.numerator, -1); + CHECK_EQ(result->data.denominator, 4); + CHECK_EQ(result2->data.numerator, 1); + CHECK_EQ(result2->data.denominator, 4); } SUBCASE("Subtraction with Native Real") { - auto native_real{ make_box(0.25) }; - auto result = ratio - native_real; - auto result2 = native_real - ratio; - CHECK(result == doctest::Approx(0.5)); - CHECK(result2 == doctest::Approx(-0.5)); + auto const native_real{ make_box(0.25) }; + auto const result{ ratio - native_real }; + auto const result2{ native_real - ratio }; + CHECK_EQ(result, doctest::Approx(0.5)); + CHECK_EQ(result2, doctest::Approx(-0.5)); } SUBCASE("Multiplication with Integer Pointer") { - auto int_ptr{ make_box(3) }; - auto result = *expect_object(ratio * int_ptr); - auto result2 = *expect_object(int_ptr * ratio); - CHECK(result.data.numerator == 9); - CHECK(result.data.denominator == 4); - CHECK(result2.data.numerator == 9); - CHECK(result2.data.denominator == 4); + auto const int_ptr{ make_box(3) }; + auto const result{ *expect_object(ratio * int_ptr) }; + auto const result2{ *expect_object(int_ptr * ratio) }; + CHECK_EQ(result.data.numerator, 9); + CHECK_EQ(result.data.denominator, 4); + CHECK_EQ(result2.data.numerator, 9); + CHECK_EQ(result2.data.denominator, 4); } SUBCASE("Multiplication with Native Real") { - auto native_real{ 0.5L }; - auto result = ratio * native_real; - auto result2 = native_real * ratio; - CHECK(result == doctest::Approx(0.375)); - CHECK(result2 == doctest::Approx(0.375)); + auto const native_real{ 0.5L }; + auto const result{ ratio * native_real }; + auto const result2{ native_real * ratio }; + CHECK_EQ(result, doctest::Approx(0.375)); + CHECK_EQ(result2, doctest::Approx(0.375)); } SUBCASE("Division with Native Integer") { - auto native_int{ 2LL }; - auto result = ratio / native_int; - auto result2 = expect_object(native_int / ratio); - CHECK(result->data.numerator == 3); - CHECK(result->data.denominator == 8); - CHECK(result2->data.numerator == 8); - CHECK(result2->data.denominator == 3); + auto const native_int{ 2LL }; + auto const result{ ratio / native_int }; + auto const result2{ expect_object(native_int / ratio) }; + CHECK_EQ(result->data.numerator, 3); + CHECK_EQ(result->data.denominator, 8); + CHECK_EQ(result2->data.numerator, 8); + CHECK_EQ(result2->data.denominator, 3); } SUBCASE("Division with Native Real") { - auto native_real{ 0.5L }; - auto result = ratio / native_real; - auto result2 = native_real / ratio; - CHECK(result == doctest::Approx(1.5)); - CHECK(result2 == doctest::Approx(1 / 1.5)); + auto const native_real{ 0.5L }; + auto const result{ ratio / native_real }; + auto const result2{ native_real / ratio }; + CHECK_EQ(result, doctest::Approx(1.5)); + CHECK_EQ(result2, doctest::Approx(1 / 1.5)); } SUBCASE("Comparison with Integer Pointer") { - auto int_ptr{ make_box(1LL) }; - CHECK(ratio < int_ptr); - CHECK(ratio != int_ptr); - CHECK(int_ptr > ratio); - CHECK(int_ptr != ratio); + auto const int_ptr{ make_box(1LL) }; + CHECK_LT(ratio, int_ptr); + CHECK_NE(ratio, int_ptr); + CHECK_GT(int_ptr, ratio); + CHECK_NE(int_ptr, ratio); } SUBCASE("Comparison with Native Integer") { - auto native_int{ 1LL }; + auto const native_int{ 1LL }; CHECK(ratio < native_int); CHECK(ratio != native_int); CHECK(native_int > ratio); @@ -230,7 +232,7 @@ namespace jank::runtime SUBCASE("Comparison with Native Real") { - auto native_real{ 0.75L }; + auto const native_real{ 0.75L }; CHECK(ratio == native_real); CHECK(native_real == ratio); } @@ -239,24 +241,24 @@ namespace jank::runtime TEST_CASE("Ratio Mixed Arithmetic and Comparisons") { obj::ratio_data ratio{ 5, 8 }; - auto native_int{ 3LL }; - auto native_real{ 0.25L }; + auto const native_int{ 3LL }; + auto const native_real{ 0.25L }; SUBCASE("Complex Arithmetic Chain") { - auto result = (ratio + native_int)->data - native_real; - CHECK(result == doctest::Approx(3.375)); + auto const result{ (ratio + native_int)->data - native_real }; + CHECK_EQ(result, doctest::Approx(3.375)); } SUBCASE("Mixed Comparison") { - auto real_ptr{ make_box(1.0L) }; - auto int_ptr{ make_box(1LL) }; + auto const real_ptr{ make_box(1.0L) }; + auto const int_ptr{ make_box(1LL) }; - CHECK(ratio < real_ptr); - CHECK(ratio < int_ptr); - CHECK(real_ptr > ratio); - CHECK(int_ptr > ratio); + CHECK_LT(ratio, real_ptr); + CHECK_LT(ratio, int_ptr); + CHECK_GT(real_ptr, ratio); + CHECK_GT(int_ptr, ratio); } } @@ -264,15 +266,16 @@ namespace jank::runtime { SUBCASE("Ratio Divided by Zero") { - auto result = obj::ratio_data(1, 2) / 0.0L; + auto const result{ obj::ratio_data(1, 2) / 0.0L }; CHECK(std::isinf(result)); - CHECK(result > 0); - CHECK(result == std::numeric_limits::infinity()); + CHECK_GT(result, 0); + CHECK_EQ(result, std::numeric_limits::infinity()); - auto neg_result = expect_object(-1LL * obj::ratio_data(1, 2))->data / 0.0L; + auto const neg_result{ expect_object(-1LL * obj::ratio_data(1, 2))->data + / 0.0L }; CHECK(std::isinf(neg_result)); - CHECK(neg_result < 0); - CHECK(neg_result == -std::numeric_limits::infinity()); + CHECK_LT(neg_result, 0); + CHECK_EQ(neg_result, -std::numeric_limits::infinity()); CHECK_THROWS_AS((obj::ratio_data(1, 2) / 0LL), std::invalid_argument); CHECK_THROWS_AS((obj::ratio_data(1, 2) / obj::ratio_data(0, 1)), std::invalid_argument); @@ -280,122 +283,114 @@ namespace jank::runtime SUBCASE("Ratio Multiplied by Negative Integer") { - auto result = expect_object(obj::ratio_data(2, 3) * -4LL); - CHECK(result->data.numerator == -8); - CHECK(result->data.denominator == 3); + auto const result{ expect_object(obj::ratio_data(2, 3) * -4LL) }; + CHECK_EQ(result->data.numerator, -8); + CHECK_EQ(result->data.denominator, 3); } } } - TEST_SUITE("ratio") + TEST_CASE("constructor") { - obj::ratio_ptr make_ptr(native_integer num, native_integer denom) - { - auto r(make_box()); - r->data.numerator = num; - r->data.denominator = denom; - return r; - } - - TEST_CASE("constructor") - { - auto a = expect_object(obj::ratio::create(3, 4)); - CHECK(a->data.numerator == 3); - CHECK(a->data.denominator == 4); - } - - TEST_CASE("to_real") - { - auto a = make_ptr(3, 4); - CHECK(a->to_real() == 3.0 / 4.0); - } + auto const a{ expect_object(obj::ratio::create(3, 4)) }; + CHECK_EQ(a->data.numerator, 3); + CHECK_EQ(a->data.denominator, 4); + } - TEST_CASE("to_integer") - { - auto a = make_ptr(7, 4); - CHECK(a->to_integer() == 1); - } + TEST_CASE("to_real") + { + auto const a{ make_box(obj::ratio_data(3, 4)) }; + CHECK_EQ(a->to_real(), 3.0 / 4.0); + } - TEST_CASE("to_string") - { - auto a = make_ptr(3, 4); - CHECK(a->to_string() == "3/4"); - } + TEST_CASE("to_integer") + { + auto const a{ make_box(obj::ratio_data(7, 4)) }; + CHECK_EQ(a->to_integer(), 1); + } + TEST_CASE("to_string") + { + auto const a{ make_box(obj::ratio_data(3, 4)) }; + CHECK_EQ(a->to_string(), "3/4"); + } - TEST_CASE("compare_less_than") - { - auto a = make_ptr(3, 4); - auto b = make_ptr(5, 4); - CHECK(a->compare(*b) < 0); - } + TEST_CASE("compare_less_than") + { + auto const a{ make_box(obj::ratio_data(3, 4)) }; + auto const b{ make_box(obj::ratio_data(5, 4)) }; + CHECK_LT(a->compare(*b), 0); + } - TEST_CASE("compare_greater_than") - { - auto a = make_ptr(5, 4); - auto b = make_ptr(3, 4); - CHECK(a->compare(*b) > 0); - } + TEST_CASE("compare_greater_than") + { + auto const a{ make_box(obj::ratio_data(5, 4)) }; + auto const b{ make_box(obj::ratio_data(3, 4)) }; + CHECK_GT(a->compare(*b), 0); + } - TEST_CASE("compare_equal") - { - auto a = make_ptr(3, 4); - auto b = make_ptr(3, 4); - CHECK(a->compare(*b) == 0); - } + TEST_CASE("compare_equal") + { + auto const a{ make_box(obj::ratio_data(3, 4)) }; + auto const b{ make_box(obj::ratio_data(3, 4)) }; + CHECK_EQ(a->compare(*b), 0); + } - TEST_CASE("is_zero") - { - CHECK(is_zero(make_ptr(0, 1))); - } + TEST_CASE("is_zero") + { + CHECK(is_zero(make_box(obj::ratio_data(0, 1)))); + } - TEST_CASE("is_positive") - { - obj::ratio; - CHECK(is_pos(make_ptr(3, 4))); - } + TEST_CASE("is_positive") + { + obj::ratio; + CHECK(is_pos(make_box(obj::ratio_data(3, 4)))); + } - TEST_CASE("is_negative") - { - CHECK(is_neg(make_ptr(-3, 4))); - } + TEST_CASE("is_negative") + { + CHECK(is_neg(make_box(obj::ratio_data(-3, 4)))); + } - TEST_CASE("is_equivalent") - { - CHECK(is_equiv(make_ptr(3, 4), make_ptr(6, 8))); - } + TEST_CASE("is_equivalent") + { + CHECK(is_equiv(make_box(obj::ratio_data(3, 4)), + make_box(obj::ratio_data(6, 8)))); + } - TEST_CASE("increment") - { - auto result = expect_object(inc(make_ptr(3, 4))); - CHECK(result->data.numerator == 7); - CHECK(result->data.denominator == 4); - } + TEST_CASE("increment") + { + auto const result{ expect_object( + inc(make_box(obj::ratio_data(3, 4)))) }; + CHECK_EQ(result->data.numerator, 7); + CHECK_EQ(result->data.denominator, 4); + } - TEST_CASE("decrement") - { - auto result = expect_object(dec(make_ptr(3, 4))); - CHECK(result->data.numerator == -1); - CHECK(result->data.denominator == 4); - } + TEST_CASE("decrement") + { + auto const result{ expect_object( + dec(make_box(obj::ratio_data(3, 4)))) }; + CHECK_EQ(result->data.numerator, -1); + CHECK_EQ(result->data.denominator, 4); + } - TEST_CASE("abs") - { - auto result = expect_object(abs(make_ptr(-3, 4))); - CHECK(result->data.numerator == 3); - CHECK(result->data.denominator == 4); - } + TEST_CASE("abs") + { + auto const result{ expect_object( + abs(make_box(obj::ratio_data(-3, 4)))) }; + CHECK_EQ(result->data.numerator, 3); + CHECK_EQ(result->data.denominator, 4); + } - TEST_CASE("sqrt") - { - auto result = make_ptr(3, 4); - CHECK(sqrt(result) == doctest::Approx(std::sqrt(3.0 / 4.0))); - } + TEST_CASE("sqrt") + { + auto const result{ make_box(obj::ratio_data(3, 4)) }; + CHECK_EQ(sqrt(result), doctest::Approx(std::sqrt(3.0 / 4.0))); + } - TEST_CASE("pow") - { - auto a = make_ptr(3, 4); - CHECK(pow(a, a) == doctest::Approx(std::pow(3.0 / 4.0, 3.0 / 4.0))); - } + TEST_CASE("pow") + { + auto const a{ make_box(obj::ratio_data(3, 4)) }; + CHECK_EQ(pow(a, a), doctest::Approx(std::pow(3.0 / 4.0, 3.0 / 4.0))); } } From a40eebf2359596f9ffd8ca6c561ec9ed4d3b2e25 Mon Sep 17 00:00:00 2001 From: Jianling Zhong Date: Fri, 29 Nov 2024 18:28:42 -0800 Subject: [PATCH 3/4] Move operators into obj namespace --- .../include/cpp/jank/runtime/obj/ratio.hpp | 168 ++--- .../src/cpp/jank/runtime/obj/ratio.cpp | 688 +++++++++--------- .../test/cpp/jank/runtime/obj/ratio.cpp | 20 +- 3 files changed, 440 insertions(+), 436 deletions(-) diff --git a/compiler+runtime/include/cpp/jank/runtime/obj/ratio.hpp b/compiler+runtime/include/cpp/jank/runtime/obj/ratio.hpp index c883a70db..a9b95266d 100644 --- a/compiler+runtime/include/cpp/jank/runtime/obj/ratio.hpp +++ b/compiler+runtime/include/cpp/jank/runtime/obj/ratio.hpp @@ -51,89 +51,89 @@ namespace jank::runtime { using ratio = static_object; using ratio_ptr = native_box; - } - object_ptr operator+(obj::ratio_data l, obj::ratio_data r); - obj::ratio_ptr operator+(obj::integer_ptr l, obj::ratio_data r); - obj::ratio_ptr operator+(obj::ratio_data l, obj::integer_ptr r); - native_real operator+(obj::real_ptr l, obj::ratio_data r); - native_real operator+(obj::ratio_data l, obj::real_ptr r); - native_real operator+(obj::ratio_data l, native_real r); - native_real operator+(native_real l, obj::ratio_data r); - obj::ratio_ptr operator+(obj::ratio_data l, native_integer r); - obj::ratio_ptr operator+(native_integer l, obj::ratio_data r); - object_ptr operator-(obj::ratio_data l, obj::ratio_data r); - obj::ratio_ptr operator-(obj::integer_ptr l, obj::ratio_data r); - obj::ratio_ptr operator-(obj::ratio_data l, obj::integer_ptr r); - native_real operator-(obj::real_ptr l, obj::ratio_data r); - native_real operator-(obj::ratio_data l, obj::real_ptr r); - native_real operator-(obj::ratio_data l, native_real r); - native_real operator-(native_real l, obj::ratio_data r); - obj::ratio_ptr operator-(obj::ratio_data l, native_integer r); - obj::ratio_ptr operator-(native_integer l, obj::ratio_data r); - object_ptr operator*(obj::ratio_data l, obj::ratio_data r); - object_ptr operator*(obj::integer_ptr l, obj::ratio_data r); - object_ptr operator*(obj::ratio_data l, obj::integer_ptr r); - native_real operator*(obj::real_ptr l, obj::ratio_data r); - native_real operator*(obj::ratio_data l, obj::real_ptr r); - native_real operator*(obj::ratio_data l, native_real r); - native_real operator*(native_real l, obj::ratio_data r); - object_ptr operator*(obj::ratio_data l, native_integer r); - object_ptr operator*(native_integer l, obj::ratio_data r); - object_ptr operator/(obj::ratio_data l, obj::ratio_data r); - object_ptr operator/(obj::integer_ptr l, obj::ratio_data r); - obj::ratio_ptr operator/(obj::ratio_data l, obj::integer_ptr r); - native_real operator/(obj::real_ptr l, obj::ratio_data r); - native_real operator/(obj::ratio_data l, obj::real_ptr r); - native_real operator/(obj::ratio_data l, native_real r); - native_real operator/(native_real l, obj::ratio_data r); - obj::ratio_ptr operator/(obj::ratio_data l, native_integer r); - object_ptr operator/(native_integer l, obj::ratio_data r); - native_bool operator==(obj::ratio_data l, obj::ratio_data r); - native_bool operator==(obj::integer_ptr l, obj::ratio_data r); - native_bool operator==(obj::ratio_data l, obj::integer_ptr r); - native_bool operator==(obj::real_ptr l, obj::ratio_data r); - native_bool operator==(obj::ratio_data l, obj::real_ptr r); - native_bool operator==(obj::ratio_data l, native_real r); - native_bool operator==(native_real l, obj::ratio_data r); - native_bool operator==(obj::ratio_data l, native_integer r); - native_bool operator==(native_integer l, obj::ratio_data r); - native_bool operator<(obj::ratio_data l, obj::ratio_data r); - native_bool operator<(obj::integer_ptr l, obj::ratio_data r); - native_bool operator<(obj::ratio_data l, obj::integer_ptr r); - native_bool operator<(obj::real_ptr l, obj::ratio_data r); - native_bool operator<(obj::ratio_data l, obj::real_ptr r); - native_bool operator<(obj::ratio_data l, native_real r); - native_bool operator<(native_real l, obj::ratio_data r); - native_bool operator<(obj::ratio_data l, native_integer r); - native_bool operator<(native_integer l, obj::ratio_data r); - native_bool operator<(native_bool l, obj::ratio_data r); - native_bool operator<=(obj::ratio_data l, obj::ratio_data r); - native_bool operator<=(obj::integer_ptr l, obj::ratio_data r); - native_bool operator<=(obj::ratio_data l, obj::integer_ptr r); - native_bool operator<=(obj::real_ptr l, obj::ratio_data r); - native_bool operator<=(obj::ratio_data l, obj::real_ptr r); - native_bool operator<=(obj::ratio_data l, native_real r); - native_bool operator<=(native_real l, obj::ratio_data r); - native_bool operator<=(obj::ratio_data l, native_integer r); - native_bool operator<=(native_integer l, obj::ratio_data r); - native_bool operator>(obj::ratio_data l, obj::ratio_data r); - native_bool operator>(obj::integer_ptr l, obj::ratio_data r); - native_bool operator>(obj::ratio_data l, obj::integer_ptr r); - native_bool operator>(obj::real_ptr l, obj::ratio_data r); - native_bool operator>(obj::ratio_data l, obj::real_ptr r); - native_bool operator>(obj::ratio_data l, native_real r); - native_bool operator>(native_real l, obj::ratio_data r); - native_bool operator>(obj::ratio_data l, native_integer r); - native_bool operator>(native_integer l, obj::ratio_data r); - native_bool operator>(native_bool l, obj::ratio_data r); - native_bool operator>=(obj::ratio_data l, obj::ratio_data r); - native_bool operator>=(obj::integer_ptr l, obj::ratio_data r); - native_bool operator>=(obj::ratio_data l, obj::integer_ptr r); - native_bool operator>=(obj::real_ptr l, obj::ratio_data r); - native_bool operator>=(obj::ratio_data l, obj::real_ptr r); - native_bool operator>=(obj::ratio_data l, native_real r); - native_bool operator>=(native_real l, obj::ratio_data r); - native_bool operator>=(obj::ratio_data l, native_integer r); - native_bool operator>=(native_integer l, obj::ratio_data r); + object_ptr operator+(obj::ratio_data const &l, obj::ratio_data const &r); + obj::ratio_ptr operator+(obj::integer_ptr l, obj::ratio_data const &r); + obj::ratio_ptr operator+(obj::ratio_data const &l, obj::integer_ptr r); + native_real operator+(obj::real_ptr l, obj::ratio_data const &r); + native_real operator+(obj::ratio_data const &l, obj::real_ptr r); + native_real operator+(obj::ratio_data const &l, native_real r); + native_real operator+(native_real l, obj::ratio_data const &r); + obj::ratio_ptr operator+(obj::ratio_data const &l, native_integer r); + obj::ratio_ptr operator+(native_integer l, obj::ratio_data const &r); + object_ptr operator-(obj::ratio_data const &l, obj::ratio_data const &r); + obj::ratio_ptr operator-(obj::integer_ptr l, obj::ratio_data const &r); + obj::ratio_ptr operator-(obj::ratio_data const &l, obj::integer_ptr r); + native_real operator-(obj::real_ptr l, obj::ratio_data const &r); + native_real operator-(obj::ratio_data const &l, obj::real_ptr r); + native_real operator-(obj::ratio_data const &l, native_real r); + native_real operator-(native_real l, obj::ratio_data const &r); + obj::ratio_ptr operator-(obj::ratio_data const &l, native_integer r); + obj::ratio_ptr operator-(native_integer l, obj::ratio_data const &r); + object_ptr operator*(obj::ratio_data const &l, obj::ratio_data const &r); + object_ptr operator*(obj::integer_ptr l, obj::ratio_data const &r); + object_ptr operator*(obj::ratio_data const &l, obj::integer_ptr r); + native_real operator*(obj::real_ptr l, obj::ratio_data const &r); + native_real operator*(obj::ratio_data const &l, obj::real_ptr r); + native_real operator*(obj::ratio_data const &l, native_real r); + native_real operator*(native_real l, obj::ratio_data const &r); + object_ptr operator*(obj::ratio_data const &l, native_integer r); + object_ptr operator*(native_integer l, obj::ratio_data const &r); + object_ptr operator/(obj::ratio_data const &l, obj::ratio_data const &r); + object_ptr operator/(obj::integer_ptr l, obj::ratio_data const &r); + obj::ratio_ptr operator/(obj::ratio_data const &l, obj::integer_ptr r); + native_real operator/(obj::real_ptr l, obj::ratio_data const &r); + native_real operator/(obj::ratio_data const &l, obj::real_ptr r); + native_real operator/(obj::ratio_data const &l, native_real r); + native_real operator/(native_real l, obj::ratio_data const &r); + obj::ratio_ptr operator/(obj::ratio_data const &l, native_integer r); + object_ptr operator/(native_integer l, obj::ratio_data const &r); + native_bool operator==(obj::ratio_data const &l, obj::ratio_data const &r); + native_bool operator==(obj::integer_ptr l, obj::ratio_data const &r); + native_bool operator==(obj::ratio_data const &l, obj::integer_ptr r); + native_bool operator==(obj::real_ptr l, obj::ratio_data const &r); + native_bool operator==(obj::ratio_data const &l, obj::real_ptr r); + native_bool operator==(obj::ratio_data const &l, native_real r); + native_bool operator==(native_real l, obj::ratio_data const &r); + native_bool operator==(obj::ratio_data const &l, native_integer r); + native_bool operator==(native_integer l, obj::ratio_data const &r); + native_bool operator<(obj::ratio_data const &l, obj::ratio_data const &r); + native_bool operator<(obj::integer_ptr l, obj::ratio_data const &r); + native_bool operator<(obj::ratio_data const &l, obj::integer_ptr r); + native_bool operator<(obj::real_ptr l, obj::ratio_data const &r); + native_bool operator<(obj::ratio_data const &l, obj::real_ptr r); + native_bool operator<(obj::ratio_data const &l, native_real r); + native_bool operator<(native_real l, obj::ratio_data const &r); + native_bool operator<(obj::ratio_data const &l, native_integer r); + native_bool operator<(native_integer l, obj::ratio_data const &r); + native_bool operator<(native_bool l, obj::ratio_data const &r); + native_bool operator<=(obj::ratio_data const &l, obj::ratio_data const &r); + native_bool operator<=(obj::integer_ptr l, obj::ratio_data const &r); + native_bool operator<=(obj::ratio_data const &l, obj::integer_ptr r); + native_bool operator<=(obj::real_ptr l, obj::ratio_data const &r); + native_bool operator<=(obj::ratio_data const &l, obj::real_ptr r); + native_bool operator<=(obj::ratio_data const &l, native_real r); + native_bool operator<=(native_real l, obj::ratio_data const &r); + native_bool operator<=(obj::ratio_data const &l, native_integer r); + native_bool operator<=(native_integer l, obj::ratio_data const &r); + native_bool operator>(obj::ratio_data const &l, obj::ratio_data const &r); + native_bool operator>(obj::integer_ptr l, obj::ratio_data const &r); + native_bool operator>(obj::ratio_data const &l, obj::integer_ptr r); + native_bool operator>(obj::real_ptr l, obj::ratio_data const &r); + native_bool operator>(obj::ratio_data const &l, obj::real_ptr r); + native_bool operator>(obj::ratio_data const &l, native_real r); + native_bool operator>(native_real l, obj::ratio_data const &r); + native_bool operator>(obj::ratio_data const &l, native_integer r); + native_bool operator>(native_integer l, obj::ratio_data const &r); + native_bool operator>(native_bool l, obj::ratio_data const &r); + native_bool operator>=(obj::ratio_data const &l, obj::ratio_data const &r); + native_bool operator>=(obj::integer_ptr l, obj::ratio_data const &r); + native_bool operator>=(obj::ratio_data const &l, obj::integer_ptr r); + native_bool operator>=(obj::real_ptr l, obj::ratio_data const &r); + native_bool operator>=(obj::ratio_data const &l, obj::real_ptr r); + native_bool operator>=(obj::ratio_data const &l, native_real r); + native_bool operator>=(native_real l, obj::ratio_data const &r); + native_bool operator>=(obj::ratio_data const &l, native_integer r); + native_bool operator>=(native_integer l, obj::ratio_data const &r); + } } diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/ratio.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/ratio.cpp index 39624e8a0..1bb99f768 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/ratio.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/ratio.cpp @@ -126,432 +126,436 @@ namespace jank::runtime return (data > o.data) - (data < o.data); } - object_ptr operator+(obj::ratio_data const l, obj::ratio_data const r) + namespace obj { - auto const denom{ l.denominator * r.denominator }; - auto const num{ l.numerator * r.denominator + r.numerator * l.denominator }; - return obj::ratio::create(num, denom); - } + object_ptr operator+(obj::ratio_data const &l, obj::ratio_data const &r) + { + auto const denom{ l.denominator * r.denominator }; + auto const num{ l.numerator * r.denominator + r.numerator * l.denominator }; + return obj::ratio::create(num, denom); + } - obj::ratio_ptr operator+(obj::integer_ptr const l, obj::ratio_data const r) - { - return l->data + r; - } + obj::ratio_ptr operator+(obj::integer_ptr const l, obj::ratio_data const &r) + { + return l->data + r; + } - obj::ratio_ptr operator+(obj::ratio_data const l, obj::integer_ptr const r) - { - return r + l; - } + obj::ratio_ptr operator+(obj::ratio_data const &l, obj::integer_ptr const r) + { + return r + l; + } - native_real operator+(obj::real_ptr const l, obj::ratio_data const r) - { - return l->data + r.to_real(); - } + native_real operator+(obj::real_ptr const l, obj::ratio_data const &r) + { + return l->data + r.to_real(); + } - native_real operator+(obj::ratio_data const l, obj::real_ptr const r) - { - return l.to_real() + r->data; - } + native_real operator+(obj::ratio_data const &l, obj::real_ptr const r) + { + return l.to_real() + r->data; + } - native_real operator+(obj::ratio_data const l, native_real const r) - { - return l.to_real() + r; - } + native_real operator+(obj::ratio_data const &l, native_real const r) + { + return l.to_real() + r; + } - native_real operator+(native_real const l, obj::ratio_data const r) - { - return l + r.to_real(); - } + native_real operator+(native_real const l, obj::ratio_data const &r) + { + return l + r.to_real(); + } - obj::ratio_ptr operator+(obj::ratio_data const l, native_integer const r) - { - return make_box(obj::ratio_data(l.numerator + r * l.denominator, l.denominator)); - } + obj::ratio_ptr operator+(obj::ratio_data const &l, native_integer const r) + { + return make_box(obj::ratio_data(l.numerator + r * l.denominator, l.denominator)); + } - obj::ratio_ptr operator+(native_integer const l, obj::ratio_data const r) - { - return r + l; - } + obj::ratio_ptr operator+(native_integer const l, obj::ratio_data const &r) + { + return r + l; + } - object_ptr operator-(obj::ratio_data const l, obj::ratio_data const r) - { - auto const denom{ l.denominator * r.denominator }; - auto const num{ l.numerator * r.denominator - r.numerator * l.denominator }; - return obj::ratio::create(num, denom); - } + object_ptr operator-(obj::ratio_data const &l, obj::ratio_data const &r) + { + auto const denom{ l.denominator * r.denominator }; + auto const num{ l.numerator * r.denominator - r.numerator * l.denominator }; + return obj::ratio::create(num, denom); + } - obj::ratio_ptr operator-(obj::integer_ptr const l, obj::ratio_data const r) - { - return l->data - r; - } + obj::ratio_ptr operator-(obj::integer_ptr const l, obj::ratio_data const &r) + { + return l->data - r; + } - obj::ratio_ptr operator-(obj::ratio_data const l, obj::integer_ptr const r) - { - return l - r->data; - } + obj::ratio_ptr operator-(obj::ratio_data const &l, obj::integer_ptr const r) + { + return l - r->data; + } - native_real operator-(obj::real_ptr const l, obj::ratio_data const r) - { - return l->data - r.to_real(); - } + native_real operator-(obj::real_ptr const l, obj::ratio_data const &r) + { + return l->data - r.to_real(); + } - native_real operator-(obj::ratio_data const l, obj::real_ptr const r) - { - return l.to_real() - r->data; - } + native_real operator-(obj::ratio_data const &l, obj::real_ptr const r) + { + return l.to_real() - r->data; + } - native_real operator-(obj::ratio_data const l, native_real const r) - { - return l.to_real() - r; - } + native_real operator-(obj::ratio_data const &l, native_real const r) + { + return l.to_real() - r; + } - native_real operator-(native_real const l, obj::ratio_data const r) - { - return l - r.to_real(); - } + native_real operator-(native_real const l, obj::ratio_data const &r) + { + return l - r.to_real(); + } - obj::ratio_ptr operator-(obj::ratio_data const l, native_integer const r) - { - return make_box(obj::ratio_data(l.numerator - r * l.denominator, l.denominator)); - } + obj::ratio_ptr operator-(obj::ratio_data const &l, native_integer const r) + { + return make_box(obj::ratio_data(l.numerator - r * l.denominator, l.denominator)); + } - obj::ratio_ptr operator-(native_integer const l, obj::ratio_data const r) - { - return make_box(obj::ratio_data(l * r.denominator - r.denominator, r.denominator)); - } + obj::ratio_ptr operator-(native_integer const l, obj::ratio_data const &r) + { + return make_box( + obj::ratio_data(l * r.denominator - r.denominator, r.denominator)); + } - object_ptr operator*(obj::ratio_data const l, obj::ratio_data const r) - { - return obj::ratio::create(l.numerator * r.numerator, l.denominator * r.denominator); - } + object_ptr operator*(obj::ratio_data const &l, obj::ratio_data const &r) + { + return obj::ratio::create(l.numerator * r.numerator, l.denominator * r.denominator); + } - object_ptr operator*(obj::integer_ptr const l, obj::ratio_data const r) - { - return obj::ratio_data(l->data, 1LL) * r; - } + object_ptr operator*(obj::integer_ptr const l, obj::ratio_data const &r) + { + return obj::ratio_data(l->data, 1LL) * r; + } - object_ptr operator*(obj::ratio_data const l, obj::integer_ptr const r) - { - return l * obj::ratio_data(r->data, 1LL); - } + object_ptr operator*(obj::ratio_data const &l, obj::integer_ptr const r) + { + return l * obj::ratio_data(r->data, 1LL); + } - native_real operator*(obj::real_ptr const l, obj::ratio_data const r) - { - return l->data * r.to_real(); - } + native_real operator*(obj::real_ptr const l, obj::ratio_data const &r) + { + return l->data * r.to_real(); + } - native_real operator*(obj::ratio_data const l, obj::real_ptr const r) - { - return l.to_real() * r->data; - } + native_real operator*(obj::ratio_data const &l, obj::real_ptr const r) + { + return l.to_real() * r->data; + } - native_real operator*(obj::ratio_data const l, native_real const r) - { - return l.to_real() * r; - } + native_real operator*(obj::ratio_data const &l, native_real const r) + { + return l.to_real() * r; + } - native_real operator*(native_real const l, obj::ratio_data const r) - { - return l * r.to_real(); - } + native_real operator*(native_real const l, obj::ratio_data const &r) + { + return l * r.to_real(); + } - object_ptr operator*(obj::ratio_data const l, native_integer const r) - { - return l * obj::ratio_data(r, 1LL); - } + object_ptr operator*(obj::ratio_data const &l, native_integer const r) + { + return l * obj::ratio_data(r, 1LL); + } - object_ptr operator*(native_integer const l, obj::ratio_data const r) - { - return r * l; - } + object_ptr operator*(native_integer const l, obj::ratio_data const &r) + { + return r * l; + } - object_ptr operator/(obj::ratio_data const l, obj::ratio_data const r) - { - return obj::ratio::create(l.numerator * r.denominator, l.denominator * r.numerator); - } + object_ptr operator/(obj::ratio_data const &l, obj::ratio_data const &r) + { + return obj::ratio::create(l.numerator * r.denominator, l.denominator * r.numerator); + } - object_ptr operator/(obj::integer_ptr const l, obj::ratio_data const r) - { - return obj::ratio_data(l->data, 1LL) / r; - } + object_ptr operator/(obj::integer_ptr const l, obj::ratio_data const &r) + { + return obj::ratio_data(l->data, 1LL) / r; + } - obj::ratio_ptr operator/(obj::ratio_data const l, obj::integer_ptr const r) - { - return l / r->data; - } + obj::ratio_ptr operator/(obj::ratio_data const &l, obj::integer_ptr const r) + { + return l / r->data; + } - native_real operator/(obj::real_ptr const l, obj::ratio_data const r) - { - return l->data / r.to_real(); - } + native_real operator/(obj::real_ptr const l, obj::ratio_data const &r) + { + return l->data / r.to_real(); + } - native_real operator/(obj::ratio_data const l, obj::real_ptr const r) - { - return l.to_real() / r->data; - } + native_real operator/(obj::ratio_data const &l, obj::real_ptr const r) + { + return l.to_real() / r->data; + } - native_real operator/(obj::ratio_data const l, native_real const r) - { - return l.to_real() / r; - } + native_real operator/(obj::ratio_data const &l, native_real const r) + { + return l.to_real() / r; + } - native_real operator/(native_real const l, obj::ratio_data const r) - { - return l / r.to_real(); - } + native_real operator/(native_real const l, obj::ratio_data const &r) + { + return l / r.to_real(); + } - obj::ratio_ptr operator/(obj::ratio_data const l, native_integer const r) - { - return make_box(obj::ratio_data(l.numerator, l.denominator * r)); - } + obj::ratio_ptr operator/(obj::ratio_data const &l, native_integer const r) + { + return make_box(obj::ratio_data(l.numerator, l.denominator * r)); + } - object_ptr operator/(native_integer const l, obj::ratio_data const r) - { - return obj::ratio_data(l, 1LL) / r; - } + object_ptr operator/(native_integer const l, obj::ratio_data const &r) + { + return obj::ratio_data(l, 1LL) / r; + } - native_bool operator==(obj::ratio_data const l, obj::ratio_data const r) - { - return l.numerator == r.numerator && l.denominator == r.denominator; - } + native_bool operator==(obj::ratio_data const &l, obj::ratio_data const &r) + { + return l.numerator == r.numerator && l.denominator == r.denominator; + } - native_bool operator==(obj::integer_ptr const l, obj::ratio_data const r) - { - return l->data * r.denominator == r.numerator; - } + native_bool operator==(obj::integer_ptr const l, obj::ratio_data const &r) + { + return l->data * r.denominator == r.numerator; + } - native_bool operator==(obj::ratio_data const l, obj::integer_ptr const r) - { - return l.numerator == r->data * l.denominator; - } + native_bool operator==(obj::ratio_data const &l, obj::integer_ptr const r) + { + return l.numerator == r->data * l.denominator; + } - native_bool operator==(obj::real_ptr const l, obj::ratio_data const r) - { - return std::fabs(l->data - r) < epsilon; - } + native_bool operator==(obj::real_ptr const l, obj::ratio_data const &r) + { + return std::fabs(l->data - r) < epsilon; + } - native_bool operator==(obj::ratio_data const l, obj::real_ptr const r) - { - return r == l; - } + native_bool operator==(obj::ratio_data const &l, obj::real_ptr const r) + { + return r == l; + } - native_bool operator==(obj::ratio_data const l, native_real const r) - { - return std::fabs(l - r) < epsilon; - } + native_bool operator==(obj::ratio_data const &l, native_real const r) + { + return std::fabs(l - r) < epsilon; + } - native_bool operator==(native_real const l, obj::ratio_data const r) - { - return r == l; - } + native_bool operator==(native_real const l, obj::ratio_data const &r) + { + return r == l; + } - native_bool operator==(obj::ratio_data const l, native_integer const r) - { - return l.numerator == r * l.denominator; - } + native_bool operator==(obj::ratio_data const &l, native_integer const r) + { + return l.numerator == r * l.denominator; + } - native_bool operator==(native_integer const l, obj::ratio_data const r) - { - return l * r.denominator == r.numerator; - } + native_bool operator==(native_integer const l, obj::ratio_data const &r) + { + return l * r.denominator == r.numerator; + } - native_bool operator<(obj::ratio_data const l, obj::ratio_data const r) - { - return l.numerator * r.denominator < r.numerator * l.denominator; - } + native_bool operator<(obj::ratio_data const &l, obj::ratio_data const &r) + { + return l.numerator * r.denominator < r.numerator * l.denominator; + } - native_bool operator<=(obj::ratio_data const l, obj::ratio_data const r) - { - return l.numerator * r.denominator <= r.numerator * l.denominator; - } + native_bool operator<=(obj::ratio_data const &l, obj::ratio_data const &r) + { + return l.numerator * r.denominator <= r.numerator * l.denominator; + } - native_bool operator<(obj::integer_ptr const l, obj::ratio_data const r) - { - return l->data * r.denominator < r.numerator; - } + native_bool operator<(obj::integer_ptr const l, obj::ratio_data const &r) + { + return l->data * r.denominator < r.numerator; + } - native_bool operator<(obj::ratio_data const l, obj::integer_ptr const r) - { - return l.numerator < r->data * l.denominator; - } + native_bool operator<(obj::ratio_data const &l, obj::integer_ptr const r) + { + return l.numerator < r->data * l.denominator; + } - native_bool operator<=(obj::integer_ptr const l, obj::ratio_data const r) - { - return l->data * r.denominator <= r.numerator; - } + native_bool operator<=(obj::integer_ptr const l, obj::ratio_data const &r) + { + return l->data * r.denominator <= r.numerator; + } - native_bool operator<=(obj::ratio_data const l, obj::integer_ptr const r) - { - return l.numerator <= r->data * l.denominator; - } + native_bool operator<=(obj::ratio_data const &l, obj::integer_ptr const r) + { + return l.numerator <= r->data * l.denominator; + } - native_bool operator<(obj::real_ptr const l, obj::ratio_data const r) - { - return l->data < r.to_real(); - } + native_bool operator<(obj::real_ptr const l, obj::ratio_data const &r) + { + return l->data < r.to_real(); + } - native_bool operator<(obj::ratio_data const l, obj::real_ptr const r) - { - return l.to_real() < r->data; - } + native_bool operator<(obj::ratio_data const &l, obj::real_ptr const r) + { + return l.to_real() < r->data; + } - native_bool operator<=(obj::real_ptr const l, obj::ratio_data const r) - { - return l->data <= r.to_real(); - } + native_bool operator<=(obj::real_ptr const l, obj::ratio_data const &r) + { + return l->data <= r.to_real(); + } - native_bool operator<=(obj::ratio_data const l, obj::real_ptr const r) - { - return l.to_real() <= r->data; - } + native_bool operator<=(obj::ratio_data const &l, obj::real_ptr const r) + { + return l.to_real() <= r->data; + } - native_bool operator<(obj::ratio_data const l, native_real const r) - { - return l.to_real() < r; - } + native_bool operator<(obj::ratio_data const &l, native_real const r) + { + return l.to_real() < r; + } - native_bool operator<(native_real const l, obj::ratio_data const r) - { - return l < r.to_real(); - } + native_bool operator<(native_real const l, obj::ratio_data const &r) + { + return l < r.to_real(); + } - native_bool operator<=(obj::ratio_data const l, native_real const r) - { - return l.to_real() <= r; - } + native_bool operator<=(obj::ratio_data const &l, native_real const r) + { + return l.to_real() <= r; + } - native_bool operator<=(native_real const l, obj::ratio_data const r) - { - return l <= r.to_real(); - } + native_bool operator<=(native_real const l, obj::ratio_data const &r) + { + return l <= r.to_real(); + } - native_bool operator<(obj::ratio_data const l, native_integer const r) - { - return l.numerator < r * l.denominator; - } + native_bool operator<(obj::ratio_data const &l, native_integer const r) + { + return l.numerator < r * l.denominator; + } - native_bool operator<(native_integer const l, obj::ratio_data const r) - { - return l * r.denominator < r.numerator; - } + native_bool operator<(native_integer const l, obj::ratio_data const &r) + { + return l * r.denominator < r.numerator; + } - native_bool operator<=(obj::ratio_data const l, native_integer const r) - { - return l.numerator <= r * l.denominator; - } + native_bool operator<=(obj::ratio_data const &l, native_integer const r) + { + return l.numerator <= r * l.denominator; + } - native_bool operator<=(native_integer const l, obj::ratio_data const r) - { - return l * r.denominator <= r.numerator; - } + native_bool operator<=(native_integer const l, obj::ratio_data const &r) + { + return l * r.denominator <= r.numerator; + } - native_bool operator>(obj::ratio_data const l, obj::ratio_data const r) - { - return l.numerator * r.denominator > r.numerator * l.denominator; - } + native_bool operator>(obj::ratio_data const &l, obj::ratio_data const &r) + { + return l.numerator * r.denominator > r.numerator * l.denominator; + } - native_bool operator>(obj::integer_ptr const l, obj::ratio_data const r) - { - return l->data * r.denominator > r.numerator; - } + native_bool operator>(obj::integer_ptr const l, obj::ratio_data const &r) + { + return l->data * r.denominator > r.numerator; + } - native_bool operator>(obj::ratio_data const l, obj::integer_ptr const r) - { - return l.numerator > r->data * l.denominator; - } + native_bool operator>(obj::ratio_data const &l, obj::integer_ptr const r) + { + return l.numerator > r->data * l.denominator; + } - native_bool operator>(obj::real_ptr const l, obj::ratio_data const r) - { - return l->data > r.to_real(); - } + native_bool operator>(obj::real_ptr const l, obj::ratio_data const &r) + { + return l->data > r.to_real(); + } - native_bool operator>(obj::ratio_data const l, obj::real_ptr const r) - { - return l.to_real() > r->data; - } + native_bool operator>(obj::ratio_data const &l, obj::real_ptr const r) + { + return l.to_real() > r->data; + } - native_bool operator>(obj::ratio_data const l, native_real const r) - { - return l.to_real() > r; - } + native_bool operator>(obj::ratio_data const &l, native_real const r) + { + return l.to_real() > r; + } - native_bool operator>(native_real const l, obj::ratio_data const r) - { - return l > r.to_real(); - } + native_bool operator>(native_real const l, obj::ratio_data const &r) + { + return l > r.to_real(); + } - native_bool operator>(obj::ratio_data const l, native_integer const r) - { - return l.numerator > r * l.denominator; - } + native_bool operator>(obj::ratio_data const &l, native_integer const r) + { + return l.numerator > r * l.denominator; + } - native_bool operator>(native_integer const l, obj::ratio_data const r) - { - return l * r.denominator > r.numerator; - } + native_bool operator>(native_integer const l, obj::ratio_data const &r) + { + return l * r.denominator > r.numerator; + } - native_bool operator>=(obj::ratio_data const l, obj::ratio_data const r) - { - return l.numerator * r.denominator >= r.numerator * l.denominator; - } + native_bool operator>=(obj::ratio_data const &l, obj::ratio_data const &r) + { + return l.numerator * r.denominator >= r.numerator * l.denominator; + } - native_bool operator>=(obj::integer_ptr const l, obj::ratio_data const r) - { - return l->data * r.denominator >= r.numerator; - } + native_bool operator>=(obj::integer_ptr const l, obj::ratio_data const &r) + { + return l->data * r.denominator >= r.numerator; + } - native_bool operator>=(obj::ratio_data const l, obj::integer_ptr const r) - { - return l.numerator >= r->data * l.denominator; - } + native_bool operator>=(obj::ratio_data const &l, obj::integer_ptr const r) + { + return l.numerator >= r->data * l.denominator; + } - native_bool operator>=(obj::real_ptr const l, obj::ratio_data const r) - { - return l->data >= r.to_real(); - } + native_bool operator>=(obj::real_ptr const l, obj::ratio_data const &r) + { + return l->data >= r.to_real(); + } - native_bool operator>=(obj::ratio_data const l, obj::real_ptr const r) - { - return l.to_real() >= r->data; - } + native_bool operator>=(obj::ratio_data const &l, obj::real_ptr const r) + { + return l.to_real() >= r->data; + } - native_bool operator>=(obj::ratio_data const l, native_real const r) - { - return l.to_real() >= r; - } + native_bool operator>=(obj::ratio_data const &l, native_real const r) + { + return l.to_real() >= r; + } - native_bool operator>=(native_real const l, obj::ratio_data const r) - { - return l >= r.to_real(); - } + native_bool operator>=(native_real const l, obj::ratio_data const &r) + { + return l >= r.to_real(); + } - native_bool operator>=(obj::ratio_data const l, native_integer const r) - { - return l.numerator >= r * l.denominator; - } + native_bool operator>=(obj::ratio_data const &l, native_integer const r) + { + return l.numerator >= r * l.denominator; + } - native_bool operator>=(native_integer const l, obj::ratio_data const r) - { - return l * r.denominator >= r.numerator; - } + native_bool operator>=(native_integer const l, obj::ratio_data const &r) + { + return l * r.denominator >= r.numerator; + } - native_bool operator>(native_bool l, obj::ratio_data const r) - { - return (l ? 1LL : 0LL) > r; - } + native_bool operator>(native_bool l, obj::ratio_data const &r) + { + return (l ? 1LL : 0LL) > r; + } - native_bool operator<(native_bool l, obj::ratio_data const r) - { - return (l ? 1LL : 0LL) < r; - } + native_bool operator<(native_bool l, obj::ratio_data const &r) + { + return (l ? 1LL : 0LL) < r; + } - native_bool operator>(obj::ratio_data const l, native_bool r) - { - return l > (r ? 1LL : 0LL); - } + native_bool operator>(obj::ratio_data const &l, native_bool r) + { + return l > (r ? 1LL : 0LL); + } - native_bool operator<(obj::ratio_data const l, native_bool r) - { - return l < (r ? 1LL : 0LL); + native_bool operator<(obj::ratio_data const &l, native_bool r) + { + return l < (r ? 1LL : 0LL); + } } } diff --git a/compiler+runtime/test/cpp/jank/runtime/obj/ratio.cpp b/compiler+runtime/test/cpp/jank/runtime/obj/ratio.cpp index 163b71fd0..e1fa84884 100644 --- a/compiler+runtime/test/cpp/jank/runtime/obj/ratio.cpp +++ b/compiler+runtime/test/cpp/jank/runtime/obj/ratio.cpp @@ -92,17 +92,17 @@ namespace jank::runtime SUBCASE("Equality") { - CHECK(a == b); - CHECK(a != c); + CHECK_EQ(a, b); + CHECK_NE(a, c); } SUBCASE("Less Than") { - CHECK(c < a); + CHECK_LT(c, a); CHECK_FALSE(a < b); } SUBCASE("Greater Than") { - CHECK(a > c); + CHECK_GT(a, c); CHECK_FALSE(c > a); } } @@ -224,17 +224,17 @@ namespace jank::runtime SUBCASE("Comparison with Native Integer") { auto const native_int{ 1LL }; - CHECK(ratio < native_int); - CHECK(ratio != native_int); - CHECK(native_int > ratio); - CHECK(native_int != ratio); + CHECK_LT(ratio, native_int); + CHECK_NE(ratio, native_int); + CHECK_GT(native_int, ratio); + CHECK_NE(native_int, ratio); } SUBCASE("Comparison with Native Real") { auto const native_real{ 0.75L }; - CHECK(ratio == native_real); - CHECK(native_real == ratio); + CHECK_EQ(ratio, native_real); + CHECK_EQ(native_real, ratio); } } From 2321b2277bb1085a6007daada51bfdf59de25cb8 Mon Sep 17 00:00:00 2001 From: Jianling Zhong Date: Wed, 4 Dec 2024 22:57:48 -0800 Subject: [PATCH 4/4] Fix integer ratio subtraction bug --- compiler+runtime/src/cpp/jank/runtime/obj/ratio.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler+runtime/src/cpp/jank/runtime/obj/ratio.cpp b/compiler+runtime/src/cpp/jank/runtime/obj/ratio.cpp index 1bb99f768..964ad368e 100644 --- a/compiler+runtime/src/cpp/jank/runtime/obj/ratio.cpp +++ b/compiler+runtime/src/cpp/jank/runtime/obj/ratio.cpp @@ -220,7 +220,7 @@ namespace jank::runtime obj::ratio_ptr operator-(native_integer const l, obj::ratio_data const &r) { return make_box( - obj::ratio_data(l * r.denominator - r.denominator, r.denominator)); + obj::ratio_data(l * r.denominator - r.numerator, r.denominator)); } object_ptr operator*(obj::ratio_data const &l, obj::ratio_data const &r)