mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 23:58:50 +00:00
Ellipsis is now just ..; Remove half-closed range operator and treat all of them as half-closed; slice expression uses ..;
This commit is contained in:
+65
-66
@@ -3,11 +3,10 @@
|
||||
// NOTE: This is only for floating point printing and nothing else
|
||||
|
||||
Decimal :: struct {
|
||||
d: [384]byte, // big-endian digits
|
||||
ndu: int,
|
||||
dp: int,
|
||||
neg: bool,
|
||||
trunc: bool,
|
||||
digits: [384]byte, // big-endian digits
|
||||
count: int,
|
||||
decimal_point: int,
|
||||
neg, trunc: bool,
|
||||
}
|
||||
|
||||
decimal_to_string :: proc(buf: []byte, a: ^Decimal) -> string {
|
||||
@@ -19,42 +18,42 @@ decimal_to_string :: proc(buf: []byte, a: ^Decimal) -> string {
|
||||
}
|
||||
|
||||
|
||||
n := 10 + a.ndu + abs(a.dp);
|
||||
n := 10 + a.count + abs(a.decimal_point);
|
||||
|
||||
// TODO(bill): make this work with a buffer that's not big enough
|
||||
assert(buf.count >= n);
|
||||
buf = buf[:n];
|
||||
buf = buf[..n];
|
||||
|
||||
if a.ndu == 0 {
|
||||
if a.count == 0 {
|
||||
buf[0] = '0';
|
||||
return cast(string)buf[0:1];
|
||||
return cast(string)buf[0..1];
|
||||
}
|
||||
|
||||
w := 0;
|
||||
if a.dp <= 0 {
|
||||
if a.decimal_point <= 0 {
|
||||
buf[w] = '0'; w++;
|
||||
buf[w] = '.'; w++;
|
||||
w += digit_zero(buf[w: w-a.dp]);
|
||||
w += copy(buf[w:], a.d[0:a.ndu]);
|
||||
} else if a.dp < a.ndu {
|
||||
w += copy(buf[w:], a.d[0:a.dp]);
|
||||
w += digit_zero(buf[w .. w-a.decimal_point]);
|
||||
w += copy(buf[w..], a.digits[0..a.count]);
|
||||
} else if a.decimal_point < a.count {
|
||||
w += copy(buf[w..], a.digits[0..a.decimal_point]);
|
||||
buf[w] = '.'; w++;
|
||||
w += copy(buf[w:], a.d[a.dp:a.ndu]);
|
||||
w += copy(buf[w..], a.digits[a.decimal_point .. a.count]);
|
||||
} else {
|
||||
w += copy(buf[w:], a.d[0:a.ndu]);
|
||||
w += digit_zero(buf[w : w+a.dp-a.ndu]);
|
||||
w += copy(buf[w..], a.digits[0..a.count]);
|
||||
w += digit_zero(buf[w .. w+a.decimal_point-a.count]);
|
||||
}
|
||||
|
||||
return cast(string)buf[0:w];
|
||||
return cast(string)buf[0..w];
|
||||
}
|
||||
|
||||
// trim trailing zeros
|
||||
trim :: proc(a: ^Decimal) {
|
||||
for a.ndu > 0 && a.d[a.ndu-1] == '0' {
|
||||
a.ndu--;
|
||||
for a.count > 0 && a.digits[a.count-1] == '0' {
|
||||
a.count--;
|
||||
}
|
||||
if a.ndu == 0 {
|
||||
a.dp = 0;
|
||||
if a.count == 0 {
|
||||
a.decimal_point = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,12 +69,12 @@ assign :: proc(a: ^Decimal, i: u64) {
|
||||
i = j;
|
||||
}
|
||||
|
||||
a.ndu = 0;
|
||||
a.count = 0;
|
||||
for n--; n >= 0; n-- {
|
||||
a.d[a.ndu] = buf[n];
|
||||
a.ndu++;
|
||||
a.digits[a.count] = buf[n];
|
||||
a.count++;
|
||||
}
|
||||
a.dp = a.ndu;
|
||||
a.decimal_point = a.count;
|
||||
trim(a);
|
||||
}
|
||||
|
||||
@@ -88,10 +87,10 @@ shift_right :: proc(a: ^Decimal, k: uint) {
|
||||
|
||||
n: uint;
|
||||
for ; n>>k == 0; r++ {
|
||||
if r >= a.ndu {
|
||||
if r >= a.count {
|
||||
if n == 0 {
|
||||
// Just in case
|
||||
a.ndu = 0;
|
||||
a.count = 0;
|
||||
return;
|
||||
}
|
||||
for n>>k == 0 {
|
||||
@@ -100,18 +99,18 @@ shift_right :: proc(a: ^Decimal, k: uint) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
c := cast(uint)a.d[r];
|
||||
c := cast(uint)a.digits[r];
|
||||
n = n*10 + c - '0';
|
||||
}
|
||||
a.dp -= r-1;
|
||||
a.decimal_point -= r-1;
|
||||
|
||||
mask: uint = (1<<k) - 1;
|
||||
|
||||
for ; r < a.ndu; r++ {
|
||||
c := cast(uint)a.d[r];
|
||||
for ; r < a.count; r++ {
|
||||
c := cast(uint)a.digits[r];
|
||||
dig := n>>k;
|
||||
n &= mask;
|
||||
a.d[w] = cast(byte)('0' + dig);
|
||||
a.digits[w] = cast(byte)('0' + dig);
|
||||
w++;
|
||||
n = n*10 + c - '0';
|
||||
}
|
||||
@@ -119,8 +118,8 @@ shift_right :: proc(a: ^Decimal, k: uint) {
|
||||
for n > 0 {
|
||||
dig := n>>k;
|
||||
n &= mask;
|
||||
if w < a.d.count {
|
||||
a.d[w] = cast(byte)('0' + dig);
|
||||
if w < a.digits.count {
|
||||
a.digits[w] = cast(byte)('0' + dig);
|
||||
w++;
|
||||
} else if dig > 0 {
|
||||
a.trunc = true;
|
||||
@@ -129,24 +128,24 @@ shift_right :: proc(a: ^Decimal, k: uint) {
|
||||
}
|
||||
|
||||
|
||||
a.ndu = w;
|
||||
a.count = w;
|
||||
trim(a);
|
||||
}
|
||||
|
||||
shift_left :: proc(a: ^Decimal, k: uint) {
|
||||
delta := cast(int)(k/4);
|
||||
|
||||
r := a.ndu; // read index
|
||||
w := a.ndu+delta; // write index
|
||||
r := a.count; // read index
|
||||
w := a.count+delta; // write index
|
||||
|
||||
n: uint;
|
||||
for r--; r >= 0; r-- {
|
||||
n += (cast(uint)a.d[r] - '0') << k;
|
||||
n += (cast(uint)a.digits[r] - '0') << k;
|
||||
quo := n/10;
|
||||
rem := n - 10*quo;
|
||||
w--;
|
||||
if w < a.d.count {
|
||||
a.d[w] = cast(byte)('0' + rem);
|
||||
if w < a.digits.count {
|
||||
a.digits[w] = cast(byte)('0' + rem);
|
||||
} else if rem != 0 {
|
||||
a.trunc = true;
|
||||
}
|
||||
@@ -157,23 +156,23 @@ shift_left :: proc(a: ^Decimal, k: uint) {
|
||||
quo := n/10;
|
||||
rem := n - 10*quo;
|
||||
w--;
|
||||
if w < a.d.count {
|
||||
a.d[w] = cast(byte)('0' + rem);
|
||||
if w < a.digits.count {
|
||||
a.digits[w] = cast(byte)('0' + rem);
|
||||
} else if rem != 0 {
|
||||
a.trunc = true;
|
||||
}
|
||||
n = quo;
|
||||
}
|
||||
|
||||
a.ndu += delta;
|
||||
a.ndu = min(a.ndu, a.d.count);
|
||||
a.dp += delta;
|
||||
a.count += delta;
|
||||
a.count = min(a.count, a.digits.count);
|
||||
a.decimal_point += delta;
|
||||
trim(a);
|
||||
}
|
||||
|
||||
shift :: proc(a: ^Decimal, k: int) {
|
||||
match {
|
||||
case a.ndu == 0:
|
||||
case a.count == 0:
|
||||
// no need to update
|
||||
case k > 0:
|
||||
for k > max_shift {
|
||||
@@ -193,19 +192,19 @@ shift :: proc(a: ^Decimal, k: int) {
|
||||
}
|
||||
|
||||
can_round_up :: proc(a: ^Decimal, nd: int) -> bool {
|
||||
if nd < 0 || nd >= a.ndu { return false ; }
|
||||
if a.d[nd] == '5' && nd+1 == a.ndu {
|
||||
if nd < 0 || nd >= a.count { return false ; }
|
||||
if a.digits[nd] == '5' && nd+1 == a.count {
|
||||
if a.trunc {
|
||||
return true;
|
||||
}
|
||||
return nd > 0 && (a.d[nd-1]-'0')%2 != 0;
|
||||
return nd > 0 && (a.digits[nd-1]-'0')%2 != 0;
|
||||
}
|
||||
|
||||
return a.d[nd] >= '5';
|
||||
return a.digits[nd] >= '5';
|
||||
}
|
||||
|
||||
round :: proc(a: ^Decimal, nd: int) {
|
||||
if nd < 0 || nd >= a.ndu { return; }
|
||||
if nd < 0 || nd >= a.count { return; }
|
||||
if can_round_up(a, nd) {
|
||||
round_up(a, nd);
|
||||
} else {
|
||||
@@ -214,44 +213,44 @@ round :: proc(a: ^Decimal, nd: int) {
|
||||
}
|
||||
|
||||
round_up :: proc(a: ^Decimal, nd: int) {
|
||||
if nd < 0 || nd >= a.ndu { return; }
|
||||
if nd < 0 || nd >= a.count { return; }
|
||||
|
||||
for i := nd-1; i >= 0; i-- {
|
||||
if c := a.d[i]; c < '9' {
|
||||
a.d[i]++;
|
||||
a.ndu = i+1;
|
||||
if c := a.digits[i]; c < '9' {
|
||||
a.digits[i]++;
|
||||
a.count = i+1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Number is just 9s
|
||||
a.d[0] = '1';
|
||||
a.ndu = 1;
|
||||
a.dp++;
|
||||
a.digits[0] = '1';
|
||||
a.count = 1;
|
||||
a.decimal_point++;
|
||||
}
|
||||
|
||||
round_down :: proc(a: ^Decimal, nd: int) {
|
||||
if nd < 0 || nd >= a.ndu { return; }
|
||||
a.ndu = nd;
|
||||
if nd < 0 || nd >= a.count { return; }
|
||||
a.count = nd;
|
||||
trim(a);
|
||||
}
|
||||
|
||||
|
||||
// Extract integer part, rounded appropriately. There are no guarantees about overflow.
|
||||
rounded_integer :: proc(a: ^Decimal) -> u64 {
|
||||
if a.dp > 20 {
|
||||
if a.decimal_point > 20 {
|
||||
return 0xffff_ffff_ffff_ffff;
|
||||
}
|
||||
i: int;
|
||||
n: u64 = 0;
|
||||
m := min(a.dp, a.ndu);
|
||||
m := min(a.decimal_point, a.count);
|
||||
for i = 0; i < m; i++ {
|
||||
n = n*10 + cast(u64)(a.d[i]-'0');
|
||||
n = n*10 + cast(u64)(a.digits[i]-'0');
|
||||
}
|
||||
for ; i < a.dp; i++ {
|
||||
for ; i < a.decimal_point; i++ {
|
||||
n *= 10;
|
||||
}
|
||||
if can_round_up(a, a.dp) {
|
||||
if can_round_up(a, a.decimal_point) {
|
||||
n++;
|
||||
}
|
||||
return n;
|
||||
|
||||
Reference in New Issue
Block a user