Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 25 additions & 22 deletions .github/workflows/arm.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,33 @@ on: [push]

jobs:
build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
# native arm64 runner (free for public repositories)
os: [ubuntu-24.04-arm]
version: [ 14 ]
build_type: [Release, Debug]

name: Build & test on ${{ matrix.os }} with gcc-${{ matrix.version }} in ${{ matrix.build_type }} mode.
runs-on: ${{ matrix.os }}

steps:
- uses: actions/checkout@v4
with:
submodules: recursive

- uses: pguyot/arm-runner-action@HEAD
with:
bind_mount_repository: true
base_image: raspios_lite_arm64:latest
cpu: cortex-a53
image_additional_mb: 512
commands: |
sudo apt-get install -y cmake make git autoconf libtool libgmp-dev libgmp10
git clone --depth=1 --single-branch --branch v1.7.1 https://github.com/google/benchmark.git benchmark && mkdir -p benchmark/build && cd ./benchmark/build && cmake -DCMAKE_BUILD_TYPE=Release -DBENCHMARK_ENABLE_GTEST_TESTS=OFF ../ && make -j
sudo apt-get install -y libgtest-dev && cd /usr/src/gtest && sudo cmake CMakeLists.txt && sudo make && sudo cp lib/libgtest.a /usr/lib && sudo cp lib/libgtest_main.a /usr/lib && sudo ln -s /usr/lib/libgtest.a /usr/local/lib/libgtest.a && sudo ln -s /usr/lib/libgtest_main.a /usr/local/lib/libgtest_main.a
cd /decoding
mkdir -p cmake-build-release
mkdir -p cmake-build-debug
cd cmake-build-debug
cmake .. -DCMAKE_BUILD_TYPE=Debug
make -j
ctest -C Debug -V
cd ../cmake-build-release
cmake .. -DCMAKE_BUILD_TYPE=Release
make -j
ctest -C Debug -V
- name: Install Software
run: |
sudo apt-get update
sudo apt-get install -y libtbb-dev g++-${{matrix.version}} libgtest-dev libbenchmark-dev

- name: Configure CMake
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{matrix.build_type}} -DCMAKE_CXX_COMPILER=g++-${{matrix.version}}

- name: Build
run: cmake --build ${{github.workspace}}/build --parallel $(nproc)

- name: Test
working-directory: ${{github.workspace}}/build
run: ctest --output-on-failure --timeout 600 -j$(nproc)
2 changes: 1 addition & 1 deletion .github/workflows/osx-x86.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ jobs:
brew install libomp llvm googletest google-benchmark

- name: Configure CMake
run: cmake -B ${{github.workspace}}/build -D CMAKE_CXX_COMPILER=$(brew --prefix llvm)/bin/clang++
run: cmake -B ${{github.workspace}}/build -D CMAKE_C_COMPILER=$(brew --prefix llvm)/bin/clang -D CMAKE_CXX_COMPILER=$(brew --prefix llvm)/bin/clang++

- name: Build
run: cmake --build ${{github.workspace}}/build --config Debug
Expand Down
25 changes: 7 additions & 18 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,37 +8,26 @@ jobs:
matrix:
# ubuntu 20 doesnt support c++20
#os: [ubuntu-22.04, ubuntu-20.04]
os: [ubuntu-22.04]
# TODO currently not working. The CI does not find omp? Probably need
# to install the correct omp version for the correct compiler
# compiler: [ g++-10, clang++-11, clang++-12, clang++-13, clang++-14, clang++-15]
# NOTE: C++23 needs a newer gcc than ubuntu-22.04's gcc-11
os: [ubuntu-24.04]
compiler: [ g++-14 ]
build_type: [Release, Debug]

name: Build & test on ${{ matrix.os }} with ${{ matrix.compiler }} in ${{ matrix.build_type }} mode.
runs-on: ${{ matrix.os }}

steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
submodules: recursive

- name: Install Software
run: |
sudo apt-get install -y libtbb-dev llvm-11 clang-11 llvm-12 clang-12 llvm-13 clang-13 llvm-14 clang-14 llvm-15 clang-15 gcc-10
# libomp-11-dev libomp-12-dev libomp-13-dev libomp-14-dev libomp-15-dev libomp5-11 libomp5-12 libomp5-13 libomp5-14 libomp5-15

