jrpycpp 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- jrpycpp/__init__.py +3 -0
- jrpycpp/__version__.py +1 -0
- jrpycpp/examples/cpp_scripts/chapter2/demo/01-class.cpp +24 -0
- jrpycpp/examples/cpp_scripts/chapter2/demo/02-const.cpp +25 -0
- jrpycpp/examples/cpp_scripts/chapter2/exercise/stats.cpp +26 -0
- jrpycpp/examples/cpp_scripts/chapter2/solution/stats.cpp +44 -0
- jrpycpp/examples/cpp_scripts/chapter3/demo/01-free-function/bindings.cpp +11 -0
- jrpycpp/examples/cpp_scripts/chapter3/demo/01-free-function/pi.cpp +10 -0
- jrpycpp/examples/cpp_scripts/chapter3/demo/01-free-function/pi.h +3 -0
- jrpycpp/examples/cpp_scripts/chapter3/demo/01-free-function/pyproject.toml +11 -0
- jrpycpp/examples/cpp_scripts/chapter3/demo/01-free-function/setup.py +12 -0
- jrpycpp/examples/cpp_scripts/chapter3/demo/01-free-function/test_pi.py +11 -0
- jrpycpp/examples/cpp_scripts/chapter3/demo/02-class/bindings.cpp +17 -0
- jrpycpp/examples/cpp_scripts/chapter3/demo/02-class/pyproject.toml +11 -0
- jrpycpp/examples/cpp_scripts/chapter3/demo/02-class/setup.py +12 -0
- jrpycpp/examples/cpp_scripts/chapter3/demo/02-class/stats.cpp +26 -0
- jrpycpp/examples/cpp_scripts/chapter3/demo/02-class/stats.h +15 -0
- jrpycpp/examples/cpp_scripts/chapter3/demo/02-class/test_livstats.py +18 -0
- jrpycpp/examples/cpp_scripts/chapter3/exercise/bindings.cpp +12 -0
- jrpycpp/examples/cpp_scripts/chapter3/exercise/pyproject.toml +11 -0
- jrpycpp/examples/cpp_scripts/chapter3/exercise/setup.py +12 -0
- jrpycpp/examples/cpp_scripts/chapter3/exercise/stats.cpp +26 -0
- jrpycpp/examples/cpp_scripts/chapter3/exercise/stats.h +15 -0
- jrpycpp/examples/cpp_scripts/chapter3/solution/bindings.cpp +22 -0
- jrpycpp/examples/cpp_scripts/chapter3/solution/pyproject.toml +11 -0
- jrpycpp/examples/cpp_scripts/chapter3/solution/setup.py +12 -0
- jrpycpp/examples/cpp_scripts/chapter3/solution/stats.cpp +26 -0
- jrpycpp/examples/cpp_scripts/chapter3/solution/stats.h +15 -0
- jrpycpp/examples/cpp_scripts/chapter3/solution/test_livstats.py +18 -0
- jrpycpp/examples/cpp_scripts/chapter4/demo/arrays.cpp +13 -0
- jrpycpp/examples/cpp_scripts/chapter4/demo/arrays.h +7 -0
- jrpycpp/examples/cpp_scripts/chapter4/demo/bindings.cpp +73 -0
- jrpycpp/examples/cpp_scripts/chapter4/demo/pyproject.toml +11 -0
- jrpycpp/examples/cpp_scripts/chapter4/demo/setup.py +12 -0
- jrpycpp/examples/cpp_scripts/chapter4/demo/test_arrays.py +38 -0
- jrpycpp/examples/cpp_scripts/chapter4/exercise/arrays.cpp +13 -0
- jrpycpp/examples/cpp_scripts/chapter4/exercise/arrays.h +7 -0
- jrpycpp/examples/cpp_scripts/chapter4/exercise/bindings.cpp +36 -0
- jrpycpp/examples/cpp_scripts/chapter4/exercise/pyproject.toml +11 -0
- jrpycpp/examples/cpp_scripts/chapter4/exercise/setup.py +12 -0
- jrpycpp/examples/cpp_scripts/chapter4/solution/arrays.cpp +13 -0
- jrpycpp/examples/cpp_scripts/chapter4/solution/arrays.h +7 -0
- jrpycpp/examples/cpp_scripts/chapter4/solution/bindings.cpp +49 -0
- jrpycpp/examples/cpp_scripts/chapter4/solution/pyproject.toml +11 -0
- jrpycpp/examples/cpp_scripts/chapter4/solution/setup.py +12 -0
- jrpycpp/examples/cpp_scripts/chapter4/solution/test_arrays.py +19 -0
- jrpycpp/examples/cpp_scripts/chapter5/demo/01-cmake/CMakeLists.txt +22 -0
- jrpycpp/examples/cpp_scripts/chapter5/demo/01-cmake/include/stats.h +15 -0
- jrpycpp/examples/cpp_scripts/chapter5/demo/01-cmake/src/main.cpp +9 -0
- jrpycpp/examples/cpp_scripts/chapter5/demo/01-cmake/src/stats.cpp +26 -0
- jrpycpp/examples/cpp_scripts/chapter5/demo/01-cmake/tests/test_stats.cpp +20 -0
- jrpycpp/examples/cpp_scripts/chapter5/demo/02-python/CMakeLists.txt +28 -0
- jrpycpp/examples/cpp_scripts/chapter5/demo/02-python/include/stats.h +15 -0
- jrpycpp/examples/cpp_scripts/chapter5/demo/02-python/pyproject.toml +11 -0
- jrpycpp/examples/cpp_scripts/chapter5/demo/02-python/python/bindings.cpp +17 -0
- jrpycpp/examples/cpp_scripts/chapter5/demo/02-python/src/stats.cpp +26 -0
- jrpycpp/examples/cpp_scripts/chapter5/demo/02-python/tests/test_livstats.py +10 -0
- jrpycpp/examples/cpp_scripts/chapter5/demo/02-python/tests/test_stats.cpp +20 -0
- jrpycpp/examples/cpp_scripts/chapter5/exercise/CMakeLists.txt +17 -0
- jrpycpp/examples/cpp_scripts/chapter5/exercise/include/stats.h +15 -0
- jrpycpp/examples/cpp_scripts/chapter5/exercise/src/main.cpp +9 -0
- jrpycpp/examples/cpp_scripts/chapter5/exercise/src/stats.cpp +26 -0
- jrpycpp/examples/cpp_scripts/chapter5/exercise/tests/test_stats.cpp +16 -0
- jrpycpp/examples/cpp_scripts/chapter5/solution/CMakeLists.txt +22 -0
- jrpycpp/examples/cpp_scripts/chapter5/solution/include/stats.h +15 -0
- jrpycpp/examples/cpp_scripts/chapter5/solution/src/main.cpp +9 -0
- jrpycpp/examples/cpp_scripts/chapter5/solution/src/stats.cpp +26 -0
- jrpycpp/examples/cpp_scripts/chapter5/solution/tests/test_stats.cpp +20 -0
- jrpycpp/examples/cpp_scripts/chapter6/demo/01-map.cpp +19 -0
- jrpycpp/examples/cpp_scripts/chapter6/demo/02-lambda.cpp +22 -0
- jrpycpp/examples/cpp_scripts/chapter6/demo/03-move.cpp +14 -0
- jrpycpp/examples/cpp_scripts/chapter6/demo/04-unique.cpp +19 -0
- jrpycpp/examples/cpp_scripts/chapter6/exercise/copies.cpp +34 -0
- jrpycpp/examples/cpp_scripts/chapter6/exercise/integrate.cpp +20 -0
- jrpycpp/examples/cpp_scripts/chapter6/exercise/words.cpp +21 -0
- jrpycpp/examples/cpp_scripts/chapter6/solution/copies.cpp +37 -0
- jrpycpp/examples/cpp_scripts/chapter6/solution/integrate.cpp +25 -0
- jrpycpp/examples/cpp_scripts/chapter6/solution/words.cpp +21 -0
- jrpycpp/examples/templates/cpp-project/CMakeLists.txt +22 -0
- jrpycpp/examples/templates/cpp-project/README.md +68 -0
- jrpycpp/examples/templates/cpp-project/include/stats.h +15 -0
- jrpycpp/examples/templates/cpp-project/src/main.cpp +9 -0
- jrpycpp/examples/templates/cpp-project/src/stats.cpp +26 -0
- jrpycpp/examples/templates/cpp-project/tests/test_stats.cpp +20 -0
- jrpycpp/examples/templates/python-cpp-project/CMakeLists.txt +28 -0
- jrpycpp/examples/templates/python-cpp-project/README.md +72 -0
- jrpycpp/examples/templates/python-cpp-project/include/stats.h +15 -0
- jrpycpp/examples/templates/python-cpp-project/pyproject.toml +11 -0
- jrpycpp/examples/templates/python-cpp-project/python/bindings.cpp +17 -0
- jrpycpp/examples/templates/python-cpp-project/src/stats.cpp +26 -0
- jrpycpp/examples/templates/python-cpp-project/tests/test_livstats.py +10 -0
- jrpycpp/examples/templates/python-cpp-project/tests/test_stats.cpp +20 -0
- jrpycpp/examples.py +43 -0
- jrpycpp-0.1.0.dist-info/METADATA +16 -0
- jrpycpp-0.1.0.dist-info/RECORD +96 -0
- jrpycpp-0.1.0.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#include "arrays.h"
|
|
2
|
+
|
|
3
|
+
double total(const double* data, std::size_t n) {
|
|
4
|
+
double sum = 0.0;
|
|
5
|
+
for (std::size_t i = 0; i < n; ++i) {
|
|
6
|
+
sum += data[i];
|
|
7
|
+
}
|
|
8
|
+
return sum;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
double total_vector(const std::vector<double>& v) {
|
|
12
|
+
return total(v.data(), v.size());
|
|
13
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#include <pybind11/pybind11.h>
|
|
2
|
+
#include <pybind11/numpy.h>
|
|
3
|
+
#include <pybind11/stl.h>
|
|
4
|
+
|
|
5
|
+
#include "arrays.h"
|
|
6
|
+
|
|
7
|
+
namespace py = pybind11;
|
|
8
|
+
|
|
9
|
+
double total_array(py::array_t<double> values) {
|
|
10
|
+
auto v = values.unchecked<1>();
|
|
11
|
+
double sum = 0.0;
|
|
12
|
+
for (py::ssize_t i = 0; i < v.shape(0); ++i) {
|
|
13
|
+
sum += v(i);
|
|
14
|
+
}
|
|
15
|
+
return sum;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
void scale_inplace(py::array_t<double> values, double factor) {
|
|
19
|
+
auto v = values.mutable_unchecked<1>();
|
|
20
|
+
for (py::ssize_t i = 0; i < v.shape(0); ++i) {
|
|
21
|
+
v(i) *= factor;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
PYBIND11_MODULE(livarrays, m) {
|
|
26
|
+
m.doc() = "NumPy arrays crossing into C++";
|
|
27
|
+
|
|
28
|
+
m.def("total_array", &total_array, py::arg("values"),
|
|
29
|
+
"Sum an array of doubles without copying it");
|
|
30
|
+
|
|
31
|
+
m.def("total_list", &total_vector, py::arg("values"),
|
|
32
|
+
"Sum a sequence, copying it into a vector first");
|
|
33
|
+
|
|
34
|
+
m.def("scale_inplace", &scale_inplace, py::arg("values"), py::arg("factor"),
|
|
35
|
+
"Multiply an array of doubles in place");
|
|
36
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from setuptools import setup
|
|
2
|
+
from pybind11.setup_helpers import Pybind11Extension, build_ext
|
|
3
|
+
|
|
4
|
+
ext_modules = [
|
|
5
|
+
Pybind11Extension(
|
|
6
|
+
"livarrays",
|
|
7
|
+
["bindings.cpp", "arrays.cpp"],
|
|
8
|
+
cxx_std=17,
|
|
9
|
+
),
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
setup(ext_modules=ext_modules, cmdclass={"build_ext": build_ext})
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#include "arrays.h"
|
|
2
|
+
|
|
3
|
+
double total(const double* data, std::size_t n) {
|
|
4
|
+
double sum = 0.0;
|
|
5
|
+
for (std::size_t i = 0; i < n; ++i) {
|
|
6
|
+
sum += data[i];
|
|
7
|
+
}
|
|
8
|
+
return sum;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
double total_vector(const std::vector<double>& v) {
|
|
12
|
+
return total(v.data(), v.size());
|
|
13
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
#include <pybind11/pybind11.h>
|
|
2
|
+
#include <pybind11/numpy.h>
|
|
3
|
+
#include <pybind11/stl.h>
|
|
4
|
+
|
|
5
|
+
#include "arrays.h"
|
|
6
|
+
|
|
7
|
+
namespace py = pybind11;
|
|
8
|
+
|
|
9
|
+
double total_array(py::array_t<double> values) {
|
|
10
|
+
auto v = values.unchecked<1>();
|
|
11
|
+
double sum = 0.0;
|
|
12
|
+
for (py::ssize_t i = 0; i < v.shape(0); ++i) {
|
|
13
|
+
sum += v(i);
|
|
14
|
+
}
|
|
15
|
+
return sum;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
void scale_inplace(py::array_t<double> values, double factor) {
|
|
19
|
+
auto v = values.mutable_unchecked<1>();
|
|
20
|
+
for (py::ssize_t i = 0; i < v.shape(0); ++i) {
|
|
21
|
+
v(i) *= factor;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
py::array_t<double> squares(py::ssize_t n) {
|
|
26
|
+
py::array_t<double> out(n);
|
|
27
|
+
auto o = out.mutable_unchecked<1>();
|
|
28
|
+
for (py::ssize_t i = 0; i < n; ++i) {
|
|
29
|
+
o(i) = static_cast<double>(i) * static_cast<double>(i);
|
|
30
|
+
}
|
|
31
|
+
return out;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
PYBIND11_MODULE(livarrays, m) {
|
|
35
|
+
m.doc() = "NumPy arrays crossing into C++";
|
|
36
|
+
|
|
37
|
+
m.def("total_array", &total_array, py::arg("values"),
|
|
38
|
+
"Sum an array of doubles without copying it");
|
|
39
|
+
|
|
40
|
+
m.def("total_list", &total_vector, py::arg("values"),
|
|
41
|
+
"Sum a sequence, copying it into a vector first");
|
|
42
|
+
|
|
43
|
+
m.def("scale_inplace", &scale_inplace,
|
|
44
|
+
py::arg("values").noconvert(), py::arg("factor"),
|
|
45
|
+
"Multiply an array of doubles in place");
|
|
46
|
+
|
|
47
|
+
m.def("squares", &squares, py::arg("n"),
|
|
48
|
+
"Return the first n squares as a new array");
|
|
49
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from setuptools import setup
|
|
2
|
+
from pybind11.setup_helpers import Pybind11Extension, build_ext
|
|
3
|
+
|
|
4
|
+
ext_modules = [
|
|
5
|
+
Pybind11Extension(
|
|
6
|
+
"livarrays",
|
|
7
|
+
["bindings.cpp", "arrays.cpp"],
|
|
8
|
+
cxx_std=17,
|
|
9
|
+
),
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
setup(ext_modules=ext_modules, cmdclass={"build_ext": build_ext})
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import pytest
|
|
3
|
+
|
|
4
|
+
import livarrays
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def test_squares():
|
|
8
|
+
assert livarrays.squares(4) == pytest.approx(np.array([0.0, 1.0, 4.0, 9.0]))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def test_noconvert_refuses_int32():
|
|
12
|
+
with pytest.raises(TypeError):
|
|
13
|
+
livarrays.scale_inplace(np.arange(5, dtype=np.int32), 2.0)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def test_float64_is_changed_in_place():
|
|
17
|
+
a = np.arange(5.0)
|
|
18
|
+
livarrays.scale_inplace(a, 2.0)
|
|
19
|
+
assert a == pytest.approx(np.array([0.0, 2.0, 4.0, 6.0, 8.0]))
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
cmake_minimum_required(VERSION 3.16)
|
|
2
|
+
project(stats LANGUAGES CXX VERSION 0.1.0)
|
|
3
|
+
|
|
4
|
+
set(CMAKE_CXX_STANDARD 17)
|
|
5
|
+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
6
|
+
set(CMAKE_CXX_EXTENSIONS OFF)
|
|
7
|
+
|
|
8
|
+
add_library(stats src/stats.cpp)
|
|
9
|
+
target_include_directories(stats PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
|
10
|
+
target_compile_options(stats PRIVATE -Wall -Wextra)
|
|
11
|
+
|
|
12
|
+
add_executable(report src/main.cpp)
|
|
13
|
+
target_link_libraries(report PRIVATE stats)
|
|
14
|
+
|
|
15
|
+
enable_testing()
|
|
16
|
+
|
|
17
|
+
find_package(Catch2 3 REQUIRED)
|
|
18
|
+
add_executable(test_stats tests/test_stats.cpp)
|
|
19
|
+
target_link_libraries(test_stats PRIVATE stats Catch2::Catch2WithMain)
|
|
20
|
+
|
|
21
|
+
include(Catch)
|
|
22
|
+
catch_discover_tests(test_stats)
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#include "stats.h"
|
|
2
|
+
|
|
3
|
+
#include <cmath>
|
|
4
|
+
|
|
5
|
+
Stats::Stats(const std::vector<double>& values) : values_(values) {}
|
|
6
|
+
|
|
7
|
+
double Stats::mean() const {
|
|
8
|
+
double total = 0.0;
|
|
9
|
+
for (double v : values_) {
|
|
10
|
+
total += v;
|
|
11
|
+
}
|
|
12
|
+
return total / values_.size();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
double Stats::stddev() const {
|
|
16
|
+
double m = mean();
|
|
17
|
+
double total = 0.0;
|
|
18
|
+
for (double v : values_) {
|
|
19
|
+
total += (v - m) * (v - m);
|
|
20
|
+
}
|
|
21
|
+
return std::sqrt(total / values_.size());
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
int Stats::count() const {
|
|
25
|
+
return static_cast<int>(values_.size());
|
|
26
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#include <catch2/catch_test_macros.hpp>
|
|
2
|
+
#include <catch2/catch_approx.hpp>
|
|
3
|
+
|
|
4
|
+
#include "stats.h"
|
|
5
|
+
|
|
6
|
+
using Catch::Approx;
|
|
7
|
+
|
|
8
|
+
TEST_CASE("mean of yesterday's numbers", "[stats]") {
|
|
9
|
+
Stats s({2.0, 4.0, 4.0, 4.0, 5.0, 5.0, 7.0, 9.0});
|
|
10
|
+
REQUIRE(s.mean() == Approx(5.0));
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
TEST_CASE("standard deviation of yesterday's numbers", "[stats]") {
|
|
14
|
+
Stats s({2.0, 4.0, 4.0, 4.0, 5.0, 5.0, 7.0, 9.0});
|
|
15
|
+
REQUIRE(s.stddev() == Approx(2.0));
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
TEST_CASE("count is the number of values", "[stats]") {
|
|
19
|
+
REQUIRE(Stats({1.0, 2.0, 3.0}).count() == 3);
|
|
20
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
cmake_minimum_required(VERSION 3.16)
|
|
2
|
+
project(livstats LANGUAGES CXX VERSION 0.1.0)
|
|
3
|
+
|
|
4
|
+
set(CMAKE_CXX_STANDARD 17)
|
|
5
|
+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
6
|
+
set(CMAKE_CXX_EXTENSIONS OFF)
|
|
7
|
+
|
|
8
|
+
add_library(stats src/stats.cpp)
|
|
9
|
+
target_include_directories(stats PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
|
10
|
+
target_compile_options(stats PRIVATE -Wall -Wextra)
|
|
11
|
+
set_target_properties(stats PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
|
12
|
+
|
|
13
|
+
set(PYBIND11_FINDPYTHON ON)
|
|
14
|
+
find_package(pybind11 CONFIG REQUIRED)
|
|
15
|
+
|
|
16
|
+
pybind11_add_module(livstats python/bindings.cpp)
|
|
17
|
+
target_link_libraries(livstats PRIVATE stats)
|
|
18
|
+
|
|
19
|
+
install(TARGETS livstats DESTINATION .)
|
|
20
|
+
|
|
21
|
+
if(NOT SKBUILD)
|
|
22
|
+
enable_testing()
|
|
23
|
+
find_package(Catch2 3 REQUIRED)
|
|
24
|
+
add_executable(test_stats tests/test_stats.cpp)
|
|
25
|
+
target_link_libraries(test_stats PRIVATE stats Catch2::Catch2WithMain)
|
|
26
|
+
include(Catch)
|
|
27
|
+
catch_discover_tests(test_stats)
|
|
28
|
+
endif()
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["scikit-build-core>=0.11", "pybind11>=3.0"]
|
|
3
|
+
build-backend = "scikit_build_core.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "livstats"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
requires-python = ">=3.9"
|
|
9
|
+
|
|
10
|
+
[tool.scikit-build]
|
|
11
|
+
minimum-version = "build-system.requires"
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#include <pybind11/pybind11.h>
|
|
2
|
+
#include <pybind11/stl.h>
|
|
3
|
+
|
|
4
|
+
#include "stats.h"
|
|
5
|
+
|
|
6
|
+
namespace py = pybind11;
|
|
7
|
+
|
|
8
|
+
PYBIND11_MODULE(livstats, m) {
|
|
9
|
+
m.doc() = "The stats library, built by CMake";
|
|
10
|
+
|
|
11
|
+
py::class_<Stats>(m, "Stats")
|
|
12
|
+
.def(py::init<const std::vector<double>&>(), py::arg("values"),
|
|
13
|
+
"Build from a sequence of numbers")
|
|
14
|
+
.def("mean", &Stats::mean, "Arithmetic mean")
|
|
15
|
+
.def("stddev", &Stats::stddev, "Standard deviation, dividing by n")
|
|
16
|
+
.def("count", &Stats::count, "How many values");
|
|
17
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#include "stats.h"
|
|
2
|
+
|
|
3
|
+
#include <cmath>
|
|
4
|
+
|
|
5
|
+
Stats::Stats(const std::vector<double>& values) : values_(values) {}
|
|
6
|
+
|
|
7
|
+
double Stats::mean() const {
|
|
8
|
+
double total = 0.0;
|
|
9
|
+
for (double v : values_) {
|
|
10
|
+
total += v;
|
|
11
|
+
}
|
|
12
|
+
return total / values_.size();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
double Stats::stddev() const {
|
|
16
|
+
double m = mean();
|
|
17
|
+
double total = 0.0;
|
|
18
|
+
for (double v : values_) {
|
|
19
|
+
total += (v - m) * (v - m);
|
|
20
|
+
}
|
|
21
|
+
return std::sqrt(total / values_.size());
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
int Stats::count() const {
|
|
25
|
+
return static_cast<int>(values_.size());
|
|
26
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#include <catch2/catch_test_macros.hpp>
|
|
2
|
+
#include <catch2/catch_approx.hpp>
|
|
3
|
+
|
|
4
|
+
#include "stats.h"
|
|
5
|
+
|
|
6
|
+
using Catch::Approx;
|
|
7
|
+
|
|
8
|
+
TEST_CASE("mean of yesterday's numbers", "[stats]") {
|
|
9
|
+
Stats s({2.0, 4.0, 4.0, 4.0, 5.0, 5.0, 7.0, 9.0});
|
|
10
|
+
REQUIRE(s.mean() == Approx(5.0));
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
TEST_CASE("standard deviation of yesterday's numbers", "[stats]") {
|
|
14
|
+
Stats s({2.0, 4.0, 4.0, 4.0, 5.0, 5.0, 7.0, 9.0});
|
|
15
|
+
REQUIRE(s.stddev() == Approx(2.0));
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
TEST_CASE("count is the number of values", "[stats]") {
|
|
19
|
+
REQUIRE(Stats({1.0, 2.0, 3.0}).count() == 3);
|
|
20
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
cmake_minimum_required(VERSION 3.16)
|
|
2
|
+
project(stats LANGUAGES CXX VERSION 0.1.0)
|
|
3
|
+
|
|
4
|
+
set(CMAKE_CXX_STANDARD 17)
|
|
5
|
+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
6
|
+
set(CMAKE_CXX_EXTENSIONS OFF)
|
|
7
|
+
|
|
8
|
+
add_library(stats src/stats.cpp)
|
|
9
|
+
target_include_directories(stats PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
|
10
|
+
target_compile_options(stats PRIVATE -Wall -Wextra)
|
|
11
|
+
|
|
12
|
+
add_executable(report src/main.cpp)
|
|
13
|
+
target_link_libraries(report PRIVATE stats)
|
|
14
|
+
|
|
15
|
+
# Task 2 goes here: enable testing, find Catch2, build tests/test_stats.cpp
|
|
16
|
+
# into a target that links stats and Catch2::Catch2WithMain, and register it
|
|
17
|
+
# with catch_discover_tests.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#include "stats.h"
|
|
2
|
+
|
|
3
|
+
#include <cmath>
|
|
4
|
+
|
|
5
|
+
Stats::Stats(const std::vector<double>& values) : values_(values) {}
|
|
6
|
+
|
|
7
|
+
double Stats::mean() const {
|
|
8
|
+
double total = 0.0;
|
|
9
|
+
for (double v : values_) {
|
|
10
|
+
total += v;
|
|
11
|
+
}
|
|
12
|
+
return total / values_.size();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
double Stats::stddev() const {
|
|
16
|
+
double m = mean();
|
|
17
|
+
double total = 0.0;
|
|
18
|
+
for (double v : values_) {
|
|
19
|
+
total += (v - m) * (v - m);
|
|
20
|
+
}
|
|
21
|
+
return std::sqrt(total / values_.size());
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
int Stats::count() const {
|
|
25
|
+
return static_cast<int>(values_.size());
|
|
26
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#include <catch2/catch_test_macros.hpp>
|
|
2
|
+
#include <catch2/catch_approx.hpp>
|
|
3
|
+
|
|
4
|
+
#include "stats.h"
|
|
5
|
+
|
|
6
|
+
using Catch::Approx;
|
|
7
|
+
|
|
8
|
+
TEST_CASE("mean of yesterday's numbers", "[stats]") {
|
|
9
|
+
Stats s({2.0, 4.0, 4.0, 4.0, 5.0, 5.0, 7.0, 9.0});
|
|
10
|
+
REQUIRE(s.mean() == Approx(5.0));
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
TEST_CASE("standard deviation of yesterday's numbers", "[stats]") {
|
|
14
|
+
Stats s({2.0, 4.0, 4.0, 4.0, 5.0, 5.0, 7.0, 9.0});
|
|
15
|
+
REQUIRE(s.stddev() == Approx(1.5));
|
|
16
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
cmake_minimum_required(VERSION 3.16)
|
|
2
|
+
project(stats LANGUAGES CXX VERSION 0.1.0)
|
|
3
|
+
|
|
4
|
+
set(CMAKE_CXX_STANDARD 17)
|
|
5
|
+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
6
|
+
set(CMAKE_CXX_EXTENSIONS OFF)
|
|
7
|
+
|
|
8
|
+
add_library(stats src/stats.cpp)
|
|
9
|
+
target_include_directories(stats PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
|
10
|
+
target_compile_options(stats PRIVATE -Wall -Wextra)
|
|
11
|
+
|
|
12
|
+
add_executable(report src/main.cpp)
|
|
13
|
+
target_link_libraries(report PRIVATE stats)
|
|
14
|
+
|
|
15
|
+
enable_testing()
|
|
16
|
+
|
|
17
|
+
find_package(Catch2 3 REQUIRED)
|
|
18
|
+
add_executable(test_stats tests/test_stats.cpp)
|
|
19
|
+
target_link_libraries(test_stats PRIVATE stats Catch2::Catch2WithMain)
|
|
20
|
+
|
|
21
|
+
include(Catch)
|
|
22
|
+
catch_discover_tests(test_stats)
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#include "stats.h"
|
|
2
|
+
|
|
3
|
+
#include <cmath>
|
|
4
|
+
|
|
5
|
+
Stats::Stats(const std::vector<double>& values) : values_(values) {}
|
|
6
|
+
|
|
7
|
+
double Stats::mean() const {
|
|
8
|
+
double total = 0.0;
|
|
9
|
+
for (double v : values_) {
|
|
10
|
+
total += v;
|
|
11
|
+
}
|
|
12
|
+
return total / values_.size();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
double Stats::stddev() const {
|
|
16
|
+
double m = mean();
|
|
17
|
+
double total = 0.0;
|
|
18
|
+
for (double v : values_) {
|
|
19
|
+
total += (v - m) * (v - m);
|
|
20
|
+
}
|
|
21
|
+
return std::sqrt(total / values_.size());
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
int Stats::count() const {
|
|
25
|
+
return static_cast<int>(values_.size());
|
|
26
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#include <catch2/catch_test_macros.hpp>
|
|
2
|
+
#include <catch2/catch_approx.hpp>
|
|
3
|
+
|
|
4
|
+
#include "stats.h"
|
|
5
|
+
|
|
6
|
+
using Catch::Approx;
|
|
7
|
+
|
|
8
|
+
TEST_CASE("mean of yesterday's numbers", "[stats]") {
|
|
9
|
+
Stats s({2.0, 4.0, 4.0, 4.0, 5.0, 5.0, 7.0, 9.0});
|
|
10
|
+
REQUIRE(s.mean() == Approx(5.0));
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
TEST_CASE("standard deviation of yesterday's numbers", "[stats]") {
|
|
14
|
+
Stats s({2.0, 4.0, 4.0, 4.0, 5.0, 5.0, 7.0, 9.0});
|
|
15
|
+
REQUIRE(s.stddev() == Approx(2.0));
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
TEST_CASE("count is the number of values", "[stats]") {
|
|
19
|
+
REQUIRE(Stats({1.0, 2.0, 3.0}).count() == 3);
|
|
20
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#include <iostream>
|
|
2
|
+
#include <map>
|
|
3
|
+
#include <string>
|
|
4
|
+
|
|
5
|
+
int main() {
|
|
6
|
+
std::map<std::string, int> counts;
|
|
7
|
+
|
|
8
|
+
counts["alpha"] = 1;
|
|
9
|
+
counts["beta"] += 1;
|
|
10
|
+
counts["alpha"] += 1;
|
|
11
|
+
|
|
12
|
+
for (const auto& entry : counts) {
|
|
13
|
+
std::cout << entry.first << " " << entry.second << "\n";
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
std::cout << "beta present: " << (counts.count("beta") == 1) << "\n";
|
|
17
|
+
std::cout << "gamma present: " << (counts.count("gamma") == 1) << "\n";
|
|
18
|
+
return 0;
|
|
19
|
+
}
|