From 85a1493837ec17c6cbb68e29c89475a127563bc8 Mon Sep 17 00:00:00 2001
From: Klaus Reuter <khr@mpcdf.mpg.de>
Date: Thu, 2 Dec 2021 21:56:23 +0100
Subject: [PATCH] add minimal numpy example for illustration purposes

---
 CMakeLists.txt         |  9 +++------
 setup.py               |  9 ++++-----
 src/cumsum/__init__.py |  1 +
 src/cumsum/cumsum.cpp  | 34 ++++++++++++++++++++++++++++++++++
 test/test_cumsum.py    | 11 +++++++++++
 5 files changed, 53 insertions(+), 11 deletions(-)
 create mode 100644 src/cumsum/__init__.py
 create mode 100644 src/cumsum/cumsum.cpp
 create mode 100755 test/test_cumsum.py

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 48d3439..6d32bb0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,9 +1,6 @@
 cmake_minimum_required(VERSION 3.18)
-
-project(hello-world VERSION "1.0")
-
+project(pybind11-hello-world VERSION "1.0")
 find_package(pybind11)
 
-pybind11_add_module(_hello MODULE src/hello/hello.cpp)
-
-install(TARGETS _hello DESTINATION .)
+pybind11_add_module(_cumsum MODULE src/cumsum/cumsum.cpp)
+install(TARGETS _cumsum DESTINATION .)
\ No newline at end of file
diff --git a/setup.py b/setup.py
index ff4960c..b484203 100644
--- a/setup.py
+++ b/setup.py
@@ -1,13 +1,12 @@
-import sys
 from skbuild import setup
 
 setup(
-    name="hello-world",
+    name="pybind11-numpy-like-cumsum-example",
     version="1.0",
-    description="hello world example",
+    description="pybind11-numpy example",
     author='MPCDF',
     license="MIT",
-    packages=['hello'],
+    packages=['cumsum'],
     package_dir={'': 'src'},
-    cmake_install_dir='src/hello'
+    cmake_install_dir='src/cumsum'
 )
diff --git a/src/cumsum/__init__.py b/src/cumsum/__init__.py
new file mode 100644
index 0000000..c96cb7b
--- /dev/null
+++ b/src/cumsum/__init__.py
@@ -0,0 +1 @@
+from ._cumsum import cumsum
\ No newline at end of file
diff --git a/src/cumsum/cumsum.cpp b/src/cumsum/cumsum.cpp
new file mode 100644
index 0000000..db99448
--- /dev/null
+++ b/src/cumsum/cumsum.cpp
@@ -0,0 +1,34 @@
+// pybind11 example module 'cumsum'
+#include <numeric>
+#include <functional>
+#include <pybind11/pybind11.h>
+#include <pybind11/numpy.h>
+
+namespace py = pybind11;
+
+// numpy-like cumulative sum, taking a NumPy array as input and returning a NumPy array
+py::array_t<double> cumsum(py::array_t<double> a)
+{
+    // obtain information about the nd input array
+    auto shape = a.request().shape;
+    size_t count = std::accumulate(shape.begin(), shape.end(), 1, std::multiplies<size_t>());
+    // create output NumPy array
+    py::array_t<double> b(count);
+    // obtain raw pointers
+    double * a_p = (double*) a.request().ptr;
+    double * b_p = (double*) b.request().ptr;
+    // compute cumulative sum into b
+    double cs = 0.0;
+    for (size_t i = 0; i<count; ++i) {
+        cs += a_p[i];
+        b_p[i] = cs;
+    }
+    return b;
+}
+
+// Python binary module _cumsum, expose cumsum C++ function as cumsum to Python
+PYBIND11_MODULE(_cumsum, m) {
+    m.doc() = "pybind11 cumulative sum example"; // module docstring
+    m.def("cumsum", &cumsum,  // third parameter is the function docstring
+          "return the cumulative sum of a double-precision numpy array");
+}
diff --git a/test/test_cumsum.py b/test/test_cumsum.py
new file mode 100755
index 0000000..782fc1f
--- /dev/null
+++ b/test/test_cumsum.py
@@ -0,0 +1,11 @@
+#!/usr/bin/env python3
+import numpy as np
+import cumsum
+
+a = np.random.rand(80)
+ap = a.reshape(20,4)
+b = cumsum.cumsum(ap)
+c = np.cumsum(ap)
+
+assert(np.allclose(b, c))
+print("OK!")
\ No newline at end of file
-- 
GitLab