| OLD | NEW |
| 1 // Copyright 2012 Google Inc. All Rights Reserved. | 1 // Copyright 2012 Google Inc. All Rights Reserved. |
| 2 | 2 |
| 3 #include "vm/bigint_operations.h" | 3 #include "vm/bigint_operations.h" |
| 4 | 4 |
| 5 #include "platform/utils.h" | 5 #include "platform/utils.h" |
| 6 | 6 |
| 7 #include "vm/double_internals.h" | 7 #include "vm/double_internals.h" |
| 8 #include "vm/exceptions.h" | 8 #include "vm/exceptions.h" |
| 9 #include "vm/object_store.h" | 9 #include "vm/object_store.h" |
| 10 #include "vm/zone.h" | 10 #include "vm/zone.h" |
| (...skipping 951 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 962 } | 962 } |
| 963 | 963 |
| 964 ASSERT(a.IsNegative()); | 964 ASSERT(a.IsNegative()); |
| 965 ASSERT(b.IsNegative()); | 965 ASSERT(b.IsNegative()); |
| 966 // The result will be negative. | 966 // The result will be negative. |
| 967 // We need to convert a and b to two's complement. Do the bit-operation there, | 967 // We need to convert a and b to two's complement. Do the bit-operation there, |
| 968 // and transform the resulting bits from two's complement back to separated | 968 // and transform the resulting bits from two's complement back to separated |
| 969 // magnitude and sign. | 969 // magnitude and sign. |
| 970 // a & b is therefore computed as ~((~(a - 1)) | (~(b - 1))) + 1 which is | 970 // a & b is therefore computed as ~((~(a - 1)) | (~(b - 1))) + 1 which is |
| 971 // equal to ((a-1) & (b-1)) + 1. | 971 // equal to ((a-1) & (b-1)) + 1. |
| 972 ASSERT(a_length >= b_length); |
| 973 ASSERT(min_length == b_length); |
| 972 intptr_t result_length = min_length + 1; | 974 intptr_t result_length = min_length + 1; |
| 973 const Bigint& result = Bigint::Handle(Bigint::Allocate(result_length)); | 975 const Bigint& result = Bigint::Handle(Bigint::Allocate(result_length)); |
| 974 result.ToggleSign(); | 976 result.ToggleSign(); |
| 975 Chunk a_borrow = 1; | 977 Chunk a_borrow = 1; |
| 976 Chunk b_borrow = 1; | 978 Chunk b_borrow = 1; |
| 977 Chunk result_carry = 1; | 979 Chunk result_carry = 1; |
| 978 ASSERT(a_length >= b_length); | |
| 979 for (intptr_t i = 0; i < b_length; i++) { | 980 for (intptr_t i = 0; i < b_length; i++) { |
| 980 Chunk a_digit = a.GetChunkAt(i) - a_borrow; | 981 Chunk a_digit = a.GetChunkAt(i) - a_borrow; |
| 981 Chunk b_digit = b.GetChunkAt(i) - b_borrow; | 982 Chunk b_digit = b.GetChunkAt(i) - b_borrow; |
| 982 Chunk result_chunk = ((a_digit & b_digit) & kDigitMask) + result_carry; | 983 Chunk result_chunk = ((a_digit & b_digit) & kDigitMask) + result_carry; |
| 983 result.SetChunkAt(i, result_chunk & kDigitMask); | 984 result.SetChunkAt(i, result_chunk & kDigitMask); |
| 984 a_borrow = a_digit >> (kChunkBitSize - 1); | 985 a_borrow = a_digit >> (kChunkBitSize - 1); |
| 985 b_borrow = b_digit >> (kChunkBitSize - 1); | 986 b_borrow = b_digit >> (kChunkBitSize - 1); |
| 986 result_carry = result_chunk >> kDigitBitSize; | 987 result_carry = result_chunk >> kDigitBitSize; |
| 987 } | 988 } |
| 988 result.SetChunkAt(a_length, result_carry); | 989 result.SetChunkAt(b_length, result_carry); |
| 989 Clamp(result); | 990 Clamp(result); |
| 990 return result.raw(); | 991 return result.raw(); |
| 991 } | 992 } |
| 992 | 993 |
| 993 | 994 |
| 994 RawBigint* BigintOperations::BitXor(const Bigint& a, const Bigint& b) { | 995 RawBigint* BigintOperations::BitXor(const Bigint& a, const Bigint& b) { |
| 995 ASSERT(IsClamped(a)); | 996 ASSERT(IsClamped(a)); |
| 996 ASSERT(IsClamped(b)); | 997 ASSERT(IsClamped(b)); |
| 997 | 998 |
| 998 if (a.IsZero()) { | 999 if (a.IsZero()) { |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1077 Clamp(result); | 1078 Clamp(result); |
| 1078 return result.raw(); | 1079 return result.raw(); |
| 1079 } | 1080 } |
| 1080 | 1081 |
| 1081 ASSERT(a.IsNegative()); | 1082 ASSERT(a.IsNegative()); |
| 1082 ASSERT(b.IsNegative()); | 1083 ASSERT(b.IsNegative()); |
| 1083 // The result will be positive. | 1084 // The result will be positive. |
| 1084 // We need to convert a and b to two's complement, do the bit-operation there, | 1085 // We need to convert a and b to two's complement, do the bit-operation there, |
| 1085 // and simply store the result. | 1086 // and simply store the result. |
| 1086 // a ^ b is therefore computed as (~(a - 1)) ^ (~(b - 1)). | 1087 // a ^ b is therefore computed as (~(a - 1)) ^ (~(b - 1)). |
| 1088 ASSERT(a_length >= b_length); |
| 1089 ASSERT(max_length == a_length); |
| 1087 intptr_t result_length = max_length; | 1090 intptr_t result_length = max_length; |
| 1088 const Bigint& result = Bigint::Handle(Bigint::Allocate(result_length)); | 1091 const Bigint& result = Bigint::Handle(Bigint::Allocate(result_length)); |
| 1089 Chunk a_borrow = 1; | 1092 Chunk a_borrow = 1; |
| 1090 Chunk b_borrow = 1; | 1093 Chunk b_borrow = 1; |
| 1091 ASSERT(a_length >= b_length); | |
| 1092 for (intptr_t i = 0; i < b_length; i++) { | 1094 for (intptr_t i = 0; i < b_length; i++) { |
| 1093 Chunk a_digit = a.GetChunkAt(i) - a_borrow; | 1095 Chunk a_digit = a.GetChunkAt(i) - a_borrow; |
| 1094 Chunk b_digit = b.GetChunkAt(i) - b_borrow; | 1096 Chunk b_digit = b.GetChunkAt(i) - b_borrow; |
| 1095 Chunk result_chunk = (~a_digit) ^ (~b_digit); | 1097 Chunk result_chunk = (~a_digit) ^ (~b_digit); |
| 1096 result.SetChunkAt(i, result_chunk & kDigitMask); | 1098 result.SetChunkAt(i, result_chunk & kDigitMask); |
| 1097 a_borrow = a_digit >> (kChunkBitSize - 1); | 1099 a_borrow = a_digit >> (kChunkBitSize - 1); |
| 1098 b_borrow = b_digit >> (kChunkBitSize - 1); | 1100 b_borrow = b_digit >> (kChunkBitSize - 1); |
| 1099 } | 1101 } |
| 1100 ASSERT(b_borrow == 0); | 1102 ASSERT(b_borrow == 0); |
| 1101 for (intptr_t i = b_length; i < a_length; i++) { | 1103 for (intptr_t i = b_length; i < a_length; i++) { |
| 1102 Chunk a_digit = a.GetChunkAt(i) - a_borrow; | 1104 Chunk a_digit = a.GetChunkAt(i) - a_borrow; |
| 1103 result.SetChunkAt(i, (~a_digit) & kDigitMask); | 1105 // (~a_digit) ^ 0xFFF..FFF == a_digit. |
| 1106 result.SetChunkAt(i, a_digit & kDigitMask); |
| 1104 a_borrow = a_digit >> (kChunkBitSize - 1); | 1107 a_borrow = a_digit >> (kChunkBitSize - 1); |
| 1105 } | 1108 } |
| 1106 ASSERT(a_borrow == 0); | 1109 ASSERT(a_borrow == 0); |
| 1107 Clamp(result); | 1110 Clamp(result); |
| 1108 return result.raw(); | 1111 return result.raw(); |
| 1109 } | 1112 } |
| 1110 | 1113 |
| 1111 | 1114 |
| 1112 RawBigint* BigintOperations::BitNot(const Bigint& bigint) { | 1115 RawBigint* BigintOperations::BitNot(const Bigint& bigint) { |
| 1113 if (bigint.IsZero()) { | 1116 if (bigint.IsZero()) { |
| (...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1504 int BigintOperations::CountBits(Chunk digit) { | 1507 int BigintOperations::CountBits(Chunk digit) { |
| 1505 int result = 0; | 1508 int result = 0; |
| 1506 while (digit != 0) { | 1509 while (digit != 0) { |
| 1507 digit >>= 1; | 1510 digit >>= 1; |
| 1508 result++; | 1511 result++; |
| 1509 } | 1512 } |
| 1510 return result; | 1513 return result; |
| 1511 } | 1514 } |
| 1512 | 1515 |
| 1513 } // namespace dart | 1516 } // namespace dart |
| OLD | NEW |