• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

geo-ant / varpro / 16353761282

17 Jul 2025 07:07PM UTC coverage: 74.598% (-3.8%) from 78.389%
16353761282

Pull #50

github

web-flow
Merge cdf03495a into f242b6e14
Pull Request #50: Feature/documentation improvements 2

743 of 996 relevant lines covered (74.6%)

2609.82 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

80.0
/src/basis_function/detail.rs
1
//! This module provides blanket implementations for the BasisFunction trait for all callables
2
//! `Fn(&DVector<T>,T)->DVector<T>`
3
//! `Fn(&DVector<T>,T,T)->DVector<T>`
4
//! `Fn(&DVector<T>,T,T,T)->DVector<T>`
5
//! ...
6
//! and so on up to a maximum number of parameters. T is of nalgebra::Scalar type.
7
//! Currently the maximum number of scalar parameters is 10.
8

9
use crate::basis_function::BasisFunction;
10
use nalgebra::{DVector, Scalar};
11

12
// this is just hand implemented so we can see the pattern from the first implementation.
13
// After that we'll use a macro to get rid of some of the boilerplate
14
impl<ScalarType, Func> BasisFunction<ScalarType, ScalarType> for Func
15
where
16
    ScalarType: Scalar,
17
    Func: Fn(&DVector<ScalarType>, ScalarType) -> DVector<ScalarType> + Send + Sync,
18
{
19
    fn eval(&self, x: &DVector<ScalarType>, params: &[ScalarType]) -> DVector<ScalarType> {
1,809✔
20
        if params.len() != Self::ARGUMENT_COUNT {
1,809✔
21
            panic!(
1✔
22
                "Basisfunction expected {} arguments but the provided parameter slice has {} elements.",
1✔
23
                Self::ARGUMENT_COUNT,
×
24
                params.len()
2✔
25
            );
26
        }
27
        (self)(x, params[0].clone())
×
28
    }
29

30
    const ARGUMENT_COUNT: usize = 1;
31
}
32

33
// a helper macro set for counting
34
// cribbed (and slightly modified) from
35
// https://danielkeep.github.io/tlborm/book/blk-counting.html
36
// and here
37
// https://stackoverflow.com/questions/43143327/how-to-allow-optional-trailing-commas-in-macros
38
// the macro can be called with or without trailing comma
39
// i.e. these example expressions evaluate to true:
40
// count_args(1,2,3)==count_args(1,2,3,) == 3usize, as well as
41
// count_args(a,b)==count_args(a,b,)==2usize
42
//TODO (Performance): maybe see also daniel keep post (see above): recursion is not the most efficient way to implement this!
43
// however, the alternative solutions can't be used in constant expressions, iirc.
44
macro_rules! count_args {
45
    () => {0usize};
46
    ($_head:tt, $($tail:tt),*) => {1usize + count_args!($($tail,)*)}; //these overloads are there to allow with and w/o trailing comma syntax
47
    ($_head:tt, $($tail:tt,)*) => {1usize + count_args!($($tail,)*)};
48
}
49

50
// a macro to implement the BasisFunction trait on functions taking a number of arguments
51
// without having to copy paste a lot of boilerplate.
52
// shamelessly cribbed and modified from:
53
// https://github.com/actix/actix-web/blob/web-v3.3.2/src/handler.rs
54
macro_rules! basefunction_impl_helper ({$ScalarType:ident, $(($n:tt, $T:ident)),+} => {
55
    impl<$ScalarType, Func> BasisFunction<$ScalarType,($($T,)+)> for Func
56
    where Func: Fn(&DVector<$ScalarType>,$($T,)+) -> DVector<$ScalarType> + Send + Sync,
57
    $ScalarType : Scalar
58
    {
59
        fn eval(&self, x : &DVector<$ScalarType>,params : &[$ScalarType]) -> DVector<$ScalarType> {
96✔
60
            if params.len() != Self::ARGUMENT_COUNT {
96✔
61
                panic!("Basisfunction expected {} arguments but the provided parameter slice has {} elements.",Self::ARGUMENT_COUNT,params.len());
4✔
62
            }
63
            (&self)(
64
            x,
65
            $(params[$n].clone(),)+)
66
        }
67

68
        const ARGUMENT_COUNT :usize = count_args!($($T,)+);
69

70
    }
71
});
72

73
// this is the usage of the above macro to generate the required blanket implementations
74
// The trait bound on T is T: Scalar. It is important to continue the increasing sequence
75
// of numbers when extending the macro, because these numbers are used for indexing into
76
// the parameter slice
77
basefunction_impl_helper!(T, (0, T), (1, T));
78
basefunction_impl_helper!(T, (0, T), (1, T), (2, T));
79
basefunction_impl_helper!(T, (0, T), (1, T), (2, T), (3, T));
80
basefunction_impl_helper!(T, (0, T), (1, T), (2, T), (3, T), (4, T));
81
basefunction_impl_helper!(T, (0, T), (1, T), (2, T), (3, T), (4, T), (5, T));
82
basefunction_impl_helper!(T, (0, T), (1, T), (2, T), (3, T), (4, T), (5, T), (6, T));
83
basefunction_impl_helper!(
84
    T,
85
    (0, T),
86
    (1, T),
87
    (2, T),
88
    (3, T),
89
    (4, T),
90
    (5, T),
91
    (6, T),
92
    (7, T)
93
);
94
basefunction_impl_helper!(
95
    T,
96
    (0, T),
97
    (1, T),
98
    (2, T),
99
    (3, T),
100
    (4, T),
101
    (5, T),
102
    (6, T),
103
    (7, T),
104
    (8, T)
105
);
106
basefunction_impl_helper!(
107
    T,
108
    (0, T),
109
    (1, T),
110
    (2, T),
111
    (3, T),
112
    (4, T),
113
    (5, T),
114
    (6, T),
115
    (7, T),
116
    (8, T),
117
    (9, T)
118
); //10 parameter arguments
119
   //if more are implemented, add tests as well
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc