25 #define DIGIT_SHIFT 31
26 #define DIGIT_MAX 0x7FFFFFFF
40 static int krk_long_init_si(
KrkLong * num, int64_t val) {
50 int sign = (val < 0) ? -1 : 1;
51 uint64_t abs = (val < 0) ? -val : val;
54 if (abs <= DIGIT_MAX) {
56 num->digits = malloc(
sizeof(uint32_t));
65 while (tmp > DIGIT_MAX) {
71 num->width = cnt * sign;
72 num->digits = malloc(
sizeof(uint32_t) * cnt);
75 for (int64_t i = 0; i < cnt; ++i) {
76 num->digits[i] = (abs & DIGIT_MAX);
86 static int krk_long_init_ui(
KrkLong * num, uint64_t val) {
95 if (val <= DIGIT_MAX) {
97 num->digits = malloc(
sizeof(uint32_t));
106 while (tmp > DIGIT_MAX) {
113 num->digits = malloc(
sizeof(uint32_t) * cnt);
116 for (uint64_t i = 0; i < cnt; ++i) {
117 num->digits[i] = (val & DIGIT_MAX);
129 static int krk_long_init_many(
KrkLong *a, ...) {
135 krk_long_init_si(next, 0);
136 next = va_arg(argp,
KrkLong *);
149 static int krk_long_init_copy(
KrkLong * out,
const KrkLong * in) {
150 size_t abs_width = in->width < 0 ? -in->width : in->width;
151 out->width = in->width;
152 out->digits = out->width ? malloc(
sizeof(uint32_t) * abs_width) : NULL;
153 for (
size_t i = 0; i < abs_width; ++i) {
154 out->digits[i] = in->digits[i];
165 static int krk_long_clear(
KrkLong * num) {
166 if (num->digits) free(num->digits);
177 static int krk_long_clear_many(
KrkLong *a, ...) {
183 krk_long_clear(next);
184 next = va_arg(argp,
KrkLong *);
197 static int krk_long_resize(
KrkLong * num, ssize_t newdigits) {
198 if (newdigits == 0) {
203 size_t abs = newdigits < 0 ? -newdigits : newdigits;
204 size_t eabs = num->width < 0 ? -num->width : num->width;
205 if (num->width == 0) {
206 num->digits = calloc(
sizeof(uint32_t), newdigits);
207 }
else if (eabs < abs) {
208 num->digits = realloc(num->digits,
sizeof(uint32_t) * newdigits);
209 memset(&num->digits[eabs], 0,
sizeof(uint32_t)*(abs-eabs));
212 num->width = newdigits;
221 static int krk_long_set_sign(
KrkLong * num,
int sign) {
222 num->width = num->width < 0 ? (-num->width) * sign : num->width * sign;
232 static int krk_long_trim(
KrkLong * num) {
233 int invert = num->width < 0;
234 size_t owidth = invert ? -num->width : num->width;
235 size_t redundant = 0;
236 for (
size_t i = 0; i < owidth; i++) {
237 if (num->digits[owidth-i-1] == 0) {
245 krk_long_resize(num, owidth - redundant);
246 if (invert) krk_long_set_sign(num, -1);
260 static int krk_long_compare(
const KrkLong * a,
const KrkLong * b) {
261 if (a->width > b->width)
return 1;
262 if (b->width > a->width)
return -1;
263 int sign = a->width < 0 ? -1 : 1;
264 size_t abs_width = a->width < 0 ? -a->width : a->width;
265 for (
size_t i = 0; i < abs_width; ++i) {
266 if (a->digits[abs_width-i-1] > b->digits[abs_width-i-1])
return sign;
267 if (a->digits[abs_width-i-1] < b->digits[abs_width-i-1])
return -sign;
278 static int krk_long_compare_abs(
const KrkLong * a,
const KrkLong * b) {
279 size_t a_width = a->width < 0 ? -a->width : a->width;
280 size_t b_width = b->width < 0 ? -b->width : b->width;
281 if (a_width > b_width)
return 1;
282 if (b_width > a_width)
return -1;
283 size_t abs_width = a_width;
284 for (
size_t i = 0; i < abs_width; ++i) {
285 if (a->digits[abs_width-i-1] > b->digits[abs_width-i-1])
return 1;
286 if (a->digits[abs_width-i-1] < b->digits[abs_width-i-1])
return -1;
298 size_t awidth = a->width < 0 ? -a->width : a->width;
299 size_t bwidth = b->width < 0 ? -b->width : b->width;
300 size_t owidth = awidth < bwidth ? bwidth + 1 : awidth + 1;
302 krk_long_resize(res, owidth);
303 for (
size_t i = 0; i < owidth - 1; ++i) {
304 uint32_t out = (i < awidth ? a->digits[i] : 0) + (i < bwidth ? b->digits[i] : 0) + carry;
305 res->digits[i] = out & DIGIT_MAX;
306 carry = out > DIGIT_MAX;
309 res->digits[owidth-1] = 1;
311 krk_long_resize(res, owidth - 1);
323 size_t awidth = a->width < 0 ? -a->width : a->width;
324 size_t bwidth = b->width < 0 ? -b->width : b->width;
325 size_t owidth = awidth;
327 krk_long_resize(res, owidth);
331 for (
size_t i = 0; i < owidth; ++i) {
333 int64_t a_digit = (int64_t)(i < awidth ? a->digits[i] : 0) - carry;
334 int64_t b_digit = i < bwidth ? b->digits[i] : 0;
335 if (a_digit < b_digit) {
336 a_digit += (int64_t)1 << DIGIT_SHIFT;
342 res->digits[i] = (a_digit - b_digit) & DIGIT_MAX;
354 ssize_t width = a->width;
355 uint32_t * digits = a->digits;
357 a->digits = b->digits;
364 #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)
365 #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)
366 #define FINISH_OUTPUT(res) do { if (_swap_out_ ## res) { _swap(_swap_out_ ## res, res); krk_long_clear(&_tmp_out_ ## res); } } while (0)
374 PREP_OUTPUT(res,a,b);
378 krk_long_init_copy(res,b);
381 }
else if (b->width == 0) {
383 krk_long_init_copy(res,a);
388 if (a->width < 0 && b->width > 0) {
389 switch (krk_long_compare_abs(a,b)) {
391 _sub_big_small(res,b,a);
392 krk_long_set_sign(res,1);
396 _sub_big_small(res,a,b);
397 krk_long_set_sign(res,-1);
404 }
else if (a->width > 0 && b->width < 0) {
405 switch (krk_long_compare_abs(a,b)) {
407 _sub_big_small(res,b,a);
408 krk_long_set_sign(res,-1);
412 _sub_big_small(res,a,b);
413 krk_long_set_sign(res,1);
423 int sign = a->width < 0 ? -1 : 1;
424 if (krk_long_add_ignore_sign(res,a,b)) {
428 krk_long_set_sign(res,sign);
439 PREP_OUTPUT(res,a,b);
442 krk_long_init_copy(res,b);
443 krk_long_set_sign(res, b->width < 0 ? 1 : -1);
446 }
else if (b->width == 0) {
448 krk_long_init_copy(res,a);
453 if ((a->width < 0) != (b->width < 0)) {
454 if (krk_long_add_ignore_sign(res,a,b)) { FINISH_OUTPUT(res);
return 1; }
455 krk_long_set_sign(res,a->width < 0 ? -1 : 1);
461 switch (krk_long_compare_abs(a,b)) {
467 _sub_big_small(res,a,b);
468 if (a->width < 0) krk_long_set_sign(res, -1);
472 _sub_big_small(res,b,a);
473 if (b->width > 0) krk_long_set_sign(res, -1);
478 __builtin_unreachable();
486 static int krk_long_zero(
KrkLong * num) {
487 size_t abs_width = num->width < 0 ? -num->width : num->width;
488 for (
size_t i = 0; i < abs_width; ++i) {
505 size_t awidth = a->width < 0 ? -a->width : a->width;
506 size_t bwidth = b->width < 0 ? -b->width : b->width;
508 krk_long_resize(res, awidth+bwidth);
511 for (
size_t i = 0; i < bwidth; ++i) {
512 uint64_t b_digit = b->digits[i];
514 for (
size_t j = 0; j < awidth; ++j) {
515 uint64_t a_digit = a->digits[j];
516 uint64_t tmp = carry + a_digit * b_digit + res->digits[i+j];
517 carry = tmp >> DIGIT_SHIFT;
518 res->digits[i+j] = tmp & DIGIT_MAX;
520 res->digits[i + awidth] = carry;
534 PREP_OUTPUT(res,a,b);
538 krk_long_init_copy(res,a);
545 krk_long_init_copy(res,b);
550 if (_mul_abs(res,a,b)) {
555 if ((a->width < 0) == (b->width < 0)) {
556 krk_long_set_sign(res,1);
558 krk_long_set_sign(res,-1);
570 static int _lshift_one(
KrkLong * in) {
571 if (in->width == 0) {
575 size_t abs_width = in->width < 0 ? -in->width : in->width;
576 size_t out_width = abs_width;
578 if (in->digits[abs_width-1] >> (DIGIT_SHIFT - 1)) {
582 krk_long_resize(in, out_width);
586 for (
size_t i = 0; i < abs_width; ++i) {
587 uint32_t digit = in->digits[i];
588 in->digits[i] = ((digit << 1) + carry) & DIGIT_MAX;
589 carry = (digit >> (DIGIT_SHIFT -1));
593 in->digits[out_width-1] = 1;
606 static size_t _bits_in(
const KrkLong * num) {
607 if (num->width == 0)
return 0;
609 size_t abs_width = num->width < 0 ? -num->width : num->width;
613 uint32_t digit = num->digits[abs_width-1];
619 return c + (abs_width-1) * DIGIT_SHIFT;
625 static size_t _bit_is_set(
const KrkLong * num,
size_t bit) {
626 size_t digit_offset = bit / DIGIT_SHIFT;
627 size_t digit_bit = bit % DIGIT_SHIFT;
628 return !!(num->digits[digit_offset] & (1 << digit_bit));
634 static int _bit_set_zero(
KrkLong * num,
int val) {
635 if (num->width == 0) {
637 krk_long_init_si(num, !!val);
641 num->digits[0] = (num->digits[0] & ~1) | (!!val);
653 static int krk_long_bit_set(
KrkLong * num,
size_t bit) {
654 size_t abs_width = num->width < 0 ? -num->width : num->width;
655 size_t digit_offset = bit / DIGIT_SHIFT;
656 size_t digit_bit = bit % DIGIT_SHIFT;
658 if (digit_offset >= abs_width) {
659 krk_long_resize(num, digit_offset+1);
660 for (
size_t i = abs_width; i < digit_offset + 1; ++i) {
665 num->digits[digit_offset] |= (1 << digit_bit);
684 krk_long_clear(quot);
687 if (b->width == 0)
return 1;
688 if (a->width == 0)
return 0;
690 size_t awidth = a->width < 0 ? -a->width : a->width;
691 size_t bwidth = b->width < 0 ? -b->width : b->width;
693 if (bwidth == 1 && b->digits[0] == 1) {
694 krk_long_init_copy(quot, a);
695 krk_long_set_sign(quot, 1);
699 if (awidth < bwidth) {
700 krk_long_init_copy(rem, a);
701 krk_long_set_sign(rem, 1);
706 krk_long_init_copy(&absa, a);
707 krk_long_set_sign(&absa, 1);
708 krk_long_init_copy(&absb, b);
709 krk_long_set_sign(&absb, 1);
712 uint64_t remainder = 0;
713 for (
size_t i = 0; i < awidth; ++i) {
714 size_t _i = awidth - i - 1;
715 remainder = (remainder << DIGIT_SHIFT) | absa.digits[_i];
716 absa.digits[_i] = (uint32_t)(remainder / absb.digits[0]) & DIGIT_MAX;
717 remainder -= (uint64_t)(absa.digits[_i]) * absb.digits[0];
720 krk_long_init_si(rem, remainder);
724 krk_long_clear_many(&absa, &absb, NULL);
728 size_t bits = _bits_in(a);
729 for (
size_t i = 0; i < bits; ++i) {
730 size_t _i = bits - i - 1;
735 int is_set = _bit_is_set(&absa, _i);
736 _bit_set_zero(rem, is_set);
737 if (krk_long_compare(rem,&absb) >= 0) {
738 _sub_big_small(rem,rem,&absb);
739 krk_long_bit_set(quot, _i);
744 krk_long_clear_many(&absa,&absb,NULL);
760 PREP_OUTPUT(quot,a,b);
761 PREP_OUTPUT(rem,a,b);
762 if (_div_abs(quot,rem,a,b)) {
768 if ((a->width < 0) != (b->width < 0)) {
772 krk_long_init_si(&one, 1);
773 krk_long_add(quot, quot, &one);
774 _sub_big_small(rem, b, rem);
775 krk_long_clear(&one);
779 krk_long_set_sign(quot, -1);
783 krk_long_set_sign(rem, -1);
797 PREP_OUTPUT1(out,in);
799 krk_long_init_copy(out, in);
800 krk_long_set_sign(out, 1);
810 static int krk_long_sign(
const KrkLong * num) {
811 if (num->width == 0)
return 0;
812 return num->width < 0 ? -1 : 1;
822 if (num->width == 0)
return 1;
824 size_t bits = _bits_in(num);
826 if (base < 4)
return bits;
827 if (base < 8)
return (bits+1)/2;
828 if (base < 16)
return (bits+2)/3;
829 if (base == 16)
return (bits+3)/4;
836 static int64_t krk_long_medium(
KrkLong * num) {
837 if (num->width == 0)
return 0;
839 if (num->width < 0) {
840 uint64_t val = num->digits[0];
841 if (num->width < -1) {
842 val |= (num->digits[1]) << 31;
846 uint64_t val = num->digits[0];
847 if (num->width > 1) {
848 val |= (num->digits[1]) << 31;
862 size_t awidth = a->width < 0 ? -a->width : a->width;
863 size_t bwidth = b->width < 0 ? -b->width : b->width;
864 size_t owidth = ((awidth > bwidth) ? awidth : bwidth) + 1;
866 int aneg = (a->width < 0);
867 int bneg = (b->width < 0);
871 case '|': rneg = aneg | bneg;
break;
872 case '^': rneg = aneg ^ bneg;
break;
873 case '&': rneg = aneg & bneg;
break;
876 krk_long_resize(res, owidth);
878 int acarry = aneg ? 1 : 0;
879 int bcarry = bneg ? 1 : 0;
880 int rcarry = rneg ? 1 : 0;
882 for (
size_t i = 0; i < owidth; ++i) {
883 uint32_t a_digit = (i < awidth ? a->digits[i] : 0);
884 a_digit = aneg ? ((a_digit ^ DIGIT_MAX) + acarry) : a_digit;
885 acarry = a_digit >> DIGIT_SHIFT;
887 uint32_t b_digit = (i < bwidth ? b->digits[i] : 0);
888 b_digit = bneg ? ((b_digit ^ DIGIT_MAX) + bcarry) : b_digit;
889 bcarry = b_digit >> DIGIT_SHIFT;
893 case '|': r = a_digit | b_digit;
break;
894 case '^': r = a_digit ^ b_digit;
break;
895 case '&': r = a_digit & b_digit;
break;
896 default: __builtin_unreachable();
899 r = rneg ? (((r & DIGIT_MAX) ^ DIGIT_MAX) + rcarry) : r;
900 res->digits[i] = r & DIGIT_MAX;
901 rcarry = r >> DIGIT_SHIFT;
907 krk_long_set_sign(res,-1);
917 PREP_OUTPUT(res,a,b);
920 krk_long_init_copy(res,b);
923 }
else if (b->width == 0) {
925 krk_long_init_copy(res,a);
930 int out = do_bin_op(res,a,b,
'|');
939 PREP_OUTPUT(res,a,b);
940 int out = do_bin_op(res,a,b,
'^');
949 PREP_OUTPUT(res,a,b);
952 krk_long_init_copy(res,a);
955 }
else if (b->width == 0) {
957 krk_long_init_copy(res,b);
962 int out = do_bin_op(res,a,b,
'&');
970 static uint32_t _div_inplace(
KrkLong * a, uint32_t base) {
974 size_t awidth = a->width;
975 uint64_t remainder = 0;
976 for (
size_t i = 0; i < awidth; ++i) {
977 size_t _i = awidth - i - 1;
978 remainder = (remainder << DIGIT_SHIFT) | a->digits[_i];
979 a->digits[_i] = (uint32_t)(remainder / base) & DIGIT_MAX;
980 remainder -= (uint64_t)(a->digits[_i]) * base;
987 static const char _vals[] =
"0123456789abcdef";
988 static char * _fast_conversion(
const KrkLong * abs,
unsigned int bits,
char * writer) {
989 uint64_t buf = abs->digits[0];
990 uint32_t cnt = DIGIT_SHIFT;
994 while (ind < abs->width || buf) {
995 if (ind < abs->width && cnt < bits) {
996 buf |= (uint64_t)abs->digits[ind] << (uint64_t)cnt;
1001 out = buf & ((1 << bits) - 1);
1005 *writer++ = _vals[out];
1014 static char * krk_long_to_str(
const KrkLong * n,
int _base,
const char * prefix,
size_t *size, uint32_t *_hash) {
1017 krk_long_init_si(&abs, 0);
1018 krk_long_abs(&abs, n);
1020 int sign = krk_long_sign(n);
1023 char * tmp = malloc(len);
1024 char * writer = tmp;
1030 case 2: writer = _fast_conversion(&abs,1,writer);
break;
1031 case 4: writer = _fast_conversion(&abs,2,writer);
break;
1032 case 8: writer = _fast_conversion(&abs,3,writer);
break;
1033 case 16: writer = _fast_conversion(&abs,4,writer);
break;
1035 while (krk_long_sign(&abs) > 0) {
1036 uint32_t rem = _div_inplace(&abs,_base);
1037 *writer++ = _vals[rem];
1042 while (*prefix) { *writer++ = *prefix++; }
1043 if (sign < 0) *writer++ =
'-';
1045 char * rev = malloc(len);
1048 while (writer != tmp) {
1050 krk_hash_advance(hash,*out);
1058 krk_long_clear(&abs);
1059 *size = strlen(rev);
1064 static const unsigned char _convert_table[256] = {
1065 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
1066 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,255,255,255,255,255,255,
1067 255, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,255,255,255,255,255,
1068 255, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,255,255,255,255,255,
1069 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
1070 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
1071 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
1072 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
1075 static int is_valid(
int base, uint8_t c) {
1076 return _convert_table[c] < base;
1079 static int convert_digit(uint8_t c) {
1080 return _convert_table[c];
1083 static int is_whitespace(
char c) {
1085 return (c ==
' ' || c ==
'\t' || c ==
'\n' || c ==
'\r');
1096 static int krk_long_parse_string(
const char * str,
KrkLong * num,
unsigned int base,
size_t len) {
1097 const char * end = str + len;
1098 const char * c = str;
1102 while (c < end && is_whitespace(*c)) c++;
1105 while (end > c && is_whitespace(end[-1])) end--;
1115 }
else if (*c ==
'+') {
1132 krk_long_init_si(num, 0);
1136 if (*c ==
'x' || *c ==
'X') {
1139 }
else if (*c ==
'o' || *c ==
'O') {
1142 }
else if (*c ==
'b' || *c ==
'B') {
1155 if (base == 1 || base > 36) {
1159 krk_long_init_si(num, 0);
1161 if (base == 2 || base == 4 || base == 8 || base == 16 || base == 32) {
1164 case 2: bits = 1;
break;
1165 case 4: bits = 2;
break;
1166 case 8: bits = 3;
break;
1167 case 16:bits = 4;
break;
1168 case 32:bits = 5;
break;
1171 for (
const char * x = c; x < end; ++x) {
1172 if (*x ==
'_')
continue;
1173 if (unlikely(!is_valid(base, *x))) {
1174 krk_long_clear(num);
1181 krk_long_clear(num);
1185 size_t digit_offset = (digits * bits - 1) / DIGIT_SHIFT;
1186 krk_long_resize(num, digit_offset + 1);
1190 const char * x = end;
1193 while (x != c && x[-1] ==
'_') x--;
1195 while (x != c || buf) {
1196 while (cnt < DIGIT_SHIFT && x > c) {
1197 buf |= (uint64_t)convert_digit(x[-1]) << cnt;
1200 while (x != c && x[-1] ==
'_') x--;
1203 num->digits[i++] = buf & DIGIT_MAX;
1205 buf >>= DIGIT_SHIFT;
1211 krk_long_init_si(&_base, 0);
1212 krk_long_init_si(&scratch, 0);
1214 while (c < end && *c) {
1216 uint64_t basediv = 1;
1217 while (c < end && *c && (basediv * base < 0x10000000000000UL)) {
1218 if (*c ==
'_') { c++;
continue; }
1219 if (!is_valid(base, *c)) {
1220 krk_long_clear_many(&_base, &scratch, num, NULL);
1226 accum += convert_digit(*c);
1229 krk_long_init_ui(&_base, basediv);
1230 krk_long_mul(num, num, &_base);
1231 krk_long_clear_many(&scratch, &_base, NULL);
1232 krk_long_init_ui(&scratch, accum);
1233 krk_long_add(num, num, &scratch);
1236 krk_long_clear_many(&_base, &scratch, NULL);
1240 krk_long_set_sign(num, -1);
1253 #define AS_long(o) ((struct BigInt *)AS_OBJECT(o))
1254 #define IS_long(o) (krk_isInstanceOf(o, KRK_BASE_CLASS(long)))
1256 #define CURRENT_CTYPE struct BigInt *
1257 #define CURRENT_NAME self
1259 static KrkValue make_long(krk_integer_type t) {
1262 krk_long_init_si(self->value, t);
1267 krk_long_clear(((
struct BigInt*)
self)->value);
1270 #ifndef KRK_NO_FLOAT
1271 KrkValue krk_int_from_float(
double val);
1274 KRK_StaticMethod(
long,__new__) {
1275 FUNCTION_TAKES_AT_MOST(2);
1278 return make_long(0);
1279 }
else if (IS_INTEGER(argv[1])) {
1280 return make_long(AS_INTEGER(argv[1]));
1281 }
else if (IS_BOOLEAN(argv[1])) {
1282 return make_long(AS_BOOLEAN(argv[1]));
1283 #ifndef KRK_NO_FLOAT
1284 }
else if (IS_FLOATING(argv[1])) {
1285 return krk_int_from_float(AS_FLOATING(argv[1]));
1287 }
else if (IS_STRING(argv[1])) {
1291 if (krk_long_parse_string(AS_CSTRING(argv[1]),self->value,0,AS_STRING(argv[1])->length)) {
1292 return krk_runtimeError(
vm.exceptions->valueError,
"invalid literal for long() with base 0: %R", argv[1]);
1295 }
else if (IS_long(argv[1])) {
1298 krk_long_init_copy(self->value,AS_long(argv[1])->value);
1301 return krk_runtimeError(
vm.exceptions->typeError,
"%s() argument must be a string or a number, not '%T'",
"int", argv[1]);
1305 #ifndef KRK_NO_FLOAT
1314 static double krk_long_get_double(
const KrkLong * value) {
1315 size_t awidth = value->width < 0 ? -value->width : value->width;
1316 if (awidth == 0)
return 0.0;
1318 uint64_t sign = value->width < 0 ? 1 : 0;
1321 uint64_t mantissa = 0;
1322 uint64_t high = value->digits[awidth-1];
1323 uint64_t med = awidth > 1 ? value->digits[awidth-2] : 0;
1324 uint64_t low = awidth > 2 ? value->digits[awidth-3] : 0;
1327 for (s = DIGIT_SHIFT; s >= 0; s--) {
1328 if (high & (1 << s))
break;
1331 int high_shift = 52 - s;
1332 int med_shift = 21 - s;
1333 int low_shift = 10 + s;
1335 mantissa |= high << high_shift;
1336 mantissa |= med_shift >= 0 ? (med << med_shift) : (med >> -med_shift);
1337 mantissa |= low >> low_shift;
1339 mantissa &= 0xfffffffffffffUL;
1341 uint64_t exp = (s + (awidth - 1) * DIGIT_SHIFT) + 0x3FF;
1344 krk_runtimeError(
vm.exceptions->valueError,
"overflow, too large for float conversion");
1348 uint64_t val = (sign << 63) | (exp << 52) | mantissa;
1350 union { uint64_t asInt;
double asDbl; } u = {val};
1354 KRK_Method(
long,__float__) {
1355 return FLOATING_VAL(krk_long_get_double(self->value));
1359 if (_bottom->width == 0)
return krk_runtimeError(
vm.exceptions->valueError,
"float division by zero");
1360 if (_top->width == 0)
return FLOATING_VAL(0);
1363 krk_long_init_si(&rem, 0);
1364 krk_long_init_copy(&top, _top);
1365 krk_long_init_copy(&bottom, _bottom);
1368 int negative = (krk_long_sign(&top) < 0) != (krk_long_sign(&bottom) < 0);
1371 krk_long_set_sign(&top, 1);
1372 krk_long_set_sign(&bottom, 1);
1378 #define NEEDED_BITS 53
1379 int bits_wanted = NEEDED_BITS;
1380 size_t bits = _bits_in(&top);
1381 for (ssize_t i = 0; bits_wanted >= 0; ++i) {
1382 ssize_t _i = bits - i - 1;
1384 _bit_set_zero(&rem, (_i >= 0 ? _bit_is_set(&top, _i) : 0));
1385 if (krk_long_compare(&rem,&bottom) >= 0) {
1386 if (bits_wanted == NEEDED_BITS) {
1387 exp = 1023 + (bits - i - 1);
1389 _sub_big_small(&rem,&rem,&bottom);
1390 quot |= (1ULL << bits_wanted);
1392 }
else if (bits_wanted != NEEDED_BITS) {
1398 if (exp < 1) quot >>= -exp + 1;
1399 if ((quot & 1) && !(quot & 2)) {
1400 if (rem.width != 0) quot += 2;
1401 }
else if (quot & 1) quot += 2;
1403 if (exp < 1) quot <<= -exp + 1;
1404 if (quot & (1ULL << 54)) {
1406 quot = (1ULL << 53);
1409 krk_long_clear_many(&rem, &top, &bottom, NULL);
1414 quot = 0x1fffffffffffffULL;
1416 }
else if (exp < 1 && exp >= -52) {
1419 quot |= 0x10000000000000ULL;
1421 }
else if (exp < -52) {
1423 quot = 0x10000000000000ULL;
1428 if (negative) exp |= 2048;
1433 union {
double d; uint64_t u; } val = {.u = quot};
1435 return FLOATING_VAL(val.d);
1438 static KrkValue checked_float_div(
double top,
double bottom) {
1439 if (unlikely(bottom == 0.0))
return krk_runtimeError(
vm.exceptions->valueError,
"float division by zero");
1440 return FLOATING_VAL(top/bottom);
1443 KRK_Method(
long,__truediv__) {
1445 if (IS_long(argv[1])) krk_long_init_copy(tmp, AS_long(argv[1])->value);
1446 else if (IS_INTEGER(argv[1])) krk_long_init_si(tmp, AS_INTEGER(argv[1]));
1447 else if (IS_FLOATING(argv[1]))
return checked_float_div(krk_long_get_double(self->value), AS_FLOATING(argv[1]));
1448 else return NOTIMPL_VAL();
1449 KrkValue result = _krk_long_truediv(self->value,tmp);
1450 krk_long_clear(tmp);
1454 KRK_Method(
long,__rtruediv__) {
1456 if (IS_long(argv[1])) krk_long_init_copy(tmp, AS_long(argv[1])->value);
1457 else if (IS_INTEGER(argv[1])) krk_long_init_si(tmp, AS_INTEGER(argv[1]));
1458 else if (IS_FLOATING(argv[1]))
return checked_float_div(AS_FLOATING(argv[1]), krk_long_get_double(self->value));
1459 else return NOTIMPL_VAL();
1460 KrkValue result = _krk_long_truediv(tmp,self->value);
1461 krk_long_clear(tmp);
1465 static void _krk_long_pow(krk_long out, krk_long a, krk_long b);
1473 static KrkValue _krk_long_pow_internal(krk_long a, krk_long b) {
1475 krk_long_init_si(tmp,0);
1476 if (krk_long_sign(b) < 0) {
1480 krk_long_init_si(ex,0);
1481 krk_long_init_copy(ex,b);
1482 krk_long_set_sign(ex,1);
1483 _krk_long_pow(tmp,a,ex);
1485 krk_long_init_si(ex,1);
1486 KrkValue result = _krk_long_truediv(ex,tmp);
1488 krk_long_clear(tmp);
1492 _krk_long_pow(tmp,a,b);
1493 return make_long_obj(tmp);
1496 KRK_Method(
long,__pow__) {
1498 if (IS_long(argv[1])) krk_long_init_copy(tmp, AS_long(argv[1])->value);
1499 else if (IS_INTEGER(argv[1])) krk_long_init_si(tmp, AS_INTEGER(argv[1]));
1500 else return NOTIMPL_VAL();
1501 KrkValue result = _krk_long_pow_internal(self->value,tmp);
1502 krk_long_clear(tmp);
1506 KRK_Method(
long,__rpow__) {
1508 if (IS_long(argv[1])) krk_long_init_copy(tmp, AS_long(argv[1])->value);
1509 else if (IS_INTEGER(argv[1])) krk_long_init_si(tmp, AS_INTEGER(argv[1]));
1510 else return NOTIMPL_VAL();
1511 KrkValue result = _krk_long_pow_internal(tmp,self->value);
1512 krk_long_clear(tmp);
1517 KrkValue krk_long_coerced_pow(krk_integer_type a, krk_integer_type b) {
1518 krk_long tmp_a, tmp_b;
1519 krk_long_init_si(tmp_a, a);
1520 krk_long_init_si(tmp_b, b);
1521 KrkValue result = _krk_long_pow_internal(tmp_a,tmp_b);
1522 krk_long_clear_many(tmp_a, tmp_b, NULL);
1527 #define PRINTER(name,base,prefix) \
1528 KRK_Method(long,__ ## name ## __) { \
1531 char * rev = krk_long_to_str(self->value, base, prefix, &size, &hash); \
1532 return OBJECT_VAL(krk_takeStringVetted(rev,size,size,KRK_OBJ_FLAGS_STRING_ASCII,hash)); \
1535 PRINTER(hex,16,
"x0")
1539 KRK_Method(
long,__hash__) {
1540 return INTEGER_VAL((uint32_t)(krk_long_medium(self->value)));
1544 krk_integer_type maybe = 0;
1545 if (val->width == 0) {
1547 }
else if (val->width == 1) {
1548 maybe = val->digits[0];
1549 }
else if (val->width == -1) {
1550 maybe = -(int64_t)val->digits[0];
1551 }
else if (val->width == 2 && (val->digits[1] & 0xFFFF0000) == 0) {
1552 maybe = ((uint64_t)val->digits[1] << 31) | val->digits[0];
1553 }
else if (val->width == -2 && (val->digits[1] & 0xFFFF0000) == 0) {
1554 maybe = -(((uint64_t)val->digits[1] << 31) | val->digits[0]);
1557 *AS_long(
krk_peek(0))->value = *val;
1561 krk_long_clear(val);
1562 return INTEGER_VAL(maybe);
1565 KrkValue krk_parse_int(
const char * start,
size_t width,
unsigned int base) {
1567 if (krk_long_parse_string(start, &_value, base, width)) {
1571 return make_long_obj(&_value);
1574 KRK_Method(
long,__int__) {
1575 return INTEGER_VAL(krk_long_medium(self->value));
1578 #define BASIC_BIN_OP_FLOATS(name, long_func, MAYBE_FLOAT, MAYBE_FLOAT_INV) \
1579 KRK_Method(long,__ ## name ## __) { \
1581 if (IS_long(argv[1])) krk_long_init_copy(tmp, AS_long(argv[1])->value); \
1582 else if (IS_INTEGER(argv[1])) krk_long_init_si(tmp, AS_INTEGER(argv[1])); \
1584 else return NOTIMPL_VAL(); \
1585 long_func(tmp,self->value,tmp); \
1586 return make_long_obj(tmp); \
1588 KRK_Method(long,__r ## name ## __) { \
1590 if (IS_long(argv[1])) krk_long_init_copy(tmp, AS_long(argv[1])->value); \
1591 else if (IS_INTEGER(argv[1])) krk_long_init_si(tmp, AS_INTEGER(argv[1])); \
1593 else return NOTIMPL_VAL(); \
1594 long_func(tmp,tmp,self->value); \
1595 return make_long_obj(tmp); \
1598 KrkValue krk_long_coerced_ ## name (krk_integer_type a, krk_integer_type b) { \
1599 krk_long tmp_res, tmp_a, tmp_b; \
1600 krk_long_init_si(tmp_res, 0); \
1601 krk_long_init_si(tmp_a, a); \
1602 krk_long_init_si(tmp_b, b); \
1603 long_func(tmp_res, tmp_a, tmp_b); \
1604 krk_long_clear_many(tmp_a, tmp_b, NULL); \
1605 return make_long_obj(tmp_res); \
1608 #define BASIC_BIN_OP(a,b) BASIC_BIN_OP_FLOATS(a,b,,)
1609 #ifndef KRK_NO_FLOAT
1610 #define FLOAT_A(op) else if (IS_FLOATING(argv[1])) return FLOATING_VAL(krk_long_get_double(self->value) op AS_FLOATING(argv[1]));
1611 #define FLOAT_B(op) else if (IS_FLOATING(argv[1])) return FLOATING_VAL(AS_FLOATING(argv[1]) op krk_long_get_double(self->value));
1613 #define FLOAT_A(op) else if (IS_FLOATING(argv[1])) return krk_runtimeError(vm.exceptions->valueError, "no float support");
1614 #define FLOAT_B(op) else if (IS_FLOATING(argv[1])) return krk_runtimeError(vm.exceptions->valueError, "no float support");
1616 #define BASIC_BIN_OP_FLOAT(a,b,op) BASIC_BIN_OP_FLOATS(a,b,FLOAT_A(op),FLOAT_B(op))
1618 BASIC_BIN_OP_FLOAT(add,krk_long_add,+)
1619 BASIC_BIN_OP_FLOAT(sub,krk_long_sub,-)
1620 BASIC_BIN_OP_FLOAT(mul,krk_long_mul,*)
1621 BASIC_BIN_OP(or, krk_long_or)
1622 BASIC_BIN_OP(xor,krk_long_xor)
1623 BASIC_BIN_OP(and,krk_long_and)
1625 static
void _krk_long_lshift_z(krk_long out, krk_long val,
size_t amount) {
1627 krk_long_clear(out);
1628 krk_long_init_copy(out,val);
1632 int64_t count = _bits_in(val);
1633 krk_long_clear(out);
1634 if (count == 0)
return;
1636 size_t offset = amount % 31;
1637 size_t cycles = amount / 31;
1638 ssize_t w = val->width < 0 ? -val->width : val->width;
1639 krk_long_bit_set(out, count - 1 + amount);
1642 for (ssize_t i = 0; i < w; ++i) {
1643 out->digits[i+cycles] = val->digits[i];
1646 uint32_t shift_in = 0;
1647 for (ssize_t i = 0; i < w; ++i) {
1648 out->digits[i+cycles] = ((val->digits[i] << offset) & DIGIT_MAX) | shift_in;
1649 shift_in = (val->digits[i] >> (31 - offset)) & DIGIT_MAX;
1652 out->digits[w+cycles] = shift_in;
1656 if (krk_long_sign(val) < 0) krk_long_set_sign(out,-1);
1659 static void _krk_long_lshift(krk_long out, krk_long val, krk_long shift) {
1660 if (krk_long_sign(shift) < 0) {
krk_runtimeError(
vm.exceptions->valueError,
"negative shift count");
return; }
1661 int64_t amount = krk_long_medium(shift);
1662 _krk_long_lshift_z(out,val,amount);
1665 static void _krk_long_rshift_z(krk_long out, krk_long val,
size_t amount) {
1667 krk_long_clear(out);
1668 krk_long_init_copy(out,val);
1672 int64_t count = _bits_in(val);
1673 krk_long_clear(out);
1674 if (count == 0)
return;
1676 if (amount < (
size_t)count) {
1677 size_t offset = amount % 31;
1678 size_t cycles = amount / 31;
1679 ssize_t w = val->width < 0 ? -val->width : val->width;
1680 krk_long_bit_set(out, count - 1 - amount);
1683 for (ssize_t i = cycles; i < w; ++i) {
1684 out->digits[i-cycles] = val->digits[i];
1687 out->digits[0] = (val->digits[cycles] >> offset) & DIGIT_MAX;
1688 for (
size_t i = 1; i < (size_t)out->width; ++i) {
1689 out->digits[i-1] |= (val->digits[i+cycles] << (31 - offset)) & DIGIT_MAX;
1690 out->digits[i] = (val->digits[i+cycles] >> offset) & DIGIT_MAX;
1692 if (out->width+cycles < (
size_t)w) {
1693 out->digits[out->width-1] |= (val->digits[out->width+cycles] << (31 - offset)) & DIGIT_MAX;
1698 if (krk_long_sign(val) < 0) {
1700 krk_long_init_si(&one, 1);
1701 krk_long_add(out,out,&one);
1702 krk_long_set_sign(out,-1);
1703 krk_long_clear(&one);
1707 static void _krk_long_rshift(krk_long out, krk_long val, krk_long shift) {
1708 if (krk_long_sign(shift) < 0) {
krk_runtimeError(
vm.exceptions->valueError,
"negative shift count");
return; }
1709 int64_t amount = krk_long_medium(shift);
1710 _krk_long_rshift_z(out, val, amount);
1713 static void _krk_long_mod(krk_long out, krk_long a, krk_long b) {
1714 if (krk_long_sign(b) == 0) {
krk_runtimeError(
vm.exceptions->valueError,
"integer division or modulo by zero");
return; }
1716 krk_long_init_si(garbage,0);
1717 krk_long_div_rem(garbage,out,a,b);
1718 krk_long_clear(garbage);
1721 static void _krk_long_div(krk_long out, krk_long a, krk_long b) {
1722 if (krk_long_sign(b) == 0) {
krk_runtimeError(
vm.exceptions->valueError,
"integer division or modulo by zero");
return; }
1724 krk_long_init_si(garbage,0);
1725 krk_long_div_rem(out,garbage,a,b);
1726 krk_long_clear(garbage);
1729 static void _krk_long_pow(krk_long out, krk_long a, krk_long b) {
1730 if (krk_long_sign(b) == 0) {
1731 krk_long_clear(out);
1732 krk_long_init_si(out, 1);
1736 if (krk_long_sign(b) < 0) {
1754 PREP_OUTPUT(out,a,b);
1756 krk_long_clear(out);
1757 krk_long_init_si(out, 1);
1760 krk_long_init_si(scratch, 0);
1762 for (ssize_t i = b[0].width-1; i >= 0; --i) {
1763 uint32_t b_i = b[0].digits[i];
1765 for (
size_t j = (uint32_t)1 << (DIGIT_SHIFT-1); j != 0; j >>= 1) {
1766 krk_long_mul(scratch, out, out);
1767 _swap(out, scratch);
1770 krk_long_mul(out, out, a);
1776 krk_long_clear_many(scratch, out, NULL);
1784 krk_long_clear(scratch);
1788 BASIC_BIN_OP(lshift,_krk_long_lshift)
1789 BASIC_BIN_OP(rshift,_krk_long_rshift)
1790 BASIC_BIN_OP(mod,_krk_long_mod)
1791 BASIC_BIN_OP(floordiv,_krk_long_div)
1793 #ifndef KRK_NO_FLOAT
1794 #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]));
1796 #define KRK_FLOAT_COMPARE(comp)
1799 #define COMPARE_OP(name, comp) \
1800 KRK_Method(long,__ ## name ## __) { \
1802 if (IS_long(argv[1])) krk_long_init_copy(tmp, AS_long(argv[1])->value); \
1803 else if (IS_INTEGER(argv[1])) krk_long_init_si(tmp, AS_INTEGER(argv[1])); \
1804 KRK_FLOAT_COMPARE(comp) \
1805 else return NOTIMPL_VAL(); \
1806 int cmp = krk_long_compare(self->value,tmp); \
1807 krk_long_clear(tmp); \
1808 return BOOLEAN_VAL(cmp comp 0); \
1820 KRK_Method(
long,__len__) {
1821 return INTEGER_VAL(krk_long_sign(self->value));
1824 KRK_Method(
long,__invert__) {
1826 krk_long_init_copy(&tmp, self->value);
1827 krk_long_init_si(&one, 1);
1828 krk_long_add(&tmp, &tmp, &one);
1829 krk_long_set_sign(&tmp, tmp.width > 0 ? -1 : 1);
1830 krk_long_clear(&one);
1831 return make_long_obj(&tmp);
1834 KRK_Method(
long,__neg__) {
1836 krk_long_init_copy(&tmp, self->value);
1837 krk_long_set_sign(&tmp, tmp.width > 0 ? -1 : 1);
1838 return make_long_obj(&tmp);
1841 KRK_Method(
long,__abs__) {
1843 krk_long_init_copy(&tmp, self->value);
1844 krk_long_set_sign(&tmp, 1);
1845 return make_long_obj(&tmp);
1848 KRK_Method(
long,__pos__) {
1852 typedef int (*fmtCallback)(
void *, int,
int *);
1853 KrkValue krk_doFormatString(
const char * typeName,
KrkString * format_spec,
int positive,
void * abs, fmtCallback callback, fmtCallback (*prepCallback)(
void*,
int));
1862 static int formatLongCallback(
void * a,
int base,
int *more) {
1866 char c = *val->next;
1868 if (c >=
'0' && c <=
'9') out = c -
'0';
1869 else if (c >=
'a' && c <=
'f') out = c -
'a' + 10;
1870 if (val->next == val->asStr || *(--val->next) ==
'-') {
1883 static char * krk_long_to_decimal_str(
const KrkLong * value,
size_t * len);
1884 static fmtCallback prepLongCallback(
void * a,
int base) {
1886 if (base != 10 || (val->val->width > -10 && val->val->width < 10)) {
1888 val->asStr = krk_long_to_str(val->val, base,
"", &val->len, &hash);
1890 val->asStr = krk_long_to_decimal_str(val->val, &val->len);
1892 val->next = &val->asStr[val->len-1];
1893 return formatLongCallback;
1896 KRK_Method(
long,__format__) {
1897 METHOD_TAKES_EXACTLY(1);
1898 CHECK_ARG(1,str,
KrkString*,format_spec);
1900 struct _private tmp = {
self->value, NULL, NULL, 0 };
1902 KrkValue result = krk_doFormatString(
"long",format_spec,
1903 krk_long_sign(self->value) >= 0,
1917 size_t bits = _bits_in(val);
1919 for (
size_t i = 0; i < bits; ++i) {
1920 count += _bit_is_set(val, i);
1924 krk_long_init_ui(&tmp, count);
1925 return make_long_obj(&tmp);
1928 KRK_Method(
long,bit_count) {
1929 return long_bit_count(self->value);
1933 size_t bits = _bits_in(val);
1935 krk_long_init_ui(&tmp, bits);
1936 return make_long_obj(&tmp);
1939 KRK_Method(
long,bit_length) {
1940 return long_bit_length(self->value);
1944 static const char _method_name[] =
"to_bytes";
1946 const char * byteorder;
1948 if (!
krk_parseArgs(
".is|p", (
const char*[]){
"length",
"byteorder",
"signed"}, &length, &byteorder, &_signed))
return NONE_VAL();
1949 if (length < 0)
return krk_runtimeError(
vm.exceptions->valueError,
"length must be non-negative");
1951 if (!strcmp(byteorder,
"little")) {
1953 }
else if (!strcmp(byteorder,
"big")) {
1956 return krk_runtimeError(
vm.exceptions->valueError,
"byteorder must be either 'little' or 'big'");
1959 if (krk_long_sign(val) < 0 && !_signed) {
1960 return krk_runtimeError(
vm.exceptions->notImplementedError,
"can not convert negative value to unsigned");
1965 krk_long_init_ui(&tmp, 0);
1966 krk_long_abs(&tmp, val);
1969 if (krk_long_sign(val) < 0) {
1971 krk_long_init_ui(&one, 1);
1972 krk_long_sub(&tmp, &tmp, &one);
1973 krk_long_clear(&one);
1977 size_t bitCount = _bits_in(&tmp);
1985 if (_signed && val->width != 0) bitCount++;
1987 if ((
size_t)length * 8 < bitCount) {
1988 krk_long_clear(&tmp);
1995 memset(AS_BYTES(
krk_peek(0))->bytes, 0, length);
2006 int32_t remaining = 0;
2009 while (i < length && !break_here) {
2010 if (remaining < 8) {
2011 if (j < tmp.width) {
2012 accum |= ((uint64_t)tmp.digits[j]) << remaining;
2020 uint8_t
byte = accum & 0xFF;
2024 AS_BYTES(
krk_peek(0))->bytes[order == 1 ? i : (length - i - 1)] =
byte;
2030 if (krk_long_sign(val) < 0) {
2031 for (
size_t i = 0; i < (size_t)length; ++i) {
2032 AS_BYTES(
krk_peek(0))->bytes[i] ^= 0xFF;
2037 krk_long_clear(&tmp);
2041 KRK_Method(
long,to_bytes) {
2042 METHOD_TAKES_AT_LEAST(2);
2043 return long_to_bytes(self->value, argc, argv, hasKw);
2054 KRK_Method(
long,_digit_count) {
2056 krk_long_init_si(result, self->value[0].width);
2057 return make_long_obj(result);
2070 KRK_Method(
long,_get_digit) {
2071 METHOD_TAKES_EXACTLY(1);
2073 KrkLong * _self =
self->value;
2075 size_t abs_width = _self->width < 0 ? -_self->width : _self->width;
2078 if (IS_INTEGER(argv[1])) {
2079 index = AS_INTEGER(argv[1]);
2080 }
else if (IS_long(argv[1])) {
2081 KrkLong * value = AS_long(argv[1])->value;
2082 if (value->width < 0 || value->width > 2) {
2085 index = krk_long_medium(value);
2087 return TYPE_ERROR(
int,argv[1]);
2090 if (index >= abs_width) {
2094 return INTEGER_VAL(_self->digits[index]);
2105 #define DEC_DIGIT_SIZE sizeof(digit_t)
2106 #define DEC_DIGIT_CNT 9
2107 #define DEC_DIGIT_MAX 1000000000
2112 static digit_t * dec_add(
const digit_t * a,
size_t awidth,
const digit_t * b,
size_t bwidth,
size_t * outwidth) {
2113 *outwidth = (awidth > bwidth ? awidth : bwidth) + 1;
2114 digit_t * out = calloc(*outwidth, DEC_DIGIT_SIZE);
2116 for (
size_t i = 0; i < *outwidth - 1; ++i) {
2117 digit_t n = ((i < awidth) ? a[i] : 0) + ((i < bwidth) ? b[i] : 0) + carry;
2118 out[i] = n % DEC_DIGIT_MAX;
2119 carry = (n >= DEC_DIGIT_MAX);
2122 out[*outwidth-1] = 1;
2127 if (*outwidth == 0) {
2138 static void dec_isub(
digit_t * a,
size_t awidth,
const digit_t * b,
size_t bwidth) {
2140 for (
size_t i = 0; i < awidth; ++i) {
2141 int64_t a_digit = (int64_t)((i < awidth) ? a[i] : 0) - carry;
2142 int64_t b_digit = (int64_t)((i < bwidth) ? b[i] : 0);
2143 if (a_digit < b_digit) {
2144 a_digit += DEC_DIGIT_MAX;
2149 a[i] = (a_digit - b_digit) % DEC_DIGIT_MAX;
2156 static digit_t * dec_shift(
const digit_t * a,
size_t awidth,
size_t amount,
size_t * outwidth) {
2157 if (awidth == 1 && a[0] == 0) {
2159 return calloc(1,DEC_DIGIT_SIZE);
2161 *outwidth = awidth + amount;
2162 digit_t * out = calloc(*outwidth,DEC_DIGIT_SIZE);
2164 for (
size_t i = 0; i < awidth; ++i) {
2165 out[i+amount] = a[i];
2177 static digit_t * dec_mul(
const digit_t * a,
size_t a_width,
const digit_t * b,
size_t b_width,
size_t * outwidth) {
2179 if (a_width < b_width) {
2183 size_t tmp = a_width;
2188 *outwidth = a_width + b_width;
2191 if ((a_width == 1 && a[0] == 0) || (b_width == 1 && b[0] == 0)) {
2193 return calloc(1,DEC_DIGIT_SIZE);
2197 if (a_width == 1 && a[0] == 1) {
2198 *outwidth = b_width;
2199 digit_t * out = malloc(*outwidth * DEC_DIGIT_SIZE);
2200 memcpy(out, b, *outwidth * DEC_DIGIT_SIZE);
2205 if (b_width == 1 && b[0] == 1) {
2206 *outwidth = a_width;
2207 digit_t * out = malloc(*outwidth * DEC_DIGIT_SIZE);
2208 memcpy(out, a, *outwidth * DEC_DIGIT_SIZE);
2214 digit_t * out = calloc(*outwidth,DEC_DIGIT_SIZE);
2215 for (
size_t i = 0; i < b_width; ++i) {
2216 digit_t bdigit = (i < b_width) ? b[i] : 0;
2218 for (
size_t j = 0; j < a_width; ++j) {
2219 digit_t adigit = (j < a_width) ? a[j] : 0;
2220 uint64_t t = carry + (int64_t)adigit * (int64_t)bdigit + out[i+j];
2221 carry = t / DEC_DIGIT_MAX;
2222 out[i+j] = t % DEC_DIGIT_MAX;
2224 out[i+a_width] = carry;
2226 while (*outwidth > 1 && out[(*outwidth)-1] == 0) (*outwidth)--;
2229 size_t m2 = a_width / 2;
2233 size_t low1_width = (m2 <= a_width) ? m2 : a_width;
2234 while (low1_width > 1 && low1[low1_width-1] == 0) low1_width--;
2236 const digit_t * high1 = (m2 <= a_width) ? (a + m2) : &a_zero;
2237 size_t high1_width = (m2 <= a_width) ? (a_width - m2) : 1;
2241 size_t low2_width = (m2 <= b_width) ? m2 : b_width;
2242 while (low2_width > 1 && low2[low2_width-1] == 0) low2_width--;
2244 const digit_t * high2 = (m2 <= b_width) ? (b + m2) : &b_zero;
2245 size_t high2_width = (m2 <= b_width) ? (b_width - m2) : 1;
2247 size_t z0_width, z1_width, z2_width;
2250 digit_t * z0 = dec_mul(low1, low1_width, low2, low2_width, &z0_width);
2251 digit_t * z2 = dec_mul(high1, high1_width, high2, high2_width, &z2_width);
2254 size_t sleft_width, sright_width;
2255 digit_t * sleft = dec_add(low1, low1_width, high1, high1_width, &sleft_width);
2256 digit_t * sright = dec_add(low2, low2_width, high2, high2_width, &sright_width);
2257 digit_t * z1 = dec_mul(sleft, sleft_width, sright, sright_width, &z1_width);
2262 dec_isub(z1, z1_width, z2, z2_width);
2263 dec_isub(z1, z1_width, z0, z0_width);
2266 size_t m2_shift_width;
2267 digit_t * m2_shift = dec_shift(z1, z1_width, m2, &m2_shift_width);
2272 digit_t * add = dec_add(m2_shift, m2_shift_width, z0, z0_width, &add_width);
2278 digit_t * m2_2 = dec_shift(z2, z2_width, m2 * 2, &m2_2_width);
2282 size_t result_width;
2283 digit_t * result = dec_add(m2_2, m2_2_width, add, add_width, &result_width);
2287 *outwidth = result_width;
2310 static digit_t * dec_two_raised(
size_t w,
size_t * sizeOut) {
2313 digit_t * out = malloc(DEC_DIGIT_SIZE);
2322 digit_t * t = dec_two_raised(w2, &tSize);
2326 digit_t * result = dec_mul(t, tSize, t, tSize, sizeOut);
2331 size_t wmw2 = w - w2;
2335 digit_t * right = dec_two_raised(wmw2, &rightSize);
2338 digit_t * result = dec_mul(t, tSize, right, rightSize, sizeOut);
2357 static digit_t * long_to_dec_inner(
KrkLong * n,
size_t w,
size_t * sizeOut) {
2358 if (n->width == 0) {
2360 return calloc(1,DEC_DIGIT_SIZE);
2364 digit_t * out = malloc(DEC_DIGIT_SIZE);
2365 out[0] = n->digits[0];
2369 size_t aSize, bSize, cSize;
2372 krk_long_init_many(&hi, &lo, &tmp, NULL);
2376 _krk_long_rshift_z(&hi, n, w2);
2378 _krk_long_lshift_z(&tmp, &hi, w2);
2380 krk_long_sub(&lo, n, &tmp);
2381 krk_long_clear_many(&tmp, NULL);
2383 a = long_to_dec_inner(&hi, w - w2, &aSize);
2384 krk_long_clear_many(&hi, NULL);
2386 b = dec_two_raised(w2, &bSize);
2388 c = dec_mul(a, aSize, b, bSize, &cSize);
2392 a = long_to_dec_inner(&lo, w2, &aSize);
2393 krk_long_clear_many(&lo,NULL);
2395 digit_t * result = dec_add(a, aSize, c, cSize, sizeOut);
2401 static char * krk_long_to_decimal_str(
const KrkLong * value,
size_t * len) {
2406 int inv = (krk_long_sign(&abs) == -1);
2407 krk_long_set_sign(&abs, 1);
2410 size_t w = _bits_in(&abs);
2414 digit_t * digits = long_to_dec_inner(&abs, w, &size);
2418 for (
size_t j = 0, div = DEC_DIGIT_MAX/10; j < DEC_DIGIT_CNT; j++, div/=10) {
2419 if (((digits[size-1] / div) % 10))
break;
2424 char * out = malloc(size * DEC_DIGIT_CNT + 1 - leading + inv);
2425 char * writer = out;
2428 if (inv) *(writer++) =
'-';
2431 for (
size_t i = 0; i < size; ++i) {
2432 for (
size_t j = 0, div = DEC_DIGIT_MAX/10; j < DEC_DIGIT_CNT; j++, div/=10) {
2433 if (leading) { leading--;
continue; }
2434 *(writer++) = ((digits[size-i-1] / div) % 10) +
'0';
2440 *len = writer - out;
2445 KRK_Method(
long,__repr__) {
2449 if (self->value->width > -10 && self->value->width < 10) {
2451 char * rev = krk_long_to_str(self->value, 10,
"", &len, &hash);
2455 char * out = krk_long_to_decimal_str(self->value, &len);
2459 #ifndef KRK_NO_FLOAT
2460 KrkValue krk_int_from_float(
double a) {
2461 union {
double d; uint64_t u; } val = {.d = a};
2463 int sign = (val.u >> 63ULL) ? 1 : 0;
2464 int64_t m = val.u & 0x000fffffffffffffULL;
2465 int64_t e = ((val.u >> 52ULL) & 0x7FF) - 0x3FF;
2467 if (e < 0)
return INTEGER_VAL(0);
2468 if (e == 1024)
return krk_runtimeError(
vm.exceptions->valueError,
"can not convert float %s to int", m ?
"Nan" :
"infinity");
2469 if (e < 47)
return INTEGER_VAL((int64_t)a);
2472 krk_long_init_si(&_value, 0x10000000000000ULL | m);
2473 krk_long_init_si(&_tmp, 0);
2476 _krk_long_lshift_z(&_tmp, &_value, e - 52);
2477 krk_long_clear(&_value);
2479 }
else if (e < 52) {
2480 _krk_long_rshift_z(&_tmp, &_value, 52 - e);
2481 krk_long_clear(&_value);
2484 krk_long_clear(&_tmp);
2487 krk_long_set_sign(&_value, sign == 1 ? -1 : 1);
2488 return make_long_obj(&_value);
2493 static size_t round_to(
char * str,
size_t len,
size_t actual,
size_t digits) {
2496 if (actual > digits) {
2498 if (str[digits] ==
'5' && ((digits ? str[digits-1] : 0) % 2 == 0)) {
2503 for (
size_t j = actual - 1; j > digits; j--) {
2504 if (str[j] !=
'0') {
2509 carry = all_zeros ? 0 : 1;
2510 }
else if (str[digits] >=
'5') {
2515 while (i && carry) {
2517 if (str[i-1] -
'0' + carry > 9) {
2526 if (carry && i == 0) {
2528 for (
size_t j = 0; j < digits; ++j) {
2563 union {
double d; uint64_t u; } val = {.d = a};
2565 int noexp = (formatter | 0x20) ==
'f';
2566 int alwaysexp = (formatter | 0x20) ==
'e';
2567 int caps = !(formatter & 0x20);
2568 char expch = caps ?
'E' :
'e';
2571 int sign = (val.u >> 63ULL) ? 1 : 0;
2572 int64_t m = val.u & 0x000fffffffffffffULL;
2573 int64_t e = ((val.u >> 52ULL) & 0x7FF) - 0x3FF;
2582 if (e == -1023 && m == 0) {
2588 if (digits && (forcedigits || formatter ==
' ')) {
2590 for (
unsigned int i = 0; i < ((formatter ==
' ') ? 1 : (digits - ((!noexp && !alwaysexp) ? 1 : 0))); ++i) {
2603 KrkValue float_decimal_parts = NONE_VAL();
2604 if (!
krk_tableGet_fast(&
vm.baseClasses->floatClass->methods, S(
"__decimals__"), &float_decimal_parts)) {
2609 krk_long_parse_string(
"10000000000000000000000000000000000000000000000000000", &d, 10, 53);
2611 for (
int i = 0; i < 53; ++i) {
2612 AS_TUPLE(float_decimal_parts)->values.values[AS_TUPLE(float_decimal_parts)->values.count++] = make_long_obj(&d);
2615 krk_long_init_si(&o,0);
2616 _krk_long_rshift_z(&o,&d,1);
2624 krk_long_parse_string(
"10000000000000000000000000000000", &f, 10, 32);
2625 AS_TUPLE(float_decimal_parts)->values.values[AS_TUPLE(float_decimal_parts)->values.count++] = make_long_obj(&f);
2647 krk_long_init_si(&c,0);
2652 krk_long_init_copy(&c, AS_long(AS_TUPLE(float_decimal_parts)->values.values[0])->value);
2656 for (
int i = 0; i < 52; ++i) {
2657 if (m & (1ULL << (51 - i))) {
2658 krk_long_add(&c,&c, AS_long(AS_TUPLE(float_decimal_parts)->values.values[i+1])->value);
2675 while (!_bit_is_set(&c,i)) i++;
2677 krk_long_mul(&c,&c,AS_long(AS_TUPLE(float_decimal_parts)->values.values[53])->value);
2686 krk_long_init_si(&o,0);
2688 _krk_long_rshift_z(&o,&c,-e);
2690 _krk_long_lshift_z(&o,&c,e);
2702 char * str = krk_long_to_decimal_str(&c, &len);
2706 size_t actual = len;
2707 while (actual > 1 && str[actual-1] ==
'0') actual--;
2709 int ten_exponent = (int)len - b - 1;
2710 int print_exponent = 0;
2711 int whole_digits = ((int)len >= b) ? ten_exponent + 1 : 0;
2712 int missing_digits = (b >= (int)len) ? b - (int)len : 0;
2713 int trailing_zeros = 0;
2720 if (!alwaysexp && !noexp) {
2722 if (digits == 0) digits = 1;
2723 if (actual > digits) {
2725 int overflowed = round_to(str, len, actual, digits);
2729 if (ten_exponent) whole_digits++;
2735 trailing_zeros = digits - actual;
2740 while (actual > 1 && str[actual-1] ==
'0') {
2746 if (ten_exponent < -4 || ten_exponent >= (
int)digits) {
2750 if (!forcedigits) trailing_zeros = 0;
2751 }
else if (!forcedigits) {
2752 if (formatter ==
' ' && actual <= (
size_t)whole_digits) trailing_zeros = 1;
2753 else trailing_zeros = 0;
2757 if (missing_digits > (
int)digits) {
2758 actual = whole_digits;
2759 missing_digits = digits;
2760 }
else if (missing_digits && missing_digits + actual > digits) {
2762 if (round_to(str, len, actual, digits - missing_digits)) missing_digits--;
2763 actual = digits - missing_digits;
2764 }
else if (!missing_digits && actual - whole_digits > digits) {
2766 if (round_to(str, len, actual, digits + whole_digits)) whole_digits++;
2767 actual = digits + whole_digits;
2768 }
else if (actual == (
size_t)whole_digits) {
2770 missing_digits = digits;
2773 trailing_zeros = digits - (actual + missing_digits);
2775 }
else if (alwaysexp) {
2776 if (actual > digits) {
2777 if (round_to(str, len, actual, digits + 1)) ten_exponent += 1;
2778 actual = digits + 1;
2780 trailing_zeros = digits + 1 - actual;
2789 if (forcedigits || actual > (
size_t)whole_digits || trailing_zeros)
krk_pushStringBuilder(&sb,
'.');
2794 if (print_exponent) {
2795 char expsign = ten_exponent < 0 ?
'-' :
'+';
2796 int abs_ten_exponent = ten_exponent < 0 ? -ten_exponent : ten_exponent;
2797 krk_pushStringBuilderFormat(&sb,
"%c%c%s%d",
2798 expch, expsign, abs_ten_exponent < 10 ?
"0" :
"", abs_ten_exponent);
2823 size_t ps = 0, pe = 0, ss = 0, se = 0, es = 0, ee = 0, e_ex = 0;
2825 union Float {
double d; uint64_t i; };
2827 while (c < l && (s[c] ==
' ' || s[c] ==
'\t' || s[c] ==
'\n' || s[c] ==
'\r')) c++;
2833 }
else if (s[c] ==
'+') {
2840 if (((s[c+0] | 0x20) ==
'n') && ((s[c+1] | 0x20) ==
'a') && ((s[c+2] | 0x20) ==
'n')) {
2841 return FLOATING_VAL(((
union Float){.i=0x7ff0000000000001ULL}).d);
2843 if (((s[c+0] | 0x20) ==
'i') && ((s[c+1] | 0x20) ==
'n') && ((s[c+2] | 0x20) ==
'f')) {
2844 return FLOATING_VAL(((
union Float){.i=0x7ff0000000000000ULL}).d * sign);
2849 while (c < l && ((s[c] >=
'0' && s[c] <=
'9') || s[c] ==
'_')) c++;
2853 if (c < l && s[c] ==
'.') {
2856 while (c < l && s[c] >=
'0' && s[c] <=
'9') c++;
2861 if (c < l && (s[c] ==
'e' || s[c] ==
'E')) {
2866 if (c < l && s[c] ==
'-') c++;
2867 else if (c < l && s[c] ==
'+') { c++; es++; }
2870 while (c < l && s[c] >=
'0' && s[c] <=
'9') c++;
2874 while (c < l && (s[c] ==
' ' || s[c] ==
'\t' || s[c] ==
'\n' || s[c] ==
'\r')) c++;
2877 if (c != l)
return krk_runtimeError(
vm.exceptions->valueError,
"invalid literal for float");
2883 while (ps != pe && s[ps] ==
'0') ps++;
2885 while (ss != se && s[ss] ==
'0') {
2894 for (
size_t i = ps; i < pe; ++i) {
2895 if (!sb.length && s[i] ==
'0')
continue;
2896 if (s[i] ==
'_')
continue;
2899 for (
size_t i = ss; i < se; ++i) {
2900 if (!sb.length && s[i] ==
'0')
continue;
2906 const char * m = sb.bytes;
2907 size_t m_len = sb.length;
2916 krk_long_parse_string(m,&m_l,10,m_len);
2921 krk_long_set_sign(&m_l,sign);
2924 const char * e = (es != ee) ? &s[es] :
"0";
2925 size_t e_len = (es != ee) ? (ee-es) : 1;
2929 krk_long_parse_string(e,&e_l,10,e_len);
2934 if (e_l.width > 1) {
2935 krk_long_clear_many(&m_l,&e_l,NULL);
2936 return FLOATING_VAL(((
union Float){.i=0x7ff0000000000000ULL}).d * sign);
2937 }
else if (e_l.width < -1) {
2938 krk_long_clear_many(&m_l,&e_l,NULL);
2939 return FLOATING_VAL(0.0 * sign);
2943 int64_t exp = krk_long_medium(&e_l);
2944 ssize_t digits = (se - ss + e_ex) - exp;
2948 if (exp + (ssize_t)(pe - ps) - (ssize_t)e_ex > 309) {
2949 krk_long_clear_many(&m_l,&e_l,NULL);
2950 return FLOATING_VAL(((
union Float){.i=0x7ff0000000000000ULL}).d * sign);
2951 }
else if (exp + (ssize_t)(pe - ps) - (ssize_t)e_ex < -324) {
2952 krk_long_clear_many(&m_l,&e_l,NULL);
2953 return FLOATING_VAL(0.0 * sign);
2959 KrkLong ten_digits, digits_el;
2960 krk_long_init_si(&ten_digits, 10);
2961 krk_long_init_si(&digits_el, digits);
2962 _krk_long_pow(&ten_digits,&ten_digits,&digits_el);
2963 KrkValue v = _krk_long_truediv(&m_l, &ten_digits);
2964 krk_long_clear_many(&digits_el,&m_l,&e_l,&ten_digits, NULL);
2966 }
else if (digits < 0) {
2969 KrkLong ten_digits, digits_el, one;
2970 krk_long_init_si(&ten_digits, 10);
2971 krk_long_init_si(&digits_el, -digits);
2972 krk_long_init_si(&one, 1);
2973 _krk_long_pow(&ten_digits,&ten_digits,&digits_el);
2974 krk_long_mul(&m_l,&m_l,&ten_digits);
2975 KrkValue v = _krk_long_truediv(&m_l, &one);
2976 krk_long_clear_many(&digits_el,&m_l,&e_l,&ten_digits,&one,NULL);
2982 krk_long_init_si(&one, 1);
2983 KrkValue v = _krk_long_truediv(&m_l, &one);
2984 krk_long_clear_many(&m_l,&e_l,&one,NULL);
2999 uint64_t x = ((
union Float {
double d; uint64_t i; }){.d=d}).i;
3001 uint64_t m = x & 0x000fffffffffffffULL;
3002 uint64_t e = ((x >> 52) & 0x7FF);
3015 if (e == 0x7FF)
return krk_runtimeError(
vm.exceptions->valueError,
"unrepresentable");
3018 krk_long_init_ui(a, 0);
3019 krk_long_init_ui(b, 1);
3023 krk_long_init_ui(a, m);
3024 krk_long_init_ui(b, (1ULL << 52));
3029 krk_long_init_ui(tmp, 0);
3030 _krk_long_lshift_z(tmp,a,e-0x3FF);
3032 memcpy(&a,&tmp,
sizeof(krk_long));
3033 }
else if (e < 0x3FF) {
3035 krk_long_init_ui(tmp, 0);
3036 _krk_long_lshift_z(tmp,b,0x3FF-e);
3038 memcpy(&b,&tmp,
sizeof(krk_long));
3046 while (!_bit_is_set(a,0) && !_bit_is_set(b,0)) {
3047 krk_long tmpa, tmpb;
3048 krk_long_init_ui(tmpa, 0);
3049 krk_long_init_ui(tmpb, 0);
3051 _krk_long_rshift_z(tmpa, a, 1);
3052 _krk_long_rshift_z(tmpb, b, 1);
3057 memcpy(&a,&tmpa,
sizeof(krk_long));
3058 memcpy(&b,&tmpb,
sizeof(krk_long));
3062 krk_long_set_sign(a, d < 0 ? -1 : 1);
3086 if (IS_INTEGER(val)) {
3089 accum = AS_INTEGER(val);
3090 }
else if (IS_long(val)) {
3092 struct BigInt *
self = (
void*)AS_OBJECT(val);
3094 size_t swidth = this->width < 0 ? -this->width : this->width;
3099 accum |= (uint64_t)this->digits[0];
3101 accum |= (uint64_t)this->digits[1] << DIGIT_SHIFT;
3103 accum |= (uint64_t)(this->digits[2] & 0x3) << DIGIT_SHIFT * 2;
3107 if (this->width < 0) {
3109 accum ^= 0xFFFFffffFFFFffff;
3112 #ifndef KRK_NO_FLOAT
3113 }
else if (IS_FLOATING(val)) {
3114 krk_push(krk_int_from_float(AS_FLOATING(val)));
3126 case sizeof(uint8_t): *(uint8_t*)out = accum;
break;
3127 case sizeof(uint16_t): *(uint16_t*)out = accum;
break;
3128 case sizeof(uint32_t): *(uint32_t*)out = accum;
break;
3129 case sizeof(uint64_t): *(uint64_t*)out = accum;
break;
3139 #undef CURRENT_CTYPE
3140 #define CURRENT_CTYPE krk_integer_type
3148 KRK_Method(
int,bit_count) {
3150 krk_long_init_si(value,
self);
3151 KrkValue out = long_bit_count(value);
3152 krk_long_clear(value);
3156 KRK_Method(
int,bit_length) {
3158 krk_long_init_si(value,
self);
3159 KrkValue out = long_bit_length(value);
3160 krk_long_clear(value);
3164 KRK_Method(
int,to_bytes) {
3166 krk_long_init_si(value,
self);
3167 KrkValue out = long_to_bytes(value, argc, argv, hasKw);
3168 krk_long_clear(value);
3173 #undef BIND_STATICMETHOD
3175 #define BIND_METHOD(klass,method) do { krk_defineNative(& _ ## klass->methods, #method, _ ## klass ## _ ## method); } while (0)
3176 #define BIND_STATICMETHOD(klass,method) do { krk_defineNativeStaticMethod(& _ ## klass->methods, #method, _ ## klass ## _ ## method); } while (0)
3177 #define BIND_TRIPLET(klass,name) \
3178 BIND_METHOD(klass,__ ## name ## __); \
3179 BIND_METHOD(klass,__r ## name ## __); \
3180 krk_defineNative(&_ ## klass->methods,"__i" #name "__",_ ## klass ## ___ ## name ## __);
3182 void _createAndBind_longClass(
void) {
3183 KrkClass * _long = ADD_BASE_CLASS(
vm.baseClasses->longClass,
"long",
vm.baseClasses->intClass);
3184 _long->
obj.
flags |= KRK_OBJ_FLAGS_NO_INHERIT;
3188 BIND_STATICMETHOD(
long,__new__);
3189 BIND_METHOD(
long,__repr__);
3190 BIND_METHOD(
long,__eq__);
3191 BIND_METHOD(
long,__hash__);
3192 BIND_METHOD(
long,__hex__);
3193 BIND_METHOD(
long,__oct__);
3194 BIND_METHOD(
long,__bin__);
3195 BIND_METHOD(
long,__int__);
3196 BIND_METHOD(
long,__len__);
3197 BIND_METHOD(
long,__pos__);
3199 BIND_TRIPLET(
long,add);
3200 BIND_TRIPLET(
long,sub);
3201 BIND_TRIPLET(
long,mul);
3202 BIND_TRIPLET(
long,or);
3203 BIND_TRIPLET(
long,xor);
3204 BIND_TRIPLET(
long,and);
3205 BIND_TRIPLET(
long,lshift);
3206 BIND_TRIPLET(
long,rshift);
3207 BIND_TRIPLET(
long,mod);
3208 BIND_TRIPLET(
long,floordiv);
3209 BIND_TRIPLET(
long,pow);
3211 #ifndef KRK_NO_FLOAT
3212 BIND_METHOD(
long,__float__);
3213 BIND_TRIPLET(
long,truediv);
3216 BIND_METHOD(
long,__lt__);
3217 BIND_METHOD(
long,__gt__);
3218 BIND_METHOD(
long,__le__);
3219 BIND_METHOD(
long,__ge__);
3220 BIND_METHOD(
long,__invert__);
3221 BIND_METHOD(
long,__neg__);
3222 BIND_METHOD(
long,__abs__);
3223 BIND_METHOD(
long,__format__);
3225 BIND_METHOD(
long,bit_count);
3226 BIND_METHOD(
long,bit_length);
3227 BIND_METHOD(
long,to_bytes);
3231 BIND_METHOD(
long,_digit_count);
3232 BIND_METHOD(
long,_get_digit);
3238 BIND_METHOD(
int,bit_count);
3239 BIND_METHOD(
int,bit_length);
3240 BIND_METHOD(
int,to_bytes);
KrkValue krk_runtimeError(KrkClass *type, const char *fmt,...)
Produce and raise an exception with a formatted message.
KrkValue krk_parse_float(const char *s, size_t l)
Parse a string into a float.
_protected int krk_long_to_int(KrkValue val, char size, void *out)
Convert an int or long to a C integer.
size_t krk_long_digits_in_base(KrkLong *num, int base)
Estimate how many digits are needed to convert a long to a base.
KrkValue krk_double_to_string(double a, unsigned int digits, char formatter, int plus, int forcedigits)
Convert a double to a KrkString.
KrkValue krk_float_to_fraction(double d)
Convert a double to a tuple of two longs.
KrkBytes * krk_newBytes(size_t length, uint8_t *source)
Create a new byte array.
KrkCleanupCallback _ongcsweep
C function to call when the garbage collector is discarding an instance of this class.
size_t allocSize
Size to allocate when creating instances of this class.
void krk_finalizeClass(KrkClass *_class)
Finalize a class by collecting pointers to core methods.
KrkInstance * krk_newInstance(KrkClass *_class)
Create a new instance of the given class.
uint16_t flags
General object flags, mostly related to garbage collection.
Immutable sequence of Unicode codepoints.
KrkString * krk_takeString(char *chars, size_t length)
Yield ownership of a C string to the GC and obtain a string object.
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,...
void krk_attachNamedValue(KrkTable *table, const char name[], KrkValue obj)
Attach a value to an attribute table.
int krk_tableGet_fast(KrkTable *table, struct KrkString *str, KrkValue *value)
Obtain the value associated with a string key in a table.
Immutable sequence of arbitrary values.
KrkValueArray values
Stores the length, capacity, and actual values of the tuple.
KrkTuple * krk_newTuple(size_t length)
Create a new tuple.
Stack reference or primative value.
Inline flexible string array.
Utilities for creating native bindings.
void krk_pushStringBuilderStr(struct StringBuilder *sb, const char *str, size_t len)
Append a string to the end of a string builder.
#define krk_parseArgs(f, n,...)
Parse arguments to a function while accepting keyword arguments.
KrkValue krk_discardStringBuilder(struct StringBuilder *sb)
Discard the contents of a string builder.
KrkValue krk_finishStringBuilder(struct StringBuilder *sb)
Finalize a string builder into a string object.
void krk_pushStringBuilder(struct StringBuilder *sb, char c)
Add a character to the end of a string builder.
Definitions for primitive stack references.
Core API for the bytecode virtual machine.
krk_threadLocal KrkThreadState krk_currentThread
Thread-local VM state.
#define vm
Convenience macro for namespacing.
KrkValue krk_pop(void)
Pop the top of the stack.
void krk_push(KrkValue value)
Push a stack value.
KrkValue krk_peek(int distance)
Peek down from the top of the stack.