Skip to content

Commit 54d510e

Browse files
committed
eat(deep_causality_num): Introduce generic FloatOption trait
Introduces a new `FloatOption<F>` trait to abstract over float types ( `f32`, `f64`) and their `Option` variants. This trait provides a unified `to_option()` method that converts the implementing type into an `Option<F>`, treating `NaN` values as `None`. This change enables generic programming for algorithms that need to handle both concrete float values and optional/missing float values, reducing code duplication in dependent crates. Signed-off-by: Marvin Hansen <[email protected]>
1 parent 609b2ef commit 54d510e

File tree

17 files changed

+144
-18
lines changed

17 files changed

+144
-18
lines changed
File renamed without changes.
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* SPDX-License-Identifier: MIT
3+
* Copyright (c) "2025" . The DeepCausality Authors and Contributors. All Rights Reserved.
4+
*/
5+
6+
use crate::Float;
7+
use std::fmt::Debug;
8+
9+
/// A trait to abstract over float types (`f32`, `f64`) and their `Option` variants.
10+
///
11+
/// It provides a unified way to convert these types into an `Option<F>`
12+
/// where `F` is a type that implements the `Float` trait.
13+
pub trait FloatOption<F: Float>: Clone + Debug + Send + Sync + 'static {
14+
/// Converts the implementing type into an `Option<F>`.
15+
///
16+
/// - For a float type `F`, `NaN` is treated as a missing value (`None`).
17+
/// - For `Option<F>`, this handles `Some(NaN)` by returning `None`, and passes through `Some(value)` and `None`.
18+
fn to_option(&self) -> Option<F>;
19+
}
20+
21+
// Implementation for any `F` that implements `Float`.
22+
// This covers `f32` and `f64`.
23+
impl<F> FloatOption<F> for F
24+
where
25+
F: Float + Debug + Send + Sync + 'static,
26+
{
27+
fn to_option(&self) -> Option<F> {
28+
if self.is_nan() { None } else { Some(*self) }
29+
}
30+
}
31+
32+
// Implementation for `Option<F>`.
33+
// This covers `Option<f32>` and `Option<f64>`.
34+
impl<F> FloatOption<F> for Option<F>
35+
where
36+
F: Float + Debug + Send + Sync + 'static,
37+
{
38+
fn to_option(&self) -> Option<F> {
39+
self.and_then(|value| if value.is_nan() { None } else { Some(value) })
40+
}
41+
}

deep_causality_num/src/lib.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
mod cast;
2+
pub mod float;
3+
mod float_option;
24
mod identity;
5+
pub mod num;
36
mod ops;
4-
mod types;
57

68
pub use crate::cast::as_primitive::AsPrimitive;
79
pub use crate::cast::as_scalar::float_as_scalar_impl::FloatAsScalar;
@@ -10,8 +12,9 @@ pub use crate::cast::from_primitive::FromPrimitive;
1012
pub use crate::cast::num_cast::NumCast;
1113
pub use crate::cast::to_float::{FloatFromInt, IntoFloat};
1214
pub use crate::cast::to_primitive::ToPrimitive;
15+
pub use crate::float::Float;
16+
pub use crate::float_option::FloatOption;
1317
pub use crate::identity::one::{ConstOne, One};
1418
pub use crate::identity::zero::{ConstZero, Zero};
19+
pub use crate::num::Num;
1520
pub use crate::ops::num_ops::*;
16-
pub use crate::types::float::Float;
17-
pub use crate::types::num::Num;
File renamed without changes.

deep_causality_num/src/types/mod.rs

Lines changed: 0 additions & 6 deletions
This file was deleted.

deep_causality_num/tests/BUILD.bazel

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,22 @@ rust_test_suite(
1818
],
1919
)
2020

21+
rust_test_suite(
22+
name = "float",
23+
srcs = glob([
24+
"float/*_tests.rs",
25+
"types/num/*_tests.rs",
26+
]),
27+
tags = [
28+
"unit-test",
29+
],
30+
visibility = ["//visibility:public"],
31+
deps = [
32+
# Crate to test
33+
"//deep_causality_num",
34+
],
35+
)
36+
2137
rust_test_suite(
2238
name = "identity",
2339
srcs = glob([
@@ -34,9 +50,9 @@ rust_test_suite(
3450
)
3551

3652
rust_test_suite(
37-
name = "ops",
53+
name = "num",
3854
srcs = glob([
39-
"ops/*_tests.rs",
55+
"num/*_tests.rs",
4056
]),
4157
tags = [
4258
"unit-test",
@@ -49,10 +65,9 @@ rust_test_suite(
4965
)
5066

5167
rust_test_suite(
52-
name = "types",
68+
name = "ops",
5369
srcs = glob([
54-
"types/float/*_tests.rs",
55-
"types/num/*_tests.rs",
70+
"ops/*_tests.rs",
5671
]),
5772
tags = [
5873
"unit-test",
@@ -62,4 +77,4 @@ rust_test_suite(
6277
# Crate to test
6378
"//deep_causality_num",
6479
],
65-
)
80+
)

0 commit comments

Comments
 (0)