use std::{
cmp::{Ordering, PartialEq, PartialOrd},
fmt::{Display, Formatter, Result as FmtResult},
ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, RemAssign, Sub, SubAssign},
};
use bitvec::{prelude::*, vec::BitVec};
use num_traits::{FromPrimitive, NumCast, One, ToPrimitive, Zero};
use crate::unsigned::UnsignedIntegerExtendable;
#[derive(Clone, Debug, Ord, Eq)]
pub struct SignedIntegerExtendable(pub(crate) BitVec);
impl Display for SignedIntegerExtendable {
fn fmt(&self, f: &mut Formatter) -> FmtResult {
let ten = SignedIntegerExtendable::one()
+ SignedIntegerExtendable::one()
+ SignedIntegerExtendable::one()
+ SignedIntegerExtendable::one()
+ SignedIntegerExtendable::one()
+ SignedIntegerExtendable::one()
+ SignedIntegerExtendable::one()
+ SignedIntegerExtendable::one()
+ SignedIntegerExtendable::one()
+ SignedIntegerExtendable::one();
let mut s = String::new();
let mut a = self.clone();
let mut is_neg = false;
if a.is_negative() {
is_neg = true;
a = -a;
}
if a.clone().is_zero() {
s += "0";
} else {
while !a.clone().is_zero() {
let mut digit = (a.clone() % ten.clone()).0;
while digit.len() < 4 {
digit.insert(0, false);
}
let digit_slice = &digit[0..4];
let mut i = 0;
if digit_slice[3] {
i += 1;
}
if digit_slice[2] {
i += 2;
}
if digit_slice[1] {
i += 4;
}
if digit_slice[0] {
i += 8;
}
s += &format!("{}", i);
a /= ten.clone();
}
}
if is_neg {
s += "-";
}
s = s.chars().rev().collect();
write!(f, "{}", s)
}
}
const MAXITER: i32 = 15;
fn fac(val: i128) -> i128 {
if val <= 0 {
1
} else {
fac(val - 1) * val
}
}
impl SignedIntegerExtendable {
pub fn is_negative(&self) -> bool {
self.0[0]
}
pub fn to_unsigned(&self) -> UnsignedIntegerExtendable {
if self.is_negative() {
panic!("Attempt to cast negative integer to unsigned: {}", self);
}
let mut bits = self.0.clone();
bits.remove(0);
UnsignedIntegerExtendable(bits)
}
pub fn ln(self) -> Self {
if self.clone().is_one() {
Self::zero()
} else {
let mut result = Self::zero();
for n in 0..MAXITER {
let current_value = ((self.clone() - Self::one()) / self.clone()).powi(n)
/ Self::from_usize(fac(n as i128) as usize).unwrap();
result += current_value;
}
result
}
}
pub fn log10(self) -> Self {
self.ln() / SignedIntegerExtendable(bitvec![1, 0, 1, 0]).ln()
}
pub fn powi(self, n: i32) -> Self {
if n == 0 {
Self::one()
} else if n % 2 == 0 {
(self.clone() * self.clone()).powi(n / 2)
} else {
self.clone() * (self.clone() * self.clone()).powi((n - 1) / 2)
}
}
pub fn powf(self, n: Self) -> Self {
(self.ln() * n).exp()
}
pub fn pow(mut self, p: usize) -> Self {
for _ in 0..p {
self *= self.clone();
}
self
}
pub fn exp(self) -> Self {
let mut result = Self::zero();
for n in 0..MAXITER {
let current_value =
self.clone().powi(n) / Self::from_usize(fac(n as i128) as usize).unwrap();
result += current_value;
}
result
}
}
impl PartialEq for SignedIntegerExtendable {
fn eq(&self, other: &Self) -> bool {
if self.is_zero() && other.is_zero() {
true
} else {
let mut a = self.0.clone();
let mut b = other.0.clone();
if a[0] && !b[0] {
false
} else if !a[0] && b[0] {
false
} else {
if a[0] {
a = Self(a).0;
}
if b[0] {
b = Self(b).0;
}
let length = a.len().max(b.len());
while a.len() < length + 1 {
a.insert(1, false);
}
while b.len() < length + 1 {
b.insert(1, false);
}
a.eq(&b)
}
}
}
}
impl PartialOrd for SignedIntegerExtendable {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
if self.is_zero() && other.is_zero() {
Some(Ordering::Equal)
} else {
let mut a = self.0.clone();
let mut b = other.0.clone();
if a[0] && !b[0] {
Some(Ordering::Less)
} else if !a[0] && b[0] {
Some(Ordering::Greater)
} else {
if a[0] {
a = Self(a).0;
}
if b[0] {
b = Self(b).0;
}
let length = a.len().max(b.len());
while a.len() < length + 1 {
a.insert(1, false);
}
while b.len() < length + 1 {
b.insert(1, false);
}
a.partial_cmp(&b)
}
}
}
}
impl Zero for SignedIntegerExtendable {
fn zero() -> Self {
Self(bitvec![0, 0])
}
fn set_zero(&mut self) {
*self = Self::zero();
}
fn is_zero(&self) -> bool {
self.0.iter().all(|b| !*b)
}
}
impl One for SignedIntegerExtendable {
fn one() -> Self {
Self(bitvec![0, 1])
}
fn set_one(&mut self) {
*self = Self::one();
}
fn is_one(&self) -> bool {
*self.0.first().unwrap() && self.0.iter().rev().skip(1).all(|b| !*b)
}
}
impl Neg for SignedIntegerExtendable {
type Output = Self;
fn neg(self) -> Self::Output {
Self(!self.0) + Self::one()
}
}
impl Add for SignedIntegerExtendable {
type Output = SignedIntegerExtendable;
fn add(self, rhs: Self) -> Self::Output {
let length = self.0.len().max(rhs.0.len());
if self.is_zero() && rhs.is_zero() {
Self::zero()
} else {
let mut a = self.0;
while a.len() < length + 1 {
if a[0] {
a.insert(1, true);
} else {
a.insert(1, false);
}
}
let mut b = rhs.0;
while b.len() < length + 1 {
if b[0] {
b.insert(1, true);
} else {
b.insert(1, false);
}
}
while !Self(a.clone()).is_zero() {
let mut c = b.clone() & a.clone();
b = b ^ a;
c <<= 1;
c.push(false);
a = c;
}
let mut ret = b;
let leading_remove = if ret[0] {
ret.iter().skip(1).take_while(|&&b| b).count()
} else {
ret.iter().skip(1).take_while(|&&b| !b).count()
};
for _ in 0..leading_remove {
ret.remove(1);
}
Self(ret)
}
}
}
impl AddAssign for SignedIntegerExtendable {
fn add_assign(&mut self, rhs: Self) {
*self = self.clone() + rhs;
}
}
impl Sub for SignedIntegerExtendable {
type Output = SignedIntegerExtendable;
fn sub(self, rhs: Self) -> Self::Output {
self + -rhs
}
}
impl SubAssign for SignedIntegerExtendable {
fn sub_assign(&mut self, rhs: Self) {
*self = self.clone() - rhs;
}
}
impl Mul for SignedIntegerExtendable {
type Output = SignedIntegerExtendable;
fn mul(mut self, mut rhs: Self) -> Self::Output {
let mut make_negative = false;
if self.is_negative() {
make_negative ^= true;
self = -self;
}
if rhs.is_negative() {
make_negative ^= true;
rhs = -rhs;
}
let mut count = Self::zero();
let mut ret = Self::zero();
while count < rhs.clone() {
ret += self.clone();
count += Self::one();
}
if make_negative {
ret = -ret;
}
ret
}
}
impl MulAssign for SignedIntegerExtendable {
fn mul_assign(&mut self, rhs: Self) {
*self = self.clone() * rhs;
}
}
impl Div for SignedIntegerExtendable {
type Output = SignedIntegerExtendable;
fn div(mut self, mut rhs: Self) -> Self::Output {
let mut make_negative = false;
if self.is_negative() {
make_negative ^= true;
self = -self;
}
if rhs.is_negative() {
make_negative ^= true;
rhs = -rhs;
}
let mut ret = Self::zero();
while self.clone() > rhs.clone() {
self -= rhs.clone();
ret += Self::one();
}
if make_negative {
ret = -ret;
}
ret
}
}
impl DivAssign for SignedIntegerExtendable {
fn div_assign(&mut self, rhs: Self) {
*self = self.clone() / rhs;
}
}
impl Rem for SignedIntegerExtendable {
type Output = Self;
fn rem(mut self, mut rhs: Self) -> Self::Output {
if self.is_negative() {
self = -self;
}
if rhs.is_negative() {
rhs = -rhs;
}
while self.clone() > rhs.clone() {
self -= rhs.clone();
}
self
}
}
impl RemAssign for SignedIntegerExtendable {
fn rem_assign(&mut self, rhs: Self) {
*self = self.clone() - rhs;
}
}
impl NumCast for SignedIntegerExtendable {
fn from<T: ToPrimitive>(n: T) -> Option<Self> {
n.to_i128().and_then(|i| {
let mut ret = BitVec::new();
ret.extend_from_slice(i.to_be_bytes().bits::<Msb0>());
if ret[0] {
while ret.len() > 2 && ret[1] {
ret.remove(1);
}
} else {
while ret.len() > 2 && !ret[1] {
ret.remove(1);
}
}
Some(Self(ret))
})
}
}
impl FromPrimitive for SignedIntegerExtendable {
fn from_isize(_n: isize) -> Option<Self> {
unimplemented!()
}
fn from_i8(_n: i8) -> Option<Self> {
unimplemented!()
}
fn from_i16(_n: i16) -> Option<Self> {
unimplemented!()
}
fn from_i32(_n: i32) -> Option<Self> {
unimplemented!()
}
fn from_i64(_n: i64) -> Option<Self> {
unimplemented!()
}
fn from_i128(_n: i128) -> Option<Self> {
unimplemented!()
}
fn from_usize(n: usize) -> Option<Self> {
NumCast::from(n)
}
fn from_u8(_n: u8) -> Option<Self> {
unimplemented!()
}
fn from_u16(_n: u16) -> Option<Self> {
unimplemented!()
}
fn from_u32(_n: u32) -> Option<Self> {
unimplemented!()
}
fn from_u64(_n: u64) -> Option<Self> {
unimplemented!()
}
fn from_u128(_n: u128) -> Option<Self> {
unimplemented!()
}
fn from_f32(_n: f32) -> Option<Self> {
unimplemented!()
}
fn from_f64(_n: f64) -> Option<Self> {
unimplemented!()
}
}
impl ToPrimitive for SignedIntegerExtendable {
fn to_isize(&self) -> Option<isize> {
unimplemented!()
}
fn to_i8(&self) -> Option<i8> {
unimplemented!()
}
fn to_i16(&self) -> Option<i16> {
unimplemented!()
}
fn to_i32(&self) -> Option<i32> {
unimplemented!()
}
fn to_i64(&self) -> Option<i64> {
unimplemented!()
}
fn to_i128(&self) -> Option<i128> {
unimplemented!()
}
fn to_usize(&self) -> Option<usize> {
unimplemented!()
}
fn to_u8(&self) -> Option<u8> {
unimplemented!()
}
fn to_u16(&self) -> Option<u16> {
unimplemented!()
}
fn to_u32(&self) -> Option<u32> {
unimplemented!()
}
fn to_u64(&self) -> Option<u64> {
unimplemented!()
}
fn to_u128(&self) -> Option<u128> {
unimplemented!()
}
fn to_f32(&self) -> Option<f32> {
unimplemented!()
}
fn to_f64(&self) -> Option<f64> {
unimplemented!()
}
}