BigInts should be done

This commit is contained in:
mStar aka a person 2024-01-25 15:29:47 +01:00
parent 4a2c1927f5
commit 0cc19e0883
2 changed files with 133 additions and 3 deletions

View file

@ -1,6 +1,135 @@
use num_bigint::BigInt; use num_bigint::{BigInt, BigUint, ToBigInt};
#[derive(Debug)] use super::{bool::JsBool, string::JsString};
#[derive(Debug, Clone)]
pub struct JsBigInt { pub struct JsBigInt {
pub value: BigInt pub value: BigInt
} }
// Implements https://tc39.es/ecma262/2023/#table-numeric-type-ops
impl JsBigInt {
pub fn unary_minus(&self) -> JsBigInt {
JsBigInt{
value: &self.value * -1
}
}
pub fn bitwise_not(&self) -> JsBigInt {
JsBigInt{
value: !&self.value
}
}
pub fn exponentiate(&self, x: &JsBigInt) -> JsBigInt {
let (_, digits) = x.value.to_u32_digits();
JsBigInt{
value: self.value.pow(*digits.first().expect("Exponent bigint didn't have any digits"))
}
}
pub fn multiply(&self, x: &JsBigInt) -> JsBigInt {
JsBigInt{
value: &self.value * &x.value
}
}
pub fn divide(&self, x: &JsBigInt) -> JsBigInt {
JsBigInt{
value: &self.value / &x.value
}
}
pub fn add(&self, x: &JsBigInt) -> JsBigInt {
JsBigInt{
value: &self.value + &x.value
}
}
pub fn pre_add(&mut self) -> JsBigInt {
self.value += 1;
self.clone()
}
pub fn post_add(&mut self) -> JsBigInt {
let old = self.clone();
self.value += 1;
old
}
pub fn subtract(&self, x: &JsBigInt) -> JsBigInt {
JsBigInt{
value: &self.value - &x.value
}
}
pub fn pre_subtract(&mut self) -> JsBigInt {
self.value -= 1;
self.clone()
}
pub fn post_subtract(&mut self) -> JsBigInt {
let old = self.clone();
self.value -= 1;
old
}
pub fn left_shift(&self, x: &JsBigInt) -> JsBigInt {
let (_, digits) = x.value.to_u32_digits();
JsBigInt{
value: &self.value << *digits.first().expect("Shift amount bigint didn't have any digits")
}
}
pub fn right_shift_signed(&self, x: &JsBigInt) -> JsBigInt {
let (_, digits) = x.value.to_u32_digits();
JsBigInt{
value: &self.value >> *digits.first().expect("Shift amount bigint didn't have any digits")
}
}
pub fn right_shift_unsigned(&self, x: &JsBigInt) -> JsBigInt {
let (_, digits) = x.value.to_u32_digits();
let (_, old_bytes) = self.value.to_bytes_be();
let u = BigUint::from_bytes_be(&old_bytes);
JsBigInt{
value: (u >> *digits.first().expect("Shift amount bigint didn't have any digits")).to_bigint().expect("Failed to convert BigUInt to BigInt")
}
}
pub fn less_than(&self, x: &JsBigInt) -> JsBool {
JsBool { value: self.value < x.value }
}
pub fn equal(&self, x: &JsBigInt) -> JsBool {
JsBool { value: self.value == x.value }
}
pub fn same_value(&self, x: &JsBigInt) -> JsBool {
JsBool { value: std::ptr::eq(self, x) }
}
pub fn bitwise_and(&self, x: &JsBigInt) -> JsBigInt {
JsBigInt{
value: &self.value & &x.value
}
}
pub fn bitwise_xor(&self, x: &JsBigInt) -> JsBigInt {
JsBigInt{
value: &self.value ^ &x.value
}
}
pub fn bitwise_or(&self, x: &JsBigInt) -> JsBigInt {
JsBigInt{
value: &self.value | &x.value
}
}
pub fn to_string(&self) -> JsString {
JsString {
value: self.value.to_string().into()
}
}
}

View file

@ -1,5 +1,6 @@
use self::{big_int::JsBigInt, bool::JsBool, number::JsNumber, object::JsObject, string::JsString, symbol::JsSymbol}; use self::{big_int::JsBigInt, bool::JsBool, number::JsNumber, object::JsObject, string::JsString, symbol::JsSymbol};
// All Js primitive objects are wrappers around a single value
pub mod bool; pub mod bool;
pub mod string; pub mod string;
pub mod symbol; pub mod symbol;