-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 2d4bc6f
Showing
207 changed files
with
19,697 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
--- | ||
# We use clang-format to keep C++ code styling consistent | ||
# The rules for our specific style are delineated here | ||
AccessModifierOffset: "-4" | ||
AlignConsecutiveMacros: "true" | ||
# AlignConsecutiveAssignments: "true" | ||
AlignConsecutiveDeclarations: "true" | ||
AlignEscapedNewlines: Left | ||
AllowShortBlocksOnASingleLine: "true" | ||
AllowShortCaseLabelsOnASingleLine: "true" | ||
AllowShortFunctionsOnASingleLine: All | ||
AllowShortIfStatementsOnASingleLine: WithoutElse | ||
AllowShortLoopsOnASingleLine: "true" | ||
AlwaysBreakAfterReturnType: TopLevelDefinitions | ||
AlwaysBreakTemplateDeclarations: "Yes" | ||
BreakBeforeBraces: Stroustrup | ||
BreakBeforeTernaryOperators: "true" | ||
BreakConstructorInitializers: AfterColon | ||
BreakInheritanceList: AfterColon | ||
ColumnLimit: 120 | ||
CompactNamespaces: "true" | ||
FixNamespaceComments: "true" | ||
IncludeBlocks: Regroup | ||
IndentCaseLabels: "true" | ||
IndentPPDirectives: BeforeHash | ||
IndentWidth: "4" | ||
PointerAlignment: Left | ||
NamespaceIndentation: Inner | ||
SortIncludes: false | ||
SortUsingDeclarations: "true" | ||
SpaceAfterTemplateKeyword: "false" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
# Creates & releases a minimal archive of this library's core files and directories. | ||
# This is useful for the standard CMake module `FetchContent` and friends. | ||
name: Release library archive | ||
|
||
# The files & directories we archive and the name for the archive. | ||
# The git tag for the release is either 'current' or the relase tag like '2.1.2' | ||
env: | ||
archive_content: LICENSE CMakeLists.txt include | ||
archive_name: ${{ github.event.repository.name }}.zip | ||
archive_tag: ${{github.ref == 'refs/heads/main' && 'current' || github.ref}} | ||
|
||
# We may overwrite the $archive_tag so need write permissions | ||
permissions: | ||
contents: write | ||
|
||
# When is the workflow run? | ||
on: | ||
# Any push to the main branch that changes the content of the archive. | ||
# TODO: Perhaps we can use the $archive_content variable here? | ||
push: | ||
branches: | ||
- main | ||
paths: | ||
- "LICENSE" | ||
- "CMakeLists.txt" | ||
- "include/**" | ||
# Any formal release | ||
release: | ||
types: [published] | ||
|
||
# You can trigger the workflow manually (handy to debug the workflow). | ||
workflow_dispatch: | ||
|
||
# There is just a single job in the workflow | ||
jobs: | ||
archive: | ||
name: Create and release an archive of the library's core files and directories. | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v4 | ||
|
||
- name: Zip the important files and directories | ||
run: | | ||
echo "Creating archive '$archive_name' from: '$archive_content' ..." | ||
echo "The git ref is: '${{github.ref}}'" | ||
echo "The release tag: '${{env.archive_tag}}'" | ||
zip -r $archive_name $archive_content | ||
- name: Upload the archive to a release | ||
uses: svenstaro/upload-release-action@v2 | ||
with: | ||
repo_token: ${{secrets.GITHUB_TOKEN}} | ||
file: ${{env.archive_name}} | ||
tag: ${{env.archive_tag}} | ||
overwrite: true | ||
body: "Latest minimal version of the library for CMake's module `FetchContent` and friends." |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
# Set up the folders/files that should never go into the git repository. | ||
|
||
# The Mac Finder produces a metadata file in directories that is noise | ||
.DS_Store | ||
|
||
# My specific Visual Code setup is only useful to me | ||
.vscode/ | ||
|
||
# Ditto for the IntelliJ setup which I have used very occasionally | ||
.idea/ | ||
|
||
# Occasionally build with Visual Studio which puts its artifacts into an out directory | ||
out/ | ||
|
||
# Otherwise we build using CMake on a Unix system and force artifacts to go into "build" folders | ||
build* | ||
build*/ | ||
|
||
# Some local scratch files are kept in private directories that need not go into git | ||
private/ | ||
|
||
# The documentation website uses Quarto and we don't need to version its cache or what it builds. | ||
.quarto/ | ||
_site/ | ||
.luarc.json | ||
|
||
# Jupyter checkpoint directories need not go into git | ||
.ipynb_checkpoints/ | ||
|
||
# Generally don't want to check Node.js modules into the remote repo -- just the recipes for installing them. | ||
node_modules/ | ||
|
||
# The old documentation website used Antora and various things it builds/installs need not be in the remote repo | ||
antora/*/.cache/ | ||
antora/*/playbook-remote | ||
antora/*/build/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
cmake_minimum_required(VERSION 3.24) | ||
|
||
# Our C++ project ... | ||
project(bit DESCRIPTION "C++ classes for working in GF(2)" LANGUAGES CXX) | ||
|
||
# Add a target for the "library" we are building (bit is header only -- hence INTERFACE). | ||
# Also add an alias that prepends a "namespace" -- if clients use that to link to, they get better error messages. | ||
add_library(bit INTERFACE) | ||
add_library(bit::bit ALIAS bit) | ||
|
||
# We use some C++20 features. | ||
target_compile_features(bit INTERFACE cxx_std_20) | ||
|
||
# Where to find the bit headers (e.g., how to resolve `#include <bit/bit.h>`). | ||
target_include_directories(bit INTERFACE | ||
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include/> | ||
$<INSTALL_INTERFACE:include/bit>) | ||
|
||
# That's it unless we are developing the library instead of just using it. | ||
if (PROJECT_IS_TOP_LEVEL) | ||
|
||
# Append our local directory of CMake modules to the default ones searched by CMake. | ||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") | ||
|
||
# Prevent in-source builds for the example programs. | ||
include(disable_in_source_builds) | ||
disable_in_source_builds() | ||
|
||
# Make the compiler issue warnings for "bad" code, etc. | ||
include(compiler_init) | ||
compiler_init(bit) | ||
|
||
# Debug builds get the BIT_VERIFY flag set. | ||
target_compile_definitions(bit INTERFACE $<$<CONFIG:Debug>: -DBIT_VERIFY>) | ||
|
||
# For neatness, we put the example executables in build/bin/. | ||
include(GNUInstallDirs) | ||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}") | ||
|
||
# Our example programs use the header-only `utilities` library. | ||
include(FetchContent) | ||
FetchContent_Declare(utilities URL https://github.com/nessan/utilities/releases/download/current/utilities.zip) | ||
FetchContent_MakeAvailable(utilities) | ||
|
||
# Walk through the examples/ directory and build a target for each .cpp file with appropriate linkage. | ||
# We have a CMake module that makes that traversal straightforward. | ||
include(add_executables) | ||
add_executables(examples bit::bit utilities::utilities) | ||
|
||
endif() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# Changelog | ||
|
||
This file documents notable changes to the project. | ||
|
||
## 30-Apr-2024 | ||
|
||
- Moved the repo to github. | ||
- The documentation/site-builder was moved from AsciiDoc/Antora to Markdown/Quarto. | ||
- Added the `bit::polynomial` class for polynomials over GF(2). | ||
- Incorporated various fixes and speedups from @jason. | ||
|
||
## Earlier (2022-23) | ||
|
||
- The library started as `GF2` which evolved to the `bit` library hosted on GitLab. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
Copyright (c) 2023 Nessan Fitzmaurice | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
# README | ||
|
||
`bit` is a header-only C++ library for numerical work in _bit-space_, which mathematicians call {gf2}[], the simplest Galois field with just two elements 0 & 1. All arithmetic operations in bit-space are mod 2, so what starts in bit-space stays in bit-space. | ||
|
||
The library provides vector and matrix classes for performing linear algebra in bit-space. The [`bit::vector`][] class represents _bit_vectors_, and the [`bit::matrix`][] class represents _bit-matrices_. The library also has a [`bit::polynomial`][] class to represent _bit-polynomials_ over GF(2). | ||
|
||
These classes are efficient and pack the individual bit elements into natural word blocks. You can size/resize the classes at run-time. | ||
|
||
Because arithmetic operations in GF(2) are mod 2, addition/subtraction becomes the `XOR` operation, and multiplication/division becomes the `AND` operation. The `bit` library uses those equivalences to efficiently perform most interactions on and between bit-vectors and bit-matrices by simultaneously working on whole blocks of elements. | ||
|
||
The `bit` library provides a rich interface to set up and manipulate bit-vectors and bit-matrices in various ways. Amongst other things, the interface includes methods to solve systems of linear equations over GF(2) and to look at the eigen-structure of bit-matrices. | ||
|
||
The `bit::polynomial` class has methods to compute $x^N\bmod{p(x)}$ where $p(x)$ is a polynomial over $\mathbb{F}_2$ and $N$ is a potentially huge integer. | ||
|
||
## Installation | ||
|
||
This library is header-only, so there is nothing to compile and link—drop the `bit` include directory somewhere convenient, and you're good to go. | ||
|
||
Alternatively, if you are using `CMake`, you can use the standard `FetchContent` module by adding a few lines to your project's `CMakeLists.txt` file: | ||
|
||
```cmake | ||
include(FetchContent) | ||
FetchContent_Declare(bit URL https://github.com/nessan/bit/releases/download/current/bit.zip) | ||
FetchContent_MakeAvailable(bit) | ||
``` | ||
|
||
This command downloads and unpacks an archive of the current version of the `bit` library to your project's build folder. You can then add a dependency on `bit::bit`, a `CMake` alias for `bit`. `FetchContent` will automatically ensure the build system knows where to find the downloaded header files and any needed compiler flags. | ||
|
||
Used like this, `FetchContent` will only download a minimal library version without any redundant test code, sample programs, documentation files, etc. | ||
|
||
## Example | ||
|
||
Here is a simple example of a program that uses `bit`: | ||
|
||
```cpp | ||
#include <bit/bit.h> | ||
int main() | ||
{ | ||
auto M = bit::matrix<>::random(6, 6); | ||
auto c = bit::characteristic_polynomial(M); | ||
std::cout << "The bit-matrix M:\n" << M << "\n"; | ||
std::cout << "has characteristic polynomial c(x) = " << c << ".\n"; | ||
std::cout << "The polynomial sum c(M) gives:\n"; | ||
std::cout << c(M) << "\n"; | ||
} | ||
``` | ||
|
||
This program creates a random 6 x 6 bit-matrix `M` where 0 & 1 are equally likely to occur and then extracts its characteristic polynomial $c(x) = c_0 + c_1 x + c_2 x^2 + ... + c_6 x^6$. Finally, the program verifies that `M` satisfies its characteristic equation as expected from the Cayley-Hamilton theorem. | ||
|
||
Here is the output from one run of the program: | ||
|
||
```sh | ||
The bit-matrix M: | ||
│0 1 1 0 0 0│ | ||
│0 0 1 0 1 0│ | ||
│1 1 0 0 0 1│ | ||
│0 0 0 0 0 1│ | ||
│0 1 0 0 1 1│ | ||
│1 1 0 1 0 1│ | ||
has characteristic polynomial c(x) = x^1 + x^4 + x^6. | ||
The polynomial sum c(M) gives: | ||
│0 0 0 0 0 0│ | ||
│0 0 0 0 0 0│ | ||
│0 0 0 0 0 0│ | ||
│0 0 0 0 0 0│ | ||
│0 0 0 0 0 0│ | ||
│0 0 0 0 0 0│ | ||
``` | ||
|
||
**NOTE:** `bit` makes it possible to quickly extract the characteristic polynomial for a bit-matrix with millions of elements. This problem chokes a naive implementation that does not consider the unique nature of arithmetic in GF(2). | ||
|
||
## Why Use `bit`? | ||
|
||
The standard library already has [`std::bitset`][], an efficient _bitset_ class that is familiar and well thought through, so our `bit::vector` class replicates and extends much of that interface. | ||
|
||
All `std::bitset` objects have a fixed size determined at compile time. The well-known _Boost_ library adds a dynamic version [`boost::dynamic_bitset`][], where the bitset size can be set and changed at runtime. | ||
|
||
However, as the two names suggest, those types are aimed at _bitsets_ instead of _bit-vectors_. So, for example, they print in _bit-order_ with the least significant element/bit on the right. More importantly, those classes don't have any particular methods aimed at linear algebra, and neither does the standard library's vector class `std::vector`. | ||
|
||
On the other hand, several well-known linear algebra libraries, such as [Eigen][], exist. Those packages efficiently manage all the standard _numeric_ types (floats, doubles, integers, etc.) but do not correctly handle GF(2). You can create matrices of integers where all the elements are 0 or 1, but there is no built-in knowledge in those libraries that arithmetic is mod 2. | ||
|
||
For example, you might use `Eigen` to create an integer matrix of all 0's and 1's and then use a built-in function from that library to extract the characteristic polynomial. Modding the coefficients of that polynomial with 2 gets the appropriate version for GF(2). Technically, this works, but you will have overflow problems for even relatively modest-sized matrices with just a few hundred rows and columns. Of course, you might use an underlying `BitInt` type that never overflows, but the calculations become dog slow for larger bit-matrices, which doesn't help much. | ||
|
||
This specialized `bit` library is better for linear algebra problems over GF(2). Consider it if, for example, your interest is in cryptography or random number generation. | ||
|
||
## Documentation | ||
|
||
You can read the project's documentation [here](https://nessan.github.io/bit/). | ||
The documentation site was generated using [Quarto](https://quarto.org). | ||
|
||
### Contact | ||
|
||
You can contact me by email [here](mailto:[email protected]). | ||
|
||
### Copyright and License | ||
|
||
Copyright (c) 2022-present Nessan Fitzmaurice. | ||
You can use this software under the [MIT license](https://opensource.org/license/mit). | ||
|
||
<!-- Reference Links --> | ||
|
||
{gf2}: https://en.wikipedia.org/wiki/Finite_field | ||
[Eigen]: https://eigen.tuxfamily.org/overview.php?title=Main_Page | ||
[`bit::vector`]: https://nessan.github.io/bit/pages/vector/ | ||
[`bit::matrix`]: https://nessan.github.io/bit/pages/matrix/ | ||
[`bit::polynomial`]: https://nessan.github.io/bit/pages/polynomial/ | ||
[`std::bitset`]: https://en.cppreference.com/w/cpp/utility/bitset | ||
[`boost::dynamic_bitset`]: https://www.boost.org/doc/libs/1_80_0/libs/dynamic_bitset/dynamic_bitset.html |
Oops, something went wrong.