Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #![feature(trace_macros)]
- use std::ops;
- use std::fmt;
- use std::cmp;
- #[derive(Clone)]
- struct BigUInt {
- val : Vec<u128>,
- }
- fn sgn(i: i128) -> i8 {
- if i == 0 {
- 0
- } else if i < 0 {
- -1
- } else {
- 1
- }
- }
- impl BigUInt {
- fn new(v: u128) -> BigUInt {
- BigUInt {
- val : vec![v],
- }
- }
- fn parse_hex(hex: String) -> BigUInt {
- let mut ret = Vec::new();
- ret.resize(hex.len() * 4 / 128 + 1, 0);
- let mut pos = 0;
- for i in hex.bytes().rev() {
- let mut byte = i - 48;
- if byte > 10 {
- byte = i - 65 + 10;
- }
- let batch = pos / 128;
- let shift = pos % 128;
- ret[batch] |= (byte as u128) << shift;
- pos += 4;
- }
- let mut len = ret.len();
- while len > 1 && ret[len - 1] == 0 {
- len -= 1;
- }
- ret.resize(len, 0);
- BigUInt {
- val: ret,
- }
- }
- fn num_bits(&self) -> usize {
- while self.val[0] == 0 && self.val.len() == 1 {
- return 0;
- }
- let mut bit = 127;
- let last = self.val.len() - 1;
- while ((self.val[last] >> bit) & 1) == 0 {
- bit -= 1;
- }
- bit
- }
- fn getBit(&self, i: usize) -> bool {
- let batch = i / 128;
- if batch >= self.val.len() {
- false
- } else {
- if self.val[batch] & (1u128 << i % 128) == 0 {
- false
- } else {
- true
- }
- }
- }
- fn sq(&self) -> BigUInt {
- self * self
- }
- fn pow(&self, pow: &BigUInt) -> BigUInt {
- let mut sq = self.clone();
- let mut ret = BigUInt::new(1);
- let num_bits = pow.num_bits();
- for i in 0..num_bits + 1 {
- if ((pow.val[i / 128] >> (i % 128)) & 1) == 1 {
- ret = &ret * &sq;
- }
- if i < num_bits {
- sq = &sq * &sq;
- }
- }
- ret
- }
- fn powmod(&self, pow: &BigUInt, modulus: &BigUInt) -> BigUInt {
- let mut sq = self.clone();
- let mut ret = BigUInt::new(1);
- let num_bits = pow.num_bits();
- for i in 0..num_bits + 1 {
- if ((pow.val[i / 128] >> (i % 128)) & 1) == 1 {
- ret = &ret * &sq;
- }
- if i < num_bits {
- sq = &sq * &sq;
- if &sq >= modulus {
- sq = &sq % &modulus;
- }
- }
- }
- &ret % &modulus
- }
- }
- impl fmt::Display for BigUInt {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- //let mut out : Vec<u8> = Vec::new();
- let mut rest = self.clone();
- let zero = BigUInt::new(0);
- let ten = BigUInt::new(10);
- if rest == zero {
- write!(f, "0")
- } else {
- let mut digits = Vec::new();
- while rest > zero {
- let digit = &rest % &ten;
- digits.push(digit.val[0] as u8 + 48);
- rest = &rest / &ten;
- }
- digits.reverse();
- write!(f, "{}", String::from_utf8(digits).unwrap())
- }
- }
- }
- impl fmt::Binary for BigUInt {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- for i in self.val.iter().rev() {
- write!(f, "{:0128b}", i)?;
- }
- write!(f, "")
- }
- }
- impl fmt::Debug for BigUInt {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- for i in self.val.iter().rev() {
- write!(f, "{:0128b}", i)?;
- }
- write!(f, "")
- }
- }
- impl cmp::Ord for BigUInt {
- fn cmp(&self, other: &BigUInt) -> cmp::Ordering {
- let mut len_cmp = (&self.val.len()).cmp(&other.val.len());
- if len_cmp == cmp::Ordering::Equal {
- let mut len = self.val.len();
- while len > 0 && len_cmp == cmp::Ordering::Equal {
- len_cmp = self.val[len - 1].cmp(&other.val[len - 1]);
- len -= 1;
- }
- }
- len_cmp
- }
- }
- impl cmp::Eq for BigUInt {}
- impl cmp::PartialOrd for BigUInt {
- fn partial_cmp(&self, other: &BigUInt) -> Option<cmp::Ordering> {
- Some(self.cmp(other))
- }
- }
- impl cmp::PartialEq for BigUInt {
- fn eq(&self, other: &BigUInt) -> bool {
- self.cmp(other) == cmp::Ordering::Equal
- }
- }
- macro_rules! implBigUIntFrom {
- ($originType:ty) => {
- impl From<$originType> for BigUInt {
- fn from(v : $originType) -> BigUInt {
- BigUInt::new(v as u128)
- }
- }
- };
- }
- implBigUIntFrom!(u8);
- implBigUIntFrom!(u16);
- implBigUIntFrom!(u32);
- implBigUIntFrom!(u64);
- implBigUIntFrom!(u128);
- implBigUIntFrom!(i8);
- implBigUIntFrom!(i16);
- implBigUIntFrom!(i32);
- implBigUIntFrom!(i64);
- implBigUIntFrom!(i128);
- fn smaller<'a>(v1 : &'a Vec<u128>, v2 : &'a Vec<u128>) -> (&'a Vec<u128>, &'a Vec<u128>) {
- if v1.len() < v2.len() {
- (v1, v2)
- } else {
- (v2, v1)
- }
- }
- macro_rules! toVal {
- (@parsing ($($stack:tt)*) R $($rest:tt)*) => {
- {
- toVal!(@parsing (* $($stack)*) $($rest)*)
- }
- };
- (@parsing ($($stack:tt)*) $($rest:tt)*) => {
- {
- $($stack)*
- }
- };
- ($first:expr, $($rest:tt)*) => {
- {
- toVal!(@parsing ($first) $($rest)*)
- }
- };
- }
- macro_rules! implBigUIntAdd {
- ($lhsType:ty, $rhsType:ty, $($lhsRefs:ident)*, $($rhsRefs:ident)*, $($generics:tt)*) => {
- impl$($generics)* ops::Add<$rhsType> for $lhsType {
- type Output = BigUInt;
- fn add(self, rhs: $rhsType) -> BigUInt {
- let ord = smaller(&self.val, &rhs.val);
- let mut ret = Vec::new();
- ret.resize(ord.1.len() + 1, 0);
- let mut carry = false;
- for i in 0..ord.0.len() {
- let mut res = ord.0[i].overflowing_add(ord.1[i]);
- ret[i] = res.0;
- if carry {
- if !ret[i] == 0 {
- if res.1 {
- panic!("Double Carry!");
- }
- ret[i] = 0;
- res.1 = true;
- } else {
- ret[i] += 1;
- }
- }
- carry = res.1;
- }
- let mut real_len = ord.0.len();
- if ord.0.len() != ord.1.len() {
- for i in ord.0.len()..ord.1.len() {
- ret[i] = ord.1[i];
- if carry {
- if !ret[i] == 0 {
- ret[i] = 0;
- carry = true;
- } else {
- ret[i] += 1;
- carry = false;
- }
- } else {
- carry = false;
- }
- if ret[i] != 0 {
- real_len = cmp::max(real_len, i + 1);
- }
- }
- }
- if carry {
- ret[ord.1.len()] += 1;
- } else {
- ret.resize(real_len, 0);
- }
- if ret.len() > 1 && ret[ret.len() - 1] == 0 {
- panic!("Invalid len at add!");
- }
- debug_assert!(ret.len() == 1 || ret[ret.len() - 1] != 0);
- BigUInt {
- val: ret,
- }
- }
- }
- };
- }
- macro_rules! implBigUIntSub {
- ($lhsType:ty, $rhsType:ty, $($lhsRefs:ident)*, $($rhsRefs:ident)*, $($generics:tt)*) => {
- impl$($generics)* ops::Sub<$rhsType> for $lhsType {
- type Output = BigUInt;
- fn sub(self, rhs: $rhsType) -> BigUInt {
- if toVal!(&rhs, $($rhsRefs)*) > toVal!(&self, $($lhsRefs)*) {
- panic!("Subtracting the wrong way!");
- }
- let mut subtrahend_buf = rhs.val.clone();
- let mut len = self.val.len() + 1;
- subtrahend_buf.resize(len, 0);
- for i in subtrahend_buf.iter_mut() {
- *i = !*i;
- }
- let subtrahend = BigUInt {
- val: subtrahend_buf,
- };
- let mut ret = self + &subtrahend + BigUInt::new(1);
- ret.val[len] -= 1;
- while len > 1 && ret.val[len - 1] == 0 {
- len -= 1;
- }
- ret.val.resize(len, 0);
- debug_assert!(ret.val.len() == 1 || ret.val[ret.val.len() - 1] != 0);
- ret
- }
- }
- };
- }
- macro_rules! implBigUIntMul {
- ($lhsType:ty, $rhsType:ty, $($lhsRefs:ident)*, $($rhsRefs:ident)*, $($generics:tt)*) => {
- impl$($generics)* ops::Mul<$rhsType> for $lhsType {
- type Output = BigUInt;
- fn mul(self, rhs: $rhsType) -> BigUInt {
- const LOWER_MASK : u128 = !0u64 as u128;
- let mut ret : Vec<u128> = Vec::new();
- let len = self.val.len() + rhs.val.len();
- ret.resize(3 * len, 0);
- let ord = smaller(&self.val, &rhs.val);
- for i in 0..ord.0.len()*2 {
- for j in 0..ord.1.len()*2 {
- let mut x = ord.0[i >> 1];
- if (i & 1) == 0 {
- x = x & LOWER_MASK;
- } else {
- x = x >> 64;
- }
- let mut y = ord.1[j >> 1];
- if (j & 1) == 0 {
- y = y & LOWER_MASK;
- } else {
- y = y >> 64;
- }
- let dest = len + i + j;
- let mut res = ret[dest].overflowing_add(x * y);
- ret[dest] = res.0;
- let mut next = dest + 1;
- while res.1 {
- ret[next] += 1;
- if ret[next] != 0 {
- res.1 = false
- }
- next += 1
- }
- }
- }
- let mut carry = 0;
- let mut final_len = 0;
- for i in 0..len {
- let mut new_carry = 0;
- let dest = len + 2 * i;
- let res = ret[dest].overflowing_add(carry);
- ret[i] = res.0;
- if res.1 {
- new_carry += 1;
- }
- let res = ret[i].overflowing_add((ret[dest + 1] & LOWER_MASK) << 64);
- ret[i] = res.0;
- if ret[i] != 0 {
- final_len = i + 1;
- }
- if res.1 {
- new_carry += 1;
- }
- carry = new_carry + ret[dest + 1] >> 64;
- }
- ret.resize(final_len, 0);
- debug_assert!(ret.len() == 1 || ret[ret.len() - 1] != 0);
- BigUInt {
- val: ret,
- }
- }
- }
- };
- }
- macro_rules! implBigUIntDiv {
- ($lhsType:ty, $rhsType:ty, $($lhsRefs:ident)*, $($rhsRefs:ident)*, $($generics:tt)*) => {
- impl$($generics)* ops::Div<$rhsType> for $lhsType {
- type Output = BigUInt;
- fn div(self, rhs: $rhsType) -> BigUInt {
- let mut pows : Vec<BigUInt> = Vec::new();
- pows.push(toVal!(&rhs, $($rhsRefs)*).clone());
- let mut pow_len = 1;
- while &pows[pow_len - 1] < toVal!(&self, $($lhsRefs)*) {
- let next_sq = &pows[pow_len - 1] + &pows[pow_len - 1];
- pows.push(next_sq);
- pow_len += 1;
- }
- let mut div : Vec<u128> = Vec::new();
- let mut div_len = self.val.len();
- div.resize(div_len, 0);
- let mut ret = toVal!(&self, $($lhsRefs)*).clone();
- while ret >= pows[0] {
- while pows[pow_len - 1] > ret {
- pow_len -= 1;
- }
- let mut bucket = (pow_len - 1) / 128;
- let res = div[bucket].overflowing_add(1 << ((pow_len - 1) % 128));
- div[bucket] = res.0;
- if res.1 {
- loop {
- bucket += 1;
- if !div[bucket] == 0 {
- div[bucket] = 0;
- } else {
- div[bucket] += 1;
- break;
- }
- }
- }
- ret = ret - &pows[pow_len - 1];
- }
- while div_len > 1 && div[div_len - 1] == 0 {
- div_len -= 1;
- }
- div.resize(div_len, 0);
- BigUInt {
- val: div,
- }
- }
- }
- };
- }
- macro_rules! implBigUIntRem {
- ($lhsType:ty, $rhsType:ty, $($lhsRefs:ident)*, $($rhsRefs:ident)*, $($generics:tt)*) => {
- impl$($generics)* ops::Rem<$rhsType> for $lhsType {
- type Output = BigUInt;
- fn rem(self, rhs: $rhsType) -> BigUInt {
- let mut pows : Vec<BigUInt> = Vec::new();
- pows.push(toVal!(&rhs, $($rhsRefs)*).clone());
- let mut pow_len = 1;
- while &pows[pow_len - 1] < toVal!(&self, $($lhsRefs)*) {
- let next_sq = &pows[pow_len - 1] + &pows[pow_len - 1];
- pows.push(next_sq);
- pow_len += 1;
- }
- let mut ret = toVal!(&self, $($lhsRefs)*).clone();
- while ret >= pows[0] {
- while pows[pow_len - 1] > ret {
- pow_len -= 1;
- }
- ret = ret - &pows[pow_len - 1];
- }
- ret
- }
- }
- };
- }
- macro_rules! implBigUIntTypes {
- ($implMacro:ident) => {
- $implMacro!(&'a BigUInt, &'b BigUInt, R, R, <'a, 'b>);
- $implMacro!(&'a BigUInt, BigUInt, R, , <'a>);
- $implMacro!(BigUInt, &'b BigUInt, , R, <'b>);
- $implMacro!(BigUInt, BigUInt, , , <>);
- $implMacro!(&&'a BigUInt, &&'b BigUInt, R R, R R, <'a, 'b>);
- $implMacro!(&&'a BigUInt, &BigUInt, R R, R, <'a>);
- $implMacro!(&BigUInt, &&'b BigUInt, R, R R, <'b>);
- $implMacro!(&&'a BigUInt, BigUInt, R R, , <'a>);
- $implMacro!(BigUInt, &&'b BigUInt, , R R, <'b>);
- }
- }
- implBigUIntTypes!(implBigUIntAdd);
- implBigUIntTypes!(implBigUIntSub);
- implBigUIntTypes!(implBigUIntMul);
- implBigUIntTypes!(implBigUIntDiv);
- implBigUIntTypes!(implBigUIntRem);
- //implBigUInt!(Add, add, +);
- //implBigUInt!(Sub, sub, -);
- //implBigUInt!(Div, div, /);
- macro_rules! bigeval {
- // Ignore tokens that are member accesses
- (@parsing ($($stack:tt)*) . $member:tt $($rest:tt)*) => {
- {
- bigeval!(@parsing ($($stack)* . $member) $($rest)*)
- }
- };
- // Power mod a ** b % c shortcut
- // Ketwords with higher precedence: as - * ! & &mut
- // None of them apply so it can be ignored
- (@parsing ($($stack:tt)*) $lhs:tt * * $rhs:tt % $modulus:tt $($rest:tt)*) => {
- {
- bigeval!(@parsing ($($stack)* bigeval!($lhs).powmod(bigeval!($rhs), bigeval!($modulus))) $($rest)*)
- }
- };
- // Power function a ** b shortcut
- (@parsing ($($stack:tt)*) $lhs:tt * * $rhs:tt $($rest:tt)*) => {
- {
- bigeval!(@parsing ($($stack)* bigeval!($lhs).pow(bigeval!($rhs))) $($rest)*)
- }
- };
- // Dereference identifiers
- (@parsing ($($stack:tt)*) $id:ident $($rest:tt)*) => {
- {
- bigeval!(@parsing ($($stack)* & $id) $($rest)*)
- }
- };
- // Recurse on parenthesis
- (@parsing ($($stack:tt)*) ($($inside:tt)+)) => {
- {
- //bigeval!(@parsing ( $($i)* (bigeval!($($k)*)) ))
- $($stack)* (bigeval!($($inside)*))
- }
- };
- // Recurse on parenthesis, without injecting a phantom AST node
- (@parsing ($($stack:tt)*) ()) => {
- {
- //bigeval!(@parsing ( $($i)* (bigeval!($($k)*)) ))
- $($stack)* ()
- }
- };
- // Ignore remaining tokens
- (@parsing ($($stack:tt)*) $token:tt $($rest:tt)*) => {
- {
- bigeval!(@parsing ($($stack)* $token) $($rest)*)
- }
- };
- // No more tokens to pop, so return the stack
- (@parsing ($($stack:tt)*)) => {
- {
- $($stack)*
- }
- };
- // Initialize with an empty stack
- ($($tokens:tt)*) => {
- {
- bigeval!(@parsing () $($tokens)*)
- }
- };
- }
- struct P {
- x : BigUInt,
- }
- fn test() {
- let a : BigUInt = 9.into();
- let b : BigUInt = 3.into();
- let c : BigUInt = 2.into();
- //println!("Hello, world! {:?}", &a / &b);
- let myp = P { x : 2.into() };
- let v = vec![&a, &b, &c];
- //trace_macros!(true);
- let d = bigeval!(a + b * myp.x.sq() + a ** (&b) % c + a ** b - v[5 - 4] * c);
- //d = &a + &b - &c;
- //trace_macros!(false);
- //println!("Hello, world! {:?}", d - BigUInt::new(3));
- let mut f = BigUInt::new(1);
- for _ in 0..100 {
- f = &f * BigUInt::new(5);
- }
- let mut g = BigUInt::new(1);
- for i in 0..105 {
- //println!("g = 5^{}: {}", i, g);
- //println!("f: {}", f);
- //println!("g % f = {}", &g % &f);
- g = &g * BigUInt::new(5);
- }
- //println!("5^100: {}", BigUInt::new(5).pow(&BigUInt::new(100)));
- //println!("5^100 % 10000000: {}", BigUInt::new(5).powmod(&BigUInt::new(100), &BigUInt::new(10000000)));
- /*for i in 0..105 {
- println!("g = 5^{}: {}", 105 - i, g);
- println!("f: {}", f);
- println!("g % f = {}", &g % &f);
- g = &g / BigUInt::new(5);
- }*/
- let k = a.clone();
- //println!("Hello, world! {}", &a + k);
- //println!("ToHex: {}", BigUInt::parse_hex("AB84E91F9D89F9AB84E91F9D89F9AB84E91F9D89F9AB84E91F9D89F9".to_string()));
- }
- #[derive(PartialEq, Clone, Debug)]
- struct Point {
- x: BigUInt,
- y: BigUInt
- }
- fn point_add(p: &Point, q: &Point) -> Point {
- println!("p: {:?}", p);
- println!("q: {:?}", q);
- let P: BigUInt = BigUInt::parse_hex("115792089237316195423570985008687907853269984665640564039457584007908834671663".to_string());
- let lam: BigUInt = if p == q {
- BigUInt::new(3) * &p.x * &p.x * ((BigUInt::new(2) * &p.y) % &P).powmod(&(&P - BigUInt::new(2)), &P)
- } else {
- &(&q.x - &p.x).powmod(&(&P - BigUInt::new(2)), &P) * (&q.y - &p.y) % &P
- };
- let rx = lam.clone().pow(&BigUInt::new(2)) - &p.x - &q.x;
- let ry: BigUInt = lam * (&p.x - &rx) - &p.y;
- let ret = Point{x: rx % &P, y: ry % &P};
- println!("ret: {:?}", ret);
- ret
- }
- fn point_mul(p: &Point, d: u32) -> Point {
- let mut n: Point = (*p).clone();
- let mut q: Option<Point> = None;
- let binary: String = format!("{:0256b}", d);
- for (i, digit) in binary.chars().rev().enumerate() {
- if digit == '1' {
- q = match q { None => Some(n.clone()), Some(i) => Some(point_add(&i, &n)) }
- }
- n = point_add(&n, &n);
- }
- q.unwrap()
- }
- fn main() {
- //test();
- let G: Point = Point {
- x: BigUInt::parse_hex("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798".to_string()),
- y: BigUInt::parse_hex("483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8".to_string())
- };
- let res = point_mul(&G, 5);
- println!(" {}", res.x);
- println!(" {}", res.y);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement