<commit_before>/* The implementation of Bignum, providing infinite size integers */

#include <ctype.h>
#include <math.h>
#include <iostream>
#include <sstream>

#include "gc/gc.hpp"
#include "vm/object_utils.hpp"
#include "vm.hpp"
#include "objectmemory.hpp"
#include "builtin/array.hpp"
#include "builtin/class.hpp"
#include "builtin/exception.hpp"
#include "builtin/fixnum.hpp"
#include "builtin/float.hpp"
#include "builtin/string.hpp"
#include "builtin/bytearray.hpp"

#include "missing/math.h"

#define BASIC_CLASS(blah) G(blah)
#define NEW_STRUCT(obj, str, kls, kind) \
  obj = (typeof(obj))Bignum::create(state); \
  str = (kind *)(obj->mp_val())
#define DATA_STRUCT(obj, type) ((type)(obj->mp_val()))

#define NMP mp_int *n; Bignum* n_obj; \
  NEW_STRUCT(n_obj, n, BASIC_CLASS(bignum), mp_int);

#define MMP mp_int *m; Bignum* m_obj; \
  NEW_STRUCT(m_obj, m, BASIC_CLASS(bignum), mp_int);


#define BDIGIT_DBL long long
#define DIGIT_RADIX (1UL << DIGIT_BIT)

#define XST ((void*)state)

namespace rubinius {

  /*
   * LibTomMath actually stores stuff internally in longs.
   * The problem with it's API is that it's int based, so
   * this will create problems on 64 bit platforms if
   * everything is cut down to 32 bits. Hence the existence
   * of the mp_set_long, mp_init_set_long and mp_get_long
   * functions here.
   */
  static int mp_set_long MPA(mp_int* a, unsigned long b) {
    int     err;
    // @todo Move these two values to bignum.h
    size_t  count = sizeof(unsigned long) * 2;
    size_t  shift_width = (sizeof(unsigned long) * 8) - 4;

    mp_zero(a);

    /* set four bits at a time */
    for(size_t x = 0; x < count; x++) {
      /* shift the number up four bits */
      if((err = mp_mul_2d(MPST, a, 4, a)) != MP_OKAY) {
        return err;
      }

      /* OR in the top four bits of the source */
      a->dp[0] |= (b >> shift_width) & 15;

      /* shift the source up to the next four bits */
      b <<= 4;

      /* ensure that digits are not clamped off */
      a->used += 1;
    }

    mp_clamp(a);
    return MP_OKAY;
  }

  static unsigned long mp_get_long(mp_int* a) {
      int i;
      unsigned long res;

      if(a->used == 0) return 0;

      /* get number of digits of the lsb we have to read */
      i = MIN(a->used,(int)((sizeof(unsigned long)*CHAR_BIT+DIGIT_BIT-1)/DIGIT_BIT))-1;
<commit_msg>Improve the performance of mp_set_long<commit_after>/* The implementation of Bignum, providing infinite size integers */

#include <ctype.h>
#include <math.h>
#include <iostream>
#include <sstream>

#include "gc/gc.hpp"
#include "vm/object_utils.hpp"
#include "vm.hpp"
#include "objectmemory.hpp"
#include "builtin/array.hpp"
#include "builtin/class.hpp"
#include "builtin/exception.hpp"
#include "builtin/fixnum.hpp"
#include "builtin/float.hpp"
#include "builtin/string.hpp"
#include "builtin/bytearray.hpp"

#include "missing/math.h"

#define BASIC_CLASS(blah) G(blah)
#define NEW_STRUCT(obj, str, kls, kind) \
  obj = (typeof(obj))Bignum::create(state); \
  str = (kind *)(obj->mp_val())
#define DATA_STRUCT(obj, type) ((type)(obj->mp_val()))

#define NMP mp_int *n; Bignum* n_obj; \
  NEW_STRUCT(n_obj, n, BASIC_CLASS(bignum), mp_int);

#define MMP mp_int *m; Bignum* m_obj; \
  NEW_STRUCT(m_obj, m, BASIC_CLASS(bignum), mp_int);


#define BDIGIT_DBL long long
#define DIGIT_RADIX (1UL << DIGIT_BIT)

#define XST ((void*)state)

namespace rubinius {

  /*
   * LibTomMath actually stores stuff internally in longs.
   * The problem with it's API is that it's int based, so
   * this will create problems on 64 bit platforms if
   * everything is cut down to 32 bits. Hence the existence
   * of the mp_set_long, mp_init_set_long and mp_get_long
   * functions here.
   */
  static int mp_set_long MPA(mp_int* a, unsigned long b) {
    int     err;

    mp_zero(a);

    while(b > MP_DIGIT_MAX) {
      a->dp[0] |= b >> DIGIT_BIT;
      a->used += 1;
      if((err = mp_mul_2d(MPST, a, DIGIT_BIT, a)) != MP_OKAY) {
        return err;
      }
      b &= MP_MASK;
    }

    a->dp[0] |= b;
    a->used += 1;

    mp_clamp(a);
    return MP_OKAY;
  }

  static unsigned long mp_get_long(mp_int* a) {
      int i;
      unsigned long res;

      if(a->used == 0) return 0;

      /* get number of digits of the lsb we have to read */
      i = MIN(a->used,(int)((sizeof(unsigned long)*CHAR_BIT+DIGIT_BIT-1)/DIGIT_BIT))-1;

{'fraction_non_alphanumeric': 0.1380255941499086, 'fraction_numerical': 0.007769652650822669, 'mean_word_length': 3.3293768545994067, 'pattern_counts': {'":': 0, '<': 18, '<?xml version=': 0, '>': 30, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7282007', 'n_tokens_mistral': 1684, 'n_tokens_neox': 1639, 'n_words': 458}