Skip to content

Commit 290f2fd

Browse files
committed
Update project to version 2.0.0 with modular architecture and enhanced features
- Bump version from 1.0.0 to 2.0.0 in CMakeLists.txt - Add BUILD_REPL option and calc_repl executable target - Refactor CMake to include modular header directory structure - Rename example executables for consistency (advanced_usage → example_functions, error_handling_demo → example_errors, numeric_types_demo → example_types) - Rename benchmark executable from 'benchmark' to 'calc_benchmark' - Update test configuration
1 parent 1f2714d commit 290f2fd

File tree

20 files changed

+4149
-1009
lines changed

20 files changed

+4149
-1009
lines changed

.gitignore

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,68 @@
3131
*.out
3232
*.app
3333

34-
# CMake
34+
# CMake build artifacts
3535
build/
36+
cmake-build-*/
37+
CMakeCache.txt
38+
CMakeFiles/
39+
cmake_install.cmake
40+
CTestTestfile.cmake
41+
compile_commands.json
42+
Makefile
43+
*.sln
44+
*.vcxproj
45+
*.vcxproj.filters
46+
*.vcxproj.user
47+
Testing/
3648

49+
# xmake build artifacts
50+
.xmake/
51+
.build/
52+
53+
# IDE specific files
54+
# Visual Studio
55+
.vs/
56+
*.suo
57+
*.user
58+
*.userosscache
59+
*.sln.docstates
60+
*.VC.db
61+
*.VC.opendb
62+
63+
# Visual Studio Code
64+
.vscode/
65+
*.code-workspace
66+
67+
# CLion
68+
.idea/
69+
cmake-build-*/
70+
71+
# Clangd
72+
.clangd/
3773
.cache/
38-
site/
74+
75+
# Documentation
76+
site/
77+
docs/_build/
78+
docs/.buildinfo
79+
80+
# OS specific
81+
.DS_Store
82+
Thumbs.db
83+
*.swp
84+
*.swo
85+
*~
86+
87+
# Python (for documentation tools)
88+
__pycache__/
89+
*.py[cod]
90+
*$py.class
91+
.Python
92+
venv/
93+
env/
94+
ENV/
95+
96+
# Test and benchmark outputs
97+
*.log
98+
*.tlog

CMakeLists.txt

Lines changed: 36 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
11
cmake_minimum_required(VERSION 3.20)
2-
project(calculator VERSION 1.0.0 LANGUAGES CXX)
2+
project(calculator VERSION 2.0.0 LANGUAGES CXX)
33

44
option(BUILD_TESTS "Build tests" ON)
55
option(BUILD_EXAMPLES "Build examples" ON)
66
option(BUILD_BENCHMARKS "Build benchmarks" OFF)
7+
option(BUILD_REPL "Build REPL executable" ON)
78

89
if(NOT CMAKE_CXX_STANDARD)
910
set(CMAKE_CXX_STANDARD 17)
1011
set(CMAKE_CXX_STANDARD_REQUIRED ON)
1112
endif()
1213

1314
add_library(calculator INTERFACE)
14-
target_include_directories(calculator INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
15+
target_include_directories(calculator INTERFACE
16+
${CMAKE_CURRENT_SOURCE_DIR}
17+
${CMAKE_CURRENT_SOURCE_DIR}/include
18+
)
1519

1620
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
1721
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "8.0.0")
@@ -26,32 +30,32 @@ endif()
2630
install(FILES calculator.hpp DESTINATION calculator)
2731

2832
if (BUILD_EXAMPLES)
29-
# Main comprehensive example
33+
# Main example
3034
add_executable(example example/main.cpp)
3135
target_link_libraries(example PRIVATE calculator)
3236

33-
# Advanced usage patterns
34-
add_executable(advanced_usage example/advanced_usage.cpp)
35-
target_link_libraries(advanced_usage PRIVATE calculator)
37+
# Functions example
38+
add_executable(example_functions example/functions.cpp)
39+
target_link_libraries(example_functions PRIVATE calculator)
3640