- name: Install Google Benchmark
run: git clone --depth=1 --single-branch --branch v1.7.1 https://github.com/google/benchmark.git benchmark && mkdir -p benchmark/build && cd ./benchmark/build && cmake -DCMAKE_BUILD_TYPE=Release -DBENCHMARK_ENABLE_GTEST_TESTS=OFF ../ && make -j

- name: Install gtest
run:
sudo apt-get install libgtest-dev && cd /usr/src/gtest && sudo cmake CMakeLists.txt && sudo make && sudo cp lib/libgtest.a /usr/lib && sudo cp lib/libgtest_main.a /usr/lib && sudo ln -s /usr/lib/libgtest.a /usr/local/lib/libgtest.a && sudo ln -s /usr/lib/libgtest_main.a /usr/local/lib/libgtest_main.a

sudo apt-get update
sudo apt-get install -y libtbb-dev ${{ matrix.compiler }} libgtest-dev libbenchmark-dev

- name: Configure CMake
# env:
# CXX: ${{ matrix.compiler }}
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{matrix.build_type}}
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{matrix.build_type}} -DCMAKE_CXX_COMPILER=${{ matrix.compiler }}

- name: Build
run: cmake --build ${{github.workspace}}/build --config ${{matrix.build_type}}
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ deps/decoding/
deps/elena_smallSecretLWE/
.clangd/
build/
build-gcc/
build-clang/
compile_commands.json
.vimspector.json
main.h
Expand Down
85 changes: 54 additions & 31 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ cmake_minimum_required(VERSION 3.20)
project(decoding)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_VERBOSE_MAKEFILE ON)
set(CMAKE_CXX_STANDARD 20)
# NOTE: cryptanalysislib needs C++23 (e.g. `static` variables in `constexpr` functions)
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# options
Expand All @@ -13,7 +14,7 @@ option(USE_LTO "Enable -flto" OFF)
option(USE_PROFILE "Enable profile guided optmization" OFF)
option(USE_POLLY "Enable polly loop optimization" OFF)
option(USE_BOLT "Enable bolt binary optmization" OFF)
option(USE_TRACY "Enable tracy profiling" ON)
option(USE_TRACY "Enable tracy profiling" OFF)

set(default_build_type "Release")

Expand All @@ -35,49 +36,52 @@ endif()
include(FetchContent)
include(ExternalProject)
include(CheckCXXCompilerFlag) # check for compiler optimization flags
include(CheckCXXSourceCompiles) # check for libraries
include(CheckIPOSupported) # check for -flto
include(CheckLanguage) # needed for `check_language(CUDA)`

# load the external main project. This encloses all helper functions.
ExternalProject_Add(cryptanalysislib_project
SOURCE_DIR ${CMAKE_SOURCE_DIR}/deps/cryptanalysislib
CONFIGURE_COMMAND cd <SOURCE_DIR> && mkdir -p build
COMMAND cd <SOURCE_DIR> && cd build/ && cmake ..
BUILD_COMMAND cd <SOURCE_DIR> && cd build/ && make -j8
INSTALL_COMMAND ""
TEST_COMMAND ""
)

# NOTE: cryptanalysislib is header only, hence it is not build (neither its
# tests nor its benchmarks). Only its `src` directory is included below.

include("deps/cryptanalysislib/deps/cmake_optimize_for_architecture/HostOptimizations.cmake")
include("${CMAKE_CURRENT_SOURCE_DIR}/deps/cryptanalysislib/deps/cmake_optimize_for_architecture/HostOptimizations.cmake")

check_cxx_compiler_flag(-march=native COMPILER_SUPPORTS_MARCH_NATIVE)
check_cxx_compiler_flag(-fno-inline COMPILER_SUPPORTS_NO_INLINE)
check_cxx_compiler_flag(-fsanitize=address COMPILER_SUPPORTS_SANITIZE_ADDRESS) # TODO support not recognized
# NOTE: the sanitizer runtime is needed at link time
set(CMAKE_REQUIRED_LINK_OPTIONS -fsanitize=address)
check_cxx_compiler_flag(-fsanitize=address COMPILER_SUPPORTS_SANITIZE_ADDRESS)
unset(CMAKE_REQUIRED_LINK_OPTIONS)
check_cxx_compiler_flag(-fsanitize=memory COMPILER_SUPPORTS_SANITIZE_MEMORY)
check_cxx_compiler_flag(-fconstexpr-steps=9999999 COMPILER_SUPPORTS_CONSTEXPR_COST)
check_cxx_compiler_flag(-fno-exceptions COMPILER_SUPPORTS_NO_EXCEPTION)
check_ipo_supported(RESULT lto_supported OUTPUT error)
check_cxx_compiler_flag(-latomic LINKER_SUPPORTS_ATOMIC) # TODO
# NOTE: `-l` is a linker flag, hence a library check
set(CMAKE_REQUIRED_LIBRARIES atomic)
check_cxx_source_compiles("int main() { return 0; }" LINKER_SUPPORTS_ATOMIC)
unset(CMAKE_REQUIRED_LIBRARIES)

