Skip to content

Commit 2cb2dc6

Browse files
committed
encapsulate programming by contract within this library, so that is not affected by and can not affect any outside code
1 parent cc73cd1 commit 2cb2dc6

File tree

63 files changed

+1201
-1002
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+1201
-1002
lines changed

README.md

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
![Alt text](images/clockxtrasmall_border2.jpg?raw=true "Clock Gears, photo by Krzysztof Golik, licensed CC BY-SA 4.0")
44

5-
Clockwork is a high performance, easy to use Modular Arithmetic library for C++ provided as a "header-only" library, supporting up to 128 bit integer types, and providing extensive support for Montgomery arithmetic. If you want or need Montgomery arithmetic in this range, or general modular arithmetic functions, Clockwork is almost certainly the fastest and easiest library you could use. For best performance make sure you define the standard C++ macro NDEBUG.
5+
Clockwork is a high performance, easy to use Modular Arithmetic library for C++ provided as a "header-only" library, supporting up to 128 bit integer types, and providing extensive support for Montgomery arithmetic. If you want or need Montgomery arithmetic in this range, or general modular arithmetic functions, Clockwork is almost certainly the fastest and easiest library you could use.
66

77
The library requires only C++11, and works with all higher versions of the C++ standard.
88

@@ -12,9 +12,7 @@ Clockwork is designed to be a flexible and bulletproof library with the best per
1212

1313
## Requirements
1414

15-
The Clockwork library requires only compiler support for C++11, which is essentially supported universally at this point.
16-
17-
For good performance you *must* ensure that the standard macro NDEBUG (see <cassert>) is defined when compiling.
15+
The Clockwork library requires only compiler support for C++11, which is essentially supported universally at this point.
1816

1917
Compilers that are confirmed to build this library without warnings or errors on Ubuntu linux (x64) include clang6, clang10, clang18, gcc7, gcc10, gcc13, and intel compiler 19. On Windows, Microsoft Visual C++ 2017, 2019, 2022 are all confirmed to build the library without warnings or errors. On MacOS, clang16 and gcc14 are confirmed to build without warnings or errors. The library is intended for use on all architectures (e.g. x86/64, ARM, RISC-V), but has so far been tested only with x86, x64 (Windows and Ubuntu), and ARM64 (MacOS).
2018

@@ -40,8 +38,6 @@ If you're using CMake for your project and you wish to add the Clockwork modular
4038
add_subdirectory(*path_of_the_cloned_modular_arithmetic_repository*   *your_binary_dir*/modular_arithmetic)
4139
target_link_libraries(*your_project_target_name*   hurchalla_modular_arithmetic)
4240

43-
For best performance you *must* ensure that the standard macro NDEBUG (see <cassert>) is defined when compiling. You can do this by calling CMake with -DCMAKE_BUILD_TYPE=Release.
44-
4541
It may help to see a simple [example project with CMake](examples/example_with_cmake).
4642

4743
### Without CMake
@@ -58,8 +54,6 @@ If you prefer, for the last command you could instead use CMake's default instal
5854
This will copy all the files needed for this modular arithmetic library to an "include" subfolder in the installation folder of your choosing.
5955
When compiling your project, you'll of course need to ensure that you have that include subfolder as part of your include path.
6056

61-
For best performance you *must* ensure that the standard macro NDEBUG (see <cassert>) is defined when compiling. You can generally do this by adding the option flag -DNDEBUG to your compile command.
62-
6357
It may help to see a simple [example](examples/example_without_cmake).
6458

6559
## The API

build_tests.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -567,7 +567,8 @@ elif [ "${mode,,}" = "debug" ]; then
567567
-DFORCE_TEST_HURCHALLA_CPP11_STANDARD=$force_cpp11_testing \
568568
-DCMAKE_BUILD_TYPE=Debug \
569569
-DCMAKE_EXE_LINKER_FLAGS="$clang_ubsan_link_flags" \
570-
-DCMAKE_CXX_FLAGS="$cpp_standard $cpp_stdlib \
570+
-DCMAKE_CXX_FLAGS="-DHURCHALLA_CLOCKWORK_ENABLE_ASSERTS=1 \
571+
$cpp_standard $cpp_stdlib \
571572
$clang_ubsan $gcc_ubsan \
572573
$test_avoid_cselect $test_heavyweight \
573574
$use_inline_asm $use_all_inline_asm \

examples/example_with_cmake/example.cpp

Lines changed: 20 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) 2020-2022 Jeffrey Hurchalla.
1+
// Copyright (c) 2020-2025 Jeffrey Hurchalla.
22
/*
33
* This Source Code Form is subject to the terms of the Mozilla Public
44
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -15,40 +15,37 @@
1515
#include <cassert>
1616
#include <cstdint>
1717

18-
#ifndef NDEBUG
19-
// remove this if you want to allow asserts
20-
// (they're very good for testing and debugging but may drastically slow down
21-
// the library).
22-
#error "Performance warning: asserts are enabled and will slow performance"
23-
#endif
2418

2519
int main()
2620
{
2721
namespace hc = ::hurchalla;
28-
int64_t modulus = 333333333;
29-
int64_t base = 42;
30-
int64_t exponent = 123456789;
22+
23+
// you could use any integer type that the compiler supports
24+
// (including __uint128_t)
25+
using T = uint64_t;
26+
27+
T modulus = 333333333;
28+
T base = 42;
29+
T exponent = 123456789;
3130

3231
// ---- Demonstration of modular exponentiation ----
3332

3433
// Montgomery arithmetic version:
3534
assert(modulus % 2 == 1); // montgomery arithmetic always needs odd modulus.
36-
// first construct a MontgomeryForm object to do Montgomery arithmetic
37-
// with a particular modulus.
38-
hc::MontgomeryForm<int64_t> mf(modulus);
39-
// convert base to its Montgomery representation.
40-
auto base_montval = mf.convertIn(base);
41-
// get the pow result in Montgomery representation.
42-
auto result_montval = mf.pow(base_montval, exponent);
43-
// convert the Montgomery representation result to normal integer domain.
44-
int64_t result1 = mf.convertOut(result_montval);
35+
// First construct a MontgomeryForm object to do Montgomery arithmetic
36+
// with the modulus we chose.
37+
hc::MontgomeryForm<T> mf(modulus);
38+
// Convert base to its Montgomery representation.
39+
auto mont_base = mf.convertIn(base);
40+
// Get the pow result in Montgomery representation.
41+
auto mont_result = mf.pow(mont_base, exponent);
42+
// Convert the Montgomery representation result to normal integer domain.
43+
T result1 = mf.convertOut(mont_result);
4544

4645

4746
// Standard arithmetic version: (note that Montgomery arithmetic is
48-
// typically faster, and that modular_pow() requires an unsigned type)
49-
uint64_t result2 = hc::modular_pow(static_cast<uint64_t>(base),
50-
static_cast<uint64_t>(exponent),
51-
static_cast<uint64_t>(modulus));
47+
// usually much faster)
48+
T result2 = hc::modular_pow(base, exponent, modulus);
5249

5350

5451
std::cout << "Example results for " << base << "^" << exponent

examples/example_with_cmake/example.sh

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/usr/bin/env bash
22

3-
# Copyright (c) 2020-2022 Jeffrey Hurchalla.
3+
# Copyright (c) 2020-2025 Jeffrey Hurchalla.
44
# This Source Code Form is subject to the terms of the Mozilla Public
55
# License, v. 2.0. If a copy of the MPL was not distributed with this
66
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
@@ -10,10 +10,6 @@
1010
# a CMake project. If you haven't already done so, you should follow the steps
1111
# in the README.md for "How to use the library" | "With CMake"
1212

13-
# Note that using CMake with -DCMAKE_BUILD_TYPE=Release will ensure that the
14-
# standard macro NDEBUG (see <cassert>) is defined, which is essential for best
15-
# performance.
16-
1713
mkdir -p tmp
1814
cmake -S. -B./tmp -DCMAKE_BUILD_TYPE=Release
1915
cmake --build ./tmp --config Release

examples/example_without_cmake/example.cpp

Lines changed: 20 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) 2020-2022 Jeffrey Hurchalla.
1+
// Copyright (c) 2020-2025 Jeffrey Hurchalla.
22
/*
33
* This Source Code Form is subject to the terms of the Mozilla Public
44
* License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -15,40 +15,37 @@
1515
#include <cassert>
1616
#include <cstdint>
1717

18-
#ifndef NDEBUG
19-
// remove this if you want to allow asserts
20-
// (they're very good for testing and debugging but may drastically slow down
21-
// the library).
22-
#error "Performance warning: asserts are enabled and will slow performance"
23-
#endif
2418

2519
int main()
2620
{
2721
namespace hc = ::hurchalla;
28-
int64_t modulus = 333333333;
29-
int64_t base = 42;
30-
int64_t exponent = 123456789;
22+
23+
// you could use any integer type that the compiler supports
24+
// (including __uint128_t)
25+
using T = uint64_t;
26+
27+
T modulus = 333333333;
28+
T base = 42;
29+
T exponent = 123456789;
3130

3231
// ---- Demonstration of modular exponentiation ----
3332

3433
// Montgomery arithmetic version:
3534
assert(modulus % 2 == 1); // montgomery arithmetic always needs odd modulus.
36-
// first construct a MontgomeryForm object to do Montgomery arithmetic
37-
// with a particular modulus.
38-
hc::MontgomeryForm<int64_t> mf(modulus);
39-
// convert base to its Montgomery representation.
40-
auto base_montval = mf.convertIn(base);
41-
// get the pow result in Montgomery representation.
42-
auto result_montval = mf.pow(base_montval, exponent);
43-
// convert the Montgomery representation result to normal integer domain.
44-
int64_t result1 = mf.convertOut(result_montval);
35+
// First construct a MontgomeryForm object to do Montgomery arithmetic
36+
// with the modulus we chose.
37+
hc::MontgomeryForm<T> mf(modulus);
38+
// Convert base to its Montgomery representation.
39+
auto mont_base = mf.convertIn(base);
40+
// Get the pow result in Montgomery representation.
41+
auto mont_result = mf.pow(mont_base, exponent);
42+
// Convert the Montgomery representation result to normal integer domain.
43+
T result1 = mf.convertOut(mont_result);
4544

4645

4746
// Standard arithmetic version: (note that Montgomery arithmetic is
48-
// typically faster, and that modular_pow() requires an unsigned type)
49-
uint64_t result2 = hc::modular_pow(static_cast<uint64_t>(base),
50-
static_cast<uint64_t>(exponent),
51-
static_cast<uint64_t>(modulus));
47+
// usually much faster)
48+
T result2 = hc::modular_pow(base, exponent, modulus);
5249

5350

5451
std::cout << "Example results for " << base << "^" << exponent

examples/example_without_cmake/example.sh

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/usr/bin/env bash
22

3-
# Copyright (c) 2020-2022 Jeffrey Hurchalla.
3+
# Copyright (c) 2020-2025 Jeffrey Hurchalla.
44
# This Source Code Form is subject to the terms of the Mozilla Public
55
# License, v. 2.0. If a copy of the MPL was not distributed with this
66
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
@@ -27,8 +27,7 @@ cpp_compiler=g++
2727

2828

2929
$cpp_compiler -std="c++17" \
30-
-Wall -Wextra \
31-
-O2 -DNDEBUG \
30+
-Wall -Wextra -O2 \
3231
-I$include_path \
3332
-o example example.cpp
3433

modular_arithmetic/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ target_sources(hurchalla_basic_modular_arithmetic INTERFACE
4646
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/hurchalla/modular_arithmetic/modular_multiplicative_inverse.h>
4747
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/hurchalla/modular_arithmetic/modular_pow.h>
4848
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/hurchalla/modular_arithmetic/modular_subtraction.h>
49+
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/hurchalla/modular_arithmetic/detail/clockwork_programming_by_contract.h>
4950
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/hurchalla/modular_arithmetic/detail/impl_modular_multiplicative_inverse.h>
5051
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/hurchalla/modular_arithmetic/detail/impl_modular_pow.h>
5152
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/hurchalla/modular_arithmetic/detail/optimization_tag_structs.h>

modular_arithmetic/include/hurchalla/modular_arithmetic/absolute_value_difference.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
#include "hurchalla/modular_arithmetic/detail/platform_specific/impl_absolute_value_difference.h"
1313
#include "hurchalla/util/traits/ut_numeric_limits.h"
1414
#include "hurchalla/util/compiler_macros.h"
15-
#include "hurchalla/util/programming_by_contract.h"
15+
#include "hurchalla/modular_arithmetic/detail/clockwork_programming_by_contract.h"
1616

1717
namespace hurchalla {
1818

@@ -24,13 +24,13 @@ template <typename T> HURCHALLA_FORCE_INLINE
2424
T absolute_value_difference(T a, T b)
2525
{
2626
static_assert(ut_numeric_limits<T>::is_integer, "");
27-
HPBC_PRECONDITION(a >= 0);
28-
HPBC_PRECONDITION(b >= 0);
27+
HPBC_CLOCKWORK_PRECONDITION(a >= 0);
28+
HPBC_CLOCKWORK_PRECONDITION(b >= 0);
2929

3030
T result = detail::impl_absolute_value_difference<T>::call(a, b);
3131

32-
HPBC_POSTCONDITION(result >= 0);
33-
HPBC_POSTCONDITION(result == ((a>b) ? a-b : b-a));
32+
HPBC_CLOCKWORK_POSTCONDITION(result >= 0);
33+
HPBC_CLOCKWORK_POSTCONDITION(result == ((a>b) ? a-b : b-a));
3434
return result;
3535
}
3636

0 commit comments

Comments
 (0)