1pub fn cross_sign(ax: i64, ay: i64, bx: i64, by: i64, cx: i64, cy: i64) -> i128 {
22 let dx1 = (bx as i128) - (ax as i128);
23 let dy1 = (by as i128) - (ay as i128);
24 let dx2 = (cx as i128) - (ax as i128);
25 let dy2 = (cy as i128) - (ay as i128);
26 dx1 * dy2 - dy1 * dx2
27}
28
29pub fn sub_u64(a: u64, b: u64) -> i128 {
32 (a as i128) - (b as i128)
33}
34
35pub fn sign(v: i128) -> i32 {
37 v.cmp(&0) as i32
38}
39
40pub fn is_left_turn(cross: i128) -> bool {
42 cross > 0
43}
44
45pub fn is_right_turn(cross: i128) -> bool {
47 cross < 0
48}
49
50pub fn is_collinear(cross: i128) -> bool {
52 cross == 0
53}
54
55#[cfg(test)]
56mod tests {
57 use super::*;
58
59 #[test]
60 fn cross_sign_left_turn_is_positive() {
61 let result = cross_sign(0, 0, 2_000_000, 0, 2_000_000, 2_000_000);
63 assert!(result > 0, "left turn should be positive, got {result}");
64 }
65
66 #[test]
67 fn cross_sign_right_turn_is_negative() {
68 let result = cross_sign(0, 0, 2_000_000, 2_000_000, 4_000_000, 0);
70 assert!(result < 0, "right turn should be negative, got {result}");
71 }
72
73 #[test]
74 fn cross_sign_collinear_is_zero() {
75 let result = cross_sign(0, 0, 1_000_000, 0, 2_000_000, 0);
77 assert_eq!(result, 0, "collinear should be zero");
78 }
79
80 #[test]
81 fn cross_sign_matches_move_test_vectors() {
82 let zero = cross_sign(0, 2, 1, 1, 2, 0);
84 assert_eq!(zero, 0);
85
86 let left = cross_sign(0, 0, 2, 0, 2, 2);
88 assert_eq!(left, 4);
89
90 let right = cross_sign(0, 0, 2, 2, 4, 0);
92 assert!(right < 0);
93 }
94
95 #[test]
96 fn cross_sign_no_overflow_with_max_world_coordinates() {
97 const MAX_WORLD: i64 = 40_075_017_000_000;
100 let result = cross_sign(0, 0, MAX_WORLD, 0, 0, MAX_WORLD);
101 let expected = (MAX_WORLD as i128) * (MAX_WORLD as i128);
103 assert_eq!(result, expected);
104 }
105
106 #[test]
107 fn cross_sign_large_negative_no_overflow() {
108 const MAX_WORLD: i64 = 40_075_017_000_000;
109 let result = cross_sign(0, MAX_WORLD, MAX_WORLD, 0, 0, 0);
111 assert!(result < 0);
112 }
113
114 #[test]
115 fn sub_u64_positive_and_negative() {
116 assert_eq!(sub_u64(10, 5), 5_i128);
117 assert_eq!(sub_u64(5, 10), -5_i128);
118 assert_eq!(sub_u64(7, 7), 0_i128);
119 }
120
121 #[test]
122 fn sign_returns_correct_values() {
123 assert_eq!(sign(42), 1);
124 assert_eq!(sign(-42), -1);
125 assert_eq!(sign(0), 0);
126 }
127}