Skip to main content

affine/
utils.rs

1// Copyright 2026 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5/// Performs saturating addition on i64.
6///
7/// This implements a clamping policy in the case of overflow, returning
8/// `i64::MIN` or `i64::MAX`.
9pub fn clamp_add(a: i64, b: i64) -> i64 {
10    a.saturating_add(b)
11}
12
13/// Performs saturating subtraction on i64.
14///
15/// This implements a clamping policy in the case of overflow, returning
16/// `i64::MIN` or `i64::MAX`.
17pub fn clamp_sub(a: i64, b: i64) -> i64 {
18    a.saturating_sub(b)
19}
20
21#[cfg(test)]
22mod tests {
23    use super::*;
24
25    const MAX: i64 = i64::MAX;
26    const MIN: i64 = i64::MIN;
27
28    struct TestVector {
29        a: i64,
30        b: i64,
31        expected: i64,
32    }
33
34    #[test]
35    fn test_clamp_add() {
36        let test_vectors = [
37            TestVector { a: 15, b: 25, expected: 40 },
38            TestVector { a: 15, b: -25, expected: -10 },
39            TestVector { a: 15, b: MAX - 16, expected: MAX - 1 },
40            TestVector { a: 15, b: MAX - 15, expected: MAX - 0 },
41            TestVector { a: 15, b: MAX - 14, expected: MAX - 0 },
42            TestVector { a: MAX - 16, b: 15, expected: MAX - 1 },
43            TestVector { a: MAX - 15, b: 15, expected: MAX - 0 },
44            TestVector { a: MAX - 14, b: 15, expected: MAX - 0 },
45            TestVector { a: -15, b: MIN + 16, expected: MIN + 1 },
46            TestVector { a: -15, b: MIN + 15, expected: MIN + 0 },
47            TestVector { a: -15, b: MIN + 14, expected: MIN + 0 },
48            TestVector { a: MIN + 16, b: -15, expected: MIN + 1 },
49            TestVector { a: MIN + 15, b: -15, expected: MIN + 0 },
50            TestVector { a: MIN + 14, b: -15, expected: MIN + 0 },
51            TestVector { a: MAX, b: MAX - 1, expected: MAX },
52            TestVector { a: MAX - 1, b: MAX, expected: MAX },
53            TestVector { a: MAX, b: MAX, expected: MAX },
54        ];
55
56        for v in &test_vectors {
57            let result = clamp_add(v.a, v.b);
58            assert_eq!(result, v.expected, "test case: {} + {}", v.a, v.b);
59        }
60    }
61
62    #[test]
63    fn test_clamp_sub() {
64        let test_vectors = [
65            TestVector { a: 15, b: 25, expected: -10 },
66            TestVector { a: 15, b: -25, expected: 40 },
67            TestVector { a: -15, b: MAX - 16, expected: MIN + 2 },
68            TestVector { a: -15, b: MAX - 15, expected: MIN + 1 },
69            TestVector { a: -15, b: MAX - 14, expected: MIN + 0 },
70            TestVector { a: -15, b: MAX - 13, expected: MIN + 0 },
71            TestVector { a: MIN + 16, b: 15, expected: MIN + 1 },
72            TestVector { a: MIN + 15, b: 15, expected: MIN + 0 },
73            TestVector { a: MIN + 14, b: 15, expected: MIN + 0 },
74            TestVector { a: 15, b: MIN + 15, expected: MAX - 0 },
75            TestVector { a: 15, b: MIN + 16, expected: MAX - 0 },
76            TestVector { a: 15, b: MIN + 17, expected: MAX - 1 },
77            TestVector { a: MAX - 16, b: -15, expected: MAX - 1 },
78            TestVector { a: MAX - 15, b: -15, expected: MAX - 0 },
79            TestVector { a: MAX - 14, b: -15, expected: MAX - 0 },
80            TestVector { a: 0, b: MIN + 0, expected: MAX - 0 },
81            TestVector { a: 0, b: MIN + 1, expected: MAX - 0 },
82            TestVector { a: 0, b: MIN + 2, expected: MAX - 1 },
83            TestVector { a: MIN, b: MIN + 1, expected: -1 },
84            TestVector { a: MIN, b: MIN, expected: 0 },
85        ];
86
87        for v in &test_vectors {
88            let result = clamp_sub(v.a, v.b);
89            assert_eq!(result, v.expected, "test case: {} - {}", v.a, v.b);
90        }
91    }
92}