Skip to content

Commit

Permalink
feat(random): Implement templated random number generation and remove…
Browse files Browse the repository at this point in the history
… move semantics
  • Loading branch information
merlinvn committed Sep 25, 2024
1 parent 6ebb3d8 commit 2c76ec3
Show file tree
Hide file tree
Showing 12 changed files with 367 additions and 286 deletions.
119 changes: 53 additions & 66 deletions .clang-tidy
Original file line number Diff line number Diff line change
@@ -1,103 +1,90 @@
Checks: >
*,
-altera-id-dependent-backward-branch,
-altera-struct-pack-align,
-altera-unroll-loops,
-fuchsia-*,
-llvmlibc-*,
-llvm-header-guard,
-llvm-include-order,
-cppcoreguidelines-owning-memory,
-cppcoreguidelines-non-private-member-variables-in-classes,
-cppcoreguidelines-avoid-non-const-global-variables,
-cppcoreguidelines-avoid-magic-numbers,
-google-readability-todo,
-modernize-use-trailing-return-type,
-modernize-pass-by-value,
-misc-non-private-member-variables-in-classes,
-performance-avoid-endl,
-*,
bugprone-*, # Enable bug-prone checks
cppcoreguidelines-*, # Enable C++ Core Guidelines checks
modernize-*, # Enable modernization checks
readability-*, # Enable readability checks
performance-* # Enable performance checks
# Checks: >
# *,
# -cppcoreguidelines-owning-memory
# -google-readability-todo,
# -altera-unroll-loops,
# -altera-id-dependent-backward-branch,
# -altera-struct-pack-align,
# -fuchsia-*,
# fuchsia-multiple-inheritance,
# -llvm-header-guard,
# -llvm-include-order,
# -llvmlibc-*,
# -modernize-use-trailing-return-type,
# -misc-non-private-member-variables-in-classes,
# -cppcoreguidelines-pro-type-vararg,
# -cppcoreguidelines-avoid-c-arrays,
# -hicpp-vararg,
# -hicpp-avoid-c-arrays,
# -modernize-avoid-c-arrays
# Optionally, disable specific checks that are not relevant
# For example, if you don't use certain C++ features or have specific project constraints
# -*.fuchsia-*
# -*.llvmlibc-*
# -*.llvm-*

WarningsAsErrors: ""
# WarningsAsErrors: "*,-readability-convert-member-functions-to-static"
WarningsAsErrors: "*"

CheckOptions:
- key: "readability-identifier-length.MinimumVariableNameLength"
# Identifier Length
- key: readability-identifier-length.MinimumVariableNameLength
value: "2"
- key: "readability-identifier-length.MinimumParameterNameLength"
- key: readability-identifier-length.MinimumParameterNameLength
value: "2"
- key: "readability-identifier-length.MinimumLoopCounterNameLength"
- key: readability-identifier-length.MinimumLoopCounterNameLength
value: "2"
- { key: readability-identifier-naming.NamespaceCase, value: lower_case }

# Naming Conventions
# Namespaces
- { key: readability-identifier-naming.NamespaceCase, value: snake_case }

# Macros
- {
key: readability-identifier-naming.MacroDefinitionCase,
value: UPPER_CASE,
}

# Types
- { key: readability-identifier-naming.ClassCase, value: CamelCase }
- { key: readability-identifier-naming.StructCase, value: CamelCase }
- { key: readability-identifier-naming.EnumCase, value: CamelCase }
- { key: readability-identifier-naming.EnumConstantCase, value: CamelCase }
- { key: readability-identifier-naming.EnumConstantCase, value: UPPER_CASE }
- { key: readability-identifier-naming.TypedefCase, value: CamelCase }
- { key: readability-identifier-naming.TypeAliasCase, value: CamelCase }
- { key: readability-identifier-naming.UnionCase, value: CamelCase }

- { key: readability-identifier-naming.FunctionCase, value: lower_case }
- { key: readability-identifier-naming.GlobalFunctionCase, value: lower_case }
# Functions
- { key: readability-identifier-naming.FunctionCase, value: snake_case }
- { key: readability-identifier-naming.GlobalFunctionCase, value: snake_case }

- { key: readability-identifier-naming.GlobalVariableCase, value: CamelCase }
# Variables
- { key: readability-identifier-naming.GlobalVariableCase, value: snake_case }
- { key: readability-identifier-naming.LocalVariableCase, value: snake_case }
- { key: readability-identifier-naming.ParameterCase, value: snake_case }

