Skip to content

Commit

Permalink
Addition of MacOS workflow
Browse files Browse the repository at this point in the history
  • Loading branch information
sjanel committed May 30, 2021
1 parent dabb75a commit 89cd882
Show file tree
Hide file tree
Showing 6 changed files with 231 additions and 58 deletions.
22 changes: 22 additions & 0 deletions .github/workflows/macos.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: macOS

on:
push:
branches:
- master
pull_request:

jobs:
xcode:
runs-on: macos-latest
env:
DEVELOPER_DIR: /Applications/Xcode_12.4.app/Contents/Developer

steps:
- uses: actions/checkout@v2
- name: cmake
run: cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_COMPILER=g++-11 -DOPENSSL_ROOT_DIR=/usr/local/Cellar/openssl@1.1/1.1.1k
- name: build
run: cmake --build build --parallel 2
- name: test
run: cd build && ctest -j 2 --output-on-failure
4 changes: 2 additions & 2 deletions .github/workflows/ubuntu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@ jobs:
working-directory: ${{github.workspace}}/build
shell: bash
# Execute the build. You can specify a specific target with "--target <NAME>"
run: cmake --build . --config ${{matrix.buildmode}} -j 8
run: cmake --build . --config ${{matrix.buildmode}} -j 2

- name: Test
working-directory: ${{github.workspace}}/build
shell: bash
# Execute tests defined by the CMake configuration. Print debug traces on failure
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
run: ctest -j 8 -C ${{matrix.buildmode}} --output-on-failure
run: ctest -j 2 -C ${{matrix.buildmode}} --output-on-failure
4 changes: 2 additions & 2 deletions .github/workflows/windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ jobs:

- name: Build
working-directory: ${{github.workspace}}/build
run: cmake --build . --config ${{matrix.buildmode}}
run: cmake --build . --config ${{matrix.buildmode}} --parallel 2

