| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/bigint_operations.h" | 5 #include "vm/bigint_operations.h" |
| 6 | 6 |
| 7 #include <openssl/crypto.h> | 7 #include <openssl/crypto.h> |
| 8 | 8 |
| 9 #include "vm/bigint_store.h" | 9 #include "vm/bigint_store.h" |
| 10 #include "vm/double_internals.h" | 10 #include "vm/double_internals.h" |
| 11 #include "vm/exceptions.h" | 11 #include "vm/exceptions.h" |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 133 // Shortcut for small numbers. Also makes the right-shift below | 133 // Shortcut for small numbers. Also makes the right-shift below |
| 134 // well specified. | 134 // well specified. |
| 135 Smi& zero = Smi::Handle(Smi::New(0)); | 135 Smi& zero = Smi::Handle(Smi::New(0)); |
| 136 return NewFromSmi(zero, space); | 136 return NewFromSmi(zero, space); |
| 137 } | 137 } |
| 138 DoubleInternals internals = DoubleInternals(d); | 138 DoubleInternals internals = DoubleInternals(d); |
| 139 if (internals.IsSpecial()) { | 139 if (internals.IsSpecial()) { |
| 140 GrowableArray<const Object*> exception_arguments; | 140 GrowableArray<const Object*> exception_arguments; |
| 141 exception_arguments.Add( | 141 exception_arguments.Add( |
| 142 &Object::ZoneHandle(String::New("BigintOperations::NewFromDouble"))); | 142 &Object::ZoneHandle(String::New("BigintOperations::NewFromDouble"))); |
| 143 exception_arguments.Add(&Object::ZoneHandle(Double::New(d))); | 143 Exceptions::ThrowByType(Exceptions::kInternalError, exception_arguments); |
| 144 Exceptions::ThrowByType(Exceptions::kInternalError, | |
| 145 exception_arguments); | |
| 146 } | 144 } |
| 147 uint64_t significand = internals.Significand(); | 145 uint64_t significand = internals.Significand(); |
| 148 int exponent = internals.Exponent(); | 146 int exponent = internals.Exponent(); |
| 149 int sign = internals.Sign(); | 147 int sign = internals.Sign(); |
| 150 if (exponent <= 0) { | 148 if (exponent <= 0) { |
| 151 significand >>= -exponent; | 149 significand >>= -exponent; |
| 152 exponent = 0; | 150 exponent = 0; |
| 153 } else if (exponent <= 10) { | 151 } else if (exponent <= 10) { |
| 154 // A double significand has at most 53 bits. The following shift will | 152 // A double significand has at most 53 bits. The following shift will |
| 155 // hence not overflow, and yield an integer of at most 63 bits. | 153 // hence not overflow, and yield an integer of at most 63 bits. |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 349 | 347 |
| 350 | 348 |
| 351 uint64_t BigintOperations::ToUint64(const Bigint& bigint) { | 349 uint64_t BigintOperations::ToUint64(const Bigint& bigint) { |
| 352 ASSERT(FitsIntoUint64(bigint)); | 350 ASSERT(FitsIntoUint64(bigint)); |
| 353 return AbsToUint64(bigint); | 351 return AbsToUint64(bigint); |
| 354 } | 352 } |
| 355 | 353 |
| 356 | 354 |
| 357 RawBigint* BigintOperations::Add(const Bigint& a, const Bigint& b) { | 355 RawBigint* BigintOperations::Add(const Bigint& a, const Bigint& b) { |
| 358 int status = BN_add(TmpBN(), a.BNAddr(), b.BNAddr()); | 356 int status = BN_add(TmpBN(), a.BNAddr(), b.BNAddr()); |
| 359 ASSERT(status == 1); | 357 if (status == 0) { |
| 358 GrowableArray<const Object*> exception_arguments; |
| 359 exception_arguments.Add( |
| 360 &Object::ZoneHandle(String::New("BigintOperations::Add"))); |
| 361 Exceptions::ThrowByType(Exceptions::kInternalError, exception_arguments); |
| 362 } |
| 360 const Bigint& result = Bigint::Handle(Bigint::New(TmpBN())); | 363 const Bigint& result = Bigint::Handle(Bigint::New(TmpBN())); |
| 361 return result.raw(); | 364 return result.raw(); |
| 362 } | 365 } |
| 363 | 366 |
| 364 | 367 |
| 365 RawBigint* BigintOperations::Subtract(const Bigint& a, const Bigint& b) { | 368 RawBigint* BigintOperations::Subtract(const Bigint& a, const Bigint& b) { |
| 366 int status = BN_sub(TmpBN(), a.BNAddr(), b.BNAddr()); | 369 int status = BN_sub(TmpBN(), a.BNAddr(), b.BNAddr()); |
| 367 ASSERT(status == 1); | 370 if (status == 0) { |
| 371 GrowableArray<const Object*> exception_arguments; |
| 372 exception_arguments.Add( |
| 373 &Object::ZoneHandle(String::New("BigintOperations::Subtract"))); |
| 374 Exceptions::ThrowByType(Exceptions::kInternalError, exception_arguments); |
| 375 } |
| 368 const Bigint& result = Bigint::Handle(Bigint::New(TmpBN())); | 376 const Bigint& result = Bigint::Handle(Bigint::New(TmpBN())); |
| 369 return result.raw(); | 377 return result.raw(); |
| 370 } | 378 } |
| 371 | 379 |
| 372 | 380 |
| 373 RawBigint* BigintOperations::Multiply(const Bigint& a, const Bigint& b) { | 381 RawBigint* BigintOperations::Multiply(const Bigint& a, const Bigint& b) { |
| 374 int status = BN_mul(TmpBN(), a.BNAddr(), b.BNAddr(), TmpBNCtx()); | 382 int status = BN_mul(TmpBN(), a.BNAddr(), b.BNAddr(), TmpBNCtx()); |
| 375 ASSERT(status == 1); | 383 if (status == 0) { |
| 384 GrowableArray<const Object*> exception_arguments; |
| 385 exception_arguments.Add( |
| 386 &Object::ZoneHandle(String::New("BigintOperations::Multiply"))); |
| 387 Exceptions::ThrowByType(Exceptions::kInternalError, exception_arguments); |
| 388 } |
| 376 const Bigint& result = Bigint::Handle(Bigint::New(TmpBN())); | 389 const Bigint& result = Bigint::Handle(Bigint::New(TmpBN())); |
| 377 return result.raw(); | 390 return result.raw(); |
| 378 } | 391 } |
| 379 | 392 |
| 380 | 393 |
| 381 RawBigint* BigintOperations::Divide(const Bigint& a, const Bigint& b) { | 394 RawBigint* BigintOperations::Divide(const Bigint& a, const Bigint& b) { |
| 382 int status = BN_div(TmpBN(), NULL, a.BNAddr(), b.BNAddr(), TmpBNCtx()); | 395 int status = BN_div(TmpBN(), NULL, a.BNAddr(), b.BNAddr(), TmpBNCtx()); |
| 383 ASSERT(status == 1); | 396 if (status == 0) { |
| 397 GrowableArray<const Object*> exception_arguments; |
| 398 exception_arguments.Add( |
| 399 &Object::ZoneHandle(String::New("BigintOperations::Divide"))); |
| 400 Exceptions::ThrowByType(Exceptions::kInternalError, exception_arguments); |
| 401 } |
| 384 const Bigint& quotient = Bigint::Handle(Bigint::New(TmpBN())); | 402 const Bigint& quotient = Bigint::Handle(Bigint::New(TmpBN())); |
| 385 return quotient.raw(); | 403 return quotient.raw(); |
| 386 } | 404 } |
| 387 | 405 |
| 388 | 406 |
| 389 RawBigint* BigintOperations::Modulo(const Bigint& a, const Bigint& b) { | 407 RawBigint* BigintOperations::Modulo(const Bigint& a, const Bigint& b) { |
| 390 int status = BN_nnmod(TmpBN(), a.BNAddr(), b.BNAddr(), TmpBNCtx()); | 408 int status = BN_nnmod(TmpBN(), a.BNAddr(), b.BNAddr(), TmpBNCtx()); |
| 391 ASSERT(status == 1); | 409 if (status == 0) { |
| 410 GrowableArray<const Object*> exception_arguments; |
| 411 exception_arguments.Add( |
| 412 &Object::ZoneHandle(String::New("BigintOperations::Modulo"))); |
| 413 Exceptions::ThrowByType(Exceptions::kInternalError, exception_arguments); |
| 414 } |
| 392 const Bigint& modulo = Bigint::Handle(Bigint::New(TmpBN())); | 415 const Bigint& modulo = Bigint::Handle(Bigint::New(TmpBN())); |
| 393 return modulo.raw(); | 416 return modulo.raw(); |
| 394 } | 417 } |
| 395 | 418 |
| 396 | 419 |
| 397 RawBigint* BigintOperations::Remainder(const Bigint& a, const Bigint& b) { | 420 RawBigint* BigintOperations::Remainder(const Bigint& a, const Bigint& b) { |
| 398 int status = BN_div(NULL, TmpBN(), a.BNAddr(), b.BNAddr(), TmpBNCtx()); | 421 int status = BN_div(NULL, TmpBN(), a.BNAddr(), b.BNAddr(), TmpBNCtx()); |
| 399 ASSERT(status == 1); | 422 if (status == 0) { |
| 423 GrowableArray<const Object*> exception_arguments; |
| 424 exception_arguments.Add( |
| 425 &Object::ZoneHandle(String::New("BigintOperations::Remainder"))); |
| 426 Exceptions::ThrowByType(Exceptions::kInternalError, exception_arguments); |
| 427 } |
| 400 const Bigint& remainder = Bigint::Handle(Bigint::New(TmpBN())); | 428 const Bigint& remainder = Bigint::Handle(Bigint::New(TmpBN())); |
| 401 return remainder.raw(); | 429 return remainder.raw(); |
| 402 } | 430 } |
| 403 | 431 |
| 404 | 432 |
| 405 RawBigint* BigintOperations::ShiftLeft(const Bigint& bigint, intptr_t amount) { | 433 RawBigint* BigintOperations::ShiftLeft(const Bigint& bigint, intptr_t amount) { |
| 406 int status = BN_lshift(TmpBN(), bigint.BNAddr(), amount); | 434 int status = BN_lshift(TmpBN(), bigint.BNAddr(), amount); |
| 407 ASSERT(status == 1); | 435 if (status == 0) { |
| 436 GrowableArray<const Object*> exception_arguments; |
| 437 exception_arguments.Add( |
| 438 &Object::ZoneHandle(String::New("BigintOperations::ShiftLeft"))); |
| 439 Exceptions::ThrowByType(Exceptions::kInternalError, exception_arguments); |
| 440 } |
| 408 const Bigint& result = Bigint::Handle(Bigint::New(TmpBN())); | 441 const Bigint& result = Bigint::Handle(Bigint::New(TmpBN())); |
| 409 return result.raw(); | 442 return result.raw(); |
| 410 } | 443 } |
| 411 | 444 |
| 412 | 445 |
| 413 RawBigint* BigintOperations::ShiftRight(const Bigint& bigint, intptr_t amount) { | 446 RawBigint* BigintOperations::ShiftRight(const Bigint& bigint, intptr_t amount) { |
| 414 ASSERT(amount >= 0); | 447 ASSERT(amount >= 0); |
| 415 int status = BN_rshift(TmpBN(), bigint.BNAddr(), amount); | 448 int status = BN_rshift(TmpBN(), bigint.BNAddr(), amount); |
| 416 ASSERT(status == 1); | 449 if (status == 0) { |
| 417 | 450 GrowableArray<const Object*> exception_arguments; |
| 451 exception_arguments.Add( |
| 452 &Object::ZoneHandle(String::New("BigintOperations::ShiftRight"))); |
| 453 Exceptions::ThrowByType(Exceptions::kInternalError, exception_arguments); |
| 454 } |
| 418 // OpenSSL doesn't take account of sign when shifting - this fixes it. | 455 // OpenSSL doesn't take account of sign when shifting - this fixes it. |
| 419 if (bigint.IsNegative()) { | 456 if (bigint.IsNegative()) { |
| 420 for (intptr_t i = 0; i < amount; ++i) { | 457 for (intptr_t i = 0; i < amount; ++i) { |
| 421 if (bigint.IsBitSet(i)) { | 458 if (bigint.IsBitSet(i)) { |
| 422 int status = BN_sub_word(TmpBN(), 1); | 459 int status = BN_sub_word(TmpBN(), 1); |
| 423 ASSERT(status == 1); | 460 ASSERT(status == 1); |
| 424 break; | 461 break; |
| 425 } | 462 } |
| 426 } | 463 } |
| 427 } | 464 } |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 590 result.ToggleSign(); | 627 result.ToggleSign(); |
| 591 return result.raw(); | 628 return result.raw(); |
| 592 } | 629 } |
| 593 | 630 |
| 594 | 631 |
| 595 int BigintOperations::Compare(const Bigint& a, const Bigint& b) { | 632 int BigintOperations::Compare(const Bigint& a, const Bigint& b) { |
| 596 return BN_cmp(a.BNAddr(), b.BNAddr()); | 633 return BN_cmp(a.BNAddr(), b.BNAddr()); |
| 597 } | 634 } |
| 598 | 635 |
| 599 } // namespace dart | 636 } // namespace dart |
| OLD | NEW |