- { key: readability-identifier-naming.LocalVariableCase, value: aNy_CasE }
- { key: readability-identifier-naming.ParameterCase, value: aNy_CasE }
#static
- { key: readability-identifier-naming.ClassMemberCase, value: lower_case }
- { key: readability-identifier-naming.ClassMethodCase, value: lower_case }
# Class Members and Methods
- { key: readability-identifier-naming.ClassMemberCase, value: snake_case_ }
- { key: readability-identifier-naming.ClassMethodCase, value: snake_case }

- { key: readability-identifier-naming.MethodCase, value: lower_case }
- { key: readability-identifier-naming.PrivateMethodCase, value: lower_case }
# General Methods
- { key: readability-identifier-naming.MethodCase, value: snake_case }
- { key: readability-identifier-naming.PrivateMethodCase, value: snake_case }

- { key: readability-identifier-naming.MemberCase, value: lower_case }
- { key: readability-identifier-naming.PrivateMemberCase, value: lower_case }
# Members
- { key: readability-identifier-naming.MemberCase, value: snake_case_ }
- { key: readability-identifier-naming.PrivateMemberCase, value: snake_case_ }
- { key: readability-identifier-naming.PrivateMemberSuffix, value: "_" }

- { key: readability-identifier-naming.VariableCase, value: lower_case }

- { key: readability-identifier-naming.StaticVariableCase, value: lower_case }
# Variables
- { key: readability-identifier-naming.VariableCase, value: snake_case }
- { key: readability-identifier-naming.StaticVariableCase, value: snake_case }
- {
key: readability-identifier-naming.ConstexprVariableCase,
value: UPPER_CASE,
}
#constant
- { key: readability-identifier-naming.GlobalConstantCase, value: lower_case }

- { key: readability-identifier-naming.MemberConstantCase, value: lower_case }

- { key: readability-identifier-naming.StaticConstantCase, value: lower_case }
# Constants
- { key: readability-identifier-naming.GlobalConstantCase, value: UPPER_CASE }
- { key: readability-identifier-naming.MemberConstantCase, value: UPPER_CASE }
- { key: readability-identifier-naming.StaticConstantCase, value: UPPER_CASE }

# Template Parameters
- {
key: readability-identifier-naming.TemplateParameterCase,
value: CamelCase,
}
# some magic number

# Magic Numbers
- {
key: readability-magic-numbers.IgnoredIntegerValues,
value: "-1; 0; 1; 2; 3; 4; 5;10;100",
}
value: "-1;0;1;2;3;4;5;10;100",
}
64 changes: 64 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
name: C++ CI

on:
push:
branches: [ main ]
pull_request:
branches: [ main ]

jobs:
build-and-test:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2

- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y cmake g++ make
- name: Build
run: |
mkdir build && cd build
cmake ..
make
- name: Run tests
run: |
cd build
ctest --output-on-failure
lint:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2

- name: Install clang-format
run: sudo apt-get install -y clang-format

- name: Run clang-format
run: |
find src tests -name '*.cpp' -o -name '*.h' | xargs clang-format -i --style=file
git diff --exit-code
clang-tidy:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2

- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y cmake g++ make clang-tidy
- name: Generate compile_commands.json
run: |
mkdir build && cd build
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ..
- name: Run clang-tidy
run: |
find src tests -name '*.cpp' -o -name '*.h' | xargs clang-tidy -p build
9 changes: 7 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,11 @@ generate-ninja gn:
generate-test gt:
@$(MAKE) generate BUILD_TESTS=ON

format f:
fd "\.(h|cpp|hxx)$$" src -x clang-format -i
format:
find src tests -name '*.cpp' -o -name '*.h' | xargs clang-format -i --style=file

lint: build
find src tests -name '*.cpp' -o -name '*.h' | xargs clang-tidy -p build

docs:
@echo "Generating documentation..."
Expand All @@ -65,6 +68,7 @@ help h:
@echo " all : Default target, builds the project."
@echo " build (b) : Build the project with specified BUILD_TYPE (default: Release)."
@echo " format (f) : Format the source code using clang-format."
@echo " lint : Run clang-tidy on the source code."
@echo " test : Rebuild and run tests."
@echo " run [path] : Rebuild and run the executable. Provide path to override default."
@echo " clean : Remove the build directory."
Expand All @@ -75,3 +79,4 @@ help h:
@echo " generate-test (gt) : Generate the build system with tests."
@echo " docs : Generate Doxygen documentation into $(DOCS_OUTPUT_DIR)."
@echo " help : Show this help message."

7 changes: 4 additions & 3 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
# Random class

- [] Review all the unit tests
- [ ] Random unit tests

# Project wide

- add gcov
- add CI/Coverage
- [ ] add gcov
- [ ] add CI/Coverage
- [ ] choose a logging library
61 changes: 55 additions & 6 deletions src/Core/Random/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,41 @@ The `Random` class encapsulates random number generation functionalities using t
- **Shuffling Capabilities:** Shuffle elements in an array using the current random generator.
- **Resource Management:** Utilizes `std::unique_ptr` with a custom deleter to manage the GSL RNG resource.
- **Seed Control:** Allows setting and retrieving the RNG seed for reproducibility.
- **Move Semantics:** Supports move construction and move assignment for flexible resource management.
- **Templated Methods:** Provides templated methods for generating uniformly and normally distributed random numbers with flexible types.

## Dependencies

- [GNU Scientific Library (GSL)](https://www.gnu.org/software/gsl/)
- [fmt](https://fmt.dev/) (Optional, used for formatting logs)

## Installation

### Prerequisites

Ensure that the following dependencies are installed on your system:

- **GNU Scientific Library (GSL):**
```bash
sudo apt-get install libgsl-dev
```
- **fmt Library:** (Optional, only if you intend to use logging features)
```bash
sudo apt-get install libfmt-dev
```

### Building the Project

Assuming you're using CMake for your project, ensure that you link against GSL and fmt (if used):

```cmake
find_package(GSL REQUIRED)
find_package(fmt REQUIRED) # Optional
add_executable(your_executable main.cpp Random.cpp)
target_include_directories(your_executable PRIVATE ${GSL_INCLUDE_DIRS})
target_link_libraries(your_executable PRIVATE ${GSL_LIBRARIES} fmt::fmt) # fmt is optional
```

## Usage

### Initialization
Expand Down Expand Up @@ -51,7 +79,7 @@ int poisson_sample = rng.random_poisson(lambda);
uint64_t uniform_int = rng.random_uniform(100);

// Uniform integer in [50, 150)
uint64_t uniform_int_range = rng.random_uniform(50, 150);
uint64_t uniform_int_range = rng.random_uniform<uint64_t>(50, 150);

// Uniform double in [0.0, 1.0)
double uniform_double = rng.random_uniform();
Expand All @@ -73,7 +101,7 @@ double normal_sample = rng.random_normal(mean, std_dev);
double truncated_normal = rng.random_normal_truncated(mean, std_dev);

// Normal integer
int normal_int = rng.random_normal(5, 2);
int normal_int = rng.random_normal<int>(5, 2);

// Truncated normal integer within ±3 standard deviations
int truncated_normal_int = rng.random_normal_truncated(5, 2);
Expand Down Expand Up @@ -147,11 +175,13 @@ rng.set_seed(123456789);

### Move Semantics

> **Note:** The `Random` class **does not** support move construction or move assignment. Both copy and move operations are deleted to ensure unique ownership of the RNG resource.
```cpp
Random rng1;
Random rng2 = std::move(rng1); // Move constructor
Random rng3;
rng3 = std::move(rng2); // Move assignment
// The following operations are **not** allowed and will result in a compile-time error
// Random rng2 = std::move(rng1); // Move constructor - Deleted
// rng2 = std::move(rng1); // Move assignment - Deleted
```

## Example
Expand Down Expand Up @@ -205,3 +235,22 @@ Contributions are welcome! Please fork the repository and submit a pull request

- [GNU Scientific Library (GSL)](https://www.gnu.org/software/gsl/)
- [fmt Library](https://fmt.dev/)

---

### Changelog

#### v1.1.0

- **Removed Move Semantics:** The `Random` class no longer supports move construction or move assignment to ensure unique ownership of the RNG resource.
- **Added Templated Methods:** Introduced templated methods `random_uniform` and `random_normal` for greater flexibility in generating random numbers of different types.
- **Updated Documentation:** Revised the README to accurately reflect the class's capabilities and limitations.
- **Dependency Clarifications:** Specified that the `fmt` library is optional and primarily used for logging purposes.

#### v1.0.0

- Initial release with comprehensive random number generation functionalities using GSL.

---

_This README was generated and updated by ChatGPT based on the provided `Random.cpp` and `Random.h` implementations._
Loading

0 comments on commit 2c76ec3

Please sign in to comment.