use super::funejson::Value; const MAX_SAFE: i64 = (1i64 << 53) - 1; /// The largest whole number whose square does not exceed `n`. /// /// The floating-point square root is only a first guess: it is corrected with /// exact `i128` arithmetic, so a number just below a perfect square never /// rounds up to its root. /// /// # Panics /// Panics if `n` is negative or above 2^53 - 1. pub fn integer_sqrt(n: i64) -> i64 { if !(0..=MAX_SAFE).contains(&n) { panic!("n must be a whole number from 0 to 2^53 - 1, received {}", n); } let target = n as i128; let mut r = (n as f64).sqrt().floor() as i128; while r * r > target { r -= 1; } while (r + 1) * (r + 1) <= target { r += 1; } r as i64 } pub fn fune_vector(args: &[Value]) -> Value { if let Value::Float(f) = &args[0] { panic!("n must be a whole number from 0 to 2^53 - 1, received {}", f); } Value::Int(integer_sqrt(args[0].as_i64())) }