obj_long.c File Reference

Big ints, implemented through my own makeshift thing. More...

#include <kuroko/vm.h>
#include <kuroko/value.h>
#include <kuroko/util.h>
#include "private.h"
Include dependency graph for obj_long.c:

Go to the source code of this file.

Data Structures

struct  KrkLong_Internal
 
struct  BigInt
 
struct  _private
 

Macros

#define DIGIT_SHIFT   31
 
#define DIGIT_MAX   0x7FFFFFFF
 
#define PREP_OUTPUT(res, a, b)   KrkLong _tmp_out_ ## res, *_swap_out_ ## res = NULL; do { if (res == a || res == b) { krk_long_init_si(&_tmp_out_ ## res, 0); _swap_out_ ## res = res; res = &_tmp_out_ ## res; } } while (0)
 
#define PREP_OUTPUT1(res, a)   KrkLong _tmp_out_ ## res, *_swap_out_ ## res = NULL; do { if (res == a) { krk_long_init_si(&_tmp_out_ ## res, 0); _swap_out_ ## res = res; res = &_tmp_out_ ## res; } } while (0)
 
#define FINISH_OUTPUT(res)   do { if (_swap_out_ ## res) { _swap(_swap_out_ ## res, res); krk_long_clear(&_tmp_out_ ## res); } } while (0)
 
#define AS_long(o)   ((struct BigInt *)AS_OBJECT(o))
 
#define IS_long(o)   (krk_isInstanceOf(o, KRK_BASE_CLASS(long)))
 
#define CURRENT_CTYPE   struct BigInt *
 
#define CURRENT_NAME   self
 
#define PRINTER(name, base, prefix)
 
#define BASIC_BIN_OP_FLOATS(name, long_func, MAYBE_FLOAT, MAYBE_FLOAT_INV)
 
#define BASIC_BIN_OP(a, b)   BASIC_BIN_OP_FLOATS(a,b,,)
 
#define FLOAT_A(op)   else if (IS_FLOATING(argv[1])) return FLOATING_VAL(krk_long_get_double(self->value) op AS_FLOATING(argv[1]));
 
#define FLOAT_B(op)   else if (IS_FLOATING(argv[1])) return FLOATING_VAL(AS_FLOATING(argv[1]) op krk_long_get_double(self->value));
 
#define BASIC_BIN_OP_FLOAT(a, b, op)   BASIC_BIN_OP_FLOATS(a,b,FLOAT_A(op),FLOAT_B(op))
 
#define KRK_FLOAT_COMPARE(comp)   else if (IS_FLOATING(argv[1])) return BOOLEAN_VAL(krk_long_get_double(self->value) comp AS_FLOATING(argv[1]));
 
#define COMPARE_OP(name, comp)
 
#define CURRENT_CTYPE   krk_integer_type
 
#define BIND_METHOD(klass, method)   do { krk_defineNative(& _ ## klass->methods, #method, _ ## klass ## _ ## method); } while (0)
 
#define BIND_STATICMETHOD(klass, method)   do { krk_defineNativeStaticMethod(& _ ## klass->methods, #method, _ ## klass ## _ ## method); } while (0)
 
#define BIND_TRIPLET(klass, name)
 

Typedefs

typedef struct KrkLong_Internal KrkLong
 
typedef KrkLong krk_long[1]
 
typedef int(* fmtCallback) (void *, int, int *)
 

Functions

size_t krk_long_digits_in_base (KrkLong *num, int base)
 Estimate how many digits are needed to convert a long to a base. More...
 
KrkValue krk_int_from_float (double val)
 
 KRK_StaticMethod (long, __new__)
 
KrkValue _long___float__ (int, KrkValue *, int)
 
KrkValue _long___truediv__ (int, KrkValue *, int)
 
KrkValue _long___rtruediv__ (int, KrkValue *, int)
 
KrkValue _long___hash__ (int, KrkValue *, int)
 
KrkValue krk_parse_int (const char *start, size_t width, unsigned int base)
 
KrkValue _long___int__ (int, KrkValue *, int)
 
KrkValue _long___len__ (int, KrkValue *, int)
 
KrkValue _long___invert__ (int, KrkValue *, int)
 
KrkValue _long___neg__ (int, KrkValue *, int)
 
KrkValue _long___abs__ (int, KrkValue *, int)
 
KrkValue _long___pos__ (int, KrkValue *, int)
 
KrkValue krk_doFormatString (const char *typeName, KrkString *format_spec, int positive, void *abs, fmtCallback callback, fmtCallback(*prepCallback)(void *, int))
 
KrkValue _long___format__ (int, KrkValue *, int)
 
KrkValue _long_bit_count (int, KrkValue *, int)
 
KrkValue _long_bit_length (int, KrkValue *, int)
 
KrkValue _long_to_bytes (int, KrkValue *, int)
 
KrkValue _long__digit_count (int, KrkValue *, int)
 
KrkValue _long__get_digit (int, KrkValue *, int)
 
_protected int krk_long_to_int (KrkValue val, char size, void *out)
 Convert an int or long to a C integer. More...
 
KrkValue _int_bit_count (int, KrkValue *, int)
 
KrkValue _int_bit_length (int, KrkValue *, int)
 
