MCPcopy Create free account
hub / github.com/dylan-sutton-chavez/edge-python / call_round

Method call_round

compiler/src/modules/vm/builtins/numeric.rs:214–250  ·  view source on GitHub ↗
(&mut self, op: u16)

Source from the content-addressed store, hash-verified

212 }
213
214 pub fn call_round(&mut self, op: u16) -> Result<(), VmErr> {
215 let args = self.pop_n(op as usize)?;
216 let v = match (args.first().copied(), args.get(1).copied()) {
217 (Some(o), Some(n)) if o.is_float() && n.is_int() => {
218 let x = o.as_float();
219 let nd = n.as_int();
220 if !x.is_finite() {
221 Val::float(x)
222 } else if nd >= 0 {
223 // Correctly-rounded decimal (round-half-even on the true value); avoids the double-rounding `x*10^n` would introduce (e.g. round(2.675, 2) -> 2.67).
224 let s = alloc::format!("{:.*}", (nd as usize).min(323), x);
225 Val::float(s.parse().unwrap_or(x))
226 } else {
227 let factor = fpowi(10.0, (-nd) as i32);
228 Val::float(fround(x / factor) * factor)
229 }
230 }
231 (Some(o), None) if o.is_float() => {
232 // 1-arg round returns an int; promote via int_to_val so large results don't wrap.
233 let f = o.as_float();
234 if f.is_nan() { return Err(cold_value("cannot convert float NaN to integer")); }
235 if f.is_infinite() { return Err(VmErr::Raised(alloc::string::String::from("OverflowError: cannot convert float infinity to integer"))); }
236 let r = fround(f);
237 if !(-1.7014118346046923e38..=1.7014118346046921e38).contains(&r) { return Err(cold_overflow()); }
238 self.int_to_val(Some(r as i128))?
239 }
240 // Ints/bools round to themselves; negative ndigits round to tens/hundreds.
241 (Some(o), n) if o.is_bool() || o.is_int() || (o.is_heap() && matches!(self.heap.get(o), HeapObj::LongInt(_))) => {
242 let i = if o.is_bool() { o.as_bool() as i128 } else { self.as_i128(o).ok_or(cold_type("round() requires a number"))? };
243 let nd = match n { Some(n) if n.is_int() => n.as_int(), _ => 0 };
244 let r = if nd < 0 { round_int_banker(i, (-nd) as u32) } else { i };
245 self.int_to_val(Some(r))?
246 }
247 _ => return Err(cold_type("round() requires a number")),
248 };
249 self.push(v); Ok(())
250 }
251
252 pub fn call_min(&mut self, op: u16, chunk: &crate::modules::parser::SSAChunk, slots: &mut [Val]) -> Result<(), VmErr> { self.call_minmax(op, true, chunk, slots) }
253 pub fn call_max(&mut self, op: u16, chunk: &crate::modules::parser::SSAChunk, slots: &mut [Val]) -> Result<(), VmErr> { self.call_minmax(op, false, chunk, slots) }

Callers 2

handle_functionMethod · 0.80
dispatch_nativeMethod · 0.80

Calls 15

fpowiFunction · 0.85
froundFunction · 0.85
cold_valueFunction · 0.85
cold_overflowFunction · 0.85
cold_typeFunction · 0.85
round_int_bankerFunction · 0.85
pop_nMethod · 0.80
is_floatMethod · 0.80
is_intMethod · 0.80
as_floatMethod · 0.80
as_intMethod · 0.80
int_to_valMethod · 0.80

Tested by

no test coverage detected