37-
# Error handling demonstration
38-
add_executable(error_handling_demo example/error_handling_demo.cpp)
39-
target_link_libraries(error_handling_demo PRIVATE calculator)
41+
# Error handling example
42+
add_executable(example_errors example/errors.cpp)
43+
target_link_libraries(example_errors PRIVATE calculator)
4044

41-
# Numeric types demonstration
42-
add_executable(numeric_types_demo example/numeric_types_demo.cpp)
43-
target_link_libraries(numeric_types_demo PRIVATE calculator)
45+
# Numeric types example
46+
add_executable(example_types example/types.cpp)
47+
target_link_libraries(example_types PRIVATE calculator)
4448

4549
# Ensure math constants like M_PI and M_E are available on MSVC
4650
if (MSVC)
4751
target_compile_definitions(example PRIVATE _USE_MATH_DEFINES)
48-
target_compile_definitions(advanced_usage PRIVATE _USE_MATH_DEFINES)
49-
target_compile_definitions(error_handling_demo PRIVATE _USE_MATH_DEFINES)
50-
target_compile_definitions(numeric_types_demo PRIVATE _USE_MATH_DEFINES)
52+
target_compile_definitions(example_functions PRIVATE _USE_MATH_DEFINES)
53+
target_compile_definitions(example_errors PRIVATE _USE_MATH_DEFINES)
54+
target_compile_definitions(example_types PRIVATE _USE_MATH_DEFINES)
5155
endif()
5256

