Ver Fonte

Support larger integer literals to work with the new BigInt system

gingerBill há 7 anos atrás
pai
commit
49f2124df0
3 ficheiros alterados com 57 adições e 43 exclusões
  1. 19 19
      core/bits/bits.odin
  2. 34 21
      src/big_int.cpp
  3. 4 3
      src/exact_value.cpp

+ 19 - 19
core/bits/bits.odin

@@ -2,25 +2,25 @@ package bits
 
 import "core:os"
 
-U8_MIN  ::  u8(0);
-U16_MIN :: u16(0);
-U32_MIN :: u32(0);
-U64_MIN :: u64(0);
-
-U8_MAX  ::  ~u8(0);
-U16_MAX :: ~u16(0);
-U32_MAX :: ~u32(0);
-U64_MAX :: ~u64(0);
-
-I8_MIN  ::  i8( ~u8(0) >> 1);
-I16_MIN :: i16(~u16(0) >> 1);
-I32_MIN :: i32(~u32(0) >> 1);
-I64_MIN :: i64(~u64(0) >> 1);
-
-I8_MAX  ::  -I8_MIN - 1;
-I16_MAX :: -I16_MIN - 1;
-I32_MAX :: -I32_MIN - 1;
-I64_MAX :: -I64_MIN - 1;
+U8_MIN  :: 0;
+U16_MIN :: 0;
+U32_MIN :: 0;
+U64_MIN :: 0;
+
+U8_MAX  :: 1 <<  8 - 1;
+U16_MAX :: 1 << 16 - 1;
+U32_MAX :: 1 << 32 - 1;
+U64_MAX :: 1 << 64 - 1;
+
+I8_MIN  :: - 1 << 7;
+I16_MIN :: - 1 << 15;
+I32_MIN :: - 1 << 31;
+I64_MIN :: - 1 << 63;
+
+I8_MAX  :: 1 <<  7 - 1;
+I16_MAX :: 1 << 15 - 1;
+I32_MAX :: 1 << 31 - 1;
+I64_MAX :: 1 << 63 - 1;
 
 foreign {
 	@(link_name="llvm.ctpop.i8")        count_ones8  :: proc(i:  u8) ->  u8 ---

+ 34 - 21
src/big_int.cpp

@@ -36,6 +36,11 @@ void global_big_int_init(void) {
 #endif
 }
 
+// IMPORTANT NOTE LEAK(bill): This entire BigInt library leaks memory like there is no tomorrow
+// However, this isn't really a problem as the vast majority of BigInt operations will not use
+// more than 1 word.
+// I could track how much this does leaks because I use an arena_allocator but I doubt I will require
+// it any time soon
 gb_inline gbAllocator big_int_allocator(void) {
 	return arena_allocator(&global_big_int_arena);
 }
@@ -55,6 +60,13 @@ void big_int_from_i64(BigInt *dst, i64 x);
 void big_int_init    (BigInt *dst, BigInt const *src);
 void big_int_from_string(BigInt *dst, String const &s);
 
+void big_int_dealloc(BigInt *dst) {
+	if (dst->len > 1) {
+		gb_free(big_int_allocator(), dst->d.words);
+	}
+	gb_zero_item(dst);
+}
+
 BigInt big_int_make(BigInt const *b, bool abs=false);
 BigInt big_int_make_abs(BigInt const *b);
 BigInt big_int_make_u64(u64 x);
@@ -246,6 +258,10 @@ BigInt big_int_make_i64(i64 x) {
 
 
 void big_int_from_string(BigInt *dst, String const &s) {
+#if 0
+	u64 u = u64_from_string(s);
+	big_int_from_u64(dst, u);
+#else
 	u64 base = 10;
 	bool has_prefix = false;
 	if (s.len > 2 && s[0] == '0') {
@@ -266,28 +282,24 @@ void big_int_from_string(BigInt *dst, String const &s) {
 		len -= 2;
 	}
 
-	BigInt result = {};
-	BigInt val = {};
 	BigInt b = {};
 	big_int_from_u64(&b, base);
-	val.len = 1;
-	val.d.word = 100000000ull;
-
-	// for (isize i = 0; i < len; i++) {
-	// 	Rune r = cast(Rune)text[i];
-	// 	if (r == '_') {
-	// 		continue;
-	// 	}
-	// 	u64 v = u64_digit_value(r);
-	// 	if (v >= base) {
-	// 		break;
-	// 	}
-	// 	val.d.word = v;
-
-	// 	big_int_mul_eq(&result, &b);
-	// 	big_int_add_eq(&result, &val);
-	// }
-	*dst = result;
+	big_int_init(dst, &BIG_INT_ZERO);
+
+	for (isize i = 0; i < len; i++) {
+		Rune r = cast(Rune)text[i];
+		if (r == '_') {
+			continue;
+		}
+		u64 v = u64_digit_value(r);
+		if (v >= base) {
+			break;
+		}
+		BigInt val = big_int_make_u64(v);
+		big_int_mul_eq(dst, &b);
+		big_int_add_eq(dst, &val);
+	}
+#endif
 }
 
 
@@ -1291,6 +1303,8 @@ void big_int_not(BigInt *dst, BigInt const *x, u64 bit_count, bool is_signed) {
 		return;
 	}
 
+	// TODO(bill): Is this fast enough?
+
 	dst->neg = false;
 	u64 const *xd = big_int_ptr(x);
 	if (bit_count <= 64) {
@@ -1361,7 +1375,6 @@ char digit_to_char(u8 digit) {
 String big_int_to_string(gbAllocator allocator, BigInt const *x, u64 base) {
 	GB_ASSERT(base <= 16);
 
-
 	if ((x->len == 0) && (x->len == 1 && x->d.word == 0)) {
 		u8 *buf = gb_alloc_array(allocator, u8, 1);
 		buf[0] = '0';

+ 4 - 3
src/exact_value.cpp

@@ -135,9 +135,10 @@ ExactValue exact_value_procedure(Ast *node) {
 }
 
 
-ExactValue exact_value_integer_from_string(String string) {
-	u64 u = u64_from_string(string);
-	return exact_value_u64(u);
+ExactValue exact_value_integer_from_string(String const &string) {
+	ExactValue result = {ExactValue_Integer};
+	big_int_from_string(&result.value_integer, string);
+	return result;
 }
 
 f64 float_from_string(String string) {