Functional Weave
Code in Python

math.gcd-lcm@2.0.0

impl/rust/gcd_lcm.rs

1,153 bytes · the Rust implementation · view raw

Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.

use super::funejson::Value;  ← the fune runtime: the JSON value the test vectors use; fune build keeps it only where a signature takes one
use super::math_gcd_lcm_gcd::gcd;  ← gcd, another function of this group · built into the same file, even by a slim install
use super::math_gcd_lcm_lcm::lcm;  ← lcm, another function of this group · built into the same file, even by a slim install

/// Greatest common divisor and least common multiple of two integers.
///
/// Both are returned together because a caller needing one nearly always
/// needs the other (common denominators, repeating schedules).
///
/// # Panics
/// Panics if either input is outside ±(2^53 - 1), or the lcm is.
pub fn gcd_lcm(a: i64, b: i64) -> GcdLcm {
    GcdLcm {
        gcd: gcd(a, b),
        lcm: lcm(a, b),
    }
}

pub fn gcd_lcm_to_value(result: &GcdLcm) -> Value {
    Value::obj(vec![
        ("gcd", Value::Int(result.gcd)),
        ("lcm", Value::Int(result.lcm)),
    ])
}

// Refuse what the typed signature cannot hold, with the wording TypeScript
// and Python use, rather than let the conversion quietly truncate it.
fn int_arg(v: &Value, name: &str) -> i64 {
    if let Value::Float(f) = v {
        if f.fract() != 0.0 {
            panic!("{} must be an integer, received {}", name, f);
        }
    }
    v.as_i64()
}

pub fn fune_vector(args: &[Value]) -> Value {
    gcd_lcm_to_value(&gcd_lcm(int_arg(&args[0], "a"), int_arg(&args[1], "b")))
}