Skip to content

Commit c97f084

Browse files
authored
Add serialization and deserialization with serde for scalar dual numbers (#74)
1 parent 6340132 commit c97f084

8 files changed

+88
-1
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
66

77
## [Unreleased]
88

9+
## [0.9.1] - 2024-04-15
10+
### Added
11+
- Added `serde` feature that enables serialization and deserialization of all scalar dual numbers. [#74](https://github.com/itt-ustutt/num-dual/pull/74)
12+
913
## [0.9.0] - 2024-04-11
1014
### Packaging
1115
- Updated `pyo3` and `numpy` dependencies to 0.21 and adapted to the new `Bound` API.

Cargo.toml

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "num-dual"
3-
version = "0.9.0"
3+
version = "0.9.1"
44
authors = ["Gernot Bauer <[email protected]>",
55
"Philipp Rehner <[email protected]>"]
66
edition = "2021"
@@ -24,6 +24,7 @@ ndarray = { version = "0.15", optional = true }
2424
numpy = { version = "0.21", optional = true }
2525
approx = "0.5"
2626
simba = "0.8"
27+
serde = { version = "1.0", features = ["derive"], optional = true }
2728

2829
[profile.release]
2930
lto = true
@@ -36,6 +37,7 @@ linalg = ["ndarray"]
3637

3738
[dev-dependencies]
3839
criterion = "0.5"
40+
serde_json = "1.0"
3941

4042
[[bench]]
4143
name = "benchmark"

src/dual.rs

+4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ use crate::{DualNum, DualNumFloat};
22
use approx::{AbsDiffEq, RelativeEq, UlpsEq};
33
use nalgebra::*;
44
use num_traits::{Float, FloatConst, FromPrimitive, Inv, Num, One, Signed, Zero};
5+
#[cfg(feature = "serde")]
6+
use serde::{Deserialize, Serialize};
57
use std::convert::Infallible;
68
use std::fmt;
79
use std::iter::{Product, Sum};
@@ -12,11 +14,13 @@ use std::ops::{
1214

1315
/// A scalar dual number for the calculations of first derivatives.
1416
#[derive(Copy, Clone, Debug)]
17+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1518
pub struct Dual<T: DualNum<F>, F> {
1619
/// Real part of the dual number
1720
pub re: T,
1821
/// Derivative part of the dual number
1922
pub eps: T,
23+
#[cfg_attr(feature = "serde", serde(skip))]
2024
f: PhantomData<F>,
2125
}
2226

src/dual2.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use crate::{DualNum, DualNumFloat};
22
use num_traits::{Float, FloatConst, FromPrimitive, Inv, Num, One, Signed, Zero};
3+
#[cfg(feature = "serde")]
4+
use serde::{Deserialize, Serialize};
35
use std::convert::Infallible;
46
use std::fmt;
57
use std::iter::{Product, Sum};
@@ -10,13 +12,15 @@ use std::ops::{
1012

1113
/// A scalar second order dual number for the calculation of second derivatives.
1214
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
15+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1316
pub struct Dual2<T: DualNum<F>, F> {
1417
/// Real part of the second order dual number
1518
pub re: T,
1619
/// First derivative part of the second order dual number
1720
pub v1: T,
1821
/// Second derivative part of the second order dual number
1922
pub v2: T,
23+
#[cfg_attr(feature = "serde", serde(skip))]
2024
f: PhantomData<F>,
2125
}
2226

src/dual3.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use crate::{DualNum, DualNumFloat};
22
use num_traits::{Float, FloatConst, FromPrimitive, Inv, Num, One, Signed, Zero};
3+
#[cfg(feature = "serde")]
4+
use serde::{Deserialize, Serialize};
35
use std::convert::Infallible;
46
use std::fmt;
57
use std::iter::{Product, Sum};
@@ -8,6 +10,7 @@ use std::ops::*;
810

911
/// A scalar third order dual number for the calculation of third derivatives.
1012
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
13+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1114
pub struct Dual3<T, F = T> {
1215
/// Real part of the third order dual number
1316
pub re: T,
@@ -17,6 +20,7 @@ pub struct Dual3<T, F = T> {
1720
pub v2: T,
1821
/// Third derivative part of the third order dual number
1922
pub v3: T,
23+
#[cfg_attr(feature = "serde", serde(skip))]
2024
f: PhantomData<F>,
2125
}
2226

src/hyperdual.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use crate::{DualNum, DualNumFloat};
22
use num_traits::{Float, FloatConst, FromPrimitive, Inv, Num, One, Signed, Zero};
3+
#[cfg(feature = "serde")]
4+
use serde::{Deserialize, Serialize};
35
use std::convert::Infallible;
46
use std::fmt;
57
use std::iter::{Product, Sum};
@@ -10,6 +12,7 @@ use std::ops::{
1012

1113
/// A scalar hyper-dual number for the calculation of second partial derivatives.
1214
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
15+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1316
pub struct HyperDual<T: DualNum<F>, F> {
1417
/// Real part of the hyper-dual number
1518
pub re: T,
@@ -19,6 +22,7 @@ pub struct HyperDual<T: DualNum<F>, F> {
1922
pub eps2: T,
2023
/// Second partial derivative part of the hyper-dual number
2124
pub eps1eps2: T,
25+
#[cfg_attr(feature = "serde", serde(skip))]
2226
f: PhantomData<F>,
2327
}
2428

src/hyperhyperdual.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use crate::{DualNum, DualNumFloat};
22
use num_traits::{Float, FloatConst, FromPrimitive, Inv, Num, One, Signed, Zero};
3+
#[cfg(feature = "serde")]
4+
use serde::{Deserialize, Serialize};
35
use std::convert::Infallible;
46
use std::fmt;
57
use std::iter::{Product, Sum};
@@ -8,6 +10,7 @@ use std::ops::*;
810

911
/// A scalar hyper-hyper-dual number for the calculation of third partial derivatives.
1012
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
13+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1114
pub struct HyperHyperDual<T, F = T> {
1215
/// Real part of the hyper-hyper-dual number
1316
pub re: T,
@@ -25,6 +28,7 @@ pub struct HyperHyperDual<T, F = T> {
2528
pub eps2eps3: T,
2629
/// Third partial derivative part of the hyper-hyper-dual number
2730
pub eps1eps2eps3: T,
31+
#[cfg_attr(feature = "serde", serde(skip))]
2832
f: PhantomData<F>,
2933
}
3034

tests/test_serde.rs

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
#![cfg(feature = "serde")]
2+
use num_dual::*;
3+
use serde_json::Error;
4+
5+
#[test]
6+
fn test_serde_dual() -> Result<(), Error> {
7+
let x = Dual::from_re(2.0).derivative();
8+
let s = serde_json::to_string(&x)?;
9+
println!("{s}");
10+
let y: Dual64 = serde_json::from_str(&s)?;
11+
println!("{y}");
12+
assert_eq!(x, y);
13+
Ok(())
14+
}
15+
16+
#[test]
17+
fn test_serde_dual2() -> Result<(), Error> {
18+
let x = Dual2::from_re(2.0).derivative();
19+
let s = serde_json::to_string(&x)?;
20+
println!("{s}");
21+
let y: Dual2_64 = serde_json::from_str(&s)?;
22+
println!("{y}");
23+
assert_eq!(x, y);
24+
Ok(())
25+
}
26+
27+
#[test]
28+
fn test_serde_dual3() -> Result<(), Error> {
29+
let x = Dual3::from_re(2.0).derivative();
30+
let s = serde_json::to_string(&x)?;
31+
println!("{s}");
32+
let y: Dual3_64 = serde_json::from_str(&s)?;
33+
println!("{y}");
34+
assert_eq!(x, y);
35+
Ok(())
36+
}
37+
38+
#[test]
39+
fn test_serde_hyperdual() -> Result<(), Error> {
40+
let x = HyperDual::from_re(2.0).derivative1().derivative2();
41+
let s = serde_json::to_string(&x)?;
42+
println!("{s}");
43+
let y: HyperDual64 = serde_json::from_str(&s)?;
44+
println!("{y}");
45+
assert_eq!(x, y);
46+
Ok(())
47+
}
48+
49+
#[test]
50+
fn test_serde_hyperhyperdual() -> Result<(), Error> {
51+
let x = HyperHyperDual::from_re(2.0)
52+
.derivative1()
53+
.derivative2()
54+
.derivative3();
55+
let s = serde_json::to_string(&x)?;
56+
println!("{s}");
57+
let y: HyperHyperDual64 = serde_json::from_str(&s)?;
58+
println!("{y}");
59+
assert_eq!(x, y);
60+
Ok(())
61+
}

0 commit comments

Comments
 (0)