1use std::time::Instant;
10
11use crate::BackendError;
12
13pub const BASIS_POINTS_DENOMINATOR: u32 = 10_000;
15
16#[derive(Clone, Copy, Debug, Eq, PartialEq)]
22pub struct BackendNumericPolicy {
23 backend: &'static str,
24}
25
26impl BackendNumericPolicy {
27 #[must_use]
29 pub const fn new(backend: &'static str) -> Self {
30 Self { backend }
31 }
32
33 #[must_use]
35 pub const fn backend(self) -> &'static str {
36 self.backend
37 }
38
39 pub fn usize_to_u64(self, value: usize, label: &str) -> Result<u64, BackendError> {
45 usize_to_u64(value, label, self.backend)
46 }
47
48 pub fn u128_to_u64(self, value: u128, label: &str) -> Result<u64, BackendError> {
54 u128_to_u64(value, label, self.backend)
55 }
56
57 pub fn elapsed_nanos_u64(self, started: Instant, label: &str) -> Result<u64, BackendError> {
63 elapsed_nanos_u64(started, label, self.backend)
64 }
65
66 pub fn rounded_f64_to_u64(self, value: f64, label: &str) -> Result<u64, BackendError> {
72 rounded_f64_to_u64(value, label, self.backend)
73 }
74
75 #[must_use]
77 pub fn ratio_basis_points_u64(
78 self,
79 part: u64,
80 whole: u64,
81 denominator_zero_value: u32,
82 label: &str,
83 ) -> u32 {
84 ratio_basis_points_u64(part, whole, denominator_zero_value, label, self.backend)
85 }
86
87 #[must_use]
89 pub fn ratio_basis_points_u64_wide(
90 self,
91 part: u64,
92 whole: u64,
93 denominator_zero_value: u64,
94 label: &str,
95 ) -> u64 {
96 ratio_basis_points_u64_wide(part, whole, denominator_zero_value, label, self.backend)
97 }
98
99 #[must_use]
101 pub fn ratio_parts_per_million_u64(
102 self,
103 part: u64,
104 whole: u64,
105 denominator_zero_value: u32,
106 label: &str,
107 ) -> u32 {
108 ratio_parts_per_million_u64(part, whole, denominator_zero_value, label, self.backend)
109 }
110
111 #[must_use]
113 pub fn compose_basis_points_u32(self, left: u32, right: u32, label: &str) -> u32 {
114 compose_basis_points_u32(left, right, label, self.backend)
115 }
116
117 #[must_use]
119 pub fn scale_u64_by_basis_points_round_clamped(
120 self,
121 base: u64,
122 scale_bps: u32,
123 zero_scale_value: u64,
124 max_scale_bps: u32,
125 label: &str,
126 ) -> u64 {
127 scale_u64_by_basis_points_round_clamped(
128 base,
129 scale_bps,
130 zero_scale_value,
131 max_scale_bps,
132 label,
133 self.backend,
134 )
135 }
136
137 #[must_use]
139 pub fn scale_u64_by_basis_points_floor_min(
140 self,
141 base: u64,
142 scale_bps: u32,
143 min_value: u64,
144 label: &str,
145 ) -> u64 {
146 scale_u64_by_basis_points_floor_min(base, scale_bps, min_value, label, self.backend)
147 }
148
149 #[must_use]
151 pub fn finite_f64_to_u32_trunc(self, value: f64, label: &str) -> u32 {
152 finite_f64_to_u32_trunc(value, label, self.backend)
153 }
154
155 #[must_use]
157 pub fn finite_f64_to_u32_round(self, value: f64, label: &str) -> u32 {
158 finite_f64_to_u32_round(value, label, self.backend)
159 }
160
161 #[must_use]
163 pub fn finite_f64_ratio_basis_points_trunc(
164 self,
165 numerator: f64,
166 denominator: f64,
167 invalid_numerator_value: u32,
168 invalid_denominator_value: u32,
169 label: &str,
170 ) -> u32 {
171 finite_f64_ratio_basis_points_trunc(
172 numerator,
173 denominator,
174 invalid_numerator_value,
175 invalid_denominator_value,
176 label,
177 self.backend,
178 )
179 }
180
181 #[must_use]
183 pub fn finite_f64_ratio_basis_points_round(
184 self,
185 numerator: f64,
186 denominator: f64,
187 invalid_numerator_value: u32,
188 invalid_denominator_value: u32,
189 label: &str,
190 ) -> u32 {
191 finite_f64_ratio_basis_points_round(
192 numerator,
193 denominator,
194 invalid_numerator_value,
195 invalid_denominator_value,
196 label,
197 self.backend,
198 )
199 }
200
201 #[must_use]
203 pub fn finite_f64_unit_basis_points_trunc(
204 self,
205 value: f64,
206 invalid_value: u32,
207 label: &str,
208 ) -> u32 {
209 finite_f64_unit_basis_points_trunc(value, invalid_value, label, self.backend)
210 }
211
212 #[must_use]
215 pub fn checked_ceil_div_u64(self, value: u64, divisor: u64) -> Option<u64> {
216 checked_ceil_div_u64(value, divisor)
217 }
218
219 #[must_use]
221 pub fn checked_dim_product_u64(self, dims: [u32; 3]) -> Option<u64> {
222 checked_dim_product_u64(dims)
223 }
224
225 #[must_use]
227 pub fn checked_dim_product_u32(self, dims: [u32; 3]) -> Option<u32> {
228 checked_dim_product_u32(dims)
229 }
230
231 pub fn align_up_u64(
237 self,
238 value: u64,
239 alignment: u64,
240 min_value: u64,
241 label: &str,
242 ) -> Result<u64, BackendError> {
243 align_up_u64(value, alignment, min_value, label, self.backend)
244 }
245
246 pub fn align_up_usize(
252 self,
253 value: usize,
254 alignment: usize,
255 min_value: usize,
256 label: &str,
257 ) -> Result<usize, BackendError> {
258 align_up_usize(value, alignment, min_value, label, self.backend)
259 }
260}
261
262pub fn usize_to_u64(value: usize, label: &str, backend: &str) -> Result<u64, BackendError> {
268 u64::try_from(value).map_err(|source| BackendError::InvalidProgram {
269 fix: format!(
270 "Fix: {backend} {label} cannot fit u64: {source}; split the workload before crossing the host/device boundary."
271 ),
272 })
273}
274
275pub fn u128_to_u64(value: u128, label: &str, backend: &str) -> Result<u64, BackendError> {
281 u64::try_from(value).map_err(|source| BackendError::InvalidProgram {
282 fix: format!(
283 "Fix: {backend} {label} cannot fit u64: {source}; split the dispatch before telemetry overflows."
284 ),
285 })
286}
287
288pub fn elapsed_nanos_u64(
294 started: Instant,
295 label: &str,
296 backend: &str,
297) -> Result<u64, BackendError> {
298 u128_to_u64(started.elapsed().as_nanos(), label, backend)
299}
300
301pub fn rounded_f64_to_u64(value: f64, label: &str, backend: &str) -> Result<u64, BackendError> {
307 let rounded = value.round();
308 if !rounded.is_finite() || rounded < 0.0 || rounded > u64::MAX as f64 {
309 return Err(BackendError::InvalidProgram {
310 fix: format!(
311 "Fix: {backend} {label} value {value} cannot fit u64 after rounding; inspect device timing and split the dispatch before telemetry overflows."
312 ),
313 });
314 }
315 u64::try_from(rounded as u128).map_err(|source| BackendError::InvalidProgram {
316 fix: format!(
317 "Fix: {backend} {label} rounded value cannot fit u64: {source}; inspect device timing and split the dispatch before telemetry overflows."
318 ),
319 })
320}
321
322#[must_use]
329pub fn ratio_basis_points_u64(
330 part: u64,
331 whole: u64,
332 denominator_zero_value: u32,
333 label: &str,
334 backend: &str,
335) -> u32 {
336 let value = ratio_basis_points_u64_wide(
337 part,
338 whole,
339 u64::from(denominator_zero_value),
340 label,
341 backend,
342 );
343 if value > u64::from(u32::MAX) {
344 tracing::error!(
345 "{backend} {label} basis-points value exceeded u32. Fix: shard or normalize the telemetry domain before release-path planning."
346 );
347 return u32::MAX;
348 }
349 value as u32
350}
351
352#[must_use]
355pub fn ratio_basis_points_u64_wide(
356 part: u64,
357 whole: u64,
358 denominator_zero_value: u64,
359 label: &str,
360 backend: &str,
361) -> u64 {
362 if whole == 0 {
363 return denominator_zero_value;
364 }
365 let value = (u128::from(part) * u128::from(BASIS_POINTS_DENOMINATOR)) / u128::from(whole);
366 if value > u128::from(u64::MAX) {
367 tracing::error!(
368 "{backend} {label} basis-points value exceeded u64. Fix: shard or normalize the telemetry domain before release-path planning."
369 );
370 return u64::MAX;
371 }
372 value as u64
373}
374
375#[must_use]
378pub fn ratio_parts_per_million_u64(
379 part: u64,
380 whole: u64,
381 denominator_zero_value: u32,
382 label: &str,
383 backend: &str,
384) -> u32 {
385 if whole == 0 {
386 return denominator_zero_value;
387 }
388 let value = (u128::from(part) * 1_000_000) / u128::from(whole);
389 if value > u128::from(u32::MAX) {
390 tracing::error!(
391 "{backend} {label} parts-per-million value exceeded u32. Fix: shard or normalize telemetry before release-path planning."
392 );
393 return u32::MAX;
394 }
395 value as u32
396}
397
398#[must_use]
401pub fn compose_basis_points_u32(left: u32, right: u32, label: &str, backend: &str) -> u32 {
402 let value = (u128::from(left) * u128::from(right)) / u128::from(BASIS_POINTS_DENOMINATOR);
403 if value > u128::from(u32::MAX) {
404 tracing::error!(
405 "{backend} {label} composed basis-points value exceeded u32. Fix: normalize chained multipliers before release-path planning."
406 );
407 return u32::MAX;
408 }
409 value as u32
410}
411
412#[must_use]
415pub fn checked_compose_basis_points_u64(left: u64, right: u64) -> Option<u64> {
416 let value = (u128::from(left) * u128::from(right)) / u128::from(BASIS_POINTS_DENOMINATOR);
417 u64::try_from(value).ok()
418}
419
420#[must_use]
423pub fn scale_u64_by_basis_points_round_clamped(
424 base: u64,
425 scale_bps: u32,
426 zero_scale_value: u64,
427 max_scale_bps: u32,
428 label: &str,
429 backend: &str,
430) -> u64 {
431 if scale_bps == 0 {
432 return zero_scale_value;
433 }
434 let clamped = if max_scale_bps == 0 {
435 scale_bps
436 } else {
437 scale_bps.min(max_scale_bps)
438 };
439 let value = (u128::from(base) * u128::from(clamped) + u128::from(BASIS_POINTS_DENOMINATOR / 2))
440 / u128::from(BASIS_POINTS_DENOMINATOR);
441 if value > u128::from(u64::MAX) {
442 tracing::error!(
443 "{backend} {label} rounded basis-point scaling exceeded u64. Fix: shard or normalize the cost domain before extraction."
444 );
445 return u64::MAX;
446 }
447 value as u64
448}
449
450#[must_use]
453
454pub fn scale_u64_by_basis_points_floor_min(
455 base: u64,
456 scale_bps: u32,
457 min_value: u64,
458 label: &str,
459 backend: &str,
460) -> u64 {
461 let value = (u128::from(base) * u128::from(scale_bps)) / u128::from(BASIS_POINTS_DENOMINATOR);
462 if value > u128::from(u64::MAX) {
463 tracing::error!(
464 "{backend} {label} floor basis-point scaling exceeded u64. Fix: shard or normalize the cost domain before extraction."
465 );
466 return u64::MAX;
467 }
468 (value as u64).max(min_value)
469}
470
471#[must_use]
473pub fn weighted_u64_by_basis_points_u128(value: u64, basis_points: u32) -> u128 {
474 (u128::from(value) * u128::from(basis_points)) / u128::from(BASIS_POINTS_DENOMINATOR)
475}
476
477#[must_use]
480pub fn finite_f64_to_u32_trunc(value: f64, label: &str, backend: &str) -> u32 {
481 if !value.is_finite() {
482 tracing::error!(
483 "{backend} {label} value {value} is not finite. Fix: normalize telemetry before release-path planning."
484 );
485 return u32::MAX;
486 }
487 if value <= 0.0 {
488 return 0;
489 }
490 if value > f64::from(u32::MAX) {
491 tracing::error!(
492 "{backend} {label} value {value} cannot fit u32. Fix: shard or normalize telemetry before release-path planning."
493 );
494 return u32::MAX;
495 }
496 value as u32
497}
498
499#[must_use]
502pub fn finite_f64_to_u32_round(value: f64, label: &str, backend: &str) -> u32 {
503 let rounded = value.round();
504 if !rounded.is_finite() {
505 tracing::error!(
506 "{backend} {label} rounded value {rounded} is not finite. Fix: normalize telemetry before release-path planning."
507 );
508 return u32::MAX;
509 }
510 if rounded <= 0.0 {
511 return 0;
512 }
513 if rounded > f64::from(u32::MAX) {
514 tracing::error!(
515 "{backend} {label} rounded value {rounded} cannot fit u32. Fix: shard or normalize telemetry before release-path planning."
516 );
517 return u32::MAX;
518 }
519 rounded as u32
520}
521
522#[must_use]
525pub fn finite_f64_ratio_basis_points_trunc(
526 numerator: f64,
527 denominator: f64,
528 invalid_numerator_value: u32,
529 invalid_denominator_value: u32,
530 label: &str,
531 backend: &str,
532) -> u32 {
533 finite_f64_ratio_basis_points(
534 numerator,
535 denominator,
536 invalid_numerator_value,
537 invalid_denominator_value,
538 label,
539 backend,
540 finite_f64_to_u32_trunc,
541 )
542}
543
544#[must_use]
547pub fn finite_f64_ratio_basis_points_round(
548 numerator: f64,
549 denominator: f64,
550 invalid_numerator_value: u32,
551 invalid_denominator_value: u32,
552 label: &str,
553 backend: &str,
554) -> u32 {
555 finite_f64_ratio_basis_points(
556 numerator,
557 denominator,
558 invalid_numerator_value,
559 invalid_denominator_value,
560 label,
561 backend,
562 finite_f64_to_u32_round,
563 )
564}
565
566#[must_use]
568pub fn finite_f64_unit_basis_points_trunc(
569 value: f64,
570 invalid_value: u32,
571 label: &str,
572 backend: &str,
573) -> u32 {
574 if !value.is_finite() {
575 tracing::error!(
576 "{backend} {label} value {value} is not finite. Fix: normalize telemetry before release-path planning."
577 );
578 return invalid_value;
579 }
580 finite_f64_to_u32_trunc(
581 value.max(0.0) * f64::from(BASIS_POINTS_DENOMINATOR),
582 label,
583 backend,
584 )
585}
586
587fn finite_f64_ratio_basis_points(
588 numerator: f64,
589 denominator: f64,
590 invalid_numerator_value: u32,
591 invalid_denominator_value: u32,
592 label: &str,
593 backend: &str,
594 convert: fn(f64, &str, &str) -> u32,
595) -> u32 {
596 if !numerator.is_finite() {
597 tracing::error!(
598 "{backend} {label} numerator {numerator} is not finite. Fix: record finite dispatch timing before release-path planning."
599 );
600 return invalid_numerator_value;
601 }
602 if !denominator.is_finite() || denominator <= 0.0 {
603 tracing::error!(
604 "{backend} {label} denominator {denominator} is not finite and positive. Fix: record finite dispatch timing before release-path planning."
605 );
606 return invalid_denominator_value;
607 }
608 if numerator <= 0.0 {
609 return 0;
610 }
611 convert(
612 (numerator / denominator) * f64::from(BASIS_POINTS_DENOMINATOR),
613 label,
614 backend,
615 )
616}
617
618#[must_use]
621pub fn checked_ceil_div_u64(value: u64, divisor: u64) -> Option<u64> {
622 if divisor == 0 {
623 return None;
624 }
625 if value == 0 {
626 return Some(0);
627 }
628 ((value - 1) / divisor).checked_add(1)
629}
630
631#[must_use]
637pub fn checked_dim_product_u64(dims: [u32; 3]) -> Option<u64> {
638 u64::from(dims[0])
639 .checked_mul(u64::from(dims[1]))
640 .and_then(|xy| xy.checked_mul(u64::from(dims[2])))
641}
642
643#[must_use]
645pub fn checked_dim_product_u32(dims: [u32; 3]) -> Option<u32> {
646 u32::try_from(checked_dim_product_u64(dims)?).ok()
647}
648
649macro_rules! define_align_up {
650 ($name:ident, $ty:ty) => {
651 #[doc = concat!(
652 "Align a `",
653 stringify!($ty),
654 "` value upward after applying a minimum."
655 )]
656 pub fn $name(
662 value: $ty,
663 alignment: $ty,
664 min_value: $ty,
665 label: &str,
666 backend: &str,
667 ) -> Result<$ty, BackendError> {
668 if alignment == 0 {
669 return Err(BackendError::InvalidProgram {
670 fix: format!(
671 "Fix: {backend} {label} alignment must be non-zero before padding."
672 ),
673 });
674 }
675 let normalized = value.max(min_value);
676 let remainder = normalized % alignment;
677 if remainder == 0 {
678 return Ok(normalized);
679 }
680 normalized.checked_add(alignment - remainder).ok_or_else(|| {
681 BackendError::InvalidProgram {
682 fix: format!(
683 "Fix: {backend} {label} overflows {} while padding to {alignment}-byte alignment; split the workload before crossing the host/device boundary.",
684 stringify!($ty)
685 ),
686 }
687 })
688 }
689 };
690}
691
692define_align_up!(align_up_u64, u64);
693define_align_up!(align_up_usize, usize);
694
695#[cfg(test)]
696mod tests {
697 use super::*;
698
699 #[test]
700 fn usize_boundary_accepts_fit_values() {
701 assert_eq!(usize_to_u64(17, "bytes", "test").unwrap(), 17);
702 }
703
704 #[test]
705 fn backend_numeric_policy_carries_backend_label_without_local_wrappers() {
706 let policy = BackendNumericPolicy::new("CUDA");
707 assert_eq!(policy.backend(), "CUDA");
708 assert_eq!(policy.usize_to_u64(17, "bytes").unwrap(), 17);
709 assert_eq!(policy.ratio_basis_points_u64(1, 4, 0, "pressure"), 2_500);
710 assert_eq!(
711 policy.finite_f64_ratio_basis_points_round(1.0, 6.0, 99, 77, "ratio"),
712 1_667
713 );
714 assert_eq!(policy.checked_ceil_div_u64(65_537, 65_536), Some(2));
715 assert_eq!(
716 policy.checked_dim_product_u64([65_535, 2, 3]),
717 Some(393_210)
718 );
719 assert_eq!(
720 policy.checked_dim_product_u32([65_535, 2, 3]),
721 Some(393_210)
722 );
723
724 let err = policy
725 .u128_to_u64(u128::from(u64::MAX) + 1, "resident bytes")
726 .unwrap_err();
727 let rendered = err.to_string();
728 assert!(
729 rendered.contains("CUDA resident bytes"),
730 "backend policy diagnostics must carry the backend label and boundary name: {rendered}"
731 );
732 }
733
734 #[test]
735 fn u128_boundary_rejects_overflow_with_backend_label() {
736 let err = u128_to_u64(u128::from(u64::MAX) + 1, "counter", "test").unwrap_err();
737 let rendered = err.to_string();
738 assert!(
739 rendered.contains("test counter"),
740 "numeric boundary diagnostics must identify the backend and label: {rendered}"
741 );
742 }
743
744 #[test]
745 fn rounded_f64_rejects_non_finite_values() {
746 let err = rounded_f64_to_u64(f64::NAN, "timestamp", "test").unwrap_err();
747 let rendered = err.to_string();
748 assert!(
749 rendered.contains("timestamp"),
750 "rounded timestamp diagnostics must include the failing label: {rendered}"
751 );
752 }
753
754 #[test]
755 fn ratio_basis_points_preserves_zero_denominator_policy() {
756 assert_eq!(
757 ratio_basis_points_u64(1, 0, u32::MAX, "pressure", "test"),
758 u32::MAX
759 );
760 assert_eq!(ratio_basis_points_u64(0, 0, 0, "savings", "test"), 0);
761 }
762
763 #[test]
764 fn ratio_basis_points_uses_wide_arithmetic_before_clamping() {
765 assert_eq!(
766 ratio_basis_points_u64(u64::MAX, u64::MAX / 2, 0, "wide", "test"),
767 20_000
768 );
769 assert_eq!(
770 ratio_basis_points_u64(u64::MAX, 1, 0, "overflow", "test"),
771 u32::MAX
772 );
773 }
774
775 #[test]
776 fn wide_ratio_basis_points_retains_u64_telemetry_domain() {
777 assert_eq!(ratio_basis_points_u64_wide(3, 2, 0, "wide", "test"), 15_000);
778 assert_eq!(
779 ratio_basis_points_u64_wide(u64::MAX, u64::MAX / 4, 0, "wide", "test"),
780 40_000
781 );
782 assert_eq!(
783 ratio_basis_points_u64_wide(u64::MAX, 1, 0, "overflow", "test"),
784 u64::MAX
785 );
786 }
787
788 #[test]
789 fn finite_f64_to_u32_helpers_pin_invalid_values() {
790 assert_eq!(finite_f64_to_u32_trunc(12.9, "value", "test"), 12);
791 assert_eq!(finite_f64_to_u32_round(12.5, "value", "test"), 13);
792 assert_eq!(finite_f64_to_u32_trunc(-1.0, "value", "test"), 0);
793 assert_eq!(
794 finite_f64_to_u32_round(f64::INFINITY, "value", "test"),
795 u32::MAX
796 );
797 assert_eq!(
798 finite_f64_to_u32_trunc(f64::from(u32::MAX) * 2.0, "value", "test"),
799 u32::MAX
800 );
801 }
802
803 #[test]
804 fn finite_f64_basis_point_helpers_pin_invalid_policies() {
805 assert_eq!(
806 finite_f64_ratio_basis_points_trunc(1.0, 4.0, 99, 77, "ratio", "test"),
807 2_500
808 );
809 assert_eq!(
810 finite_f64_ratio_basis_points_round(1.0, 6.0, 99, 77, "ratio", "test"),
811 1_667
812 );
813 assert_eq!(
814 finite_f64_ratio_basis_points_trunc(f64::NAN, 1.0, 99, 77, "ratio", "test"),
815 99
816 );
817 assert_eq!(
818 finite_f64_ratio_basis_points_trunc(1.0, 0.0, 99, 77, "ratio", "test"),
819 77
820 );
821 assert_eq!(
822 finite_f64_ratio_basis_points_round(-1.0, 1.0, 99, 77, "ratio", "test"),
823 0
824 );
825 assert_eq!(
826 finite_f64_unit_basis_points_trunc(0.25, 33, "unit", "test"),
827 2_500
828 );
829 assert_eq!(
830 finite_f64_unit_basis_points_trunc(f64::INFINITY, 33, "unit", "test"),
831 33
832 );
833 }
834
835 #[test]
836 fn alignment_helpers_pad_minimums_and_reject_overflow() {
837 assert_eq!(align_up_u64(0, 4, 4, "copy", "test").unwrap(), 4);
838 assert_eq!(align_up_u64(5, 4, 0, "copy", "test").unwrap(), 8);
839 assert_eq!(align_up_usize(0, 4, 4, "copy", "test").unwrap(), 4);
840 assert_eq!(align_up_usize(5, 4, 0, "copy", "test").unwrap(), 8);
841
842 let zero_alignment = align_up_u64(1, 0, 0, "copy", "test").unwrap_err();
843 assert!(
844 zero_alignment
845 .to_string()
846 .contains("alignment must be non-zero"),
847 "zero-alignment diagnostics must be actionable: {zero_alignment}"
848 );
849
850 let overflow_u64 = align_up_u64(u64::MAX, 4, 0, "copy", "test").unwrap_err();
851 assert!(
852 overflow_u64.to_string().contains("overflows u64"),
853 "u64 alignment overflow diagnostics must name the target type: {overflow_u64}"
854 );
855
856 let overflow_usize = align_up_usize(usize::MAX, 4, 0, "copy", "test").unwrap_err();
857 assert!(
858 overflow_usize.to_string().contains("overflows usize"),
859 "usize alignment overflow diagnostics must name the target type: {overflow_usize}"
860 );
861 }
862
863 #[test]
864 fn checked_ceil_div_u64_handles_cuda_queue_boundaries() {
865 assert_eq!(checked_ceil_div_u64(0, 64), Some(0));
866 assert_eq!(checked_ceil_div_u64(1, 64), Some(1));
867 assert_eq!(checked_ceil_div_u64(65_537, 65_536), Some(2));
868 assert_eq!(
869 checked_ceil_div_u64(u64::MAX, 65_536),
870 Some(281_474_976_710_656)
871 );
872 assert_eq!(checked_ceil_div_u64(u64::MAX, 1), Some(u64::MAX));
873 assert_eq!(checked_ceil_div_u64(1, 0), None);
874 }
875
876 #[test]
877 fn checked_dim_product_helpers_cover_cuda_launch_boundaries() {
878 assert_eq!(checked_dim_product_u64([1, 1, 1]), Some(1));
879 assert_eq!(checked_dim_product_u64([0, 999, 999]), Some(0));
880 assert_eq!(checked_dim_product_u64([65_535, 2, 3]), Some(393_210));
881 assert_eq!(checked_dim_product_u32([65_535, 2, 3]), Some(393_210));
882 assert_eq!(
883 checked_dim_product_u64([u32::MAX, u32::MAX, u32::MAX]),
884 None
885 );
886 assert_eq!(checked_dim_product_u32([u32::MAX, 2, 1]), None);
887 }
888
889 #[test]
890 fn generated_dim_product_matrix_matches_wide_integer_reference() {
891 const VALUES: [u32; 9] = [0, 1, 2, 3, 7, 32, 255, 65_535, u32::MAX];
892 for x in VALUES {
893 for y in VALUES {
894 for z in VALUES {
895 let wide = u128::from(x) * u128::from(y) * u128::from(z);
896 let expected_u64 = u64::try_from(wide).ok();
897 let expected_u32 = u32::try_from(wide).ok();
898 assert_eq!(checked_dim_product_u64([x, y, z]), expected_u64);
899 assert_eq!(checked_dim_product_u32([x, y, z]), expected_u32);
900 }
901 }
902 }
903 }
904
905 #[test]
906 fn ratio_parts_per_million_uses_wide_arithmetic_and_pins_overflow() {
907 assert_eq!(
908 ratio_parts_per_million_u64(1, 4, 0, "commit-rate", "test"),
909 250_000
910 );
911 assert_eq!(
912 ratio_parts_per_million_u64(1, 0, 7, "commit-rate", "test"),
913 7
914 );
915 assert_eq!(
916 ratio_parts_per_million_u64(u64::MAX, 1, 0, "commit-rate", "test"),
917 u32::MAX
918 );
919 }
920
921 #[test]
922 fn basis_point_composition_and_scaling_helpers_are_widened() {
923 assert_eq!(
924 compose_basis_points_u32(15_000, 2_500, "compose", "test"),
925 3_750
926 );
927 assert_eq!(
928 compose_basis_points_u32(u32::MAX, u32::MAX, "compose", "test"),
929 u32::MAX
930 );
931 assert_eq!(
932 checked_compose_basis_points_u64(50_000, 20_000),
933 Some(100_000)
934 );
935 assert_eq!(checked_compose_basis_points_u64(u64::MAX, u64::MAX), None);
936 assert_eq!(
937 scale_u64_by_basis_points_round_clamped(10, 1_000_000, 10, 40_000, "scale", "test"),
938 40
939 );
940 assert_eq!(
941 scale_u64_by_basis_points_round_clamped(7, 0, 7, 40_000, "scale", "test"),
942 7
943 );
944 assert_eq!(
945 scale_u64_by_basis_points_floor_min(1, 1, 1, "scale", "test"),
946 1
947 );
948 assert_eq!(
949 weighted_u64_by_basis_points_u128(u64::MAX, 10_000),
950 u128::from(u64::MAX)
951 );
952 }
953}