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.
Files changed (96) hide show
  1. jrpycpp/__init__.py +3 -0
  2. jrpycpp/__version__.py +1 -0
  3. jrpycpp/examples/cpp_scripts/chapter2/demo/01-class.cpp +24 -0
  4. jrpycpp/examples/cpp_scripts/chapter2/demo/02-const.cpp +25 -0
  5. jrpycpp/examples/cpp_scripts/chapter2/exercise/stats.cpp +26 -0
  6. jrpycpp/examples/cpp_scripts/chapter2/solution/stats.cpp +44 -0
  7. jrpycpp/examples/cpp_scripts/chapter3/demo/01-free-function/bindings.cpp +11 -0
  8. jrpycpp/examples/cpp_scripts/chapter3/demo/01-free-function/pi.cpp +10 -0
  9. jrpycpp/examples/cpp_scripts/chapter3/demo/01-free-function/pi.h +3 -0
  10. jrpycpp/examples/cpp_scripts/chapter3/demo/01-free-function/pyproject.toml +11 -0
  11. jrpycpp/examples/cpp_scripts/chapter3/demo/01-free-function/setup.py +12 -0
  12. jrpycpp/examples/cpp_scripts/chapter3/demo/01-free-function/test_pi.py +11 -0
  13. jrpycpp/examples/cpp_scripts/chapter3/demo/02-class/bindings.cpp +17 -0
  14. jrpycpp/examples/cpp_scripts/chapter3/demo/02-class/pyproject.toml +11 -0
  15. jrpycpp/examples/cpp_scripts/chapter3/demo/02-class/setup.py +12 -0
  16. jrpycpp/examples/cpp_scripts/chapter3/demo/02-class/stats.cpp +26 -0
  17. jrpycpp/examples/cpp_scripts/chapter3/demo/02-class/stats.h +15 -0
  18. jrpycpp/examples/cpp_scripts/chapter3/demo/02-class/test_livstats.py +18 -0
  19. jrpycpp/examples/cpp_scripts/chapter3/exercise/bindings.cpp +12 -0
  20. jrpycpp/examples/cpp_scripts/chapter3/exercise/pyproject.toml +11 -0
  21. jrpycpp/examples/cpp_scripts/chapter3/exercise/setup.py +12 -0
  22. jrpycpp/examples/cpp_scripts/chapter3/exercise/stats.cpp +26 -0
  23. jrpycpp/examples/cpp_scripts/chapter3/exercise/stats.h +15 -0
  24. jrpycpp/examples/cpp_scripts/chapter3/solution/bindings.cpp +22 -0
  25. jrpycpp/examples/cpp_scripts/chapter3/solution/pyproject.toml +11 -0
  26. jrpycpp/examples/cpp_scripts/chapter3/solution/setup.py +12 -0
  27. jrpycpp/examples/cpp_scripts/chapter3/solution/stats.cpp +26 -0
  28. jrpycpp/examples/cpp_scripts/chapter3/solution/stats.h +15 -0
  29. jrpycpp/examples/cpp_scripts/chapter3/solution/test_livstats.py +18 -0
  30. jrpycpp/examples/cpp_scripts/chapter4/demo/arrays.cpp +13 -0
  31. jrpycpp/examples/cpp_scripts/chapter4/demo/arrays.h +7 -0
  32. jrpycpp/examples/cpp_scripts/chapter4/demo/bindings.cpp +73 -0
  33. jrpycpp/examples/cpp_scripts/chapter4/demo/pyproject.toml +11 -0
  34. jrpycpp/examples/cpp_scripts/chapter4/demo/setup.py +12 -0
  35. jrpycpp/examples/cpp_scripts/chapter4/demo/test_arrays.py +38 -0
  36. jrpycpp/examples/cpp_scripts/chapter4/exercise/arrays.cpp +13 -0
  37. jrpycpp/examples/cpp_scripts/chapter4/exercise/arrays.h +7 -0
  38. jrpycpp/examples/cpp_scripts/chapter4/exercise/bindings.cpp +36 -0
  39. jrpycpp/examples/cpp_scripts/chapter4/exercise/pyproject.toml +11 -0
  40. jrpycpp/examples/cpp_scripts/chapter4/exercise/setup.py +12 -0
  41. jrpycpp/examples/cpp_scripts/chapter4/solution/arrays.cpp +13 -0
  42. jrpycpp/examples/cpp_scripts/chapter4/solution/arrays.h +7 -0
  43. jrpycpp/examples/cpp_scripts/chapter4/solution/bindings.cpp +49 -0
  44. jrpycpp/examples/cpp_scripts/chapter4/solution/pyproject.toml +11 -0
  45. jrpycpp/examples/cpp_scripts/chapter4/solution/setup.py +12 -0
  46. jrpycpp/examples/cpp_scripts/chapter4/solution/test_arrays.py +19 -0
  47. jrpycpp/examples/cpp_scripts/chapter5/demo/01-cmake/CMakeLists.txt +22 -0
  48. jrpycpp/examples/cpp_scripts/chapter5/demo/01-cmake/include/stats.h +15 -0
  49. jrpycpp/examples/cpp_scripts/chapter5/demo/01-cmake/src/main.cpp +9 -0
  50. jrpycpp/examples/cpp_scripts/chapter5/demo/01-cmake/src/stats.cpp +26 -0
  51. jrpycpp/examples/cpp_scripts/chapter5/demo/01-cmake/tests/test_stats.cpp +20 -0
  52. jrpycpp/examples/cpp_scripts/chapter5/demo/02-python/CMakeLists.txt +28 -0
  53. jrpycpp/examples/cpp_scripts/chapter5/demo/02-python/include/stats.h +15 -0
  54. jrpycpp/examples/cpp_scripts/chapter5/demo/02-python/pyproject.toml +11 -0
  55. jrpycpp/examples/cpp_scripts/chapter5/demo/02-python/python/bindings.cpp +17 -0
  56. jrpycpp/examples/cpp_scripts/chapter5/demo/02-python/src/stats.cpp +26 -0
  57. jrpycpp/examples/cpp_scripts/chapter5/demo/02-python/tests/test_livstats.py +10 -0
  58. jrpycpp/examples/cpp_scripts/chapter5/demo/02-python/tests/test_stats.cpp +20 -0
  59. jrpycpp/examples/cpp_scripts/chapter5/exercise/CMakeLists.txt +17 -0
  60. jrpycpp/examples/cpp_scripts/chapter5/exercise/include/stats.h +15 -0
  61. jrpycpp/examples/cpp_scripts/chapter5/exercise/src/main.cpp +9 -0
  62. jrpycpp/examples/cpp_scripts/chapter5/exercise/src/stats.cpp +26 -0
  63. jrpycpp/examples/cpp_scripts/chapter5/exercise/tests/test_stats.cpp +16 -0
  64. jrpycpp/examples/cpp_scripts/chapter5/solution/CMakeLists.txt +22 -0
  65. jrpycpp/examples/cpp_scripts/chapter5/solution/include/stats.h +15 -0
  66. jrpycpp/examples/cpp_scripts/chapter5/solution/src/main.cpp +9 -0
  67. jrpycpp/examples/cpp_scripts/chapter5/solution/src/stats.cpp +26 -0
  68. jrpycpp/examples/cpp_scripts/chapter5/solution/tests/test_stats.cpp +20 -0
  69. jrpycpp/examples/cpp_scripts/chapter6/demo/01-map.cpp +19 -0
  70. jrpycpp/examples/cpp_scripts/chapter6/demo/02-lambda.cpp +22 -0
  71. jrpycpp/examples/cpp_scripts/chapter6/demo/03-move.cpp +14 -0
  72. jrpycpp/examples/cpp_scripts/chapter6/demo/04-unique.cpp +19 -0
  73. jrpycpp/examples/cpp_scripts/chapter6/exercise/copies.cpp +34 -0
  74. jrpycpp/examples/cpp_scripts/chapter6/exercise/integrate.cpp +20 -0
  75. jrpycpp/examples/cpp_scripts/chapter6/exercise/words.cpp +21 -0
  76. jrpycpp/examples/cpp_scripts/chapter6/solution/copies.cpp +37 -0
  77. jrpycpp/examples/cpp_scripts/chapter6/solution/integrate.cpp +25 -0
  78. jrpycpp/examples/cpp_scripts/chapter6/solution/words.cpp +21 -0
  79. jrpycpp/examples/templates/cpp-project/CMakeLists.txt +22 -0
  80. jrpycpp/examples/templates/cpp-project/README.md +68 -0
  81. jrpycpp/examples/templates/cpp-project/include/stats.h +15 -0
  82. jrpycpp/examples/templates/cpp-project/src/main.cpp +9 -0
  83. jrpycpp/examples/templates/cpp-project/src/stats.cpp +26 -0
  84. jrpycpp/examples/templates/cpp-project/tests/test_stats.cpp +20 -0
  85. jrpycpp/examples/templates/python-cpp-project/CMakeLists.txt +28 -0
  86. jrpycpp/examples/templates/python-cpp-project/README.md +72 -0
  87. jrpycpp/examples/templates/python-cpp-project/include/stats.h +15 -0
  88. jrpycpp/examples/templates/python-cpp-project/pyproject.toml +11 -0
  89. jrpycpp/examples/templates/python-cpp-project/python/bindings.cpp +17 -0
  90. jrpycpp/examples/templates/python-cpp-project/src/stats.cpp +26 -0
  91. jrpycpp/examples/templates/python-cpp-project/tests/test_livstats.py +10 -0
  92. jrpycpp/examples/templates/python-cpp-project/tests/test_stats.cpp +20 -0
  93. jrpycpp/examples.py +43 -0
  94. jrpycpp-0.1.0.dist-info/METADATA +16 -0
  95. jrpycpp-0.1.0.dist-info/RECORD +96 -0
  96. 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,7 @@
