Permalink
Browse files

Merge pull request #9 from gsarkis/nearodd

Implement NearOdd rounding
  • Loading branch information...
gsarkis committed Feb 25, 2016
2 parents b9b15bd + 031d916 commit 284381fa10ce57a055dd0c879d0c47a98a6bf942
Showing with 485 additions and 0 deletions.
  1. +1 −0 README.md
  2. +187 −0 include/fi/private/rounding/NearOdd.hpp
  3. +43 −0 include/fi/rounding/NearOdd.hpp
  4. +254 −0 tests/NearOdd_test.cpp
View
@@ -50,6 +50,7 @@ The `Fi::Fixed<TOTAL_WIDTH, FRACTION_WIDTH, SIGNEDNESS, OVERFLOW, ROUNDING>` dat
| `Fi::Floor` | Round towards negative infinity. |
| `Fi::Fix` | Round towards zero. |
| `Fi::NearEven` | Round to nearest representable value. Ties are rounded towards an LSB of 0. |
+| `Fi::NearOdd` | Round to nearest representable value. Ties are rounded towards an LSB of 1. |
#### Overflow
@@ -0,0 +1,187 @@
+/*
+
+ *Copyright © 2013 Gabi Sarkis.
+ *Copyright © 2013 Alexandre Raymond.
+
+ *This file is part of the C++ Fixed-Point Library (LibFi).
+
+ *LibFi 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.
+
+ *LibFi 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 LibFi. If not, see <http://www.gnu.org/licenses/>.
+
+ */
+
+#ifndef FI_PRIVATE_ROUNDING_NEARODD_HPP
+#define FI_PRIVATE_ROUNDING_NEARODD_HPP
+
+#include "fi/private/Fi.hpp"
+#include "fi/private/DoubleConversion.hpp"
+
+#include <string>
+#include <iostream>
+#include <utility>
+
+namespace Fi {
+
+ /**
+ *\ingroup rounding
+ *\brief Round towards nearest, ties towards odd values.
+
+ *If rounding occurs, the assigned value is rounded (up or down)
+ *to the nearest value. Ties are rounded towards nearest odd value,
+ *i.e. towards a lsb of '0'.
+
+ *\tparam T Fi::Traits of the fixed-point type.
+
+ *\tparam T Fi::Traits of the fixed-point type.
+ */
+ template <typename T>
+ struct NearOdd {
+
+ /**\internal
+ *\brief Round towards nearest, ties towards even values.
+ *\param n Fixed-point number to be rounded.
+ *\return The rounded value and -1 (+1) indicating that
+ *positive (negative) numbers can decrease (increase) in value
+ *as a result of rounding, or 0 if the input \c n is zero.
+ */
+ static std::pair<typename T::valtype, int>
+ round(const typename T::valtype& n);
+
+ /**\internal
+ *\brief Round towards nearest, ties towards even values.
+ *\param fl Original floating-point number.
+ *\param n Fixed-point number to be rounded.
+ *\return The rounded value and -1 (+1) indicating that
+ *positive (negative) numbers can decrease (increase) in value
+ *as a result of rounding, or 0 if the input \c fl is zero.
+ */
+ static std::pair<typename T::valtype, int>
+ round(double fl, const typename T::valtype& n);
+
+ /**\internal
+ *\brief Round towards nearest, ties towards even values.
+ *\param str Original string representation of number.
+ *\param n Fixed-point number to be rounded.
+ *\return The rounded value and -1 (+1) indicating that
+ *positive (negative) numbers can decrease (increase) in value
+ *as a result of rounding, or 0 if the input \c str is zero.
+ */
+ static std::pair<typename T::valtype, int>
+ round(const std::string& str, const typename T::valtype& n);
+
+ };
+
+}
+
+template <typename T>
+inline std::pair<typename T::valtype, int> Fi::NearOdd<T>::
+round(const typename T::valtype& n) {
+
+ int direction = 0;
+ typename T::valtype ret = 0;
+
+ if (n != 0) {
+
+ ret = n >> T::FRACTION_LENGTH;
+
+ if ((n & T::F_MASK) == (1 << (T::FRACTION_LENGTH-1))) {
+ if ((n & (1 << T::FRACTION_LENGTH)) == 0) {
+ ret += 1;
+ direction = 1;
+ }
+ else {
+ direction = -1;
+ }
+ }
+ else if ((n & T::F_MASK) > (1 << (T::FRACTION_LENGTH-1))) {
+ ret += 1;
+ direction = 1;
+ }
+ else { //if ((n & T::F_MASK) < (1 << (T::FRACTION_LENGTH-1))) {
+ direction = -1;
+ }
+
+ }
+
+ return std::make_pair(ret, direction);
+
+}
+
+template <typename T>
+inline std::pair<typename T::valtype, int> Fi::NearOdd<T>::
+round(double fl, const typename T::valtype& n) {
+
+ int direction = 0;
+ typename T::valtype ret = 0;
+
+ if (fl != 0.0) {
+ ret = n >> T::FRACTION_LENGTH;
+
+ if ((n & T::F_MASK) == (1 << (T::FRACTION_LENGTH-1))) {
+ if ((n & (1 << T::FRACTION_LENGTH)) == 0) {
+ ret += 1;
+ direction = 1;
+ }
+ else {
+ direction = -1;
+ }
+ }
+ else if ((n & T::F_MASK) > (1 << (T::FRACTION_LENGTH-1))) {
+ ret += 1;
+ direction = 1;
+ }
+ else { //if ((n & T::F_MASK) < (1 << (T::FRACTION_LENGTH-1))) {
+ direction = -1;
+ }
+
+ }
+
+ return std::make_pair(ret, direction);
+
+}
+
+template <typename T>
+inline std::pair<typename T::valtype, int> Fi::NearOdd<T>::
+round(const std::string& str, const typename T::valtype& n) {
+
+ int direction = 0;
+ typename T::valtype ret = 0;
+
+ if (str != "0.0") {
+
+ ret = n >> T::FRACTION_LENGTH;
+
+ if ((n & T::F_MASK) == (1 << (T::FRACTION_LENGTH-1))) {
+ if ((n & (1 << T::FRACTION_LENGTH)) == 0) {
+ ret += 1;
+ direction = 1;
+ }
+ else {
+ direction = -1;
+ }
+ }
+ else if ((n & T::F_MASK) > (1 << (T::FRACTION_LENGTH-1))) {
+ ret += 1;
+ direction = 1;
+ }
+ else { //if ((n & T::F_MASK) < (1 << (T::FRACTION_LENGTH-1))) {
+ direction = -1;
+ }
+
+ }
+
+ return std::make_pair(ret, direction);
+
+}
+
+#endif
@@ -0,0 +1,43 @@
+/*
+
+ *Copyright © 2011-2012 Gabi Sarkis.
+ *Copyright © 2013 Alexandre Raymond.
+
+ *This file is part of the C++ Fixed-Point Library (LibFi).
+
+ *LibFi 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.
+
+ *LibFi 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 LibFi. If not, see <http://www.gnu.org/licenses/>.
+
+ */
+
+#ifndef FI_ROUNDING_NEARODD_HPP
+#define FI_ROUNDING_NEARODD_HPP
+
+namespace Fi {
+ /**
+ *\ingroup rounding
+ *\brief Round towards the nearest value.
+
+ *A value is rounded towards the nearest value, except for ties,
+ *which are settled towards the nearest odd value.
+
+ *\tparam T Fi::Traits of the fixed-point type.
+ */
+ template <typename T>
+ struct NearOdd;
+
+}
+
+#include "fi/private/rounding/NearOdd.hpp"
+
+#endif
Oops, something went wrong.

0 comments on commit 284381f

Please sign in to comment.