Skip to content

Commit

Permalink
std::math::big: add decimal format support to the Int for string parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
mertcandav committed Mar 12, 2024
1 parent a7e00e1 commit 17601a8
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 1 deletion.
27 changes: 26 additions & 1 deletion std/math/big/conv.jule
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,31 @@ fn parse_octal(&s: str)!: bits {
ret buf
}

fn parse_decimal(&s: str)!: []byte {
let mut sb = stobs(s)
let mut buf = make([]byte, 0, s.len * 4)
loop:
for {
let d = sb[sb.len-1] - '0'
buf = append(buf, d%2)
let mut carry = byte(0)
for i, b in sb {
let t = carry*10 + (b - '0')
sb[i] = '0' + (t >> 1)
carry = t % 2
}
for i in sb {
if sb[i] != '0' {
sb = sb[i:]
continue loop
}
}
break
}
fit(buf)
ret buf
}

fn format_binary(&b: bits): []byte {
if b.len == 0 {
ret ['0']
Expand Down Expand Up @@ -138,7 +163,7 @@ fn format_decimal_part(mut &buf: []byte, m: byte) {
}

fn format_decimal(&b: bits): []byte {
let mut buf = make([]byte, 1, b.len)
let mut buf = make([]byte, 1, b.len >> 1)
buf[0] = '0'
for _, bit in format_binary(b) {
format_decimal_part(buf, 1)
Expand Down
24 changes: 24 additions & 0 deletions std/math/big/conv_test.jule
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,24 @@ static cases_parse_hex = [

static cases_parse_octal = [
[[]byte("0"), []],
[[]byte("000"), []],
[[]byte("001"), [1]],
[[]byte("563"), [1, 1, 0, 0, 1, 1, 1, 0, 1]],
[[]byte("01234567"), [1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1]],
[[]byte("76543210"), [0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1]],
[[]byte("56323242425551121325623237"), [1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1]],
]

static cases_parse_decimal = [
[[]byte("0"), []],
[[]byte("00000"), []],
[[]byte("010"), [0, 1, 0, 1]],
[[]byte("011"), [1, 1, 0, 1]],
[[]byte("11101293"), [1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1]],
[[]byte("77738310"), [0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1]],
[[]byte("52386786278527310725769899"), [1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1]],
]

#test
fn test_parse_hex(mut t: &T) {
for _, c in cases_parse_hex {
Expand All @@ -45,3 +57,15 @@ fn test_parse_octal(mut t: &T) {
}
}
}

#test
fn test_parse_decimal(mut t: &T) {
for _, c in cases_parse_decimal {
let c0 = str(c[0])
let bits = parse_decimal(c0)!
let c1 = c[1]
if cmp(bits, c1) != 0 {
t.errorf("{} != {}", str(c[0]), c1)
}
}
}
1 change: 1 addition & 0 deletions std/math/big/int.jule
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ impl Int {
// Valid fmt values are;
// - 2 for binary.
// - 8 for octal.
// - 10 for decimal.
// - 16 for hexadecimal.
pub static fn parse(mut s: str, fmt: int)!: Int {
let mut r = Int{}
Expand Down
5 changes: 5 additions & 0 deletions std/math/big/nat.jule
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ impl Nat {
// Valid fmt values are;
// - 2 for binary.
// - 8 for octal.
// - 10 for decimal.
// - 16 for hexadecimal.
static fn parse(s: str, fmt: int)!: Nat {
if s == "" {
Expand All @@ -80,6 +81,10 @@ impl Nat {
match fmt {
| 2:
r.bits = parse_binary(s) else { error(error) }
| 8:
r.bits = parse_octal(s) else { error(error) }
| 10:
r.bits = parse_decimal(s) else { error(error) }
| 16:
r.bits = parse_hex(s) else { error(error) }
|:
Expand Down
18 changes: 18 additions & 0 deletions std/math/big/unsafe.jule
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright 2024 The Jule Programming Language.
// Use of this source code is governed by a BSD 3-Clause
// license that can be found in the LICENSE file.

use integ for std::jule::integrated

// Returns byte slice that uses string's allocation.
// Does not performs deallocation.
fn stobs(&s: str): []byte {
unsafe {
integ::emit("{} slice;", []byte)
integ::emit("slice.data.alloc = {}.begin();", s)
integ::emit("slice.data.ref = {};", nil)
integ::emit("slice._slice = slice.data.alloc;")
integ::emit("slice._len = slice._cap = {};", s.len)
ret integ::emit[[]byte]("slice")
}
}

0 comments on commit 17601a8

Please sign in to comment.