Browse Source

Fix `big_int_to_f64`

gingerBill 5 years ago
parent
commit
d8bc2030e6
2 changed files with 56 additions and 6 deletions
  1. 51 6
      src/big_int.cpp
  2. 5 0
      src/exact_value.cpp

+ 51 - 6
src/big_int.cpp

@@ -291,7 +291,8 @@ void big_int_from_string(BigInt *dst, String const &s) {
 	big_int_from_u64(&b, base);
 	big_int_from_u64(&b, base);
 	big_int_init(dst, &BIG_INT_ZERO);
 	big_int_init(dst, &BIG_INT_ZERO);
 
 
-	for (isize i = 0; i < len; i++) {
+	isize i = 0;
+	for (; i < len; i++) {
 		Rune r = cast(Rune)text[i];
 		Rune r = cast(Rune)text[i];
 		if (r == '_') {
 		if (r == '_') {
 			continue;
 			continue;
@@ -304,6 +305,32 @@ void big_int_from_string(BigInt *dst, String const &s) {
 		big_int_mul_eq(dst, &b);
 		big_int_mul_eq(dst, &b);
 		big_int_add_eq(dst, &val);
 		big_int_add_eq(dst, &val);
 	}
 	}
+	if (i < len && (text[i] == 'e' || text[i] == 'E')) {
+		i += 1;
+		GB_ASSERT(base == 10);
+		GB_ASSERT(text[i] != '-');
+		if (text[i] == '+') {
+			i += 1;
+		}
+		u64 exp = 0;
+		for (; i < len; i++) {
+			char r = cast(char)text[i];
+			if (r == '_') {
+				continue;
+			}
+			u64 v = 0;
+			if (gb_char_is_digit(r)) {
+				v = u64_digit_value(r);
+			} else {
+				break;
+			}
+			exp *= 10;
+			exp += v;
+		}
+		for (u64 x = 0; x < exp; x++) {
+			big_int_mul_eq(dst, &b);
+		}
+	}
 	big_int_normalize(dst);
 	big_int_normalize(dst);
 }
 }
 
 
@@ -341,12 +368,30 @@ i64 big_int_to_i64(BigInt const *x) {
 }
 }
 
 
 f64 big_int_to_f64(BigInt const *x) {
 f64 big_int_to_f64(BigInt const *x) {
-	if (x->neg) {
-		i64 i = big_int_to_i64(x);
-		return cast(f64)i;
+	switch (x->len) {
+	case 0:
+		return 0.0;
+	case 1:
+		if (x->neg) {
+			i64 i = big_int_to_i64(x);
+			return cast(f64)i;
+		} else {
+			u64 u = big_int_to_u64(x);
+			return cast(f64)u;
+		}
+	}
+
+
+	u64 const *words = big_int_ptr(x);
+	f64 base = pow(2.0, gb_size_of(u64));
+	// TODO(bill): clean up this code and make it more accurate
+	f64 res = 0;
+	for (isize i = x->len-1; i >= 0; i--) {
+		res *= base;
+		u64 w = words[i];
+		res += cast(f64)w;
 	}
 	}
-	u64 u = big_int_to_u64(x);
-	return cast(f64)u;
+	return res;
 }
 }
 
 
 bool bi__alias(BigInt const *dst, BigInt const *src) {
 bool bi__alias(BigInt const *dst, BigInt const *src) {

+ 5 - 0
src/exact_value.cpp

@@ -281,6 +281,11 @@ ExactValue exact_value_float_from_string(String string) {
 		}
 		}
 	}
 	}
 
 
+	if (!string_contains_char(string, '.') && !string_contains_char(string, '-')) {
+		// NOTE(bill): treat as integer
+		return exact_value_integer_from_string(string);
+	}
+
 	f64 f = float_from_string(string);
 	f64 f = float_from_string(string);
 	return exact_value_float(f);
 	return exact_value_float(f);
 }
 }