// Copyright 2012 Google Inc. All Rights Reserved.

#ifndef VM_BIGINT_OPERATIONS_H_
#define VM_BIGINT_OPERATIONS_H_

#include "platform/utils.h"

#include "vm/object.h"

namespace dart {

class BigintOperations : public AllStatic {
 public:
  static RawBigint* NewFromSmi(const Smi& smi, Heap::Space space = Heap::kNew);
  static RawBigint* NewFromInt64(int64_t value, Heap::Space space = Heap::kNew);
  static RawBigint* NewFromUint64(uint64_t value,
                                  Heap::Space space = Heap::kNew);
  // The given string must be a valid integer representation. It may be
  // prefixed by a minus and/or "0x".
  // Returns Bigint::null() if the string cannot be parsed.
  static RawBigint* NewFromCString(const char* str,
                                   Heap::Space space = Heap::kNew);
  static RawBigint* NewFromDouble(double d, Heap::Space space = Heap::kNew);

  // Compute chunk length of the bigint instance created for the
  // specified hex string.  The specified hex string must be a
  // nul-terminated string of hex-digits.  It must only contain
  // hex-digits. Leading "0x" is not allowed.
  static intptr_t ComputeChunkLength(const char* hex_string);

  // Create a bigint instance from the specified hex string. The given string
  // must be a nul-terminated string of hex-digits. It must only contain
  // hex-digits. Leading "0x" is not allowed.
  static RawBigint* FromHexCString(const char* hex_string,
                                   Heap::Space space = Heap::kNew);

  // Helper method to initialize a bigint instance object with the bigint value
  // in the specified string. The given string must be a nul-terminated string
  // of hex-digits. It must only contain hex-digits, leading "0x" is not
  // allowed.
  static void FromHexCString(const char* hex_string, const Bigint& value);

  // The given string must be a nul-terminated string of decimal digits. It
  // must only contain decimal digits (0-9). No sign is allowed. Leading
  // zeroes are ignored.
  static RawBigint* FromDecimalCString(const char* str,
                                   Heap::Space space = Heap::kNew);

  // Converts the bigint to a HEX string. The returned string is prepended by
  // a "0x" (after the optional minus-sign).
  static const char* ToHexCString(intptr_t length,
                                  bool is_negative,
                                  void* data,
                                  uword (*allocator)(intptr_t size));

  static const char* ToHexCString(const Bigint& bigint,
                                  uword (*allocator)(intptr_t size));

  static const char* ToDecimalCString(const Bigint& bigint,
                                      uword (*allocator)(intptr_t size));

  static bool FitsIntoSmi(const Bigint& bigint);
  static RawSmi* ToSmi(const Bigint& bigint);

  static bool FitsIntoInt64(const Bigint& bigint);
  static int64_t ToInt64(const Bigint& bigint);

  static bool FitsIntoUint64(const Bigint& bigint);
  static bool AbsFitsIntoUint64(const Bigint& bigint);
  static uint64_t ToUint64(const Bigint& bigint);
  static uint64_t AbsToUint64(const Bigint& bigint);

  static RawDouble* ToDouble(const Bigint& bigint);

  static RawBigint* Add(const Bigint& a, const Bigint& b) {
    bool negate_b = false;
    return AddSubtract(a, b, negate_b);
  }
  static RawBigint* Subtract(const Bigint& a, const Bigint& b) {
    bool negate_b = true;
    return AddSubtract(a, b, negate_b);
  }
  static RawBigint* Multiply(const Bigint& a, const Bigint& b);
  // TODO(floitsch): what to do for divisions by zero.
  static RawBigint* Divide(const Bigint& a, const Bigint& b);
  static RawBigint* Modulo(const Bigint& a, const Bigint& b);
  static RawBigint* Remainder(const Bigint& a, const Bigint& b);

  static RawBigint* ShiftLeft(const Bigint& bigint, intptr_t amount);
  static RawBigint* ShiftRight(const Bigint& bigint, intptr_t amount);
  static RawBigint* BitAnd(const Bigint& a, const Bigint& b);
  static RawBigint* BitOr(const Bigint& a, const Bigint& b);
  static RawBigint* BitXor(const Bigint& a, const Bigint& b);
  static RawBigint* BitNot(const Bigint& bigint);
  static int64_t BitLength(const Bigint& bigint);

  static int Compare(const Bigint& a, const Bigint& b);

  static bool IsClamped(const Bigint& bigint) {
    intptr_t length = bigint.Length();
    return (length == 0) || (bigint.GetChunkAt(length - 1) != 0);
  }

 private:
  typedef Bigint::Chunk Chunk;
  typedef Bigint::DoubleChunk DoubleChunk;

  static const int kDigitBitSize = 28;
  static const Chunk kDigitMask = (static_cast<Chunk>(1) << kDigitBitSize) - 1;
  static const Chunk kDigitMaxValue = kDigitMask;
  static const int kChunkSize = sizeof(Chunk);
  static const int kChunkBitSize = kChunkSize * kBitsPerByte;
  static const int kHexCharsPerDigit = kDigitBitSize / 4;

  static RawBigint* Zero() { return Bigint::Allocate(0); }
  static RawBigint* One() {
    Bigint& result = Bigint::Handle(Bigint::Allocate(1));
    result.SetChunkAt(0, 1);
    return result.raw();
  }
  static RawBigint* MinusOne() {
    Bigint& result = Bigint::Handle(One());
    result.ToggleSign();
    return result.raw();
  }

  // Performs an addition or subtraction depending on the negate_b argument.
  static RawBigint* AddSubtract(const Bigint& a,
                                const Bigint& b,
                                bool negate_b);

  static int UnsignedCompare(const Bigint& a, const Bigint& b);
  static int UnsignedCompareNonClamped(const Bigint& a, const Bigint& b);
  static RawBigint* UnsignedAdd(const Bigint& a, const Bigint& b);
  static RawBigint* UnsignedSubtract(const Bigint& a, const Bigint& b);

  static RawBigint* MultiplyWithDigit(const Bigint& bigint, Chunk digit);
  static RawBigint* DigitsShiftLeft(const Bigint& bigint, intptr_t amount) {
    return ShiftLeft(bigint, amount * kDigitBitSize);
  }
  static void DivideRemainder(const Bigint& a, const Bigint& b,
                              Bigint* quotient, Bigint* remainder);
  static Chunk InplaceUnsignedDivideRemainderDigit(
      const Bigint& dividend_quotient, Chunk divisor_digit);

  // Removes leading zero-chunks by adjusting the bigint's length.
  static void Clamp(const Bigint& bigint);

  static RawBigint* Copy(const Bigint& bigint);

  static int CountBits(Chunk digit);

  DISALLOW_IMPLICIT_CONSTRUCTORS(BigintOperations);
};

}  // namespace dart

#endif  // VM_BIGINT_OPERATIONS_H_
