From 2bf5effe95641667a1ed51c04eff7760f6a42ef4 Mon Sep 17 00:00:00 2001 From: tomsmeding Date: Mon, 3 Oct 2016 13:00:14 +0200 Subject: Initial --- .gitignore | 4 + Makefile | 24 +++ bigint.cpp | 498 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ bigint.h | 87 ++++++++++ biginttest.py | 38 +++++ main.cpp | 141 +++++++++++++++++ numalgo.cpp | 50 ++++++ numalgo.h | 11 ++ rsa.cpp | 12 ++ rsa.h | 15 ++ 10 files changed, 880 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 bigint.cpp create mode 100644 bigint.h create mode 100755 biginttest.py create mode 100644 main.cpp create mode 100644 numalgo.cpp create mode 100644 numalgo.h create mode 100644 rsa.cpp create mode 100644 rsa.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..89805cd --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.o +*.dSYM +main +*.txt diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..14220de --- /dev/null +++ b/Makefile @@ -0,0 +1,24 @@ +CXX = g++ +CXXFLAGS = -Wall -Wextra -std=c++11 -fwrapv +ifneq ($(DEBUG),) + CXXFLAGS += -g +else + CXXFLAGS += -O2 +endif +BIN = main + +.PHONY: all clean remake + +all: $(BIN) + +clean: + rm -rf $(BIN) *.o *.dSYM + +remake: clean all + + +$(BIN): $(patsubst %.cpp,%.o,$(wildcard *.cpp)) + $(CXX) -o $@ $^ + +%.o: %.cpp $(wildcard *.h) + $(CXX) $(CXXFLAGS) -c -o $@ $< diff --git a/bigint.cpp b/bigint.cpp new file mode 100644 index 0000000..5182d07 --- /dev/null +++ b/bigint.cpp @@ -0,0 +1,498 @@ +#include +#include +#include +#include +#include "bigint.h" +#include "numalgo.h" + +using namespace std; + +Bigint::Bigint() + :sign(1){} + +Bigint::Bigint(slongdigit_t v) + :digits(1,abs(v)),sign(v>=0?1:-1){ + static_assert(sizeof(longdigit_t)==2*sizeof(digit_t), + "longdigit_t should be twice as large as digit_t"); + v=abs(v); + if(v>digits[0])digits.push_back(v>>digit_bits); + else if(v==0)digits.clear(); + checkconsistent(); +} + +void Bigint::add(Bigint &a,const Bigint &b){ + if(a.digits.size()=((longdigit_t)1<>digit_bits; + } + if(carry)a.digits.push_back(1); + a.normalise(); + a.checkconsistent(); +} + +void Bigint::subtract(Bigint &a,const Bigint &b){ + if(a.digits.size()=b.digits.size()); + if(a.digits.size()==0){ + a.checkconsistent(); + return; + } + assert(a.digits.size()>0); + int sz=a.digits.size(); + int carry=0; + for(int i=0;i=(int)b.digits.size()&&!carry)break; + digit_t adig=a.digits[i]; + digit_t bdig=i<(int)b.digits.size()?b.digits[i]:0; + digit_t res=adig-(bdig+carry); + // cerr<<"carry="<>digit_bits; + // cerr<<"carry="<>digit_bits; + // cerr<<"(2) carry="<=0?1:-1; + v*=sign; + digits[0]=v; + if(v>digits[0])digits.push_back(v>>digit_bits); + shrink(); + normalise(); + checkconsistent(); + return *this; +} + +Bigint& Bigint::operator+=(const Bigint &o){ + if(&o==this){ + return *this=Bigint(*this)+=o; + } + if(sign==1){ + if(o.sign==1)add(*this,o); + else subtract(*this,o); + } else { + if(o.sign==1)subtract(*this,o); + else add(*this,o); + } + checkconsistent(); + return *this; +} + +Bigint& Bigint::operator-=(const Bigint &o){ + if(&o==this){ + return *this=Bigint(*this)-=o; + } + if(sign==1){ + if(o.sign==1)subtract(*this,o); + else add(*this,o); + } else { + if(o.sign==1)add(*this,o); + else subtract(*this,o); + } + checkconsistent(); + return *this; +} + +Bigint& Bigint::operator*=(const Bigint &o){ + *this=product(*this,o); + checkconsistent(); + return *this; +} + +Bigint& Bigint::operator<<=(int sh){ + if(sh==0)return *this; + if(digits.size()==0)return *this; + if(sh<0)return *this>>=-sh; + if(sh/digit_bits>0){ + digits.insert(digits.begin(),sh/digit_bits,0); + sh%=digit_bits; + if(sh==0){ + checkconsistent(); + return *this; + } + } + digits.push_back(0); + for(int i=digits.size()-2;i>=0;i--){ + digits[i+1]|=digits[i]>>(digit_bits-sh); + digits[i]<<=sh; + } + shrink(); + normalise(); + checkconsistent(); + return *this; +} + +Bigint& Bigint::operator>>=(int sh){ + if(sh==0)return *this; + if(digits.size()==0)return *this; + if(sh<0)return *this<<=-sh; + if(sh/digit_bits>0){ + if(sh/digit_bits>=(int)digits.size()){ + digits.clear(); + sign=1; + checkconsistent(); + return *this; + } + digits.erase(digits.begin(),digits.begin()+sh/digit_bits); + sh%=digit_bits; + if(sh==0){ + checkconsistent(); + return *this; + } + } + digits[0]>>=sh; + int sz=digits.size(); + for(int i=1;i>=sh; + } + shrink(); + normalise(); + checkconsistent(); + return *this; +} + +Bigint& Bigint::negate(){ + sign=-sign; + return *this; +} + +Bigint Bigint::operator+(const Bigint &o) const { + return Bigint(*this)+=o; +} + +Bigint Bigint::operator-(const Bigint &o) const { + return Bigint(*this)-=o; +} + +Bigint Bigint::operator*(const Bigint &o) const { + return product(*this,o); +} + +int depthrecord; + +pair Bigint::divmod(const Bigint &div) const { + pair res=divmod(div,1); + //cerr< Bigint::divmod(const Bigint &div,int depth) const { + //cerr<<"divmod("<=0;i--){ + os< outbuf; + while(b!=0){ + pair dm=b.divmod(div); + b=dm.first; + Bigint::longdigit_t val=0; + assert(dm.second.digits.size()<=2); + if(dm.second.digits.size()>=2) + val+=((Bigint::longdigit_t)1<=1) + val+=dm.second.digits[0]; + outbuf.push_back(val); + } + for(int i=outbuf.size()-1;i>=0;i--){ + (i==(int)outbuf.size()-1?os:os< +#include +#include +#include + +class Bigint{ +public: + using digit_t=uint32_t; + using longdigit_t=uint64_t; + using slongdigit_t=int64_t; + static const int digit_bits=8*sizeof(digit_t); + +private: + std::vector digits; + int sign; + + static void add(Bigint&,const Bigint&); //ignores sign of arguments + static void subtract(Bigint&,const Bigint&); //ignores sign of arguments; assumes a>=b + static Bigint product(const Bigint&,const Bigint&); + + void shrink(); + void normalise(); + void checkconsistent(); + + std::pair divmod(const Bigint&,int depth) const; + +public: + Bigint(); + Bigint(const Bigint&)=default; + Bigint(Bigint&&)=default; + explicit Bigint(slongdigit_t); + + Bigint& operator=(const Bigint&)=default; + Bigint& operator=(Bigint&&)=default; + Bigint& operator=(slongdigit_t); + + Bigint& operator+=(const Bigint&); + Bigint& operator-=(const Bigint&); + Bigint& operator*=(const Bigint&); + Bigint& operator<<=(int); + Bigint& operator>>=(int); + Bigint& negate(); + + Bigint operator+(const Bigint&) const; + Bigint operator-(const Bigint&) const; + Bigint operator*(const Bigint&) const; + Bigint operator<<(int) const; + Bigint operator>>(int) const; + std::pair divmod(const Bigint&) const; + + bool operator==(const Bigint&) const; + bool operator!=(const Bigint&) const; + bool operator<(const Bigint&) const; + bool operator>(const Bigint&) const; + bool operator<=(const Bigint&) const; + bool operator>=(const Bigint&) const; + bool operator==(slongdigit_t) const; + bool operator!=(slongdigit_t) const; + bool operator<(slongdigit_t) const; + bool operator>(slongdigit_t) const; + bool operator<=(slongdigit_t) const; + bool operator>=(slongdigit_t) const; + + int compare(const Bigint&) const; //-1: <; 0: ==; 1: > + int compare(slongdigit_t) const; + int compareAbs(const Bigint&) const; //-1: <; 0: ==; 1: >; disregards sign + int compareAbs(slongdigit_t) const; + + int bitcount() const; + slongdigit_t lowdigits() const; + + std::vector serialise() const; + void deserialise(const std::vector&); + std::vector bits() const; + + friend std::istream& operator>>(std::istream&,Bigint&); + friend std::ostream& operator<<(std::ostream&,Bigint); + + digit_t _digit(int idx) const; +}; + +Bigint pow(const Bigint &b,const Bigint &ex); + +std::istream& operator>>(std::istream&,Bigint&); +std::ostream& operator<<(std::ostream&,Bigint); diff --git a/biginttest.py b/biginttest.py new file mode 100755 index 0000000..f125953 --- /dev/null +++ b/biginttest.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python3 +import sys, random, subprocess + +ntimes=10000 +maxn=1e100 + +def check(desc,x,y): + if x==y: return + print("{}: {} != {}".format(desc,x,y)) + assert False + +def gendata(): + for _ in range(ntimes): + yield random.randint(0,maxn), random.randint(1,maxn) + +def proctest(): + proc=subprocess.Popen(["./main"],stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=sys.stderr) + + for (a,b) in gendata(): + proc.stdin.write("div {} {}\n".format(a,b).encode("ascii")) + proc.stdin.write("mod {} {}\n".format(a,b).encode("ascii")) + proc.stdin.flush() + + ans=int(proc.stdout.readline()) + check("{}/{}".format(a,b),ans,a//b) + + ans=int(proc.stdout.readline()) + check("{}%{}".format(a,b),ans,a%b) + + proc.kill() + +def justprint(): + for (a,b) in gendata(): + print("div {} {}".format(a,b)) + print("mod {} {}".format(a,b)) + +#justprint() +proctest() diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..ce1573f --- /dev/null +++ b/main.cpp @@ -0,0 +1,141 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "bigint.h" +#include "numalgo.h" +#include "rsa.h" + +using namespace std; + +class eof_error : public runtime_error{ +public: + eof_error() + :runtime_error("EOF"){} +}; + +int64_t rand64(){ + return ((int64_t)rand()<<32)+(((int64_t)rand()%2)<<31)+rand(); +} + +Bigint readevalexpr(istream &is){ + Bigint a; + is>>a; + if(is.eof())throw eof_error(); + // cerr<<"Read "<>s; + assert(!is.fail()); + a=readevalexpr(is); + Bigint b=readevalexpr(is); + //cerr<<"Operation "<>bi; + assert(bi==Bigint(n)); + } + } +#endif + +#if 1 + { + string s="4405994068155852661780322209877856931246944549396705884037139443014164958640201650440984581318995014"; + istringstream iss(s); + Bigint bi; + iss>>bi; + uint32_t digs[11]={1752788038,953502834,2175607868,1627159508,1754291416,1207689192,3196357285,3165170272,3313904421,3194703103,2062}; + for(int i=0;i<11;i++)assert(bi._digit(i)==digs[i]); + ostringstream oss; + oss<=b)a=a.divmod(b).second; + else b=b.divmod(a).second; + } +} + +Bigint egcd(const Bigint &a,const Bigint &b,Bigint &x,Bigint &y){ + Bigint x2(0),y2(1),r(a),r2(b); + x=1; y=0; + //cerr< +#include "numalgo.h" +#include "rsa.h" + +Bigint encrypt(const PublicKey &pubkey,Bigint msg){ + assert(msg>1&&msg