diff --git a/.github/workflows/commit-builds.yml b/.github/workflows/commit-builds.yml new file mode 100644 index 00000000..9bb12bef --- /dev/null +++ b/.github/workflows/commit-builds.yml @@ -0,0 +1,88 @@ +name: Data Builds +on: + push: + branches: + - '*' + - '*/*' + - '**' + - '!production' +env: + BUILD_TYPE: Debug +jobs: + prep: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Get Conan + uses: turtlebrowser/get-conan@v1.0 + - name: Cache Conan packages + uses: actions/cache@v3 + id: cache-conan + env: + cache-name: cache-conan + with: + key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/conanfile.py') }} + path: | + ~/.conan/ + - if: ${{ steps.cache-conan.outputs.cache-hit != 'true' }} + name: Create default profile + run: conan profile new default --detect + - if: ${{ steps.cache-conan.outputs.cache-hit != 'true' }} + name: Update profile 11 + run: conan profile update settings.compiler.libcxx=libstdc++11 default + - if: ${{ steps.cache-conan.outputs.cache-hit != 'true' }} + name: Update profile version + run: conan profile update settings.compiler.version=10 default + - if: ${{ steps.cache-conan.outputs.cache-hit != 'true' }} + name: Add conan remote + run: | + conan config set general.revisions_enabled=True + conan remote add proofofwork https://conan.pow.co/artifactory/api/conan/conan + conan user -p ${{ secrets.CONAN_USER_KEY }} -r proofofwork github + test: + runs-on: ubuntu-latest + needs: + - prep + steps: + - uses: actions/checkout@v2 + - name: Get Conan + uses: turtlebrowser/get-conan@v1.0 + - name: Cache Conan packages + uses: actions/cache@v3 + env: + cache-name: cache-conan + with: + key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/conanfile.py') }} + path: | + ~/.conan/ + - name: run tests + run: | + mkdir test_build + cd test_build + conan install .. -r=proofofwork + cmake .. -DPACKAGE_TESTS=ON + cmake --build . + cd bin + for f in test*; do "./$f" ; done + upload: + runs-on: ubuntu-latest + needs: + - test + steps: + - uses: actions/checkout@v2 + - name: Get Conan + uses: turtlebrowser/get-conan@v1.0 + - name: Cache Conan packages + uses: actions/cache@v3 + env: + cache-name: cache-conan + with: + key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/conanfile.py') }} + path: | + ~/.conan/ + - name: Run Conan + run: | + export CURRENT_VERSION=`git rev-parse --short HEAD` + conan install . -r proofofwork + conan create . proofofwork/unstable + conan upload data/${CURRENT_VERSION}@proofofwork/unstable -r proofofwork --all \ No newline at end of file diff --git a/.github/workflows/conan.yml b/.github/workflows/conan.yml deleted file mode 100644 index 7d78846e..00000000 --- a/.github/workflows/conan.yml +++ /dev/null @@ -1,38 +0,0 @@ -name: Conan development -on: - push: - branches: - - '*' - - '*/*' - - '**' - - '!production' - pull_request: - branches: - - '*' - - '*/*' - - '**' - - '!production' -env: - BUILD_TYPE: Debug -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Get Conan - uses: turtlebrowser/get-conan@v1.0 - - name: Create default profile - run: conan profile new default --detect - - name: Update profile 11 - run: conan profile update settings.compiler.libcxx=libstdc++11 default - - name: Update profile version - run: conan profile update settings.compiler.version=10 default - - name: setup conan - run: | - conan config set general.revisions_enabled=True - conan remote add proofofwork https://conan.pow.co/artifactory/api/conan/conan - conan user -p ${{ secrets.CONAN_USER_KEY }} -r proofofwork github - export CURRENT_VERSION=`git rev-parse --short HEAD` - conan install . -r proofofwork - conan create . proofofwork/unstable - conan upload data/${CURRENT_VERSION}@proofofwork/unstable -r proofofwork --all diff --git a/.github/workflows/prcheck-build.yml b/.github/workflows/prcheck-build.yml new file mode 100644 index 00000000..e7847d63 --- /dev/null +++ b/.github/workflows/prcheck-build.yml @@ -0,0 +1,62 @@ +name: Test PR Builds +on: + pull_request: + branches: + - '*' +env: + BUILD_TYPE: Debug +jobs: + prep: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Get Conan + uses: turtlebrowser/get-conan@v1.0 + - name: Cache Conan packages + id: cache-conan + uses: actions/cache@v3 + env: + cache-name: cache-conan-test + with: + key: ${{ runner.os }}-test-${{ env.cache-name }}-${{ hashFiles('**/conanfile.py') }} + path: | + ~/.conan/ + - if: ${{ steps.cache-conan.outputs.cache-hit != 'true' }} + name: Create default profile + run: conan profile new default --detect + - if: ${{ steps.cache-conan.outputs.cache-hit != 'true' }} + name: Update profile 11 + run: conan profile update settings.compiler.libcxx=libstdc++11 default + - if: ${{ steps.cache-conan.outputs.cache-hit != 'true' }} + name: Update profile version + run: conan profile update settings.compiler.version=10 default + - if: ${{ steps.cache-conan.outputs.cache-hit != 'true' }} + name: Add conan remote + run: | + conan config set general.revisions_enabled=True + conan remote add proofofwork https://conan.pow.co/artifactory/api/conan/conan + test: + runs-on: ubuntu-latest + needs: + - prep + steps: + - uses: actions/checkout@v2 + - name: Get Conan + uses: turtlebrowser/get-conan@v1.0 + - name: Cache Conan packages + uses: actions/cache@v3 + env: + cache-name: cache-conan-test + with: + key: ${{ runner.os }}-test-${{ env.cache-name }}-${{ hashFiles('**/conanfile.py') }} + path: | + ~/.conan/ + - name: run tests + run: | + mkdir test_build + cd test_build + conan install .. -r=proofofwork + cmake .. -DPACKAGE_TESTS=ON + cmake --build . + cd bin + for f in test*; do "./$f" ; done \ No newline at end of file diff --git a/.github/workflows/stable-builds.yml b/.github/workflows/stable-builds.yml new file mode 100644 index 00000000..244c405e --- /dev/null +++ b/.github/workflows/stable-builds.yml @@ -0,0 +1,108 @@ +name: Stable Builds +on: + push: + branches: + - production +env: + BUILD_TYPE: Release +jobs: + prep: + runs-on: ubuntu-latest + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - id: release + uses: rymndhng/release-on-push-action@master + with: + bump_version_scheme: patch + use_github_release_notes: true + - name: Check Output Parameters + run: | + echo "Got tag name ${{ steps.release.outputs.tag_name }}" + echo "Got release version ${{ steps.release.outputs.version }}" + - uses: actions/checkout@v2 + - name: Get Conan + uses: turtlebrowser/get-conan@v1.0 + - name: Cache Conan packages + uses: actions/cache@v3 + id: cache-conan + env: + cache-name: cache-conan + with: + key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/conanfile.py') }} + path: | + ~/.conan/ + - if: ${{ steps.cache-conan.outputs.cache-hit != 'true' }} + name: Create default profile + run: conan profile new default --detect + - if: ${{ steps.cache-conan.outputs.cache-hit != 'true' }} + name: Update profile 11 + run: conan profile update settings.compiler.libcxx=libstdc++11 default + - if: ${{ steps.cache-conan.outputs.cache-hit != 'true' }} + name: Update profile version + run: conan profile update settings.compiler.version=10 default + - if: ${{ steps.cache-conan.outputs.cache-hit != 'true' }} + name: Add conan remote + run: | + conan config set general.revisions_enabled=True + conan remote add proofofwork https://conan.pow.co/artifactory/api/conan/conan + conan user -p ${{ secrets.CONAN_USER_KEY }} -r proofofwork github + outputs: + releaseVersion: ${{ steps.release.outputs.tag_name }} + upload: + runs-on: ubuntu-latest + needs: + - prep + steps: + - uses: actions/checkout@v2 + - name: Get Conan + uses: turtlebrowser/get-conan@v1.0 + - name: Cache Conan packages + uses: actions/cache@v3 + env: + cache-name: cache-conan + with: + key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/conanfile.py') }} + path: | + ~/.conan/ + - name: Run Conan + run: | + export CURRENT_VERSION="${{ needs.prep.outputs.releaseVersion }}" + conan install . -r proofofwork + conan create . proofofwork/stable + conan upload data/${CURRENT_VERSION}@proofofwork/stable -r proofofwork --all + release: + runs-on: ubuntu-latest + needs: + - prep + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v2 + - name: Get Conan + uses: turtlebrowser/get-conan@v1.0 + - name: Cache Conan packages + uses: actions/cache@v3 + env: + cache-name: cache-conan + with: + key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/conanfile.py') }} + path: | + ~/.conan/ + - name: prepare release package + run: | + mkdir build + cd build + conan install .. -r=proofofwork + cmake .. -DPACKAGE_TESTS=Off + cmake --build . + export CURRENT_VERSION="${{ needs.prep.outputs.releaseVersion }}" + cp -r ../include ./ + tar -czvf "data-${CURRENT_VERSION}-linux.tar.gz" lib include + - name: Upload release + uses: svenstaro/upload-release-action@v2 + with: + tag: ${{ needs.prep.outputs.releaseVersion }} + file: build/data-${{ needs.prep.outputs.releaseVersion }}-linux.tar.gz + asset_name: data-${{ needs.prep.outputs.releaseVersion }}-linux.tar.gz + diff --git a/.github/workflows/stable.yml b/.github/workflows/stable.yml deleted file mode 100644 index 02262fdf..00000000 --- a/.github/workflows/stable.yml +++ /dev/null @@ -1,57 +0,0 @@ -name: Conan development -on: - push: - branches: - - production -env: - BUILD_TYPE: Release -jobs: - build: - runs-on: ubuntu-latest - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - steps: - - id: release - uses: rymndhng/release-on-push-action@master - with: - bump_version_scheme: patch - use_github_release_notes: true - - name: Check Output Parameters - run: | - echo "Got tag name ${{ steps.release.outputs.tag_name }}" - echo "Got release version ${{ steps.release.outputs.version }}" - - uses: actions/checkout@v2 - - name: Get Conan - uses: turtlebrowser/get-conan@v1.0 - - name: Create default profile - run: conan profile new default --detect - - name: Update profile 11 - run: conan profile update settings.compiler.libcxx=libstdc++11 default - - name: Update profile version - run: conan profile update settings.compiler.version=10 default - - name: setup conan - run: | - conan config set general.revisions_enabled=True - conan remote add proofofwork https://conan.pow.co/artifactory/api/conan/conan - conan user -p ${{ secrets.CONAN_USER_KEY }} -r proofofwork github - export CURRENT_VERSION="${{ steps.release.outputs.tag_name }}" - echo "Current version: ${CURRENT_VERSION}" - conan install . -r proofofwork - conan create . proofofwork/stable -r proofofwork - conan upload data/${CURRENT_VERSION}@proofofwork/stable -r proofofwork --all - - name: prepare release package - run: | - mkdir build - cd build - conan install .. -r=proofofwork - cmake .. -DPACKAGE_TESTS=Off - cmake --build . - export CURRENT_VERSION="${{ steps.release.outputs.tag_name }}" - cp -r ../include ./ - tar -czvf "data-${CURRENT_VERSION}-linux.tar.gz" lib include - - name: Upload release - uses: svenstaro/upload-release-action@v2 - with: - tag: ${{ steps.release.outputs.tag_name }} - file: build/data-${{ steps.release.outputs.tag_name }}-linux.tar.gz - asset_name: data-${{ steps.release.outputs.tag_name }}-linux.tar.gz diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 56f9d10d..00000000 --- a/.travis.yml +++ /dev/null @@ -1,91 +0,0 @@ -language: cpp - -env: - global: - # Ubuntu version - - LINUX_DIST=xenial - - DEPS_DIR=${TRAVIS_BUILD_DIR}/deps - # Global build options and C++ flags - - CXX_FLAGS="-Wall -pedantic -Werror -Wno-variadic-macros -Wno-long-long -Wno-shadow" - # Misc - - RUN_TESTS=true - - COVERAGE=false - -cache: - directories: - - ${TRAVIS_BUILD_DIR}/user/ - -matrix: - include: - - os: linux - dist: xenial - env: CONDA_PYTHON_VERSION=3.6 - sudo: true - compiler: gcc - addons: - apt: - packages: &precise_latest_boost_packages - - gcc-7 - - g++-7 - #- gcov-4.9 - - clang-3.7 - - valgrind - # Misc - - python-yaml - - lcov - - libopencv-dev - - swig - - libcrypto++-dev - - pkg-config - - cmake-data - - libntl-dev - - cmake - sources: &precise_latest_boost_sources - - ubuntu-toolchain-r-test - - llvm-toolchain-xenial-3.7 - - -before_install: - # Combine global build options with OS/compiler-dependent options - - export CMAKE_OPTIONS=${CMAKE_OPTIONS}" "${ENV_CMAKE_OPTIONS} - - export CXX_FLAGS=${CXX_FLAGS}" "${ENV_CXX_FLAGS} - - sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-7 90 --slave /usr/bin/g++ g++ /usr/bin/g++-7 --slave /usr/bin/gcov gcov /usr/bin/gcov-7 - - -install: - - | - if [ ! -d "${TRAVIS_BUILD_DIR}/user/include" ]; then - mkdir tmp; - cd tmp; - wget https://gist.githubusercontent.com/KatrinaAS/9a2d3e841d2d305aee7a4aa71a984334/raw/14a9e4ff36590fa0cff72ebec7d82463ad25ad61/install.sh ; - chmod +x install.sh ; - sudo ${TRAVIS_BUILD_DIR}/tmp/install.sh --prefix=${TRAVIS_BUILD_DIR}/user/ --build-boost; - fi - - sudo ldconfig ${TRAVIS_BUILD_DIR}/user/lib/ - - ls ${TRAVIS_BUILD_DIR}/user/lib/ - - export PKG_CONFIG_PATH="${TRAVIS_BUILD_DIR}/user/lib/pkgconfig:${PKG_CONFIG_PATH}" ; - - echo $PKG_CONFIG_PATH ; - - if [ "$CXX" = "clang++" ] && [ "$TRAVIS_OS_NAME" = "linux" ]; then export CXX="clang++-3.7" CC="clang-3.7"; fi - - echo ${PATH} - - echo ${CXX} - - ${CXX} --version - - ${CXX} -v - - cd /tmp/ - - wget https://github.com/bitcoin-core/secp256k1/archive/master.zip - - unzip master.zip - - cd secp256k1-master - - ./autogen.sh - - ./configure - - make - - sudo make install - - cd ${TRAVIS_BUILD_DIR} - -script: - ############################################################################ - # Build main and tests - ############################################################################ - - mkdir -p build - - cd build - - cmake ${CMAKE_OPTIONS} -DCMAKE_CXX_FLAGS=${CXX_FLAGS} -DBOOST_ROOT=${TRAVIS_BUILD_DIR}/user/ -DBUILD_TESTS=ON .. - - cmake --build . - - ctest . diff --git a/include/data/math/number/bounded/bounded.hpp b/include/data/math/number/bounded/bounded.hpp index 6c71bb1d..2716ecdf 100644 --- a/include/data/math/number/bounded/bounded.hpp +++ b/include/data/math/number/bounded/bounded.hpp @@ -5,903 +5,1047 @@ #ifndef DATA_MATH_NUMBER_BOUNDED #define DATA_MATH_NUMBER_BOUNDED -#include #include -#include -#include -#include #include -#include #include #include +#include +#include +#include +#include +#include namespace data::math::number { - - // satisfies range - template requires (size >= 8) - struct bounded; - - template - bounded operator~(const bounded&); - - template - bounded operator&(const bounded&, const bounded&); - - template - bounded operator|(const bounded&, const bounded&); - - template - bounded operator^(const bounded&, const bounded&); - - template - bounded &operator&=(bounded&, const bounded&); - - template - bounded &operator|=(bounded&, const bounded&); - - template - bounded &operator^=(bounded&, const bounded&); - - template - bounded operator<<(const bounded&, int); - - template - bounded operator>>(const bounded&, int); - - template - bounded &operator<<=(bounded&, int); - - template - bounded &operator>>=(bounded&, int); - - template - bounded operator++(bounded&, int); - - template - bounded &operator++(bounded&); - - template - bounded operator--(bounded&, int); - - template - bounded &operator--(bounded&); - - template - bounded operator+(const bounded&, const bounded&); - - template - bounded &operator+=(bounded&, const bounded&); - - template - bounded operator-(const bounded&, const bounded&); - - template - bounded &operator-=(bounded&, const bounded&); - - template - bounded operator*(const bounded&, const bounded&); - - template - bounded &operator*=(bounded&, const bounded&); -} - -namespace data::math { - - template - using uint = typename number::bounded; - - template - using sint = typename number::bounded; - - template - using uint_little = typename number::bounded; - - template - using uint_big = typename number::bounded; - - template - using sint_little = typename number::bounded; - - template - using sint_big = typename number::bounded; - - // plus and times are associative and commutative - // for both bounded and bytes. - template - struct commutative>, - number::bounded> {}; - - template - struct associative>, - number::bounded> {}; - - template - struct commutative>, - number::bounded> {}; - - template - struct associative>, - number::bounded> {}; - -} + +// satisfies range +template +requires(size >= 8) struct bounded; + +template +bounded operator~(const bounded &); + +template +bounded operator&(const bounded &, + const bounded &); + +template +bounded operator|(const bounded &, + const bounded &); + +template +bounded operator^(const bounded &, + const bounded &); + +template +bounded &operator&=(bounded &, + const bounded &); + +template +bounded &operator|=(bounded &, + const bounded &); + +template +bounded &operator^=(bounded &, + const bounded &); + +template +bounded operator<<(const bounded &, int); + +template +bounded operator>>(const bounded &, int); + +template +bounded &operator<<=(bounded &, int); + +template +bounded &operator>>=(bounded &, int); + +template +bounded operator++(bounded &, int); + +template +bounded &operator++(bounded &); + +template +bounded operator--(bounded &, int); + +template +bounded &operator--(bounded &); + +template +bounded operator+(const bounded &, + const bounded &); + +template +bounded &operator+=(bounded &, + const bounded &); + +template +bounded operator-(const bounded &, + const bounded &); + +template +bounded &operator-=(bounded &, + const bounded &); + +template +bounded operator*(const bounded &, + const bounded &); + +template +bounded &operator*=(bounded &, + const bounded &); +} // namespace data::math::number + +namespace data::math { + +template +using uint = typename number::bounded; + +template +using sint = typename number::bounded; + +template +using uint_little = typename number::bounded; + +template +using uint_big = typename number::bounded; + +template +using sint_little = typename number::bounded; + +template +using sint_big = typename number::bounded; + +// plus and times are associative and commutative +// for both bounded and bytes. +template +struct commutative>, + number::bounded> {}; + +template +struct associative>, + number::bounded> {}; + +template +struct commutative>, + number::bounded> {}; + +template +struct associative>, + number::bounded> {}; + +} // namespace data::math + +namespace data { + +template math::sign sign(const math::uint &); +template math::sign sign(const math::sint &); + +template +math::number::bounded +increment(const math::number::bounded &); +template +math::number::bounded +decrement(const math::number::bounded &); + +} // namespace data namespace data::math::number { - - template - bool operator==(const bounded&, const bounded&); - - template - std::weak_ordering operator<=>(const sint&, const sint&); - - template - std::weak_ordering operator<=>(const uint&, const uint&); - - template - std::weak_ordering operator<=>(const bounded&, const bounded&); - - template - bool operator==(const bounded&, const endian::arithmetic&); - - template - std::weak_ordering operator<=>(const bounded&, const endian::arithmetic&); - - template - bool operator==(const sint&, const Z_bytes&); - - template - std::weak_ordering operator<=>(const sint&, const Z_bytes&); - - template - bool operator==(const uint&, const N_bytes&); - - template - std::weak_ordering operator<=>(const uint&, const N_bytes&); - - template - bool operator==(const sint&, const Z&); - - template - std::weak_ordering operator<=>(const sint&, const Z&); - - template - bool operator==(const uint&, const N&); - - template - std::weak_ordering operator<=>(const uint&, const N&); - - template - sint operator-(const bounded&); - - template - sint operator|(const sint&, const uint&); - - template - sint operator&(const sint&, const uint&); - - template - sint operator^(const sint&, const uint&); - - template - sint operator+(const sint&, const uint&); - - template - sint operator-(const sint&, const uint&); - - template - sint operator*(const sint&, const uint&); - - template bool is_zero(const bounded &); - - template bool is_negative(const uint &); - template bool is_negative(const sint &); - - template bool is_positive(const uint &); - template bool is_positive(const sint &); - -} - + +template +bool operator==(const bounded &, const bounded &); + +template +std::weak_ordering operator<=>(const sint &, const sint &); + +template +std::weak_ordering operator<=>(const uint &, const uint &); + +template +std::weak_ordering operator<=>(const bounded &, + const bounded &); + +template +bool operator==(const bounded &, const endian::arithmetic &); + +template +std::weak_ordering operator<=>(const bounded &, + const endian::arithmetic &); + +template +bool operator==(const sint &, const Z_bytes &); + +template +std::weak_ordering operator<=>(const sint &, const Z_bytes &); + +template +bool operator==(const uint &, const N_bytes &); + +template +std::weak_ordering operator<=>(const uint &, const N_bytes &); + +template +bool operator==(const sint &, const Z &); + +template +std::weak_ordering operator<=>(const sint &, const Z &); + +template +bool operator==(const uint &, const N &); + +template +std::weak_ordering operator<=>(const uint &, const N &); + +template +sint operator-(const bounded &); + +template +sint operator|(const sint &, const uint &); + +template +sint operator&(const sint &, const uint &); + +template +sint operator^(const sint &, const uint &); + +template +sint operator+(const sint &, const uint &); + +template +sint operator-(const sint &, const uint &); + +template +sint operator*(const sint &, const uint &); + +template +sint operator|(const uint &, const sint &); + +template +sint operator&(const uint &, const sint &); + +template +sint operator^(const uint &, const sint &); + +template +sint operator+(const uint &, const sint &); + +template +sint operator-(const uint &, const sint &); + +template +sint operator*(const uint &, const sint &); + +template +sint operator-(const bounded &); + +template +uint operator+(const uint &, uint64); + +template +uint operator-(const uint &, uint64); + +template +uint operator*(const uint &, uint64); + +template +sint operator+(const sint &, int64); + +template +sint operator-(const sint &, int64); + +template +sint operator*(const sint &, int64); + +template +bool is_zero(const bounded &); + +template bool is_negative(const uint &); +template bool is_negative(const sint &); + +template bool is_positive(const uint &); +template bool is_positive(const sint &); + +} // namespace data::math::number + namespace data::encoding::hexidecimal { - - template - std::string write(const math::number::bounded& n); + +template +std::string write(const math::number::bounded &n); } namespace data::encoding::decimal { - - template - std::string write(const math::number::bounded& n); - + +template +std::string write(const math::number::bounded &n); + } namespace data::math::number { - template - struct bounded : oriented { - - bounded() : oriented() { - this->fill(0x00); - } - - bounded(const uint64 x); - - bounded(const byte_array& x) : oriented{x} {} - - explicit bounded(slice x); - - // The string can be a hex string or a representation of a number. - explicit bounded(string_view s); - static bounded read(string_view s) { - return bounded{s}; - } - - math::sign sign() const; - - bounded& operator+=(uint64); - bounded& operator-=(uint64); - bounded& operator*=(uint64); - - math::division divide(const bounded&) const; - - bounded operator/(const bounded& n) const { - return divide(n).Quotient; - } - - bounded operator%(const bounded& n) const { - return divide(n).Remainder; - } - - static bounded max(); - static bounded min(); - static N_bytes modulus(); - - operator N_bytes() const { - N_bytes n; - n.resize(size); - std::copy(this->begin(), this->end(), n.begin()); - return n; - } - - operator bytes_view() const { - return bytes_view(*this); - } - - explicit operator N() const { - return N(N_bytes(*this)); - } - - explicit operator double() const { - return double(N(*this)); - } - - explicit bounded(const N_bytes& n) : bounded{} { - if (n.size() <= size) { - if (r == endian::little) { - std::copy(n.begin(), n.end(), byte_array::begin()); - } else { - std::copy(n.begin(), n.end(), byte_array::begin() + (size - n.size())); - } - } - if (n > N_bytes {max()}) throw std::out_of_range{"N_bytes too big"}; - if (r == endian::little) { - std::copy(n.begin(), n.begin() + size, byte_array::begin()); - } else { - std::copy(n.begin() + (n.size() - size), n.end(), byte_array::begin()); - } - } - - private: - bounded(const sint&) { - throw method::unimplemented{"bounded{bounded}"}; - } - - friend struct abs>; - }; - - template - struct bounded : oriented { - - bounded() : oriented{} { - this->fill(0); - } - - bounded(const int64 x); - - bounded(const byte_array& x) : oriented{x} {} - - bounded(const bounded&); - - explicit bounded(string_view s); - static bounded read(string_view s) { - return bounded{s}; - } - - explicit bounded(slice); - - math::sign sign() const; - - bounded& operator+=(int64); - bounded& operator-=(int64); - bounded& operator*=(int64); - - static bounded max(); - static bounded min(); - - static N_bytes modulus() { - return uint::modulus(); - } - - math::division divide(const bounded&) const; - - bounded operator/(const bounded& n) const { - return divide(n).Quotient; - } - - bounded operator%(const bounded& n) const { - return divide(n).Remainder; - } - - operator bytes_view() const { - return bytes_view(*this); - } - - operator Z_bytes() const { - Z_bytes n; - n.resize(size); - std::copy(this->begin(), this->end(), n.begin()); - return n; - } - - explicit operator Z() const { - return Z(Z_bytes(*this)); - } - - explicit operator double() const { - return double(Z(*this)); - } - - private: - explicit bounded(const Z_bytes& z) { - if (z > Z_bytes {max()} || z < Z_bytes {min()}) throw std::out_of_range{"Z_bytes too big"}; - throw method::unimplemented{"bounded{Z_bytes}"}; - } - }; - - template - bool inline operator==(const bounded &a, const bounded &b) { - return (a <=> b) == 0; - } - - template - bool operator==(const bounded &a, const endian::arithmetic &b) { - return (a <=> b) == 0; - } - - template - bool operator==(const sint &a, const Z_bytes &b) { - return (a <=> b) == 0; - } - - template - bool operator==(const uint &a, const N_bytes &b) { - return (a <=> b) == 0; - } - - template - bool operator==(const sint &a, const Z &b) { - return (a <=> b) == 0; - } - - template - bool operator==(const uint &a, const N &b) { - return (a <=> b) == 0; - } - - template - std::weak_ordering operator<=>(const sint &a, const Z_bytes &b) { - return Z_bytes(a) <=> b; - } - - template - std::weak_ordering operator<=>(const uint &a, const N_bytes &b) { - return Z_bytes(a) <=> b; - } - - template - std::weak_ordering operator<=>(const sint &a, const Z &b) { - return Z(a) <=> b; - } - - template - std::weak_ordering operator<=>(const uint &a, const N &b) { - return N(a) <=> b; - } - - template - std::weak_ordering operator<=>(const bounded &a, const endian::arithmetic &b) { - return a <=> bounded(b); - } - - template bool inline is_positive(const uint &n) { - return !is_zero(n); - } - - template bool inline is_positive(const sint &n) { - return !is_negative(n) && !is_zero(n); - } - - template bool inline is_negative(const uint &n) { - return false; - } - - template - std::ostream inline &operator<<(std::ostream& s, const sint& n) { - return s << Z_bytes(n); - } +template +struct bounded : oriented { - template - std::ostream inline &operator<<(std::ostream& s, const uint& n) { - return s << N_bytes(n); - } + bounded() : oriented() { this->fill(0x00); } - template - inline math::sign uint::sign() const { - return *this == 0 ? math::zero : math::positive; - } - - template - bounded inline operator++(bounded &x, int) { - bounded n = x; - ++x; - return n; - } - - template - bounded inline operator--(bounded &x, int) { - bounded n = x; - ++x; - return n; - } - - template - sint operator|(const sint &a, const uint &b) { - sint x; - std::copy(b.begin(), b.end(), x.begin()); - return a | x; - } - - template - sint operator&(const sint &a, const uint &b) { - sint x; - std::copy(b.begin(), b.end(), x.begin()); - return a & x; - } - - template - sint operator^(const sint &a, const uint &b) { - sint x; - std::copy(b.begin(), b.end(), x.begin()); - return a ^ x; - } - - template - sint operator+(const sint &a, const uint &b) { - sint x; - std::copy(b.begin(), b.end(), x.begin()); - return a + x; - } - - template - sint operator-(const sint &a, const uint &b) { - sint x; - std::copy(b.begin(), b.end(), x.begin()); - return a - x; - } - - template - sint operator*(const sint &a, const uint &b) { - sint x; - std::copy(b.begin(), b.end(), x.begin()); - return a * x; - } + bounded(const uint64 x); + + bounded(const byte_array &x) : oriented{x} {} + + explicit bounded(slice x); + + // The string can be a hex string or a representation of a number. + explicit bounded(string_view s); + static bounded read(string_view s) { return bounded{s}; } + + bounded &operator+=(uint64); + bounded &operator-=(uint64); + bounded &operator*=(uint64); + + math::division divide(const bounded &) const; + + bounded operator/(const bounded &n) const { return divide(n).Quotient; } + + bounded operator%(const bounded &n) const { return divide(n).Remainder; } + + static bounded max(); + static bounded min(); + static N_bytes modulus(); + + operator N_bytes() const { + N_bytes n; + n.resize(size); + std::copy(this->begin(), this->end(), n.begin()); + return n; + } + + operator bytes_view() const { return bytes_view(*this); } + + explicit operator N() const { return N(N_bytes(*this)); } + + explicit operator double() const { return double(N(*this)); } + + explicit bounded(const N_bytes &n) : bounded{} { + if (n.size() <= size) { + if (r == endian::little) { + std::copy(n.begin(), n.end(), byte_array::begin()); + } else { + std::copy(n.begin(), n.end(), + byte_array::begin() + (size - n.size())); + } + } + if (n > N_bytes{max()}) + throw std::out_of_range{"N_bytes too big"}; + if (r == endian::little) { + std::copy(n.begin(), n.begin() + size, byte_array::begin()); + } else { + std::copy(n.begin() + (n.size() - size), n.end(), + byte_array::begin()); + } + } + +private: + bounded(const sint &) { + throw method::unimplemented{ + "bounded{bounded}"}; + } + + friend struct abs>; +}; + +template +struct bounded : oriented { + + bounded() : oriented{} { this->fill(0); } + + bounded(const int64 x); + + bounded(const byte_array &x) : oriented{x} {} + + bounded(const bounded &); + + explicit bounded(string_view s); + static bounded read(string_view s) { return bounded{s}; } + + explicit bounded(slice); + + bounded &operator+=(int64); + bounded &operator-=(int64); + bounded &operator*=(int64); + + static bounded max(); + static bounded min(); + static N_bytes modulus() { return uint::modulus(); } + + math::division divide(const bounded &) const; + + bounded operator/(const bounded &n) const { return divide(n).Quotient; } + + bounded operator%(const bounded &n) const { return divide(n).Remainder; } + + operator bytes_view() const { return bytes_view(*this); } + + operator Z_bytes() const { + Z_bytes n; + n.resize(size); + std::copy(this->begin(), this->end(), n.begin()); + return n; + } + + explicit operator Z() const { return Z(Z_bytes(*this)); } + + explicit operator double() const { return double(Z(*this)); } + +private: + explicit bounded(const Z_bytes &z) { + if (z > Z_bytes{max()} || z < Z_bytes{min()}) + throw std::out_of_range{"Z_bytes too big"}; + throw method::unimplemented{"bounded{Z_bytes}"}; + } +}; + +template +bool inline operator==(const bounded &a, const bounded &b) { + return (a <=> b) == 0; +} + +template +bool operator==(const bounded &a, + const endian::arithmetic &b) { + return (a <=> b) == 0; +} + +template +bool operator==(const sint &a, const Z_bytes &b) { + return (a <=> b) == 0; +} + +template +bool operator==(const uint &a, const N_bytes &b) { + return (a <=> b) == 0; +} + +template +bool operator==(const sint &a, const Z &b) { + return (a <=> b) == 0; +} + +template +bool operator==(const uint &a, const N &b) { + return (a <=> b) == 0; +} + +template +std::weak_ordering operator<=>(const sint &a, const Z_bytes &b) { + return Z_bytes(a) <=> b; +} + +template +std::weak_ordering operator<=>(const uint &a, const N_bytes &b) { + return Z_bytes(a) <=> b; } +template +std::weak_ordering operator<=>(const sint &a, const Z &b) { + return Z(a) <=> b; +} + +template +std::weak_ordering operator<=>(const uint &a, const N &b) { + return N(a) <=> b; +} + +template +std::weak_ordering operator<=>(const bounded &a, + const endian::arithmetic &b) { + return a <=> bounded(b); +} + +template +bool inline is_positive(const uint &n) { + return !is_zero(n); +} + +template +bool inline is_positive(const sint &n) { + return !is_negative(n) && !is_zero(n); +} + +template +bool inline is_negative(const uint &n) { + return false; +} + +template +std::ostream inline &operator<<(std::ostream &s, const sint &n) { + return s << Z_bytes(n); +} + +template +std::ostream inline &operator<<(std::ostream &s, const uint &n) { + return s << N_bytes(n); +} + +template +bounded inline operator++(bounded &x, int) { + bounded n = x; + ++x; + return n; +} + +template +bounded inline operator--(bounded &x, int) { + bounded n = x; + ++x; + return n; +} + +template +sint operator|(const sint &a, const uint &b) { + sint x; + std::copy(b.begin(), b.end(), x.begin()); + return a | x; +} + +template +sint operator&(const sint &a, const uint &b) { + sint x; + std::copy(b.begin(), b.end(), x.begin()); + return a & x; +} + +template +sint operator^(const sint &a, const uint &b) { + sint x; + std::copy(b.begin(), b.end(), x.begin()); + return a ^ x; +} + +template +sint operator+(const sint &a, const uint &b) { + sint x; + std::copy(b.begin(), b.end(), x.begin()); + return a + x; +} + +template +sint operator-(const sint &a, const uint &b) { + sint x; + std::copy(b.begin(), b.end(), x.begin()); + return a - x; +} + +template +sint operator*(const sint &a, const uint &b) { + sint x; + std::copy(b.begin(), b.end(), x.begin()); + return a * x; +} + +} // namespace data::math::number + namespace data { - namespace encoding::hexidecimal { +template +math::sign inline sign(const math::uint &z) { + return math::arithmetic::N_sign(z.words()); +} + +template +math::sign inline sign(const math::sint &z) { + return math::arithmetic::Z_sign_ones(z.words()); +} - template - std::string write(const math::number::bounded& n) { - std::stringstream ss; - ss << std::hex << n; - return ss.str(); - } +template +math::number::bounded inline increment( + const math::number::bounded &n) { + auto z = n; + return ++z; +} - } +template +math::number::bounded inline decrement( + const math::number::bounded &n) { + auto z = n; + return --z; +} - namespace encoding::decimal { +namespace encoding::hexidecimal { - template - std::string write(const math::number::bounded& n) { - std::stringstream ss; - ss << std::dec << n; - return ss.str(); - } +template +std::string write(const math::number::bounded &n) { + std::stringstream ss; + ss << std::hex << n; + return ss.str(); +} - } - - namespace math { - - template - struct abs> { - uint operator()(const uint& i) { - return i; - } - }; - - template - struct abs> { - uint operator()(const sint& i) { - uint u; - sint x = number::is_negative(i) ? -i : i; - std::copy(x.begin(), x.end(), u.begin()); - return u; - } - }; - - } +} // namespace encoding::hexidecimal + +namespace encoding::decimal { +template +std::string write(const math::number::bounded &n) { + std::stringstream ss; + ss << std::dec << n; + return ss.str(); } +} // namespace encoding::decimal + +namespace math { + +template struct abs> { + uint operator()(const uint &i) { return i; } +}; + +template struct abs> { + uint operator()(const sint &i) { + uint u; + sint x = number::is_negative(i) ? -i : i; + std::copy(x.begin(), x.end(), u.begin()); + return u; + } +}; + +} // namespace math + +} // namespace data + namespace data::math::number { - - template - std::weak_ordering operator<=>(const sint &a, const sint &b) { - bool na = is_negative(a); - bool nb = is_negative(b); - - if (na && nb) { - return arithmetic::N_compare(b.words(), a.words()); - } - - if (!na && !nb) return arithmetic::N_compare(a.words(), b.words()); - return na ? std::weak_ordering::less : std::weak_ordering::greater; - } - - template - std::weak_ordering inline operator<=>(const uint &a, const uint &b) { - return arithmetic::N_compare(a.words(), b.words()); - } - - template - std::weak_ordering inline operator<=>(const bounded&, const bounded&) { - throw 0; - } - - template - inline math::sign sint::sign() const { - if (*this == 0) return math::zero; - return (this->words()[-1]) < 0x80 ? math::positive : math::negative; - } - - template - uint::bounded(const uint64 x) : oriented{} { - this->fill(0); - endian::arithmetic n{x}; - std::copy(n.begin(), n.end(), this->words().begin()); - } - - template - sint::bounded(const int64 x) : oriented{} { - this->fill(x < 0 ? 0xff : 0x00); - endian::arithmetic n{x}; - std::copy(n.begin(), n.end(), this->words().begin()); - } - - template - uint::bounded(slice x) { - std::copy(x.begin(), x.end(), this->begin()); - } - - template - uint::bounded(string_view s) : bounded{} { - - ptr> dec = encoding::natural::read(s); - if (dec != nullptr) { - if (dec->size() <= size) { - std::copy(dec->begin(), dec->end(), this->words().begin()); - return; - } else throw std::invalid_argument{"decimal number too big"}; - } - - ptr hex = encoding::hex::read(s); - if (hex != nullptr) { - if (hex->size() == size) { - std::copy(hex->begin(), hex->end(), this->begin()); - return; - } else throw std::invalid_argument{"hex string has the wrong size."}; - } - - throw std::invalid_argument{"format is unrecognized."}; - - } - - template - sint::bounded(string_view s) : bounded{} { - ptr> dec = encoding::integer::read(s); - if (dec != nullptr) { - if (dec->size() <= size) { - if (is_negative(*dec)) this->fill(0xff); - std::copy(dec->begin(), dec->end(), this->words().begin()); - return; - } else throw std::invalid_argument{"decimal number has too many digits"}; - } - - ptr hex = encoding::hex::read(s); - if (hex != nullptr) { - if (hex->size() == size) { - std::copy(hex->begin(), hex->end(), this->begin()); - return; - } else throw std::invalid_argument{"hex string has the wrong size."}; - } - - throw std::invalid_argument{"format is unrecognized."}; - - } - - template - bounded inline &operator++(bounded &x) { - data::arithmetic::plus(x.words().end(), x.words().begin(), 1, x.words().begin()); - return x; - } - - template - bounded inline &operator--(bounded &x) { - data::arithmetic::minus(x.words().end(), x.words().begin(), 1, x.words().begin()); - return x; - } - - template - bounded inline operator<<(const bounded &z, int i) { - auto n = z; - return n <<= i; - } - - template - bounded inline operator>>(const bounded &z, int i) { - auto n = z; - return n >>= i; - } - - namespace { - template - void shift_right(byte_array &n, uint32 i, byte fill) { - if (r == endian::big) data::arithmetic::bit_shift_right(n.rbegin(), n.rend(), i, fill); - else data::arithmetic::bit_shift_right(n.begin(), n.end(), i, fill); - } - - template - void shift_left(byte_array &n, uint32 i, byte fill) { - if (r == endian::big) data::arithmetic::bit_shift_left(n.begin(), n.end(), i, fill); - else data::arithmetic::bit_shift_left(n.rbegin(), n.rend(), i, fill); - } - } - - template - bounded inline &operator<<=(bounded &n, int i) { - (i < 0 ? shift_right : shift_left)(n, i, is_negative(n)); - return n; - } - - template - bounded inline &operator>>=(bounded &n, int i) { - (i < 0 ? shift_left : shift_right)(n, i, is_negative(n)); - return n; - } - - template - sint operator-(const bounded& a) { - sint x; - std::copy(a.begin(), a.end(), x.begin()); - x.bit_negate(); - return ++x; - } - - template - uint uint::min() { - bounded b{}; - for (int i = 0; i <= size; i++) b[i] = 0x00; - return b; - } - - template - uint uint::max() { - bounded b{}; - for (int i = 0; i <= size; i++) b[i] = 0xff; - return b; - } - template - sint sint::min() { - bounded b{}; - b.words()[-1] = 0x80; - return b; - } - - template - sint sint::max() { - bounded b{-1}; - b.words()[-1] = 0x7f; - return b; - } - - template - bounded inline operator&(const bounded &a, const bounded &b) { - bounded x; - data::arithmetic::bit_and(x.words().end(), x.words().begin(), a.words().begin(), b.words().begin()); - return x; - } - - template - bounded inline operator|(const bounded &a, const bounded &b) { - bounded x; - data::arithmetic::bit_or(x.words().end(), x.words().begin(), a.words().begin(), b.words().begin()); - return x; - } - - template - bounded inline operator^(const bounded &a, const bounded &b) { - bounded x; - data::arithmetic::bit_xor(x.words().end(), x.words().begin(), a.words().begin(), b.words().begin()); - return x; - } - - template - bounded inline &operator&=(bounded &a, const bounded &b) { - data::arithmetic::bit_and(a.words().end(), a.words().begin(), - const_cast&>(a).words().begin(), b.words().begin()); - return a; - } - - template - bounded inline &operator|=(bounded &a, const bounded &b) { - data::arithmetic::bit_or(a.words().end(), a.words().begin(), - const_cast&>(a).words().begin(), b.words().begin()); - return a; - } - - template - bounded inline &operator^=(bounded &a, const bounded &b) { - data::arithmetic::bit_xor(a.words().end(), a.words().begin(), - const_cast&>(a).words().begin(), b.words().begin()); - return a; - } - - template - bounded inline operator+(const bounded &a, const bounded &n) { - bounded x; - data::arithmetic::plus(x.words().end(), x.words().begin(), a.words().begin(), n.words().begin()); - return x; - } - - template - bounded inline &operator+=(bounded &a, const bounded &n) { - data::arithmetic::plus(a.words().end(), a.words().begin(), - const_cast&>(a).words().begin(), n.words().begin()); - return a; - } - - template - bounded operator-(const bounded &a, const bounded &n) { - bounded z; - std::copy(n.begin(), n.end(), z.begin()); - z.bit_negate(); - ++z; - bounded x; - data::arithmetic::minus(x.words().end(), x.words().begin(), a.words().begin(), z.words().begin()); - return x; - } - - template - bounded &operator-=(bounded &a, const bounded &n) { - bounded z; - std::copy(n.begin(), n.end(), z.begin()); - z.bit_negate(); - ++z; - data::arithmetic::plus(a.words().end(), a.words().begin(), - const_cast&>(a).words().begin(), z.words().begin()); - return a; - } - - template - bounded inline operator*(const bounded &a, const bounded &n) { - bounded x; - data::arithmetic::times(x.words().end(), x.words().begin(), a.words().begin(), n.words().begin()); - return x; - } - - template - bounded inline &operator*=(bounded &a, const bounded &n) { - data::arithmetic::times(a.words().end(), a.words().begin(), - const_cast&>(a).words().begin(), n.words().begin()); - return a; - } +template +std::weak_ordering operator<=>(const sint &a, const sint &b) { + bool na = is_negative(a); + bool nb = is_negative(b); - template - bounded inline &bounded::operator+=(int64 x) { - return *this += bounded{x}; - } - - template - bounded inline &bounded::operator+=(uint64 x) { - return *this += bounded{x}; - } + if (na && nb) { + return arithmetic::N_compare(b.words(), a.words()); + } - template - bounded inline &bounded::operator-=(int64 x) { - return *this -= bounded{x}; - } - - template - bounded inline &bounded::operator-=(uint64 x) { - return *this -= bounded{x}; - } - - template - bounded operator+(const bounded &a, const bounded &b) { - bounded n{}; - data::arithmetic::plus(n.words().end(), n.words().begin(), a.words().begin(), b.words().begin()); - return n; - } - - template - bounded operator+(const bounded &a, const bounded &b) { - bounded n{}; - data::arithmetic::plus(n.words().end(), n.words().begin(), a.words().begin(), b.words().begin()); - return n; - } - - template - bounded operator~(const bounded &n) { - bounded x; - data::arithmetic::bit_negate(x.end(), x.begin(), n.begin()); - return x; - } - - template - bool operator==(const bounded &a, const bounded &b) { - return data::arithmetic::equal(a.end(), a.begin(), b.begin()); - } - - template - uint inline operator+(const uint& a, uint64 b) { - return a + bounded{b}; - } - - template - sint inline operator+(const sint& a, int64 b) { - return a + bounded{b}; - } - - template - uint inline operator-(const uint& a, uint64 b) { - return a - bounded{b}; - } - - template - sint inline operator-(const sint& a, int64 b) { - return a - sint{b}; - } - - template bool inline is_zero(const bounded &z) { - return arithmetic::ones_is_zero(z.words()); - } - - template bool inline is_negative(const sint &z) { - return arithmetic::sign_bit(z.words()); - } + if (!na && !nb) + return arithmetic::N_compare(a.words(), b.words()); + return na ? std::weak_ordering::less : std::weak_ordering::greater; +} + +template +std::weak_ordering inline operator<=>(const uint &a, + const uint &b) { + return arithmetic::N_compare(a.words(), b.words()); +} + +template +std::weak_ordering inline operator<=>(const bounded &, + const bounded &) { + throw 0; +} + +template +sint inline operator|(const uint &a, const sint &b) { + return sint(a) | b; +} + +template +sint inline operator&(const uint &a, const sint &b) { + return sint(a) & b; +} + +template +sint inline operator^(const uint &a, const sint &b) { + return sint(a) ^ b; +} + +template +sint inline operator+(const uint &a, const sint &b) { + return sint(a) + b; +} + +template +sint inline operator-(const uint &a, const sint &b) { + return sint(a) - b; +} + +template +sint inline operator*(const uint &a, const sint &b) { + return sint(a) * b; +} + +template +sint inline operator+(const sint &a, int64 b) { + return a + sint(b); +} + +template +sint inline operator-(const sint &a, int64 b) { + return a - sint(b); +} + +template +sint inline operator*(const sint &a, int64 b) { + return a * sint(b); +} + +template +uint inline &operator+=(uint &a, uint64 b) { + return a += uint(b); +} + +template +uint::bounded(const uint64 x) : oriented{} { + this->fill(0); + endian::arithmetic n{x}; + std::copy(n.begin(), n.end(), this->words().begin()); +} + +template +sint::bounded(const int64 x) : oriented{} { + this->fill(x < 0 ? 0xff : 0x00); + endian::arithmetic n{x}; + std::copy(n.begin(), n.end(), this->words().begin()); +} + +template +uint::bounded(slice x) { + std::copy(x.begin(), x.end(), this->begin()); +} + +template +uint::bounded(string_view s) : bounded{} { + + ptr> dec = encoding::natural::read(s); + if (dec != nullptr) { + if (dec->size() <= size) { + std::copy(dec->begin(), dec->end(), this->words().begin()); + return; + } else + throw std::invalid_argument{"decimal number too big"}; + } + + ptr hex = encoding::hex::read(s); + if (hex != nullptr) { + if (hex->size() == size) { + std::copy(hex->begin(), hex->end(), this->begin()); + return; + } else + throw std::invalid_argument{"hex string has the wrong size."}; + } + + throw std::invalid_argument{"format is unrecognized."}; +} + +template +sint::bounded(string_view s) : bounded{} { + ptr> dec = encoding::integer::read(s); + if (dec != nullptr) { + if (dec->size() <= size) { + if (is_negative(*dec)) + this->fill(0xff); + std::copy(dec->begin(), dec->end(), this->words().begin()); + return; + } else + throw std::invalid_argument{"decimal number has too many digits"}; + } + + ptr hex = encoding::hex::read(s); + if (hex != nullptr) { + if (hex->size() == size) { + std::copy(hex->begin(), hex->end(), this->begin()); + return; + } else + throw std::invalid_argument{"hex string has the wrong size."}; + } + + throw std::invalid_argument{"format is unrecognized."}; +} + +template +bounded inline &operator++(bounded &x) { + data::arithmetic::plus(x.words().end(), x.words().begin(), 1, + x.words().begin()); + return x; +} + +template +bounded inline &operator--(bounded &x) { + data::arithmetic::minus(x.words().end(), x.words().begin(), 1, + x.words().begin()); + return x; +} +template +bounded inline +operator<<(const bounded &z, int i) { + auto n = z; + return n <<= i; } +template +bounded inline +operator>>(const bounded &z, int i) { + auto n = z; + return n >>= i; +} + +namespace { +template +void shift_right(byte_array &n, uint32 i, byte fill) { + if (r == endian::big) + data::arithmetic::bit_shift_right(n.rbegin(), n.rend(), i, fill); + else + data::arithmetic::bit_shift_right(n.begin(), n.end(), i, fill); +} + +template +void shift_left(byte_array &n, uint32 i, byte fill) { + if (r == endian::big) + data::arithmetic::bit_shift_left(n.begin(), n.end(), i, fill); + else + data::arithmetic::bit_shift_left(n.rbegin(), n.rend(), i, fill); +} +} // namespace + +template +bounded inline &operator<<=(bounded &n, + int i) { + (i < 0 ? shift_right : shift_left)(n, i, is_negative(n)); + return n; +} + +template +bounded inline &operator>>=(bounded &n, + int i) { + (i < 0 ? shift_left : shift_right)(n, i, is_negative(n)); + return n; +} + +template +sint operator-(const bounded &a) { + sint x; + std::copy(a.begin(), a.end(), x.begin()); + x.bit_negate(); + return ++x; +} + +template uint uint::min() { + bounded b{}; + for (int i = 0; i <= size; i++) + b[i] = 0x00; + return b; +} + +template uint uint::max() { + bounded b{}; + for (int i = 0; i <= size; i++) + b[i] = 0xff; + return b; +} + +template sint sint::min() { + bounded b{}; + b.words()[-1] = 0x80; + return b; +} + +template sint sint::max() { + bounded b{-1}; + b.words()[-1] = 0x7f; + return b; +} + +template +bounded inline operator&(const bounded &a, + const bounded &b) { + bounded x; + data::arithmetic::bit_and(x.words().end(), x.words().begin(), + a.words().begin(), b.words().begin()); + return x; +} + +template +bounded inline operator|(const bounded &a, + const bounded &b) { + bounded x; + data::arithmetic::bit_or(x.words().end(), x.words().begin(), + a.words().begin(), b.words().begin()); + return x; +} + +template +bounded inline operator^(const bounded &a, + const bounded &b) { + bounded x; + data::arithmetic::bit_xor(x.words().end(), x.words().begin(), + a.words().begin(), b.words().begin()); + return x; +} + +template +bounded inline &operator&=(bounded &a, + const bounded &b) { + data::arithmetic::bit_and( + a.words().end(), a.words().begin(), + const_cast &>(a).words().begin(), + b.words().begin()); + return a; +} + +template +bounded inline &operator|=(bounded &a, + const bounded &b) { + data::arithmetic::bit_or( + a.words().end(), a.words().begin(), + const_cast &>(a).words().begin(), + b.words().begin()); + return a; +} + +template +bounded inline &operator^=(bounded &a, + const bounded &b) { + data::arithmetic::bit_xor( + a.words().end(), a.words().begin(), + const_cast &>(a).words().begin(), + b.words().begin()); + return a; +} + +template +bounded inline operator+(const bounded &a, + const bounded &n) { + bounded x; + data::arithmetic::plus(x.words().end(), x.words().begin(), + a.words().begin(), n.words().begin()); + return x; +} + +template +bounded inline &operator+=(bounded &a, + const bounded &n) { + data::arithmetic::plus( + a.words().end(), a.words().begin(), + const_cast &>(a).words().begin(), + n.words().begin()); + return a; +} + +template +bounded operator-(const bounded &a, + const bounded &n) { + bounded z; + std::copy(n.begin(), n.end(), z.begin()); + z.bit_negate(); + ++z; + bounded x; + data::arithmetic::minus(x.words().end(), x.words().begin(), + a.words().begin(), z.words().begin()); + return x; +} + +template +bounded &operator-=(bounded &a, + const bounded &n) { + bounded z; + std::copy(n.begin(), n.end(), z.begin()); + z.bit_negate(); + ++z; + data::arithmetic::plus( + a.words().end(), a.words().begin(), + const_cast &>(a).words().begin(), + z.words().begin()); + return a; +} + +template +bounded inline operator*(const bounded &a, + const bounded &n) { + bounded x; + data::arithmetic::times(x.words().end(), x.words().begin(), + a.words().begin(), n.words().begin()); + return x; +} + +template +bounded inline &operator*=(bounded &a, + const bounded &n) { + data::arithmetic::times( + a.words().end(), a.words().begin(), + const_cast &>(a).words().begin(), + n.words().begin()); + return a; +} + +template +bounded inline &bounded::operator+=(int64 x) { + return *this += bounded{x}; +} + +template +bounded inline &bounded::operator+=(uint64 x) { + return *this += bounded{x}; +} + +template +bounded inline &bounded::operator-=(int64 x) { + return *this -= bounded{x}; +} + +template +bounded inline &bounded::operator-=(uint64 x) { + return *this -= bounded{x}; +} + +template +bounded operator+(const bounded &a, + const bounded &b) { + bounded n{}; + data::arithmetic::plus(n.words().end(), n.words().begin(), + a.words().begin(), b.words().begin()); + return n; +} + +template +bounded operator+(const bounded &a, + const bounded &b) { + bounded n{}; + data::arithmetic::plus(n.words().end(), n.words().begin(), + a.words().begin(), b.words().begin()); + return n; +} + +template +bounded operator~(const bounded &n) { + bounded x; + data::arithmetic::bit_negate(x.end(), x.begin(), n.begin()); + return x; +} + +template +bool operator==(const bounded &a, + const bounded &b) { + return data::arithmetic::equal(a.end(), a.begin(), b.begin()); +} + +template +uint inline operator+(const uint &a, uint64 b) { + return a + bounded{b}; +} + +template +uint inline operator-(const uint &a, uint64 b) { + return a - bounded{b}; +} + +template +bool inline is_zero(const bounded &z) { + return arithmetic::ones_is_zero(z.words()); +} + +template +bool inline is_negative(const sint &z) { + return arithmetic::sign_bit(z.words()); +} + +} // namespace data::math::number + #endif