Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(470)

Side by Side Diff: runtime/vm/bigint_operations.cc

Issue 9625027: Fix bit-or and bit-xor for two negative bigints. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | runtime/vm/bigint_operations_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | runtime/vm/bigint_operations_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698