Update README, implement encoding for Decimal.

This commit is contained in:
yukirij 2023-08-30 18:49:44 -07:00
parent e7781c721f
commit 8a833b41e0
5 changed files with 132 additions and 34 deletions

View File

@ -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<Self,()>`
`try_from(refer:Reference) -> Result<Self,()>`
```
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.

View File

@ -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<u8>)
{
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"); }
}
}

View File

@ -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<u8>
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<u8>, type_id:usize, index:&mut usize) -> Result<Typ
tag::INTEGER => {
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(())
}

View File

@ -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)
}
}

View File

@ -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 {