# find needed packages: the good thing only is: we only have a single external
# dependencies.
enable_testing()
find_package(OpenMP REQUIRED)
# NOTE: only C++ is compiled, the C compiler may lack OpenMP (AppleClang)
find_package(OpenMP REQUIRED COMPONENTS CXX)
find_package(Threads REQUIRED)
find_package(GTest)
find_package(benchmark)
find_package(Git QUIET)

# init the submodules
FetchContent_Declare(
tracy
GIT_REPOSITORY https://github.com/wolfpld/tracy
GIT_TAG master
GIT_SHALLOW TRUE
GIT_PROGRESS TRUE
)
FetchContent_MakeAvailable(tracy)
# NOTE: only download tracy if it is actually used.
if(USE_TRACY)
FetchContent_Declare(
tracy
GIT_REPOSITORY https://github.com/wolfpld/tracy
GIT_TAG v0.14.1
GIT_SHALLOW TRUE
GIT_PROGRESS TRUE
)
FetchContent_MakeAvailable(tracy)
endif()

# global include directories
include_directories("deps/b63/include/b63")
Expand All @@ -90,14 +94,15 @@ link_directories("/usr/local/lib")
# two possible options. 'tcmalloc' is the standard google malloc implementation
if(USE_TCMALLOC)
message(STATUS "Using tcmalloc")
set(MALLOC_LIBRARY_FLAGS "tcmalloc")
# NOTE: the test targets link against `TCMALLOC_LIBRARIES`
set(TCMALLOC_LIBRARIES "tcmalloc")
endif()

#if(USE_SANITIZER AND COMPILER_SUPPORTS_SANITIZE_ADDRESS)
if(USE_SANITIZER AND COMPILER_SUPPORTS_SANITIZE_ADDRESS)
message(STATUS "Using address sanitize")
# possible sanitizers = -fsanitize=[address,leak,thread,memory,undefined]
set(SANITIZER_FLAGS "-fsanitize=address -fsanitize=pointer-compare -fno-omit-frame-pointer")
#endif()
endif()

if(USE_NOINLINE AND COMPILER_SUPPORTS_NO_INLINE)
message(STATUS "not inlining")
Expand All @@ -113,7 +118,11 @@ if(lto_supported AND USE_LTO)
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
endif()

set(ALLOWED_WARNINGS " -Wno-unknown-pragmas -Wno-c99-designator -Wno-invalid-constexpr -Wno-unused-function -Wno-zero-length-array")
set(ALLOWED_WARNINGS " -Wno-unknown-pragmas -Wno-invalid-constexpr -Wno-unused-function")
# NOTE: clang only flags, gcc warns about them
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(ALLOWED_WARNINGS "${ALLOWED_WARNINGS} -Wno-c99-designator -Wno-zero-length-array")
endif()

message(STATUS "System Processor: ${CMAKE_SYSTEM_PROCESSOR}")

Expand All @@ -135,6 +144,10 @@ set(LINK_TEST_FLAGS
OpenMP::OpenMP_CXX
)

if(LINKER_SUPPORTS_ATOMIC)
list(APPEND LINK_TEST_FLAGS atomic)
endif()

if(USE_TRACY)
message(STATUS "Using tracy")
list(APPEND LINK_TEST_FLAGS TracyClient)
Expand Down Expand Up @@ -228,8 +241,8 @@ include_directories("deps/cryptanalysislib/deps/b63/include/b63")
include_directories("deps/cryptanalysislib/src")

include_directories("src")
include_directories("test/decoding/challenges")
include_directories("test/mceliece/challenges")
include_directories("tests/decoding/challenges")
include_directories("tests/mceliece/challenges")
include_directories("/usr/local/include")