- name: Tests
working-directory: ${{github.workspace}}/build
run: ctest -C ${{matrix.buildmode}} -j 10 --output-on-failure
run: ctest -C ${{matrix.buildmode}} -j 2 --output-on-failure
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
[![ubuntu](https://github.com/sjanel/coincenter/actions/workflows/ubuntu.yml/badge.svg?branch=master)](https://github.com/sjanel/coincenter/actions/workflows/ubuntu.yml)
[![alpine_docker](https://github.com/sjanel/coincenter/actions/workflows/alpine_docker.yml/badge.svg?branch=master)](https://github.com/sjanel/coincenter/actions/workflows/alpine_docker.yml)
[![macos](https://github.com/sjanel/coincenter/actions/workflows/macos.yml/badge.svg?branch=master)](https://github.com/sjanel/coincenter/actions/workflows/macos.yml)
[![ubuntu](https://github.com/sjanel/coincenter/actions/workflows/ubuntu.yml/badge.svg?branch=master)](https://github.com/sjanel/coincenter/actions/workflows/ubuntu.yml)
[![windows](https://github.com/sjanel/coincenter/actions/workflows/windows.yml/badge.svg?branch=master)](https://github.com/sjanel/coincenter/actions/workflows/windows.yml)

[![formatted](https://github.com/sjanel/coincenter/actions/workflows/clang-format-check.yml/badge.svg?branch=master)](https://github.com/sjanel/coincenter/actions/workflows/clang-format-check.yml)
Expand Down
89 changes: 60 additions & 29 deletions src/tools/include/cct_mathhelpers.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include <concepts>
#include <cstdint>
#include <limits>
#include <type_traits>
Expand Down Expand Up @@ -67,42 +68,72 @@ constexpr int64_t ipow(int64_t base, uint8_t exp) {
}
}

/// Return the number of digits of given integral.
/// Uses dichotomy for highest performance as possible.
constexpr int ndigits(int32_t n) {
if (n < 0) {
if (CCT_UNLIKELY(n == std::numeric_limits<decltype(n)>::min())) {
++n;
}
n *= -1;
}
return n < 1000000 ? (n < 1000 ? (n < 100 ? (n < 10 ? 1 : 2) : 3) : (n < 100000 ? (n < 10000 ? 4 : 5) : 6))
: (n < 100000000 ? (n < 10000000 ? 7 : 8) : (n < 1000000000 ? 9 : 10));
}
template <class T>
concept SignedIntegral = std::integral<T>&& std::is_signed<T>::value;

template <class T>
concept UnsignedIntegral = std::integral<T> && !SignedIntegral<T>;

/// Return the number of digits of given integral.
/// Uses dichotomy for highest performance as possible.
constexpr int ndigits(uint64_t n) {
return n < 10000000000UL
? (n < 1000000UL
? (n < 1000UL ? (n < 100UL ? (n < 10UL ? 1 : 2) : 3) : (n < 100000UL ? (n < 10000UL ? 4 : 5) : 6))
: (n < 100000000UL ? (n < 10000000UL ? 7 : 8) : (n < 1000000000UL ? 9 : 10)))
: (n < 10000000000000000UL
? (n < 10000000000000UL ? (n < 1000000000000UL ? (n < 100000000000UL ? 11 : 12) : 13)
: (n < 1000000000000000UL ? (n < 100000000000000UL ? 14 : 15) : 16))
: (n < 1000000000000000000UL ? (n < 100000000000000000UL ? 17 : 18)
: (n < 10000000000000000000UL ? 19 : 20)));
template <SignedIntegral T>
constexpr int ndigits(T n) {
if constexpr (std::is_same_v<T, int8_t>) {
return n < 0 ? (n > -100 ? (n > -10 ? 1 : 2) : 3) : (n < 100 ? (n < 10 ? 1 : 2) : 3);
} else if constexpr (std::is_same_v<T, int16_t>) {
return n < 0 ? (n > -1000 ? (n > -100 ? (n > -10 ? 1 : 2) : 3) : (n > -10000 ? 4 : 5))
: (n < 1000 ? (n < 100 ? (n < 10 ? 1 : 2) : 3) : (n < 10000 ? 4 : 5));
} else if constexpr (std::is_same_v<T, int32_t>) {
return n < 0 ? (n > -1000000
? (n > -1000 ? (n > -100 ? (n > -10 ? 1 : 2) : 3) : (n > -100000 ? (n > -10000 ? 4 : 5) : 6))
: (n > -100000000 ? (n > -10000000 ? 7 : 8) : (n > -1000000000 ? 9 : 10)))
: (n < 1000000 ? (n < 1000 ? (n < 100 ? (n < 10 ? 1 : 2) : 3) : (n < 100000 ? (n < 10000 ? 4 : 5) : 6))
: (n < 100000000 ? (n < 10000000 ? 7 : 8) : (n < 1000000000 ? 9 : 10)));
} else {
// int64_t
return n < 0 ? (n > -10000000000L
? (n > -1000000L ? (n > -1000L ? (n > -100L ? (n > -10L ? 1 : 2) : 3)
: (n > -100000L ? (n > -10000L ? 4 : 5) : 6))
: (n > -100000000L ? (n > -10000000L ? 7 : 8) : (n > -1000000000L ? 9 : 10)))
: (n > -10000000000000000L
? (n > -10000000000000L
? (n > -1000000000000L ? (n > -100000000000L ? 11 : 12) : 13)
: (n > -1000000000000000L ? (n > -100000000000000L ? 14 : 15) : 16))
: (n > -1000000000000000000L ? (n > -100000000000000000L ? 17 : 18) : 19)))
: (n < 10000000000L
? (n < 1000000L ? (n < 1000L ? (n < 100L ? (n < 10L ? 1 : 2) : 3)
: (n < 100000L ? (n < 10000L ? 4 : 5) : 6))
: (n < 100000000L ? (n < 10000000L ? 7 : 8) : (n < 1000000000L ? 9 : 10)))
: (n < 10000000000000000L
? (n < 10000000000000L ? (n < 1000000000000L ? (n < 100000000000L ? 11 : 12) : 13)
: (n < 1000000000000000L ? (n < 100000000000000L ? 14 : 15) : 16))
: (n < 1000000000000000000L ? (n < 100000000000000000L ? 17 : 18) : 19)));
}
}

/// Return the number of digits of given integral.
/// Uses dichotomy for highest performance as possible.
constexpr int ndigits(int64_t n) {
if (n < 0) {
if (CCT_UNLIKELY(n == std::numeric_limits<decltype(n)>::min())) {
++n;
}
n *= -1;
template <UnsignedIntegral T>
constexpr int ndigits(T n) {
if constexpr (std::is_same_v<T, uint8_t>) {
return n < 100U ? (n < 10U ? 1 : 2) : 3;
} else if constexpr (std::is_same_v<T, uint16_t>) {
return n < 1000U ? (n < 100U ? (n < 10U ? 1 : 2) : 3) : (n < 10000U ? 4 : 5);
} else if constexpr (std::is_same_v<T, uint32_t>) {
return n < 1000000U ? (n < 1000U ? (n < 100U ? (n < 10U ? 1 : 2) : 3) : (n < 100000U ? (n < 10000U ? 4 : 5) : 6))
: (n < 100000000U ? (n < 10000000U ? 7 : 8) : (n < 1000000000U ? 9 : 10));
} else {
// uint64_t
return n < 10000000000UL
? (n < 1000000UL
? (n < 1000UL ? (n < 100UL ? (n < 10UL ? 1 : 2) : 3) : (n < 100000UL ? (n < 10000UL ? 4 : 5) : 6))
: (n < 100000000UL ? (n < 10000000UL ? 7 : 8) : (n < 1000000000UL ? 9 : 10)))
: (n < 10000000000000000UL
? (n < 10000000000000UL ? (n < 1000000000000UL ? (n < 100000000000UL ? 11 : 12) : 13)
: (n < 1000000000000000UL ? (n < 100000000000000UL ? 14 : 15) : 16))
: (n < 1000000000000000000UL ? (n < 100000000000000000UL ? 17 : 18)
: (n < 10000000000000000000UL ? 19 : 20)));
}
return ndigits(static_cast<uint64_t>(n));
}

} // namespace cct
167 changes: 143 additions & 24 deletions src/tools/test/cct_mathhelpers_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,46 +15,165 @@ TEST(MathHelpers, Power) {
static_assert(ipow(-7, 0) == 1);
}

TEST(MathHelpers, NDigits) {
TEST(MathHelpers, NDigitsS8) {
EXPECT_EQ(ndigits(static_cast<int8_t>(0)), 1);
EXPECT_EQ(ndigits(static_cast<int8_t>(3)), 1);
EXPECT_EQ(ndigits(static_cast<int8_t>(78)), 2);
EXPECT_EQ(ndigits(static_cast<int8_t>(112)), 3);
EXPECT_EQ(ndigits(static_cast<int8_t>(-125)), 3);
EXPECT_EQ(ndigits(static_cast<int8_t>(-10)), 2);
EXPECT_EQ(ndigits(static_cast<int8_t>(-1)), 1);

static_assert(ndigits(std::numeric_limits<int8_t>::max()) == 3);
static_assert(ndigits(std::numeric_limits<int8_t>::min()) == 3);
}

TEST(MathHelpers, NDigitsS16) {
EXPECT_EQ(ndigits(static_cast<int16_t>(0)), 1);
EXPECT_EQ(ndigits(static_cast<int16_t>(3)), 1);
EXPECT_EQ(ndigits(static_cast<int16_t>(78)), 2);
EXPECT_EQ(ndigits(static_cast<int16_t>(170)), 3);
EXPECT_EQ(ndigits(static_cast<int16_t>(9245)), 4);
EXPECT_EQ(ndigits(static_cast<int16_t>(31710)), 5);
EXPECT_EQ(ndigits(static_cast<int16_t>(-26816)), 5);
EXPECT_EQ(ndigits(static_cast<int16_t>(-3686)), 4);
EXPECT_EQ(ndigits(static_cast<int16_t>(-686)), 3);
EXPECT_EQ(ndigits(static_cast<int16_t>(-10)), 2);
EXPECT_EQ(ndigits(static_cast<int16_t>(-2)), 1);

static_assert(ndigits(std::numeric_limits<int16_t>::max()) == 5);
static_assert(ndigits(std::numeric_limits<int16_t>::min()) == 5);
}

TEST(MathHelpers, NDigitsS32) {
EXPECT_EQ(ndigits(0), 1);
EXPECT_EQ(ndigits(-3), 1);
EXPECT_EQ(ndigits(-78), 2);
EXPECT_EQ(ndigits(3), 1);
EXPECT_EQ(ndigits(78), 2);
EXPECT_EQ(ndigits(170), 3);
EXPECT_EQ(ndigits(-9245), 4);
EXPECT_EQ(ndigits(100000), 6);
EXPECT_EQ(ndigits(9245), 4);
EXPECT_EQ(ndigits(35710), 5);
EXPECT_EQ(ndigits(100000), 6);
EXPECT_EQ(ndigits(1035710), 7);
EXPECT_EQ(ndigits(-5905614858), 10);
EXPECT_EQ(ndigits(21035710), 8);
EXPECT_EQ(ndigits(461035710), 9);
EXPECT_EQ(ndigits(5905614858), 10);
EXPECT_EQ(ndigits(-3954784858), 10);
EXPECT_EQ(ndigits(-908561485), 9);
EXPECT_EQ(ndigits(18561485), 8);
EXPECT_EQ(ndigits(-18561485), 8);
EXPECT_EQ(ndigits(-1861485), 7);
EXPECT_EQ(ndigits(-186148), 6);
EXPECT_EQ(ndigits(36816), 5);
EXPECT_EQ(ndigits(-36816), 5);
EXPECT_EQ(ndigits(-3686), 4);
EXPECT_EQ(ndigits(686), 3);
EXPECT_EQ(ndigits(-686), 3);
EXPECT_EQ(ndigits(-10), 2);
EXPECT_EQ(ndigits(1), 1);
EXPECT_EQ(ndigits(-1), 1);

static_assert(ndigits(std::numeric_limits<int32_t>::max()) == 10);
static_assert(ndigits(std::numeric_limits<int32_t>::min()) == 10);
}

EXPECT_EQ(ndigits(std::numeric_limits<int64_t>::max()), 19);
EXPECT_EQ(ndigits(7299385028562659L), 16);
EXPECT_EQ(ndigits(299385028562659L), 15);
EXPECT_EQ(ndigits(29938502856265L), 14);
TEST(MathHelpers, NDigitsS64) {
EXPECT_EQ(ndigits(0L), 1);
EXPECT_EQ(ndigits(3L), 1);
EXPECT_EQ(ndigits(78L), 2);
EXPECT_EQ(ndigits(170L), 3);
EXPECT_EQ(ndigits(9245L), 4);
EXPECT_EQ(ndigits(35710L), 5);
EXPECT_EQ(ndigits(100000L), 6);
EXPECT_EQ(ndigits(1035710L), 7);
EXPECT_EQ(ndigits(18561485L), 8);
EXPECT_EQ(ndigits(908561485L), 9);
EXPECT_EQ(ndigits(5905614858L), 10);
EXPECT_EQ(ndigits(59085614858L), 11);
EXPECT_EQ(ndigits(590385614858L), 12);
EXPECT_EQ(ndigits(2938502856265L), 13);
EXPECT_EQ(ndigits(29938502856265L), 14);
EXPECT_EQ(ndigits(299385028562659L), 15);
EXPECT_EQ(ndigits(7299385028562659L), 16);
static_assert(ndigits(72993850285626590L) == 17);
EXPECT_EQ(ndigits(372993850285626590L), 18);
EXPECT_EQ(ndigits(8729938502856126509L), 19);
EXPECT_EQ(ndigits(std::numeric_limits<int64_t>::max()), 19);
EXPECT_EQ(ndigits(std::numeric_limits<int64_t>::min()), 19);
EXPECT_EQ(ndigits(-372909385028562659L), 18);
EXPECT_EQ(ndigits(-87299385028566509L), 17);
EXPECT_EQ(ndigits(-7299385028562659L), 16);
EXPECT_EQ(ndigits(-299385028562659L), 15);
EXPECT_EQ(ndigits(-29938502856265L), 14);
EXPECT_EQ(ndigits(-2938502856265L), 13);
EXPECT_EQ(ndigits(-590385614858L), 12);
EXPECT_EQ(ndigits(-59085614858L), 11);
EXPECT_EQ(ndigits(-5905614858L), 10);
EXPECT_EQ(ndigits(-908561485), 9);
EXPECT_EQ(ndigits(18561485), 8);
EXPECT_EQ(ndigits(1861485), 7);
EXPECT_EQ(ndigits(186148), 6);
EXPECT_EQ(ndigits(36816), 5);
EXPECT_EQ(ndigits(3686), 4);
EXPECT_EQ(ndigits(686), 3);
EXPECT_EQ(ndigits(10), 2);
EXPECT_EQ(ndigits(0), 1);
static_assert(ndigits(72993850285626590L) == 17);
EXPECT_EQ(ndigits(-908561485L), 9);
EXPECT_EQ(ndigits(-93058365L), 8);
EXPECT_EQ(ndigits(-1861485L), 7);
EXPECT_EQ(ndigits(-186148L), 6);
EXPECT_EQ(ndigits(-73686L), 5);
EXPECT_EQ(ndigits(-3686L), 4);
EXPECT_EQ(ndigits(-686L), 3);
EXPECT_EQ(ndigits(-10L), 2);
}

TEST(MathHelpers, NDigitsU8) {
EXPECT_EQ(ndigits(static_cast<uint8_t>(0)), 1);
EXPECT_EQ(ndigits(static_cast<uint8_t>(3)), 1);
EXPECT_EQ(ndigits(static_cast<uint8_t>(78)), 2);
EXPECT_EQ(ndigits(static_cast<uint8_t>(200)), 3);

static_assert(ndigits(std::numeric_limits<uint8_t>::max()) == 3);
static_assert(ndigits(std::numeric_limits<uint8_t>::min()) == 1);
}

TEST(MathHelpers, NDigitsU16) {
EXPECT_EQ(ndigits(static_cast<uint16_t>(0)), 1);
EXPECT_EQ(ndigits(static_cast<uint16_t>(10)), 2);
EXPECT_EQ(ndigits(static_cast<uint16_t>(170)), 3);
EXPECT_EQ(ndigits(static_cast<uint16_t>(4710)), 4);
EXPECT_EQ(ndigits(static_cast<uint16_t>(46816)), 5);

static_assert(ndigits(std::numeric_limits<uint16_t>::max()) == 5);
static_assert(ndigits(std::numeric_limits<uint16_t>::min()) == 1);
}

TEST(MathHelpers, NDigitsU32) {
EXPECT_EQ(ndigits(0U), 1);
EXPECT_EQ(ndigits(3U), 1);
EXPECT_EQ(ndigits(78U), 2);
EXPECT_EQ(ndigits(170U), 3);
EXPECT_EQ(ndigits(9245U), 4);
EXPECT_EQ(ndigits(35710U), 5);
EXPECT_EQ(ndigits(100000U), 6);
EXPECT_EQ(ndigits(1035710U), 7);
EXPECT_EQ(ndigits(31035710U), 8);
EXPECT_EQ(ndigits(561035710U), 9);
EXPECT_EQ(ndigits(4105614858U), 10);

static_assert(ndigits(std::numeric_limits<uint32_t>::max()) == 10);
static_assert(ndigits(std::numeric_limits<uint32_t>::min()) == 1);
}

TEST(MathHelpers, NDigitsU64) {
EXPECT_EQ(ndigits(0UL), 1);
EXPECT_EQ(ndigits(3UL), 1);
EXPECT_EQ(ndigits(78UL), 2);
EXPECT_EQ(ndigits(170UL), 3);
EXPECT_EQ(ndigits(9245UL), 4);
EXPECT_EQ(ndigits(35710UL), 5);
EXPECT_EQ(ndigits(100000UL), 6);
EXPECT_EQ(ndigits(1035710UL), 7);
EXPECT_EQ(ndigits(18561485UL), 8);
EXPECT_EQ(ndigits(908561485UL), 9);
EXPECT_EQ(ndigits(5905614858UL), 10);
EXPECT_EQ(ndigits(59085614858UL), 11);
EXPECT_EQ(ndigits(590385614858UL), 12);
EXPECT_EQ(ndigits(2938502856265UL), 13);
EXPECT_EQ(ndigits(29938502856265UL), 14);
EXPECT_EQ(ndigits(299385028562659UL), 15);
EXPECT_EQ(ndigits(7299385028562659UL), 16);
static_assert(ndigits(72993850285626590UL) == 17);
EXPECT_EQ(ndigits(372993850285626590UL), 18);
EXPECT_EQ(ndigits(8729938502856126509UL), 19);
EXPECT_EQ(ndigits(std::numeric_limits<uint64_t>::max()), 20);
EXPECT_EQ(ndigits(std::numeric_limits<uint64_t>::min()), 1);
}
} // namespace cct

0 comments on commit 89cd882

Please sign in to comment.