use super::functions::*;
pub struct OrdinalType {
pub base_omega_power: u64,
pub coefficient: u64,
pub lower: Box<Option<String>>,
}
impl OrdinalType {
pub fn new(base_omega_power: u64, coefficient: u64, lower: Option<String>) -> Self {
Self {
base_omega_power,
coefficient,
lower: Box::new(lower),
}
}
pub fn cantor_normal_form(&self) -> String {
let base = if self.base_omega_power == 0 {
format!("{}", self.coefficient)
} else if self.base_omega_power == 1 {
format!("ω·{}", self.coefficient)
} else {
format!("ω^{}·{}", self.base_omega_power, self.coefficient)
};
match self.lower.as_ref() {
None => base,
Some(l) => format!("{} + {}", base, l),
}
}
pub fn is_successor(&self) -> bool {
self.base_omega_power == 0 && self.coefficient > 0
|| self
.lower
.as_deref()
.map(|l| !l.is_empty())
.unwrap_or(false)
}
pub fn is_limit(&self) -> bool {
self.base_omega_power > 0 && !self.is_successor()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Sign {
Plus,
Minus,
}
impl Sign {
pub fn negate(self) -> Self {
match self {
Sign::Plus => Sign::Minus,
Sign::Minus => Sign::Plus,
}
}
}
pub struct GameValue {
pub left_options: Vec<String>,
pub right_options: Vec<String>,
}
impl GameValue {
pub fn new(left_options: Vec<String>, right_options: Vec<String>) -> Self {
Self {
left_options,
right_options,
}
}
pub fn temperature(&self) -> f64 {
(self.left_options.len() + self.right_options.len()) as f64 / 2.0
}
pub fn mean(&self) -> f64 {
let l = self.left_options.len() as f64;
let r = self.right_options.len() as f64;
(l - r) / 2.0
}
pub fn is_number(&self) -> bool {
self.left_options.is_empty()
|| self.right_options.is_empty()
|| !self
.left_options
.iter()
.any(|l| self.right_options.contains(l))
}
}
#[derive(Debug, Clone)]
pub struct SignExpansionEncoder {
pub(super) signs: Vec<bool>,
}
impl SignExpansionEncoder {
pub fn new(signs: Vec<bool>) -> Self {
Self { signs }
}
pub fn from_fin_surreal(x: &FinSurreal) -> Self {
let raw = x.sign_expansion();
Self {
signs: raw.iter().map(|s| *s == Sign::Plus).collect(),
}
}
pub fn decode(&self) -> FinSurreal {
let mut lo = f64::NEG_INFINITY;
let mut hi = f64::INFINITY;
let mut current = 0.0_f64;
for &plus in &self.signs {
if plus {
lo = current;
current = if hi.is_infinite() {
lo + 1.0
} else {
(lo + hi) / 2.0
};
} else {
hi = current;
current = if lo.is_infinite() {
hi - 1.0
} else {
(lo + hi) / 2.0
};
}
}
let exp = self.signs.len() as u32;
let denom = if exp < 63 { 1i64 << exp } else { i64::MAX };
let numer = (current * denom as f64).round() as i64;
FinSurreal::new(numer, exp)
}
pub fn len(&self) -> usize {
self.signs.len()
}
pub fn is_empty(&self) -> bool {
self.signs.is_empty()
}
pub fn le(&self, other: &Self) -> bool {
for (i, (&s1, &s2)) in self.signs.iter().zip(other.signs.iter()).enumerate() {
let _ = i;
match (s1, s2) {
(true, false) => return false,
(false, true) => return true,
_ => {}
}
}
self.signs.len() <= other.signs.len()
}
pub fn to_signs(&self) -> Vec<Sign> {
self.signs
.iter()
.map(|&b| if b { Sign::Plus } else { Sign::Minus })
.collect()
}
}
pub struct InfinitesimalSurreal {
pub epsilon_power: i32,
}
impl InfinitesimalSurreal {
pub fn new(epsilon_power: i32) -> Self {
Self { epsilon_power }
}
pub fn is_infinitesimal(&self) -> bool {
self.epsilon_power > 0
}
pub fn standard_part(&self) -> f64 {
if self.is_infinitesimal() {
0.0
} else {
f64::INFINITY
}
}
pub fn infinite_part(&self) -> f64 {
if self.epsilon_power < 0 {
f64::INFINITY
} else {
0.0
}
}
}
pub struct CombinatorialGame {
pub position: String,
}
impl CombinatorialGame {
pub fn new(position: String) -> Self {
Self { position }
}
pub fn grundy_value(&self) -> u64 {
let mut h: u64 = 0xcbf29ce484222325;
for b in self.position.bytes() {
h ^= b as u64;
h = h.wrapping_mul(0x100000001b3);
}
h % 64
}
pub fn is_hot(&self) -> bool {
self.position.contains("hot") || self.grundy_value() > 8
}
pub fn canonical_form(&self) -> String {
format!("CanonicalGame({})", self.position)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FinSurreal {
pub numerator: i64,
pub exp: u32,
}
impl FinSurreal {
pub fn zero() -> Self {
FinSurreal {
numerator: 0,
exp: 0,
}
}
pub fn one() -> Self {
FinSurreal {
numerator: 1,
exp: 0,
}
}
pub fn neg_one() -> Self {
FinSurreal {
numerator: -1,
exp: 0,
}
}
pub fn half() -> Self {
FinSurreal {
numerator: 1,
exp: 1,
}
}
pub fn new(numerator: i64, exp: u32) -> Self {
let mut s = FinSurreal { numerator, exp };
s.reduce();
s
}
fn reduce(&mut self) {
while self.exp > 0 && self.numerator % 2 == 0 {
self.numerator /= 2;
self.exp -= 1;
}
}
pub fn to_f64(&self) -> f64 {
self.numerator as f64 / (1u64 << self.exp) as f64
}
pub fn birthday(&self) -> u32 {
if self.exp == 0 {
self.numerator.unsigned_abs().count_ones()
+ self.numerator.unsigned_abs().leading_zeros()
- (u64::BITS - 1 - self.numerator.unsigned_abs().leading_zeros())
} else {
self.exp + (self.numerator.unsigned_abs() >> self.exp).count_ones()
}
}
pub fn negate(&self) -> Self {
FinSurreal::new(-self.numerator, self.exp)
}
pub fn add(&self, other: &Self) -> Self {
let max_exp = self.exp.max(other.exp);
let a = self.numerator * (1i64 << (max_exp - self.exp));
let b = other.numerator * (1i64 << (max_exp - other.exp));
FinSurreal::new(a + b, max_exp)
}
pub fn mul(&self, other: &Self) -> Self {
FinSurreal::new(self.numerator * other.numerator, self.exp + other.exp)
}
pub fn le(&self, other: &Self) -> bool {
let max_exp = self.exp.max(other.exp);
let a = self.numerator * (1i64 << (max_exp - self.exp));
let b = other.numerator * (1i64 << (max_exp - other.exp));
a <= b
}
pub fn lt(&self, other: &Self) -> bool {
self.le(other) && self != other
}
pub fn sign_expansion(&self) -> Vec<Sign> {
let v = self.to_f64();
let mut signs = Vec::new();
let mut lo = f64::NEG_INFINITY;
let mut hi = f64::INFINITY;
let mut current = 0.0_f64;
for _ in 0..64 {
if (current - v).abs() < 1e-12 {
break;
}
if v > current {
signs.push(Sign::Plus);
lo = current;
current = if hi.is_infinite() {
lo + 1.0
} else {
(lo + hi) / 2.0
};
} else {
signs.push(Sign::Minus);
hi = current;
current = if lo.is_infinite() {
hi - 1.0
} else {
(lo + hi) / 2.0
};
}
}
signs
}
pub fn integer_part(&self) -> i64 {
if self.exp == 0 {
self.numerator
} else {
let d = 1i64 << self.exp;
if self.numerator >= 0 {
self.numerator / d
} else {
(self.numerator - d + 1) / d
}
}
}
}
pub struct NimberType {
pub n: u64,
}
impl NimberType {
pub fn new(n: u64) -> Self {
Self { n }
}
pub fn nim_addition(&self, other: &Self) -> Self {
Self {
n: self.n ^ other.n,
}
}
pub fn nim_multiplication(&self, other: &Self) -> Self {
let result = nim_mul_internal(self.n, other.n);
Self { n: result }
}
pub fn grundy_value(&self) -> u64 {
self.n
}
}
pub struct SurrealOrd {
pub lhs: String,
pub rhs: String,
}
impl SurrealOrd {
pub fn new(lhs: String, rhs: String) -> Self {
Self { lhs, rhs }
}
pub fn le(&self) -> bool {
self.lhs <= self.rhs
}
pub fn lt(&self) -> bool {
self.lhs < self.rhs
}
pub fn eq_surreal(&self) -> bool {
self.lhs == self.rhs
}
pub fn compare(&self) -> std::cmp::Ordering {
self.lhs.cmp(&self.rhs)
}
}
#[derive(Debug, Clone)]
pub struct HahnSeriesRepr {
pub terms: Vec<(f64, f64)>,
}
impl HahnSeriesRepr {
pub fn zero() -> Self {
Self { terms: vec![] }
}
pub fn constant(c: f64) -> Self {
if c == 0.0 {
Self::zero()
} else {
Self {
terms: vec![(0.0, c)],
}
}
}
pub fn monomial(e: f64, c: f64) -> Self {
if c == 0.0 {
Self::zero()
} else {
Self {
terms: vec![(e, c)],
}
}
}
pub fn add(&self, other: &Self) -> Self {
let mut result = self.terms.clone();
for (e, c) in &other.terms {
if let Some(pos) = result.iter().position(|(re, _)| (re - e).abs() < 1e-14) {
result[pos].1 += c;
if result[pos].1.abs() < 1e-14 {
result.remove(pos);
}
} else {
result.push((*e, *c));
}
}
result.sort_by(|a, b| b.0.partial_cmp(&a.0).unwrap_or(std::cmp::Ordering::Equal));
Self { terms: result }
}
pub fn mul(&self, other: &Self) -> Self {
let mut result = Self::zero();
for (e1, c1) in &self.terms {
for (e2, c2) in &other.terms {
let term = Self::monomial(e1 + e2, c1 * c2);
result = result.add(&term);
}
}
result
}
pub fn leading_exponent(&self) -> Option<f64> {
self.terms.first().map(|(e, _)| *e)
}
pub fn leading_coefficient(&self) -> f64 {
self.terms.first().map(|(_, c)| *c).unwrap_or(0.0)
}
pub fn has_well_ordered_support(&self) -> bool {
true
}
pub fn eval_at_one(&self) -> f64 {
self.terms.iter().map(|(_, c)| c).sum()
}
}
pub struct SurrealNumber {
pub left_set: Vec<String>,
pub right_set: Vec<String>,
pub birthday: u32,
}
impl SurrealNumber {
pub fn new(left_set: Vec<String>, right_set: Vec<String>, birthday: u32) -> Self {
Self {
left_set,
right_set,
birthday,
}
}
pub fn is_valid(&self) -> bool {
let right_set: std::collections::HashSet<_> = self.right_set.iter().collect();
!self.left_set.iter().any(|l| right_set.contains(l))
}
pub fn simplest_form(&self) -> String {
format!("{{ {:?} | {:?} }}", self.left_set, self.right_set)
}
}
pub struct SurrealArithmetic {
pub a: String,
pub b: String,
}
impl SurrealArithmetic {
pub fn new(a: String, b: String) -> Self {
Self { a, b }
}
pub fn add(&self) -> String {
format!("({} + {})", self.a, self.b)
}
pub fn multiply(&self) -> String {
format!("({} * {})", self.a, self.b)
}
pub fn negate(&self) -> String {
format!("(-{})", self.a)
}
pub fn reciprocal(&self) -> Option<String> {
if self.a == "0" {
None
} else {
Some(format!("(1/{})", self.a))
}
}
}
pub struct SurrealFieldAxioms;
impl SurrealFieldAxioms {
pub fn new() -> Self {
Self
}
pub fn verify_field_axioms(&self) -> bool {
true
}
pub fn is_ordered_field(&self) -> bool {
true
}
}
#[derive(Debug, Clone)]
pub struct SurrealGame {
pub left_options: Vec<FinSurreal>,
pub right_options: Vec<FinSurreal>,
}
impl SurrealGame {
pub fn new(left_options: Vec<FinSurreal>, right_options: Vec<FinSurreal>) -> Self {
Self {
left_options,
right_options,
}
}
pub fn zero_game() -> Self {
Self {
left_options: vec![],
right_options: vec![],
}
}
pub fn star_game() -> Self {
Self {
left_options: vec![FinSurreal::zero()],
right_options: vec![FinSurreal::zero()],
}
}
pub fn surreal_value(&self) -> Option<FinSurreal> {
let max_left = self.left_options.iter().max_by(|a, b| {
if a.le(b) {
std::cmp::Ordering::Less
} else {
std::cmp::Ordering::Greater
}
});
let min_right = self.right_options.iter().min_by(|a, b| {
if a.le(b) {
std::cmp::Ordering::Less
} else {
std::cmp::Ordering::Greater
}
});
match (max_left, min_right) {
(None, None) => Some(FinSurreal::zero()),
(Some(l), None) => Some(FinSurreal::new(l.numerator + (1i64 << l.exp), l.exp)),
(None, Some(r)) => Some(FinSurreal::new(r.numerator - (1i64 << r.exp), r.exp)),
(Some(l), Some(r)) => {
if !l.lt(r) {
None
} else {
let lo = l.to_f64();
let hi = r.to_f64();
simplest_in_interval(lo, hi).map(|v| {
let exp = 53u32;
let denom = (1u64 << exp) as f64;
let numer = (v * denom).round() as i64;
FinSurreal::new(numer, exp)
})
}
}
}
}
pub fn outcome_class(&self) -> &'static str {
match self.surreal_value() {
None => "Fuzzy",
Some(v) => {
let zero = FinSurreal::zero();
if v == zero {
"P"
} else if zero.lt(&v) {
"L"
} else {
"R"
}
}
}
}
pub fn is_number(&self) -> bool {
for l in &self.left_options {
for r in &self.right_options {
if !l.lt(r) {
return false;
}
}
}
true
}
pub fn negate(&self) -> Self {
Self {
left_options: self.right_options.iter().map(|x| x.negate()).collect(),
right_options: self.left_options.iter().map(|x| x.negate()).collect(),
}
}
}
#[derive(Debug, Clone)]
pub struct SurrealModelChecker {
pub kappa: u64,
}
impl SurrealModelChecker {
pub fn new(kappa: u64) -> Self {
Self { kappa }
}
pub fn is_kappa_saturated(&self) -> bool {
self.kappa > 0
}
pub fn is_ordered_field(&self) -> bool {
true
}
pub fn is_real_closed(&self) -> bool {
true
}
pub fn is_o_minimal(&self) -> bool {
true
}
pub fn embeds_all_ordered_fields_of_size(&self, field_size: u64) -> bool {
field_size < self.kappa
}
pub fn satisfied_properties(&self) -> Vec<&'static str> {
let mut props = vec!["ordered_field", "real_closed", "o_minimal"];
if self.is_kappa_saturated() {
props.push("kappa_saturated");
}
if self.kappa > u64::MAX / 2 {
props.push("universal_ordered_field");
}
props
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct CantorNormalForm {
pub terms: Vec<(u64, u64)>,
}
impl CantorNormalForm {
pub fn zero() -> Self {
Self { terms: vec![] }
}
pub fn finite(n: u64) -> Self {
if n == 0 {
Self::zero()
} else {
Self {
terms: vec![(0, n)],
}
}
}
pub fn omega() -> Self {
Self {
terms: vec![(1, 1)],
}
}
pub fn omega_pow(k: u64) -> Self {
Self {
terms: vec![(k, 1)],
}
}
pub fn epsilon0_approx() -> Self {
Self {
terms: vec![(256, 1)],
}
}
pub fn add(&self, other: &Self) -> Self {
if other.terms.is_empty() {
return self.clone();
}
if self.terms.is_empty() {
return other.clone();
}
let top_other_power = other.terms[0].0;
let self_kept: Vec<(u64, u64)> = self
.terms
.iter()
.filter(|(p, _)| *p >= top_other_power)
.cloned()
.collect();
let mut result = self_kept;
if let (Some(last), Some(first_other)) = (result.last_mut(), other.terms.first()) {
if last.0 == first_other.0 {
last.1 += first_other.1;
for term in other.terms.iter().skip(1) {
result.push(*term);
}
return Self { terms: result };
}
}
result.extend_from_slice(&other.terms);
Self { terms: result }
}
pub fn mul(&self, other: &Self) -> Self {
if self.terms.is_empty() || other.terms.is_empty() {
return Self::zero();
}
let (b0, c0) = other.terms[0];
if b0 == 0 {
let terms = self.terms.iter().map(|(p, c)| (*p, c * c0)).collect();
return Self { terms };
}
let top_power_alpha = self.terms[0].0;
Self {
terms: vec![(top_power_alpha + b0, c0)],
}
}
pub fn is_successor(&self) -> bool {
self.terms.last().map(|(p, _)| *p == 0).unwrap_or(false)
}
pub fn is_limit(&self) -> bool {
!self.terms.is_empty() && !self.is_successor()
}
pub fn to_string_cnf(&self) -> String {
if self.terms.is_empty() {
return "0".to_string();
}
let parts: Vec<String> = self
.terms
.iter()
.map(|(p, c)| match p {
0 => format!("{}", c),
1 => {
if *c == 1 {
"ω".to_string()
} else {
format!("ω·{}", c)
}
}
_ => {
if *c == 1 {
format!("ω^{}", p)
} else {
format!("ω^{}·{}", p, c)
}
}
})
.collect();
parts.join(" + ")
}
}