1
+ #pragma once
2
+
3
+ #include <cstddef>
4
+ #include <vector>
5
+
6
+ double total(const double* data, std::size_t n);
7
+ double total_vector(const std::vector<double>& v);
@@ -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,11 @@
1
+ [build-system]
2
+ requires = ["setuptools>=64", "pybind11>=3.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "livarrays"
7
+ version = "0.1.0"
8
+ requires-python = ">=3.9"
9
+
10
+ [tool.setuptools]
11
+ py-modules = []
@@ -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,7 @@
1
+ #pragma once
2
+
3
+ #include <cstddef>
4
+ #include <vector>
5
+
6
+ double total(const double* data, std::size_t n);
7
+ double total_vector(const std::vector<double>& v);
@@ -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,11 @@
1
+ [build-system]
2
+ requires = ["setuptools>=64", "pybind11>=3.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "livarrays"
7
+ version = "0.1.0"
8
+ requires-python = ">=3.9"
9
+
10
+ [tool.setuptools]
11
+ py-modules = []
@@ -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,15 @@
1
+ #pragma once
2
+
3
+ #include <vector>
4
+
5
+ class Stats {
6
+ public:
7
+ Stats(const std::vector<double>& values);
8
+
9
+ double mean() const;
10
+ double stddev() const;
11
+ int count() const;
12
+
13
+ private:
14
+ std::vector<double> values_;
15
+ };
@@ -0,0 +1,9 @@
1
+ #include <iostream>
2
+
3
+ #include "stats.h"
4
+
5
+ int main() {
6
+ Stats s({2.0, 4.0, 4.0, 4.0, 5.0, 5.0, 7.0, 9.0});
7
+ std::cout << "mean " << s.mean() << ", standard deviation " << s.stddev() << "\n";
8
+ return 0;
9
+ }
@@ -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,15 @@
1
+ #pragma once
2
+
3
+ #include <vector>
4
+
5
+ class Stats {
6
+ public:
7
+ Stats(const std::vector<double>& values);
8
+
9
+ double mean() const;
10
+ double stddev() const;
11
+ int count() const;
12
+
13
+ private:
14
+ std::vector<double> values_;
15
+ };
@@ -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,10 @@
1
+ import pytest
2
+
3
+ import livstats
4
+
5
+
6
+ def test_the_class_survived_the_move_to_cmake():
7
+ s = livstats.Stats([2.0, 4.0, 4.0, 4.0, 5.0, 5.0, 7.0, 9.0])
8
+ assert s.mean() == pytest.approx(5.0)
9
+ assert s.stddev() == pytest.approx(2.0)
10
+ assert s.count() == 8
@@ -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,15 @@
1
+ #pragma once
2
+
3
+ #include <vector>
4
+
5
+ class Stats {
6
+ public:
7
+ Stats(const std::vector<double>& values);
8
+
9
+ double mean() const;
10
+ double stddev() const;
11
+ int count() const;
12
+
13
+ private:
14
+ std::vector<double> values_;
15
+ };
@@ -0,0 +1,9 @@
1
+ #include <iostream>
2
+
3
+ #include "stats.h"
4
+
5
+ int main() {
6
+ Stats s({2.0, 4.0, 4.0, 4.0, 5.0, 5.0, 7.0, 9.0});
7
+ std::cout << "mean " << s.mean() << ", standard deviation " << s.stddev() << "\n";
8
+ return 0;
9
+ }
@@ -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,15 @@
1
+ #pragma once
2
+
3
+ #include <vector>
4
+
5
+ class Stats {
6
+ public:
7
+ Stats(const std::vector<double>& values);
8
+
9
+ double mean() const;
10
+ double stddev() const;
11
+ int count() const;
12
+
13
+ private:
14
+ std::vector<double> values_;
15
+ };
@@ -0,0 +1,9 @@
1
+ #include <iostream>
2
+
3
+ #include "stats.h"
4
+
5
+ int main() {
6
+ Stats s({2.0, 4.0, 4.0, 4.0, 5.0, 5.0, 7.0, 9.0});
7
+ std::cout << "mean " << s.mean() << ", standard deviation " << s.stddev() << "\n";
8
+ return 0;
9
+ }
@@ -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
+ }