polenta 0.1.2

A toy language about polynomials over finite-fields
Documentation
use lambdaworks_math::{
    field::{element::FieldElement, traits::IsPrimeField},
    polynomial::Polynomial,
};
use std::collections::HashMap;

/// Supported prime fields.
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum FieldType {
    Babybear31,
    Goldilocks,
    Stark252,
    Mersenne31,
}

impl FieldType {
    pub fn name(&self) -> &'static str {
        match self {
            FieldType::Babybear31 => "babybear31",
            FieldType::Goldilocks => "goldilocks",
            FieldType::Stark252 => "stark252",
            FieldType::Mersenne31 => "mersenne31",
        }
    }

    pub fn order(&self) -> &'static str {
        match self {
            FieldType::Babybear31 => "2013265921",
            FieldType::Goldilocks => "18446744069414584321",
            FieldType::Stark252 => {
                "3618502788666131213697322783095070105623107215331596699973092056135872020481"
            }
            FieldType::Mersenne31 => "2147483647",
        }
    }

    pub fn all() -> &'static [FieldType] {
        &[
            FieldType::Babybear31,
            FieldType::Goldilocks,
            FieldType::Stark252,
            FieldType::Mersenne31,
        ]
    }

    pub fn from_name(name: &str) -> Option<Self> {
        match name.to_lowercase().as_str() {
            "babybear31" => Some(FieldType::Babybear31),
            "goldilocks" => Some(FieldType::Goldilocks),
            "stark252" => Some(FieldType::Stark252),
            "mersenne31" => Some(FieldType::Mersenne31),
            _ => None,
        }
    }
}

/// Export symbols as (name, hex coefficient strings) pairs.
/// Always normalizes to unprefixed hex so `from_hex` can parse on import.
pub fn export_symbols<F: IsPrimeField>(
    symbols: &HashMap<String, Polynomial<FieldElement<F>>>,
) -> Vec<(String, Vec<String>)> {
    symbols
        .iter()
        .map(|(name, poly)| {
            let hex_coeffs = poly
                .coefficients()
                .iter()
                .map(|c| repr_to_hex(&format!("{}", c.representative())))
                .collect();
            (name.clone(), hex_coeffs)
        })
        .collect()
}

/// Import symbols from hex coefficient strings, reducing mod p automatically via `from_hex`.
pub fn import_symbols<F: IsPrimeField>(
    symbols: &mut HashMap<String, Polynomial<FieldElement<F>>>,
    data: &[(String, Vec<String>)],
) {
    for (name, hex_coeffs) in data {
        let coeffs: Vec<FieldElement<F>> = hex_coeffs
            .iter()
            .filter_map(|h| FieldElement::<F>::from_hex(h).ok())
            .collect();
        symbols.insert(name.clone(), Polynomial::new(&coeffs));
    }
}

/// Normalizes a representative Display string to unprefixed hex.
/// - u64 Display gives decimal (e.g. "42") → converted to hex ("2a")
/// - UnsignedInteger Display gives "0x..." → prefix stripped
fn repr_to_hex(s: &str) -> String {
    if let Some(h) = s.strip_prefix("0x").or_else(|| s.strip_prefix("0X")) {
        return h.to_string();
    }

    // decimal string from u64 Display — parse and format as hex
    // (all u64-backed fields fit in u64)
    match s.parse::<u64>() {
        Ok(v) => format!("{:x}", v),
        Err(_) => s.to_string(),
    }
}