From 8a833b41e085699b65c95488251206f3fab1ab10 Mon Sep 17 00:00:00 2001 From: yukirij Date: Wed, 30 Aug 2023 18:49:44 -0700 Subject: [PATCH] Update README, implement encoding for Decimal. --- README.md | 70 +++++++++++++++++++++++++++++++++++++--- src/bin/main.rs | 32 +++++++++++++++--- src/encoding/mod.rs | 18 ++++++++++- src/interface/builder.rs | 4 +-- src/interface/decimal.rs | 42 ++++++++++++------------ 5 files changed, 132 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 010d838..4be6683 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,8 @@ While the runtime provides methods for directly acquring and releasing memory, i |Boolean|x02|--|True or false| |Natural|x10|--|Non-negative integers| |Integer|x11|--|Positive and negative whole numbers| -|Significant|x13|--|Fixed-precision, variable-magnitude numbers| +|Decimal|x12|mantissa|Fixed-maginutide rational numbers| +|Significant|x13|--|Variable-magnitude rational numbers| |Block|x1e|size|Constant-sized series of bytes| |Sequence|x1f|--|Variable-sized series of bytes| |Array|x22|size, type|Constant-sized, indexed collection| @@ -49,6 +50,7 @@ Type building functions are used to generate identifiers used in the constructio * `boolean()` * `natural()` * `integer()` +* `decimal(mantissa)` * `significant()` * `block(size)` * `sequence()` @@ -229,7 +231,7 @@ let value = Integer::new(); ``` --- -`from(refer:Reference) -> Result` +`try_from(refer:Reference) -> Result` ``` match Integer::from(list.at(0)) { @@ -379,12 +381,70 @@ value.set(-273); --- ## Decimal -Stores a constant-magnitude number with whole and decimal components. +Stores a constant-magnitude rational number of specified mantissa size. -> Not implemented. +`new(mantissa:u8) -> Self` + +--- + +`with(mantissa:u8, value:f64) -> Self` + +--- + +`with_raw(mantissa:u8, value:i64) -> Self` + +--- + +`get() -> f64` + +Returns the contained value. + +--- + +`get_raw() -> i64` + +Returns the raw contained value. + +--- + +`set(value:f64)` + +Replaces the contained value. + +--- + +`set_raw(value:i64)` + +Replaces the raw contained value. + +--- + +`-Neg() -> Self` + +`Add+(rhs:Self) -> Self` + +`AddAssign+=(rhs:Self)` + +`Sub-(rhs:Self) -> Self` + +`SubAssign-=(rhs:Self)` + +`Mul*(rhs:Self) -> Self` + +`MulAssign*=(rhs:Self)` + +`Div/(rhs:Self) -> Self` + +`DivAssign/=(rhs:Self)` + +`Rem%(rhs:Self) -> Self` + +`RemAssign%=(rhs:Self)` + +--- ## Significant -Stores a fixed-precision, variable-magnitude number. +Stores a variable-magnitude rational number. > Encode/decode not implemented. diff --git a/src/bin/main.rs b/src/bin/main.rs index 9b926c8..d7f518f 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -1,9 +1,17 @@ -fn main() { - let a = szun::Decimal::with(32, 18.5); - let b = szun::Decimal::with(24, 6.0); +fn print_bytes(bytes:&Vec) +{ + for b in bytes { + print!("{:02x} ", *b); + } print!("\n"); +} - println!("A = {} (.{})", a.get(), a.exponent()); - println!("B = {} (.{})", b.get(), b.exponent()); +fn main() { + let a = szun::Decimal::with(32, 128.5); + let b = szun::Decimal::with(24, 16.0); + let c = a.copy() / b.copy(); + + println!("A = {} (.{})", a.get(), a.mantissa()); + println!("B = {} (.{})", b.get(), b.mantissa()); print!("\n"); println!("A + B = {}", (a.copy() + b.copy()).get()); println!("A - B = {}", (a.copy() - b.copy()).get()); @@ -16,4 +24,18 @@ fn main() { println!("B * A = {}", (b.copy() * a.copy()).get()); println!("B / A = {}", (b.copy() / a.copy()).get()); println!("B % A = {}", (b.copy() % a.copy()).get()); + + print!("\n"); + let out = szun::encode(*c); + println!("c = {}", c.get()); + print_bytes(&out); + match szun::decode(&out, &mut 0) { + Ok(ty) => match ty { + szun::Type::Decimal(val) => { + println!("decode = {}", val.get()); + } + _ => { println!("other"); } + } + Err(_) => { println!("failed"); } + } } diff --git a/src/encoding/mod.rs b/src/encoding/mod.rs index 3367667..2449a7c 100644 --- a/src/encoding/mod.rs +++ b/src/encoding/mod.rs @@ -14,7 +14,7 @@ use crate::{ Varying, Boolean, Natural, Integer, - //Significant, + Decimal, //Significant, Block, Sequence, Array, List, Record, @@ -56,6 +56,14 @@ pub fn encode_data(addr:Reference) -> Vec tag::INTEGER => { result.append(&mut &mut util::pack_integer(Integer::try_from(addr).unwrap().get() as i64)); } + tag::DECIMAL => { + let mantissa = unsafe {type_innerkey(addr.class)}; + let raw = Decimal::try_from(addr).unwrap().get_raw(); + let whole = raw >> mantissa; + let fract = (raw as u64 & ((1u64 << mantissa) - 1)).reverse_bits() >> (u64::BITS as usize - mantissa); + result.append(&mut &mut util::pack_integer(whole)); + result.append(&mut &mut util::pack_natural(fract)); + } tag::SIGNIFICANT => { result.append(&mut vec![0]); } @@ -191,6 +199,14 @@ pub fn decode_data(data:&Vec, type_id:usize, index:&mut usize) -> Result { return Ok(Type::Integer(Integer::with(unpack_integer(data, index)))); } + tag::DECIMAL => { + let mantissa = unsafe {type_innerkey(type_id)}; + let whole = unpack_integer(data, index); + let fract = unpack_natural(data, index).reverse_bits() >> (u64::BITS as usize - mantissa); + let raw = (whole << mantissa) | fract as i64; + + return Ok(Type::Decimal(Decimal::with_raw(unsafe {type_innerkey(type_id)}, raw))); + } tag::SIGNIFICANT => { return Err(()) } diff --git a/src/interface/builder.rs b/src/interface/builder.rs index 1597830..c73dd8a 100644 --- a/src/interface/builder.rs +++ b/src/interface/builder.rs @@ -11,9 +11,9 @@ pub fn natural() -> usize { unsafe { runtime::type_outer(0, tag::NATURAL) } } pub fn integer() -> usize { unsafe { runtime::type_outer(0, tag::INTEGER) } } pub fn significant() -> usize { unsafe { runtime::type_outer(0, tag::SIGNIFICANT) } } -pub fn decimal(exponent:usize) -> usize { +pub fn decimal(mantissa:usize) -> usize { unsafe { - let inner_node = runtime::type_outer(0, exponent); + let inner_node = runtime::type_outer(0, mantissa); runtime::type_outer(inner_node, tag::DECIMAL) } } diff --git a/src/interface/decimal.rs b/src/interface/decimal.rs index fcd42e6..4e9ac0f 100644 --- a/src/interface/decimal.rs +++ b/src/interface/decimal.rs @@ -12,24 +12,24 @@ pub struct Decimal { addr:Reference, } impl Decimal { - pub fn new(exponent:usize) -> Self + pub fn new(mantissa:usize) -> Self { Self { managed:true, - addr:unsafe {acquire(decimal(exponent))}, + addr:unsafe {acquire(decimal(mantissa))}, } } - fn with_raw(exponent:usize, data:i64) -> Self + pub fn with_raw(mantissa:usize, data:i64) -> Self { - let mut obj = Self::new(exponent); + let mut obj = Self::new(mantissa); obj.set_raw(data); return obj; } - pub fn with(exponent:usize, value:f64) -> Self + pub fn with(mantissa:usize, value:f64) -> Self { - let mut obj = Self::new(exponent); + let mut obj = Self::new(mantissa); obj.set(value); return obj; } @@ -39,30 +39,30 @@ impl Decimal { Decimal::try_from(self.addr).unwrap() } - fn set_raw(&mut self, data:i64) + pub fn set_raw(&mut self, data:i64) { unsafe { decimal_set(self.addr, data) }; } pub fn set(&mut self, value:f64) { - let exponent = unsafe {type_innerkey(self.addr.class)}; + let mantissa = unsafe {type_innerkey(self.addr.class)}; let whole = value as i64; - let decimal = ((value - value.trunc()).abs() * (1i64 << exponent) as f64).floor() as i64; - let data = (whole << exponent) + (decimal as i64); + let decimal = ((value - value.trunc()).abs() * (1i64 << mantissa) as f64).floor() as i64; + let data = (whole << mantissa) + (decimal as i64); self.set_raw(data); } - fn get_raw(&self) -> i64 + pub fn get_raw(&self) -> i64 { unsafe {decimal_get(self.addr)} } pub fn get(&self) -> f64 { - let exponent = unsafe {type_innerkey(self.addr.class)}; + let mantissa = unsafe {type_innerkey(self.addr.class)}; let data = self.get_raw(); - (data >> exponent) as f64 + ((data & ((1i64 << exponent) - 1)) as f64 / (1i64 << exponent) as f64) + (data >> mantissa) as f64 + ((data & ((1i64 << mantissa) - 1)) as f64 / (1i64 << mantissa) as f64) } fn rebase(to:usize, from:usize, data:i64) -> i64 @@ -74,22 +74,22 @@ impl Decimal { } else { data } } - pub fn to_base(&self, exponent:usize) -> Self + pub fn to_base(&self, mantissa:usize) -> Self { - let from_exp = self.exponent(); - let mut result = Decimal::new(exponent); - result.set_raw(Self::rebase(from_exp, exponent, self.get_raw())); + let from_exp = self.mantissa(); + let mut result = Decimal::new(mantissa); + result.set_raw(Self::rebase(from_exp, mantissa, self.get_raw())); return result; } - pub fn exponent(&self) -> usize + pub fn mantissa(&self) -> usize { unsafe {type_innerkey(self.addr.class)} } } impl Clone for Decimal { fn clone(&self) -> Self { - Decimal::with_raw(self.exponent(), self.get_raw()) + Decimal::with_raw(self.mantissa(), self.get_raw()) } } impl std::ops::Add for Decimal { @@ -200,8 +200,8 @@ impl std::ops::RemAssign for Decimal { impl std::ops::Neg for Decimal { type Output = Self; fn neg(self) -> Self::Output { - let exponent = unsafe {type_innerkey(self.addr.class)}; - Decimal::with_raw(exponent, -self.get_raw()) + let mantissa = unsafe {type_innerkey(self.addr.class)}; + Decimal::with_raw(mantissa, -self.get_raw()) } } impl std::ops::Deref for Decimal {