File size: 4,810 Bytes
8ef2d83 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
//! # Point
//!
//! A position in dimensional space. The fundamental primitive.
//!
//! Dimensionality is NOT fixed - configure it for your model.
//! 768-dim, 1024-dim, 4096-dim, or any size you need.
//!
//! The point IS the thought's position.
//! The position IS its relationship to all other thoughts.
/// A point in dimensional space
#[derive(Clone, Debug, PartialEq)]
pub struct Point {
dims: Vec<f32>,
}
impl Point {
/// Create a new point from a vector of dimensions
///
/// # Example
/// ```
/// use arms::Point;
/// let p = Point::new(vec![1.0, 2.0, 3.0]);
/// assert_eq!(p.dimensionality(), 3);
/// ```
pub fn new(dims: Vec<f32>) -> Self {
Self { dims }
}
/// Create an origin point (all zeros) of given dimensionality
///
/// # Example
/// ```
/// use arms::Point;
/// let origin = Point::origin(768);
/// assert_eq!(origin.dimensionality(), 768);
/// assert!(origin.dims().iter().all(|&x| x == 0.0));
/// ```
pub fn origin(dims: usize) -> Self {
Self {
dims: vec![0.0; dims],
}
}
/// Get the dimensionality of this point
pub fn dimensionality(&self) -> usize {
self.dims.len()
}
/// Access the dimensions as a slice
pub fn dims(&self) -> &[f32] {
&self.dims
}
/// Mutable access to dimensions
pub fn dims_mut(&mut self) -> &mut [f32] {
&mut self.dims
}
/// Calculate the magnitude (L2 norm) of this point
///
/// # Example
/// ```
/// use arms::Point;
/// let p = Point::new(vec![3.0, 4.0]);
/// assert!((p.magnitude() - 5.0).abs() < 0.0001);
/// ```
pub fn magnitude(&self) -> f32 {
self.dims.iter().map(|x| x * x).sum::<f32>().sqrt()
}
/// Check if this point is normalized (magnitude ≈ 1.0)
pub fn is_normalized(&self) -> bool {
let mag = self.magnitude();
(mag - 1.0).abs() < 0.001
}
/// Return a normalized copy of this point
///
/// If magnitude is zero, returns a clone of self.
///
/// # Example
/// ```
/// use arms::Point;
/// let p = Point::new(vec![3.0, 4.0]);
/// let normalized = p.normalize();
/// assert!(normalized.is_normalized());
/// ```
pub fn normalize(&self) -> Self {
let mag = self.magnitude();
if mag == 0.0 {
return self.clone();
}
Self {
dims: self.dims.iter().map(|x| x / mag).collect(),
}
}
/// Add another point to this one (element-wise)
pub fn add(&self, other: &Point) -> Self {
assert_eq!(
self.dimensionality(),
other.dimensionality(),
"Points must have same dimensionality"
);
Self {
dims: self
.dims
.iter()
.zip(other.dims.iter())
.map(|(a, b)| a + b)
.collect(),
}
}
/// Scale this point by a scalar
pub fn scale(&self, scalar: f32) -> Self {
Self {
dims: self.dims.iter().map(|x| x * scalar).collect(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_new_point() {
let p = Point::new(vec![1.0, 2.0, 3.0]);
assert_eq!(p.dimensionality(), 3);
assert_eq!(p.dims(), &[1.0, 2.0, 3.0]);
}
#[test]
fn test_origin() {
let origin = Point::origin(768);
assert_eq!(origin.dimensionality(), 768);
assert!(origin.dims().iter().all(|&x| x == 0.0));
}
#[test]
fn test_magnitude() {
let p = Point::new(vec![3.0, 4.0]);
assert!((p.magnitude() - 5.0).abs() < 0.0001);
}
#[test]
fn test_normalize() {
let p = Point::new(vec![3.0, 4.0]);
let normalized = p.normalize();
assert!(normalized.is_normalized());
assert!((normalized.dims()[0] - 0.6).abs() < 0.0001);
assert!((normalized.dims()[1] - 0.8).abs() < 0.0001);
}
#[test]
fn test_normalize_zero() {
let p = Point::origin(3);
let normalized = p.normalize();
assert_eq!(normalized.dims(), &[0.0, 0.0, 0.0]);
}
#[test]
fn test_add() {
let a = Point::new(vec![1.0, 2.0]);
let b = Point::new(vec![3.0, 4.0]);
let c = a.add(&b);
assert_eq!(c.dims(), &[4.0, 6.0]);
}
#[test]
fn test_scale() {
let p = Point::new(vec![1.0, 2.0]);
let scaled = p.scale(2.0);
assert_eq!(scaled.dims(), &[2.0, 4.0]);
}
#[test]
#[should_panic(expected = "same dimensionality")]
fn test_add_different_dims_panics() {
let a = Point::new(vec![1.0, 2.0]);
let b = Point::new(vec![1.0, 2.0, 3.0]);
let _ = a.add(&b);
}
}
|