From 5ff845aa6bc0c2455ef662b52763b808e38be4bd Mon Sep 17 00:00:00 2001 From: Darby Johnston Date: Sun, 11 Jun 2023 10:22:48 -0700 Subject: [PATCH 1/3] Add utility functions for comparison and rounding Signed-off-by: Darby Johnston --- src/opentime/rationalTime.h | 33 ++++++++++++++++++++++++++++----- src/opentime/timeRange.h | 2 +- tests/test_opentime.cpp | 22 ++++++++++++++++++++++ 3 files changed, 51 insertions(+), 6 deletions(-) diff --git a/src/opentime/rationalTime.h b/src/opentime/rationalTime.h index fbdd02d4e..0d5463b2c 100644 --- a/src/opentime/rationalTime.h +++ b/src/opentime/rationalTime.h @@ -77,6 +77,34 @@ class RationalTime return fabs(value_rescaled_to(other._rate) - other._value) <= delta; } + // Return whether the value and rate are equal to another RationalTime. + // This is different from the operator "==" that rescales the time before + // comparison. + constexpr bool exactly_equal(RationalTime other) const noexcept + { + return _value == other._value && _rate == other._rate; + } + + // Return a RationalTime with the largest integer value not greater than + // this value. + RationalTime floor() const + { + return RationalTime{ std::floor(_value), _rate }; + } + + // Return a RationalTime with the smallest integer value not less than + // this value. + RationalTime ceil() const + { + return RationalTime{ std::ceil(_value), _rate }; + } + + // Return a RationalTime with the nearest integer value to this value. + RationalTime round() const + { + return RationalTime{ std::round(_value), _rate }; + } + static RationalTime constexpr duration_from_start_end_time( RationalTime start_time, RationalTime end_time_exclusive) noexcept @@ -263,11 +291,6 @@ class RationalTime static RationalTime _invalid_time; static constexpr double _invalid_rate = -1; - RationalTime _floor() const noexcept - { - return RationalTime{ floor(_value), _rate }; - } - friend class TimeTransform; friend class TimeRange; diff --git a/src/opentime/timeRange.h b/src/opentime/timeRange.h index 3c039c6da..96664e10b 100644 --- a/src/opentime/timeRange.h +++ b/src/opentime/timeRange.h @@ -62,7 +62,7 @@ class TimeRange if ((et - _start_time.rescaled_to(_duration))._value > 1) { return _duration._value != floor(_duration._value) - ? et._floor() + ? et.floor() : et - RationalTime(1, _duration._rate); } else diff --git a/tests/test_opentime.cpp b/tests/test_opentime.cpp index b508da899..1e512860d 100644 --- a/tests/test_opentime.cpp +++ b/tests/test_opentime.cpp @@ -27,6 +27,8 @@ main(int argc, char** argv) assertEqual(t1, t1); otime::RationalTime t2(30.2); assertEqual(t1, t2); + otime::RationalTime t3(60.4, 2.0); + assertEqual(t1, t3); }); tests.add_test("test_inequality", [] { @@ -38,6 +40,26 @@ main(int argc, char** argv) assertFalse(t1 != t3); }); + tests.add_test("test_exact_equality", [] { + otime::RationalTime t1(30.2); + assertTrue(t1.exactly_equal(t1)); + otime::RationalTime t2(30.2); + assertTrue(t1.exactly_equal(t2)); + otime::RationalTime t3(60.4, 2.0); + assertFalse(t1.exactly_equal(t3)); + }); + + tests.add_test("test_rounding", [] { + otime::RationalTime t1(30.2); + assertEqual(t1.floor(), otime::RationalTime(30.0)); + assertEqual(t1.ceil(), otime::RationalTime(31.0)); + assertEqual(t1.round(), otime::RationalTime(30.0)); + otime::RationalTime t2(30.8); + assertEqual(t2.floor(), otime::RationalTime(30.0)); + assertEqual(t2.ceil(), otime::RationalTime(31.0)); + assertEqual(t2.round(), otime::RationalTime(31.0)); + }); + tests.add_test("test_from_time_string", [] { std::string time_string = "0:12:04"; auto t = otime::RationalTime(24 * (12 * 60 + 4), 24); From 81d84640bd6384c11e6b6f80b01c9fcaaa21068f Mon Sep 17 00:00:00 2001 From: Darby Johnston Date: Mon, 12 Jun 2023 09:09:18 -0700 Subject: [PATCH 2/3] Rename functions and add Python bindings Signed-off-by: Darby Johnston --- src/opentime/rationalTime.h | 8 ++++---- src/opentime/timeRange.h | 4 ++-- .../opentime_rationalTime.cpp | 4 ++++ tests/test_opentime.cpp | 20 +++++++++---------- tests/test_opentime.py | 20 +++++++++++++++++++ 5 files changed, 40 insertions(+), 16 deletions(-) diff --git a/src/opentime/rationalTime.h b/src/opentime/rationalTime.h index 0d5463b2c..ed70b2b67 100644 --- a/src/opentime/rationalTime.h +++ b/src/opentime/rationalTime.h @@ -80,27 +80,27 @@ class RationalTime // Return whether the value and rate are equal to another RationalTime. // This is different from the operator "==" that rescales the time before // comparison. - constexpr bool exactly_equal(RationalTime other) const noexcept + constexpr bool strictly_equal(RationalTime other) const noexcept { return _value == other._value && _rate == other._rate; } // Return a RationalTime with the largest integer value not greater than // this value. - RationalTime floor() const + RationalTime floor_value() const { return RationalTime{ std::floor(_value), _rate }; } // Return a RationalTime with the smallest integer value not less than // this value. - RationalTime ceil() const + RationalTime ceil_value() const { return RationalTime{ std::ceil(_value), _rate }; } // Return a RationalTime with the nearest integer value to this value. - RationalTime round() const + RationalTime round_value() const { return RationalTime{ std::round(_value), _rate }; } diff --git a/src/opentime/timeRange.h b/src/opentime/timeRange.h index 96664e10b..f5d25df78 100644 --- a/src/opentime/timeRange.h +++ b/src/opentime/timeRange.h @@ -61,8 +61,8 @@ class TimeRange if ((et - _start_time.rescaled_to(_duration))._value > 1) { - return _duration._value != floor(_duration._value) - ? et.floor() + return _duration._value != std::floor(_duration._value) + ? et.floor_value() : et - RationalTime(1, _duration._rate); } else diff --git a/src/py-opentimelineio/opentime-bindings/opentime_rationalTime.cpp b/src/py-opentimelineio/opentime-bindings/opentime_rationalTime.cpp index 776467c1a..34172357f 100644 --- a/src/py-opentimelineio/opentime-bindings/opentime_rationalTime.cpp +++ b/src/py-opentimelineio/opentime-bindings/opentime_rationalTime.cpp @@ -81,6 +81,10 @@ or if the rate is less than or equal to zero. .def("value_rescaled_to", (double (RationalTime::*)(RationalTime) const) &RationalTime::value_rescaled_to, "other"_a) .def("almost_equal", &RationalTime::almost_equal, "other"_a, "delta"_a = 0) + .def("strictly_equal", &RationalTime::strictly_equal, "other"_a) + .def("floor_value", &RationalTime::floor_value) + .def("ceil_value", &RationalTime::ceil_value) + .def("round_value", &RationalTime::round_value) .def("__copy__", [](RationalTime rt) { return rt; }) diff --git a/tests/test_opentime.cpp b/tests/test_opentime.cpp index 1e512860d..c83396498 100644 --- a/tests/test_opentime.cpp +++ b/tests/test_opentime.cpp @@ -40,24 +40,24 @@ main(int argc, char** argv) assertFalse(t1 != t3); }); - tests.add_test("test_exact_equality", [] { + tests.add_test("test_strict_equality", [] { otime::RationalTime t1(30.2); - assertTrue(t1.exactly_equal(t1)); + assertTrue(t1.strictly_equal(t1)); otime::RationalTime t2(30.2); - assertTrue(t1.exactly_equal(t2)); + assertTrue(t1.strictly_equal(t2)); otime::RationalTime t3(60.4, 2.0); - assertFalse(t1.exactly_equal(t3)); + assertFalse(t1.strictly_equal(t3)); }); tests.add_test("test_rounding", [] { otime::RationalTime t1(30.2); - assertEqual(t1.floor(), otime::RationalTime(30.0)); - assertEqual(t1.ceil(), otime::RationalTime(31.0)); - assertEqual(t1.round(), otime::RationalTime(30.0)); + assertEqual(t1.floor_value(), otime::RationalTime(30.0)); + assertEqual(t1.ceil_value(), otime::RationalTime(31.0)); + assertEqual(t1.round_value(), otime::RationalTime(30.0)); otime::RationalTime t2(30.8); - assertEqual(t2.floor(), otime::RationalTime(30.0)); - assertEqual(t2.ceil(), otime::RationalTime(31.0)); - assertEqual(t2.round(), otime::RationalTime(31.0)); + assertEqual(t2.floor_value(), otime::RationalTime(30.0)); + assertEqual(t2.ceil_value(), otime::RationalTime(31.0)); + assertEqual(t2.round_value(), otime::RationalTime(31.0)); }); tests.add_test("test_from_time_string", [] { diff --git a/tests/test_opentime.py b/tests/test_opentime.py index 5afc847b7..4445e385c 100755 --- a/tests/test_opentime.py +++ b/tests/test_opentime.py @@ -32,6 +32,8 @@ def test_equality(self): t2 = otio.opentime.RationalTime(30.2) self.assertTrue(t1 is not t2) self.assertEqual(t1, t2) + t3 = otio.opentime.RationalTime(60.4, 2.0) + self.assertEqual(t1, t3) def test_inequality(self): t1 = otio.opentime.RationalTime(30.2) @@ -43,6 +45,24 @@ def test_inequality(self): self.assertTrue(t1 is not t3) self.assertFalse(t1 != t3) + def test_strict_equality(self): + t1 = otio.opentime.RationalTime(30.2) + self.assertTrue(t1.strictly_equal(t1)) + t2 = otio.opentime.RationalTime(30.2) + self.assertTrue(t1.strictly_equal(t2)) + t3 = otio.opentime.RationalTime(60.4, 2.0) + self.assertFalse(t1.strictly_equal(t3)) + + def test_rounding(self): + t1 = otio.opentime.RationalTime(30.2) + self.assertEqual(t1.floor_value(), otio.opentime.RationalTime(30.0)) + self.assertEqual(t1.ceil_value(), otio.opentime.RationalTime(31.0)) + self.assertEqual(t1.round_value(), otio.opentime.RationalTime(30.0)) + t2 = otio.opentime.RationalTime(30.8) + self.assertEqual(t2.floor_value(), otio.opentime.RationalTime(30.0)) + self.assertEqual(t2.ceil_value(), otio.opentime.RationalTime(31.0)) + self.assertEqual(t2.round_value(), otio.opentime.RationalTime(31.0)) + def test_comparison(self): t1 = otio.opentime.RationalTime(15.2) t2 = otio.opentime.RationalTime(15.6) From 0012fe1386a901766b349cc548994ff9561c6584 Mon Sep 17 00:00:00 2001 From: Darby Johnston Date: Tue, 5 Dec 2023 17:32:44 -0800 Subject: [PATCH 3/3] Revert to short names Signed-off-by: Darby Johnston --- src/opentime/rationalTime.h | 6 +++--- src/opentime/timeRange.h | 2 +- .../opentime-bindings/opentime_rationalTime.cpp | 6 +++--- tests/test_opentime.cpp | 12 ++++++------ tests/test_opentime.py | 12 ++++++------ 5 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/opentime/rationalTime.h b/src/opentime/rationalTime.h index ed70b2b67..373324454 100644 --- a/src/opentime/rationalTime.h +++ b/src/opentime/rationalTime.h @@ -87,20 +87,20 @@ class RationalTime // Return a RationalTime with the largest integer value not greater than // this value. - RationalTime floor_value() const + RationalTime floor() const { return RationalTime{ std::floor(_value), _rate }; } // Return a RationalTime with the smallest integer value not less than // this value. - RationalTime ceil_value() const + RationalTime ceil() const { return RationalTime{ std::ceil(_value), _rate }; } // Return a RationalTime with the nearest integer value to this value. - RationalTime round_value() const + RationalTime round() const { return RationalTime{ std::round(_value), _rate }; } diff --git a/src/opentime/timeRange.h b/src/opentime/timeRange.h index f5d25df78..e4cad571c 100644 --- a/src/opentime/timeRange.h +++ b/src/opentime/timeRange.h @@ -62,7 +62,7 @@ class TimeRange if ((et - _start_time.rescaled_to(_duration))._value > 1) { return _duration._value != std::floor(_duration._value) - ? et.floor_value() + ? et.floor() : et - RationalTime(1, _duration._rate); } else diff --git a/src/py-opentimelineio/opentime-bindings/opentime_rationalTime.cpp b/src/py-opentimelineio/opentime-bindings/opentime_rationalTime.cpp index 34172357f..a311b5d0a 100644 --- a/src/py-opentimelineio/opentime-bindings/opentime_rationalTime.cpp +++ b/src/py-opentimelineio/opentime-bindings/opentime_rationalTime.cpp @@ -82,9 +82,9 @@ or if the rate is less than or equal to zero. "other"_a) .def("almost_equal", &RationalTime::almost_equal, "other"_a, "delta"_a = 0) .def("strictly_equal", &RationalTime::strictly_equal, "other"_a) - .def("floor_value", &RationalTime::floor_value) - .def("ceil_value", &RationalTime::ceil_value) - .def("round_value", &RationalTime::round_value) + .def("floor", &RationalTime::floor) + .def("ceil", &RationalTime::ceil) + .def("round", &RationalTime::round) .def("__copy__", [](RationalTime rt) { return rt; }) diff --git a/tests/test_opentime.cpp b/tests/test_opentime.cpp index c83396498..2569522a4 100644 --- a/tests/test_opentime.cpp +++ b/tests/test_opentime.cpp @@ -51,13 +51,13 @@ main(int argc, char** argv) tests.add_test("test_rounding", [] { otime::RationalTime t1(30.2); - assertEqual(t1.floor_value(), otime::RationalTime(30.0)); - assertEqual(t1.ceil_value(), otime::RationalTime(31.0)); - assertEqual(t1.round_value(), otime::RationalTime(30.0)); + assertEqual(t1.floor(), otime::RationalTime(30.0)); + assertEqual(t1.ceil(), otime::RationalTime(31.0)); + assertEqual(t1.round(), otime::RationalTime(30.0)); otime::RationalTime t2(30.8); - assertEqual(t2.floor_value(), otime::RationalTime(30.0)); - assertEqual(t2.ceil_value(), otime::RationalTime(31.0)); - assertEqual(t2.round_value(), otime::RationalTime(31.0)); + assertEqual(t2.floor(), otime::RationalTime(30.0)); + assertEqual(t2.ceil(), otime::RationalTime(31.0)); + assertEqual(t2.round(), otime::RationalTime(31.0)); }); tests.add_test("test_from_time_string", [] { diff --git a/tests/test_opentime.py b/tests/test_opentime.py index 4445e385c..81f03bd7f 100755 --- a/tests/test_opentime.py +++ b/tests/test_opentime.py @@ -55,13 +55,13 @@ def test_strict_equality(self): def test_rounding(self): t1 = otio.opentime.RationalTime(30.2) - self.assertEqual(t1.floor_value(), otio.opentime.RationalTime(30.0)) - self.assertEqual(t1.ceil_value(), otio.opentime.RationalTime(31.0)) - self.assertEqual(t1.round_value(), otio.opentime.RationalTime(30.0)) + self.assertEqual(t1.floor(), otio.opentime.RationalTime(30.0)) + self.assertEqual(t1.ceil(), otio.opentime.RationalTime(31.0)) + self.assertEqual(t1.round(), otio.opentime.RationalTime(30.0)) t2 = otio.opentime.RationalTime(30.8) - self.assertEqual(t2.floor_value(), otio.opentime.RationalTime(30.0)) - self.assertEqual(t2.ceil_value(), otio.opentime.RationalTime(31.0)) - self.assertEqual(t2.round_value(), otio.opentime.RationalTime(31.0)) + self.assertEqual(t2.floor(), otio.opentime.RationalTime(30.0)) + self.assertEqual(t2.ceil(), otio.opentime.RationalTime(31.0)) + self.assertEqual(t2.round(), otio.opentime.RationalTime(31.0)) def test_comparison(self): t1 = otio.opentime.RationalTime(15.2)