forked from ethereum/serpent
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbignum.cpp
More file actions
114 lines (102 loc) · 3.42 KB
/
bignum.cpp
File metadata and controls
114 lines (102 loc) · 3.42 KB
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
#include <stdio.h>
#include <iostream>
#include <vector>
#include <map>
#include "bignum.h"
//Integer to string conversion
std::string unsignedToDecimal(unsigned branch) {
if (branch < 10) return nums.substr(branch, 1);
else return unsignedToDecimal(branch / 10) + nums.substr(branch % 10, 1);
}
//Prepend zeros if needed
static std::string prependZeros(const std::string &source, int how_many) {
std::string prefix = "";
for (int i = 0; i < how_many; ++i) {
prefix += "0";
}
return prefix + source;
}
//Add two strings representing decimal values
std::string decimalAdd(const std::string &a, const std::string &b) {
std::string o = prependZeros(a, b.length() - a.length());
std::string c = prependZeros(b, a.length() - b.length());
bool carry = false;
for (int i = o.length() - 1; i >= 0; i--) {
o[i] = o[i] + c[i] - '0';
if (carry) o[i]++;
carry = false;
if (o[i] > '9') {
o[i] -= 10;
carry = true;
}
}
if (carry) o = "1" + o;
return o;
}
//Helper function for decimalMul
static std::string decimalDigitMul(const std::string &a, int dig) {
if (dig == 0) return "0";
else return decimalAdd(a, decimalDigitMul(a, dig - 1));
}
//Multiply two strings representing decimal values
std::string decimalMul(const std::string &a, const std::string &b) {
std::string o = "0";
std::string n;
for (unsigned i = 0; i < b.length(); i++) {
n = decimalDigitMul(a, b[i] - '0');
if (n != "0") {
for (unsigned j = i + 1; j < b.length(); j++) n += "0";
}
o = decimalAdd(o, n);
}
return o;
}
//Is a greater than b? Flag allows equality
bool decimalGt(const std::string &a, const std::string &b, bool eqAllowed) {
if (a == b) return eqAllowed;
return (a.length() > b.length()) || (a.length() >= b.length() && a > b);
}
//Remove leading zeros if needed
static std::string removeRedundantLeadingZeros(const std::string &s) {
int n_zeros = 0;
for (int i = 0; i < s.size() - 1 && s[i] == '0'; ++i)
n_zeros++;
return s.substr(n_zeros);
}
//Subtract the two strings representing decimal values
std::string decimalSub(const std::string &a, const std::string &b) {
if (b == "0") return a;
if (b == a) return "0";
std::string c = prependZeros(b, a.length() - b.length());
for (unsigned i = 0; i < c.length(); i++) c[i] = '0' + ('9' - c[i]);
std::string o = decimalAdd(decimalAdd(a, c).substr(1), "1");
return removeRedundantLeadingZeros(o);
}
//Divide the two strings representing decimal values
std::string decimalDiv(std::string a, std::string b) {
std::string c = b;
if (decimalGt(c, a)) return "0";
int zeroes = -1;
while (decimalGt(a, c, true)) {
zeroes += 1;
c = c + "0";
}
c = c.substr(0, c.size() - 1);
std::string quot = "0";
while (decimalGt(a, c, true)) {
a = decimalSub(a, c);
quot = decimalAdd(quot, "1");
}
for (int i = 0; i < zeroes; i++) quot += "0";
return decimalAdd(quot, decimalDiv(a, b));
}
//Modulo the two strings representing decimal values
std::string decimalMod(const std::string &a, const std::string &b) {
return decimalSub(a, decimalMul(decimalDiv(a, b), b));
}
//String to int conversion
unsigned decimalToUnsigned(const std::string &a) {
if (a.size() == 0) return 0;
else return (a[a.size() - 1] - '0')
+ decimalToUnsigned(a.substr(0,a.size()-1)) * 10;
}