OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright 2012 Google Inc. All Rights Reserved. |
2 // for details. All rights reserved. Use of this source code is governed by a | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | 2 |
5 #ifndef VM_BIGINT_OPERATIONS_H_ | 3 #ifndef VM_BIGINT_OPERATIONS_H_ |
6 #define VM_BIGINT_OPERATIONS_H_ | 4 #define VM_BIGINT_OPERATIONS_H_ |
7 | 5 |
8 #include "vm/heap.h" | 6 #include "platform/utils.h" |
| 7 |
9 #include "vm/object.h" | 8 #include "vm/object.h" |
10 #include "vm/token.h" | |
11 | |
12 // This should be folded into OpenSSL | |
13 #undef BN_abs_is_word | |
14 #define BN_abs_is_word(a, w) (((a)->top == 1) \ | |
15 && ((a)->d[0] == static_cast<BN_ULONG>(w))) | |
16 | 9 |
17 namespace dart { | 10 namespace dart { |
18 | 11 |
19 class BigintOperations : public AllStatic { | 12 class BigintOperations : public AllStatic { |
20 public: | 13 public: |
21 static RawBigint* NewFromSmi(const Smi& smi, Heap::Space space = Heap::kNew); | 14 static RawBigint* NewFromSmi(const Smi& smi, Heap::Space space = Heap::kNew); |
22 static RawBigint* NewFromInt64(int64_t value, Heap::Space space = Heap::kNew); | 15 static RawBigint* NewFromInt64(int64_t value, Heap::Space space = Heap::kNew); |
23 static RawBigint* NewFromUint64(uint64_t value, | 16 static RawBigint* NewFromUint64(uint64_t value, |
24 Heap::Space space = Heap::kNew); | 17 Heap::Space space = Heap::kNew); |
25 // The given string must be a valid integer representation. It may be | 18 // The given string must be a valid integer representation. It may be |
26 // prefixed by a minus and/or "0x". | 19 // prefixed by a minus and/or "0x". |
27 // Returns Bigint::null() if the string cannot be parsed. | 20 // Returns Bigint::null() if the string cannot be parsed. |
28 static RawBigint* NewFromCString(const char* str, | 21 static RawBigint* NewFromCString(const char* str, |
29 Heap::Space space = Heap::kNew); | 22 Heap::Space space = Heap::kNew); |
30 static RawBigint* NewFromDouble(double d, Heap::Space space = Heap::kNew); | 23 static RawBigint* NewFromDouble(double d, Heap::Space space = Heap::kNew); |
31 | 24 |
32 // The given string must be a nul-terminated string of hex-digits. It must | 25 // The given string must be a nul-terminated string of hex-digits. It must |
33 // only contain hex-digits. No sign or leading "0x" is allowed. | 26 // only contain hex-digits. No sign or leading "0x" is allowed. |
34 static RawBigint* FromHexCString(const char* str, | 27 static RawBigint* FromHexCString(const char* str, |
35 Heap::Space space = Heap::kNew); | 28 Heap::Space space = Heap::kNew); |
| 29 |
36 // The given string must be a nul-terminated string of decimal digits. It | 30 // The given string must be a nul-terminated string of decimal digits. It |
37 // must only contain decimal digits (0-9). No sign is allowed. Leading | 31 // must only contain decimal digits (0-9). No sign is allowed. Leading |
38 // zeroes are ignored. | 32 // zeroes are ignored. |
39 static RawBigint* FromDecimalCString(const char* str, | 33 static RawBigint* FromDecimalCString(const char* str, |
40 Heap::Space space = Heap::kNew); | 34 Heap::Space space = Heap::kNew); |
41 // Converts the bigint to a string. The returned string is prepended by | 35 |
| 36 // Converts the bigint to a HEX string. The returned string is prepended by |
42 // a "0x" (after the optional minus-sign). | 37 // a "0x" (after the optional minus-sign). |
43 static const char* ToHexCString(const BIGNUM* bn, | 38 static const char* ToHexCString(intptr_t length, |
44 uword (*allocator)(intptr_t size)); | 39 bool is_negative, |
45 static const char* ToHexCString(const Bigint& bigint, | 40 void* data, |
46 uword (*allocator)(intptr_t size)); | 41 uword (*allocator)(intptr_t size)); |
47 | 42 |
48 // Converts the bigint to a string. | 43 static const char* ToHexCString(const Bigint& bigint, |
49 static const char* ToDecCString(const BIGNUM* bn, | |
50 uword (*allocator)(intptr_t size)); | |
51 static const char* ToDecCString(const Bigint& bigint, | |
52 uword (*allocator)(intptr_t size)); | 44 uword (*allocator)(intptr_t size)); |
53 | 45 |
54 static bool FitsIntoSmi(const Bigint& bigint); | 46 static bool FitsIntoSmi(const Bigint& bigint); |
55 static RawSmi* ToSmi(const Bigint& bigint); | 47 static RawSmi* ToSmi(const Bigint& bigint); |
56 | 48 |
57 static bool FitsIntoInt64(const Bigint& bigint); | 49 static bool FitsIntoMint(const Bigint& bigint); |
58 static int64_t ToInt64(const Bigint& bigint); | 50 static int64_t ToMint(const Bigint& bigint); |
59 | 51 |
60 static bool FitsIntoUint64(const Bigint& bigint); | 52 static bool FitsIntoUint64(const Bigint& bigint); |
61 static uint64_t ToUint64(const Bigint& bigint); | 53 static uint64_t ToUint64(const Bigint& bigint); |
62 static uint64_t AbsToUint64(const Bigint& bigint); | 54 static uint64_t AbsToUint64(const Bigint& bigint); |
63 | 55 |
64 static RawDouble* ToDouble(const Bigint& bigint); | 56 static RawDouble* ToDouble(const Bigint& bigint); |
65 | 57 |
66 static RawBigint* Add(const Bigint& a, const Bigint& b); | 58 static RawBigint* Add(const Bigint& a, const Bigint& b) { |
67 static RawBigint* Subtract(const Bigint& a, const Bigint& b); | 59 bool negate_b = false; |
| 60 return AddSubtract(a, b, negate_b); |
| 61 } |
| 62 static RawBigint* Subtract(const Bigint& a, const Bigint& b) { |
| 63 bool negate_b = true; |
| 64 return AddSubtract(a, b, negate_b); |
| 65 } |
68 static RawBigint* Multiply(const Bigint& a, const Bigint& b); | 66 static RawBigint* Multiply(const Bigint& a, const Bigint& b); |
69 // TODO(floitsch): what to do for divisions by zero. | 67 // TODO(floitsch): what to do for divisions by zero. |
70 static RawBigint* Divide(const Bigint& a, const Bigint& b); | 68 static RawBigint* Divide(const Bigint& a, const Bigint& b); |
71 static RawBigint* Modulo(const Bigint& a, const Bigint& b); | 69 static RawBigint* Modulo(const Bigint& a, const Bigint& b); |
72 static RawBigint* Remainder(const Bigint& a, const Bigint& b); | 70 static RawBigint* Remainder(const Bigint& a, const Bigint& b); |
73 | 71 |
74 static RawBigint* ShiftLeft(const Bigint& bigint, intptr_t amount); | 72 static RawBigint* ShiftLeft(const Bigint& bigint, intptr_t amount); |
75 static RawBigint* ShiftRight(const Bigint& bigint, intptr_t amount); | 73 static RawBigint* ShiftRight(const Bigint& bigint, intptr_t amount); |
76 static RawBigint* BitAnd(const Bigint& a, const Bigint& b); | 74 static RawBigint* BitAnd(const Bigint& a, const Bigint& b); |
77 static RawBigint* BitOr(const Bigint& a, const Bigint& b); | 75 static RawBigint* BitOr(const Bigint& a, const Bigint& b); |
78 static RawBigint* BitXor(const Bigint& a, const Bigint& b); | 76 static RawBigint* BitXor(const Bigint& a, const Bigint& b); |
79 static RawBigint* BitNot(const Bigint& bigint); | 77 static RawBigint* BitNot(const Bigint& bigint); |
80 static RawInteger* BitAndWithSmi(const Bigint& bigint, const Smi& smi); | |
81 static RawInteger* BitOrWithSmi(const Bigint& bigint, const Smi& smi); | |
82 static RawInteger* BitXorWithSmi(const Bigint& bigint, const Smi& smi); | |
83 | 78 |
84 static int Compare(const Bigint& a, const Bigint& b); | 79 static int Compare(const Bigint& a, const Bigint& b); |
85 | 80 |
| 81 static bool IsClamped(const Bigint& bigint) { |
| 82 intptr_t length = bigint.Length(); |
| 83 return (length == 0) || (bigint.GetChunkAt(length - 1) != 0); |
| 84 } |
86 | 85 |
87 private: | 86 private: |
88 static BIGNUM* TmpBN(); | 87 typedef Bigint::Chunk Chunk; |
89 static BN_CTX* TmpBNCtx(); | 88 typedef Bigint::DoubleChunk DoubleChunk; |
90 | 89 |
| 90 static const int kDigitBitSize = 28; |
| 91 static const Chunk kDigitMask = (static_cast<Chunk>(1) << kDigitBitSize) - 1; |
| 92 static const Chunk kDigitMaxValue = kDigitMask; |
| 93 static const int kChunkSize = sizeof(Chunk); |
| 94 static const int kChunkBitSize = kChunkSize * kBitsPerByte; |
| 95 |
| 96 static RawBigint* Zero() { return Bigint::Allocate(0); } |
91 static RawBigint* One() { | 97 static RawBigint* One() { |
92 Bigint& result = Bigint::Handle(NewFromInt64(1)); | 98 Bigint& result = Bigint::Handle(Bigint::Allocate(1)); |
| 99 result.SetChunkAt(0, 1); |
93 return result.raw(); | 100 return result.raw(); |
94 } | 101 } |
95 static RawBigint* BitTT(const Bigint& a, const Bigint& b, bool tt[4]); | 102 static RawBigint* MinusOne() { |
96 // The following function only works for bit-and and bit-or. | 103 Bigint& result = Bigint::Handle(One()); |
97 static RawSmi* BitOpWithSmi(Token::Kind kind, | 104 result.ToggleSign(); |
98 const Bigint& bigint, | 105 return result.raw(); |
99 const Smi& smi); | 106 } |
| 107 |
| 108 // Performs an addition or subtraction depending on the negate_b argument. |
| 109 static RawBigint* AddSubtract(const Bigint& a, |
| 110 const Bigint& b, |
| 111 bool negate_b); |
| 112 |
| 113 static int UnsignedCompare(const Bigint& a, const Bigint& b); |
| 114 static int UnsignedCompareNonClamped(const Bigint& a, const Bigint& b); |
| 115 static RawBigint* UnsignedAdd(const Bigint& a, const Bigint& b); |
| 116 static RawBigint* UnsignedSubtract(const Bigint& a, const Bigint& b); |
| 117 |
| 118 static RawBigint* MultiplyWithDigit(const Bigint& bigint, Chunk digit); |
| 119 static RawBigint* DigitsShiftLeft(const Bigint& bigint, intptr_t amount) { |
| 120 return ShiftLeft(bigint, amount * kDigitBitSize); |
| 121 } |
| 122 static void DivideRemainder(const Bigint& a, const Bigint& b, |
| 123 Bigint* quotient, Bigint* remainder); |
| 124 |
| 125 // Removes leading zero-chunks by adjusting the bigint's length. |
| 126 static void Clamp(const Bigint& bigint); |
| 127 |
| 128 static RawBigint* Copy(const Bigint& bigint); |
| 129 |
| 130 static int CountBits(Chunk digit); |
100 | 131 |
101 DISALLOW_IMPLICIT_CONSTRUCTORS(BigintOperations); | 132 DISALLOW_IMPLICIT_CONSTRUCTORS(BigintOperations); |
102 }; | 133 }; |
103 | 134 |
104 } // namespace dart | 135 } // namespace dart |
105 | 136 |
106 #endif // VM_BIGINT_OPERATIONS_H_ | 137 #endif // VM_BIGINT_OPERATIONS_H_ |
OLD | NEW |