link_directories("/usr/local/lib")
Expand Down Expand Up @@ -258,6 +271,15 @@ add_custom_target (
#TODO add_executable(main main.cpp)
# target_link_libraries(main ${LINK_TEST_FLAGS})

# NOTE: there is currently no `main.cpp`. All targets below depend on it.
if(NOT EXISTS ${CMAKE_SOURCE_DIR}/main.cpp)
if(USE_PROFILE OR USE_POLLY)
message(WARNING "USE_PROFILE/USE_POLLY need a `main.cpp`, which does not exist. Ignoring them.")
endif()
set(USE_PROFILE OFF)
set(USE_POLLY OFF)
endif()

if(USE_PROFILE)
add_executable(main_analysis1 main.cpp)
target_link_libraries(main_analysis1 ${LINK_TEST_FLAGS} -fprofile-instr-generate=code.profraw)
Expand All @@ -278,7 +300,8 @@ if(USE_PROFILE)
add_dependencies(main_profile2 LLVM_PROFDATA)
endif()

if (CMAKE_CXX_COMPILER_ID STREQUAL "clang")
# NOTE: the compiler id is `Clang` (or `AppleClang`), never `clang`
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND EXISTS ${CMAKE_SOURCE_DIR}/main.cpp)
add_executable(main_PGO_instrumentation_first main.cpp)
target_compile_options(main_PGO_instrumentation_first PUBLIC -fprofile-instr-generate -DUSE_LOOPS=2)
target_link_libraries(main_PGO_instrumentation_first ${LINK_TEST_FLAGS} -fprofile-instr-generate)
Expand Down
36 changes: 25 additions & 11 deletions decoding/matrix.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ def from_string(self, d: str, transposed: bool = True) -> 'Matrix':
D.data[i][j] = t

if transposed:
self = D.transpose()
# NOTE: assigning to `self` only rebinds the local name
self.data = D.transpose().data
return self

def random(self) -> 'Matrix':
Expand All @@ -81,6 +82,7 @@ def random_row_with_weight(self, row: int, w: int) -> 'Matrix':

def gauß(self, max_rank: Union[int, None] = None) -> int:
""" simple Gaussian elimination. Is an inplace operation
NOTE: `q` must be prime.
:return the rank of the matrix
"""
if max_rank is None:
Expand All @@ -91,10 +93,10 @@ def gauß(self, max_rank: Union[int, None] = None) -> int:
for col in range(self.ncols):
if row >= min(max_rank, self.nrows): break

# find pivot
# find pivot (any non-zero element, not only 1)
sel = -1
for i in range(row, self.nrows):
if self.data[i][col] == 1:
if self.data[i][col] != 0:
sel = i
break

Expand All @@ -103,14 +105,19 @@ def gauß(self, max_rank: Union[int, None] = None) -> int:

self.swap_rows(sel, row)

# solve remaining coordinates
# normalize the pivot to 1
inv = pow(self.data[row][col], -1, self.q)
for j in range(self.ncols):
self.data[row][j] = (self.data[row][j] * inv) % self.q

# solve remaining coordinates: subtract the correct multiple
for i in range(self.nrows):
if i == row: continue
if self.data[i][col] == 0: continue
factor = self.data[i][col]
if factor == 0: continue

for j in range(self.ncols):
self.data[i][j] += self.data[row][j]
self.data[i][j] %= self.q
self.data[i][j] = (self.data[i][j] - factor * self.data[row][j]) % self.q

row += 1

Expand Down Expand Up @@ -162,14 +169,14 @@ def transpose(self) -> 'Matrix':
def popcnt_row(self, row: int) -> int:
""" computes the hamming weight of a row"""
assert row < self.nrows
return sum(self.data[row])
return sum(1 for d in self.data[row] if d != 0)

def popcnt_col(self, col: int) -> int:
""" computes the hamming weight of a column"""
assert col < self.ncols
t = 0
for j in range(self.nrows):
t += self.data[j][col]
t += int(self.data[j][col] != 0)
return t

def swap_rows(self, i: int, j: int) -> None:
Expand All @@ -190,11 +197,18 @@ def swap_cols(self, i: int, j: int) -> None:
self.data[k][i] = self.data[k][j]
self.data[k][j] = tmp

def copy(self) -> 'Matrix':
""" deep copy """
C = Matrix(self.nrows, self.ncols, self.q)
C.data = [row[:] for row in self.data]
return C

def __add__(self, B: 'Matrix'):
return self.add(B)
# NOTE: `A + B` must not modify `A`
return self.copy().add(B)

def __sub__(self, B: 'Matrix'):
return self.sub(B)
return self.copy().sub(B)

def __mul__(self, B: 'Matrix'):
return self.mul(B)
Expand Down
Loading
Loading