(&mut self)
| 360 | } |
| 361 | |
| 362 | pub fn call_divmod(&mut self) -> Result<(), VmErr> { |
| 363 | let b = self.pop()?; |
| 364 | let a = self.pop()?; |
| 365 | // Float operands: divmod(a, b) == (floor(a/b), a - floor(a/b)*b). |
| 366 | if a.is_float() || b.is_float() { |
| 367 | let af = self.to_f64_coerce(a).map_err(|_| cold_type("divmod() requires numeric operands"))?; |
| 368 | let bf = self.to_f64_coerce(b).map_err(|_| cold_type("divmod() requires numeric operands"))?; |
| 369 | if bf == 0.0 { return Err(VmErr::ZeroDiv); } |
| 370 | let q = ffloor(af / bf); |
| 371 | let r = af - q * bf; |
| 372 | let qv = Val::float(q); |
| 373 | let rv = Val::float(r); |
| 374 | return self.alloc_and_push_tuple(alloc::vec![qv, rv]); |
| 375 | } |
| 376 | let (Some(ai), Some(bi)) = (self.as_i128(a), self.as_i128(b)) else { return Err(cold_type("divmod() requires numeric operands")); }; |
| 377 | if bi == 0 { return Err(VmErr::ZeroDiv); } |
| 378 | // checked_div guards i128::MIN / -1. |
| 379 | let q = ai.checked_div(bi).ok_or(cold_overflow())?; |
| 380 | let r = ai - q * bi; |
| 381 | // Floor-div sign correction so divmod matches `(a // b, a % b)`. |
| 382 | let (q, r) = if (r != 0) && ((r < 0) != (bi < 0)) { (q - 1, r + bi) } else { (q, r) }; |
| 383 | let qv = self.int_to_val(Some(q))?; |
| 384 | let rv = self.int_to_val(Some(r))?; |
| 385 | self.alloc_and_push_tuple(alloc::vec![qv, rv]) |
| 386 | } |
| 387 | |
| 388 | pub fn call_pow(&mut self, op: u16) -> Result<(), VmErr> { |
| 389 | let args = self.pop_n(op as usize)?; |
no test coverage detected