diff --git a/app/common/rational.cpp b/app/common/rational.cpp index c5b537af3..f835fa904 100644 --- a/app/common/rational.cpp +++ b/app/common/rational.cpp @@ -5,12 +5,14 @@ namespace olive { +const rational rational::NaN = rational(0, 0); + rational rational::fromDouble(const double &flt, bool* ok) { if (qIsNaN(flt)) { // Return NaN rational if (ok) *ok = false; - return rational(0, 0); + return NaN; } // Use FFmpeg function for the time being @@ -45,7 +47,7 @@ rational rational::fromString(const QString &str, bool* ok) if (ok) { *ok = false; } - return rational(0, 0); + return NaN; } } @@ -57,16 +59,12 @@ void rational::fix_signs() if (denom_ < 0) { denom_ = -denom_; numer_ = -numer_; - } - - // Normalize to 0/1 if numerator is zero - if (numer_ == intType(0)) { - denom_ = intType(1); - } - - // Normalize to 0/0 (aka NaN) if denominator is zero - if (denom_ == intType(0)) { + } else if (denom_ == intType(0)) { + // Normalize to 0/0 (aka NaN) if denominator is zero numer_ = intType(0); + } else if (numer_ == intType(0)) { + // Normalize to 0/1 if numerator is zero + denom_ = intType(1); } } @@ -438,5 +436,9 @@ uint qHash(const rational &r, uint seed) QDebug operator<<(QDebug debug, const olive::rational &r) { - return debug.space() << r.toDouble(); + if (r.isNaN()) { + return debug.space() << "NaN"; + } else { + return debug.space() << r.toDouble(); + } } diff --git a/app/common/rational.h b/app/common/rational.h index 3a3d19411..673988eea 100644 --- a/app/common/rational.h +++ b/app/common/rational.h @@ -58,9 +58,10 @@ public: } static rational fromDouble(const double& flt, bool *ok = nullptr); - static rational fromString(const QString& str, bool* ok = nullptr); + static const rational NaN; + //Assignment Operators const rational& operator=(const rational &rhs); const rational& operator+=(const rational &rhs); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index d64bc20f5..926af5116 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -66,4 +66,5 @@ function(olive_add_test GROUP NAME SOURCE) endfunction() add_subdirectory(compositing) +add_subdirectory(general) add_subdirectory(timeline) diff --git a/tests/general/CMakeLists.txt b/tests/general/CMakeLists.txt new file mode 100644 index 000000000..4b2c84b44 --- /dev/null +++ b/tests/general/CMakeLists.txt @@ -0,0 +1,17 @@ +# Olive - Non-Linear Video Editor +# Copyright (C) 2021 Olive Team +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +olive_add_test(General rational-tests rational-tests.cpp) diff --git a/tests/general/rational-tests.cpp b/tests/general/rational-tests.cpp new file mode 100644 index 000000000..8e9de8122 --- /dev/null +++ b/tests/general/rational-tests.cpp @@ -0,0 +1,64 @@ +/*** + + Olive - Non-Linear Video Editor + Copyright (C) 2021 Olive Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +***/ + +#include "testutil.h" + +#include "common/rational.h" + +namespace olive { + +OLIVE_ADD_TEST(RationalDefaults) +{ + // By default, rationals are valid 0/1 + rational basic_constructor; + OLIVE_ASSERT(basic_constructor.isNull()); + OLIVE_ASSERT(!basic_constructor.isNaN()); + + OLIVE_TEST_END; +} + +OLIVE_ADD_TEST(RationalNaN) +{ + // Create a NaN with a 0 denominator + rational nan = rational(0, 0); + OLIVE_ASSERT(nan.isNaN()); + OLIVE_ASSERT(nan.isNull()); + + // Create a non-NaN with a zero numerator + rational zero_nonnan(0, 999); + OLIVE_ASSERT(zero_nonnan.isNull()); + OLIVE_ASSERT(!zero_nonnan.isNaN()); + + // Create a non-NaN with a non-zero numerator + rational nonzer_nonnan(1, 30); + OLIVE_ASSERT(!nonzer_nonnan.isNull()); + OLIVE_ASSERT(!nonzer_nonnan.isNaN()); + + OLIVE_TEST_END; +} + +OLIVE_ADD_TEST(RationalNaNConstant) +{ + OLIVE_ASSERT(rational::NaN.isNaN()); + + OLIVE_TEST_END; +} + +}