mirror of
https://github.com/urbit/ares.git
synced 2024-11-22 06:32:47 +03:00
Add +r? jets.
This commit is contained in:
parent
4dd009c04c
commit
c8b0762a4f
@ -23,6 +23,7 @@ criterion = "0.4"
|
||||
static_assertions = "1.1.0"
|
||||
ibig = { path = "../ibig-rs" }
|
||||
assert_no_alloc = "1.1.2"
|
||||
softfloat_sys = "0.1.3"
|
||||
|
||||
[build-dependencies]
|
||||
cc = "1.0.79"
|
||||
|
558
rust/ares/src/jets/float_rd.rs
Normal file
558
rust/ares/src/jets/float_rd.rs
Normal file
@ -0,0 +1,558 @@
|
||||
/** Floating-point jets
|
||||
*/
|
||||
use crate::jets;
|
||||
use crate::jets::JetErr::*;
|
||||
use crate::jets::util::*;
|
||||
use crate::jets::util::test::{assert_jet, assert_jet_err, assert_jet_ubig, assert_nary_jet_ubig, init_stack, A};
|
||||
use crate::mem::NockStack;
|
||||
use crate::newt::Newt;
|
||||
use crate::noun::{Atom, IndirectAtom, Noun, D, T, Cell, NO, YES};
|
||||
use ibig::{UBig, ubig};
|
||||
use softfloat_sys::*;
|
||||
use std::io::Write;
|
||||
|
||||
crate::gdb!();
|
||||
|
||||
const DOUBNAN: u64 = 0x7ff8000000000000;
|
||||
const DOUBINF: u64 = 0x7ff0000000000000;
|
||||
const DOUBZERO: u64 = 0x0000000000000000;
|
||||
|
||||
#[inline(always)]
|
||||
fn _nan_test(
|
||||
a: float64_t
|
||||
) -> bool {
|
||||
unsafe {
|
||||
!f64_eq(a, a)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn _nan_unify(
|
||||
a: float64_t
|
||||
) -> float64_t {
|
||||
unsafe {
|
||||
if _nan_test(a) {
|
||||
return softfloat_sys::float64_t { v: DOUBNAN };
|
||||
}
|
||||
a
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn _set_rounding(
|
||||
r: char
|
||||
) -> u8 {
|
||||
match r {
|
||||
'n' => softfloat_round_near_even,
|
||||
'z' => softfloat_round_minMag,
|
||||
'u' => softfloat_round_max,
|
||||
'd' => softfloat_round_min,
|
||||
// formal fallthrough, should never happen
|
||||
_ => softfloat_round_near_even,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_rd_add(
|
||||
stack: &mut NockStack,
|
||||
_newt: &mut Option<&mut Newt>,
|
||||
subject: Noun
|
||||
) -> jets::Result {
|
||||
unsafe {
|
||||
let sam = slot(subject, 6)?;
|
||||
let a = slot(sam, 2)?.as_atom()?;
|
||||
let b = slot(sam, 3)?.as_atom()?;
|
||||
let r = slot(subject, 30)?.as_atom()?.as_direct()?.data() as u8 as char;
|
||||
|
||||
// @rd MAY be indirect but they are 64 bits
|
||||
let dat_a = softfloat_sys::float64_t { v: a.as_u64()? };
|
||||
let dat_b = softfloat_sys::float64_t { v: b.as_u64()? };
|
||||
let mod_r = _set_rounding(r);
|
||||
|
||||
softfloat_roundingMode_write_helper(mod_r);
|
||||
let x = _nan_unify(f64_add(dat_a, dat_b));
|
||||
|
||||
let x_msb = ((x.v >> 63) & 1) != 0;
|
||||
let x_2sb = ((x.v >> 62) & 1) != 0;
|
||||
|
||||
if x_msb || x_2sb {
|
||||
Ok(A(stack, &UBig::from(x.v as u64)))
|
||||
} else {
|
||||
Ok(D(x.v as u64))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_rd_sub(
|
||||
stack: &mut NockStack,
|
||||
_newt: &mut Option<&mut Newt>,
|
||||
subject: Noun
|
||||
) -> jets::Result {
|
||||
unsafe {
|
||||
let sam = slot(subject, 6)?;
|
||||
let a = slot(sam, 2)?.as_atom()?;
|
||||
let b = slot(sam, 3)?.as_atom()?;
|
||||
let r = slot(subject, 30)?.as_atom()?.as_direct()?.data() as u8 as char;
|
||||
|
||||
// @rd MAY be indirect but they are 64 bits
|
||||
let dat_a = softfloat_sys::float64_t { v: a.as_u64()? };
|
||||
let dat_b = softfloat_sys::float64_t { v: b.as_u64()? };
|
||||
let mod_r = _set_rounding(r);
|
||||
|
||||
softfloat_roundingMode_write_helper(mod_r);
|
||||
let x = _nan_unify(f64_sub(dat_a, dat_b));
|
||||
|
||||
let x_msb = ((x.v >> 63) & 1) != 0;
|
||||
let x_2sb = ((x.v >> 62) & 1) != 0;
|
||||
|
||||
if x_msb || x_2sb {
|
||||
Ok(A(stack, &UBig::from(x.v as u64)))
|
||||
} else {
|
||||
Ok(D(x.v as u64))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_rd_mul(
|
||||
stack: &mut NockStack,
|
||||
_newt: &mut Option<&mut Newt>,
|
||||
subject: Noun
|
||||
) -> jets::Result {
|
||||
unsafe {
|
||||
let sam = slot(subject, 6)?;
|
||||
let a = slot(sam, 2)?.as_atom()?;
|
||||
let b = slot(sam, 3)?.as_atom()?;
|
||||
let r = slot(subject, 30)?.as_atom()?.as_direct()?.data() as u8 as char;
|
||||
|
||||
// @rd MAY be indirect but they are 64 bits
|
||||
let dat_a = softfloat_sys::float64_t { v: a.as_u64()? };
|
||||
let dat_b = softfloat_sys::float64_t { v: b.as_u64()? };
|
||||
let mod_r = _set_rounding(r);
|
||||
|
||||
softfloat_roundingMode_write_helper(mod_r);
|
||||
let x = _nan_unify(f64_mul(dat_a, dat_b));
|
||||
|
||||
let x_msb = ((x.v >> 63) & 1) != 0;
|
||||
let x_2sb = ((x.v >> 62) & 1) != 0;
|
||||
|
||||
if x_msb || x_2sb {
|
||||
Ok(A(stack, &UBig::from(x.v as u64)))
|
||||
} else {
|
||||
Ok(D(x.v as u64))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_rd_div(
|
||||
stack: &mut NockStack,
|
||||
_newt: &mut Option<&mut Newt>,
|
||||
subject: Noun
|
||||
) -> jets::Result {
|
||||
unsafe {
|
||||
let sam = slot(subject, 6)?;
|
||||
let a = slot(sam, 2)?.as_atom()?;
|
||||
let b = slot(sam, 3)?.as_atom()?;
|
||||
let r = slot(subject, 30)?.as_atom()?.as_direct()?.data() as u8 as char;
|
||||
|
||||
// @rd MAY be indirect but they are 64 bits
|
||||
let dat_a = softfloat_sys::float64_t { v: a.as_u64()? };
|
||||
let dat_b = softfloat_sys::float64_t { v: b.as_u64()? };
|
||||
let mod_r = _set_rounding(r);
|
||||
|
||||
softfloat_roundingMode_write_helper(mod_r);
|
||||
let x = _nan_unify(f64_div(dat_a, dat_b));
|
||||
|
||||
let x_msb = ((x.v >> 63) & 1) != 0;
|
||||
let x_2sb = ((x.v >> 62) & 1) != 0;
|
||||
|
||||
if x_msb || x_2sb {
|
||||
Ok(A(stack, &UBig::from(x.v as u64)))
|
||||
} else {
|
||||
Ok(D(x.v as u64))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_rd_sqt(
|
||||
stack: &mut NockStack,
|
||||
_newt: &mut Option<&mut Newt>,
|
||||
subject: Noun
|
||||
) -> jets::Result {
|
||||
unsafe{
|
||||
let sam = slot(subject, 6)?;
|
||||
let a = sam.as_atom()?;
|
||||
let r = slot(subject, 30)?.as_atom()?.as_direct()?.data() as u8 as char;
|
||||
|
||||
let dat_a = softfloat_sys::float64_t { v: a.as_u64()? };
|
||||
let mod_r = _set_rounding(r);
|
||||
|
||||
softfloat_roundingMode_write_helper(mod_r);
|
||||
let x = _nan_unify(f64_sqrt(dat_a));
|
||||
|
||||
let x_msb = ((x.v >> 63) & 1) != 0;
|
||||
let x_2sb = ((x.v >> 62) & 1) != 0;
|
||||
|
||||
if x_msb || x_2sb {
|
||||
Ok(A(stack, &UBig::from(x.v as u64)))
|
||||
} else {
|
||||
Ok(D(x.v as u64))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_rd_fma(
|
||||
stack: &mut NockStack,
|
||||
_newt: &mut Option<&mut Newt>,
|
||||
subject: Noun
|
||||
) -> jets::Result {
|
||||
unsafe{
|
||||
let sam = slot(subject, 6)?;
|
||||
let a = slot(sam, 2)?.as_atom()?;
|
||||
let b = slot(sam, 6)?.as_atom()?;
|
||||
let c = slot(sam, 7)?.as_atom()?;
|
||||
let r = slot(subject, 30)?.as_atom()?.as_direct()?.data() as u8 as char;
|
||||
|
||||
let dat_a = softfloat_sys::float64_t { v: a.as_u64()? };
|
||||
let dat_b = softfloat_sys::float64_t { v: b.as_u64()? };
|
||||
let dat_c = softfloat_sys::float64_t { v: c.as_u64()? };
|
||||
let mod_r = _set_rounding(r);
|
||||
|
||||
softfloat_roundingMode_write_helper(mod_r);
|
||||
let x = _nan_unify(f64_mulAdd(dat_a, dat_b, dat_c));
|
||||
|
||||
let x_msb = ((x.v >> 63) & 1) != 0;
|
||||
let x_2sb = ((x.v >> 62) & 1) != 0;
|
||||
|
||||
if x_msb || x_2sb {
|
||||
Ok(A(stack, &UBig::from(x.v as u64)))
|
||||
} else {
|
||||
Ok(D(x.v as u64))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_rd_lth(
|
||||
stack: &mut NockStack,
|
||||
_newt: &mut Option<&mut Newt>,
|
||||
subject: Noun
|
||||
) -> jets::Result {
|
||||
unsafe{
|
||||
let sam = slot(subject, 6)?;
|
||||
let a = slot(sam, 2)?.as_atom()?;
|
||||
let b = slot(sam, 3)?.as_atom()?;
|
||||
let r = slot(subject, 30)?.as_atom()?.as_direct()?.data() as u8 as char;
|
||||
|
||||
let dat_a = softfloat_sys::float64_t { v: a.as_u64()? };
|
||||
let dat_b = softfloat_sys::float64_t { v: b.as_u64()? };
|
||||
let mod_r = _set_rounding(r);
|
||||
|
||||
softfloat_roundingMode_write_helper(mod_r);
|
||||
let t = f64_lt(dat_a, dat_b);
|
||||
|
||||
if t { Ok(YES) } else { Ok(NO) }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_rd_lte(
|
||||
stack: &mut NockStack,
|
||||
_newt: &mut Option<&mut Newt>,
|
||||
subject: Noun
|
||||
) -> jets::Result {
|
||||
unsafe{
|
||||
let sam = slot(subject, 6)?;
|
||||
let a = slot(sam, 2)?.as_atom()?;
|
||||
let b = slot(sam, 3)?.as_atom()?;
|
||||
let r = slot(subject, 30)?.as_atom()?.as_direct()?.data() as u8 as char;
|
||||
|
||||
let dat_a = softfloat_sys::float64_t { v: a.as_u64()? };
|
||||
let dat_b = softfloat_sys::float64_t { v: b.as_u64()? };
|
||||
let mod_r = _set_rounding(r);
|
||||
|
||||
softfloat_roundingMode_write_helper(mod_r);
|
||||
let t = f64_le(dat_a, dat_b);
|
||||
|
||||
if t { Ok(YES) } else { Ok(NO) }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_rd_equ(
|
||||
stack: &mut NockStack,
|
||||
_newt: &mut Option<&mut Newt>,
|
||||
subject: Noun
|
||||
) -> jets::Result {
|
||||
unsafe{
|
||||
let sam = slot(subject, 6)?;
|
||||
let a = slot(sam, 2)?.as_atom()?;
|
||||
let b = slot(sam, 3)?.as_atom()?;
|
||||
let r = slot(subject, 30)?.as_atom()?.as_direct()?.data() as u8 as char;
|
||||
|
||||
let dat_a = softfloat_sys::float64_t { v: a.as_u64()? };
|
||||
let dat_b = softfloat_sys::float64_t { v: b.as_u64()? };
|
||||
let mod_r = _set_rounding(r);
|
||||
|
||||
softfloat_roundingMode_write_helper(mod_r);
|
||||
let t = f64_eq(dat_a, dat_b);
|
||||
|
||||
if t { Ok(YES) } else { Ok(NO) }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_rd_gte(
|
||||
stack: &mut NockStack,
|
||||
_newt: &mut Option<&mut Newt>,
|
||||
subject: Noun
|
||||
) -> jets::Result {
|
||||
unsafe{
|
||||
let sam = slot(subject, 6)?;
|
||||
let a = slot(sam, 2)?.as_atom()?;
|
||||
let b = slot(sam, 3)?.as_atom()?;
|
||||
let r = slot(subject, 30)?.as_atom()?.as_direct()?.data() as u8 as char;
|
||||
|
||||
let dat_a = softfloat_sys::float64_t { v: a.as_u64()? };
|
||||
let dat_b = softfloat_sys::float64_t { v: b.as_u64()? };
|
||||
let mod_r = _set_rounding(r);
|
||||
|
||||
softfloat_roundingMode_write_helper(mod_r);
|
||||
let t = f64_le(dat_b, dat_a);
|
||||
|
||||
if t { Ok(YES) } else { Ok(NO) }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_rd_gth(
|
||||
stack: &mut NockStack,
|
||||
_newt: &mut Option<&mut Newt>,
|
||||
subject: Noun
|
||||
) -> jets::Result {
|
||||
unsafe{
|
||||
let sam = slot(subject, 6)?;
|
||||
let a = slot(sam, 2)?.as_atom()?;
|
||||
let b = slot(sam, 3)?.as_atom()?;
|
||||
let r = slot(subject, 30)?.as_atom()?.as_direct()?.data() as u8 as char;
|
||||
|
||||
let dat_a = softfloat_sys::float64_t { v: a.as_u64()? };
|
||||
let dat_b = softfloat_sys::float64_t { v: b.as_u64()? };
|
||||
let mod_r = _set_rounding(r);
|
||||
|
||||
softfloat_roundingMode_write_helper(mod_r);
|
||||
let t = f64_lt(dat_b, dat_a);
|
||||
|
||||
if t { Ok(YES) } else { Ok(NO) }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::jets::{Jet, JetErr};
|
||||
use crate::jets::util::test::{assert_jet, assert_jet_err, init_stack};
|
||||
use crate::noun::D;
|
||||
use crate::jets::util::test::{assert_noun_eq};
|
||||
use assert_no_alloc::assert_no_alloc;
|
||||
use libc::SS;
|
||||
|
||||
pub fn assert_jet_in_door(
|
||||
stack: &mut NockStack,
|
||||
jet: Jet,
|
||||
sam: &[fn(&mut NockStack) -> Noun], // regular sample
|
||||
ctx: &[fn(&mut NockStack) -> Noun], // door sample as context
|
||||
res: Noun) {
|
||||
unsafe {
|
||||
let mut sam: Vec<Noun> = sam.iter().map(|f| f(stack)).collect();
|
||||
let mut ctx: Vec<Noun> = ctx.iter().map(|f| f(stack)).collect();
|
||||
let sam = if(sam.len() > 1) { T(stack, &sam) } else { sam[0] };
|
||||
eprintln!("sam: {:?}", sam);
|
||||
let ctx = if(ctx.len() > 1) { T(stack, &ctx) } else { ctx[0] };
|
||||
eprintln!("ctx: {:?}", ctx);
|
||||
let pay = Cell::new(stack, sam, ctx).as_noun();
|
||||
eprintln!("pay: {:?}", pay);
|
||||
let sbj = Cell::new(stack, D(0), pay).as_noun();
|
||||
eprintln!("sbj: {:?}", sbj);
|
||||
std::io::stderr().flush().unwrap();
|
||||
let jet_res = jet(stack, &mut None, sbj).unwrap();
|
||||
//eprintln!("jet: {:x}\n", jet_res.as_atom().expect("").as_direct().expect("").data());
|
||||
std::io::stderr().flush().unwrap();
|
||||
assert_noun_eq(stack, jet_res, res);
|
||||
}
|
||||
}
|
||||
|
||||
fn atom_0(stack: &mut NockStack) -> Noun {
|
||||
A(stack, &ubig!(0x0000000000000000))
|
||||
}
|
||||
|
||||
fn atom_1(stack: &mut NockStack) -> Noun {
|
||||
A(stack, &ubig!(0x3ff0000000000000))
|
||||
}
|
||||
|
||||
fn atom_2(stack: &mut NockStack) -> Noun {
|
||||
A(stack, &ubig!(0x4000000000000000))
|
||||
}
|
||||
|
||||
fn atom_3(stack: &mut NockStack) -> Noun {
|
||||
A(stack, &ubig!(0x4008000000000000))
|
||||
}
|
||||
|
||||
fn atom_1_5(stack: &mut NockStack) -> Noun {
|
||||
A(stack, &ubig!(0x3ff8000000000000))
|
||||
}
|
||||
|
||||
fn atom_1_1(stack: &mut NockStack) -> Noun {
|
||||
A(stack, &ubig!(0x3ff199999999999a))
|
||||
}
|
||||
|
||||
fn atom_0_8(stack: &mut NockStack) -> Noun {
|
||||
A(stack, &ubig!(0x3fe999999999999a))
|
||||
}
|
||||
|
||||
fn atom_0_3(stack: &mut NockStack) -> Noun {
|
||||
A(stack, &ubig!(0x3fd3333333333333))
|
||||
}
|
||||
|
||||
fn r_sample_n(_stack: &mut NockStack) -> Noun {
|
||||
D('n' as u8 as u64)
|
||||
}
|
||||
|
||||
fn r_sample_z(_stack: &mut NockStack) -> Noun {
|
||||
D('z' as u8 as u64)
|
||||
}
|
||||
|
||||
fn r_sample_u(_stack: &mut NockStack) -> Noun {
|
||||
D('u' as u8 as u64)
|
||||
}
|
||||
|
||||
fn r_sample_d(_stack: &mut NockStack) -> Noun {
|
||||
D('d' as u8 as u64)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rd_add() {
|
||||
let s = &mut init_stack();
|
||||
let q = &mut init_stack();
|
||||
|
||||
assert_jet_in_door(s, jet_rd_add, &[atom_0, atom_0], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x0000000000000000)));
|
||||
assert_jet_in_door(s, jet_rd_add, &[atom_0, atom_1], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x3ff0000000000000)));
|
||||
assert_jet_in_door(s, jet_rd_add, &[atom_1, atom_1], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x4000000000000000)));
|
||||
assert_jet_in_door(s, jet_rd_add, &[atom_1, atom_2], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x4008000000000000)));
|
||||
assert_jet_in_door(s, jet_rd_add, &[atom_2, atom_1], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x4008000000000000)));
|
||||
assert_jet_in_door(s, jet_rd_add, &[atom_0_8, atom_0_3], &[atom_0, r_sample_z, atom_0], A(q, &ubig!(0x3ff1999999999999)));
|
||||
assert_jet_in_door(s, jet_rd_add, &[atom_0_8, atom_0_3], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x3ff199999999999a)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rd_sub() {
|
||||
let s = &mut init_stack();
|
||||
let q = &mut init_stack();
|
||||
|
||||
assert_jet_in_door(s, jet_rd_sub, &[atom_0, atom_0], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x0000000000000000)));
|
||||
assert_jet_in_door(s, jet_rd_sub, &[atom_0, atom_1], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0xbff0000000000000)));
|
||||
assert_jet_in_door(s, jet_rd_sub, &[atom_1, atom_1], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x0000000000000000)));
|
||||
assert_jet_in_door(s, jet_rd_sub, &[atom_1, atom_2], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0xbff0000000000000)));
|
||||
assert_jet_in_door(s, jet_rd_sub, &[atom_2, atom_1], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x3ff0000000000000)));
|
||||
assert_jet_in_door(s, jet_rd_sub, &[atom_1_1, atom_0_8], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x3fd3333333333334)));
|
||||
assert_jet_in_door(s, jet_rd_sub, &[atom_1_1, atom_0_3], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x3fe999999999999a)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rd_mul() {
|
||||
let s = &mut init_stack();
|
||||
let q = &mut init_stack();
|
||||
|
||||
assert_jet_in_door(s, jet_rd_mul, &[atom_0, atom_0], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x0000000000000000)));
|
||||
assert_jet_in_door(s, jet_rd_mul, &[atom_0, atom_1], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x0000000000000000)));
|
||||
assert_jet_in_door(s, jet_rd_mul, &[atom_1, atom_1], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x3ff0000000000000)));
|
||||
assert_jet_in_door(s, jet_rd_mul, &[atom_1, atom_2], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x4000000000000000)));
|
||||
assert_jet_in_door(s, jet_rd_mul, &[atom_2, atom_2], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x4010000000000000)));
|
||||
assert_jet_in_door(s, jet_rd_mul, &[atom_1_5, atom_2], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x4008000000000000)));
|
||||
assert_jet_in_door(s, jet_rd_mul, &[atom_1_1, atom_0_8], &[atom_0, r_sample_z, atom_0], A(q, &ubig!(0x3fec28f5c28f5c2a)));
|
||||
assert_jet_in_door(s, jet_rd_mul, &[atom_1_1, atom_0_8], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x3fec28f5c28f5c2a)));
|
||||
assert_jet_in_door(s, jet_rd_mul, &[atom_1_1, atom_0_3], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x3fd51eb851eb851f)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rd_div() {
|
||||
let s = &mut init_stack();
|
||||
let q = &mut init_stack();
|
||||
|
||||
assert_jet_in_door(s, jet_rd_div, &[atom_1, atom_0], &[atom_0, r_sample_n, atom_0], A(q, &UBig::from(DOUBINF as u64)));
|
||||
// XX test 0/0
|
||||
assert_jet_in_door(s, jet_rd_div, &[atom_0, atom_1], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x0000000000000000)));
|
||||
assert_jet_in_door(s, jet_rd_div, &[atom_1, atom_1], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x3ff0000000000000)));
|
||||
assert_jet_in_door(s, jet_rd_div, &[atom_1, atom_2], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x3fe0000000000000)));
|
||||
assert_jet_in_door(s, jet_rd_div, &[atom_2, atom_2], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x3ff0000000000000)));
|
||||
assert_jet_in_door(s, jet_rd_div, &[atom_1_1, atom_0_8], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x3ff6000000000000)));
|
||||
assert_jet_in_door(s, jet_rd_div, &[atom_1_1, atom_0_3], &[atom_0, r_sample_z, atom_0], A(q, &ubig!(0x400d555555555556)));
|
||||
assert_jet_in_door(s, jet_rd_div, &[atom_1_1, atom_0_3], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x400d555555555556)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rd_sqt() {
|
||||
let s = &mut init_stack();
|
||||
let q = &mut init_stack();
|
||||
|
||||
assert_jet_in_door(s, jet_rd_sqt, &[atom_0], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x0000000000000000)));
|
||||
assert_jet_in_door(s, jet_rd_sqt, &[atom_1], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x3ff0000000000000)));
|
||||
assert_jet_in_door(s, jet_rd_sqt, &[atom_2], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x3ff6a09e667f3bcd)));
|
||||
assert_jet_in_door(s, jet_rd_sqt, &[atom_2], &[atom_0, r_sample_z, atom_0], A(q, &ubig!(0x3ff6a09e667f3bcc)));
|
||||
assert_jet_in_door(s, jet_rd_sqt, &[atom_3], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x3ffbb67ae8584caa)));
|
||||
assert_jet_in_door(s, jet_rd_sqt, &[atom_1_1], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x3ff0c7ebc96a56f6)));
|
||||
assert_jet_in_door(s, jet_rd_sqt, &[atom_1_1], &[atom_0, r_sample_z, atom_0], A(q, &ubig!(0x3ff0c7ebc96a56f5)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rd_fma() {
|
||||
let s = &mut init_stack();
|
||||
let q = &mut init_stack();
|
||||
|
||||
assert_jet_in_door(s, jet_rd_fma, &[atom_1, atom_0, atom_0], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x0000000000000000)));
|
||||
assert_jet_in_door(s, jet_rd_fma, &[atom_0, atom_1, atom_1], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x3ff0000000000000)));
|
||||
assert_jet_in_door(s, jet_rd_fma, &[atom_1, atom_1, atom_1], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x4000000000000000)));
|
||||
assert_jet_in_door(s, jet_rd_fma, &[atom_1, atom_2, atom_1], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x4008000000000000)));
|
||||
assert_jet_in_door(s, jet_rd_fma, &[atom_2, atom_2, atom_1], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x4014000000000000)));
|
||||
assert_jet_in_door(s, jet_rd_fma, &[atom_1_1, atom_0_8, atom_0_3], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x3ff2e147ae147ae2)));
|
||||
assert_jet_in_door(s, jet_rd_fma, &[atom_1_1, atom_0_8, atom_0_3], &[atom_0, r_sample_z, atom_0], A(q, &ubig!(0x3ff2e147ae147ae1)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rd_lth() {
|
||||
let s = &mut init_stack();
|
||||
|
||||
assert_jet_in_door(s, jet_rd_lth, &[atom_1, atom_0], &[atom_0, r_sample_n, atom_0], NO);
|
||||
assert_jet_in_door(s, jet_rd_lth, &[atom_0, atom_1], &[atom_0, r_sample_n, atom_0], YES);
|
||||
assert_jet_in_door(s, jet_rd_lth, &[atom_1, atom_1], &[atom_0, r_sample_n, atom_0], NO);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rd_lte() {
|
||||
let s = &mut init_stack();
|
||||
|
||||
assert_jet_in_door(s, jet_rd_lte, &[atom_1, atom_0], &[atom_0, r_sample_n, atom_0], NO);
|
||||
assert_jet_in_door(s, jet_rd_lte, &[atom_0, atom_1], &[atom_0, r_sample_n, atom_0], YES);
|
||||
assert_jet_in_door(s, jet_rd_lte, &[atom_1, atom_1], &[atom_0, r_sample_n, atom_0], YES);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rd_equ() {
|
||||
let s = &mut init_stack();
|
||||
|
||||
assert_jet_in_door(s, jet_rd_equ, &[atom_1, atom_0], &[atom_0, r_sample_n, atom_0], NO);
|
||||
assert_jet_in_door(s, jet_rd_equ, &[atom_0, atom_1], &[atom_0, r_sample_n, atom_0], NO);
|
||||
assert_jet_in_door(s, jet_rd_equ, &[atom_1, atom_1], &[atom_0, r_sample_n, atom_0], YES);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rd_gte() {
|
||||
let s = &mut init_stack();
|
||||
|
||||
assert_jet_in_door(s, jet_rd_gte, &[atom_1, atom_0], &[atom_0, r_sample_n, atom_0], YES);
|
||||
assert_jet_in_door(s, jet_rd_gte, &[atom_0, atom_1], &[atom_0, r_sample_n, atom_0], NO);
|
||||
assert_jet_in_door(s, jet_rd_gte, &[atom_1, atom_1], &[atom_0, r_sample_n, atom_0], YES);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rd_gth() {
|
||||
let s = &mut init_stack();
|
||||
|
||||
assert_jet_in_door(s, jet_rd_gth, &[atom_1, atom_0], &[atom_0, r_sample_n, atom_0], YES);
|
||||
assert_jet_in_door(s, jet_rd_gth, &[atom_0, atom_1], &[atom_0, r_sample_n, atom_0], NO);
|
||||
assert_jet_in_door(s, jet_rd_gth, &[atom_1, atom_1], &[atom_0, r_sample_n, atom_0], NO);
|
||||
}
|
||||
}
|
510
rust/ares/src/jets/float_rh.rs
Normal file
510
rust/ares/src/jets/float_rh.rs
Normal file
@ -0,0 +1,510 @@
|
||||
/** Floating-point jets
|
||||
*/
|
||||
use crate::jets;
|
||||
use crate::jets::JetErr::*;
|
||||
use crate::jets::util::*;
|
||||
use crate::jets::util::test::{assert_jet, assert_jet_err, assert_jet_ubig, assert_nary_jet_ubig, init_stack, A};
|
||||
use crate::mem::NockStack;
|
||||
use crate::newt::Newt;
|
||||
use crate::noun::{Atom, IndirectAtom, Noun, D, T, Cell, NO, YES};
|
||||
use ibig::{UBig, ubig};
|
||||
use softfloat_sys::*;
|
||||
use std::io::Write;
|
||||
|
||||
crate::gdb!();
|
||||
|
||||
const HALFNAN: u16 = 0x7e00;
|
||||
const HALFINF: u16 = 0x7c00;
|
||||
const HALFZERO: u16 = 0x0000;
|
||||
|
||||
#[inline(always)]
|
||||
fn _nan_test(
|
||||
a: float16_t
|
||||
) -> bool {
|
||||
unsafe {
|
||||
!f16_eq(a, a)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn _nan_unify(
|
||||
a: float16_t
|
||||
) -> float16_t {
|
||||
unsafe {
|
||||
if _nan_test(a) {
|
||||
return softfloat_sys::float16_t { v: HALFNAN};
|
||||
}
|
||||
a
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn _set_rounding(
|
||||
r: char
|
||||
) -> u8 {
|
||||
match r {
|
||||
'n' => softfloat_round_near_even,
|
||||
'z' => softfloat_round_minMag,
|
||||
'u' => softfloat_round_max,
|
||||
'd' => softfloat_round_min,
|
||||
// formal fallthrough, should never happen
|
||||
_ => softfloat_round_near_even,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_rh_add(
|
||||
_stack: &mut NockStack,
|
||||
_newt: &mut Option<&mut Newt>,
|
||||
subject: Noun
|
||||
) -> jets::Result {
|
||||
unsafe{
|
||||
let sam = slot(subject, 6)?;
|
||||
let a = slot(sam, 2)?.as_atom()?.as_direct()?;
|
||||
let b = slot(sam, 3)?.as_atom()?.as_direct()?;
|
||||
let r = slot(subject, 30)?.as_atom()?.as_direct()?.data() as u8 as char;
|
||||
|
||||
let dat_a = softfloat_sys::float16_t { v: a.data() as u16};
|
||||
let dat_b = softfloat_sys::float16_t { v: b.data() as u16};
|
||||
let mod_r = _set_rounding(r);
|
||||
|
||||
softfloat_roundingMode_write_helper(mod_r);
|
||||
let x = _nan_unify(f16_add(dat_a, dat_b));
|
||||
|
||||
Ok(D(x.v as u64))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_rh_sub(
|
||||
_stack: &mut NockStack,
|
||||
_newt: &mut Option<&mut Newt>,
|
||||
subject: Noun
|
||||
) -> jets::Result {
|
||||
unsafe{
|
||||
let sam = slot(subject, 6)?;
|
||||
let a = slot(sam, 2)?.as_atom()?.as_direct()?;
|
||||
let b = slot(sam, 3)?.as_atom()?.as_direct()?;
|
||||
let r = slot(subject, 30)?.as_atom()?.as_direct()?.data() as u8 as char;
|
||||
|
||||
let dat_a = softfloat_sys::float16_t { v: a.data() as u16};
|
||||
let dat_b = softfloat_sys::float16_t { v: b.data() as u16};
|
||||
let mod_r = _set_rounding(r);
|
||||
|
||||
softfloat_roundingMode_write_helper(mod_r);
|
||||
let x = _nan_unify(f16_sub(dat_a, dat_b));
|
||||
|
||||
Ok(D(x.v as u64))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_rh_mul(
|
||||
_stack: &mut NockStack,
|
||||
_newt: &mut Option<&mut Newt>,
|
||||
subject: Noun
|
||||
) -> jets::Result {
|
||||
unsafe{
|
||||
let sam = slot(subject, 6)?;
|
||||
let a = slot(sam, 2)?.as_atom()?.as_direct()?;
|
||||
let b = slot(sam, 3)?.as_atom()?.as_direct()?;
|
||||
let r = slot(subject, 30)?.as_atom()?.as_direct()?.data() as u8 as char;
|
||||
|
||||
let dat_a = softfloat_sys::float16_t { v: a.data() as u16};
|
||||
let dat_b = softfloat_sys::float16_t { v: b.data() as u16};
|
||||
let mod_r = _set_rounding(r);
|
||||
|
||||
softfloat_roundingMode_write_helper(mod_r);
|
||||
let x = _nan_unify(f16_mul(dat_a, dat_b));
|
||||
|
||||
Ok(D(x.v as u64))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_rh_div(
|
||||
_stack: &mut NockStack,
|
||||
_newt: &mut Option<&mut Newt>,
|
||||
subject: Noun
|
||||
) -> jets::Result {
|
||||
unsafe{
|
||||
let sam = slot(subject, 6)?;
|
||||
let a = slot(sam, 2)?.as_atom()?.as_direct()?;
|
||||
let b = slot(sam, 3)?.as_atom()?.as_direct()?;
|
||||
let r = slot(subject, 30)?.as_atom()?.as_direct()?.data() as u8 as char;
|
||||
|
||||
let dat_a = softfloat_sys::float16_t { v: a.data() as u16};
|
||||
let dat_b = softfloat_sys::float16_t { v: b.data() as u16};
|
||||
let mod_r = _set_rounding(r);
|
||||
|
||||
softfloat_roundingMode_write_helper(mod_r);
|
||||
let x = _nan_unify(f16_div(dat_a, dat_b));
|
||||
|
||||
Ok(D(x.v as u64))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_rh_sqt(
|
||||
_stack: &mut NockStack,
|
||||
_newt: &mut Option<&mut Newt>,
|
||||
subject: Noun
|
||||
) -> jets::Result {
|
||||
unsafe{
|
||||
let sam = slot(subject, 6)?;
|
||||
eprintln!("»sam: {:?}", sam);
|
||||
let a = sam.as_atom()?.as_direct()?;
|
||||
eprintln!("»a: {:?}", a.as_noun());
|
||||
let r = slot(subject, 30)?.as_atom()?.as_direct()?.data() as u8 as char;
|
||||
|
||||
let dat_a = softfloat_sys::float16_t { v: a.data() as u16};
|
||||
let mod_r = _set_rounding(r);
|
||||
|
||||
softfloat_roundingMode_write_helper(mod_r);
|
||||
let x = _nan_unify(f16_sqrt(dat_a));
|
||||
|
||||
Ok(D(x.v as u64))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_rh_fma(
|
||||
_stack: &mut NockStack,
|
||||
_newt: &mut Option<&mut Newt>,
|
||||
subject: Noun
|
||||
) -> jets::Result {
|
||||
unsafe{
|
||||
let sam = slot(subject, 6)?;
|
||||
let a = slot(sam, 2)?.as_atom()?.as_direct()?;
|
||||
let b = slot(sam, 6)?.as_atom()?.as_direct()?;
|
||||
let c = slot(sam, 7)?.as_atom()?.as_direct()?;
|
||||
let r = slot(subject, 30)?.as_atom()?.as_direct()?.data() as u8 as char;
|
||||
|
||||
let dat_a = softfloat_sys::float16_t { v: a.data() as u16};
|
||||
let dat_b = softfloat_sys::float16_t { v: b.data() as u16};
|
||||
let dat_c = softfloat_sys::float16_t { v: c.data() as u16};
|
||||
let mod_r = _set_rounding(r);
|
||||
|
||||
softfloat_roundingMode_write_helper(mod_r);
|
||||
let x = _nan_unify(f16_mulAdd(dat_a, dat_b, dat_c));
|
||||
|
||||
Ok(D(x.v as u64))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_rh_lth(
|
||||
_stack: &mut NockStack,
|
||||
_newt: &mut Option<&mut Newt>,
|
||||
subject: Noun
|
||||
) -> jets::Result {
|
||||
unsafe{
|
||||
let sam = slot(subject, 6)?;
|
||||
let a = slot(sam, 2)?.as_atom()?.as_direct()?;
|
||||
let b = slot(sam, 3)?.as_atom()?.as_direct()?;
|
||||
let r = slot(subject, 30)?.as_atom()?.as_direct()?.data() as u8 as char;
|
||||
|
||||
let dat_a = softfloat_sys::float16_t { v: a.data() as u16};
|
||||
let dat_b = softfloat_sys::float16_t { v: b.data() as u16};
|
||||
let mod_r = _set_rounding(r);
|
||||
|
||||
softfloat_roundingMode_write_helper(mod_r);
|
||||
let t = f16_lt(dat_a, dat_b);
|
||||
|
||||
if t { Ok(YES) } else { Ok(NO) }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_rh_lte(
|
||||
_stack: &mut NockStack,
|
||||
_newt: &mut Option<&mut Newt>,
|
||||
subject: Noun
|
||||
) -> jets::Result {
|
||||
unsafe{
|
||||
let sam = slot(subject, 6)?;
|
||||
let a = slot(sam, 2)?.as_atom()?.as_direct()?;
|
||||
let b = slot(sam, 3)?.as_atom()?.as_direct()?;
|
||||
let r = slot(subject, 30)?.as_atom()?.as_direct()?.data() as u8 as char;
|
||||
|
||||
let dat_a = softfloat_sys::float16_t { v: a.data() as u16};
|
||||
let dat_b = softfloat_sys::float16_t { v: b.data() as u16};
|
||||
let mod_r = _set_rounding(r);
|
||||
|
||||
softfloat_roundingMode_write_helper(mod_r);
|
||||
let t = f16_le(dat_a, dat_b);
|
||||
|
||||
if t { Ok(YES) } else { Ok(NO) }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_rh_equ(
|
||||
_stack: &mut NockStack,
|
||||
_newt: &mut Option<&mut Newt>,
|
||||
subject: Noun
|
||||
) -> jets::Result {
|
||||
unsafe{
|
||||
let sam = slot(subject, 6)?;
|
||||
let a = slot(sam, 2)?.as_atom()?.as_direct()?;
|
||||
let b = slot(sam, 3)?.as_atom()?.as_direct()?;
|
||||
let r = slot(subject, 30)?.as_atom()?.as_direct()?.data() as u8 as char;
|
||||
|
||||
let dat_a = softfloat_sys::float16_t { v: a.data() as u16};
|
||||
let dat_b = softfloat_sys::float16_t { v: b.data() as u16};
|
||||
let mod_r = _set_rounding(r);
|
||||
|
||||
softfloat_roundingMode_write_helper(mod_r);
|
||||
let t = f16_eq(dat_a, dat_b);
|
||||
|
||||
if t { Ok(YES) } else { Ok(NO) }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_rh_gte(
|
||||
_stack: &mut NockStack,
|
||||
_newt: &mut Option<&mut Newt>,
|
||||
subject: Noun
|
||||
) -> jets::Result {
|
||||
unsafe{
|
||||
let sam = slot(subject, 6)?;
|
||||
let a = slot(sam, 2)?.as_atom()?.as_direct()?;
|
||||
let b = slot(sam, 3)?.as_atom()?.as_direct()?;
|
||||
let r = slot(subject, 30)?.as_atom()?.as_direct()?.data() as u8 as char;
|
||||
|
||||
let dat_a = softfloat_sys::float16_t { v: a.data() as u16};
|
||||
let dat_b = softfloat_sys::float16_t { v: b.data() as u16};
|
||||
let mod_r = _set_rounding(r);
|
||||
|
||||
softfloat_roundingMode_write_helper(mod_r);
|
||||
let t = f16_le(dat_b, dat_a);
|
||||
|
||||
if t { Ok(YES) } else { Ok(NO) }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_rh_gth(
|
||||
_stack: &mut NockStack,
|
||||
_newt: &mut Option<&mut Newt>,
|
||||
subject: Noun
|
||||
) -> jets::Result {
|
||||
unsafe{
|
||||
let sam = slot(subject, 6)?;
|
||||
let a = slot(sam, 2)?.as_atom()?.as_direct()?;
|
||||
let b = slot(sam, 3)?.as_atom()?.as_direct()?;
|
||||
let r = slot(subject, 30)?.as_atom()?.as_direct()?.data() as u8 as char;
|
||||
|
||||
let dat_a = softfloat_sys::float16_t { v: a.data() as u16};
|
||||
let dat_b = softfloat_sys::float16_t { v: b.data() as u16};
|
||||
let mod_r = _set_rounding(r);
|
||||
|
||||
softfloat_roundingMode_write_helper(mod_r);
|
||||
let t = f16_lt(dat_b, dat_a);
|
||||
|
||||
if t { Ok(YES) } else { Ok(NO) }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::jets::{Jet, JetErr};
|
||||
use crate::jets::util::test::{assert_jet, assert_jet_err, init_stack};
|
||||
use crate::noun::D;
|
||||
use crate::jets::util::test::{assert_noun_eq};
|
||||
use assert_no_alloc::assert_no_alloc;
|
||||
|
||||
pub fn assert_jet_in_door(
|
||||
stack: &mut NockStack,
|
||||
jet: Jet,
|
||||
sam: &[fn(&mut NockStack) -> Noun], // regular sample
|
||||
ctx: &[fn(&mut NockStack) -> Noun], // door sample as context
|
||||
res: Noun) {
|
||||
unsafe {
|
||||
let mut sam: Vec<Noun> = sam.iter().map(|f| f(stack)).collect();
|
||||
let mut ctx: Vec<Noun> = ctx.iter().map(|f| f(stack)).collect();
|
||||
let sam = if(sam.len() > 1) { T(stack, &sam) } else { sam[0] };
|
||||
eprintln!("sam: {:?}", sam);
|
||||
let ctx = if(ctx.len() > 1) { T(stack, &ctx) } else { ctx[0] };
|
||||
eprintln!("ctx: {:?}", ctx);
|
||||
let pay = Cell::new(stack, sam, ctx).as_noun();
|
||||
eprintln!("pay: {:?}", pay);
|
||||
let sbj = Cell::new(stack, D(0), pay).as_noun();
|
||||
eprintln!("sbj: {:?}", sbj);
|
||||
std::io::stderr().flush().unwrap();
|
||||
let jet_res = jet(stack, &mut None, sbj).unwrap();
|
||||
eprintln!("jet: {:x}\n", jet_res.as_atom().expect("").as_direct().expect("").data());
|
||||
std::io::stderr().flush().unwrap();
|
||||
assert_noun_eq(stack, jet_res, res);
|
||||
}
|
||||
}
|
||||
|
||||
fn atom_0(_stack: &mut NockStack) -> Noun {
|
||||
D(0x0000)
|
||||
}
|
||||
|
||||
fn atom_1(_stack: &mut NockStack) -> Noun {
|
||||
D(0x3c00)
|
||||
}
|
||||
|
||||
fn atom_2(_stack: &mut NockStack) -> Noun {
|
||||
D(0x4000)
|
||||
}
|
||||
|
||||
fn atom_3(_stack: &mut NockStack) -> Noun {
|
||||
D(0x4200)
|
||||
}
|
||||
|
||||
fn atom_1_5(_stack: &mut NockStack) -> Noun {
|
||||
D(0x3e00)
|
||||
}
|
||||
|
||||
fn atom_1_1(_stack: &mut NockStack) -> Noun {
|
||||
D(0x3c66)
|
||||
}
|
||||
|
||||
fn atom_0_8(_stack: &mut NockStack) -> Noun {
|
||||
D(0x3a66)
|
||||
}
|
||||
|
||||
fn atom_0_3(_stack: &mut NockStack) -> Noun {
|
||||
D(0x34cd)
|
||||
}
|
||||
|
||||
fn r_sample_n(_stack: &mut NockStack) -> Noun {
|
||||
D('n' as u8 as u64)
|
||||
}
|
||||
|
||||
fn r_sample_z(_stack: &mut NockStack) -> Noun {
|
||||
D('z' as u8 as u64)
|
||||
}
|
||||
|
||||
fn r_sample_u(_stack: &mut NockStack) -> Noun {
|
||||
D('u' as u8 as u64)
|
||||
}
|
||||
|
||||
fn r_sample_d(_stack: &mut NockStack) -> Noun {
|
||||
D('d' as u8 as u64)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rh_add() {
|
||||
let s = &mut init_stack();
|
||||
|
||||
assert_jet_in_door(s, jet_rh_add, &[atom_0, atom_0], &[atom_0, r_sample_n, atom_0], D(0x0000));
|
||||
assert_jet_in_door(s, jet_rh_add, &[atom_0, atom_1], &[atom_0, r_sample_n, atom_0], D(0x3c00));
|
||||
assert_jet_in_door(s, jet_rh_add, &[atom_1, atom_1], &[atom_0, r_sample_n, atom_0], D(0x4000));
|
||||
assert_jet_in_door(s, jet_rh_add, &[atom_1, atom_2], &[atom_0, r_sample_n, atom_0], D(0x4200));
|
||||
assert_jet_in_door(s, jet_rh_add, &[atom_2, atom_1], &[atom_0, r_sample_n, atom_0], D(0x4200));
|
||||
assert_jet_in_door(s, jet_rh_add, &[atom_0_8, atom_0_3], &[atom_0, r_sample_n, atom_0], D(0x3c66));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rh_sub() {
|
||||
let s = &mut init_stack();
|
||||
|
||||
assert_jet_in_door(s, jet_rh_sub, &[atom_0, atom_0], &[atom_0, r_sample_n, atom_0], D(0x0000));
|
||||
assert_jet_in_door(s, jet_rh_sub, &[atom_0, atom_1], &[atom_0, r_sample_n, atom_0], D(0xbc00));
|
||||
assert_jet_in_door(s, jet_rh_sub, &[atom_1, atom_1], &[atom_0, r_sample_n, atom_0], D(0x0000));
|
||||
assert_jet_in_door(s, jet_rh_sub, &[atom_1, atom_2], &[atom_0, r_sample_n, atom_0], D(0xbc00));
|
||||
assert_jet_in_door(s, jet_rh_sub, &[atom_2, atom_1], &[atom_0, r_sample_n, atom_0], D(0x3c00));
|
||||
assert_jet_in_door(s, jet_rh_sub, &[atom_1_1, atom_0_8], &[atom_0, r_sample_n, atom_0], D(0x34cc));
|
||||
assert_jet_in_door(s, jet_rh_sub, &[atom_1_1, atom_0_3], &[atom_0, r_sample_n, atom_0], D(0x3a66));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rh_mul() {
|
||||
let s = &mut init_stack();
|
||||
|
||||
assert_jet_in_door(s, jet_rh_mul, &[atom_0, atom_0], &[atom_0, r_sample_n, atom_0], D(0x0000));
|
||||
assert_jet_in_door(s, jet_rh_mul, &[atom_0, atom_1], &[atom_0, r_sample_n, atom_0], D(0x0000));
|
||||
assert_jet_in_door(s, jet_rh_mul, &[atom_1, atom_1], &[atom_0, r_sample_n, atom_0], D(0x3c00));
|
||||
assert_jet_in_door(s, jet_rh_mul, &[atom_1, atom_2], &[atom_0, r_sample_n, atom_0], D(0x4000));
|
||||
assert_jet_in_door(s, jet_rh_mul, &[atom_2, atom_2], &[atom_0, r_sample_n, atom_0], D(0x4400));
|
||||
assert_jet_in_door(s, jet_rh_mul, &[atom_1_5, atom_2], &[atom_0, r_sample_n, atom_0], D(0x4200));
|
||||
assert_jet_in_door(s, jet_rh_mul, &[atom_1_1, atom_0_8], &[atom_0, r_sample_z, atom_0], D(0x3b09));
|
||||
assert_jet_in_door(s, jet_rh_mul, &[atom_1_1, atom_0_8], &[atom_0, r_sample_u, atom_0], D(0x3b0a));
|
||||
assert_jet_in_door(s, jet_rh_mul, &[atom_1_1, atom_0_3], &[atom_0, r_sample_n, atom_0], D(0x3547));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rh_div() {
|
||||
let s = &mut init_stack();
|
||||
|
||||
assert_jet_in_door(s, jet_rh_div, &[atom_1, atom_0], &[atom_0, r_sample_n, atom_0], D(HALFINF as u64));
|
||||
// XX test 0/0
|
||||
assert_jet_in_door(s, jet_rh_div, &[atom_0, atom_1], &[atom_0, r_sample_n, atom_0], D(0x0000));
|
||||
assert_jet_in_door(s, jet_rh_div, &[atom_1, atom_1], &[atom_0, r_sample_n, atom_0], D(0x3c00));
|
||||
assert_jet_in_door(s, jet_rh_div, &[atom_1, atom_2], &[atom_0, r_sample_n, atom_0], D(0x3800));
|
||||
assert_jet_in_door(s, jet_rh_div, &[atom_2, atom_2], &[atom_0, r_sample_n, atom_0], D(0x3c00));
|
||||
assert_jet_in_door(s, jet_rh_div, &[atom_1_1, atom_0_8], &[atom_0, r_sample_z, atom_0], D(0x3d7f));
|
||||
assert_jet_in_door(s, jet_rh_div, &[atom_1_1, atom_0_8], &[atom_0, r_sample_n, atom_0], D(0x3d80));
|
||||
assert_jet_in_door(s, jet_rh_div, &[atom_1_1, atom_0_3], &[atom_0, r_sample_n, atom_0], D(0x4354));
|
||||
assert_jet_in_door(s, jet_rh_div, &[atom_1_1, atom_0_3], &[atom_0, r_sample_u, atom_0], D(0x4355));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rh_sqt() {
|
||||
let s = &mut init_stack();
|
||||
|
||||
assert_jet_in_door(s, jet_rh_sqt, &[atom_0], &[atom_0, r_sample_n, atom_0], D(0x0000));
|
||||
assert_jet_in_door(s, jet_rh_sqt, &[atom_1], &[atom_0, r_sample_n, atom_0], D(0x3c00));
|
||||
assert_jet_in_door(s, jet_rh_sqt, &[atom_2], &[atom_0, r_sample_n, atom_0], D(0x3da8));
|
||||
assert_jet_in_door(s, jet_rh_sqt, &[atom_3], &[atom_0, r_sample_n, atom_0], D(0x3eee));
|
||||
assert_jet_in_door(s, jet_rh_sqt, &[atom_3], &[atom_0, r_sample_z, atom_0], D(0x3eed));
|
||||
assert_jet_in_door(s, jet_rh_sqt, &[atom_1_1], &[atom_0, r_sample_n, atom_0], D(0x3c32));
|
||||
assert_jet_in_door(s, jet_rh_sqt, &[atom_1_1], &[atom_0, r_sample_z, atom_0], D(0x3c31));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rh_fma() {
|
||||
let s = &mut init_stack();
|
||||
|
||||
assert_jet_in_door(s, jet_rh_fma, &[atom_1, atom_0, atom_0], &[atom_0, r_sample_n, atom_0], D(0x0000));
|
||||
assert_jet_in_door(s, jet_rh_fma, &[atom_0, atom_1, atom_1], &[atom_0, r_sample_n, atom_0], D(0x3c00));
|
||||
assert_jet_in_door(s, jet_rh_fma, &[atom_1, atom_1, atom_1], &[atom_0, r_sample_n, atom_0], D(0x4000));
|
||||
assert_jet_in_door(s, jet_rh_fma, &[atom_1, atom_2, atom_1], &[atom_0, r_sample_n, atom_0], D(0x4200));
|
||||
assert_jet_in_door(s, jet_rh_fma, &[atom_2, atom_2, atom_1], &[atom_0, r_sample_n, atom_0], D(0x4500));
|
||||
assert_jet_in_door(s, jet_rh_fma, &[atom_1_1, atom_0_8, atom_0_3], &[atom_0, r_sample_n, atom_0], D(0x3cb8));
|
||||
assert_jet_in_door(s, jet_rh_fma, &[atom_1_1, atom_0_8, atom_0_3], &[atom_0, r_sample_z, atom_0], D(0x3cb7));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rh_lth() {
|
||||
let s = &mut init_stack();
|
||||
|
||||
assert_jet_in_door(s, jet_rh_lth, &[atom_1, atom_0], &[atom_0, r_sample_n, atom_0], NO);
|
||||
assert_jet_in_door(s, jet_rh_lth, &[atom_0, atom_1], &[atom_0, r_sample_n, atom_0], YES);
|
||||
assert_jet_in_door(s, jet_rh_lth, &[atom_1, atom_1], &[atom_0, r_sample_n, atom_0], NO);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rh_lte() {
|
||||
let s = &mut init_stack();
|
||||
|
||||
assert_jet_in_door(s, jet_rh_lte, &[atom_1, atom_0], &[atom_0, r_sample_n, atom_0], NO);
|
||||
assert_jet_in_door(s, jet_rh_lte, &[atom_0, atom_1], &[atom_0, r_sample_n, atom_0], YES);
|
||||
assert_jet_in_door(s, jet_rh_lte, &[atom_1, atom_1], &[atom_0, r_sample_n, atom_0], YES);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rh_equ() {
|
||||
let s = &mut init_stack();
|
||||
|
||||
assert_jet_in_door(s, jet_rh_equ, &[atom_1, atom_0], &[atom_0, r_sample_n, atom_0], NO);
|
||||
assert_jet_in_door(s, jet_rh_equ, &[atom_0, atom_1], &[atom_0, r_sample_n, atom_0], NO);
|
||||
assert_jet_in_door(s, jet_rh_equ, &[atom_1, atom_1], &[atom_0, r_sample_n, atom_0], YES);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rh_gte() {
|
||||
let s = &mut init_stack();
|
||||
|
||||
assert_jet_in_door(s, jet_rh_gte, &[atom_1, atom_0], &[atom_0, r_sample_n, atom_0], YES);
|
||||
assert_jet_in_door(s, jet_rh_gte, &[atom_0, atom_1], &[atom_0, r_sample_n, atom_0], NO);
|
||||
assert_jet_in_door(s, jet_rh_gte, &[atom_1, atom_1], &[atom_0, r_sample_n, atom_0], YES);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rh_gth() {
|
||||
let s = &mut init_stack();
|
||||
|
||||
assert_jet_in_door(s, jet_rh_gth, &[atom_1, atom_0], &[atom_0, r_sample_n, atom_0], YES);
|
||||
assert_jet_in_door(s, jet_rh_gth, &[atom_0, atom_1], &[atom_0, r_sample_n, atom_0], NO);
|
||||
assert_jet_in_door(s, jet_rh_gth, &[atom_1, atom_1], &[atom_0, r_sample_n, atom_0], NO);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
577
rust/ares/src/jets/float_rq.rs
Normal file
577
rust/ares/src/jets/float_rq.rs
Normal file
@ -0,0 +1,577 @@
|
||||
/** Floating-point jets
|
||||
*/
|
||||
use crate::jets;
|
||||
use crate::jets::JetErr::*;
|
||||
use crate::jets::util::*;
|
||||
use crate::jets::util::test::{assert_jet, assert_jet_err, assert_jet_ubig, assert_nary_jet_ubig, init_stack, A};
|
||||
use crate::mem::NockStack;
|
||||
use crate::newt::Newt;
|
||||
use crate::noun::{Atom, IndirectAtom, Noun, D, T, Cell, NO, YES};
|
||||
use ibig::{UBig, ubig};
|
||||
use softfloat_sys::*;
|
||||
use std::io::Write;
|
||||
|
||||
crate::gdb!();
|
||||
|
||||
const QUADNAN: [u64; 2] = [0x0000000000000000, 0x7fff800000000000];
|
||||
const QUADINF: [u64; 2] = [0x0000000000000000, 0x7fff000000000000];
|
||||
const QUADZERO: [u64; 2] = [0x0000000000000000, 0x0000000000000000];
|
||||
|
||||
#[inline(always)]
|
||||
fn _nan_test(
|
||||
a: float128_t
|
||||
) -> bool {
|
||||
unsafe {
|
||||
!f128_eq(a, a)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn _nan_unify(
|
||||
a: float128_t
|
||||
) -> float128_t {
|
||||
unsafe {
|
||||
if _nan_test(a) {
|
||||
return softfloat_sys::float128_t { v: QUADNAN };
|
||||
}
|
||||
a
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn _set_rounding(
|
||||
r: char
|
||||
) -> u8 {
|
||||
match r {
|
||||
'n' => softfloat_round_near_even,
|
||||
'z' => softfloat_round_minMag,
|
||||
'u' => softfloat_round_max,
|
||||
'd' => softfloat_round_min,
|
||||
// formal fallthrough, should never happen
|
||||
_ => softfloat_round_near_even,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_rq_add(
|
||||
stack: &mut NockStack,
|
||||
_newt: &mut Option<&mut Newt>,
|
||||
subject: Noun
|
||||
) -> jets::Result {
|
||||
unsafe {
|
||||
let sam = slot(subject, 6)?;
|
||||
let a = slot(sam, 2)?.as_atom()?;
|
||||
let b = slot(sam, 3)?.as_atom()?;
|
||||
let r = slot(subject, 30)?.as_atom()?.as_direct()?.data() as u8 as char;
|
||||
|
||||
// @rq MAY be indirect but they are 128 bits
|
||||
let dat_a = softfloat_sys::float128_t { v: a.as_u128_pair()? };
|
||||
let dat_b = softfloat_sys::float128_t { v: b.as_u128_pair()? };
|
||||
let mod_r = _set_rounding(r);
|
||||
|
||||
softfloat_roundingMode_write_helper(mod_r);
|
||||
let x = _nan_unify(f128_add(dat_a, dat_b));
|
||||
|
||||
let x1_msb = (x.v[1] | 0) != 0;
|
||||
let x2_msb = ((x.v[0] >> 63) & 1) != 0;
|
||||
let x2_2sb = ((x.v[0] >> 62) & 1) != 0;
|
||||
|
||||
if x1_msb || x2_msb || x2_2sb {
|
||||
let hi = (x.v[1] as u128) << 64;
|
||||
let lo = x.v[0] as u128;
|
||||
Ok(A(stack, &UBig::from(hi | lo)))
|
||||
} else {
|
||||
Ok(D(x.v[0]))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_rq_sub(
|
||||
stack: &mut NockStack,
|
||||
_newt: &mut Option<&mut Newt>,
|
||||
subject: Noun
|
||||
) -> jets::Result {
|
||||
unsafe {
|
||||
let sam = slot(subject, 6)?;
|
||||
let a = slot(sam, 2)?.as_atom()?;
|
||||
let b = slot(sam, 3)?.as_atom()?;
|
||||
let r = slot(subject, 30)?.as_atom()?.as_direct()?.data() as u8 as char;
|
||||
|
||||
// @rq MAY be indirect but they are 128 bits
|
||||
let dat_a = softfloat_sys::float128_t { v: a.as_u128_pair()? };
|
||||
let dat_b = softfloat_sys::float128_t { v: b.as_u128_pair()? };
|
||||
let mod_r = _set_rounding(r);
|
||||
|
||||
softfloat_roundingMode_write_helper(mod_r);
|
||||
let x = _nan_unify(f128_sub(dat_a, dat_b));
|
||||
|
||||
let x1_msb = (x.v[1] | 0) != 0;
|
||||
let x2_msb = ((x.v[0] >> 63) & 1) != 0;
|
||||
let x2_2sb = ((x.v[0] >> 62) & 1) != 0;
|
||||
|
||||
if x1_msb || x2_msb || x2_2sb {
|
||||
let hi = (x.v[1] as u128) << 64;
|
||||
let lo = x.v[0] as u128;
|
||||
Ok(A(stack, &UBig::from(hi | lo)))
|
||||
} else {
|
||||
Ok(D(x.v[0]))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_rq_mul(
|
||||
stack: &mut NockStack,
|
||||
_newt: &mut Option<&mut Newt>,
|
||||
subject: Noun
|
||||
) -> jets::Result {
|
||||
unsafe {
|
||||
let sam = slot(subject, 6)?;
|
||||
let a = slot(sam, 2)?.as_atom()?;
|
||||
let b = slot(sam, 3)?.as_atom()?;
|
||||
let r = slot(subject, 30)?.as_atom()?.as_direct()?.data() as u8 as char;
|
||||
|
||||
// @rq MAY be indirect but they are 128 bits
|
||||
let dat_a = softfloat_sys::float128_t { v: a.as_u128_pair()? };
|
||||
let dat_b = softfloat_sys::float128_t { v: b.as_u128_pair()? };
|
||||
let mod_r = _set_rounding(r);
|
||||
|
||||
softfloat_roundingMode_write_helper(mod_r);
|
||||
let x = _nan_unify(f128_mul(dat_a, dat_b));
|
||||
|
||||
let x1_msb = (x.v[1] | 0) != 0;
|
||||
let x2_msb = ((x.v[0] >> 63) & 1) != 0;
|
||||
let x2_2sb = ((x.v[0] >> 62) & 1) != 0;
|
||||
|
||||
if x1_msb || x2_msb || x2_2sb {
|
||||
let hi = (x.v[1] as u128) << 64;
|
||||
let lo = x.v[0] as u128;
|
||||
Ok(A(stack, &UBig::from(hi | lo)))
|
||||
} else {
|
||||
Ok(D(x.v[0]))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_rq_div(
|
||||
stack: &mut NockStack,
|
||||
_newt: &mut Option<&mut Newt>,
|
||||
subject: Noun
|
||||
) -> jets::Result {
|
||||
unsafe {
|
||||
let sam = slot(subject, 6)?;
|
||||
let a = slot(sam, 2)?.as_atom()?;
|
||||
let b = slot(sam, 3)?.as_atom()?;
|
||||
let r = slot(subject, 30)?.as_atom()?.as_direct()?.data() as u8 as char;
|
||||
|
||||
// @rq MAY be indirect but they are 128 bits
|
||||
let dat_a = softfloat_sys::float128_t { v: a.as_u128_pair()? };
|
||||
let dat_b = softfloat_sys::float128_t { v: b.as_u128_pair()? };
|
||||
let mod_r = _set_rounding(r);
|
||||
|
||||
softfloat_roundingMode_write_helper(mod_r);
|
||||
let x = _nan_unify(f128_div(dat_a, dat_b));
|
||||
|
||||
let x1_msb = (x.v[1] | 0) != 0;
|
||||
let x2_msb = ((x.v[0] >> 63) & 1) != 0;
|
||||
let x2_2sb = ((x.v[0] >> 62) & 1) != 0;
|
||||
|
||||
if x1_msb || x2_msb || x2_2sb {
|
||||
let hi = (x.v[1] as u128) << 64;
|
||||
let lo = x.v[0] as u128;
|
||||
Ok(A(stack, &UBig::from(hi | lo)))
|
||||
} else {
|
||||
Ok(D(x.v[0]))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_rq_sqt(
|
||||
stack: &mut NockStack,
|
||||
_newt: &mut Option<&mut Newt>,
|
||||
subject: Noun
|
||||
) -> jets::Result {
|
||||
unsafe{
|
||||
let sam = slot(subject, 6)?;
|
||||
let a = sam.as_atom()?;
|
||||
let r = slot(subject, 30)?.as_atom()?.as_direct()?.data() as u8 as char;
|
||||
|
||||
let dat_a = softfloat_sys::float128_t { v: a.as_u128_pair()? };
|
||||
let mod_r = _set_rounding(r);
|
||||
|
||||
softfloat_roundingMode_write_helper(mod_r);
|
||||
let x = _nan_unify(f128_sqrt(dat_a));
|
||||
|
||||
let x1_msb = (x.v[1] | 0) != 0;
|
||||
let x2_msb = ((x.v[0] >> 63) & 1) != 0;
|
||||
let x2_2sb = ((x.v[0] >> 62) & 1) != 0;
|
||||
|
||||
if x1_msb || x2_msb || x2_2sb {
|
||||
let hi = (x.v[1] as u128) << 64;
|
||||
let lo = x.v[0] as u128;
|
||||
Ok(A(stack, &UBig::from(hi | lo)))
|
||||
} else {
|
||||
Ok(D(x.v[0]))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_rq_fma(
|
||||
stack: &mut NockStack,
|
||||
_newt: &mut Option<&mut Newt>,
|
||||
subject: Noun
|
||||
) -> jets::Result {
|
||||
unsafe{
|
||||
let sam = slot(subject, 6)?;
|
||||
let a = slot(sam, 2)?.as_atom()?;
|
||||
let b = slot(sam, 6)?.as_atom()?;
|
||||
let c = slot(sam, 7)?.as_atom()?;
|
||||
let r = slot(subject, 30)?.as_atom()?.as_direct()?.data() as u8 as char;
|
||||
|
||||
let dat_a = softfloat_sys::float128_t { v: a.as_u128_pair()? };
|
||||
let dat_b = softfloat_sys::float128_t { v: b.as_u128_pair()? };
|
||||
let dat_c = softfloat_sys::float128_t { v: c.as_u128_pair()? };
|
||||
let mod_r = _set_rounding(r);
|
||||
|
||||
softfloat_roundingMode_write_helper(mod_r);
|
||||
let x = _nan_unify(f128_mulAdd(dat_a, dat_b, dat_c));
|
||||
|
||||
let x1_msb = (x.v[1] | 0) != 0;
|
||||
let x2_msb = ((x.v[0] >> 63) & 1) != 0;
|
||||
let x2_2sb = ((x.v[0] >> 62) & 1) != 0;
|
||||
|
||||
if x1_msb || x2_msb || x2_2sb {
|
||||
let hi = (x.v[1] as u128) << 64;
|
||||
let lo = x.v[0] as u128;
|
||||
Ok(A(stack, &UBig::from(hi | lo)))
|
||||
} else {
|
||||
Ok(D(x.v[0]))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_rq_lth(
|
||||
stack: &mut NockStack,
|
||||
_newt: &mut Option<&mut Newt>,
|
||||
subject: Noun
|
||||
) -> jets::Result {
|
||||
unsafe{
|
||||
let sam = slot(subject, 6)?;
|
||||
let a = slot(sam, 2)?.as_atom()?;
|
||||
let b = slot(sam, 3)?.as_atom()?;
|
||||
let r = slot(subject, 30)?.as_atom()?.as_direct()?.data() as u8 as char;
|
||||
|
||||
let dat_a = softfloat_sys::float128_t { v: a.as_u128_pair()? };
|
||||
let dat_b = softfloat_sys::float128_t { v: b.as_u128_pair()? };
|
||||
let mod_r = _set_rounding(r);
|
||||
|
||||
softfloat_roundingMode_write_helper(mod_r);
|
||||
let t = f128_lt(dat_a, dat_b);
|
||||
|
||||
if t { Ok(YES) } else { Ok(NO) }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_rq_lte(
|
||||
stack: &mut NockStack,
|
||||
_newt: &mut Option<&mut Newt>,
|
||||
subject: Noun
|
||||
) -> jets::Result {
|
||||
unsafe{
|
||||
let sam = slot(subject, 6)?;
|
||||
let a = slot(sam, 2)?.as_atom()?;
|
||||
let b = slot(sam, 3)?.as_atom()?;
|
||||
let r = slot(subject, 30)?.as_atom()?.as_direct()?.data() as u8 as char;
|
||||
|
||||
let dat_a = softfloat_sys::float128_t { v: a.as_u128_pair()? };
|
||||
let dat_b = softfloat_sys::float128_t { v: b.as_u128_pair()? };
|
||||
let mod_r = _set_rounding(r);
|
||||
|
||||
softfloat_roundingMode_write_helper(mod_r);
|
||||
let t = f128_le(dat_a, dat_b);
|
||||
|
||||
if t { Ok(YES) } else { Ok(NO) }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_rq_equ(
|
||||
stack: &mut NockStack,
|
||||
_newt: &mut Option<&mut Newt>,
|
||||
subject: Noun
|
||||
) -> jets::Result {
|
||||
unsafe{
|
||||
let sam = slot(subject, 6)?;
|
||||
let a = slot(sam, 2)?.as_atom()?;
|
||||
let b = slot(sam, 3)?.as_atom()?;
|
||||
let r = slot(subject, 30)?.as_atom()?.as_direct()?.data() as u8 as char;
|
||||
|
||||
let dat_a = softfloat_sys::float128_t { v: a.as_u128_pair()? };
|
||||
let dat_b = softfloat_sys::float128_t { v: b.as_u128_pair()? };
|
||||
let mod_r = _set_rounding(r);
|
||||
|
||||
softfloat_roundingMode_write_helper(mod_r);
|
||||
let t = f128_eq(dat_a, dat_b);
|
||||
|
||||
if t { Ok(YES) } else { Ok(NO) }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_rq_gte(
|
||||
stack: &mut NockStack,
|
||||
_newt: &mut Option<&mut Newt>,
|
||||
subject: Noun
|
||||
) -> jets::Result {
|
||||
unsafe{
|
||||
let sam = slot(subject, 6)?;
|
||||
let a = slot(sam, 2)?.as_atom()?;
|
||||
let b = slot(sam, 3)?.as_atom()?;
|
||||
let r = slot(subject, 30)?.as_atom()?.as_direct()?.data() as u8 as char;
|
||||
|
||||
let dat_a = softfloat_sys::float128_t { v: a.as_u128_pair()? };
|
||||
let dat_b = softfloat_sys::float128_t { v: b.as_u128_pair()? };
|
||||
let mod_r = _set_rounding(r);
|
||||
|
||||
softfloat_roundingMode_write_helper(mod_r);
|
||||
let t = f128_le(dat_b, dat_a);
|
||||
|
||||
if t { Ok(YES) } else { Ok(NO) }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_rq_gth(
|
||||
stack: &mut NockStack,
|
||||
_newt: &mut Option<&mut Newt>,
|
||||
subject: Noun
|
||||
) -> jets::Result {
|
||||
unsafe{
|
||||
let sam = slot(subject, 6)?;
|
||||
let a = slot(sam, 2)?.as_atom()?;
|
||||
let b = slot(sam, 3)?.as_atom()?;
|
||||
let r = slot(subject, 30)?.as_atom()?.as_direct()?.data() as u8 as char;
|
||||
|
||||
let dat_a = softfloat_sys::float128_t { v: a.as_u128_pair()? };
|
||||
let dat_b = softfloat_sys::float128_t { v: b.as_u128_pair()? };
|
||||
let mod_r = _set_rounding(r);
|
||||
|
||||
softfloat_roundingMode_write_helper(mod_r);
|
||||
let t = f128_lt(dat_b, dat_a);
|
||||
|
||||
if t { Ok(YES) } else { Ok(NO) }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::jets::{Jet, JetErr};
|
||||
use crate::jets::util::test::{assert_jet, assert_jet_err, init_stack};
|
||||
use crate::noun::D;
|
||||
use crate::jets::util::test::{assert_noun_eq};
|
||||
use assert_no_alloc::assert_no_alloc;
|
||||
use libc::SS;
|
||||
|
||||
pub fn assert_jet_in_door(
|
||||
stack: &mut NockStack,
|
||||
jet: Jet,
|
||||
sam: &[fn(&mut NockStack) -> Noun], // regular sample
|
||||
ctx: &[fn(&mut NockStack) -> Noun], // door sample as context
|
||||
res: Noun) {
|
||||
unsafe {
|
||||
let mut sam: Vec<Noun> = sam.iter().map(|f| f(stack)).collect();
|
||||
let mut ctx: Vec<Noun> = ctx.iter().map(|f| f(stack)).collect();
|
||||
let sam = if(sam.len() > 1) { T(stack, &sam) } else { sam[0] };
|
||||
eprintln!("sam: {:?}", sam);
|
||||
let ctx = if(ctx.len() > 1) { T(stack, &ctx) } else { ctx[0] };
|
||||
eprintln!("ctx: {:?}", ctx);
|
||||
let pay = Cell::new(stack, sam, ctx).as_noun();
|
||||
eprintln!("pay: {:?}", pay);
|
||||
let sbj = Cell::new(stack, D(0), pay).as_noun();
|
||||
eprintln!("sbj: {:?}", sbj);
|
||||
std::io::stderr().flush().unwrap();
|
||||
let jet_res = jet(stack, &mut None, sbj).unwrap();
|
||||
//eprintln!("jet: {:x}\n", jet_res.as_atom().expect("").as_direct().expect("").data());
|
||||
std::io::stderr().flush().unwrap();
|
||||
assert_noun_eq(stack, jet_res, res);
|
||||
}
|
||||
}
|
||||
|
||||
fn atom_0(stack: &mut NockStack) -> Noun {
|
||||
A(stack, &ubig!(0x00000000000000000000000000000000))
|
||||
}
|
||||
|
||||
fn atom_1(stack: &mut NockStack) -> Noun {
|
||||
A(stack, &ubig!(0x3fff0000000000000000000000000000))
|
||||
}
|
||||
|
||||
fn atom_2(stack: &mut NockStack) -> Noun {
|
||||
A(stack, &ubig!(0x40000000000000000000000000000000))
|
||||
}
|
||||
|
||||
fn atom_3(stack: &mut NockStack) -> Noun {
|
||||
A(stack, &ubig!(0x40008000000000000000000000000000))
|
||||
}
|
||||
|
||||
fn atom_1_5(stack: &mut NockStack) -> Noun {
|
||||
A(stack, &ubig!(0x3fff8000000000000000000000000000))
|
||||
}
|
||||
|
||||
fn atom_1_1(stack: &mut NockStack) -> Noun {
|
||||
A(stack, &ubig!(0x3fff199999999999999999999999999a))
|
||||
}
|
||||
|
||||
fn atom_0_8(stack: &mut NockStack) -> Noun {
|
||||
A(stack, &ubig!(0x3ffe999999999999999999999999999a))
|
||||
}
|
||||
|
||||
fn atom_0_3(stack: &mut NockStack) -> Noun {
|
||||
A(stack, &ubig!(0x3ffd3333333333333333333333333333))
|
||||
}
|
||||
|
||||
fn r_sample_n(_stack: &mut NockStack) -> Noun {
|
||||
D('n' as u8 as u64)
|
||||
}
|
||||
|
||||
fn r_sample_z(_stack: &mut NockStack) -> Noun {
|
||||
D('z' as u8 as u64)
|
||||
}
|
||||
|
||||
fn r_sample_u(_stack: &mut NockStack) -> Noun {
|
||||
D('u' as u8 as u64)
|
||||
}
|
||||
|
||||
fn r_sample_d(_stack: &mut NockStack) -> Noun {
|
||||
D('d' as u8 as u64)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rq_add() {
|
||||
let s = &mut init_stack();
|
||||
let q = &mut init_stack();
|
||||
|
||||
assert_jet_in_door(s, jet_rq_add, &[atom_0, atom_0], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x00000000000000000000000000000000)));
|
||||
assert_jet_in_door(s, jet_rq_add, &[atom_0, atom_1], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x3fff0000000000000000000000000000)));
|
||||
assert_jet_in_door(s, jet_rq_add, &[atom_1, atom_1], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x40000000000000000000000000000000)));
|
||||
assert_jet_in_door(s, jet_rq_add, &[atom_1, atom_2], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x40008000000000000000000000000000)));
|
||||
assert_jet_in_door(s, jet_rq_add, &[atom_2, atom_1], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x40008000000000000000000000000000)));
|
||||
assert_jet_in_door(s, jet_rq_add, &[atom_0_8, atom_0_3], &[atom_0, r_sample_z, atom_0], A(q, &ubig!(0x3fff1999999999999999999999999999)));
|
||||
assert_jet_in_door(s, jet_rq_add, &[atom_0_8, atom_0_3], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x3fff199999999999999999999999999a)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rq_sub() {
|
||||
let s = &mut init_stack();
|
||||
let q = &mut init_stack();
|
||||
|
||||
assert_jet_in_door(s, jet_rq_sub, &[atom_0, atom_0], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x00000000000000000000000000000000)));
|
||||
assert_jet_in_door(s, jet_rq_sub, &[atom_0, atom_1], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0xbfff0000000000000000000000000000)));
|
||||
assert_jet_in_door(s, jet_rq_sub, &[atom_1, atom_1], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x00000000000000000000000000000000)));
|
||||
assert_jet_in_door(s, jet_rq_sub, &[atom_1, atom_2], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0xbfff0000000000000000000000000000)));
|
||||
assert_jet_in_door(s, jet_rq_sub, &[atom_2, atom_1], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x3fff0000000000000000000000000000)));
|
||||
assert_jet_in_door(s, jet_rq_sub, &[atom_1_1, atom_0_8], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x3ffd3333333333333333333333333334)));
|
||||
assert_jet_in_door(s, jet_rq_sub, &[atom_1_1, atom_0_3], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x3ffe999999999999999999999999999a)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rq_mul() {
|
||||
let s = &mut init_stack();
|
||||
let q = &mut init_stack();
|
||||
|
||||
assert_jet_in_door(s, jet_rq_mul, &[atom_0, atom_0], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x00000000000000000000000000000000)));
|
||||
assert_jet_in_door(s, jet_rq_mul, &[atom_0, atom_1], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x00000000000000000000000000000000)));
|
||||
assert_jet_in_door(s, jet_rq_mul, &[atom_1, atom_1], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x3fff0000000000000000000000000000)));
|
||||
assert_jet_in_door(s, jet_rq_mul, &[atom_1, atom_2], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x40000000000000000000000000000000)));
|
||||
assert_jet_in_door(s, jet_rq_mul, &[atom_2, atom_2], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x40010000000000000000000000000000)));
|
||||
assert_jet_in_door(s, jet_rq_mul, &[atom_1_5, atom_2], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x40008000000000000000000000000000)));
|
||||
assert_jet_in_door(s, jet_rq_mul, &[atom_1_1, atom_0_8], &[atom_0, r_sample_z, atom_0], A(q, &ubig!(0x3ffec28f5c28f5c28f5c28f5c28f5c2a)));
|
||||
assert_jet_in_door(s, jet_rq_mul, &[atom_1_1, atom_0_8], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x3ffec28f5c28f5c28f5c28f5c28f5c2a)));
|
||||
assert_jet_in_door(s, jet_rq_mul, &[atom_1_1, atom_0_3], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x3ffd51eb851eb851eb851eb851eb851f)));
|
||||
assert_jet_in_door(s, jet_rq_mul, &[atom_1_1, atom_0_3], &[atom_0, r_sample_z, atom_0], A(q, &ubig!(0x3ffd51eb851eb851eb851eb851eb851e)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rq_div() {
|
||||
let s = &mut init_stack();
|
||||
let q = &mut init_stack();
|
||||
|
||||
assert_jet_in_door(s, jet_rq_div, &[atom_1, atom_0], &[atom_0, r_sample_n, atom_0], A(q, &UBig::from((QUADINF[1] as u128) << 64)));
|
||||
// XX test 0/0
|
||||
assert_jet_in_door(s, jet_rq_div, &[atom_0, atom_1], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x00000000000000000000000000000000)));
|
||||
assert_jet_in_door(s, jet_rq_div, &[atom_1, atom_1], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x3fff0000000000000000000000000000)));
|
||||
assert_jet_in_door(s, jet_rq_div, &[atom_1, atom_2], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x3ffe0000000000000000000000000000)));
|
||||
assert_jet_in_door(s, jet_rq_div, &[atom_2, atom_2], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x3fff0000000000000000000000000000)));
|
||||
assert_jet_in_door(s, jet_rq_div, &[atom_1_1, atom_0_8], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x3fff6000000000000000000000000000)));
|
||||
assert_jet_in_door(s, jet_rq_div, &[atom_1_1, atom_0_3], &[atom_0, r_sample_z, atom_0], A(q, &ubig!(0x4000d555555555555555555555555556)));
|
||||
assert_jet_in_door(s, jet_rq_div, &[atom_1_1, atom_0_3], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x4000d555555555555555555555555556)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rq_sqt() {
|
||||
let s = &mut init_stack();
|
||||
let q = &mut init_stack();
|
||||
|
||||
assert_jet_in_door(s, jet_rq_sqt, &[atom_0], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x00000000000000000000000000000000)));
|
||||
assert_jet_in_door(s, jet_rq_sqt, &[atom_1], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x3fff0000000000000000000000000000)));
|
||||
assert_jet_in_door(s, jet_rq_sqt, &[atom_2], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x3fff6a09e667f3bcc908b2fb1366ea95)));
|
||||
assert_jet_in_door(s, jet_rq_sqt, &[atom_2], &[atom_0, r_sample_z, atom_0], A(q, &ubig!(0x3fff6a09e667f3bcc908b2fb1366ea95)));
|
||||
assert_jet_in_door(s, jet_rq_sqt, &[atom_3], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x3fffbb67ae8584caa73b25742d7078b8)));
|
||||
assert_jet_in_door(s, jet_rq_sqt, &[atom_1_1], &[atom_0, r_sample_z, atom_0], A(q, &ubig!(0x3fff0c7ebc96a56f59f61213380ea638)));
|
||||
assert_jet_in_door(s, jet_rq_sqt, &[atom_1_1], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x3fff0c7ebc96a56f59f61213380ea638)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rq_fma() {
|
||||
let s = &mut init_stack();
|
||||
let q = &mut init_stack();
|
||||
|
||||
assert_jet_in_door(s, jet_rq_fma, &[atom_1, atom_0, atom_0], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x00000000000000000000000000000000)));
|
||||
assert_jet_in_door(s, jet_rq_fma, &[atom_0, atom_1, atom_1], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x3fff0000000000000000000000000000)));
|
||||
assert_jet_in_door(s, jet_rq_fma, &[atom_1, atom_1, atom_1], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x40000000000000000000000000000000)));
|
||||
assert_jet_in_door(s, jet_rq_fma, &[atom_1, atom_2, atom_1], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x40008000000000000000000000000000)));
|
||||
assert_jet_in_door(s, jet_rq_fma, &[atom_2, atom_2, atom_1], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x40014000000000000000000000000000)));
|
||||
assert_jet_in_door(s, jet_rq_fma, &[atom_1_1, atom_0_8, atom_0_3], &[atom_0, r_sample_n, atom_0], A(q, &ubig!(0x3fff2e147ae147ae147ae147ae147ae2)));
|
||||
assert_jet_in_door(s, jet_rq_fma, &[atom_1_1, atom_0_8, atom_0_3], &[atom_0, r_sample_z, atom_0], A(q, &ubig!(0x3fff2e147ae147ae147ae147ae147ae1)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rq_lth() {
|
||||
let s = &mut init_stack();
|
||||
|
||||
assert_jet_in_door(s, jet_rq_lth, &[atom_1, atom_0], &[atom_0, r_sample_n, atom_0], NO);
|
||||
assert_jet_in_door(s, jet_rq_lth, &[atom_0, atom_1], &[atom_0, r_sample_n, atom_0], YES);
|
||||
assert_jet_in_door(s, jet_rq_lth, &[atom_1, atom_1], &[atom_0, r_sample_n, atom_0], NO);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rq_lte() {
|
||||
let s = &mut init_stack();
|
||||
|
||||
assert_jet_in_door(s, jet_rq_lte, &[atom_1, atom_0], &[atom_0, r_sample_n, atom_0], NO);
|
||||
assert_jet_in_door(s, jet_rq_lte, &[atom_0, atom_1], &[atom_0, r_sample_n, atom_0], YES);
|
||||
assert_jet_in_door(s, jet_rq_lte, &[atom_1, atom_1], &[atom_0, r_sample_n, atom_0], YES);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rq_equ() {
|
||||
let s = &mut init_stack();
|
||||
|
||||
assert_jet_in_door(s, jet_rq_equ, &[atom_1, atom_0], &[atom_0, r_sample_n, atom_0], NO);
|
||||
assert_jet_in_door(s, jet_rq_equ, &[atom_0, atom_1], &[atom_0, r_sample_n, atom_0], NO);
|
||||
assert_jet_in_door(s, jet_rq_equ, &[atom_1, atom_1], &[atom_0, r_sample_n, atom_0], YES);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rq_gte() {
|
||||
let s = &mut init_stack();
|
||||
|
||||
assert_jet_in_door(s, jet_rq_gte, &[atom_1, atom_0], &[atom_0, r_sample_n, atom_0], YES);
|
||||
assert_jet_in_door(s, jet_rq_gte, &[atom_0, atom_1], &[atom_0, r_sample_n, atom_0], NO);
|
||||
assert_jet_in_door(s, jet_rq_gte, &[atom_1, atom_1], &[atom_0, r_sample_n, atom_0], YES);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rq_gth() {
|
||||
let s = &mut init_stack();
|
||||
|
||||
assert_jet_in_door(s, jet_rq_gth, &[atom_1, atom_0], &[atom_0, r_sample_n, atom_0], YES);
|
||||
assert_jet_in_door(s, jet_rq_gth, &[atom_0, atom_1], &[atom_0, r_sample_n, atom_0], NO);
|
||||
assert_jet_in_door(s, jet_rq_gth, &[atom_1, atom_1], &[atom_0, r_sample_n, atom_0], NO);
|
||||
}
|
||||
}
|
504
rust/ares/src/jets/float_rs.rs
Normal file
504
rust/ares/src/jets/float_rs.rs
Normal file
@ -0,0 +1,504 @@
|
||||
/** Floating-point jets
|
||||
*/
|
||||
use crate::jets;
|
||||
use crate::jets::JetErr::*;
|
||||
use crate::jets::util::*;
|
||||
use crate::jets::util::test::{assert_jet, assert_jet_err, assert_jet_ubig, assert_nary_jet_ubig, init_stack, A};
|
||||
use crate::mem::NockStack;
|
||||
use crate::newt::Newt;
|
||||
use crate::noun::{Atom, IndirectAtom, Noun, D, T, Cell, NO, YES};
|
||||
use ibig::{UBig, ubig};
|
||||
use softfloat_sys::*;
|
||||
use std::io::Write;
|
||||
|
||||
crate::gdb!();
|
||||
|
||||
const SINGNAN: u32 = 0x7fc00000;
|
||||
const SINGINF: u32 = 0x7f800000;
|
||||
const SINGZERO: u32 = 0x00000000;
|
||||
|
||||
#[inline(always)]
|
||||
fn _nan_test(
|
||||
a: float32_t
|
||||
) -> bool {
|
||||
unsafe {
|
||||
!f32_eq(a, a)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn _nan_unify(
|
||||
a: float32_t
|
||||
) -> float32_t {
|
||||
unsafe {
|
||||
if _nan_test(a) {
|
||||
return softfloat_sys::float32_t { v: SINGNAN };
|
||||
}
|
||||
a
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn _set_rounding(
|
||||
r: char
|
||||
) -> u8 {
|
||||
match r {
|
||||
'n' => softfloat_round_near_even,
|
||||
'z' => softfloat_round_minMag,
|
||||
'u' => softfloat_round_max,
|
||||
'd' => softfloat_round_min,
|
||||
// formal fallthrough, should never happen
|
||||
_ => softfloat_round_near_even,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_rs_add(
|
||||
_stack: &mut NockStack,
|
||||
_newt: &mut Option<&mut Newt>,
|
||||
subject: Noun
|
||||
) -> jets::Result {
|
||||
unsafe{
|
||||
let sam = slot(subject, 6)?;
|
||||
let a = slot(sam, 2)?.as_atom()?.as_direct()?;
|
||||
let b = slot(sam, 3)?.as_atom()?.as_direct()?;
|
||||
let r = slot(subject, 30)?.as_atom()?.as_direct()?.data() as u8 as char;
|
||||
|
||||
let dat_a = softfloat_sys::float32_t { v: a.data() as u32};
|
||||
let dat_b = softfloat_sys::float32_t { v: b.data() as u32};
|
||||
let mod_r = _set_rounding(r);
|
||||
|
||||
softfloat_roundingMode_write_helper(mod_r);
|
||||
let x = _nan_unify(f32_add(dat_a, dat_b));
|
||||
|
||||
Ok(D(x.v as u64))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_rs_sub(
|
||||
_stack: &mut NockStack,
|
||||
_newt: &mut Option<&mut Newt>,
|
||||
subject: Noun
|
||||
) -> jets::Result {
|
||||
unsafe{
|
||||
let sam = slot(subject, 6)?;
|
||||
let a = slot(sam, 2)?.as_atom()?.as_direct()?;
|
||||
let b = slot(sam, 3)?.as_atom()?.as_direct()?;
|
||||
let r = slot(subject, 30)?.as_atom()?.as_direct()?.data() as u8 as char;
|
||||
|
||||
let dat_a = softfloat_sys::float32_t { v: a.data() as u32};
|
||||
let dat_b = softfloat_sys::float32_t { v: b.data() as u32};
|
||||
let mod_r = _set_rounding(r);
|
||||
|
||||
softfloat_roundingMode_write_helper(mod_r);
|
||||
let x = _nan_unify(f32_sub(dat_a, dat_b));
|
||||
|
||||
Ok(D(x.v as u64))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_rs_mul(
|
||||
_stack: &mut NockStack,
|
||||
_newt: &mut Option<&mut Newt>,
|
||||
subject: Noun
|
||||
) -> jets::Result {
|
||||
unsafe{
|
||||
let sam = slot(subject, 6)?;
|
||||
let a = slot(sam, 2)?.as_atom()?.as_direct()?;
|
||||
let b = slot(sam, 3)?.as_atom()?.as_direct()?;
|
||||
let r = slot(subject, 30)?.as_atom()?.as_direct()?.data() as u8 as char;
|
||||
|
||||
let dat_a = softfloat_sys::float32_t { v: a.data() as u32};
|
||||
let dat_b = softfloat_sys::float32_t { v: b.data() as u32};
|
||||
let mod_r = _set_rounding(r);
|
||||
|
||||
softfloat_roundingMode_write_helper(mod_r);
|
||||
let x = _nan_unify(f32_mul(dat_a, dat_b));
|
||||
|
||||
Ok(D(x.v as u64))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_rs_div(
|
||||
_stack: &mut NockStack,
|
||||
_newt: &mut Option<&mut Newt>,
|
||||
subject: Noun
|
||||
) -> jets::Result {
|
||||
unsafe{
|
||||
let sam = slot(subject, 6)?;
|
||||
let a = slot(sam, 2)?.as_atom()?.as_direct()?;
|
||||
let b = slot(sam, 3)?.as_atom()?.as_direct()?;
|
||||
let r = slot(subject, 30)?.as_atom()?.as_direct()?.data() as u8 as char;
|
||||
|
||||
let dat_a = softfloat_sys::float32_t { v: a.data() as u32};
|
||||
let dat_b = softfloat_sys::float32_t { v: b.data() as u32};
|
||||
let mod_r = _set_rounding(r);
|
||||
|
||||
softfloat_roundingMode_write_helper(mod_r);
|
||||
let x = _nan_unify(f32_div(dat_a, dat_b));
|
||||
|
||||
Ok(D(x.v as u64))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_rs_sqt(
|
||||
_stack: &mut NockStack,
|
||||
_newt: &mut Option<&mut Newt>,
|
||||
subject: Noun
|
||||
) -> jets::Result {
|
||||
unsafe{
|
||||
let sam = slot(subject, 6)?;
|
||||
eprintln!("»sam: {:?}", sam);
|
||||
let a = sam.as_atom()?.as_direct()?;
|
||||
eprintln!("»a: {:?}", a.as_noun());
|
||||
let r = slot(subject, 30)?.as_atom()?.as_direct()?.data() as u8 as char;
|
||||
|
||||
let dat_a = softfloat_sys::float32_t { v: a.data() as u32};
|
||||
let mod_r = _set_rounding(r);
|
||||
|
||||
softfloat_roundingMode_write_helper(mod_r);
|
||||
let x = _nan_unify(f32_sqrt(dat_a));
|
||||
|
||||
Ok(D(x.v as u64))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_rs_fma(
|
||||
_stack: &mut NockStack,
|
||||
_newt: &mut Option<&mut Newt>,
|
||||
subject: Noun
|
||||
) -> jets::Result {
|
||||
unsafe{
|
||||
let sam = slot(subject, 6)?;
|
||||
let a = slot(sam, 2)?.as_atom()?.as_direct()?;
|
||||
let b = slot(sam, 6)?.as_atom()?.as_direct()?;
|
||||
let c = slot(sam, 7)?.as_atom()?.as_direct()?;
|
||||
let r = slot(subject, 30)?.as_atom()?.as_direct()?.data() as u8 as char;
|
||||
|
||||
let dat_a = softfloat_sys::float32_t { v: a.data() as u32};
|
||||
let dat_b = softfloat_sys::float32_t { v: b.data() as u32};
|
||||
let dat_c = softfloat_sys::float32_t { v: c.data() as u32};
|
||||
let mod_r = _set_rounding(r);
|
||||
|
||||
softfloat_roundingMode_write_helper(mod_r);
|
||||
let x = _nan_unify(f32_mulAdd(dat_a, dat_b, dat_c));
|
||||
|
||||
Ok(D(x.v as u64))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_rs_lth(
|
||||
_stack: &mut NockStack,
|
||||
_newt: &mut Option<&mut Newt>,
|
||||
subject: Noun
|
||||
) -> jets::Result {
|
||||
unsafe{
|
||||
let sam = slot(subject, 6)?;
|
||||
let a = slot(sam, 2)?.as_atom()?.as_direct()?;
|
||||
let b = slot(sam, 3)?.as_atom()?.as_direct()?;
|
||||
let r = slot(subject, 30)?.as_atom()?.as_direct()?.data() as u8 as char;
|
||||
|
||||
let dat_a = softfloat_sys::float32_t { v: a.data() as u32};
|
||||
let dat_b = softfloat_sys::float32_t { v: b.data() as u32};
|
||||
let mod_r = _set_rounding(r);
|
||||
|
||||
softfloat_roundingMode_write_helper(mod_r);
|
||||
let t = f32_lt(dat_a, dat_b);
|
||||
|
||||
if t { Ok(YES) } else { Ok(NO) }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_rs_lte(
|
||||
_stack: &mut NockStack,
|
||||
_newt: &mut Option<&mut Newt>,
|
||||
subject: Noun
|
||||
) -> jets::Result {
|
||||
unsafe{
|
||||
let sam = slot(subject, 6)?;
|
||||
let a = slot(sam, 2)?.as_atom()?.as_direct()?;
|
||||
let b = slot(sam, 3)?.as_atom()?.as_direct()?;
|
||||
let r = slot(subject, 30)?.as_atom()?.as_direct()?.data() as u8 as char;
|
||||
|
||||
let dat_a = softfloat_sys::float32_t { v: a.data() as u32};
|
||||
let dat_b = softfloat_sys::float32_t { v: b.data() as u32};
|
||||
let mod_r = _set_rounding(r);
|
||||
|
||||
softfloat_roundingMode_write_helper(mod_r);
|
||||
let t = f32_le(dat_a, dat_b);
|
||||
|
||||
if t { Ok(YES) } else { Ok(NO) }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_rs_equ(
|
||||
_stack: &mut NockStack,
|
||||
_newt: &mut Option<&mut Newt>,
|
||||
subject: Noun
|
||||
) -> jets::Result {
|
||||
unsafe{
|
||||
let sam = slot(subject, 6)?;
|
||||
let a = slot(sam, 2)?.as_atom()?.as_direct()?;
|
||||
let b = slot(sam, 3)?.as_atom()?.as_direct()?;
|
||||
let r = slot(subject, 30)?.as_atom()?.as_direct()?.data() as u8 as char;
|
||||
|
||||
let dat_a = softfloat_sys::float32_t { v: a.data() as u32};
|
||||
let dat_b = softfloat_sys::float32_t { v: b.data() as u32};
|
||||
let mod_r = _set_rounding(r);
|
||||
|
||||
softfloat_roundingMode_write_helper(mod_r);
|
||||
let t = f32_eq(dat_a, dat_b);
|
||||
|
||||
if t { Ok(YES) } else { Ok(NO) }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_rs_gte(
|
||||
_stack: &mut NockStack,
|
||||
_newt: &mut Option<&mut Newt>,
|
||||
subject: Noun
|
||||
) -> jets::Result {
|
||||
unsafe{
|
||||
let sam = slot(subject, 6)?;
|
||||
let a = slot(sam, 2)?.as_atom()?.as_direct()?;
|
||||
let b = slot(sam, 3)?.as_atom()?.as_direct()?;
|
||||
let r = slot(subject, 30)?.as_atom()?.as_direct()?.data() as u8 as char;
|
||||
|
||||
let dat_a = softfloat_sys::float32_t { v: a.data() as u32};
|
||||
let dat_b = softfloat_sys::float32_t { v: b.data() as u32};
|
||||
let mod_r = _set_rounding(r);
|
||||
|
||||
softfloat_roundingMode_write_helper(mod_r);
|
||||
let t = f32_le(dat_b, dat_a);
|
||||
|
||||
if t { Ok(YES) } else { Ok(NO) }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_rs_gth(
|
||||
_stack: &mut NockStack,
|
||||
_newt: &mut Option<&mut Newt>,
|
||||
subject: Noun
|
||||
) -> jets::Result {
|
||||
unsafe{
|
||||
let sam = slot(subject, 6)?;
|
||||
let a = slot(sam, 2)?.as_atom()?.as_direct()?;
|
||||
let b = slot(sam, 3)?.as_atom()?.as_direct()?;
|
||||
let r = slot(subject, 30)?.as_atom()?.as_direct()?.data() as u8 as char;
|
||||
|
||||
let dat_a = softfloat_sys::float32_t { v: a.data() as u32};
|
||||
let dat_b = softfloat_sys::float32_t { v: b.data() as u32};
|
||||
let mod_r = _set_rounding(r);
|
||||
|
||||
softfloat_roundingMode_write_helper(mod_r);
|
||||
let t = f32_lt(dat_b, dat_a);
|
||||
|
||||
if t { Ok(YES) } else { Ok(NO) }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::jets::{Jet, JetErr};
|
||||
use crate::jets::util::test::{assert_jet, assert_jet_err, init_stack};
|
||||
use crate::noun::D;
|
||||
use crate::jets::util::test::{assert_noun_eq};
|
||||
use assert_no_alloc::assert_no_alloc;
|
||||
|
||||
pub fn assert_jet_in_door(
|
||||
stack: &mut NockStack,
|
||||
jet: Jet,
|
||||
sam: &[fn(&mut NockStack) -> Noun], // regular sample
|
||||
ctx: &[fn(&mut NockStack) -> Noun], // door sample as context
|
||||
res: Noun) {
|
||||
unsafe {
|
||||
let mut sam: Vec<Noun> = sam.iter().map(|f| f(stack)).collect();
|
||||
let mut ctx: Vec<Noun> = ctx.iter().map(|f| f(stack)).collect();
|
||||
let sam = if(sam.len() > 1) { T(stack, &sam) } else { sam[0] };
|
||||
eprintln!("sam: {:?}", sam);
|
||||
let ctx = if(ctx.len() > 1) { T(stack, &ctx) } else { ctx[0] };
|
||||
eprintln!("ctx: {:?}", ctx);
|
||||
let pay = Cell::new(stack, sam, ctx).as_noun();
|
||||
eprintln!("pay: {:?}", pay);
|
||||
let sbj = Cell::new(stack, D(0), pay).as_noun();
|
||||
eprintln!("sbj: {:?}", sbj);
|
||||
std::io::stderr().flush().unwrap();
|
||||
let jet_res = jet(stack, &mut None, sbj).unwrap();
|
||||
eprintln!("jet: {:x}\n", jet_res.as_atom().expect("").as_direct().expect("").data());
|
||||
std::io::stderr().flush().unwrap();
|
||||
assert_noun_eq(stack, jet_res, res);
|
||||
}
|
||||
}
|
||||
|
||||
fn atom_0(_stack: &mut NockStack) -> Noun {
|
||||
D(0x00000000)
|
||||
}
|
||||
|
||||
fn atom_1(_stack: &mut NockStack) -> Noun {
|
||||
D(0x3f800000)
|
||||
}
|
||||
|
||||
fn atom_2(_stack: &mut NockStack) -> Noun {
|
||||
D(0x40000000)
|
||||
}
|
||||
|
||||
fn atom_3(_stack: &mut NockStack) -> Noun {
|
||||
D(0x40400000)
|
||||
}
|
||||
|
||||
fn atom_1_5(_stack: &mut NockStack) -> Noun {
|
||||
D(0x3fc00000)
|
||||
}
|
||||
|
||||
fn atom_1_1(_stack: &mut NockStack) -> Noun {
|
||||
D(0x3f8ccccd)
|
||||
}
|
||||
|
||||
fn atom_0_8(_stack: &mut NockStack) -> Noun {
|
||||
D(0x3f4ccccd)
|
||||
}
|
||||
|
||||
fn atom_0_3(_stack: &mut NockStack) -> Noun {
|
||||
D(0x3e99999a)
|
||||
}
|
||||
|
||||
fn r_sample_n(_stack: &mut NockStack) -> Noun {
|
||||
D('n' as u8 as u64)
|
||||
}
|
||||
|
||||
fn r_sample_z(_stack: &mut NockStack) -> Noun {
|
||||
D('z' as u8 as u64)
|
||||
}
|
||||
|
||||
fn r_sample_u(_stack: &mut NockStack) -> Noun {
|
||||
D('u' as u8 as u64)
|
||||
}
|
||||
|
||||
fn r_sample_d(_stack: &mut NockStack) -> Noun {
|
||||
D('d' as u8 as u64)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rs_add() {
|
||||
let s = &mut init_stack();
|
||||
|
||||
assert_jet_in_door(s, jet_rs_add, &[atom_0, atom_0], &[atom_0, r_sample_n, atom_0], D(0x00000000));
|
||||
assert_jet_in_door(s, jet_rs_add, &[atom_0, atom_1], &[atom_0, r_sample_n, atom_0], D(0x3f800000));
|
||||
assert_jet_in_door(s, jet_rs_add, &[atom_1, atom_1], &[atom_0, r_sample_n, atom_0], D(0x40000000));
|
||||
assert_jet_in_door(s, jet_rs_add, &[atom_1, atom_2], &[atom_0, r_sample_n, atom_0], D(0x40400000));
|
||||
assert_jet_in_door(s, jet_rs_add, &[atom_2, atom_1], &[atom_0, r_sample_n, atom_0], D(0x40400000));
|
||||
assert_jet_in_door(s, jet_rs_add, &[atom_0_8, atom_0_3], &[atom_0, r_sample_n, atom_0], D(0x3f8ccccd));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rs_sub() {
|
||||
let s = &mut init_stack();
|
||||
|
||||
assert_jet_in_door(s, jet_rs_sub, &[atom_0, atom_0], &[atom_0, r_sample_n, atom_0], D(0x00000000));
|
||||
assert_jet_in_door(s, jet_rs_sub, &[atom_0, atom_1], &[atom_0, r_sample_n, atom_0], D(0xbf800000));
|
||||
assert_jet_in_door(s, jet_rs_sub, &[atom_1, atom_1], &[atom_0, r_sample_n, atom_0], D(0x00000000));
|
||||
assert_jet_in_door(s, jet_rs_sub, &[atom_1, atom_2], &[atom_0, r_sample_n, atom_0], D(0xbf800000));
|
||||
assert_jet_in_door(s, jet_rs_sub, &[atom_2, atom_1], &[atom_0, r_sample_n, atom_0], D(0x3f800000));
|
||||
assert_jet_in_door(s, jet_rs_sub, &[atom_1_1, atom_0_8], &[atom_0, r_sample_n, atom_0], D(0x3e99999a));
|
||||
assert_jet_in_door(s, jet_rs_sub, &[atom_1_1, atom_0_3], &[atom_0, r_sample_n, atom_0], D(0x3f4ccccd));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rs_mul() {
|
||||
let s = &mut init_stack();
|
||||
|
||||
assert_jet_in_door(s, jet_rs_mul, &[atom_0, atom_0], &[atom_0, r_sample_n, atom_0], D(0x00000000));
|
||||
assert_jet_in_door(s, jet_rs_mul, &[atom_0, atom_1], &[atom_0, r_sample_n, atom_0], D(0x00000000));
|
||||
assert_jet_in_door(s, jet_rs_mul, &[atom_1, atom_1], &[atom_0, r_sample_n, atom_0], D(0x3f800000));
|
||||
assert_jet_in_door(s, jet_rs_mul, &[atom_1, atom_2], &[atom_0, r_sample_n, atom_0], D(0x40000000));
|
||||
assert_jet_in_door(s, jet_rs_mul, &[atom_2, atom_2], &[atom_0, r_sample_n, atom_0], D(0x40800000));
|
||||
assert_jet_in_door(s, jet_rs_mul, &[atom_1_5, atom_2], &[atom_0, r_sample_n, atom_0], D(0x40400000));
|
||||
assert_jet_in_door(s, jet_rs_mul, &[atom_1_1, atom_0_8], &[atom_0, r_sample_z, atom_0], D(0x3f6147ae));
|
||||
assert_jet_in_door(s, jet_rs_mul, &[atom_1_1, atom_0_8], &[atom_0, r_sample_n, atom_0], D(0x3f6147af));
|
||||
assert_jet_in_door(s, jet_rs_mul, &[atom_1_1, atom_0_3], &[atom_0, r_sample_n, atom_0], D(0x3ea8f5c3));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rs_div() {
|
||||
let s = &mut init_stack();
|
||||
|
||||
assert_jet_in_door(s, jet_rs_div, &[atom_1, atom_0], &[atom_0, r_sample_n, atom_0], D(SINGINF as u64));
|
||||
// XX test 0/0
|
||||
assert_jet_in_door(s, jet_rs_div, &[atom_0, atom_1], &[atom_0, r_sample_n, atom_0], D(0x00000000));
|
||||
assert_jet_in_door(s, jet_rs_div, &[atom_1, atom_1], &[atom_0, r_sample_n, atom_0], D(0x3f800000));
|
||||
assert_jet_in_door(s, jet_rs_div, &[atom_1, atom_2], &[atom_0, r_sample_n, atom_0], D(0x3f000000));
|
||||
assert_jet_in_door(s, jet_rs_div, &[atom_2, atom_2], &[atom_0, r_sample_n, atom_0], D(0x3f800000));
|
||||
assert_jet_in_door(s, jet_rs_div, &[atom_1_1, atom_0_8], &[atom_0, r_sample_n, atom_0], D(0x3fb00000));
|
||||
assert_jet_in_door(s, jet_rs_div, &[atom_1_1, atom_0_3], &[atom_0, r_sample_n, atom_0], D(0x406aaaaa));
|
||||
assert_jet_in_door(s, jet_rs_div, &[atom_1_1, atom_0_3], &[atom_0, r_sample_u, atom_0], D(0x406aaaab));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rs_sqt() {
|
||||
let s = &mut init_stack();
|
||||
|
||||
assert_jet_in_door(s, jet_rs_sqt, &[atom_0], &[atom_0, r_sample_n, atom_0], D(0x00000000));
|
||||
assert_jet_in_door(s, jet_rs_sqt, &[atom_1], &[atom_0, r_sample_n, atom_0], D(0x3f800000));
|
||||
assert_jet_in_door(s, jet_rs_sqt, &[atom_2], &[atom_0, r_sample_n, atom_0], D(0x3fb504f3));
|
||||
assert_jet_in_door(s, jet_rs_sqt, &[atom_3], &[atom_0, r_sample_n, atom_0], D(0x3fddb3d7));
|
||||
assert_jet_in_door(s, jet_rs_sqt, &[atom_1_1], &[atom_0, r_sample_n, atom_0], D(0x3f863f5e));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rs_fma() {
|
||||
let s = &mut init_stack();
|
||||
|
||||
assert_jet_in_door(s, jet_rs_fma, &[atom_1, atom_0, atom_0], &[atom_0, r_sample_n, atom_0], D(0x00000000));
|
||||
assert_jet_in_door(s, jet_rs_fma, &[atom_0, atom_1, atom_1], &[atom_0, r_sample_n, atom_0], D(0x3f800000));
|
||||
assert_jet_in_door(s, jet_rs_fma, &[atom_1, atom_1, atom_1], &[atom_0, r_sample_n, atom_0], D(0x40000000));
|
||||
assert_jet_in_door(s, jet_rs_fma, &[atom_1, atom_2, atom_1], &[atom_0, r_sample_n, atom_0], D(0x40400000));
|
||||
assert_jet_in_door(s, jet_rs_fma, &[atom_2, atom_2, atom_1], &[atom_0, r_sample_n, atom_0], D(0x40a00000));
|
||||
assert_jet_in_door(s, jet_rs_fma, &[atom_1_1, atom_0_8, atom_0_3], &[atom_0, r_sample_n, atom_0], D(0x3f970a3e));
|
||||
assert_jet_in_door(s, jet_rs_fma, &[atom_1_1, atom_0_8, atom_0_3], &[atom_0, r_sample_z, atom_0], D(0x3f970a3d));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rs_lth() {
|
||||
let s = &mut init_stack();
|
||||
|
||||
assert_jet_in_door(s, jet_rs_lth, &[atom_1, atom_0], &[atom_0, r_sample_n, atom_0], NO);
|
||||
assert_jet_in_door(s, jet_rs_lth, &[atom_0, atom_1], &[atom_0, r_sample_n, atom_0], YES);
|
||||
assert_jet_in_door(s, jet_rs_lth, &[atom_1, atom_1], &[atom_0, r_sample_n, atom_0], NO);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rs_lte() {
|
||||
let s = &mut init_stack();
|
||||
|
||||
assert_jet_in_door(s, jet_rs_lte, &[atom_1, atom_0], &[atom_0, r_sample_n, atom_0], NO);
|
||||
assert_jet_in_door(s, jet_rs_lte, &[atom_0, atom_1], &[atom_0, r_sample_n, atom_0], YES);
|
||||
assert_jet_in_door(s, jet_rs_lte, &[atom_1, atom_1], &[atom_0, r_sample_n, atom_0], YES);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rs_equ() {
|
||||
let s = &mut init_stack();
|
||||
|
||||
assert_jet_in_door(s, jet_rs_equ, &[atom_1, atom_0], &[atom_0, r_sample_n, atom_0], NO);
|
||||
assert_jet_in_door(s, jet_rs_equ, &[atom_0, atom_1], &[atom_0, r_sample_n, atom_0], NO);
|
||||
assert_jet_in_door(s, jet_rs_equ, &[atom_1, atom_1], &[atom_0, r_sample_n, atom_0], YES);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rs_gte() {
|
||||
let s = &mut init_stack();
|
||||
|
||||
assert_jet_in_door(s, jet_rs_gte, &[atom_1, atom_0], &[atom_0, r_sample_n, atom_0], YES);
|
||||
assert_jet_in_door(s, jet_rs_gte, &[atom_0, atom_1], &[atom_0, r_sample_n, atom_0], NO);
|
||||
assert_jet_in_door(s, jet_rs_gte, &[atom_1, atom_1], &[atom_0, r_sample_n, atom_0], YES);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rs_gth() {
|
||||
let s = &mut init_stack();
|
||||
|
||||
assert_jet_in_door(s, jet_rs_gth, &[atom_1, atom_0], &[atom_0, r_sample_n, atom_0], YES);
|
||||
assert_jet_in_door(s, jet_rs_gth, &[atom_0, atom_1], &[atom_0, r_sample_n, atom_0], NO);
|
||||
assert_jet_in_door(s, jet_rs_gth, &[atom_1, atom_1], &[atom_0, r_sample_n, atom_0], NO);
|
||||
}
|
||||
}
|
218
rust/ares/src/jets/tree.rs
Normal file
218
rust/ares/src/jets/tree.rs
Normal file
@ -0,0 +1,218 @@
|
||||
/** Tree jets
|
||||
*/
|
||||
use crate::jets;
|
||||
use crate::jets::JetErr::*;
|
||||
use crate::jets::util::*;
|
||||
use crate::jets::util::test::{assert_jet, assert_jet_err, assert_jet_ubig, assert_nary_jet_ubig, init_stack, A};
|
||||
use crate::mem::NockStack;
|
||||
use crate::newt::Newt;
|
||||
use crate::noun::{Atom, IndirectAtom, Noun, D, T};
|
||||
//use crate::noun::{Atom, DirectAtom, IndirectAtom, Noun, D, DIRECT_MAX, NO, T, YES};
|
||||
use ibig::{UBig, ubig};
|
||||
|
||||
crate::gdb!();
|
||||
|
||||
pub fn jet_cap(
|
||||
_stack: &mut NockStack,
|
||||
_newt: &mut Option<&mut Newt>,
|
||||
subject: Noun
|
||||
) -> jets::Result {
|
||||
let arg = slot(subject, 6)?;
|
||||
let tom = arg.as_atom()?;
|
||||
let met = met(0, tom);
|
||||
|
||||
unsafe {
|
||||
if met < 2 {
|
||||
Err(Deterministic)
|
||||
} else if *(tom.as_bitslice().get_unchecked(met - 2)) {
|
||||
Ok(D(3))
|
||||
} else {
|
||||
Ok(D(2))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_mas(
|
||||
stack: &mut NockStack,
|
||||
_newt: &mut Option<&mut Newt>,
|
||||
subject: Noun
|
||||
) -> jets::Result {
|
||||
let arg = slot(subject, 6)?;
|
||||
let tom = arg.as_atom()?;
|
||||
let met = met(0, tom);
|
||||
|
||||
if met < 2 {
|
||||
Err(Deterministic)
|
||||
} else {
|
||||
let c = bex(stack, met - 1);
|
||||
let d = bex(stack, met - 2);
|
||||
let e = sub(stack, tom, c)?;
|
||||
|
||||
Ok(con(stack, e, d).as_noun())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jet_peg(
|
||||
stack: &mut NockStack,
|
||||
_newt: &mut Option<&mut Newt>,
|
||||
subject: Noun
|
||||
) -> jets::Result {
|
||||
unsafe{
|
||||
let arg = slot(subject, 6)?;
|
||||
let a = slot(arg, 2)?.as_atom()?;
|
||||
let b = slot(arg, 3)?.as_atom()?;
|
||||
|
||||
if let Ok(a) = a.as_direct() {
|
||||
if a.data() == 0 {
|
||||
return Err(Deterministic);
|
||||
}
|
||||
};
|
||||
if let Ok(b) = b.as_direct() {
|
||||
if b.data() == 0 {
|
||||
return Err(Deterministic);
|
||||
}
|
||||
};
|
||||
|
||||
let met_a = met(6, a);
|
||||
let met_b = met(6, b);
|
||||
|
||||
let (mut result, destination) = IndirectAtom::new_raw_mut_bitslice(stack, met_a+met_b);
|
||||
|
||||
let len_a = met(0, a);
|
||||
let len_b = met(0, b);
|
||||
|
||||
destination[0..len_b-1].copy_from_bitslice(&b.as_bitslice()[0..len_b-1]);
|
||||
destination[len_b-1..len_b-1+len_a].copy_from_bitslice(&a.as_bitslice()[0..len_a]);
|
||||
|
||||
Ok(result.normalize_as_atom().as_noun())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::jets::JetErr;
|
||||
use crate::jets::util::test::{assert_jet, assert_jet_err, init_stack};
|
||||
use crate::noun::D;
|
||||
|
||||
#[test]
|
||||
fn test_cap() {
|
||||
let s = &mut init_stack();
|
||||
|
||||
assert_jet_err(s, jet_cap, D(0), JetErr::Deterministic);
|
||||
assert_jet_err(s, jet_cap, D(1), JetErr::Deterministic);
|
||||
|
||||
assert_jet(s, jet_cap, D(2), D(2));
|
||||
assert_jet(s, jet_cap, D(3), D(3));
|
||||
assert_jet(s, jet_cap, D(4), D(2));
|
||||
assert_jet(s, jet_cap, D(5), D(2));
|
||||
assert_jet(s, jet_cap, D(6), D(3));
|
||||
assert_jet(s, jet_cap, D(7), D(3));
|
||||
assert_jet(s, jet_cap, D(8), D(2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mas() {
|
||||
let s = &mut init_stack();
|
||||
|
||||
assert_jet_err(s, jet_mas, D(0), JetErr::Deterministic);
|
||||
assert_jet_err(s, jet_mas, D(1), JetErr::Deterministic);
|
||||
|
||||
assert_jet(s, jet_mas, D(2), D(1));
|
||||
assert_jet(s, jet_mas, D(3), D(1));
|
||||
assert_jet(s, jet_mas, D(4), D(2));
|
||||
assert_jet(s, jet_mas, D(5), D(3));
|
||||
assert_jet(s, jet_mas, D(6), D(2));
|
||||
assert_jet(s, jet_mas, D(7), D(3));
|
||||
assert_jet(s, jet_mas, D(8), D(4));
|
||||
}
|
||||
|
||||
fn assert_math_jet(
|
||||
stack: &mut NockStack,
|
||||
jet: jets::Jet,
|
||||
sam: &[fn(&mut NockStack) -> Noun],
|
||||
res: UBig,
|
||||
) {
|
||||
let sam: Vec<Noun> = sam.iter().map(|f| f(stack)).collect();
|
||||
assert_nary_jet_ubig(stack, jet, &sam, res);
|
||||
}
|
||||
|
||||
fn assert_math_jet_err(
|
||||
stack: &mut NockStack,
|
||||
jet: jets::Jet,
|
||||
sam: &[fn(&mut NockStack) -> Noun],
|
||||
err: JetErr,
|
||||
) {
|
||||
let sam: Vec<Noun> = sam.iter().map(|f| f(stack)).collect();
|
||||
let sam = T(stack, &sam);
|
||||
assert_jet_err(stack, jet, sam, err);
|
||||
}
|
||||
|
||||
fn atom_0(_stack: &mut NockStack) -> Noun {
|
||||
print!("{:x}", 0);
|
||||
D(0x0)
|
||||
}
|
||||
|
||||
fn atom_1(_stack: &mut NockStack) -> Noun {
|
||||
print!("{:x}", 1);
|
||||
D(0x1)
|
||||
}
|
||||
|
||||
fn atom_2(_stack: &mut NockStack) -> Noun {
|
||||
print!("{:x}", 2);
|
||||
D(0x2)
|
||||
}
|
||||
|
||||
fn atom_3(_stack: &mut NockStack) -> Noun {
|
||||
print!("{:x}", 3);
|
||||
D(0x3)
|
||||
}
|
||||
|
||||
fn atom_4(_stack: &mut NockStack) -> Noun {
|
||||
D(0x4)
|
||||
}
|
||||
|
||||
fn atom_5(_stack: &mut NockStack) -> Noun {
|
||||
D(0x5)
|
||||
}
|
||||
|
||||
fn atom_0a(_stack: &mut NockStack) -> Noun {
|
||||
D(0xa)
|
||||
}
|
||||
|
||||
fn atom_7f(_stack: &mut NockStack) -> Noun {
|
||||
D(0x7fffffffffffffff)
|
||||
}
|
||||
|
||||
fn atom_100(stack: &mut NockStack) -> Noun {
|
||||
let shl1_6 = UBig::from_str_radix("10000000000000000", 16);
|
||||
A(stack, &ubig!(shl1_6))
|
||||
}
|
||||
|
||||
fn atom_1000(stack: &mut NockStack) -> Noun {
|
||||
let shl1_7 = UBig::from_str_radix("100000000000000000000000000000000", 16);
|
||||
A(stack, &ubig!(shl1_7))
|
||||
}
|
||||
|
||||
fn atom_2000(stack: &mut NockStack) -> Noun {
|
||||
let shl2_7 = UBig::from_str_radix("200000000000000000000000000000000", 16);
|
||||
A(stack, &ubig!(shl2_7))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_peg() {
|
||||
let s = &mut init_stack();
|
||||
|
||||
assert_math_jet_err(s, jet_peg, &[atom_0, atom_1], JetErr::Deterministic);
|
||||
|
||||
// Test direct
|
||||
assert_math_jet(s, jet_peg, &[atom_2, atom_3], ubig!(5));
|
||||
assert_math_jet(s, jet_peg, &[atom_0a,atom_0a], ubig!(82));
|
||||
assert_math_jet(s, jet_peg, &[atom_7f, atom_2], ubig!(0xfffffffffffffffe));
|
||||
assert_math_jet(s, jet_peg, &[atom_7f, atom_3], ubig!(0xffffffffffffffff));
|
||||
|
||||
// Test direct with overflow.
|
||||
assert_math_jet(s, jet_peg, &[atom_7f, atom_4], ubig!(0x1fffffffffffffffc));
|
||||
assert_math_jet(s, jet_peg, &[atom_7f, atom_5], ubig!(0x1fffffffffffffffd));
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
use crate::mem::{word_size_of, NockStack};
|
||||
use bitvec::prelude::{BitSlice, Lsb0};
|
||||
use either::Either;
|
||||
use either::{Either, Left, Right};
|
||||
use ibig::{Stack, UBig};
|
||||
use intmap::IntMap;
|
||||
use std::fmt;
|
||||
@ -18,6 +18,9 @@ const DIRECT_MASK: u64 = !(u64::MAX >> 1);
|
||||
/** Maximum value of a direct atom. Values higher than this must be represented by indirect atoms. */
|
||||
pub const DIRECT_MAX: u64 = u64::MAX >> 1;
|
||||
|
||||
/** Highest direct bit (since leading 0 marks directness) */
|
||||
const DIRECT_BITS: u64 = 62;
|
||||
|
||||
/** Tag for an indirect atom. */
|
||||
const INDIRECT_TAG: u64 = u64::MAX & DIRECT_MASK;
|
||||
|
||||
@ -61,8 +64,8 @@ pub fn acyclic_noun(noun: Noun) -> bool {
|
||||
|
||||
fn acyclic_noun_go(noun: Noun, seen: &mut IntMap<()>) -> bool {
|
||||
match noun.as_either_atom_cell() {
|
||||
Either::Left(_atom) => true,
|
||||
Either::Right(cell) => {
|
||||
Left(_atom) => true,
|
||||
Right(cell) => {
|
||||
if seen.get(cell.0).is_some() {
|
||||
false
|
||||
} else {
|
||||
@ -373,11 +376,11 @@ impl IndirectAtom {
|
||||
|
||||
/** Pointer to data for indirect atom */
|
||||
pub fn data_pointer(&self) -> *const u64 {
|
||||
unsafe { self.to_raw_pointer().add(2) }
|
||||
unsafe { self.to_raw_pointer().add(2) as *const u64 }
|
||||
}
|
||||
|
||||
pub fn data_pointer_mut(&mut self) -> *mut u64 {
|
||||
unsafe { self.to_raw_pointer_mut().add(2) }
|
||||
unsafe { self.to_raw_pointer_mut().add(2) as *mut u64 }
|
||||
}
|
||||
|
||||
pub fn as_slice(&self) -> &[u64] {
|
||||
@ -431,6 +434,24 @@ impl IndirectAtom {
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn as_u64(self) -> Result<u64> {
|
||||
if self.size() == 1 {
|
||||
Ok(*(self.data_pointer()))
|
||||
} else {
|
||||
Err(Error::NotRepresentable)
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn as_u128_pair(self) -> Result<[u64; 2]> {
|
||||
if self.size() <= 2 {
|
||||
let mut u128_array = &mut [0u64; 2];
|
||||
u128_array.copy_from_slice(&(self.as_slice()[0..2]));
|
||||
Ok(unsafe { *u128_array } )
|
||||
} else {
|
||||
Err(Error::NotRepresentable)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_atom(self) -> Atom {
|
||||
Atom { indirect: self }
|
||||
}
|
||||
@ -575,6 +596,27 @@ impl fmt::Display for Cell {
|
||||
}
|
||||
}
|
||||
|
||||
impl Slots for Cell {}
|
||||
impl private::RawSlots for Cell {
|
||||
fn raw_slot(&self, axis: &BitSlice<u64, Lsb0>) -> Result<Noun> {
|
||||
let mut noun: Noun = self.as_noun();
|
||||
let mut cursor = axis.last_one().expect("raw_slow somehow by-passed 0 check");
|
||||
|
||||
while cursor != 0 {
|
||||
cursor -= 1;
|
||||
|
||||
// Returns Err if axis tried to descend through atom
|
||||
if axis[cursor] {
|
||||
noun = noun.as_cell()?.tail();
|
||||
} else {
|
||||
noun = noun.as_cell()?.head();
|
||||
}
|
||||
}
|
||||
|
||||
Ok(noun)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Memory representation of the contents of a cell
|
||||
*/
|
||||
@ -630,6 +672,29 @@ impl Atom {
|
||||
unsafe { is_indirect_atom(self.raw) }
|
||||
}
|
||||
|
||||
pub fn as_u64(self) -> Result<u64> {
|
||||
if self.is_direct() {
|
||||
Ok(unsafe { self.direct.data() })
|
||||
} else {
|
||||
unsafe {
|
||||
self.indirect.as_u64()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn as_u128_pair(self) -> Result<[u64; 2]> {
|
||||
if self.is_direct() {
|
||||
let mut u128_array = &mut [0u64; 2];
|
||||
u128_array[0] = 0x0 as u64;
|
||||
u128_array[1] = self.as_direct()?.data() as u64;
|
||||
Ok(unsafe { *u128_array } )
|
||||
} else {
|
||||
unsafe {
|
||||
self.indirect.as_u128_pair()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_direct(&self) -> Result<DirectAtom> {
|
||||
if self.is_direct() {
|
||||
unsafe { Ok(self.direct) }
|
||||
@ -648,9 +713,9 @@ impl Atom {
|
||||
|
||||
pub fn as_either(&self) -> Either<DirectAtom, IndirectAtom> {
|
||||
if self.is_indirect() {
|
||||
unsafe { Either::Right(self.indirect) }
|
||||
unsafe { Right(self.indirect) }
|
||||
} else {
|
||||
unsafe { Either::Left(self.direct) }
|
||||
unsafe { Left(self.direct) }
|
||||
}
|
||||
}
|
||||
|
||||
@ -678,24 +743,40 @@ impl Atom {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn direct(&self) -> Option<DirectAtom> {
|
||||
if self.is_direct() {
|
||||
unsafe { Some(self.direct) }
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn indirect(&self) -> Option<IndirectAtom> {
|
||||
if self.is_indirect() {
|
||||
unsafe { Some(self.indirect) }
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn size(&self) -> usize {
|
||||
match self.as_either() {
|
||||
Either::Left(_direct) => 1,
|
||||
Either::Right(indirect) => indirect.size(),
|
||||
Left(_direct) => 1,
|
||||
Right(indirect) => indirect.size(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bit_size(&self) -> usize {
|
||||
match self.as_either() {
|
||||
Either::Left(direct) => direct.bit_size(),
|
||||
Either::Right(indirect) => indirect.bit_size(),
|
||||
Left(direct) => direct.bit_size(),
|
||||
Right(indirect) => indirect.bit_size(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn data_pointer(&self) -> *const u64 {
|
||||
match self.as_either() {
|
||||
Either::Left(_direct) => (self as *const Atom) as *const u64,
|
||||
Either::Right(indirect) => indirect.data_pointer(),
|
||||
Left(_direct) => (self as *const Atom) as *const u64,
|
||||
Right(indirect) => indirect.data_pointer(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -750,24 +831,24 @@ impl Allocated {
|
||||
|
||||
pub unsafe fn forwarding_pointer(&self) -> Option<Allocated> {
|
||||
match self.as_either() {
|
||||
Either::Left(indirect) => indirect.forwarding_pointer().map(|i| i.as_allocated()),
|
||||
Either::Right(cell) => cell.forwarding_pointer().map(|c| c.as_allocated()),
|
||||
Left(indirect) => indirect.forwarding_pointer().map(|i| i.as_allocated()),
|
||||
Right(cell) => cell.forwarding_pointer().map(|c| c.as_allocated()),
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn get_metadata(&self) -> u64 {
|
||||
*(self.to_raw_pointer())
|
||||
*(self.to_raw_pointer() as *const u64)
|
||||
}
|
||||
|
||||
pub unsafe fn set_metadata(self, metadata: u64) {
|
||||
*(self.const_to_raw_pointer_mut()) = metadata;
|
||||
*(self.const_to_raw_pointer_mut() as *mut u64) = metadata;
|
||||
}
|
||||
|
||||
pub fn as_either(&self) -> Either<IndirectAtom, Cell> {
|
||||
if self.is_indirect() {
|
||||
unsafe { Either::Left(self.indirect) }
|
||||
unsafe { Left(self.indirect) }
|
||||
} else {
|
||||
unsafe { Either::Right(self.cell) }
|
||||
unsafe { Right(self.cell) }
|
||||
}
|
||||
}
|
||||
|
||||
@ -868,17 +949,57 @@ impl Noun {
|
||||
|
||||
pub fn as_either_atom_cell(&self) -> Either<Atom, Cell> {
|
||||
if self.is_cell() {
|
||||
unsafe { Either::Right(self.cell) }
|
||||
unsafe { Right(self.cell) }
|
||||
} else {
|
||||
unsafe { Either::Left(self.atom) }
|
||||
unsafe { Left(self.atom) }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_either_direct_allocated(&self) -> Either<DirectAtom, Allocated> {
|
||||
if self.is_direct() {
|
||||
unsafe { Either::Left(self.direct) }
|
||||
unsafe { Left(self.direct) }
|
||||
} else {
|
||||
unsafe { Either::Right(self.allocated) }
|
||||
unsafe { Right(self.allocated) }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn atom(&self) -> Option<Atom> {
|
||||
if self.is_atom() {
|
||||
unsafe { Some(self.atom) }
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cell(&self) -> Option<Cell> {
|
||||
if self.is_cell() {
|
||||
unsafe { Some(self.cell) }
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn direct(&self) -> Option<DirectAtom> {
|
||||
if self.is_direct() {
|
||||
unsafe { Some(self.direct) }
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn indirect(&self) -> Option<IndirectAtom> {
|
||||
if self.is_indirect() {
|
||||
unsafe { Some(self.indirect) }
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn allocated(&self) -> Option<Allocated> {
|
||||
if self.is_allocated() {
|
||||
unsafe { Some(self.allocated) }
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
@ -936,8 +1057,8 @@ impl Noun {
|
||||
if allocated.get_metadata() & (1 << 32) == 0 {
|
||||
allocated.set_metadata(allocated.get_metadata() | (1 << 32));
|
||||
match allocated.as_either() {
|
||||
Either::Left(indirect) => indirect.size() + 2,
|
||||
Either::Right(cell) => {
|
||||
Left(indirect) => indirect.size() + 2,
|
||||
Right(cell) => {
|
||||
word_size_of::<CellMemory>()
|
||||
+ cell.head().mass_wind(inside)
|
||||
+ cell.tail().mass_wind(inside)
|
||||
@ -959,7 +1080,7 @@ impl Noun {
|
||||
if let Ok(allocated) = self.as_allocated() {
|
||||
if inside(allocated.to_raw_pointer()) {
|
||||
allocated.set_metadata(allocated.get_metadata() & !(1 << 32));
|
||||
if let Either::Right(cell) = allocated.as_either() {
|
||||
if let Right(cell) = allocated.as_either() {
|
||||
cell.head().mass_unwind(inside);
|
||||
cell.tail().mass_unwind(inside);
|
||||
}
|
||||
@ -996,6 +1117,16 @@ impl fmt::Display for Noun {
|
||||
}
|
||||
}
|
||||
|
||||
impl Slots for Noun {}
|
||||
impl private::RawSlots for Noun {
|
||||
fn raw_slot(&self, axis: &BitSlice<u64, Lsb0>) -> Result<Noun> {
|
||||
match self.as_either_atom_cell() {
|
||||
Right(cell) => cell.raw_slot(axis),
|
||||
Left(_atom) => Err(Error::NotCell), // Axis tried to descend through atom
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An allocation object (probably a mem::NockStack) which can allocate a memory buffer sized to
|
||||
* a certain number of nouns
|
||||
@ -1010,3 +1141,36 @@ pub trait NounAllocator: Sized {
|
||||
/** Allocate memory for a cell */
|
||||
unsafe fn alloc_cell(&mut self) -> *mut CellMemory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementing types allow component Nouns to be retreived by numeric axis
|
||||
*/
|
||||
pub trait Slots: private::RawSlots {
|
||||
/**
|
||||
* Retrieve component Noun at given axis, or fail with descriptive error
|
||||
*/
|
||||
fn slot(&self, axis: u64) -> Result<Noun> {
|
||||
if axis == 0 {
|
||||
Err(Error::NotRepresentable) // 0 is not allowed as an axis
|
||||
} else {
|
||||
self.raw_slot(DirectAtom::new(axis).unwrap().as_bitslice())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation methods that should not be made available to derived crates
|
||||
*/
|
||||
mod private {
|
||||
use crate::noun::{BitSlice, Lsb0, Noun, Result};
|
||||
|
||||
/**
|
||||
* Implementation of the Slots trait
|
||||
*/
|
||||
pub trait RawSlots {
|
||||
/**
|
||||
* Actual logic of retreiving Noun object at some axis
|
||||
*/
|
||||
fn raw_slot(&self, axis: &BitSlice<u64, Lsb0>) -> Result<Noun>;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user