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 |