use oxilean_kernel::{BinderInfo, Declaration, Environment, Expr, Level, Name};
use super::functions::*;
use std::collections::HashMap;
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct Divisor {
pub components: Vec<(String, i32)>,
pub is_effective: bool,
pub is_prime: bool,
}
#[allow(dead_code)]
impl Divisor {
pub fn zero() -> Self {
Self {
components: Vec::new(),
is_effective: true,
is_prime: false,
}
}
pub fn prime(name: &str) -> Self {
Self {
components: vec![(name.to_string(), 1)],
is_effective: true,
is_prime: true,
}
}
pub fn degree(&self) -> i32 {
self.components.iter().map(|(_, c)| c).sum()
}
pub fn linear_equiv_description(&self) -> String {
format!("Div class of degree {}", self.degree())
}
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct ChernClass {
pub vector_bundle: String,
pub rank: usize,
pub classes: Vec<String>,
}
#[allow(dead_code)]
impl ChernClass {
pub fn new(bundle: &str, rank: usize) -> Self {
let classes = (0..=rank).map(|i| format!("c_{}({})", i, bundle)).collect();
Self {
vector_bundle: bundle.to_string(),
rank,
classes,
}
}
pub fn total_chern_class(&self) -> String {
self.classes.join(" + ")
}
pub fn grr_applies(&self) -> bool {
true
}
}
#[derive(Debug, Clone)]
pub struct AffineVariety {
pub ambient_dim: usize,
pub equations: Vec<String>,
}
impl AffineVariety {
pub fn new(ambient_dim: usize, equations: Vec<String>) -> Self {
Self {
ambient_dim,
equations,
}
}
pub fn empty(n: usize) -> Self {
Self::new(n, vec!["1".to_string()])
}
pub fn affine_space(n: usize) -> Self {
Self::new(n, vec![])
}
pub fn num_equations(&self) -> usize {
self.equations.len()
}
pub fn codimension_estimate(&self) -> usize {
self.equations.len().min(self.ambient_dim)
}
pub fn dimension_estimate(&self) -> usize {
self.ambient_dim.saturating_sub(self.codimension_estimate())
}
pub fn is_empty_variety(&self) -> bool {
self.equations.iter().any(|eq| eq.trim() == "1")
}
pub fn is_full_space(&self) -> bool {
self.equations.is_empty()
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ProjectivePoint {
pub coords: Vec<i64>,
}
impl ProjectivePoint {
pub fn new(coords: Vec<i64>) -> Option<Self> {
if coords.iter().all(|&c| c == 0) {
None
} else {
Some(Self { coords })
}
}
pub fn dim(&self) -> usize {
self.coords.len().saturating_sub(1)
}
pub fn normalize(&self) -> Self {
let g = self
.coords
.iter()
.fold(0i64, |acc, &x| gcd(acc.abs(), x.abs()));
if g == 0 {
return self.clone();
}
let sign = self
.coords
.iter()
.find(|&&c| c != 0)
.map(|&c| if c < 0 { -1i64 } else { 1i64 })
.unwrap_or(1);
Self {
coords: self.coords.iter().map(|&c| sign * c / g).collect(),
}
}
pub fn equiv(&self, other: &ProjectivePoint) -> bool {
if self.coords.len() != other.coords.len() {
return false;
}
let n = self.coords.len();
for i in 0..n {
for j in 0..n {
if self.coords[i] * other.coords[j] != self.coords[j] * other.coords[i] {
return false;
}
}
}
true
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DivisorClass {
pub degree: i64,
pub genus: i64,
pub label: String,
}
impl DivisorClass {
pub fn new(degree: i64, genus: i64, label: impl Into<String>) -> Self {
Self {
degree,
genus,
label: label.into(),
}
}
pub fn zero(genus: i64) -> Self {
Self::new(0, genus, "O")
}
pub fn canonical(genus: i64) -> Self {
Self::new(2 * genus - 2, genus, "K")
}
pub fn add(&self, other: &DivisorClass) -> Self {
assert_eq!(self.genus, other.genus, "genus must match");
Self::new(
self.degree + other.degree,
self.genus,
format!("{}+{}", self.label, other.label),
)
}
pub fn neg(&self) -> Self {
Self::new(-self.degree, self.genus, format!("-{}", self.label))
}
pub fn sub(&self, other: &DivisorClass) -> Self {
self.add(&other.neg())
}
pub fn is_effective(&self) -> bool {
self.degree >= 0
}
pub fn is_canonical(&self) -> bool {
self.degree == 2 * self.genus - 2
}
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct ProjectiveVariety {
pub name: String,
pub ambient_dim: usize,
pub degree: usize,
pub is_smooth: bool,
pub is_irreducible: bool,
}
#[allow(dead_code)]
impl ProjectiveVariety {
pub fn projective_space(n: usize) -> Self {
Self {
name: format!("P^{}", n),
ambient_dim: n,
degree: 1,
is_smooth: true,
is_irreducible: true,
}
}
pub fn hypersurface(n: usize, d: usize) -> Self {
Self {
name: format!("V_{}(P^{})", d, n),
ambient_dim: n,
degree: d,
is_smooth: true,
is_irreducible: true,
}
}
pub fn expected_dim(&self) -> usize {
if self.ambient_dim > 0 {
self.ambient_dim - 1
} else {
0
}
}
pub fn bezout_bound(&self, other_degree: usize) -> usize {
self.degree * other_degree
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AffineScheme {
pub ring: String,
}
impl AffineScheme {
pub fn new(ring: impl Into<String>) -> Self {
Self { ring: ring.into() }
}
pub fn spec_z() -> Self {
Self::new("Int")
}
pub fn affine_n_space(base_ring: &str, n: usize) -> Self {
let vars: Vec<String> = (1..=n).map(|i| format!("x{}", i)).collect();
Self::new(format!("{}[{}]", base_ring, vars.join(", ")))
}
pub fn krull_dim_estimate(&self) -> Option<usize> {
if self.ring.contains('[') {
let inner = self.ring.split('[').nth(1)?;
let vars = inner.trim_end_matches(']');
Some(vars.split(',').count())
} else if self.ring == "Int" || self.ring == "Z" {
Some(1)
} else {
None
}
}
}
#[derive(Debug, Clone)]
pub struct Sheaf<T: Clone> {
sections: std::collections::HashMap<String, T>,
restriction_labels: Vec<(String, String)>,
}
impl<T: Clone> Sheaf<T> {
pub fn new() -> Self {
Self {
sections: std::collections::HashMap::new(),
restriction_labels: Vec::new(),
}
}
pub fn add_section(&mut self, open_set: impl Into<String>, section: T) {
self.sections.insert(open_set.into(), section);
}
pub fn section(&self, open_set: &str) -> Option<&T> {
self.sections.get(open_set)
}
pub fn add_restriction(&mut self, source: impl Into<String>, target: impl Into<String>) {
self.restriction_labels.push((source.into(), target.into()));
}
pub fn num_sections(&self) -> usize {
self.sections.len()
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ProjectiveSpace {
pub dim: usize,
}
impl ProjectiveSpace {
pub fn new(dim: usize) -> Self {
Self { dim }
}
pub fn projective_line() -> Self {
Self::new(1)
}
pub fn projective_plane() -> Self {
Self::new(2)
}
pub fn num_coordinates(&self) -> usize {
self.dim + 1
}
pub fn euler_characteristic(&self) -> i64 {
(self.dim as i64) + 1
}
pub fn betti_numbers(&self) -> Vec<u64> {
let mut betti = vec![0u64; 2 * self.dim + 1];
for k in 0..=self.dim {
betti[2 * k] = 1;
}
betti
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Morphism {
pub source: String,
pub target: String,
}
impl Morphism {
pub fn new(source: impl Into<String>, target: impl Into<String>) -> Self {
Self {
source: source.into(),
target: target.into(),
}
}
pub fn identity(scheme: impl Into<String>) -> Self {
let s = scheme.into();
Self {
source: s.clone(),
target: s,
}
}
pub fn is_identity(&self) -> bool {
self.source == self.target
}
pub fn compose(&self, other: &Morphism) -> Option<Morphism> {
if self.target == other.source {
Some(Morphism::new(self.source.clone(), other.target.clone()))
} else {
None
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum EllipticCurvePoint {
Infinity,
Affine { x: i64, y: i64 },
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct ModuliProblem {
pub objects: String,
pub equivalence: String,
pub coarse_moduli_space: Option<String>,
pub has_fine_moduli: bool,
}
#[allow(dead_code)]
impl ModuliProblem {
pub fn elliptic_curves() -> Self {
Self {
objects: "elliptic curves over k".to_string(),
equivalence: "isomorphism".to_string(),
coarse_moduli_space: Some("A^1_j".to_string()),
has_fine_moduli: false,
}
}
pub fn vector_bundles(n: usize, degree: i32) -> Self {
Self {
objects: format!("rank-{} bundles of degree {}", n, degree),
equivalence: "S-equivalence".to_string(),
coarse_moduli_space: Some(format!("M({},{})", n, degree)),
has_fine_moduli: false,
}
}
pub fn fine_moduli_description(&self) -> String {
if self.has_fine_moduli {
format!("Fine moduli space exists for {}", self.objects)
} else {
format!("Only coarse moduli exists for {}", self.objects)
}
}
}
#[derive(Debug, Clone)]
pub struct EllipticCurveF {
pub a: i64,
pub b: i64,
pub p: i64,
}
impl EllipticCurveF {
pub fn new(a: i64, b: i64, p: i64) -> Self {
Self { a, b, p }
}
pub fn is_nonsingular(&self) -> bool {
let disc = mod_reduce(
4 * pow_mod(self.a, 3, self.p) + 27 * pow_mod(self.b, 2, self.p),
self.p,
);
disc != 0
}
pub fn on_curve(&self, x: i64, y: i64) -> bool {
let lhs = mod_reduce(y * y, self.p);
let rhs = mod_reduce(pow_mod(x, 3, self.p) + self.a * x + self.b, self.p);
lhs == rhs
}
pub fn points(&self) -> Vec<EllipticCurvePoint> {
let mut pts = vec![EllipticCurvePoint::Infinity];
for x in 0..self.p {
for y in 0..self.p {
if self.on_curve(x, y) {
pts.push(EllipticCurvePoint::Affine { x, y });
}
}
}
pts
}
pub fn point_count(&self) -> usize {
self.points().len()
}
pub fn add(&self, p_pt: &EllipticCurvePoint, q_pt: &EllipticCurvePoint) -> EllipticCurvePoint {
match (p_pt, q_pt) {
(EllipticCurvePoint::Infinity, q) => q.clone(),
(p, EllipticCurvePoint::Infinity) => p.clone(),
(
EllipticCurvePoint::Affine { x: x1, y: y1 },
EllipticCurvePoint::Affine { x: x2, y: y2 },
) => {
if x1 == x2 && mod_reduce(y1 + y2, self.p) == 0 {
return EllipticCurvePoint::Infinity;
}
let lambda = if x1 == x2 && y1 == y2 {
let num = mod_reduce(3 * pow_mod(*x1, 2, self.p) + self.a, self.p);
let den = mod_reduce(2 * y1, self.p);
mod_mul(num, mod_inv(den, self.p), self.p)
} else {
let num = mod_reduce(y2 - y1, self.p);
let den = mod_reduce(x2 - x1, self.p);
mod_mul(num, mod_inv(den, self.p), self.p)
};
let x3 = mod_reduce(pow_mod(lambda, 2, self.p) - x1 - x2, self.p);
let y3 = mod_reduce(lambda * (x1 - x3) - y1, self.p);
EllipticCurvePoint::Affine { x: x3, y: y3 }
}
}
}
pub fn scalar_mul(&self, n: u64, pt: &EllipticCurvePoint) -> EllipticCurvePoint {
let mut result = EllipticCurvePoint::Infinity;
let mut addend = pt.clone();
let mut k = n;
while k > 0 {
if k & 1 == 1 {
result = self.add(&result, &addend);
}
addend = self.add(&addend, &addend);
k >>= 1;
}
result
}
pub fn point_order(&self, pt: &EllipticCurvePoint, max_order: u64) -> Option<u64> {
if matches!(pt, EllipticCurvePoint::Infinity) {
return Some(1);
}
let mut current = pt.clone();
for n in 1..=max_order {
current = self.add(¤t, pt);
if matches!(current, EllipticCurvePoint::Infinity) {
return Some(n + 1);
}
}
None
}
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct AffineSchemeData {
pub ring: String,
pub is_integral: bool,
pub is_noetherian: bool,
pub dimension: Option<usize>,
}
#[allow(dead_code)]
impl AffineSchemeData {
pub fn affine_space(n: usize) -> Self {
Self {
ring: format!("k[x1,...,x{}]", n),
is_integral: true,
is_noetherian: true,
dimension: Some(n),
}
}
pub fn point() -> Self {
Self {
ring: "k".to_string(),
is_integral: true,
is_noetherian: true,
dimension: Some(0),
}
}
pub fn is_variety(&self) -> bool {
self.is_integral && self.is_noetherian
}
}