KrkValue _int_to_bytes (int, KrkValue *, int)
 
_noexport void _createAndBind_longClass (void)
 

Detailed Description

Big ints, implemented through my own makeshift thing.

Author
K. Lange klang.nosp@m.e@to.nosp@m.aruos.nosp@m..org

Simple, slightly incomplete implementation of a 'long' type. Conceptually, several things were learned from Python: we store our longs as a sequence of 31-bit unsigned digits, combined with a signed count of digits - negative for a negative number, positive for a positive number, and 0 for 0.

TODO:

  • Expose better functions for extracting and converting native integers, which would be useful in modules that want to take 64-bit values, extracted unsigned values, etc.
  • Faster division for large divisors?
  • Shifts without multiply/divide...

Definition in file obj_long.c.

Macro Definition Documentation

◆ BASIC_BIN_OP_FLOATS

#define BASIC_BIN_OP_FLOATS (   name,
  long_func,
  MAYBE_FLOAT,
  MAYBE_FLOAT_INV 
)
Value:
KRK_Method(long,__ ## name ## __) { \
krk_long tmp; \
if (IS_long(argv[1])) krk_long_init_copy(tmp, AS_long(argv[1])->value); \
else if (IS_INTEGER(argv[1])) krk_long_init_si(tmp, AS_INTEGER(argv[1])); \
MAYBE_FLOAT \
else return NOTIMPL_VAL(); \
long_func(tmp,self->value,tmp); \
return make_long_obj(tmp); \
} \
KRK_Method(long,__r ## name ## __) { \
krk_long tmp; \
if (IS_long(argv[1])) krk_long_init_copy(tmp, AS_long(argv[1])->value); \
else if (IS_INTEGER(argv[1])) krk_long_init_si(tmp, AS_INTEGER(argv[1])); \
MAYBE_FLOAT_INV \
else return NOTIMPL_VAL(); \
long_func(tmp,tmp,self->value); \
return make_long_obj(tmp); \
} \
_noexport \
KrkValue krk_long_coerced_ ## name (krk_integer_type a, krk_integer_type b) { \
krk_long tmp_res, tmp_a, tmp_b; \
krk_long_init_si(tmp_res, 0); \
krk_long_init_si(tmp_a, a); \
krk_long_init_si(tmp_b, b); \
long_func(tmp_res, tmp_a, tmp_b); \
krk_long_clear_many(tmp_a, tmp_b, NULL); \
return make_long_obj(tmp_res); \
}

Definition at line 1451 of file obj_long.c.

◆ BIND_TRIPLET

#define BIND_TRIPLET (   klass,
  name 
)
Value:
BIND_METHOD(klass,__ ## name ## __); \
BIND_METHOD(klass,__r ## name ## __); \
krk_defineNative(&_ ## klass->methods,"__i" #name "__",_ ## klass ## ___ ## name ## __);

Definition at line 2049 of file obj_long.c.

◆ COMPARE_OP

#define COMPARE_OP (   name,
  comp 
)
Value:
KRK_Method(long,__ ## name ## __) { \
krk_long tmp; \
if (IS_long(argv[1])) krk_long_init_copy(tmp, AS_long(argv[1])->value); \
else if (IS_INTEGER(argv[1])) krk_long_init_si(tmp, AS_INTEGER(argv[1])); \
KRK_FLOAT_COMPARE(comp) \
else return NOTIMPL_VAL(); \
int cmp = krk_long_compare(self->value,tmp); \
krk_long_clear(tmp); \
return BOOLEAN_VAL(cmp comp 0); \
}

Definition at line 1603 of file obj_long.c.

◆ PRINTER

#define PRINTER (   name,
  base,
  prefix 
)
Value:
KRK_Method(long,__ ## name ## __) { \
size_t size; \
uint32_t hash; \
char * rev = krk_long_to_str(self->value, base, prefix, &size, &hash); \
return OBJECT_VAL(krk_takeStringVetted(rev,size,size,KRK_OBJ_FLAGS_STRING_ASCII,hash)); \
}
KrkString * krk_takeStringVetted(char *chars, size_t length, size_t codesLength, KrkStringType type, uint32_t hash)
Like krk_takeString but for when the caller has already calculated code lengths, hash,...
Definition: object.c:238

Definition at line 1399 of file obj_long.c.

Function Documentation

◆ _int_bit_count()

KrkValue _int_bit_count ( int  ,
KrkValue ,
int   
)

int wrapper implementations of the byte conversions.

Convert to a long and just use those versions...

Definition at line 2020 of file obj_long.c.

◆ krk_long_digits_in_base()

size_t krk_long_digits_in_base ( KrkLong num,
int  base 
)

Estimate how many digits are needed to convert a long to a base.

Dumb. Should be exact for a handful of powers of two, overestimates for everything else, so deal with that on your own...

Definition at line 821 of file obj_long.c.

◆ krk_long_to_int()

_protected int krk_long_to_int ( KrkValue  val,
char  size,
void *  out 
)

Convert an int or long to a C integer.

No overflow checking is performed in any case.

Parameters
valint or long to convert.
sizeSize in bytes of desired C integer type.
outPointer to resulting int.

Definition at line 1963 of file obj_long.c.