ecma_bigint_shift (ecma_value_t left_value, /**< left BigInt value */
                   ecma_value_t right_value, /**< right BigInt value */
                   bool is_left) /**< true if left shift operation should be performed */
{
  JERRY_ASSERT (ecma_is_value_bigint (left_value) && ecma_is_value_bigint (right_value));

  if (left_value == ECMA_BIGINT_ZERO)
  {
    return ECMA_BIGINT_ZERO;
  }

  ecma_extended_primitive_t *left_p = ecma_get_extended_primitive_from_value (left_value);

  if (right_value == ECMA_BIGINT_ZERO)
  {
    ecma_ref_extended_primitive (left_p);
    return left_value;
  }

  ecma_extended_primitive_t *right_p = ecma_get_extended_primitive_from_value (right_value);

  if (right_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN)
  {
    is_left = !is_left;
  }

  if (ECMA_BIGINT_GET_SIZE (right_p) > sizeof (ecma_bigint_digit_t))
  {
    if (is_left)
    {
      return ecma_bigint_raise_memory_error ();
    }
    else if (left_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN)
    {
      /* Shifting a negative value with a very big number to the right should be -1. */
      return ecma_bigint_create_from_digit (1, true);
    }

    return ECMA_BIGINT_ZERO;
  }

  ecma_extended_primitive_t *result_p;
  ecma_bigint_digit_t shift = ECMA_BIGINT_GET_LAST_DIGIT (right_p, sizeof (ecma_bigint_digit_t));
  uint32_t left_sign = left_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN;

  if (is_left)
  {
    result_p = ecma_big_uint_shift_left (left_p, shift);
  }
  else
  {
    /* -x >> y == ~(x - 1) >> y == ~((x - 1) >> y) == -(((x - 1) >> y) + 1)
     * When a non-zero bit is shifted out: (x - 1) >> y == x >> y, so the formula is -((x >> y) + 1)
     * When only zero bits are shifted out: (((x - 1) >> y) + 1) == x >> y so the formula is: -(x >> y) */
    result_p = ecma_big_uint_shift_right (left_p, shift, left_sign != 0);

    if (result_p == ECMA_BIGINT_POINTER_TO_ZERO)
    {
      return ECMA_BIGINT_ZERO;
    }
  }

  if (JERRY_UNLIKELY (result_p == NULL))
  {
    return ecma_bigint_raise_memory_error ();
  }

  result_p->u.bigint_sign_and_size |= left_sign;
  return ecma_make_extended_primitive_value (result_p, ECMA_TYPE_BIGINT);
} /* ecma_bigint_shift */
ecma_bigint_shift (ecma_value_t left_value,  
                   ecma_value_t right_value,  
                   bool is_left)  
{
  JERRY_ASSERT (ecma_is_value_bigint (left_value) && ecma_is_value_bigint (right_value));

  if (left_value == ECMA_BIGINT_ZERO)
  {
    return ECMA_BIGINT_ZERO;
  }

  ecma_extended_primitive_t *left_p = ecma_get_extended_primitive_from_value (left_value);

  if (right_value == ECMA_BIGINT_ZERO)
  {
    ecma_ref_extended_primitive (left_p);
    return left_value;
  }

  ecma_extended_primitive_t *right_p = ecma_get_extended_primitive_from_value (right_value);

  if (right_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN)
  {
    is_left = !is_left;
  }

  if (ECMA_BIGINT_GET_SIZE (right_p) > sizeof (ecma_bigint_digit_t))
  {
    if (is_left)
    {
      return ecma_bigint_raise_memory_error ();
    }
    else if (left_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN)
    {
       
      return ecma_bigint_create_from_digit (1, true);
    }

    return ECMA_BIGINT_ZERO;
  }

  ecma_extended_primitive_t *result_p;
  ecma_bigint_digit_t shift = ECMA_BIGINT_GET_LAST_DIGIT (right_p, sizeof (ecma_bigint_digit_t));
  uint32_t left_sign = left_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN;

  if (is_left)
  {
    result_p = ecma_big_uint_shift_left (left_p, shift);
  }
  else
  {
     
    result_p = ecma_big_uint_shift_right (left_p, shift, left_sign != 0);

    if (result_p == ECMA_BIGINT_POINTER_TO_ZERO)
    {
      return ECMA_BIGINT_ZERO;
    }
  }

  if (JERRY_UNLIKELY (result_p == NULL))
  {
    return ecma_bigint_raise_memory_error ();
  }

  result_p->u.bigint_sign_and_size |= left_sign;
  return ecma_make_extended_primitive_value (result_p, ECMA_TYPE_BIGINT);
}  