Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
BigInt.cpp@14:5a1852dac7f7, 2014-03-06 (annotated)
- Committer:
- feb11
- Date:
- Thu Mar 06 11:28:18 2014 +0000
- Revision:
- 14:5a1852dac7f7
- Parent:
- 13:d0b4d7cfeb98
- Child:
- 15:85a6bd4539eb
export function done
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| feb11 | 0:9d554894785b | 1 | #include "BigInt.h" |
| feb11 | 0:9d554894785b | 2 | #include <string.h> |
| feb11 | 0:9d554894785b | 3 | #include <stdio.h> |
| feb11 | 0:9d554894785b | 4 | #include <stdlib.h> |
| feb11 | 0:9d554894785b | 5 | #include <iostream> |
| feb11 | 0:9d554894785b | 6 | #include <climits> |
| feb11 | 9:3c191fa04f6e | 7 | #include <cassert> |
| feb11 | 10:116e201f7d89 | 8 | #include <algorithm> |
| feb11 | 0:9d554894785b | 9 | |
| feb11 | 0:9d554894785b | 10 | static uint32_t num(const uint32_t a) |
| feb11 | 0:9d554894785b | 11 | { |
| feb11 | 0:9d554894785b | 12 | return a/4 + (a%4 ? 1:0); |
| feb11 | 0:9d554894785b | 13 | } |
| feb11 | 10:116e201f7d89 | 14 | |
| feb11 | 10:116e201f7d89 | 15 | |
| feb11 | 0:9d554894785b | 16 | BigInt::BigInt(): |
| feb11 | 0:9d554894785b | 17 | size(0), |
| feb11 | 0:9d554894785b | 18 | bits(0) |
| feb11 | 0:9d554894785b | 19 | { |
| feb11 | 0:9d554894785b | 20 | } |
| feb11 | 0:9d554894785b | 21 | |
| feb11 | 2:1001793a090d | 22 | BigInt::BigInt(const uint32_t a) |
| feb11 | 2:1001793a090d | 23 | { |
| feb11 | 2:1001793a090d | 24 | if(a >> 24) |
| feb11 | 2:1001793a090d | 25 | size = 4; |
| feb11 | 2:1001793a090d | 26 | else if(a >> 16) |
| feb11 | 2:1001793a090d | 27 | size = 3; |
| feb11 | 2:1001793a090d | 28 | else if(a >> 8) |
| feb11 | 2:1001793a090d | 29 | size = 2; |
| feb11 | 2:1001793a090d | 30 | else |
| feb11 | 2:1001793a090d | 31 | size = 1; |
| feb11 | 2:1001793a090d | 32 | bits = new uint32_t[1]; |
| feb11 | 2:1001793a090d | 33 | bits[0] = a; |
| feb11 | 2:1001793a090d | 34 | } |
| feb11 | 2:1001793a090d | 35 | |
| feb11 | 0:9d554894785b | 36 | BigInt::BigInt(const BigInt &a): |
| feb11 | 0:9d554894785b | 37 | size(a.size) |
| feb11 | 0:9d554894785b | 38 | { |
| feb11 | 0:9d554894785b | 39 | uint32_t l = num(size); |
| feb11 | 0:9d554894785b | 40 | bits = new uint32_t[l]; |
| feb11 | 0:9d554894785b | 41 | for(int i = 0; i < l; ++i) |
| feb11 | 0:9d554894785b | 42 | bits[i] = a.bits[i]; |
| feb11 | 0:9d554894785b | 43 | } |
| feb11 | 0:9d554894785b | 44 | |
| feb11 | 0:9d554894785b | 45 | |
| feb11 | 0:9d554894785b | 46 | BigInt::~BigInt() |
| feb11 | 0:9d554894785b | 47 | { |
| feb11 | 10:116e201f7d89 | 48 | if(size) |
| feb11 | 9:3c191fa04f6e | 49 | { |
| feb11 | 0:9d554894785b | 50 | delete[] bits; |
| feb11 | 9:3c191fa04f6e | 51 | } |
| feb11 | 0:9d554894785b | 52 | } |
| feb11 | 0:9d554894785b | 53 | |
| feb11 | 0:9d554894785b | 54 | BigInt& BigInt::operator=(const BigInt& a) |
| feb11 | 0:9d554894785b | 55 | { |
| feb11 | 0:9d554894785b | 56 | size = a.size; |
| feb11 | 0:9d554894785b | 57 | uint32_t l = num(size); |
| feb11 | 0:9d554894785b | 58 | if(bits) |
| feb11 | 0:9d554894785b | 59 | delete[] bits; |
| feb11 | 0:9d554894785b | 60 | bits = new uint32_t[l]; |
| feb11 | 0:9d554894785b | 61 | for(int i = 0; i < l; ++i) |
| feb11 | 0:9d554894785b | 62 | bits[i] = a.bits[i]; |
| feb11 | 0:9d554894785b | 63 | return *this; |
| feb11 | 0:9d554894785b | 64 | } |
| feb11 | 0:9d554894785b | 65 | |
| feb11 | 13:d0b4d7cfeb98 | 66 | void BigInt::importData(uint8_t *data, uint32_t length) |
| feb11 | 0:9d554894785b | 67 | { |
| feb11 | 0:9d554894785b | 68 | size = length; |
| feb11 | 0:9d554894785b | 69 | size_t l = size/4; |
| feb11 | 0:9d554894785b | 70 | if(size % 4 != 0) |
| feb11 | 0:9d554894785b | 71 | l++; |
| feb11 | 0:9d554894785b | 72 | if(bits) |
| feb11 | 0:9d554894785b | 73 | delete[] bits; |
| feb11 | 0:9d554894785b | 74 | bits = new uint32_t[l]; |
| feb11 | 0:9d554894785b | 75 | memset(bits, 0, sizeof(uint32_t)*l); |
| feb11 | 4:773aed3156c5 | 76 | for(int i = length-1; i >=0; --i) |
| feb11 | 0:9d554894785b | 77 | bits[i/4] |= data[i] << ((i%4)*8); |
| feb11 | 0:9d554894785b | 78 | } |
| feb11 | 0:9d554894785b | 79 | |
| feb11 | 13:d0b4d7cfeb98 | 80 | void BigInt::exportData(uint8_t *data, uint32_t length) |
| feb11 | 13:d0b4d7cfeb98 | 81 | { |
| feb11 | 13:d0b4d7cfeb98 | 82 | assert(isValid() && data != 0); |
| feb11 | 13:d0b4d7cfeb98 | 83 | |
| feb11 | 14:5a1852dac7f7 | 84 | if(length < size) |
| feb11 | 14:5a1852dac7f7 | 85 | return; |
| feb11 | 14:5a1852dac7f7 | 86 | uint32_t offset = length-size; |
| feb11 | 14:5a1852dac7f7 | 87 | memset(data, 0, offset); |
| feb11 | 14:5a1852dac7f7 | 88 | for(int i = size-1; i >= 0; --i) |
| feb11 | 14:5a1852dac7f7 | 89 | data[offset+size-1-i] = bits[i/4] >> ((i%4)*8); |
| feb11 | 13:d0b4d7cfeb98 | 90 | } |
| feb11 | 13:d0b4d7cfeb98 | 91 | |
| feb11 | 0:9d554894785b | 92 | BigInt operator+(const BigInt &a, const BigInt& b) |
| feb11 | 0:9d554894785b | 93 | { |
| feb11 | 9:3c191fa04f6e | 94 | assert(a.isValid() && b.isValid()); |
| feb11 | 9:3c191fa04f6e | 95 | |
| feb11 | 0:9d554894785b | 96 | BigInt result; |
| feb11 | 9:3c191fa04f6e | 97 | |
| feb11 | 0:9d554894785b | 98 | result.size = a.size > b.size ? a.size : b.size; |
| feb11 | 0:9d554894785b | 99 | size_t l = result.size/4; |
| feb11 | 0:9d554894785b | 100 | if(result.size % 4 != 0) |
| feb11 | 0:9d554894785b | 101 | l++; |
| feb11 | 0:9d554894785b | 102 | result.bits = new uint32_t[l]; |
| feb11 | 0:9d554894785b | 103 | memset(result.bits, 0, sizeof(uint32_t)*l); |
| feb11 | 0:9d554894785b | 104 | uint32_t al = num(a.size); |
| feb11 | 0:9d554894785b | 105 | uint32_t bl = num(b.size); |
| feb11 | 0:9d554894785b | 106 | uint32_t carry = 0; |
| feb11 | 0:9d554894785b | 107 | for(int i = 0; i < l; ++i) |
| feb11 | 0:9d554894785b | 108 | { |
| feb11 | 0:9d554894785b | 109 | uint32_t tmpA = 0, tmpB = 0; |
| feb11 | 0:9d554894785b | 110 | if(i < al) |
| feb11 | 0:9d554894785b | 111 | tmpA = a.bits[i]; |
| feb11 | 0:9d554894785b | 112 | if(i < bl) |
| feb11 | 0:9d554894785b | 113 | tmpB = b.bits[i]; |
| feb11 | 0:9d554894785b | 114 | result.bits[i] = tmpA + tmpB + carry; |
| feb11 | 10:116e201f7d89 | 115 | carry = result.bits[i] < std::max(tmpA, tmpB); |
| feb11 | 0:9d554894785b | 116 | } |
| feb11 | 0:9d554894785b | 117 | if(carry) |
| feb11 | 0:9d554894785b | 118 | { |
| feb11 | 0:9d554894785b | 119 | result.size++; |
| feb11 | 0:9d554894785b | 120 | if(result.size > l*4) |
| feb11 | 0:9d554894785b | 121 | { |
| feb11 | 0:9d554894785b | 122 | l++; |
| feb11 | 0:9d554894785b | 123 | result.bits = (uint32_t*)realloc(result.bits, l * sizeof(uint32_t)); |
| feb11 | 0:9d554894785b | 124 | result.bits[l-1] = 0x00000001; |
| feb11 | 0:9d554894785b | 125 | } |
| feb11 | 0:9d554894785b | 126 | else |
| feb11 | 0:9d554894785b | 127 | { |
| feb11 | 0:9d554894785b | 128 | result.bits[l-1] += 1 << (8 *((result.size-1)%4)); |
| feb11 | 0:9d554894785b | 129 | } |
| feb11 | 0:9d554894785b | 130 | } |
| feb11 | 0:9d554894785b | 131 | |
| feb11 | 0:9d554894785b | 132 | return result; |
| feb11 | 0:9d554894785b | 133 | } |
| feb11 | 0:9d554894785b | 134 | |
| feb11 | 0:9d554894785b | 135 | BigInt& BigInt::operator+=(const BigInt &b) |
| feb11 | 0:9d554894785b | 136 | { |
| feb11 | 0:9d554894785b | 137 | return (*this = (*this) + b); |
| feb11 | 0:9d554894785b | 138 | } |
| feb11 | 0:9d554894785b | 139 | |
| feb11 | 0:9d554894785b | 140 | BigInt& BigInt::operator++() |
| feb11 | 0:9d554894785b | 141 | { |
| feb11 | 3:3fa3ceb0c69d | 142 | return (*this += 1); |
| feb11 | 0:9d554894785b | 143 | } |
| feb11 | 0:9d554894785b | 144 | |
| feb11 | 0:9d554894785b | 145 | BigInt BigInt::operator++(int) |
| feb11 | 0:9d554894785b | 146 | { |
| feb11 | 0:9d554894785b | 147 | BigInt t = *this; |
| feb11 | 3:3fa3ceb0c69d | 148 | *this += 1; |
| feb11 | 0:9d554894785b | 149 | return t; |
| feb11 | 0:9d554894785b | 150 | } |
| feb11 | 0:9d554894785b | 151 | |
| feb11 | 0:9d554894785b | 152 | // a - b, if b >= a, returns 0 |
| feb11 | 0:9d554894785b | 153 | // No negative number allowed |
| feb11 | 0:9d554894785b | 154 | BigInt operator-(const BigInt &a, const BigInt& b) |
| feb11 | 0:9d554894785b | 155 | { |
| feb11 | 9:3c191fa04f6e | 156 | assert(a.isValid() && b.isValid()); |
| feb11 | 9:3c191fa04f6e | 157 | |
| feb11 | 0:9d554894785b | 158 | BigInt result; |
| feb11 | 0:9d554894785b | 159 | |
| feb11 | 0:9d554894785b | 160 | if(b >= a) |
| feb11 | 0:9d554894785b | 161 | { |
| feb11 | 3:3fa3ceb0c69d | 162 | return result = 0; |
| feb11 | 0:9d554894785b | 163 | } |
| feb11 | 0:9d554894785b | 164 | else |
| feb11 | 0:9d554894785b | 165 | { |
| feb11 | 0:9d554894785b | 166 | result.size = a.size; |
| feb11 | 0:9d554894785b | 167 | uint32_t l = num(a.size); |
| feb11 | 0:9d554894785b | 168 | result.bits = new uint32_t[l]; |
| feb11 | 0:9d554894785b | 169 | memset(result.bits, 0, sizeof(uint32_t)*l); |
| feb11 | 0:9d554894785b | 170 | uint32_t bl = num(b.size); |
| feb11 | 0:9d554894785b | 171 | uint8_t borrow = 0; |
| feb11 | 0:9d554894785b | 172 | for(uint32_t i = 0; i < l; ++i) |
| feb11 | 0:9d554894785b | 173 | { |
| feb11 | 0:9d554894785b | 174 | uint32_t tmpA = a.bits[i], tmpB = 0; |
| feb11 | 0:9d554894785b | 175 | if(i < bl) |
| feb11 | 0:9d554894785b | 176 | tmpB = b.bits[i]; |
| feb11 | 0:9d554894785b | 177 | if(borrow) |
| feb11 | 0:9d554894785b | 178 | { |
| feb11 | 0:9d554894785b | 179 | if(tmpA == 0) |
| feb11 | 0:9d554894785b | 180 | tmpA = ULONG_MAX; |
| feb11 | 0:9d554894785b | 181 | else |
| feb11 | 0:9d554894785b | 182 | --tmpA; |
| feb11 | 0:9d554894785b | 183 | |
| feb11 | 0:9d554894785b | 184 | if(tmpA < tmpB) |
| feb11 | 0:9d554894785b | 185 | result.bits[i] = tmpA + 1 + (ULONG_MAX - tmpB); |
| feb11 | 0:9d554894785b | 186 | else |
| feb11 | 0:9d554894785b | 187 | result.bits[i] = tmpA - tmpB; |
| feb11 | 0:9d554894785b | 188 | |
| feb11 | 0:9d554894785b | 189 | if(a.bits[i] != 0 && tmpA > tmpB) |
| feb11 | 0:9d554894785b | 190 | borrow = 0; |
| feb11 | 0:9d554894785b | 191 | } |
| feb11 | 0:9d554894785b | 192 | else |
| feb11 | 0:9d554894785b | 193 | { |
| feb11 | 0:9d554894785b | 194 | if(tmpA < tmpB) |
| feb11 | 0:9d554894785b | 195 | result.bits[i] = tmpA + 1 + (ULONG_MAX - tmpB); |
| feb11 | 0:9d554894785b | 196 | else |
| feb11 | 0:9d554894785b | 197 | result.bits[i] = tmpA - tmpB; |
| feb11 | 0:9d554894785b | 198 | borrow = tmpA < tmpB; |
| feb11 | 0:9d554894785b | 199 | } |
| feb11 | 0:9d554894785b | 200 | } |
| feb11 | 0:9d554894785b | 201 | |
| feb11 | 9:3c191fa04f6e | 202 | result.trim(); |
| feb11 | 0:9d554894785b | 203 | |
| feb11 | 0:9d554894785b | 204 | return result; |
| feb11 | 0:9d554894785b | 205 | } |
| feb11 | 0:9d554894785b | 206 | } |
| feb11 | 0:9d554894785b | 207 | |
| feb11 | 0:9d554894785b | 208 | BigInt& BigInt::operator-=(const BigInt &b) |
| feb11 | 0:9d554894785b | 209 | { |
| feb11 | 0:9d554894785b | 210 | return (*this = (*this) - b); |
| feb11 | 0:9d554894785b | 211 | } |
| feb11 | 0:9d554894785b | 212 | |
| feb11 | 0:9d554894785b | 213 | BigInt& BigInt::operator--() |
| feb11 | 0:9d554894785b | 214 | { |
| feb11 | 3:3fa3ceb0c69d | 215 | return (*this -= 1); |
| feb11 | 0:9d554894785b | 216 | } |
| feb11 | 0:9d554894785b | 217 | |
| feb11 | 0:9d554894785b | 218 | BigInt BigInt::operator--(int) |
| feb11 | 0:9d554894785b | 219 | { |
| feb11 | 0:9d554894785b | 220 | BigInt t = *this; |
| feb11 | 3:3fa3ceb0c69d | 221 | *this -= 1; |
| feb11 | 0:9d554894785b | 222 | return t; |
| feb11 | 0:9d554894785b | 223 | } |
| feb11 | 3:3fa3ceb0c69d | 224 | |
| feb11 | 1:00f2c40d46ed | 225 | BigInt operator*(const BigInt &a, const BigInt& b) |
| feb11 | 1:00f2c40d46ed | 226 | { |
| feb11 | 9:3c191fa04f6e | 227 | assert(a.isValid() && b.isValid()); |
| feb11 | 9:3c191fa04f6e | 228 | |
| feb11 | 1:00f2c40d46ed | 229 | // if a == 0 or b == 0 then result = 0 |
| feb11 | 1:00f2c40d46ed | 230 | if(!a || !b) |
| feb11 | 12:a436f15b58b6 | 231 | return 0; |
| feb11 | 1:00f2c40d46ed | 232 | |
| feb11 | 1:00f2c40d46ed | 233 | // if a == 1, then result = b |
| feb11 | 3:3fa3ceb0c69d | 234 | if(a == 1) |
| feb11 | 12:a436f15b58b6 | 235 | return b; |
| feb11 | 1:00f2c40d46ed | 236 | |
| feb11 | 1:00f2c40d46ed | 237 | // if b == 1, then result = a |
| feb11 | 3:3fa3ceb0c69d | 238 | if(b == 1) |
| feb11 | 12:a436f15b58b6 | 239 | return a; |
| feb11 | 12:a436f15b58b6 | 240 | |
| feb11 | 12:a436f15b58b6 | 241 | BigInt result; |
| feb11 | 4:773aed3156c5 | 242 | result.size = a.size + b.size; |
| feb11 | 4:773aed3156c5 | 243 | result.bits = new uint32_t[num(result.size)]; |
| feb11 | 12:a436f15b58b6 | 244 | memset(result.bits, 0, sizeof(uint32_t)*num(result.size)); |
| feb11 | 11:2f16a220ebbb | 245 | for(int i = 0; i < num(a.size); ++i) |
| feb11 | 4:773aed3156c5 | 246 | { |
| feb11 | 11:2f16a220ebbb | 247 | uint64_t carry = 0; |
| feb11 | 11:2f16a220ebbb | 248 | for(int j = 0; j < num(b.size); ++j) |
| feb11 | 11:2f16a220ebbb | 249 | { |
| feb11 | 11:2f16a220ebbb | 250 | uint64_t tmp = (uint64_t)a.bits[i] * (uint64_t)b.bits[j] + carry; |
| feb11 | 12:a436f15b58b6 | 251 | uint32_t t = result.bits[i+j]; |
| feb11 | 11:2f16a220ebbb | 252 | result.bits[i+j] += tmp; |
| feb11 | 12:a436f15b58b6 | 253 | carry = tmp >> 32; |
| feb11 | 12:a436f15b58b6 | 254 | if(t > result.bits[i+j]) |
| feb11 | 12:a436f15b58b6 | 255 | ++carry; |
| feb11 | 11:2f16a220ebbb | 256 | } |
| feb11 | 11:2f16a220ebbb | 257 | if(carry != 0) |
| feb11 | 11:2f16a220ebbb | 258 | result.bits[i+num(b.size)] += carry; |
| feb11 | 4:773aed3156c5 | 259 | } |
| feb11 | 4:773aed3156c5 | 260 | |
| feb11 | 9:3c191fa04f6e | 261 | result.trim(); |
| feb11 | 1:00f2c40d46ed | 262 | |
| feb11 | 1:00f2c40d46ed | 263 | return result; |
| feb11 | 1:00f2c40d46ed | 264 | } |
| feb11 | 1:00f2c40d46ed | 265 | |
| feb11 | 1:00f2c40d46ed | 266 | BigInt& BigInt::operator*=(const BigInt &b) |
| feb11 | 1:00f2c40d46ed | 267 | { |
| feb11 | 1:00f2c40d46ed | 268 | return (*this = (*this) * b); |
| feb11 | 1:00f2c40d46ed | 269 | } |
| feb11 | 1:00f2c40d46ed | 270 | |
| feb11 | 10:116e201f7d89 | 271 | |
| feb11 | 11:2f16a220ebbb | 272 | BigInt operator/(const BigInt &a, const BigInt &b) |
| feb11 | 10:116e201f7d89 | 273 | { |
| feb11 | 10:116e201f7d89 | 274 | assert(a.isValid() && b.isValid() && b != 0); |
| feb11 | 10:116e201f7d89 | 275 | if(b == 1) |
| feb11 | 10:116e201f7d89 | 276 | return a; |
| feb11 | 10:116e201f7d89 | 277 | if(a < b) |
| feb11 | 10:116e201f7d89 | 278 | return 0; |
| feb11 | 10:116e201f7d89 | 279 | if(a == b) |
| feb11 | 10:116e201f7d89 | 280 | return 1; |
| feb11 | 11:2f16a220ebbb | 281 | BigInt u = a; |
| feb11 | 11:2f16a220ebbb | 282 | int m = a.numBits() - b.numBits(); |
| feb11 | 10:116e201f7d89 | 283 | BigInt q = 0; |
| feb11 | 12:a436f15b58b6 | 284 | BigInt tmp = b; |
| feb11 | 12:a436f15b58b6 | 285 | tmp <<= m; |
| feb11 | 10:116e201f7d89 | 286 | for(int j = m; j >= 0; --j) |
| feb11 | 10:116e201f7d89 | 287 | { |
| feb11 | 11:2f16a220ebbb | 288 | if(tmp <= u) |
| feb11 | 10:116e201f7d89 | 289 | { |
| feb11 | 11:2f16a220ebbb | 290 | u -= tmp; |
| feb11 | 11:2f16a220ebbb | 291 | BigInt tmp2 = 1; |
| feb11 | 11:2f16a220ebbb | 292 | tmp2 <<= j; |
| feb11 | 12:a436f15b58b6 | 293 | q += tmp2; |
| feb11 | 10:116e201f7d89 | 294 | } |
| feb11 | 10:116e201f7d89 | 295 | tmp >>= 1; |
| feb11 | 10:116e201f7d89 | 296 | } |
| feb11 | 11:2f16a220ebbb | 297 | q.trim(); |
| feb11 | 11:2f16a220ebbb | 298 | return q; |
| feb11 | 10:116e201f7d89 | 299 | } |
| feb11 | 10:116e201f7d89 | 300 | |
| feb11 | 10:116e201f7d89 | 301 | BigInt& BigInt::operator/=(const BigInt &b) |
| feb11 | 10:116e201f7d89 | 302 | { |
| feb11 | 10:116e201f7d89 | 303 | return (*this = (*this) / b); |
| feb11 | 10:116e201f7d89 | 304 | } |
| feb11 | 10:116e201f7d89 | 305 | |
| feb11 | 1:00f2c40d46ed | 306 | BigInt operator>>(const BigInt &a, const uint32_t m) |
| feb11 | 1:00f2c40d46ed | 307 | { |
| feb11 | 9:3c191fa04f6e | 308 | assert(a.isValid()); |
| feb11 | 9:3c191fa04f6e | 309 | |
| feb11 | 12:a436f15b58b6 | 310 | if(m == 0) |
| feb11 | 12:a436f15b58b6 | 311 | return a; |
| feb11 | 12:a436f15b58b6 | 312 | if(m/8 >= a.size) |
| feb11 | 12:a436f15b58b6 | 313 | return 0; |
| feb11 | 12:a436f15b58b6 | 314 | |
| feb11 | 1:00f2c40d46ed | 315 | BigInt result; |
| feb11 | 1:00f2c40d46ed | 316 | result.size = a.size - m/8; |
| feb11 | 1:00f2c40d46ed | 317 | result.bits = new uint32_t[num(result.size)]; |
| feb11 | 1:00f2c40d46ed | 318 | uint8_t s = m%32; |
| feb11 | 1:00f2c40d46ed | 319 | for(uint32_t i = 0; i < num(result.size); ++i) |
| feb11 | 1:00f2c40d46ed | 320 | { |
| feb11 | 1:00f2c40d46ed | 321 | if(m/32+i+1 < num(a.size)) |
| feb11 | 1:00f2c40d46ed | 322 | result.bits[i] = (a.bits[m/32+i+1] << (32-s)) | (a.bits[m/32+i] >> s); |
| feb11 | 1:00f2c40d46ed | 323 | else |
| feb11 | 1:00f2c40d46ed | 324 | result.bits[i] = (a.bits[m/32+i] >> s); |
| feb11 | 1:00f2c40d46ed | 325 | } |
| feb11 | 1:00f2c40d46ed | 326 | |
| feb11 | 10:116e201f7d89 | 327 | result.trim(); |
| feb11 | 10:116e201f7d89 | 328 | |
| feb11 | 1:00f2c40d46ed | 329 | return result; |
| feb11 | 1:00f2c40d46ed | 330 | } |
| feb11 | 1:00f2c40d46ed | 331 | |
| feb11 | 1:00f2c40d46ed | 332 | BigInt& BigInt::operator>>=(const uint32_t m) |
| feb11 | 1:00f2c40d46ed | 333 | { |
| feb11 | 1:00f2c40d46ed | 334 | return *this = *this >> m; |
| feb11 | 1:00f2c40d46ed | 335 | } |
| feb11 | 1:00f2c40d46ed | 336 | |
| feb11 | 1:00f2c40d46ed | 337 | BigInt operator<<(const BigInt &a, const uint32_t m) |
| feb11 | 1:00f2c40d46ed | 338 | { |
| feb11 | 9:3c191fa04f6e | 339 | assert(a.isValid()); |
| feb11 | 9:3c191fa04f6e | 340 | |
| feb11 | 1:00f2c40d46ed | 341 | BigInt result; |
| feb11 | 9:3c191fa04f6e | 342 | |
| feb11 | 1:00f2c40d46ed | 343 | if(m == 0) |
| feb11 | 1:00f2c40d46ed | 344 | return result = a; |
| feb11 | 1:00f2c40d46ed | 345 | |
| feb11 | 1:00f2c40d46ed | 346 | result.size = m/8 + a.size; |
| feb11 | 1:00f2c40d46ed | 347 | uint32_t h = a.bits[num(a.size)-1]; |
| feb11 | 12:a436f15b58b6 | 348 | if((m%32)%8 != 0) |
| feb11 | 1:00f2c40d46ed | 349 | ++result.size; |
| feb11 | 1:00f2c40d46ed | 350 | uint32_t l = num(result.size); |
| feb11 | 1:00f2c40d46ed | 351 | result.bits = new uint32_t[l]; |
| feb11 | 1:00f2c40d46ed | 352 | memset(result.bits, 0, sizeof(uint32_t)*l); |
| feb11 | 1:00f2c40d46ed | 353 | uint32_t s = m % 32; |
| feb11 | 1:00f2c40d46ed | 354 | for(uint32_t i = 0; i < num(a.size); ++i) |
| feb11 | 1:00f2c40d46ed | 355 | { |
| feb11 | 1:00f2c40d46ed | 356 | if(i == 0) |
| feb11 | 1:00f2c40d46ed | 357 | result.bits[m/32+i] = a.bits[i] << s; |
| feb11 | 1:00f2c40d46ed | 358 | else |
| feb11 | 1:00f2c40d46ed | 359 | result.bits[m/32+i] = (a.bits[i] << s) | (a.bits[i-1] >> (32-s)); |
| feb11 | 1:00f2c40d46ed | 360 | } |
| feb11 | 12:a436f15b58b6 | 361 | if(a.bits[num(a.size)-1] && s != 0) |
| feb11 | 12:a436f15b58b6 | 362 | result.bits[m/32+num(result.size)-1] |= a.bits[num(a.size)-1] >> (32-s); |
| feb11 | 1:00f2c40d46ed | 363 | |
| feb11 | 12:a436f15b58b6 | 364 | result.trim(); |
| feb11 | 1:00f2c40d46ed | 365 | |
| feb11 | 1:00f2c40d46ed | 366 | return result; |
| feb11 | 1:00f2c40d46ed | 367 | } |
| feb11 | 1:00f2c40d46ed | 368 | |
| feb11 | 1:00f2c40d46ed | 369 | BigInt& BigInt::operator<<=(const uint32_t m) |
| feb11 | 1:00f2c40d46ed | 370 | { |
| feb11 | 1:00f2c40d46ed | 371 | return (*this = *this << m); |
| feb11 | 1:00f2c40d46ed | 372 | } |
| feb11 | 0:9d554894785b | 373 | |
| feb11 | 5:beeb31f340a7 | 374 | BigInt operator%(const BigInt &a, const BigInt &b) |
| feb11 | 5:beeb31f340a7 | 375 | { |
| feb11 | 10:116e201f7d89 | 376 | assert(a.isValid() && b.isValid() && b > 0); |
| feb11 | 12:a436f15b58b6 | 377 | return a - (a/b)*b; |
| feb11 | 5:beeb31f340a7 | 378 | } |
| feb11 | 5:beeb31f340a7 | 379 | |
| feb11 | 5:beeb31f340a7 | 380 | BigInt& BigInt::operator%=(const BigInt &a) |
| feb11 | 5:beeb31f340a7 | 381 | { |
| feb11 | 5:beeb31f340a7 | 382 | return (*this = *this % a); |
| feb11 | 5:beeb31f340a7 | 383 | } |
| feb11 | 5:beeb31f340a7 | 384 | |
| feb11 | 0:9d554894785b | 385 | bool operator==(const BigInt &a, const BigInt &b) |
| feb11 | 0:9d554894785b | 386 | { |
| feb11 | 9:3c191fa04f6e | 387 | assert(a.isValid() && b.isValid()); |
| feb11 | 9:3c191fa04f6e | 388 | |
| feb11 | 0:9d554894785b | 389 | if(a.size != b.size) |
| feb11 | 0:9d554894785b | 390 | return false; |
| feb11 | 0:9d554894785b | 391 | |
| feb11 | 0:9d554894785b | 392 | uint32_t l = num(a.size); |
| feb11 | 0:9d554894785b | 393 | for(int i = 0; i < l; ++i) |
| feb11 | 0:9d554894785b | 394 | if(a.bits[i] != b.bits[i]) |
| feb11 | 0:9d554894785b | 395 | return false; |
| feb11 | 0:9d554894785b | 396 | return true; |
| feb11 | 0:9d554894785b | 397 | } |
| feb11 | 0:9d554894785b | 398 | |
| feb11 | 0:9d554894785b | 399 | bool operator!=(const BigInt &a, const BigInt &b) |
| feb11 | 0:9d554894785b | 400 | { |
| feb11 | 0:9d554894785b | 401 | return ! (a==b); |
| feb11 | 0:9d554894785b | 402 | } |
| feb11 | 0:9d554894785b | 403 | |
| feb11 | 0:9d554894785b | 404 | bool operator<(const BigInt &a, const BigInt &b) |
| feb11 | 0:9d554894785b | 405 | { |
| feb11 | 9:3c191fa04f6e | 406 | assert(a.isValid() && b.isValid()); |
| feb11 | 9:3c191fa04f6e | 407 | |
| feb11 | 0:9d554894785b | 408 | if(a.size < b.size) |
| feb11 | 0:9d554894785b | 409 | return true; |
| feb11 | 0:9d554894785b | 410 | if(a.size > b.size) |
| feb11 | 0:9d554894785b | 411 | return false; |
| feb11 | 0:9d554894785b | 412 | uint32_t l = num(a.size); |
| feb11 | 0:9d554894785b | 413 | for(int i = l-1; i >= 0; --i) |
| feb11 | 12:a436f15b58b6 | 414 | { |
| feb11 | 0:9d554894785b | 415 | if(a.bits[i] < b.bits[i]) |
| feb11 | 0:9d554894785b | 416 | return true; |
| feb11 | 12:a436f15b58b6 | 417 | else if(a.bits[i] > b.bits[i]) |
| feb11 | 12:a436f15b58b6 | 418 | return false; |
| feb11 | 12:a436f15b58b6 | 419 | } |
| feb11 | 0:9d554894785b | 420 | return false; |
| feb11 | 0:9d554894785b | 421 | } |
| feb11 | 0:9d554894785b | 422 | |
| feb11 | 0:9d554894785b | 423 | bool operator<=(const BigInt &a, const BigInt &b) |
| feb11 | 0:9d554894785b | 424 | { |
| feb11 | 9:3c191fa04f6e | 425 | return !(a > b); |
| feb11 | 0:9d554894785b | 426 | } |
| feb11 | 0:9d554894785b | 427 | |
| feb11 | 0:9d554894785b | 428 | bool operator>(const BigInt &a, const BigInt &b) |
| feb11 | 0:9d554894785b | 429 | { |
| feb11 | 9:3c191fa04f6e | 430 | assert(a.isValid() && b.isValid()); |
| feb11 | 9:3c191fa04f6e | 431 | |
| feb11 | 0:9d554894785b | 432 | if(a.size > b.size) |
| feb11 | 0:9d554894785b | 433 | return true; |
| feb11 | 0:9d554894785b | 434 | if(a.size < b.size) |
| feb11 | 0:9d554894785b | 435 | return false; |
| feb11 | 0:9d554894785b | 436 | uint32_t l = num(a.size); |
| feb11 | 0:9d554894785b | 437 | for(int i = l-1; i >= 0; --i) |
| feb11 | 12:a436f15b58b6 | 438 | { |
| feb11 | 0:9d554894785b | 439 | if(a.bits[i] > b.bits[i]) |
| feb11 | 0:9d554894785b | 440 | return true; |
| feb11 | 12:a436f15b58b6 | 441 | else if(a.bits[i] < b.bits[i]) |
| feb11 | 12:a436f15b58b6 | 442 | return false; |
| feb11 | 12:a436f15b58b6 | 443 | } |
| feb11 | 0:9d554894785b | 444 | return false; |
| feb11 | 0:9d554894785b | 445 | } |
| feb11 | 0:9d554894785b | 446 | |
| feb11 | 0:9d554894785b | 447 | bool operator>=(const BigInt &a, const BigInt &b) |
| feb11 | 0:9d554894785b | 448 | { |
| feb11 | 9:3c191fa04f6e | 449 | return !(a < b); |
| feb11 | 0:9d554894785b | 450 | } |
| feb11 | 0:9d554894785b | 451 | |
| feb11 | 1:00f2c40d46ed | 452 | bool operator!(const BigInt &a) |
| feb11 | 0:9d554894785b | 453 | { |
| feb11 | 9:3c191fa04f6e | 454 | assert(a.isValid()); |
| feb11 | 9:3c191fa04f6e | 455 | |
| feb11 | 1:00f2c40d46ed | 456 | if(a.size != 1) |
| feb11 | 0:9d554894785b | 457 | return false; |
| feb11 | 1:00f2c40d46ed | 458 | return a.bits[0] == 0; |
| feb11 | 0:9d554894785b | 459 | } |
| feb11 | 0:9d554894785b | 460 | |
| feb11 | 7:1aad58757705 | 461 | |
| feb11 | 7:1aad58757705 | 462 | BigInt operator&(const BigInt &a, const BigInt &b) |
| feb11 | 7:1aad58757705 | 463 | { |
| feb11 | 9:3c191fa04f6e | 464 | assert(a.isValid() && b.isValid()); |
| feb11 | 9:3c191fa04f6e | 465 | |
| feb11 | 7:1aad58757705 | 466 | BigInt result; |
| feb11 | 7:1aad58757705 | 467 | |
| feb11 | 7:1aad58757705 | 468 | result.size = a.size < b.size ? a.size : b.size; |
| feb11 | 7:1aad58757705 | 469 | uint32_t l = num(result.size); |
| feb11 | 7:1aad58757705 | 470 | result.bits = new uint32_t[l]; |
| feb11 | 7:1aad58757705 | 471 | memset(result.bits, 0, l); |
| feb11 | 7:1aad58757705 | 472 | |
| feb11 | 7:1aad58757705 | 473 | for(uint32_t i = 0; i < l; ++i) |
| feb11 | 7:1aad58757705 | 474 | result.bits[i] = a.bits[i] & b.bits[i]; |
| feb11 | 7:1aad58757705 | 475 | |
| feb11 | 9:3c191fa04f6e | 476 | result.trim(); |
| feb11 | 7:1aad58757705 | 477 | |
| feb11 | 7:1aad58757705 | 478 | return result; |
| feb11 | 7:1aad58757705 | 479 | } |
| feb11 | 7:1aad58757705 | 480 | |
| feb11 | 7:1aad58757705 | 481 | BigInt& BigInt::operator&=(const BigInt &a) |
| feb11 | 7:1aad58757705 | 482 | { |
| feb11 | 7:1aad58757705 | 483 | return (*this = *this & a); |
| feb11 | 7:1aad58757705 | 484 | } |
| feb11 | 7:1aad58757705 | 485 | |
| feb11 | 7:1aad58757705 | 486 | BigInt operator|(const BigInt &a, const BigInt &b) |
| feb11 | 7:1aad58757705 | 487 | { |
| feb11 | 9:3c191fa04f6e | 488 | assert(a.isValid() && b.isValid()); |
| feb11 | 9:3c191fa04f6e | 489 | |
| feb11 | 7:1aad58757705 | 490 | BigInt result; |
| feb11 | 7:1aad58757705 | 491 | |
| feb11 | 7:1aad58757705 | 492 | uint32_t na = num(a.size); |
| feb11 | 7:1aad58757705 | 493 | uint32_t nb = num(b.size); |
| feb11 | 10:116e201f7d89 | 494 | uint32_t l = std::max(na,nb); |
| feb11 | 10:116e201f7d89 | 495 | result.size = std::max(a.size, b.size); |
| feb11 | 7:1aad58757705 | 496 | result.bits = new uint32_t[l]; |
| feb11 | 7:1aad58757705 | 497 | memset(result.bits, 0, l); |
| feb11 | 7:1aad58757705 | 498 | |
| feb11 | 7:1aad58757705 | 499 | for(uint32_t i = 0; i < l; ++i) |
| feb11 | 7:1aad58757705 | 500 | { |
| feb11 | 7:1aad58757705 | 501 | if(i < na && i < nb) |
| feb11 | 7:1aad58757705 | 502 | result.bits[i] = a.bits[i] | b.bits[i]; |
| feb11 | 7:1aad58757705 | 503 | else if(i < na) |
| feb11 | 7:1aad58757705 | 504 | result.bits[i] = a.bits[i]; |
| feb11 | 7:1aad58757705 | 505 | else |
| feb11 | 7:1aad58757705 | 506 | result.bits[i] = b.bits[i]; |
| feb11 | 7:1aad58757705 | 507 | } |
| feb11 | 7:1aad58757705 | 508 | |
| feb11 | 7:1aad58757705 | 509 | return result; |
| feb11 | 7:1aad58757705 | 510 | } |
| feb11 | 7:1aad58757705 | 511 | |
| feb11 | 7:1aad58757705 | 512 | BigInt& BigInt::operator|=(const BigInt &a) |
| feb11 | 7:1aad58757705 | 513 | { |
| feb11 | 7:1aad58757705 | 514 | return (*this = *this | a); |
| feb11 | 7:1aad58757705 | 515 | } |
| feb11 | 8:2a361f1b41da | 516 | |
| feb11 | 8:2a361f1b41da | 517 | BigInt operator^(const BigInt &a, const BigInt &b) |
| feb11 | 8:2a361f1b41da | 518 | { |
| feb11 | 9:3c191fa04f6e | 519 | assert(a.isValid() && b.isValid()); |
| feb11 | 9:3c191fa04f6e | 520 | |
| feb11 | 9:3c191fa04f6e | 521 | |
| feb11 | 8:2a361f1b41da | 522 | BigInt result; |
| feb11 | 8:2a361f1b41da | 523 | |
| feb11 | 8:2a361f1b41da | 524 | uint32_t na = num(a.size); |
| feb11 | 8:2a361f1b41da | 525 | uint32_t nb = num(b.size); |
| feb11 | 10:116e201f7d89 | 526 | uint32_t l = std::max(na,nb); |
| feb11 | 10:116e201f7d89 | 527 | result.size = std::max(a.size, b.size); |
| feb11 | 8:2a361f1b41da | 528 | result.bits = new uint32_t[l]; |
| feb11 | 8:2a361f1b41da | 529 | memset(result.bits, 0, l); |
| feb11 | 7:1aad58757705 | 530 | |
| feb11 | 8:2a361f1b41da | 531 | for(uint32_t i = 0; i < l; ++i) |
| feb11 | 8:2a361f1b41da | 532 | { |
| feb11 | 8:2a361f1b41da | 533 | if(i < na && i < nb) |
| feb11 | 8:2a361f1b41da | 534 | result.bits[i] = a.bits[i] ^ b.bits[i]; |
| feb11 | 8:2a361f1b41da | 535 | else if(i < na) |
| feb11 | 8:2a361f1b41da | 536 | result.bits[i] = a.bits[i]; |
| feb11 | 8:2a361f1b41da | 537 | else |
| feb11 | 8:2a361f1b41da | 538 | result.bits[i] = b.bits[i]; |
| feb11 | 8:2a361f1b41da | 539 | } |
| feb11 | 8:2a361f1b41da | 540 | |
| feb11 | 9:3c191fa04f6e | 541 | result.trim(); |
| feb11 | 9:3c191fa04f6e | 542 | |
| feb11 | 8:2a361f1b41da | 543 | return result; |
| feb11 | 8:2a361f1b41da | 544 | } |
| feb11 | 8:2a361f1b41da | 545 | |
| feb11 | 8:2a361f1b41da | 546 | BigInt& BigInt::operator^=(const BigInt &a) |
| feb11 | 8:2a361f1b41da | 547 | { |
| feb11 | 8:2a361f1b41da | 548 | return (*this = *this ^ a); |
| feb11 | 8:2a361f1b41da | 549 | } |
| feb11 | 9:3c191fa04f6e | 550 | |
| feb11 | 10:116e201f7d89 | 551 | BigInt montgomeryStep(const BigInt &a, const BigInt &b, const BigInt &m, uint32_t r) |
| feb11 | 10:116e201f7d89 | 552 | { |
| feb11 | 10:116e201f7d89 | 553 | BigInt result = 0; |
| feb11 | 10:116e201f7d89 | 554 | BigInt tmp = a; |
| feb11 | 10:116e201f7d89 | 555 | while(r > 0) |
| feb11 | 10:116e201f7d89 | 556 | { |
| feb11 | 10:116e201f7d89 | 557 | if(tmp.bits[0] & 0x01) |
| feb11 | 10:116e201f7d89 | 558 | result += b; |
| feb11 | 10:116e201f7d89 | 559 | |
| feb11 | 10:116e201f7d89 | 560 | if(result.bits[0] & 0x01) |
| feb11 | 10:116e201f7d89 | 561 | result += m; |
| feb11 | 10:116e201f7d89 | 562 | |
| feb11 | 10:116e201f7d89 | 563 | --r; |
| feb11 | 10:116e201f7d89 | 564 | result >>= 1; |
| feb11 | 10:116e201f7d89 | 565 | tmp >>= 1; |
| feb11 | 10:116e201f7d89 | 566 | } |
| feb11 | 10:116e201f7d89 | 567 | return result; |
| feb11 | 10:116e201f7d89 | 568 | } |
| feb11 | 10:116e201f7d89 | 569 | |
| feb11 | 10:116e201f7d89 | 570 | // Implementation using Montgomery algorithm |
| feb11 | 9:3c191fa04f6e | 571 | BigInt modPow(const BigInt &a, const BigInt &expn, const BigInt &modulus) |
| feb11 | 9:3c191fa04f6e | 572 | { |
| feb11 | 9:3c191fa04f6e | 573 | assert(a.isValid() && expn.isValid() && modulus.isValid()); |
| feb11 | 9:3c191fa04f6e | 574 | |
| feb11 | 10:116e201f7d89 | 575 | // precompute R and R^2 |
| feb11 | 10:116e201f7d89 | 576 | uint32_t r = 8*modulus.size; |
| feb11 | 10:116e201f7d89 | 577 | |
| feb11 | 10:116e201f7d89 | 578 | // convert a in montgomery world |
| feb11 | 11:2f16a220ebbb | 579 | BigInt tmp2 = 1; |
| feb11 | 13:d0b4d7cfeb98 | 580 | tmp2 <<= r; |
| feb11 | 11:2f16a220ebbb | 581 | tmp2 *= a; |
| feb11 | 12:a436f15b58b6 | 582 | BigInt montA = tmp2%modulus; |
| feb11 | 10:116e201f7d89 | 583 | BigInt tmp = montA; |
| feb11 | 9:3c191fa04f6e | 584 | BigInt tmpE = expn; |
| feb11 | 10:116e201f7d89 | 585 | while(tmpE > 1) |
| feb11 | 9:3c191fa04f6e | 586 | { |
| feb11 | 10:116e201f7d89 | 587 | tmp = montgomeryStep(montA, tmp, modulus, r); |
| feb11 | 10:116e201f7d89 | 588 | --tmpE; |
| feb11 | 9:3c191fa04f6e | 589 | } |
| feb11 | 9:3c191fa04f6e | 590 | |
| feb11 | 10:116e201f7d89 | 591 | // convert a to normal world |
| feb11 | 10:116e201f7d89 | 592 | return montgomeryStep(tmp, 1, modulus, r); |
| feb11 | 9:3c191fa04f6e | 593 | } |
| feb11 | 9:3c191fa04f6e | 594 | |
| feb11 | 9:3c191fa04f6e | 595 | bool BigInt::isValid() const |
| feb11 | 9:3c191fa04f6e | 596 | { |
| feb11 | 9:3c191fa04f6e | 597 | return size != 0 && bits != 0; |
| feb11 | 9:3c191fa04f6e | 598 | } |
| feb11 | 9:3c191fa04f6e | 599 | |
| feb11 | 11:2f16a220ebbb | 600 | void BigInt::print() const |
| feb11 | 0:9d554894785b | 601 | { |
| feb11 | 11:2f16a220ebbb | 602 | assert(isValid()); |
| feb11 | 11:2f16a220ebbb | 603 | |
| feb11 | 0:9d554894785b | 604 | printf("size: %d bytes\n", size); |
| feb11 | 0:9d554894785b | 605 | uint32_t n = num(size); |
| feb11 | 0:9d554894785b | 606 | for(int i = n-1; i >= 0; --i) |
| feb11 | 0:9d554894785b | 607 | { |
| feb11 | 1:00f2c40d46ed | 608 | printf("%08x ", bits[i]); |
| feb11 | 0:9d554894785b | 609 | } |
| feb11 | 0:9d554894785b | 610 | printf("\n"); |
| feb11 | 0:9d554894785b | 611 | } |
| feb11 | 9:3c191fa04f6e | 612 | |
| feb11 | 9:3c191fa04f6e | 613 | void BigInt::trim() |
| feb11 | 9:3c191fa04f6e | 614 | { |
| feb11 | 9:3c191fa04f6e | 615 | uint8_t *tmp = (uint8_t*)bits; |
| feb11 | 9:3c191fa04f6e | 616 | uint32_t newSize = size; |
| feb11 | 9:3c191fa04f6e | 617 | while(tmp[newSize-1] == 0 && newSize > 0) |
| feb11 | 9:3c191fa04f6e | 618 | newSize--; |
| feb11 | 10:116e201f7d89 | 619 | if(newSize == 0) |
| feb11 | 10:116e201f7d89 | 620 | newSize = 1; |
| feb11 | 9:3c191fa04f6e | 621 | if(num(newSize) < num(size)) |
| feb11 | 10:116e201f7d89 | 622 | { |
| feb11 | 9:3c191fa04f6e | 623 | bits = (uint32_t*)realloc(bits, sizeof(uint32_t)*num(newSize)); |
| feb11 | 10:116e201f7d89 | 624 | } |
| feb11 | 9:3c191fa04f6e | 625 | size = newSize; |
| feb11 | 9:3c191fa04f6e | 626 | } |
| feb11 | 9:3c191fa04f6e | 627 | |
| feb11 | 11:2f16a220ebbb | 628 | uint32_t BigInt::numBits() const |
| feb11 | 10:116e201f7d89 | 629 | { |
| feb11 | 10:116e201f7d89 | 630 | assert(isValid()); |
| feb11 | 12:a436f15b58b6 | 631 | |
| feb11 | 10:116e201f7d89 | 632 | uint32_t n = (size-1)*8; |
| feb11 | 11:2f16a220ebbb | 633 | uint8_t a = bits[num(size)-1] >> ((size-1)%4)*8; |
| feb11 | 10:116e201f7d89 | 634 | uint8_t tmp2 = 8; |
| feb11 | 11:2f16a220ebbb | 635 | while(!(a & 0x80)) |
| feb11 | 10:116e201f7d89 | 636 | { |
| feb11 | 11:2f16a220ebbb | 637 | a <<= 1; |
| feb11 | 10:116e201f7d89 | 638 | --tmp2; |
| feb11 | 10:116e201f7d89 | 639 | } |
| feb11 | 10:116e201f7d89 | 640 | n += tmp2; |
| feb11 | 10:116e201f7d89 | 641 | |
| feb11 | 10:116e201f7d89 | 642 | return n; |
| feb11 | 10:116e201f7d89 | 643 | } |