aboutsummaryrefslogtreecommitdiff
path: root/bigint.h
blob: a3c5be38ee81cd747dd4a8369178898bf5d64d14 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#pragma once

#include <iostream>
#include <string>
#include <vector>
#include <utility>
#include <cstdint>

class Bigint{
public:
	typedef uint32_t digit_t;
	typedef int32_t sdigit_t;
	typedef uint64_t longdigit_t;
	typedef int64_t slongdigit_t;
	static const int digit_bits=8*sizeof(digit_t);

private:
	std::vector<digit_t> 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<Bigint,Bigint> divmod(const Bigint&,int depth,int maxdepth) const; //ignores all signs

public:
	Bigint();
	Bigint(const Bigint&)=default;
	Bigint(Bigint&&);
	explicit Bigint(const std::string&);
	explicit Bigint(sdigit_t);
	explicit Bigint(digit_t);
	explicit Bigint(slongdigit_t);
	explicit Bigint(longdigit_t);

	Bigint& operator=(const Bigint&)=default;
	Bigint& operator=(Bigint&&);
	Bigint& operator=(slongdigit_t);
	Bigint& operator=(longdigit_t);
	Bigint& operator=(sdigit_t);
	Bigint& operator=(digit_t);

	Bigint& operator+=(const Bigint&);
	Bigint& operator-=(const Bigint&);
	Bigint& operator*=(const Bigint&);
	Bigint& operator+=(slongdigit_t);
	Bigint& operator-=(slongdigit_t);
	Bigint& operator*=(slongdigit_t);
	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+(slongdigit_t) const;
	Bigint operator-(slongdigit_t) const;
	Bigint operator*(slongdigit_t) const;
	Bigint operator<<(int) const;
	Bigint operator>>(int) const;

	//Uses *mathematical* division-with-remainder.
	//If we look at {q,r} = x.divmod(y), then x = q*y + r, and 0<=r<|q|. This is *not* compatible with many other
	//programming languages (and, for that matter, the C++ built-in behaviour).
	std::pair<Bigint,Bigint> 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;
	bool even() const;
	bool odd() const;

	std::string serialiseMantissa() const; //stores everything but the sign

	//restores non-negative number; can throw invalid_argument
	void deserialiseMantissa(const std::string&);
	std::vector<bool> bits() const;

	friend std::istream& operator>>(std::istream&,Bigint&);
	friend std::ostream& operator<<(std::ostream&,Bigint);

	digit_t _digit(int idx) const;


	static Bigint mone;
	static Bigint zero;
	static Bigint one;
	static Bigint two;
};

std::istream& operator>>(std::istream&,Bigint&);
std::ostream& operator<<(std::ostream&,Bigint);