5357
# Set output directory for examples
54-
set_target_properties(example advanced_usage error_handling_demo numeric_types_demo
58+
set_target_properties(example example_functions example_errors example_types
5559
PROPERTIES
5660
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/example
5761
)
@@ -60,13 +64,25 @@ endif()
6064
if (BUILD_TESTS)
6165
enable_testing()
6266
find_package(GTest REQUIRED)
63-
add_executable(calc_test test/main.cpp)
64-
target_link_libraries(calc_test PRIVATE calculator GTest::gtest)
67+
add_executable(calc_test test/main.cpp test/test_parser.cpp)
68+
target_link_libraries(calc_test PRIVATE calculator GTest::gtest GTest::gtest_main)
69+
if (MSVC)
70+
target_compile_definitions(calc_test PRIVATE _USE_MATH_DEFINES)
71+
endif()
6572
add_test(NAME CalcTest COMMAND calc_test)
6673
endif()
6774

6875
if (BUILD_BENCHMARKS)
6976
find_package(benchmark REQUIRED)
70-
add_executable(benchmark benchmark/main.cpp)
71-
target_link_libraries(benchmark PRIVATE calculator benchmark::benchmark)
77+
add_executable(calc_benchmark benchmark/main.cpp)
78+
target_link_libraries(calc_benchmark PRIVATE calculator benchmark::benchmark)
79+
endif()
80+
81+
if (BUILD_REPL)
82+
add_executable(calc_repl example/repl_main.cpp)
83+
target_link_libraries(calc_repl PRIVATE calculator)
84+
if (MSVC)
85+
target_compile_definitions(calc_repl PRIVATE _USE_MATH_DEFINES)
86+
endif()
87+
set_target_properties(calc_repl PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
7288
endif()

README.md

Lines changed: 50 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,30 @@
1-
# Modern C++ Calculator
1+
# Modern C++ Calculator v2.1
22

33
[![CodeQL](https://github.com/ElementAstro/calculator/actions/workflows/codeql.yml/badge.svg)](https://github.com/ElementAstro/calculator/actions/workflows/codeql.yml)
44
[![MinGW](https://github.com/ElementAstro/calculator/actions/workflows/windows-mingw.yml/badge.svg)](https://github.com/ElementAstro/calculator/actions/workflows/windows-mingw.yml)
55
[![Bugs](https://sonarcloud.io/api/project_badges/measure?project=ElementAstro_calculator&metric=bugs)](https://sonarcloud.io/summary/new_code?id=ElementAstro_calculator)
66
[![Documentation](https://img.shields.io/badge/docs-mkdocs-blue.svg)](https://elementastro.github.io/calculator/)
77

8-
A modern, high-performance C++ header-only calculator library for evaluating mathematical expressions. Built with C++17/20 features, this library provides a robust and flexible expression parser that supports variables, functions, and comprehensive mathematical operations.
8+
A modern, high-performance C++ header-only calculator library for evaluating mathematical expressions. Built with C++17/20 features, this library provides a robust and flexible expression parser that supports variables, functions, comparison/logical operators, conditional expressions, complex numbers, symbolic differentiation, and a REPL interface.
99

1010
📖 **[Complete Documentation](https://elementastro.github.io/calculator/)** | 🚀 **[Quick Start Guide](https://elementastro.github.io/calculator/getting-started/quick-start/)** | 📋 **[API Reference](https://elementastro.github.io/calculator/api-reference/)**
1111

1212
## ✨ Key Features
1313

14-
- **🚀 Header-only**: Single file, easy integration
15-
- **🔢 Multiple numeric types**: Support for `int`, `float`, and `double`
14+
- **🚀 Header-only**: Modular design, easy integration
15+
- **🔢 Multiple numeric types**: Support for `int`, `float`, `double`, and `std::complex<double>`
1616
- **⚡ High performance**: Optimized expression parsing and evaluation
17-
- **🧮 Comprehensive operations**: Arithmetic, bitwise, and exponentiation
18-
- **📐 Mathematical functions**: Support for custom functions and variables
17+
- **🧮 Comprehensive operations**: Arithmetic, bitwise, comparison, logical, and power operations
18+
- **📐 Mathematical functions**: 60+ built-in functions (trigonometric, hyperbolic, combinatorics, etc.)
19+
- **🔀 Conditional expressions**: Ternary operator support (`condition ? true : false`)
20+
- **📝 User-defined functions**: Define custom functions like `f(x) = x^2 + 2*x + 1`
21+
- **🔣 Complex numbers**: Full complex number arithmetic support
22+
- **📊 Symbolic differentiation**: Compute derivatives symbolically
23+
- **💻 REPL interface**: Interactive calculator with history support
1924
- **🛡️ Robust error handling**: Detailed error messages with position information
2025
- **📏 Operator precedence**: Follows standard mathematical precedence rules
2126
- **🔧 Template-based**: Type-safe generic implementation
27+
- **🔬 Physics constants**: Built-in physical constants (c, G, h, Na, etc.)
2228

2329
## 🚀 Quick Start
2430

@@ -60,17 +66,48 @@ int main() {
6066
| Category | Operators | Example | Types |
6167
|----------|-----------|---------|-------|
6268
| **Arithmetic** | `+`, `-`, `*`, `/`, `%` | `3 + 4 * 2` | All |
63-
| **Bitwise** | `\|`, `^`, `&`, `<<`, `>>`, `~` | `5 & 3` | `int` only |
64-
| **Exponentiation** | `**`, `e`/`E` | `2 ** 3`, `1.5e2` | All |
65-
| **Unary** | `+`, `-`, `~` | `+5`, `-3`, `~7` | All/`int` |
69+
| **Floor Division** | `//` | `7 // 3``2` | All |
70+
| **Power** | `^`, `**` | `2^3`, `2**3` | All |
71+
| **Comparison** | `>`, `<`, `>=`, `<=`, `==`, `!=` | `5 > 3` | All |
72+
| **Logical** | `&&`, `\|\|`, `!` | `(5>3) && (2<4)` | All |
73+
| **Bitwise** | `&`, `\|`, `~`, `<<`, `>>` | `5 & 3` | `int` only |
74+
| **Conditional** | `? :` | `x > 0 ? x : -x` | All |
75+
| **Assignment** | `=` | `x = 10` | All |
6676
| **Grouping** | `(`, `)` | `(2 + 3) * 4` | All |
6777

78+
### Built-in Functions
79+
80+
| Category | Functions |
81+
|----------|-----------|
82+
| **Trigonometric** | `sin`, `cos`, `tan`, `cot`, `sec`, `csc` |
83+
| **Inverse Trig** | `asin`, `acos`, `atan`, `acot`, `asec`, `acsc` |
84+
| **Hyperbolic** | `sinh`, `cosh`, `tanh`, `coth`, `sech`, `csch` |
85+
| **Inverse Hyperbolic** | `asinh`, `acosh`, `atanh` |
86+
| **Logarithmic** | `log`, `log10`, `log2`, `ln`, `exp`, `exp2`, `expm1`, `log1p` |
87+
| **Power/Root** | `sqrt`, `cbrt`, `sqr`, `cube`, `pow(x,y)`, `hypot(x,y)` |
88+
| **Rounding** | `floor`, `ceil`, `round`, `trunc`, `frac`, `abs` |
89+
| **Factorial/Gamma** | `fact`, `factorial`, `gamma`, `lgamma` |
90+
| **Combinatorics** | `nCr(n,r)`, `nPr(n,r)`, `comb`, `perm` |
91+
| **Number Theory** | `gcd(a,b)`, `lcm(a,b)` |
92+
| **Error Functions** | `erf`, `erfc` |
93+
| **Utility** | `sign`, `heaviside`, `recip`, `inv`, `deg`, `rad` |
94+
| **Two-Argument** | `max`, `min`, `mod`, `atan2`, `logb`, `avg`, `clamp`, `wrap` |
95+
96+
### Built-in Constants
97+
98+
| Category | Constants |
99+
|----------|-----------|
100+
| **Mathematical** | `pi`, `e`, `phi` (golden ratio), `tau` (2π), `sqrt2`, `sqrt3`, `ln2`, `ln10` |
101+
| **Special** | `inf` (infinity), `nan` (not a number) |
102+
| **Physics (SI)** | `c` (speed of light), `G` (gravitational), `h` (Planck), `kb` (Boltzmann), `Na` (Avogadro), `qe` (elementary charge) |
103+
68104
### Advanced Features
69105

70-
- **Variables**: `parser.set("x", 5.0)``"x + 10"`
71-
- **Functions**: `parser.set("sqrt", [](double x) { return std::sqrt(x); })``"sqrt(16)"`
72-
- **Multiple Types**: `int`, `float`, `double` with type-specific behaviors
73-
- **Error Handling**: Detailed error messages with position information
106+
- **Variables**: `x = 10` then use `x + 5`
107+
- **User-defined functions**: `f(x) = x^2 + 2*x + 1` then call `f(3)`
108+
- **Complex numbers**: `(3 + 4*i) * (1 + 2*i)` with `std::complex<double>`
109+
- **Symbolic differentiation**: `parser.diff("x^2", "x")` returns `"2 * x"`
110+
- **REPL interface**: Interactive calculator with command history
74111

75112
**[📋 Complete operator reference and examples →](https://elementastro.github.io/calculator/reference/operators/)**
76113

benchmark/main.cpp

Lines changed: 84 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,109 @@
11
#include "calculator.hpp"
22
#include <benchmark/benchmark.h>
3+
#include <complex>
34

45
using namespace calculator;
56

6-
static void BM_CalculatorInt(benchmark::State &state) {
7-
ExpressionParser<int> parser;
7+
// Basic arithmetic benchmarks
8+
static void BM_BasicArithmetic(benchmark::State &state) {
9+
ExpressionParser<double> parser;
10+
for (auto _ : state) {
11+
benchmark::DoNotOptimize(parser.eval("1 + 2 * 3 - 4 / 2"));
12+
}
13+
}
14+
15+
static void BM_ComplexExpression(benchmark::State &state) {
16+
ExpressionParser<double> parser;
17+
for (auto _ : state) {
18+
benchmark::DoNotOptimize(parser.eval("(1.5 + 2.5) * (3.5 - 4.5) / (5.5 + 6.5) * (7.5 - 8.5) + 9.5"));
19+
}
20+
}
21+
22+
// Power operations
23+
static void BM_PowerOperations(benchmark::State &state) {
24+
ExpressionParser<double> parser;
25+
for (auto _ : state) {
26+
benchmark::DoNotOptimize(parser.eval("2^10 + 3^5 - 4^3"));
27+
}
28+
}
29+
30+
// Comparison and logical operators
31+
static void BM_ComparisonLogical(benchmark::State &state) {
32+
ExpressionParser<double> parser;
33+
for (auto _ : state) {
34+
benchmark::DoNotOptimize(parser.eval("(5 > 3) && (2 < 4) || (1 == 1)"));
35+
}
36+
}
37+
38+
// Ternary expression
39+
static void BM_TernaryExpression(benchmark::State &state) {
40+
ExpressionParser<double> parser;
41+
for (auto _ : state) {
42+
benchmark::DoNotOptimize(parser.eval("10 > 5 ? 100 + 50 : 200 - 50"));
43+
}
44+
}
45+
46+
// Built-in functions
47+
static void BM_BuiltinFunctions(benchmark::State &state) {
48+
ExpressionParser<double> parser;
49+
for (auto _ : state) {
50+
benchmark::DoNotOptimize(parser.eval("sqrt(16) + sin(0) + cos(0) + abs(-5)"));
51+
}
52+
}
53+
54+
// Variables
55+
static void BM_Variables(benchmark::State &state) {
56+
ExpressionParser<double> parser;
57+
parser.set("x", 10.0);
58+
parser.set("y", 20.0);
859
for (auto _ : state) {
9-
parser.eval("1 + 2 * 3 - 4 / 2");
60+
benchmark::DoNotOptimize(parser.eval("x + y * 2 - x / 2"));
1061
}
1162
}
1263

13-
static void BM_CalculatorDouble(benchmark::State &state) {
64+
// User-defined functions
65+
static void BM_UserDefinedFunction(benchmark::State &state) {
1466
ExpressionParser<double> parser;
67+
parser.eval("f(x) = x^2 + 2*x + 1");
1568
for (auto _ : state) {
16-
parser.eval("1.5 + 2.5 * 3.5 - 4.5 / 2.5");
69+
benchmark::DoNotOptimize(parser.eval("f(10)"));
1770
}
1871
}
1972

20-
static void BM_CalculatorComplexInt(benchmark::State &state) {
21-
ExpressionParser<int> parser;
73+
// Complex numbers
74+
static void BM_ComplexNumbers(benchmark::State &state) {
75+
ExpressionParser<std::complex<double>> parser;
76+
for (auto _ : state) {
77+
benchmark::DoNotOptimize(parser.eval("(3 + 4*i) * (1 + 2*i)"));
78+
}
79+
}
80+
81+
// Nested expressions
82+
static void BM_NestedExpressions(benchmark::State &state) {
83+
ExpressionParser<double> parser;
2284
for (auto _ : state) {
23-
parser.eval("(1 + 2) * (3 - 4) / (5 + 6) * (7 - 8) + 9");
85+
benchmark::DoNotOptimize(parser.eval("((((1 + 2) * 3) + 4) * 5) + 6"));
2486
}
2587
}
2688

27-
static void BM_CalculatorComplexDouble(benchmark::State &state) {
89+
// Symbolic differentiation
90+
static void BM_Differentiation(benchmark::State &state) {
2891
ExpressionParser<double> parser;
2992
for (auto _ : state) {
30-
parser.eval("(1.5 + 2.5) * (3.5 - 4.5) / (5.5 + 6.5) * (7.5 - 8.5) + 9.5");
93+
benchmark::DoNotOptimize(parser.diff("x^3 + 2*x^2 + x + 1", "x"));
3194
}
3295
}
3396

34-
BENCHMARK(BM_CalculatorInt);
35-
BENCHMARK(BM_CalculatorDouble);
36-
BENCHMARK(BM_CalculatorComplexInt);
37-
BENCHMARK(BM_CalculatorComplexDouble);
97+
BENCHMARK(BM_BasicArithmetic);
98+
BENCHMARK(BM_ComplexExpression);
99+
BENCHMARK(BM_PowerOperations);
100+
BENCHMARK(BM_ComparisonLogical);
101+
BENCHMARK(BM_TernaryExpression);
102+
BENCHMARK(BM_BuiltinFunctions);
103+
BENCHMARK(BM_Variables);
104+
BENCHMARK(BM_UserDefinedFunction);
105+
BENCHMARK(BM_ComplexNumbers);
106+
BENCHMARK(BM_NestedExpressions);
107+
BENCHMARK(BM_Differentiation);
38108

39109
BENCHMARK_MAIN();

0 commit comments

Comments
 (0)