@@ -457,6 +457,60 @@ macro_rules! impl_vector_fns {
457
457
}
458
458
}
459
459
460
+ pub ( super ) fn snap_one ( mut value : i32 , step : i32 ) -> i32 {
461
+ assert ! (
462
+ value != i32 :: MIN || step != -1 ,
463
+ "snapped() called on vector component i32::MIN with step component -1"
464
+ ) ;
465
+
466
+ if step != 0 {
467
+ // Can overflow if step / 2 + value is not in range of i32.
468
+ let a = ( step / 2 ) . checked_add ( value) . expect (
469
+ "snapped() overflowed, this happened because step / 2 + component is not in range of i32" ,
470
+ ) ;
471
+
472
+ // Manually implement `a.div_floor(step)` since Rust's native method is still unstable, as of 1.79.0.
473
+
474
+ // Can overflow with a == i32::MIN and step == -1 when value == i32::MIN.
475
+ let mut d = a / step;
476
+ // Can't overflow because if a == i32::MIN and step == -1, value == -2147483647.5 which is impossible.
477
+ let r = a % step;
478
+ if ( r > 0 && step < 0 ) || ( r < 0 && step > 0 ) {
479
+ // Can't overflow because if d == i32::MIN than a == i32::MIN and step == 1 and value == -2147483648.5 which is impossible.
480
+ d -= 1 ;
481
+ }
482
+
483
+ value = step * d;
484
+ }
485
+
486
+ value
487
+ }
488
+
489
+ /// Implements functions that are present only on integer vectors.
490
+ macro_rules! impl_integer_vector_fns {
491
+ (
492
+ // Names of the components, for example `x, y`.
493
+ $( $comp: ident) ,*
494
+ ) => {
495
+ /// A new vector with each component snapped to the closest multiple of the corresponding
496
+ /// component in `step`.
497
+ ///
498
+ /// # Panics
499
+ /// On under- or overflow:
500
+ /// - If any component of `self` is [`i32::MIN`] while the same component on `step` is `-1`.
501
+ /// - If any component of `self` plus half of the same component of `step` is not in range on [`i32`].
502
+ pub fn snapped( self , step: Self ) -> Self {
503
+ use crate :: builtin:: vectors:: vector_macros:: snap_one;
504
+
505
+ Self :: new(
506
+ $(
507
+ snap_one( self . $comp, step. $comp)
508
+ ) ,*
509
+ )
510
+ }
511
+ } ;
512
+ }
513
+
460
514
/// Implements functions that are present only on floating-point vectors.
461
515
macro_rules! impl_float_vector_fns {
462
516
(
@@ -642,7 +696,6 @@ macro_rules! impl_float_vector_fns {
642
696
643
697
/// A new vector with each component snapped to the closest multiple of the corresponding
644
698
/// component in `step`.
645
- // TODO: also implement for integer vectors
646
699
#[ inline]
647
700
pub fn snapped( self , step: Self ) -> Self {
648
701
Self :: new(
0 commit comments