1pub type Node = f64;
14pub type Weight = f64;
16
17#[doc(hidden)]
22#[macro_export]
23macro_rules! __impl_node_weight_rule {
24 (
25 $quadrature_rule:ident,
27 $quadrature_rule_nodes:ident,
29 $quadrature_rule_weights:ident,
31 $quadrature_rule_iter:ident,
34 $quadrature_rule_into_iter:ident
36 ) => {
37 impl ::core::iter::IntoIterator for $quadrature_rule {
46 type IntoIter = $quadrature_rule_into_iter;
47 type Item = ($crate::Node, $crate::Weight);
48 #[inline]
49 fn into_iter(self) -> Self::IntoIter {
50 $quadrature_rule_into_iter::new(self.node_weight_pairs.into_iter())
51 }
52 }
53
54 impl<'a> ::core::iter::IntoIterator for &'a $quadrature_rule {
61 type IntoIter = $quadrature_rule_iter<'a>;
62 type Item = &'a ($crate::Node, $crate::Weight);
63 #[inline]
64 fn into_iter(self) -> Self::IntoIter {
65 $quadrature_rule_iter::new(self.node_weight_pairs.iter())
66 }
67 }
68
69 impl $quadrature_rule {
70 #[inline]
72 pub fn nodes(&self) -> $quadrature_rule_nodes<'_> {
73 $quadrature_rule_nodes::new(self.node_weight_pairs.iter().map(|p| &p.0))
74 }
75
76 #[inline]
78 pub fn weights(&self) -> $quadrature_rule_weights<'_> {
79 $quadrature_rule_weights::new(self.node_weight_pairs.iter().map(|p| &p.1))
80 }
81
82 #[inline]
84 pub fn iter(&self) -> $quadrature_rule_iter<'_> {
85 $quadrature_rule_iter::new(self.node_weight_pairs.iter())
86 }
87
88 #[inline]
90 pub fn as_node_weight_pairs(&self) -> &[($crate::Node, $crate::Weight)] {
91 &self.node_weight_pairs
92 }
93
94 #[inline]
98 #[must_use = "`self` will be dropped if the result is not used"]
99 pub fn into_node_weight_pairs(self) -> ::std::vec::Vec<($crate::Node, $crate::Weight)> {
100 self.node_weight_pairs
101 }
102
103 #[inline]
105 pub fn degree(&self) -> ::core::primitive::usize {
106 self.node_weight_pairs.len()
107 }
108 }
109
110 #[derive(::core::fmt::Debug, ::core::clone::Clone)]
114 #[must_use = "iterators are lazy and do nothing unless consumed"]
115 pub struct $quadrature_rule_nodes<'a>(
116 ::std::iter::Map<
119 ::core::slice::Iter<'a, ($crate::Node, $crate::Weight)>,
120 fn(&'a ($crate::Node, $crate::Weight)) -> &'a $crate::Node,
121 >,
122 );
123
124 impl<'a> $quadrature_rule_nodes<'a> {
125 #[inline]
126 const fn new(
127 iter_map: ::std::iter::Map<
128 ::core::slice::Iter<'a, ($crate::Node, $crate::Weight)>,
129 fn(&'a ($crate::Node, $crate::Weight)) -> &'a $crate::Node,
130 >,
131 ) -> Self {
132 Self(iter_map)
133 }
134 }
135
136 $crate::__impl_slice_iterator_newtype_traits!{$quadrature_rule_nodes<'a>, &'a $crate::Node}
137
138 #[derive(::core::fmt::Debug, ::core::clone::Clone)]
144 #[must_use = "iterators are lazy and do nothing unless consumed"]
145 pub struct $quadrature_rule_weights<'a>(
146 ::std::iter::Map<
148 ::core::slice::Iter<'a, ($crate::Node, $crate::Weight)>,
149 fn(&'a ($crate::Node, $crate::Weight)) -> &'a $crate::Weight,
150 >,
151 );
152
153 impl<'a> $quadrature_rule_weights<'a> {
154 #[inline]
155 const fn new(
156 iter_map: ::std::iter::Map<
157 ::core::slice::Iter<'a, ($crate::Node, $crate::Weight)>,
158 fn(&'a ($crate::Node, $crate::Weight)) -> &'a $crate::Weight,
159 >,
160 ) -> Self {
161 Self(iter_map)
162 }
163 }
164
165 $crate::__impl_slice_iterator_newtype_traits!{$quadrature_rule_weights<'a>, &'a $crate::Weight}
166
167 #[derive(::core::fmt::Debug, ::core::clone::Clone)]
175 #[must_use = "iterators are lazy and do nothing unless consumed"]
176 pub struct $quadrature_rule_iter<'a>(
177 ::core::slice::Iter<'a, ($crate::Node, $crate::Weight)>,
178 );
179
180 impl<'a> $quadrature_rule_iter<'a> {
181 #[inline]
182 const fn new(
183 node_weight_pairs: ::core::slice::Iter<'a, ($crate::Node, $crate::Weight)>,
184 ) -> Self {
185 Self(node_weight_pairs)
186 }
187
188 #[inline]
192 pub fn as_slice(&self) -> &'a [($crate::Node, $crate::Weight)] {
193 self.0.as_slice()
194 }
195 }
196
197 impl<'a> ::core::convert::AsRef<[($crate::Node, $crate::Weight)]>
198 for $quadrature_rule_iter<'a>
199 {
200 #[inline]
201 fn as_ref(&self) -> &[($crate::Node, $crate::Weight)] {
202 self.0.as_ref()
203 }
204 }
205
206 $crate::__impl_slice_iterator_newtype_traits!{$quadrature_rule_iter<'a>, &'a ($crate::Node, $crate::Weight)}
207
208 #[derive(::core::fmt::Debug, ::core::clone::Clone)]
216 #[must_use = "iterators are lazy and do nothing unless consumed"]
217 pub struct $quadrature_rule_into_iter(::std::vec::IntoIter<($crate::Node, $crate::Weight)>);
218
219 impl $quadrature_rule_into_iter {
220 #[inline]
221 const fn new(
222 node_weight_pairs: ::std::vec::IntoIter<($crate::Node, $crate::Weight)>,
223 ) -> Self {
224 Self(node_weight_pairs)
225 }
226
227 #[inline]
231 pub fn as_slice(&self) -> &[($crate::Node, $crate::Weight)] {
232 self.0.as_slice()
233 }
234 }
235
236 impl ::core::convert::AsRef<[($crate::Node, $crate::Weight)]>
237 for $quadrature_rule_into_iter
238 {
239 #[inline]
240 fn as_ref(&self) -> &[($crate::Node, $crate::Weight)] {
241 self.0.as_ref()
242 }
243 }
244
245 $crate::__impl_slice_iterator_newtype_traits!{$quadrature_rule_into_iter, ($crate::Node, $crate::Weight)}
246
247 };
249}
250
251#[macro_export]
255#[doc(hidden)]
256macro_rules! __impl_slice_iterator_newtype_traits {
257 ($iterator:ident$(<$a:lifetime>)?, $item:ty) => {
258 impl$(<$a>)? ::core::iter::Iterator for $iterator<$($a)?> {
259 type Item = $item;
260 #[inline]
261 fn next(&mut self) -> ::core::option::Option<Self::Item> {
262 self.0.next()
263 }
264
265 #[inline]
266 fn size_hint(&self) -> (::core::primitive::usize, ::core::option::Option<::core::primitive::usize>) {
267 self.0.size_hint()
268 }
269
270 #[inline]
276 fn nth(&mut self, index: ::core::primitive::usize) -> ::core::option::Option<Self::Item> {
277 self.0.nth(index)
278 }
279
280 #[inline]
281 fn count(self) -> ::core::primitive::usize {
282 self.0.count()
283 }
284
285 #[inline]
286 fn last(mut self) -> ::core::option::Option<Self::Item> {
287 self.0.next_back()
288 }
289 }
290
291 impl$(<$a>)? ::core::iter::DoubleEndedIterator for $iterator$(<$a>)? {
292 #[inline]
293 fn next_back(&mut self) -> ::core::option::Option<Self::Item> {
294 self.0.next_back()
295 }
296
297 #[inline]
298 fn nth_back(&mut self, n: ::core::primitive::usize) -> ::core::option::Option<Self::Item> {
299 self.0.nth_back(n)
300 }
301 }
302
303 impl$(<$a>)? ::core::iter::ExactSizeIterator for $iterator$(<$a>)? {
304 #[inline]
305 fn len(&self) -> ::core::primitive::usize {
306 self.0.len()
307 }
308 }
309 impl$(<$a>)? ::core::iter::FusedIterator for $iterator$(<$a>)? {}
310 };
311}
312
313#[macro_export]
318#[doc(hidden)]
319macro_rules! __impl_node_rule {
320 ($quadrature_rule:ident, $quadrature_rule_iter:ident, $quadrature_rule_into_iter:ident) => {
321 impl ::core::iter::IntoIterator for $quadrature_rule {
326 type Item = $crate::Node;
327 type IntoIter = $quadrature_rule_into_iter;
328 #[inline]
329 fn into_iter(self) -> Self::IntoIter {
330 $quadrature_rule_into_iter::new(self.nodes.into_iter())
331 }
332 }
333
334 impl<'a> ::core::iter::IntoIterator for &'a $quadrature_rule {
341 type IntoIter = $quadrature_rule_iter<'a>;
342 type Item = &'a $crate::Node;
343 #[inline]
344 fn into_iter(self) -> Self::IntoIter {
345 $quadrature_rule_iter::new(self.nodes.iter())
346 }
347 }
348
349 impl $quadrature_rule {
350 #[inline]
352 pub fn iter(&self) -> $quadrature_rule_iter<'_> {
353 $quadrature_rule_iter::new(self.nodes.iter())
354 }
355
356 #[inline]
358 pub fn as_nodes(&self) -> &[$crate::Node] {
359 &self.nodes
360 }
361
362 #[inline]
366 #[must_use = "`self` will be dropped if the result is not used"]
367 pub fn into_nodes(self) -> Vec<$crate::Node> {
368 self.nodes
369 }
370
371 #[inline]
373 pub fn degree(&self) -> usize {
374 self.nodes.len()
375 }
376 }
377
378 #[derive(Debug, Clone)]
382 #[must_use = "iterators are lazy and do nothing unless consumed"]
383 pub struct $quadrature_rule_iter<'a>(::core::slice::Iter<'a, $crate::Node>);
384
385 impl<'a> $quadrature_rule_iter<'a> {
386 #[inline]
387 const fn new(iter: ::core::slice::Iter<'a, $crate::Node>) -> Self {
388 Self(iter)
389 }
390
391 #[inline]
395 pub fn as_slice(&self) -> &'a [$crate::Node] {
396 self.0.as_slice()
397 }
398 }
399
400 impl<'a> ::core::convert::AsRef<[$crate::Node]> for $quadrature_rule_iter<'a> {
401 #[inline]
402 fn as_ref(&self) -> &[$crate::Node] {
403 self.0.as_ref()
404 }
405 }
406
407 $crate::__impl_slice_iterator_newtype_traits! {$quadrature_rule_iter<'a>, &'a $crate::Node}
408
409 #[derive(::core::fmt::Debug, ::core::clone::Clone)]
417 #[must_use = "iterators are lazy and do nothing unless consumed"]
418 pub struct $quadrature_rule_into_iter(::std::vec::IntoIter<$crate::Node>);
419
420 impl $quadrature_rule_into_iter {
421 #[inline]
422 const fn new(iter: ::std::vec::IntoIter<$crate::Node>) -> Self {
423 Self(iter)
424 }
425
426 #[inline]
430 pub fn as_slice(&self) -> &[$crate::Node] {
431 self.0.as_slice()
432 }
433 }
434
435 impl ::core::convert::AsRef<[$crate::Node]> for $quadrature_rule_into_iter {
436 #[inline]
437 fn as_ref(&self) -> &[$crate::Node] {
438 self.0.as_ref()
439 }
440 }
441
442 $crate::__impl_slice_iterator_newtype_traits! {$quadrature_rule_into_iter, $crate::Node}
443
444 };
446}
447
448#[cfg(test)]
449mod tests {
450 use super::*;
451 use core::fmt;
452 use std::backtrace::Backtrace;
453
454 #[derive(Debug, Clone, PartialEq)]
455 #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
456 pub struct MockQuadrature {
457 node_weight_pairs: Vec<(Node, Weight)>,
458 }
459
460 #[derive(Debug)]
461 pub struct MockQuadratureError(Backtrace);
462
463 impl MockQuadratureError {
464 pub fn backtrace(&self) -> &Backtrace {
465 &self.0
466 }
467 }
468
469 impl fmt::Display for MockQuadratureError {
470 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
471 write!(f, "wrong! bad! T_T")
472 }
473 }
474
475 impl std::error::Error for MockQuadratureError {}
476
477 impl MockQuadrature {
478 pub fn new(deg: usize) -> Result<Self, MockQuadratureError> {
479 if deg < 1 {
480 return Err(MockQuadratureError(Backtrace::capture()));
481 }
482
483 Ok(Self {
484 node_weight_pairs: (0..deg).map(|d| (d as f64, 1.0)).collect(),
485 })
486 }
487
488 pub fn integrate<F>(&self, a: f64, b: f64, integrand: F) -> f64
489 where
490 F: Fn(f64) -> f64,
491 {
492 let rect_width = (b - a) / self.node_weight_pairs.len() as f64;
493 let result: f64 = self
494 .node_weight_pairs
495 .iter()
496 .map(|(x_val, w_val)| integrand(a + rect_width * (0.5 + x_val)) * w_val)
497 .sum();
498 result * rect_width
499 }
500 }
501
502 __impl_node_weight_rule! {MockQuadrature, MockQuadratureNodes, MockQuadratureWeights, MockQuadratureIter, MockQuadratureIntoIter}
503
504 #[test]
505 fn test_macro_implementation() {
506 let quad = MockQuadrature::new(5).unwrap();
507 assert_eq!(quad.integrate(0.0, 1.0, |x| x), 0.5);
508
509 assert_eq!(quad.nodes().count(), 5);
511 assert_eq!(quad.weights().count(), 5);
512 assert_eq!(quad.iter().count(), 5);
513 assert_eq!(quad.as_node_weight_pairs().len(), 5);
514
515 let vec: Vec<(Node, Weight)> = quad.clone().into_iter().collect();
517 assert_eq!(vec.len(), 5);
518
519 let pairs = quad.clone().into_node_weight_pairs();
521 assert_eq!(pairs.len(), 5);
522
523 assert_eq!(quad.degree(), 5);
525
526 let mut quad_iter = (&quad).into_iter();
528 assert_eq!(quad_iter.next().unwrap().0, 0.0);
529 assert_eq!(quad_iter.next().unwrap().0, 1.0);
530
531 let quad_iter = (&quad).into_iter();
532 assert_eq!(quad_iter.size_hint(), (5, Some(5)));
533
534 let mut quad_iter = (&quad).into_iter();
535 assert_eq!(quad_iter.nth(2).unwrap().0, 2.0);
536
537 let quad_iter = (&quad).into_iter();
538 assert_eq!(quad_iter.count(), 5);
539
540 let quad_iter = (&quad).into_iter();
541 assert_eq!(quad_iter.last().unwrap().0, 4.0);
542
543 let mut quad_iter = (&quad).into_iter();
544 assert_eq!(quad_iter.next_back().unwrap().0, 4.0);
545
546 let mut quad_iter = (&quad).into_iter();
547 assert_eq!(quad_iter.nth_back(1).unwrap().0, 3.0);
548
549 let quad_iter = (&quad).into_iter();
550 assert_eq!(quad_iter.len(), 5);
551
552 let quad_slice = (&quad).into_iter().as_slice();
554 assert_eq!(quad_slice.len(), 5);
555 assert_eq!(quad_slice[2].0, 2.0);
556
557 let quad_iter = (&quad).into_iter();
559 let quad_ref = quad_iter.as_ref();
560 assert_eq!(quad_ref.len(), 5);
561 assert_eq!(quad_ref[2].0, 2.0);
562 }
563}