-
-
Notifications
You must be signed in to change notification settings - Fork 68
Implementation of Unum 2.0 #482
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
singul4ri7y
wants to merge
6
commits into
stillwater-sc:main
Choose a base branch
from
singul4ri7y:unum
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 1 commit
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
f12d95d
Skeletal implementation of Unum 2.0
singul4ri7y a9b82ea
Fix point multiplication bug and add support for reverse interval
singul4ri7y ae0d9ce
Added pow() and abs() + some optimizations
singul4ri7y af47324
Refactor according to Codacy suggestions
singul4ri7y 6450216
Added op table/matrix for efficient operations
singul4ri7y d0415eb
Merge branch 'stillwater-sc:main' into unum
singul4ri7y File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,320 @@ | ||
| #pragma once | ||
| // unum2.hpp: definition of the flexible configuration universal number system | ||
| // | ||
| // Copyright (C) 2017-2021 Stillwater Supercomputing, Inc. | ||
| // | ||
| // This file is part of the universal numbers project, which is released under an MIT Open Source license. | ||
| #include <cassert> | ||
| #include <limits> | ||
|
|
||
| #include <universal/native/ieee754.hpp> | ||
| #include <universal/number/shared/nan_encoding.hpp> | ||
| #include <universal/number/shared/infinite_encoding.hpp> | ||
| #include <universal/number/shared/specific_value_encoding.hpp> | ||
|
|
||
| namespace sw { namespace universal { | ||
|
|
||
| // Forward definitions | ||
| template<unsigned esizesize, unsigned fsizesize, typename bt> class unum2; | ||
| template<unsigned esizesize, unsigned fsizesize, typename bt> unum2<esizesize,fsizesize,bt> abs(const unum2<esizesize,fsizesize,bt>& v); | ||
|
|
||
| // template class reprfsizesizeenting a value in scientific notation, using a template size for the number of fraction bits | ||
| template<unsigned esizesize, unsigned fsizesize, typename bt = uint8_t> | ||
| class unum2 { | ||
| public: | ||
| static constexpr unsigned UTAGSIZE = 1 + esizesize + fsizesize; | ||
| static constexpr unsigned UTAGMASK = unsigned(~(int64_t(-1) << UTAGSIZE)); | ||
| static constexpr unsigned EBITSMASK = 1; | ||
| static constexpr unsigned FBITSMASK = 2; | ||
|
|
||
| unum2() {} | ||
|
|
||
| // specific value constructor | ||
| constexpr unum2(const SpecificValue code) { | ||
| switch (code) { | ||
| case SpecificValue::maxpos: | ||
| maxpos(); | ||
| break; | ||
| case SpecificValue::minpos: | ||
| minpos(); | ||
| break; | ||
| default: | ||
| zero(); | ||
| break; | ||
| case SpecificValue::minneg: | ||
| minneg(); | ||
| break; | ||
| case SpecificValue::maxneg: | ||
| maxneg(); | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| unum2(signed char initial_value) { *this = initial_value; } | ||
| unum2(short initial_value) { *this = initial_value; } | ||
| unum2(int initial_value) { *this = initial_value; } | ||
| unum2(long long initial_value) { *this = initial_value; } | ||
| unum2(unsigned long long initial_value) { *this = initial_value; } | ||
| unum2(float initial_value) { *this = initial_value; } | ||
| unum2(double initial_value) { *this = initial_value; } | ||
| unum2(long double initial_value) { *this = initial_value; } | ||
| unum2(const unum2& rhs) { *this = rhs; } | ||
|
|
||
| // assignment operators | ||
| unum2& operator=(signed char rhs) { | ||
| return *this = (long long)(rhs); | ||
| } | ||
| unum2& operator=(short rhs) { | ||
| return *this = (long long)(rhs); | ||
| } | ||
| unum2& operator=(int rhs) { | ||
| return *this = (long long)(rhs); | ||
| } | ||
| unum2& operator=(long long rhs) { | ||
| return *this; | ||
| } | ||
| unum2& operator=(unsigned long long rhs) { | ||
| return *this; | ||
| } | ||
| unum2& operator=(float rhs) { | ||
|
|
||
| return *this; | ||
| } | ||
| unum2& operator=(double rhs) { | ||
|
|
||
| return *this; | ||
| } | ||
| unum2& operator=(long double rhs) { | ||
|
|
||
| return *this; | ||
| } | ||
|
|
||
| // arithmetic operators | ||
| // prefix operator | ||
| unum2 operator-() const { | ||
| return *this; | ||
| } | ||
|
|
||
| unum2& operator+=(const unum2& rhs) { | ||
| return *this; | ||
| } | ||
| unum2& operator+=(double rhs) { | ||
| return *this += unum2(rhs); | ||
| } | ||
| unum2& operator-=(const unum2& rhs) { | ||
|
|
||
| return *this; | ||
| } | ||
| unum2& operator-=(double rhs) { | ||
| return *this -= unum2<esizesize, fsizesize>(rhs); | ||
| } | ||
| unum2& operator*=(const unum2& rhs) { | ||
|
|
||
| return *this; | ||
| } | ||
| unum2& operator*=(double rhs) { | ||
| return *this *= unum2<esizesize, fsizesize>(rhs); | ||
| } | ||
| unum2& operator/=(const unum2& rhs) { | ||
|
|
||
| return *this; | ||
| } | ||
| unum2& operator/=(double rhs) { | ||
| return *this /= unum2<esizesize, fsizesize>(rhs); | ||
| } | ||
| unum2& operator++() { | ||
| return *this; | ||
| } | ||
| unum2 operator++(int) { | ||
| unum2 tmp(*this); | ||
| operator++(); | ||
| return tmp; | ||
| } | ||
| unum2& operator--() { | ||
| return *this; | ||
| } | ||
| unum2 operator--(int) { | ||
| unum2 tmp(*this); | ||
| operator--(); | ||
| return tmp; | ||
| } | ||
|
|
||
| // modifiers | ||
|
|
||
| /// <summary> | ||
|
||
| /// clear the content of this bfloat to zero | ||
| /// </summary> | ||
| /// <returns>void</returns> | ||
| inline constexpr void clear() noexcept { | ||
|
|
||
| } | ||
| /// <summary> | ||
| /// set the number to +0 | ||
| /// </summary> | ||
| /// <returns>void</returns> | ||
| inline constexpr void setzero() noexcept { clear(); } | ||
| /// <summary> | ||
| /// set the number to +inf | ||
| /// </summary> | ||
| /// <param name="sign">boolean to make it + or - infinity, default is -inf</param> | ||
| /// <returns>void</returns> | ||
| inline constexpr void setinf(bool sign = true) noexcept { | ||
|
|
||
| } | ||
| /// <summary> | ||
| /// set the number to a quiet NaN (+nan) or a signalling NaN (-nan, default) | ||
| /// </summary> | ||
| /// <param name="sign">boolean to make it + or - infinity, default is -inf</param> | ||
| /// <returns>void</returns> | ||
| inline constexpr void setnan(int NaNType = NAN_TYPE_SIGNALLING) noexcept { | ||
| } | ||
| // specific number system values of interest | ||
| inline constexpr unum2& maxpos() noexcept { | ||
|
|
||
| return *this; | ||
| } | ||
| inline constexpr unum2& minpos() noexcept { | ||
|
|
||
| return *this; | ||
| } | ||
| inline constexpr unum2& zero() noexcept { | ||
|
|
||
| return *this; | ||
| } | ||
| inline constexpr unum2& minneg() noexcept { | ||
|
|
||
| return *this; | ||
| } | ||
| inline constexpr unum2& maxneg() noexcept { | ||
|
|
||
| return *this; | ||
| } | ||
|
|
||
| // selectors | ||
| inline bool isneg() const { return false; } | ||
| inline bool iszero() const { return false; } | ||
| inline bool isinf() const { return false; } | ||
| inline bool isnan() const { return false; } | ||
| inline bool issnan() const { return false; } | ||
| inline bool isqnan() const { return false; } | ||
| inline bool sign() const { return false; } | ||
| inline int32_t scale() const { return false; } // 2^+-2^31 should be enough to capture empirical use cases | ||
| inline std::string get() const { return std::string("tbd"); } | ||
|
|
||
|
|
||
| long double to_long_double() const { | ||
| return 0.0l; | ||
| } | ||
| double to_double() const { | ||
| return 0.0; | ||
| } | ||
| float to_float() const { | ||
| return 0.0f; | ||
| } | ||
| // Maybe remove explicit | ||
| explicit operator long double() const { return to_long_double(); } | ||
| explicit operator double() const { return to_double(); } | ||
| explicit operator float() const { return to_float(); } | ||
|
|
||
| private: | ||
|
|
||
| // template parameters need namfsizesize different from class template parameters (for gcc and clang) | ||
| template<unsigned nesizesize, unsigned nfsizesize, typename nbt> | ||
| friend std::ostream& operator<< (std::ostream& ostr, const unum2<nesizesize,nfsizesize,nbt>& r); | ||
| template<unsigned nesizesize, unsigned nfsizesize, typename nbt> | ||
| friend std::istream& operator>> (std::istream& istr, unum2<nesizesize,nfsizesize,nbt>& r); | ||
|
|
||
| template<unsigned nesizesize, unsigned nfsizesize, typename nbt> | ||
| friend bool operator==(const unum2<nesizesize,nfsizesize,nbt>& lhs, const unum2<nesizesize,nfsizesize,nbt>& rhs); | ||
| template<unsigned nesizesize, unsigned nfsizesize, typename nbt> | ||
| friend bool operator!=(const unum2<nesizesize,nfsizesize,nbt>& lhs, const unum2<nesizesize,nfsizesize,nbt>& rhs); | ||
| template<unsigned nesizesize, unsigned nfsizesize, typename nbt> | ||
| friend bool operator< (const unum2<nesizesize,nfsizesize,nbt>& lhs, const unum2<nesizesize,nfsizesize,nbt>& rhs); | ||
| template<unsigned nesizesize, unsigned nfsizesize, typename nbt> | ||
| friend bool operator> (const unum2<nesizesize,nfsizesize,nbt>& lhs, const unum2<nesizesize,nfsizesize,nbt>& rhs); | ||
| template<unsigned nesizesize, unsigned nfsizesize, typename nbt> | ||
| friend bool operator<=(const unum2<nesizesize,nfsizesize,nbt>& lhs, const unum2<nesizesize,nfsizesize,nbt>& rhs); | ||
| template<unsigned nesizesize, unsigned nfsizesize, typename nbt> | ||
| friend bool operator>=(const unum2<nesizesize,nfsizesize,nbt>& lhs, const unum2<nesizesize,nfsizesize,nbt>& rhs); | ||
| }; | ||
|
|
||
| ////////////////////// operators | ||
| template<unsigned nesizesize, unsigned nfsizesize, typename nbt> | ||
| inline std::ostream& operator<<(std::ostream& ostr, const unum2<nesizesize,nfsizesize,nbt>& v) { | ||
|
|
||
| return ostr; | ||
| } | ||
|
|
||
| template<unsigned nesizesize, unsigned nfsizesize, typename nbt> | ||
| inline std::istream& operator>>(std::istream& istr, const unum2<nesizesize,nfsizesize,nbt>& v) { | ||
| istr >> v._fraction; | ||
| return istr; | ||
| } | ||
|
|
||
| template<unsigned nesizesize, unsigned nfsizesize, typename nbt> | ||
| inline bool operator==(const unum2<nesizesize,nfsizesize,nbt>& lhs, const unum2<nesizesize,nfsizesize,nbt>& rhs) { return false; } | ||
| template<unsigned nesizesize, unsigned nfsizesize, typename nbt> | ||
| inline bool operator!=(const unum2<nesizesize,nfsizesize,nbt>& lhs, const unum2<nesizesize,nfsizesize,nbt>& rhs) { return !operator==(lhs, rhs); } | ||
| template<unsigned nesizesize, unsigned nfsizesize, typename nbt> | ||
| inline bool operator< (const unum2<nesizesize,nfsizesize,nbt>& lhs, const unum2<nesizesize,nfsizesize,nbt>& rhs) { return false; } | ||
| template<unsigned nesizesize, unsigned nfsizesize, typename nbt> | ||
| inline bool operator> (const unum2<nesizesize,nfsizesize,nbt>& lhs, const unum2<nesizesize,nfsizesize,nbt>& rhs) { return operator< (rhs, lhs); } | ||
| template<unsigned nesizesize, unsigned nfsizesize, typename nbt> | ||
| inline bool operator<=(const unum2<nesizesize,nfsizesize,nbt>& lhs, const unum2<nesizesize,nfsizesize,nbt>& rhs) { return !operator> (lhs, rhs); } | ||
| template<unsigned nesizesize, unsigned nfsizesize, typename nbt> | ||
| inline bool operator>=(const unum2<nesizesize,nfsizesize,nbt>& lhs, const unum2<nesizesize,nfsizesize,nbt>& rhs) { return !operator< (lhs, rhs); } | ||
|
|
||
| // posit - posit binary arithmetic operators | ||
| // BINARY ADDITION | ||
| template<unsigned esizesize, unsigned fsizesize, typename bt> | ||
| inline unum2<esizesize, fsizesize, bt> operator+(const unum2<esizesize, fsizesize, bt>& lhs, const unum2<esizesize, fsizesize, bt>& rhs) { | ||
| unum2<esizesize, fsizesize> sum(lhs); | ||
| sum += rhs; | ||
| return sum; | ||
| } | ||
| // BINARY SUBTRACTION | ||
| template<unsigned esizesize, unsigned fsizesize, typename bt> | ||
| inline unum2<esizesize, fsizesize, bt> operator-(const unum2<esizesize, fsizesize, bt>& lhs, const unum2<esizesize, fsizesize, bt>& rhs) { | ||
| unum2<esizesize, fsizesize> diff(lhs); | ||
| diff -= rhs; | ||
| return diff; | ||
| } | ||
| // BINARY MULTIPLICATION | ||
| template<unsigned esizesize, unsigned fsizesize, typename bt> | ||
| inline unum2<esizesize, fsizesize, bt> operator*(const unum2<esizesize, fsizesize, bt>& lhs, const unum2<esizesize, fsizesize, bt>& rhs) { | ||
| unum2<esizesize, fsizesize> mul(lhs); | ||
| mul *= rhs; | ||
| return mul; | ||
| } | ||
| // BINARY DIVISION | ||
| template<unsigned esizesize, unsigned fsizesize, typename bt> | ||
| inline unum2<esizesize, fsizesize, bt> operator/(const unum2<esizesize, fsizesize, bt>& lhs, const unum2<esizesize, fsizesize, bt>& rhs) { | ||
| unum2<esizesize, fsizesize> ratio(lhs); | ||
| ratio /= rhs; | ||
| return ratio; | ||
| } | ||
|
|
||
|
|
||
| template<unsigned esizesize, unsigned fsizesize, typename bt> | ||
| inline std::string components(const unum2<esizesize,fsizesize,bt>& v) { | ||
| std::stringstream s; | ||
| if (v.iszero()) { | ||
| s << " zero b" << std::setw(esizesize) << v.fraction(); | ||
| return s.str(); | ||
| } | ||
| else if (v.isinf()) { | ||
| s << " infinite b" << std::setw(esizesize) << v.fraction(); | ||
| return s.str(); | ||
| } | ||
| s << "(" << (v.sign() ? "-" : "+") << "," << v.scale() << "," << v.fraction() << ")"; | ||
| return s.str(); | ||
| } | ||
|
|
||
| /// Magnitude of a scientific notation value (equivalent to turning the sign bit off). | ||
| template<unsigned esizesize, unsigned fsizesize, typename bt> | ||
| unum2<esizesize,fsizesize> abs(const unum2<esizesize,fsizesize,bt>& v) { | ||
| return unum2<esizesize,fsizesize>(false, v.scale(), v.fraction(), v.isZero()); | ||
| } | ||
|
|
||
|
|
||
| }} // namespace sw::universal | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
need the more modern copyright header that is being used throughout the rest of the library:
// Copyright (C) 2017 Stillwater Supercomputing, Inc.
// SPDX-License-Identifier: MIT
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the old unum2 header file. We can ignore this. As for the copyright header, I will be adding it once I finish up, as the code [and the files associated] is now stable.