use geonum::*;
use std::f64::consts::PI;
const EPSILON: f64 = 1e-9;
#[test]
fn it_projects_an_origin_geonum_into_a_positioned_unit_vector() {
let q = Geonum::new_from_cartesian(1.0, 1.0);
let p = q.project(&Geonum::new(1.0, 0.0, 1.0)); let pq = q.project(&Geonum::new(1.0, 1.0, 2.0));
assert!(
p.near_mag(1.0) && p.angle.grade() == 0,
"Q's x-shadow is P = [1, 0]"
);
assert!(
pq.near_mag(1.0) && pq.angle.grade() == 1,
"the y-shadow is a unit vector at π/2"
);
assert!(pq.angle.near_rad(PI / 2.0), "its angle is π/2");
let head = p + pq;
assert!(
head.near_mag(q.mag) && head.angle.grade() == q.angle.grade(),
"P + unit reaches Q — the shadows reassemble the point"
);
}
#[test]
fn it_creates_a_line_from_a_single_angle() {
let theta = Angle::new(1.0, 4.0);
let line = Geonum::new_with_angle(1.0, theta);
assert!(line.near_mag(1.0));
assert_eq!(line.angle, theta, "from the single angle θ alone");
for r in [2.0, 0.5, -3.0, 1000.0] {
let pt = line.scale(r);
assert!(pt.near_mag(r.abs()), "point at r is one op");
assert!(
pt.reject(&line).mag < EPSILON,
"every [r, θ] is on the line"
);
}
}
#[test]
fn it_gives_the_line_its_magnitude_as_one_op() {
let theta = Angle::new(1.0, 4.0);
let line = Geonum::new(1.0, 0.0, 1.0).scale_rotate(2.0, theta);
assert!(
line.near_mag(2.0) && line.angle == theta,
"[2, π/4], length and direction"
);
let s = 2.0_f64.sqrt();
let (x, y) = coords(line);
assert!(
(x - s).abs() < EPSILON && (y - s).abs() < EPSILON,
"tip (√2, √2), projected last"
);
}
#[test]
fn it_keeps_the_angle_shapeless() {
let near = Geonum::new(1.0, 1.0, 4.0);
let far = Geonum::new(1000.0, 1.0, 4.0);
assert_eq!(
near.angle, far.angle,
"same angle at any distance — the angle is the line"
);
}
#[test]
fn it_shows_projection_is_a_cosine_scaled_multiply() {
let g = Geonum::new(3.0, 1.0, 6.0); let onto = Angle::new(1.0, 4.0);
let projected = g.project(&Geonum::new_with_angle(1.0, onto));
let cos_gap = g.angle.project(onto); let rebuilt = g.scale_rotate(cos_gap, onto - g.angle);
let via_multiply = g * Geonum::new_with_angle(cos_gap, onto - g.angle);
assert!(
projected.near(&rebuilt),
"project == scale_rotate(cos(gap), → target)"
);
assert!(
projected.near(&via_multiply),
"and both are g * [cos(gap), gap] — multiply"
);
}
#[test]
fn it_projects_a_point_against_the_single_angle() {
let line = Geonum::new_with_angle(1.0, Angle::new(1.0, 4.0));
let x = Geonum::new_from_cartesian(2.0, 0.0);
let (fx, fy) = coords(x.project(&line));
assert!(
(fx - 1.0).abs() < EPSILON && (fy - 1.0).abs() < EPSILON,
"foot of (2,0) on y=x is (1,1)"
);
assert!(
(x.reject(&line).mag - 2.0_f64.sqrt()).abs() < EPSILON,
"offset = √2"
);
}
#[test]
fn it_reads_the_swept_area_from_the_summed_rotation() {
let p1 = Geonum::new_from_cartesian(0.0, 1.0); let p2 = Geonum::new_from_cartesian(1.0, 1.0);
let net = (p1.angle.grade_angle() - p2.angle.grade_angle()).abs();
assert!(
(net - PI / 4.0).abs() < EPSILON,
"the rotations add to a single angle, π/4"
);
assert!(
(0.5 * p1.wedge(&p2).mag - 0.5).abs() < EPSILON,
"the wedge reads the swept area = ½"
);
}
#[test]
fn it_accumulates_area_per_edge_over_a_polyline() {
let p0 = Geonum::new_from_cartesian(0.0, 1.0);
let p1 = Geonum::new_from_cartesian(2.0, 1.0);
let p2 = Geonum::new_from_cartesian(2.0, 0.0);
let swept = 0.5 * (p0.wedge(&p1).mag + p1.wedge(&p2).mag);
let boundary = 0.5 * p0.wedge(&p2).mag;
assert!(
(swept - 2.0).abs() < EPSILON,
"area accumulates per edge = 2"
);
assert!(
(swept - boundary).abs() > 0.5,
"it does not telescope — the bend carries real area"
);
}
#[test]
fn it_unifies_line_and_polyline_as_one_weighted_angle_sum() {
let a = Geonum::new_from_cartesian(0.0, 1.0);
let b = Geonum::new_from_cartesian(2.0, 0.0);
let samples: Vec<Geonum> = (0..=10)
.map(|k| a + (b - a).scale(k as f64 / 10.0))
.collect();
assert!(
(weighted_angle_area(&samples) - 0.5 * a.wedge(&b).mag).abs() < EPSILON,
"the line's redundant angles collapse to the single boundary wedge"
);
let path = [
Geonum::new_from_cartesian(0.0, 1.0),
Geonum::new_from_cartesian(2.0, 1.0),
Geonum::new_from_cartesian(2.0, 0.0),
];
assert!(
(weighted_angle_area(&path) - 2.0).abs() < EPSILON,
"the polyline keeps one weighted angle per bend — same operation, more terms"
);
}
#[test]
fn it_reads_the_shape_from_the_weighted_collection() {
let path = [
Geonum::new_from_cartesian(0.0, 1.0),
Geonum::new_from_cartesian(2.0, 1.0),
Geonum::new_from_cartesian(2.0, 0.0),
];
let weighted: GeoCollection = path.windows(2).map(|w| w[0].wedge(&w[1])).collect();
assert!(
(0.5 * weighted.total_magnitude() - 2.0).abs() < EPSILON,
"the area is ½·Σ of the weighted entries — read from the collection, not an angle"
);
}
#[test]
fn it_collapses_the_constant_weight_integral_to_a_boundary_read() {
let theta = PI / 2.0;
let sector = 0.5 * theta;
let coarse = inscribed_area(10, theta);
let fine = inscribed_area(100_000, theta);
assert!(
coarse < fine && fine < sector,
"shrinking the spacing closes the gap from below"
);
assert!(
(sector - PI / 4.0).abs() < EPSILON,
"½r²θ = π/4, the boundary the chords approach"
);
assert!(
(sector - fine).abs() < 1e-7,
"the limit closes on the boundary read it collapses to"
);
}
#[test]
fn it_collapses_a_varying_radius_when_its_square_is_integrable_in_theta() {
let theta = 2.0_f64; let boundary = 0.5 * theta.powi(3) / 3.0; assert!(
(boundary - theta.powi(3) / 6.0).abs() < EPSILON,
"the boundary read is θ³/6 via r³/3"
);
let n = 200_000;
let pts: Vec<Geonum> = (0..=n)
.map(|k| {
let t = theta * k as f64 / n as f64;
Geonum::new_with_angle(t, Angle::new(t, PI)) })
.collect();
assert!(
(boundary - weighted_angle_area(&pts)).abs() < 1e-3,
"the chords converge to ½·r³/3 — the spiral collapses, varying radius and all"
);
}
#[test]
fn it_collapses_the_exponential_spiral() {
let big = 1.0_f64; let (r_a, r_b) = (0.0_f64.exp(), big.exp()); let boundary = (r_b * r_b - r_a * r_a) / 4.0;
let n = 200_000;
let pts: Vec<Geonum> = (0..=n)
.map(|k| {
let t = big * k as f64 / n as f64;
Geonum::new_with_angle(t.exp(), Angle::new(t, PI)) })
.collect();
assert!(
(boundary - weighted_angle_area(&pts)).abs() < 1e-3,
"r = e^θ collapses to (r_b² − r_a²)/4 — read from the boundary magnitudes, eˣ its own antiderivative"
);
}
#[test]
fn it_squares_an_angle_as_a_rotation() {
let theta = Angle::new(1.0, 2.0);
let squared = theta * (PI / 2.0);
assert!(
squared.near_rad((PI / 2.0) * (PI / 2.0)),
"θ scaled by θ is θ² — the square is a rotation living in the angle"
);
let powered = Geonum::new_with_angle(3.0, theta).pow(2.0);
assert!(powered.near_mag(9.0), "pow squares the magnitude: 3² = 9");
assert!(
powered.angle.near_rad(PI),
"pow doubles the angle: 2·π/2 = π, not (π/2)²"
);
}
#[test]
fn it_derives_the_definite_integral_of_cos_from_the_boundary() {
let antideriv = |x: Angle| unit(x).integrate().angle.cos_sin().0;
for &(a, b) in &[
(Angle::new(0.0, 1.0), Angle::new(1.0, 2.0)), (Angle::new(1.0, 6.0), Angle::new(2.0, 3.0)), ] {
let derived = antideriv(b) - antideriv(a);
let want = b.grade_angle().sin() - a.grade_angle().sin();
assert!(
(derived - want).abs() < EPSILON,
"∫cos = sin(b) − sin(a), a boundary read"
);
}
}
fn coords(g: Geonum) -> (f64, f64) {
(
g.mag * g.angle.project(Angle::new(0.0, 1.0)),
g.mag * g.angle.project(Angle::new(1.0, 2.0)),
)
}
fn unit(x: Angle) -> Geonum {
Geonum::new_with_angle(1.0, x)
}
fn weighted_angle_area(points: &[Geonum]) -> f64 {
points.windows(2).map(|w| 0.5 * w[0].wedge(&w[1]).mag).sum()
}
fn inscribed_area(n: usize, theta: f64) -> f64 {
let pts: Vec<Geonum> = (0..=n)
.map(|k| Geonum::new(1.0, theta * k as f64 / n as f64, PI)) .collect();
weighted_angle_area(&pts)
}