mirror of
https://github.com/horizon-rust/horizon.git
synced 2026-11-07 17:21:49 -10:00
Fix scoreboard remainder overflow for large divisors
This commit is contained in:
1 parent
993eabe86b
commit
52453208cd
3 files changed
+62
-1
No files matched your search
@@ -797,7 +797,14 @@ pub fn apply_operation(op: &str, a: i32, b: i32) -> CmdResult<(i32, i32)> {
|
||||
if b == 0 {
|
||||
return Err(div0());
|
||||
}
|
||||
(a.wrapping_rem(b).wrapping_add(b).wrapping_rem(b), b)
|
||||
let remainder = a.wrapping_rem(b);
|
||||
// Floor remainder has the divisor's sign; only correct opposite signs.
|
||||
let remainder = if remainder != 0 && ((remainder < 0) != (b < 0)) {
|
||||
remainder + b
|
||||
} else {
|
||||
remainder
|
||||
};
|
||||
(remainder, b)
|
||||
}
|
||||
"<" => (a.min(b), b),
|
||||
">" => (a.max(b), b),
|
||||
|
||||
@@ -210,6 +210,47 @@ fn division_wraps_minimum_integer_by_negative_one() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn remainder_handles_integer_boundaries() {
|
||||
for (dividend, divisor, expected) in [
|
||||
(i32::MAX - 1, i32::MAX, i32::MAX - 1),
|
||||
(7, -3, -2),
|
||||
(-7, 3, 2),
|
||||
(i32::MIN, -1, 0),
|
||||
(-1, i32::MIN, -1),
|
||||
(1, i32::MIN, i32::MIN + 1),
|
||||
(0, i32::MAX, 0),
|
||||
] {
|
||||
let mut m = mock();
|
||||
run(&mut m, "scoreboard objectives add boundary dummy").unwrap();
|
||||
run(
|
||||
&mut m,
|
||||
&format!("scoreboard players set left boundary {dividend}"),
|
||||
)
|
||||
.unwrap();
|
||||
run(
|
||||
&mut m,
|
||||
&format!("scoreboard players set right boundary {divisor}"),
|
||||
)
|
||||
.unwrap();
|
||||
run(
|
||||
&mut m,
|
||||
"scoreboard players operation left boundary %= right boundary",
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
run(&mut m, "scoreboard players get left boundary").unwrap(),
|
||||
expected,
|
||||
"{dividend} %= {divisor}"
|
||||
);
|
||||
assert_eq!(
|
||||
run(&mut m, "scoreboard players get right boundary").unwrap(),
|
||||
divisor
|
||||
);
|
||||
}
|
||||
assert!(apply_operation("%=", 1, 0).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn triggers() {
|
||||
let mut m = mock();
|
||||
|
||||
@@ -1191,8 +1191,21 @@ def compute():
|
||||
]
|
||||
|
||||
|
||||
def scoreboard_remainder_boundaries():
|
||||
operations = setup('/scoreboard objectives add boundary dummy')
|
||||
for dividend, divisor in [(2147483646, 2147483647), (7, -3), (-2147483648, -1)]:
|
||||
operations += setup(f'/scoreboard players set left boundary {dividend}',
|
||||
f'/scoreboard players set right boundary {divisor}')
|
||||
operations += [cmd('/scoreboard players operation left boundary %= right boundary'),
|
||||
cmd('/scoreboard players get left boundary'),
|
||||
cmd('/scoreboard players get right boundary')]
|
||||
operations += setup('/scoreboard objectives remove boundary')
|
||||
return operations
|
||||
|
||||
|
||||
def social():
|
||||
return [
|
||||
*scoreboard_remainder_boundaries(),
|
||||
*setup('/scoreboard objectives add trig trigger', '/scoreboard objectives add plain dummy'),
|
||||
cmd('/trigger trig'),
|
||||
cmd('/scoreboard players enable @s trig'),
|
||||
|
||||
Reference in new issue
Block a user