differintC 0.1.0__tar.gz
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.
- differintc-0.1.0/.github/workflows/ci.yml +0 -0
- differintc-0.1.0/CMakeLists.txt +100 -0
- differintc-0.1.0/LICENSE +0 -0
- differintc-0.1.0/PKG-INFO +9 -0
- differintc-0.1.0/README.MD +0 -0
- differintc-0.1.0/cmake/differintCConfig.cmake.in +5 -0
- differintc-0.1.0/docs/index.md +0 -0
- differintc-0.1.0/examples/demo_fractional.ipynb +0 -0
- differintc-0.1.0/include/differint/differint.hpp +74 -0
- differintc-0.1.0/pyproject.toml +12 -0
- differintc-0.1.0/python/CMakeLists.txt +21 -0
- differintc-0.1.0/python/module.cpp +80 -0
- differintc-0.1.0/src/differint/differint.cpp +208 -0
- differintc-0.1.0/src/differint/sanity.cpp +50 -0
- differintc-0.1.0/tests/cpp/test_differint.cpp +0 -0
- differintc-0.1.0/tests/python/test_bindings.py +0 -0
File without changes
|
@@ -0,0 +1,100 @@
|
|
1
|
+
cmake_minimum_required(VERSION 3.15)
|
2
|
+
# ——————————————————————————————————————————————————————————
|
3
|
+
# 1) Project Declaration & C++ Standard
|
4
|
+
# ——————————————————————————————————————————————————————————
|
5
|
+
project(differintC
|
6
|
+
VERSION 0.1.0
|
7
|
+
DESCRIPTION "Standalone C++ library for fractional differintegrals"
|
8
|
+
LANGUAGES CXX
|
9
|
+
)
|
10
|
+
|
11
|
+
# Force C++17
|
12
|
+
set(CMAKE_CXX_STANDARD 17)
|
13
|
+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
14
|
+
|
15
|
+
# ——————————————————————————————————————————————————————————
|
16
|
+
# 2) Find Python & pybind11
|
17
|
+
# ——————————————————————————————————————————————————————————
|
18
|
+
find_package(Python COMPONENTS Interpreter Development REQUIRED)
|
19
|
+
|
20
|
+
include(FetchContent)
|
21
|
+
FetchContent_Declare(
|
22
|
+
pybind11
|
23
|
+
GIT_REPOSITORY https://github.com/pybind/pybind11.git
|
24
|
+
GIT_TAG v2.11.0
|
25
|
+
)
|
26
|
+
FetchContent_MakeAvailable(pybind11)
|
27
|
+
|
28
|
+
# ——————————————————————————————————————————————————————————
|
29
|
+
# 3) Core Library Target
|
30
|
+
# ——————————————————————————————————————————————————————————
|
31
|
+
add_library(differint_core
|
32
|
+
src/differint/differint.cpp
|
33
|
+
)
|
34
|
+
target_include_directories(differint_core
|
35
|
+
PUBLIC ${CMAKE_SOURCE_DIR}/include
|
36
|
+
)
|
37
|
+
|
38
|
+
# Optional standalone sanity checker
|
39
|
+
if(DIFFCHECK_GL)
|
40
|
+
add_executable(sanity
|
41
|
+
src/differint/sanity.cpp
|
42
|
+
)
|
43
|
+
target_include_directories(sanity
|
44
|
+
PRIVATE ${CMAKE_SOURCE_DIR}/include
|
45
|
+
)
|
46
|
+
target_link_libraries(sanity
|
47
|
+
PRIVATE differint_core
|
48
|
+
)
|
49
|
+
endif()
|
50
|
+
|
51
|
+
# ——————————————————————————————————————————————————————————
|
52
|
+
# 4) Python Extension Module (differintC.pyd)
|
53
|
+
# ——————————————————————————————————————————————————————————
|
54
|
+
pybind11_add_module(differintC MODULE
|
55
|
+
python/module.cpp
|
56
|
+
)
|
57
|
+
|
58
|
+
target_include_directories(differintC
|
59
|
+
PRIVATE ${CMAKE_SOURCE_DIR}/include
|
60
|
+
)
|
61
|
+
|
62
|
+
target_link_libraries(differintC
|
63
|
+
PRIVATE differint_core
|
64
|
+
)
|
65
|
+
|
66
|
+
# Fix Windows pyd naming and output
|
67
|
+
set_target_properties(differintC PROPERTIES
|
68
|
+
PREFIX "" # Avoid "lib" prefix
|
69
|
+
SUFFIX ".pyd" # Ensure Python .pyd extension
|
70
|
+
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/Release # Optional: match build dir
|
71
|
+
)
|
72
|
+
|
73
|
+
|
74
|
+
|
75
|
+
# ——————————————————————————————————————————————————————————
|
76
|
+
# 5) Install: Python module into site-packages
|
77
|
+
# ——————————————————————————————————————————————————————————
|
78
|
+
# Detect Python site-packages directory
|
79
|
+
execute_process(
|
80
|
+
COMMAND "${Python_EXECUTABLE}" -c
|
81
|
+
"import sysconfig; print(sysconfig.get_paths()['purelib'])"
|
82
|
+
OUTPUT_VARIABLE PYTHON_SITE_PACKAGES
|
83
|
+
OUTPUT_STRIP_TRAILING_WHITESPACE
|
84
|
+
)
|
85
|
+
|
86
|
+
install(TARGETS differintC
|
87
|
+
LIBRARY DESTINATION "${PYTHON_SITE_PACKAGES}" # for .pyd module
|
88
|
+
)
|
89
|
+
|
90
|
+
# Optional: install core lib if desired
|
91
|
+
install(TARGETS differint_core
|
92
|
+
ARCHIVE DESTINATION lib
|
93
|
+
LIBRARY DESTINATION lib
|
94
|
+
)
|
95
|
+
|
96
|
+
# ——————————————————————————————————————————————————————————
|
97
|
+
# 5) (Optional) Testing — commented out until you add tests
|
98
|
+
# ——————————————————————————————————————————————————————————
|
99
|
+
# enable_testing()
|
100
|
+
# add_subdirectory(tests)
|
differintc-0.1.0/LICENSE
ADDED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,74 @@
|
|
1
|
+
#pragma once
|
2
|
+
|
3
|
+
#include <vector>
|
4
|
+
#include <cstddef>
|
5
|
+
|
6
|
+
namespace differint {
|
7
|
+
|
8
|
+
/**
|
9
|
+
* Riemann–Liouville fractional derivative at a single point using trapezoid rule.
|
10
|
+
* @tparam T Numeric type (e.g. float, double)
|
11
|
+
* @param alpha Fractional order (0 < alpha < 1)
|
12
|
+
* @param f_vals Either sample values of f at uniformly spaced points, or size-0 vector
|
13
|
+
* if no precomputed samples; in that case, user must call with
|
14
|
+
* a custom provider (see implementation)
|
15
|
+
* @param domain_start Left endpoint of interval
|
16
|
+
* @param domain_end Right endpoint of interval
|
17
|
+
* @param num_points Number of discretization points
|
18
|
+
* @return Approximated fractional derivative value
|
19
|
+
*/
|
20
|
+
template <typename T>
|
21
|
+
T RLpoint(T alpha,
|
22
|
+
const std::vector<T>& f_vals,
|
23
|
+
T domain_start = T(0),
|
24
|
+
T domain_end = T(1),
|
25
|
+
std::size_t num_points = 100);
|
26
|
+
|
27
|
+
|
28
|
+
/// Riemann–Liouville fractional derivative over the entire grid
|
29
|
+
template <typename T>
|
30
|
+
std::vector<T> RL(T alpha,
|
31
|
+
const std::vector<T>& f_vals,
|
32
|
+
T domain_start = T(0),
|
33
|
+
T domain_end = T(1),
|
34
|
+
std::size_t num_points = 100);
|
35
|
+
|
36
|
+
|
37
|
+
|
38
|
+
|
39
|
+
|
40
|
+
/**
|
41
|
+
* Grünwald–Letnikov fractional derivative at a single point.
|
42
|
+
* @tparam T
|
43
|
+
* @param alpha Fractional order
|
44
|
+
* @param f_vals Sampled function values at uniform nodes
|
45
|
+
* @param domain_start Left endpoint
|
46
|
+
* @param domain_end Right endpoint
|
47
|
+
* @param num_points Number of nodes
|
48
|
+
* @return Approximated derivative
|
49
|
+
*/
|
50
|
+
template <typename T>
|
51
|
+
T GLpoint(T alpha,
|
52
|
+
const std::vector<T>& f_vals,
|
53
|
+
T domain_start = T(0),
|
54
|
+
T domain_end = T(1),
|
55
|
+
std::size_t num_points = 100);
|
56
|
+
|
57
|
+
/**
|
58
|
+
* Grünwald–Letnikov fractional derivative over entire grid.
|
59
|
+
* @tparam T
|
60
|
+
* @param alpha Fractional order
|
61
|
+
* @param f_vals Sampled function values at uniform nodes
|
62
|
+
* @param domain_start Left endpoint
|
63
|
+
* @param domain_end Right endpoint
|
64
|
+
* @param num_points Number of nodes
|
65
|
+
* @return Vector of derivative values at each node
|
66
|
+
*/
|
67
|
+
template <typename T>
|
68
|
+
std::vector<T> GL(T alpha,
|
69
|
+
const std::vector<T>& f_vals,
|
70
|
+
T domain_start = T(0),
|
71
|
+
T domain_end = T(1),
|
72
|
+
std::size_t num_points = 100);
|
73
|
+
|
74
|
+
} // namespace differint
|
@@ -0,0 +1,12 @@
|
|
1
|
+
[build-system]
|
2
|
+
requires = ["scikit-build-core", "pybind11"]
|
3
|
+
build-backend = "scikit_build_core.build"
|
4
|
+
|
5
|
+
[project]
|
6
|
+
name = "differintC"
|
7
|
+
version = "0.1.0"
|
8
|
+
description = "Fast C++ implementation of fractional calculus operators"
|
9
|
+
authors = [{ name = "Your Name" }]
|
10
|
+
license = "MIT"
|
11
|
+
readme = "README.md"
|
12
|
+
requires-python = ">=3.8"
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# python/CMakeLists.txt
|
2
|
+
|
3
|
+
# Create the Python extension module
|
4
|
+
pybind11_add_module(differintC module.cpp)
|
5
|
+
|
6
|
+
# Ensure it can include our public headers
|
7
|
+
target_include_directories(differintC
|
8
|
+
PRIVATE ${CMAKE_SOURCE_DIR}/include
|
9
|
+
)
|
10
|
+
|
11
|
+
# Link against the core library
|
12
|
+
target_link_libraries(differintC
|
13
|
+
PRIVATE differint_core
|
14
|
+
)
|
15
|
+
|
16
|
+
# Optionally set properties so it's built in Release by default
|
17
|
+
set_target_properties(differintC PROPERTIES
|
18
|
+
CXX_STANDARD 17
|
19
|
+
CXX_STANDARD_REQUIRED YES
|
20
|
+
BUILD_WITH_INSTALL_RPATH ON
|
21
|
+
)
|
@@ -0,0 +1,80 @@
|
|
1
|
+
#include <pybind11/pybind11.h>
|
2
|
+
#include <pybind11/numpy.h>
|
3
|
+
#include "differint/differint.hpp"
|
4
|
+
|
5
|
+
namespace py = pybind11;
|
6
|
+
|
7
|
+
template <typename Func>
|
8
|
+
std::vector<double> call_and_sample(Func&& f, double a, double b, size_t n) {
|
9
|
+
// Build the input grid
|
10
|
+
std::vector<double> vals(n);
|
11
|
+
double step = (b - a) / (n - 1);
|
12
|
+
for (size_t i = 0; i < n; ++i)
|
13
|
+
vals[i] = f(a + step * i);
|
14
|
+
return vals;
|
15
|
+
}
|
16
|
+
|
17
|
+
// Helper to convert any array-like or callable to a std::vector<double>
|
18
|
+
std::vector<double> prepare_fvals(py::object f_obj,
|
19
|
+
double a, double b, size_t n) {
|
20
|
+
// If it's an array or list, cast directly
|
21
|
+
if (py::isinstance<py::array>(f_obj) ||
|
22
|
+
py::isinstance<py::list>(f_obj)) {
|
23
|
+
auto arr = py::array_t<double>::ensure(f_obj);
|
24
|
+
if (!arr || arr.size() != n)
|
25
|
+
throw std::runtime_error("Input array length must equal num_points");
|
26
|
+
std::vector<double> v(n);
|
27
|
+
std::memcpy(v.data(), arr.data(), n * sizeof(double));
|
28
|
+
return v;
|
29
|
+
}
|
30
|
+
// Otherwise assume callable
|
31
|
+
auto cb = f_obj.cast<py::function>();
|
32
|
+
return call_and_sample(
|
33
|
+
[&](double x){ return cb(x).cast<double>(); },
|
34
|
+
a, b, n
|
35
|
+
);
|
36
|
+
}
|
37
|
+
|
38
|
+
PYBIND11_MODULE(differintC, m) {
|
39
|
+
m.doc() = "Fractional differintegral routines (RL & GL)";
|
40
|
+
|
41
|
+
m.def("RLpoint",
|
42
|
+
[](double alpha, py::object f, double a, double b, size_t n) {
|
43
|
+
auto fv = prepare_fvals(f, a, b, n);
|
44
|
+
return differint::RLpoint(alpha, fv, a, b, n);
|
45
|
+
},
|
46
|
+
py::arg("alpha"), py::arg("f_name"),
|
47
|
+
py::arg("domain_start")=0.0, py::arg("domain_end")=1.0,
|
48
|
+
py::arg("num_points")=100
|
49
|
+
);
|
50
|
+
|
51
|
+
m.def("RL",
|
52
|
+
[](double alpha, py::object f, double a, double b, size_t n) {
|
53
|
+
auto fv = prepare_fvals(f, a, b, n);
|
54
|
+
return differint::RL(alpha, fv, a, b, n);
|
55
|
+
},
|
56
|
+
py::arg("alpha"), py::arg("f_name"),
|
57
|
+
py::arg("domain_start")=0.0, py::arg("domain_end")=1.0,
|
58
|
+
py::arg("num_points")=100
|
59
|
+
);
|
60
|
+
|
61
|
+
m.def("GLpoint",
|
62
|
+
[](double alpha, py::object f, double a, double b, size_t n) {
|
63
|
+
auto fv = prepare_fvals(f, a, b, n);
|
64
|
+
return differint::GLpoint(alpha, fv, a, b, n);
|
65
|
+
},
|
66
|
+
py::arg("alpha"), py::arg("f_name"),
|
67
|
+
py::arg("domain_start")=0.0, py::arg("domain_end")=1.0,
|
68
|
+
py::arg("num_points")=100
|
69
|
+
);
|
70
|
+
|
71
|
+
m.def("GL",
|
72
|
+
[](double alpha, py::object f, double a, double b, size_t n) {
|
73
|
+
auto fv = prepare_fvals(f, a, b, n);
|
74
|
+
return differint::GL(alpha, fv, a, b, n);
|
75
|
+
},
|
76
|
+
py::arg("alpha"), py::arg("f_name"),
|
77
|
+
py::arg("domain_start")=0.0, py::arg("domain_end")=1.0,
|
78
|
+
py::arg("num_points")=100
|
79
|
+
);
|
80
|
+
}
|
@@ -0,0 +1,208 @@
|
|
1
|
+
#include <differint/differint.hpp>
|
2
|
+
#include <cmath>
|
3
|
+
#include <stdexcept>
|
4
|
+
#include <algorithm>
|
5
|
+
|
6
|
+
namespace differint {
|
7
|
+
|
8
|
+
template <typename T>
|
9
|
+
T RLpoint(T alpha,
|
10
|
+
const std::vector<T>& f_vals,
|
11
|
+
T domain_start,
|
12
|
+
T domain_end,
|
13
|
+
std::size_t num_points) {
|
14
|
+
if (num_points < 2) {
|
15
|
+
throw std::invalid_argument("num_points must be at least 2");
|
16
|
+
}
|
17
|
+
// Ensure domain ordering
|
18
|
+
if (domain_start > domain_end) {
|
19
|
+
std::swap(domain_start, domain_end);
|
20
|
+
}
|
21
|
+
// Check input vector length
|
22
|
+
if (f_vals.size() != num_points) {
|
23
|
+
throw std::invalid_argument("f_vals size does not match num_points");
|
24
|
+
}
|
25
|
+
// Compute step size
|
26
|
+
T step = (domain_end - domain_start) / static_cast<T>(num_points - 1);
|
27
|
+
|
28
|
+
std::size_t k = num_points - 1;
|
29
|
+
std::vector<T> coeffs(num_points);
|
30
|
+
|
31
|
+
// Case j == 0
|
32
|
+
if (k > 0) {
|
33
|
+
coeffs[0] = std::pow(static_cast<T>(k - 1), static_cast<T>(1) - alpha)
|
34
|
+
- (static_cast<T>(k) + alpha - static_cast<T>(1))
|
35
|
+
* std::pow(static_cast<T>(k), -alpha);
|
36
|
+
} else {
|
37
|
+
coeffs[0] = T(1);
|
38
|
+
}
|
39
|
+
|
40
|
+
// Case j == k
|
41
|
+
coeffs[k] = T(1);
|
42
|
+
|
43
|
+
// Other indices
|
44
|
+
for (std::size_t j = 1; j < k; ++j) {
|
45
|
+
T d = static_cast<T>(k - j);
|
46
|
+
coeffs[j] = std::pow(d + static_cast<T>(1), static_cast<T>(1) - alpha)
|
47
|
+
+ std::pow(d - static_cast<T>(1), static_cast<T>(1) - alpha)
|
48
|
+
- static_cast<T>(2) * std::pow(d, static_cast<T>(1) - alpha);
|
49
|
+
}
|
50
|
+
|
51
|
+
// Compute normalization constant
|
52
|
+
T C = static_cast<T>(1) / std::tgamma(static_cast<T>(2) - alpha);
|
53
|
+
|
54
|
+
// Dot product
|
55
|
+
T result = T(0);
|
56
|
+
for (std::size_t i = 0; i < num_points; ++i) {
|
57
|
+
result += coeffs[i] * f_vals[i];
|
58
|
+
}
|
59
|
+
|
60
|
+
return C * std::pow(step, -alpha) * result;
|
61
|
+
}
|
62
|
+
|
63
|
+
|
64
|
+
// RL entire-grid implementation
|
65
|
+
template <typename T>
|
66
|
+
std::vector<T> RL(T alpha,
|
67
|
+
const std::vector<T>& f_vals,
|
68
|
+
T domain_start,
|
69
|
+
T domain_end,
|
70
|
+
std::size_t num_points) {
|
71
|
+
if (num_points < 2) {
|
72
|
+
throw std::invalid_argument("num_points must be at least 2");
|
73
|
+
}
|
74
|
+
if (domain_start > domain_end) {
|
75
|
+
std::swap(domain_start, domain_end);
|
76
|
+
}
|
77
|
+
if (f_vals.size() != num_points) {
|
78
|
+
throw std::invalid_argument("f_vals size does not match num_points");
|
79
|
+
}
|
80
|
+
T step = (domain_end - domain_start) / static_cast<T>(num_points - 1);
|
81
|
+
|
82
|
+
// Precompute coefficient matrix D
|
83
|
+
std::vector<std::vector<T>> D(num_points, std::vector<T>(num_points));
|
84
|
+
// Precompute powers v[k] = (k)^(1-alpha)
|
85
|
+
std::vector<T> v(num_points + 1);
|
86
|
+
for (std::size_t k = 0; k <= num_points; ++k) {
|
87
|
+
v[k] = std::pow(static_cast<T>(k), static_cast<T>(1) - alpha);
|
88
|
+
}
|
89
|
+
|
90
|
+
// Fill D
|
91
|
+
for (std::size_t i = 0; i < num_points; ++i) {
|
92
|
+
for (std::size_t j = 0; j < num_points; ++j) {
|
93
|
+
if (j == i) {
|
94
|
+
D[i][j] = T(1);
|
95
|
+
} else if (j == 0 && i > 0) {
|
96
|
+
T k = static_cast<T>(i);
|
97
|
+
D[i][0] = v[i - 1] - (k + alpha - static_cast<T>(1)) * std::pow(k, -alpha);
|
98
|
+
} else if (j < i) {
|
99
|
+
std::size_t k = i - j;
|
100
|
+
D[i][j] = v[k + 1] + v[k - 1] - static_cast<T>(2) * v[k];
|
101
|
+
} else {
|
102
|
+
D[i][j] = T(0);
|
103
|
+
}
|
104
|
+
}
|
105
|
+
}
|
106
|
+
|
107
|
+
// Normalize by Gamma
|
108
|
+
T C = static_cast<T>(1) / std::tgamma(static_cast<T>(2) - alpha);
|
109
|
+
|
110
|
+
// Multiply D @ f_vals
|
111
|
+
std::vector<T> result(num_points, T(0));
|
112
|
+
for (std::size_t i = 0; i < num_points; ++i) {
|
113
|
+
T acc = T(0);
|
114
|
+
for (std::size_t j = 0; j < num_points; ++j) {
|
115
|
+
acc += D[i][j] * f_vals[j];
|
116
|
+
}
|
117
|
+
result[i] = C * std::pow(step, -alpha) * acc;
|
118
|
+
}
|
119
|
+
return result;
|
120
|
+
}
|
121
|
+
|
122
|
+
|
123
|
+
|
124
|
+
|
125
|
+
// Compute GL coefficients up to order n
|
126
|
+
template <typename T>
|
127
|
+
std::vector<T> GLcoeffs(T alpha, std::size_t n) {
|
128
|
+
// b[0] = 1
|
129
|
+
std::vector<T> b(n + 1, T(1));
|
130
|
+
for (std::size_t j = 1; j <= n; ++j) {
|
131
|
+
b[j] = b[j - 1] * (static_cast<T>(-alpha) + static_cast<T>(j - 1))
|
132
|
+
/ static_cast<T>(j);
|
133
|
+
}
|
134
|
+
return b;
|
135
|
+
}
|
136
|
+
|
137
|
+
|
138
|
+
// GL at a single point (endpoint)
|
139
|
+
template <typename T>
|
140
|
+
T GLpoint(T alpha,
|
141
|
+
const std::vector<T>& f_vals,
|
142
|
+
T domain_start,
|
143
|
+
T domain_end,
|
144
|
+
std::size_t num_points) {
|
145
|
+
if (num_points < 1) {
|
146
|
+
throw std::invalid_argument("num_points must be at least 1");
|
147
|
+
}
|
148
|
+
if (domain_start > domain_end) {
|
149
|
+
std::swap(domain_start, domain_end);
|
150
|
+
}
|
151
|
+
if (f_vals.size() != num_points) {
|
152
|
+
throw std::invalid_argument("f_vals size must equal num_points");
|
153
|
+
}
|
154
|
+
T step = (domain_end - domain_start) / static_cast<T>(num_points - 1);
|
155
|
+
// Compute coefficients for k = num_points - 1
|
156
|
+
std::size_t k = num_points - 1;
|
157
|
+
auto b = GLcoeffs(alpha, k);
|
158
|
+
T acc = T(0);
|
159
|
+
for (std::size_t j = 0; j <= k; ++j) {
|
160
|
+
acc += b[j] * f_vals[k - j];
|
161
|
+
}
|
162
|
+
return std::pow(step, -alpha) * acc;
|
163
|
+
}
|
164
|
+
|
165
|
+
// GL over entire grid
|
166
|
+
template <typename T>
|
167
|
+
std::vector<T> GL(T alpha,
|
168
|
+
const std::vector<T>& f_vals,
|
169
|
+
T domain_start,
|
170
|
+
T domain_end,
|
171
|
+
std::size_t num_points) {
|
172
|
+
if (num_points < 1) {
|
173
|
+
throw std::invalid_argument("num_points must be at least 1");
|
174
|
+
}
|
175
|
+
if (domain_start > domain_end) {
|
176
|
+
std::swap(domain_start, domain_end);
|
177
|
+
}
|
178
|
+
if (f_vals.size() != num_points) {
|
179
|
+
throw std::invalid_argument("f_vals size must equal num_points");
|
180
|
+
}
|
181
|
+
T step = (domain_end - domain_start) / static_cast<T>(num_points - 1);
|
182
|
+
auto b = GLcoeffs(alpha, num_points - 1);
|
183
|
+
std::vector<T> result(num_points, T(0));
|
184
|
+
for (std::size_t i = 0; i < num_points; ++i) {
|
185
|
+
T acc = T(0);
|
186
|
+
// convolution-like sum
|
187
|
+
for (std::size_t j = 0; j <= i; ++j) {
|
188
|
+
acc += b[j] * f_vals[i - j];
|
189
|
+
}
|
190
|
+
result[i] = std::pow(step, -alpha) * acc;
|
191
|
+
}
|
192
|
+
return result;
|
193
|
+
}
|
194
|
+
|
195
|
+
|
196
|
+
// Explicit instantiations for double
|
197
|
+
template double RLpoint<double>(double, const std::vector<double>&, double, double, std::size_t);
|
198
|
+
template std::vector<double> RL<double>(double, const std::vector<double>&, double, double, std::size_t);
|
199
|
+
template double GLpoint<double>(double, const std::vector<double>&, double, double, std::size_t);
|
200
|
+
template std::vector<double> GL<double>(double, const std::vector<double>&, double, double, std::size_t);
|
201
|
+
|
202
|
+
template std::vector<double> GLcoeffs<double>(double, std::size_t);
|
203
|
+
|
204
|
+
|
205
|
+
|
206
|
+
|
207
|
+
} // namespace differint
|
208
|
+
|
@@ -0,0 +1,50 @@
|
|
1
|
+
#include <iostream>
|
2
|
+
#include <vector>
|
3
|
+
#include <cmath>
|
4
|
+
#include "differint/differint.hpp"
|
5
|
+
|
6
|
+
int main() {
|
7
|
+
double alpha = 0.5;
|
8
|
+
std::size_t n = 1000;
|
9
|
+
double a = 0.0, b = 1.0;
|
10
|
+
|
11
|
+
// sample f(x)=x^2
|
12
|
+
std::vector<double> vals(n);
|
13
|
+
for (std::size_t i = 0; i < n; ++i) {
|
14
|
+
double x = a + (b - a) * i / (n - 1);
|
15
|
+
vals[i] = x * x;
|
16
|
+
}
|
17
|
+
|
18
|
+
double num = differint::GLpoint(alpha, vals, a, b, n);
|
19
|
+
double exact = std::tgamma(3.0) / std::tgamma(3.0 - alpha);
|
20
|
+
|
21
|
+
std::cout << "GLpoint_num = " << num << "\n"
|
22
|
+
<< "GLpoint_exact= " << exact << "\n"
|
23
|
+
<< "Error = " << std::abs(num - exact) << "\n";
|
24
|
+
|
25
|
+
auto gl_vec = differint::RL(alpha, vals, a, b, n);
|
26
|
+
double gl_end = gl_vec.back();
|
27
|
+
std::cout << "\nGL.back() = " << gl_end
|
28
|
+
<< "\nGL_exact = " << exact
|
29
|
+
<< "\nError = " << std::abs(gl_end - exact) << "\n";
|
30
|
+
|
31
|
+
|
32
|
+
|
33
|
+
|
34
|
+
// RLpoint test: f(x)=x^2 at endpoint
|
35
|
+
double rl_num = differint::RLpoint(alpha, vals, a, b, n);
|
36
|
+
double rl_exact = std::tgamma(3.0)/std::tgamma(3.0 - alpha);
|
37
|
+
std::cout << "\nRLpoint_num = " << rl_num
|
38
|
+
<< "\nRLpoint_exact= " << rl_exact
|
39
|
+
<< "\nError = " << std::abs(rl_num - rl_exact) << "\n";
|
40
|
+
|
41
|
+
auto rl_vec = differint::RL(alpha, vals, a, b, n);
|
42
|
+
double rl_end = rl_vec.back();
|
43
|
+
std::cout << "\nRL.back() = " << rl_end
|
44
|
+
<< "\nRL_exact = " << exact
|
45
|
+
<< "\nError = " << std::abs(rl_end - exact) << "\n";
|
46
|
+
|
47
|
+
std::cout << "\nPress ENTER to exit...";
|
48
|
+
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
|
49
|
+
return 0;
|
50
|
+
}
|
File without changes
|
File without changes
|