-
Notifications
You must be signed in to change notification settings - Fork 35
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ENH: add rust Dual and Spline as extension modules. (#136)
Co-authored-by: JHM Darbyshire (iMac) <[email protected]>
- Loading branch information
Showing
70 changed files
with
6,019 additions
and
360 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
[package] | ||
name = "rateslibrs" | ||
version = "1.2.0" | ||
edition = "2021" | ||
|
||
[lib] | ||
name = "rateslibrs" | ||
path = "src/lib.rs" | ||
#crate-type = ["rlib"] | ||
#crate-type = ["cdylib"] # for pyO3 | ||
crate-type = ["lib"] | ||
|
||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||
|
||
[dependencies] | ||
#pyo3 = { version = "0.20.3", features = ["abi3-py39", "extension-module"] } | ||
#chrono = "0.4.0" | ||
ndarray = "0.15.6" | ||
indexmap = "1.9.3" | ||
num-traits = "0.2.15" | ||
auto_ops = "0.3.0" | ||
numpy = "0.20.0" | ||
itertools = "0.12.1" | ||
|
||
# --- This section should be live in development to use `cargo test --lib --no-default-features` | ||
[dependencies.pyo3] | ||
version = "0.20.3" | ||
|
||
[features] | ||
extension-module = ["pyo3/extension-module"] | ||
default = ["extension-module"] | ||
# ------------- When building commment this out and use the abi3-py39 feature in the above block. | ||
|
||
[dev-dependencies] | ||
criterion = { version = "0.4", features = ["html_reports"] } | ||
|
||
[[bench]] | ||
name = "my_benchmark" | ||
harness = false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
Contains benchmark files for rust implementation. | ||
Directed by Cargo.toml. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
use criterion::{black_box, criterion_group, criterion_main, Criterion}; | ||
|
||
use rateslibrs::dual::dual1::Dual; | ||
use rateslibrs::dual::Duals; | ||
|
||
use indexmap::set::IndexSet; | ||
use ndarray::Array; | ||
use std::rc::Rc; | ||
|
||
fn dual_add_bm(a: &Dual, b: &Dual) -> Dual { | ||
a + b | ||
} | ||
|
||
fn duals_add_bm(a: &Duals, b: &Duals) -> Duals { | ||
a + b | ||
} | ||
|
||
fn dual_sub_bm(a: &Dual, b: &Dual) -> Dual { | ||
a - b | ||
} | ||
|
||
fn dual_mul_bm(a: &Dual, b: &Dual) -> Dual { | ||
a * b | ||
} | ||
|
||
fn dual_div_bm(a: &Dual, b: &Dual) -> Dual { | ||
a / b | ||
} | ||
|
||
fn float_add_bm(a: &f64, b: &f64) -> f64 { | ||
a + b | ||
} | ||
|
||
fn criterion_benchmark(c: &mut Criterion) { | ||
let dual_ = Array::ones(1000); | ||
let vars = IndexSet::from_iter((0..1000).map(|x| format!("v{}", x).to_string())); | ||
let dual_2 = Array::ones(1000); | ||
let vars2 = IndexSet::from_iter((0..1000).map(|x| format!("u{}", x).to_string())); | ||
|
||
let a = Dual { | ||
real: 2.0, | ||
vars: Rc::new(vars), | ||
dual: dual_, | ||
}; | ||
let b = Dual { | ||
real: 3.0, | ||
vars: Rc::new(vars2), | ||
dual: dual_2, | ||
}; | ||
let x = 20.1; | ||
let y = 22.1; | ||
|
||
let duals_ = Array::ones(1000); | ||
let duals_2 = Array::ones(1000); | ||
let vars = IndexSet::from_iter((0..1000).map(|x| format!("v{}", x).to_string())); | ||
let vars2 = IndexSet::from_iter((0..1000).map(|x| format!("u{}", x).to_string())); | ||
let a2 = Duals::Dual(Dual { | ||
real: 2.0, | ||
vars: Rc::new(vars), | ||
dual: duals_, | ||
}); | ||
let b2 = Duals::Dual(Dual { | ||
real: 3.0, | ||
vars: Rc::new(vars2), | ||
dual: duals_2, | ||
}); | ||
let x2 = Duals::Float(20.1); | ||
let y2 = Duals::Float(22.1); | ||
|
||
c.bench_function("float add", |z| z.iter(|| float_add_bm(&x, &y))); | ||
c.bench_function("float add duals", |z| z.iter(|| duals_add_bm(&x2, &y2))); | ||
c.bench_function("dual add diff vars", |z| z.iter(|| dual_add_bm(&a, &b))); | ||
c.bench_function("duals add diff vars", |z| z.iter(|| duals_add_bm(&a2, &b2))); | ||
c.bench_function("dual sub diff vars", |z| z.iter(|| dual_sub_bm(&a, &b))); | ||
c.bench_function("dual mul diff vars", |z| z.iter(|| dual_mul_bm(&a, &b))); | ||
c.bench_function("dual div diff vars", |z| z.iter(|| dual_div_bm(&a, &b))); | ||
c.bench_function("dual add same ptr vars", |z| { | ||
z.iter(|| dual_add_bm(&a, &a.clone())) | ||
}); | ||
c.bench_function("duals add same ptr vars", |z| { | ||
z.iter(|| duals_add_bm(&a2, &a2.clone())) | ||
}); | ||
c.bench_function("dual sub same ptr vars", |z| { | ||
z.iter(|| dual_sub_bm(&a, &a.clone())) | ||
}); | ||
c.bench_function("dual mul same ptr vars", |z| { | ||
z.iter(|| dual_mul_bm(&a, &a.clone())) | ||
}); | ||
c.bench_function("dual div same ptr vars", |z| { | ||
z.iter(|| dual_div_bm(&a, &a.clone())) | ||
}); | ||
} | ||
|
||
criterion_group!(benches, criterion_benchmark); | ||
criterion_main!(benches); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
Dual | ||
========== | ||
|
||
.. currentmodule:: rateslib.dual | ||
|
||
.. py:class:: Dual(real, vars, dual) | ||
Dual number data type to perform first derivative automatic differentiation. | ||
|
||
:param real: The real coefficient of the dual number | ||
:type real: float, int | ||
|
||
:param vars: The labels of the variables for which to record derivatives. If empty, | ||
the dual number represents a constant, equivalent to a float. | ||
:type vars: tuple of str | ||
|
||
:param dual: First derivative information contained as coefficient of linear manifold. | ||
Defaults to an array of ones the length of ``vars`` if empty. | ||
:type dual: list of float | ||
|
||
.. rubric:: Attributes | ||
|
||
:ivar real: float | ||
:ivar vars: sequence of str | ||
:ivar dual: 1d ndarray | ||
|
||
.. seealso:: | ||
:class:`~rateslib.dual.Dual2`: Dual number data type to perform second derivative automatic differentiation. | ||
|
||
.. rubric:: Examples | ||
|
||
.. ipython:: python | ||
from rateslib.dual import Dual, gradient | ||
def func(x, y): | ||
return 5 * x**2 + 10 * y**3 | ||
x = Dual(1.0, ["x"], []) | ||
y = Dual(1.0, ["y"], []) | ||
gradient(func(x,y), ["x", "y"]) | ||
.. rubric:: Methods Summary | ||
|
||
.. include:: rateslib.dual.Dual.vars_from.rst |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
.. vars_from | ||
========== | ||
.. .. currentmodule:: rateslib.dual | ||
.. py:method:: Dual.vars_from(other, real, vars, dual) | ||
Create a :class:`~rateslib.dual.Dual` object with ``vars`` linked with another. | ||
|
||
:param other: The other Dual from which to link vars. | ||
:type other: Dual | ||
|
||
:param real: The real coefficient of the dual number | ||
:type real: float, int | ||
|
||
:param vars: The labels of the variables for which to record derivatives. If empty, | ||
the dual number represents a constant, equivalent to a float. | ||
:type vars: tuple of str | ||
|
||
:param dual: First derivative information contained as coefficient of linear manifold. | ||
Defaults to an array of ones the length of ``vars`` if empty. | ||
:type dual: list of float | ||
|
||
:rtype: Dual | ||
|
||
.. rubric:: Notes | ||
|
||
Variables are constantly checked when operations are performed between dual numbers. In Rust the variables | ||
are stored within an ARC pointer. It is much faster to check the equivalence of two ARC pointers than if the elements | ||
within a variables Set, say, are the same *and* in the same order. This method exists to create dual data types | ||
with shared ARC pointers directly. | ||
|
||
.. ipython:: python | ||
from rateslib import Dual | ||
x1 = Dual(1.0, ["x"], []) | ||
x2 = Dual(2.0, ["x"], []) | ||
# x1 and x2 have the same variables (["x"]) but it is a different object | ||
x1.ptr_eq(x2) | ||
x3 = Dual.vars_from(x1, 3.0, ["x"], []) | ||
# x3 contains shared object variables with x1 | ||
x1.ptr_eq(x3) |
Oops, something went wrong.