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 <assert.h>
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 | NEEDED_BITS 53 |
#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 | DEC_DIGIT_SIZE sizeof(digit_t) |
#define | DEC_DIGIT_CNT 9 |
#define | DEC_DIGIT_MAX 1000000000 |
#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 *) |
typedef uint32_t | digit_t |
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___pow__ (int, KrkValue *, int) |
KrkValue | _long___rpow__ (int, KrkValue *, int) |
_noexport KrkValue | krk_long_coerced_pow (krk_integer_type a, krk_integer_type b) |
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) |
KrkValue | _long___repr__ (int, KrkValue *, int) |
KrkValue | krk_double_to_string (double a, unsigned int digits, char formatter, int plus, int forcedigits) |
Convert a double to a KrkString. More... | |
KrkValue | krk_parse_float (const char *s, size_t l) |
Parse a string into a float. More... | |
KrkValue | krk_float_to_fraction (double d) |
Convert a double to a tuple of two longs. More... | |
_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.
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 | |||
) |
Definition at line 1578 of file obj_long.c.
◆ BIND_TRIPLET
#define BIND_TRIPLET | ( | klass, | |
name | |||
) |
Definition at line 3177 of file obj_long.c.
◆ COMPARE_OP
#define COMPARE_OP | ( | name, | |
comp | |||
) |
Definition at line 1799 of file obj_long.c.
◆ PRINTER
#define PRINTER | ( | name, | |
base, | |||
prefix | |||
) |
Definition at line 1527 of file obj_long.c.
Typedef Documentation
◆ digit_t
typedef uint32_t digit_t |
Huge decimals for fast conversion.
This is a lightweight implementation of decimal-based bigints that only supports addition, inplace subtraction, and multiplication (via Karatsuba). With this, we can much more quickly produce decimal conversions of (binary) longs.
Definition at line 2104 of file obj_long.c.
Function Documentation
◆ _int_bit_count()
int
wrapper implementations of the byte conversions.
Convert to a long
and just use those versions...
Definition at line 3148 of file obj_long.c.
◆ krk_double_to_string()
KrkValue krk_double_to_string | ( | double | a, |
unsigned int | digits, | ||
char | formatter, | ||
int | plus, | ||
int | forcedigits | ||
) |
Convert a double to a KrkString.
We approach the problem of string conversion by converting the mantissa of the double to a bigint. We then treat that bigint as part of a fraction with a large power-of-ten denominator, and then apply the 2^n portion represented by the exponent of the double. For n<0, we will increase the magnitude of the fraction by multiplying the top and bottom repeatedly by 10^31, so that the multiplication (actually a right shift) by the 2^n part does not lose any bits. The result of all of this is an exact representation of the numerator of "x" in "x * 10^y = m * 2^n" with a denominator that remains a large power-of-ten. We can then perform decimal string conversion on this, round the decimal result as needed, and piece together the digits to form a whole, fractional, and exponential part.
- Parameters
-
a Double value to convert. digits Desired precision, meaning varies between e/f and g. formatter printf-style formatter character: eEfFgG or ' ' plus Whether to force a sign character when value is positive. forcedigits Force trailing zeros, particularly in 'g' formatters.
- Returns
- A KrkValue representing the string.
Definition at line 2562 of file obj_long.c.
◆ krk_float_to_fraction()
KrkValue krk_float_to_fraction | ( | double | d | ) |
Convert a double to a tuple of two longs.
Turns a floating-point value into a tuple representing a ratio of two integers that is equivalent.
- Parameters
-
d Value to convert.
- Returns
- tuple(numerator,denominator)
Definition at line 2998 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
-
val int or long to convert. size Size in bytes of desired C integer type. out Pointer to resulting int.
Definition at line 3084 of file obj_long.c.
◆ krk_parse_float()
KrkValue krk_parse_float | ( | const char * | s, |
size_t | l | ||
) |
Parse a string into a float.
The approach we take here is to collect all of the digits left of the exponent (if present), convert them to a big int disregarding the radix point, then multiply or divide that by an appropriate power of ten based on the exponent and location of the radix point. The division step uses are long.__truediv__
to get accurate conversions of fractions to floats.
May raise exceptions if parsing fails, either here or in integer parsing.
- Parameters
-
s String to parse. l Length of string to parse.
- Returns
- A Kuroko float value, or None on exceptin.
Definition at line 2820 of file obj_long.c.