use super::FixedPoint;
use super::FixedVector;
use super::FixedMatrix;
use super::tensor::Tensor;
use crate::fixed_point::core_types::errors::OverflowDetected;
#[cfg(table_format = "q64_64")]
const PROFILE_TAG: u8 = 0x01;
#[cfg(table_format = "q128_128")]
const PROFILE_TAG: u8 = 0x02;
#[cfg(table_format = "q256_256")]
const PROFILE_TAG: u8 = 0x03;
#[cfg(table_format = "q32_32")]
const PROFILE_TAG: u8 = 0x04;
#[cfg(table_format = "q16_16")]
const PROFILE_TAG: u8 = 0x05;
#[cfg(table_format = "q64_64")]
const RAW_BYTE_LEN: usize = 16;
#[cfg(table_format = "q128_128")]
const RAW_BYTE_LEN: usize = 32;
#[cfg(table_format = "q256_256")]
const RAW_BYTE_LEN: usize = 64;
#[cfg(table_format = "q32_32")]
const RAW_BYTE_LEN: usize = 8;
#[cfg(table_format = "q16_16")]
const RAW_BYTE_LEN: usize = 4;
impl FixedPoint {
pub fn to_bytes(&self) -> Vec<u8> {
let mut bytes = Vec::with_capacity(1 + RAW_BYTE_LEN);
bytes.push(PROFILE_TAG);
bytes.extend_from_slice(&raw_to_be_bytes(self.raw()));
bytes
}
pub fn from_bytes(bytes: &[u8]) -> Result<Self, OverflowDetected> {
if bytes.len() < 1 + RAW_BYTE_LEN {
return Err(OverflowDetected::InvalidInput);
}
if bytes[0] != PROFILE_TAG {
return Err(OverflowDetected::InvalidInput);
}
Ok(Self::from_raw(be_bytes_to_raw(&bytes[1..1 + RAW_BYTE_LEN])))
}
pub fn to_raw_bytes(&self) -> Vec<u8> {
raw_to_be_bytes(self.raw())
}
pub fn from_raw_bytes(bytes: &[u8]) -> Result<Self, OverflowDetected> {
if bytes.len() < RAW_BYTE_LEN {
return Err(OverflowDetected::InvalidInput);
}
Ok(Self::from_raw(be_bytes_to_raw(&bytes[..RAW_BYTE_LEN])))
}
pub fn profile_tag() -> u8 {
PROFILE_TAG
}
pub fn raw_byte_len() -> usize {
RAW_BYTE_LEN
}
}
impl FixedVector {
pub fn to_bytes(&self) -> Vec<u8> {
let n = self.len();
let mut bytes = Vec::with_capacity(4 + n * RAW_BYTE_LEN);
bytes.extend_from_slice(&(n as u32).to_be_bytes());
for i in 0..n {
bytes.extend_from_slice(&raw_to_be_bytes(self[i].raw()));
}
bytes
}
pub fn from_bytes(bytes: &[u8]) -> Result<Self, OverflowDetected> {
if bytes.len() < 4 {
return Err(OverflowDetected::InvalidInput);
}
let n = u32::from_be_bytes(bytes[0..4].try_into().unwrap()) as usize;
let expected = 4 + n * RAW_BYTE_LEN;
if bytes.len() < expected {
return Err(OverflowDetected::InvalidInput);
}
let mut data = Vec::with_capacity(n);
for i in 0..n {
let start = 4 + i * RAW_BYTE_LEN;
let raw = be_bytes_to_raw(&bytes[start..start + RAW_BYTE_LEN]);
data.push(FixedPoint::from_raw(raw));
}
Ok(FixedVector::from_slice(&data))
}
}
impl FixedMatrix {
pub fn to_bytes(&self) -> Vec<u8> {
let n = self.rows() * self.cols();
let mut bytes = Vec::with_capacity(8 + n * RAW_BYTE_LEN);
bytes.extend_from_slice(&(self.rows() as u32).to_be_bytes());
bytes.extend_from_slice(&(self.cols() as u32).to_be_bytes());
for r in 0..self.rows() {
for c in 0..self.cols() {
bytes.extend_from_slice(&raw_to_be_bytes(self.get(r, c).raw()));
}
}
bytes
}
pub fn from_bytes(bytes: &[u8]) -> Result<Self, OverflowDetected> {
if bytes.len() < 8 {
return Err(OverflowDetected::InvalidInput);
}
let rows = u32::from_be_bytes(bytes[0..4].try_into().unwrap()) as usize;
let cols = u32::from_be_bytes(bytes[4..8].try_into().unwrap()) as usize;
let n = rows * cols;
let expected = 8 + n * RAW_BYTE_LEN;
if bytes.len() < expected {
return Err(OverflowDetected::InvalidInput);
}
let mut m = FixedMatrix::new(rows, cols);
for i in 0..n {
let start = 8 + i * RAW_BYTE_LEN;
let raw = be_bytes_to_raw(&bytes[start..start + RAW_BYTE_LEN]);
let r = i / cols;
let c = i % cols;
m.set(r, c, FixedPoint::from_raw(raw));
}
Ok(m)
}
}
impl Tensor {
pub fn to_bytes(&self) -> Vec<u8> {
let rank = self.rank();
let total = self.len();
let mut bytes = Vec::with_capacity(1 + rank * 4 + total * RAW_BYTE_LEN);
bytes.push(rank as u8);
for &dim in self.shape() {
bytes.extend_from_slice(&(dim as u32).to_be_bytes());
}
for val in self.data() {
bytes.extend_from_slice(&raw_to_be_bytes(val.raw()));
}
bytes
}
pub fn from_bytes(bytes: &[u8]) -> Result<Self, OverflowDetected> {
if bytes.is_empty() {
return Err(OverflowDetected::InvalidInput);
}
let rank = bytes[0] as usize;
let header_len = 1 + rank * 4;
if bytes.len() < header_len {
return Err(OverflowDetected::InvalidInput);
}
let mut shape = Vec::with_capacity(rank);
for i in 0..rank {
let offset = 1 + i * 4;
let dim = u32::from_be_bytes(bytes[offset..offset + 4].try_into().unwrap()) as usize;
shape.push(dim);
}
let total: usize = shape.iter().product::<usize>().max(1);
let expected = header_len + total * RAW_BYTE_LEN;
if bytes.len() < expected {
return Err(OverflowDetected::InvalidInput);
}
let mut data = Vec::with_capacity(total);
for i in 0..total {
let start = header_len + i * RAW_BYTE_LEN;
let raw = be_bytes_to_raw(&bytes[start..start + RAW_BYTE_LEN]);
data.push(FixedPoint::from_raw(raw));
}
Ok(Tensor::from_data(&shape, &data))
}
}
pub const MANIFOLD_TAG_EUCLIDEAN: u8 = 0x01;
pub const MANIFOLD_TAG_SPHERE: u8 = 0x02;
pub const MANIFOLD_TAG_HYPERBOLIC: u8 = 0x03;
pub const MANIFOLD_TAG_SPD: u8 = 0x04;
pub const MANIFOLD_TAG_GRASSMANNIAN: u8 = 0x05;
#[derive(Clone, Debug)]
pub struct ManifoldPoint {
pub manifold_tag: u8,
pub params: Vec<u32>,
pub coordinates: FixedVector,
}
impl ManifoldPoint {
pub fn euclidean(dim: usize, coords: FixedVector) -> Self {
Self {
manifold_tag: MANIFOLD_TAG_EUCLIDEAN,
params: vec![dim as u32],
coordinates: coords,
}
}
pub fn sphere(dim: usize, coords: FixedVector) -> Self {
Self {
manifold_tag: MANIFOLD_TAG_SPHERE,
params: vec![dim as u32],
coordinates: coords,
}
}
pub fn hyperbolic(dim: usize, coords: FixedVector) -> Self {
Self {
manifold_tag: MANIFOLD_TAG_HYPERBOLIC,
params: vec![dim as u32],
coordinates: coords,
}
}
pub fn spd(n: usize, coords: FixedVector) -> Self {
Self {
manifold_tag: MANIFOLD_TAG_SPD,
params: vec![n as u32],
coordinates: coords,
}
}
pub fn grassmannian(k: usize, n: usize, coords: FixedVector) -> Self {
Self {
manifold_tag: MANIFOLD_TAG_GRASSMANNIAN,
params: vec![k as u32, n as u32],
coordinates: coords,
}
}
pub fn to_bytes(&self) -> Vec<u8> {
let vec_bytes = self.coordinates.to_bytes();
let mut bytes = Vec::with_capacity(2 + self.params.len() * 4 + vec_bytes.len());
bytes.push(self.manifold_tag);
bytes.push(self.params.len() as u8);
for &p in &self.params {
bytes.extend_from_slice(&p.to_be_bytes());
}
bytes.extend_from_slice(&vec_bytes);
bytes
}
pub fn from_bytes(bytes: &[u8]) -> Result<Self, OverflowDetected> {
if bytes.len() < 2 {
return Err(OverflowDetected::InvalidInput);
}
let tag = bytes[0];
let num_params = bytes[1] as usize;
let params_end = 2 + num_params * 4;
if bytes.len() < params_end {
return Err(OverflowDetected::InvalidInput);
}
let mut params = Vec::with_capacity(num_params);
for i in 0..num_params {
let offset = 2 + i * 4;
let p = u32::from_be_bytes(bytes[offset..offset + 4].try_into().unwrap());
params.push(p);
}
let coordinates = FixedVector::from_bytes(&bytes[params_end..])?;
Ok(Self {
manifold_tag: tag,
params,
coordinates,
})
}
}
const COMPACT_ZERO: u8 = 0b000;
const COMPACT_SMALL: u8 = 0b010;
const COMPACT_MEDIUM: u8 = 0b100;
const COMPACT_FULL: u8 = 0b110;
const COMPACT_SIGN_BIT: u8 = 0b001;
impl FixedPoint {
pub fn to_compact_bytes(&self) -> Vec<u8> {
if self.is_zero() {
return vec![COMPACT_ZERO];
}
let is_neg = self.is_negative();
let abs_val = self.abs();
let full_bytes = raw_to_be_bytes(abs_val.raw());
let first_nonzero = full_bytes.iter().position(|&b| b != 0).unwrap_or(full_bytes.len());
let significant = &full_bytes[first_nonzero..];
let sig_len = significant.len();
let sign_bit = if is_neg { COMPACT_SIGN_BIT } else { 0 };
if sig_len == 0 {
vec![COMPACT_ZERO | sign_bit]
} else if sig_len <= 255 {
let mut bytes = Vec::with_capacity(2 + sig_len);
bytes.push(COMPACT_SMALL | sign_bit);
bytes.push(sig_len as u8);
bytes.extend_from_slice(significant);
bytes
} else if sig_len <= 65535 {
let mut bytes = Vec::with_capacity(3 + sig_len);
bytes.push(COMPACT_MEDIUM | sign_bit);
bytes.extend_from_slice(&(sig_len as u16).to_be_bytes());
bytes.extend_from_slice(significant);
bytes
} else {
let mut bytes = Vec::with_capacity(1 + full_bytes.len());
bytes.push(COMPACT_FULL | sign_bit);
bytes.extend_from_slice(&full_bytes);
bytes
}
}
pub fn from_compact_bytes(bytes: &[u8]) -> Result<(Self, usize), OverflowDetected> {
if bytes.is_empty() {
return Err(OverflowDetected::InvalidInput);
}
let flags = bytes[0];
let is_neg = (flags & COMPACT_SIGN_BIT) != 0;
let size_class = flags & 0b110;
match size_class {
COMPACT_ZERO => {
Ok((FixedPoint::ZERO, 1))
}
COMPACT_SMALL => {
if bytes.len() < 2 {
return Err(OverflowDetected::InvalidInput);
}
let sig_len = bytes[1] as usize;
if bytes.len() < 2 + sig_len {
return Err(OverflowDetected::InvalidInput);
}
let mut full = vec![0u8; RAW_BYTE_LEN];
let offset = RAW_BYTE_LEN.saturating_sub(sig_len);
let copy_len = sig_len.min(RAW_BYTE_LEN);
let src_offset = sig_len.saturating_sub(RAW_BYTE_LEN);
full[offset..offset + copy_len].copy_from_slice(&bytes[2 + src_offset..2 + src_offset + copy_len]);
let raw = be_bytes_to_raw(&full);
let val = FixedPoint::from_raw(raw);
let result = if is_neg { -val } else { val };
Ok((result, 2 + sig_len))
}
COMPACT_MEDIUM => {
if bytes.len() < 3 {
return Err(OverflowDetected::InvalidInput);
}
let sig_len = u16::from_be_bytes(bytes[1..3].try_into().unwrap()) as usize;
if bytes.len() < 3 + sig_len {
return Err(OverflowDetected::InvalidInput);
}
let mut full = vec![0u8; RAW_BYTE_LEN];
let offset = RAW_BYTE_LEN.saturating_sub(sig_len);
let copy_len = sig_len.min(RAW_BYTE_LEN);
let src_offset = sig_len.saturating_sub(RAW_BYTE_LEN);
full[offset..offset + copy_len].copy_from_slice(&bytes[3 + src_offset..3 + src_offset + copy_len]);
let raw = be_bytes_to_raw(&full);
let val = FixedPoint::from_raw(raw);
let result = if is_neg { -val } else { val };
Ok((result, 3 + sig_len))
}
COMPACT_FULL | _ => {
if bytes.len() < 1 + RAW_BYTE_LEN {
return Err(OverflowDetected::InvalidInput);
}
let raw = be_bytes_to_raw(&bytes[1..1 + RAW_BYTE_LEN]);
let val = FixedPoint::from_raw(raw);
let result = if is_neg { -val } else { val };
Ok((result, 1 + RAW_BYTE_LEN))
}
}
}
}
impl FixedVector {
pub fn to_compact_bytes(&self) -> Vec<u8> {
let n = self.len();
let mut bytes = Vec::new();
bytes.extend_from_slice(&(n as u32).to_be_bytes());
for i in 0..n {
bytes.extend_from_slice(&self[i].to_compact_bytes());
}
bytes
}
pub fn from_compact_bytes(bytes: &[u8]) -> Result<(Self, usize), OverflowDetected> {
if bytes.len() < 4 {
return Err(OverflowDetected::InvalidInput);
}
let n = u32::from_be_bytes(bytes[0..4].try_into().unwrap()) as usize;
let mut data = Vec::with_capacity(n);
let mut pos = 4;
for _ in 0..n {
let (val, consumed) = FixedPoint::from_compact_bytes(&bytes[pos..])?;
data.push(val);
pos += consumed;
}
Ok((FixedVector::from_slice(&data), pos))
}
}
use crate::fixed_point::universal::fasc::stack_evaluator::BinaryStorage;
#[cfg(table_format = "q64_64")]
fn raw_to_be_bytes(raw: BinaryStorage) -> Vec<u8> {
raw.to_be_bytes().to_vec()
}
#[cfg(table_format = "q64_64")]
fn be_bytes_to_raw(bytes: &[u8]) -> BinaryStorage {
let arr: [u8; 16] = bytes[..16].try_into().unwrap();
i128::from_be_bytes(arr)
}
#[cfg(table_format = "q128_128")]
fn raw_to_be_bytes(raw: BinaryStorage) -> Vec<u8> {
let le = raw.to_bytes_le();
le.into_iter().rev().collect()
}
#[cfg(table_format = "q128_128")]
fn be_bytes_to_raw(bytes: &[u8]) -> BinaryStorage {
let le: Vec<u8> = bytes.iter().rev().copied().collect();
crate::fixed_point::I256::from_bytes_le(&le)
}
#[cfg(table_format = "q256_256")]
fn raw_to_be_bytes(raw: BinaryStorage) -> Vec<u8> {
let le = raw.to_bytes_le();
le.into_iter().rev().collect()
}
#[cfg(table_format = "q256_256")]
fn be_bytes_to_raw(bytes: &[u8]) -> BinaryStorage {
let le: Vec<u8> = bytes.iter().rev().copied().collect();
crate::fixed_point::I512::from_bytes_le(&le)
}
#[cfg(table_format = "q32_32")]
fn raw_to_be_bytes(raw: BinaryStorage) -> Vec<u8> {
raw.to_be_bytes().to_vec()
}
#[cfg(table_format = "q32_32")]
fn be_bytes_to_raw(bytes: &[u8]) -> BinaryStorage {
let arr: [u8; 8] = bytes[..8].try_into().unwrap();
i64::from_be_bytes(arr)
}
#[cfg(table_format = "q16_16")]
fn raw_to_be_bytes(raw: BinaryStorage) -> Vec<u8> {
raw.to_be_bytes().to_vec()
}
#[cfg(table_format = "q16_16")]
fn be_bytes_to_raw(bytes: &[u8]) -> BinaryStorage {
let arr: [u8; 4] = bytes[..4].try_into().unwrap();
i32::from_be_bytes(arr)
}
#[cfg(feature = "serde")]
mod serde_impl {
use super::*;
use serde::{Serialize, Deserialize, Serializer, Deserializer};
use serde::de::{self, Visitor, SeqAccess};
use serde::ser::SerializeStruct;
use std::fmt;
impl Serialize for FixedPoint {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let bytes = self.to_bytes();
serializer.serialize_bytes(&bytes)
}
}
impl<'de> Deserialize<'de> for FixedPoint {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
struct FixedPointVisitor;
impl<'de> Visitor<'de> for FixedPointVisitor {
type Value = FixedPoint;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("FixedPoint bytes (profile tag + raw BE)")
}
fn visit_bytes<E: de::Error>(self, v: &[u8]) -> Result<FixedPoint, E> {
FixedPoint::from_bytes(v).map_err(|_| E::custom("invalid FixedPoint bytes"))
}
fn visit_byte_buf<E: de::Error>(self, v: Vec<u8>) -> Result<FixedPoint, E> {
FixedPoint::from_bytes(&v).map_err(|_| E::custom("invalid FixedPoint bytes"))
}
}
deserializer.deserialize_bytes(FixedPointVisitor)
}
}
impl Serialize for FixedVector {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let bytes = self.to_bytes();
serializer.serialize_bytes(&bytes)
}
}
impl<'de> Deserialize<'de> for FixedVector {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
struct VecVisitor;
impl<'de> Visitor<'de> for VecVisitor {
type Value = FixedVector;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("FixedVector bytes (u32 len BE + raw elements)")
}
fn visit_bytes<E: de::Error>(self, v: &[u8]) -> Result<FixedVector, E> {
FixedVector::from_bytes(v).map_err(|_| E::custom("invalid FixedVector bytes"))
}
fn visit_byte_buf<E: de::Error>(self, v: Vec<u8>) -> Result<FixedVector, E> {
FixedVector::from_bytes(&v).map_err(|_| E::custom("invalid FixedVector bytes"))
}
}
deserializer.deserialize_bytes(VecVisitor)
}
}
impl Serialize for FixedMatrix {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let bytes = self.to_bytes();
serializer.serialize_bytes(&bytes)
}
}
impl<'de> Deserialize<'de> for FixedMatrix {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
struct MatVisitor;
impl<'de> Visitor<'de> for MatVisitor {
type Value = FixedMatrix;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("FixedMatrix bytes (rows/cols u32 BE + raw elements)")
}
fn visit_bytes<E: de::Error>(self, v: &[u8]) -> Result<FixedMatrix, E> {
FixedMatrix::from_bytes(v).map_err(|_| E::custom("invalid FixedMatrix bytes"))
}
fn visit_byte_buf<E: de::Error>(self, v: Vec<u8>) -> Result<FixedMatrix, E> {
FixedMatrix::from_bytes(&v).map_err(|_| E::custom("invalid FixedMatrix bytes"))
}
}
deserializer.deserialize_bytes(MatVisitor)
}
}
impl Serialize for Tensor {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let bytes = self.to_bytes();
serializer.serialize_bytes(&bytes)
}
}
impl<'de> Deserialize<'de> for Tensor {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
struct TensorVisitor;
impl<'de> Visitor<'de> for TensorVisitor {
type Value = Tensor;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("Tensor bytes (rank + shape + data)")
}
fn visit_bytes<E: de::Error>(self, v: &[u8]) -> Result<Tensor, E> {
Tensor::from_bytes(v).map_err(|_| E::custom("invalid Tensor bytes"))
}
fn visit_byte_buf<E: de::Error>(self, v: Vec<u8>) -> Result<Tensor, E> {
Tensor::from_bytes(&v).map_err(|_| E::custom("invalid Tensor bytes"))
}
}
deserializer.deserialize_bytes(TensorVisitor)
}
}
impl Serialize for ManifoldPoint {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let bytes = self.to_bytes();
serializer.serialize_bytes(&bytes)
}
}
impl<'de> Deserialize<'de> for ManifoldPoint {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
struct MpVisitor;
impl<'de> Visitor<'de> for MpVisitor {
type Value = ManifoldPoint;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("ManifoldPoint bytes (tag + params + coords)")
}
fn visit_bytes<E: de::Error>(self, v: &[u8]) -> Result<ManifoldPoint, E> {
ManifoldPoint::from_bytes(v).map_err(|_| E::custom("invalid ManifoldPoint bytes"))
}
fn visit_byte_buf<E: de::Error>(self, v: Vec<u8>) -> Result<ManifoldPoint, E> {
ManifoldPoint::from_bytes(&v).map_err(|_| E::custom("invalid ManifoldPoint bytes"))
}
}
deserializer.deserialize_bytes(MpVisitor)
}
}
}