mirror of
https://github.com/roc-lang/roc.git
synced 2024-08-17 06:41:22 +03:00
Add RocDec.fromString
This commit is contained in:
parent
9cb8f5af95
commit
81b14b9122
@ -1,16 +1,110 @@
|
||||
const std = @import("std");
|
||||
|
||||
const math = std.math;
|
||||
|
||||
pub const RocDec = struct {
|
||||
num: i128,
|
||||
|
||||
pub const decimal_places: u32 = 18;
|
||||
pub const decimal_places: comptime u32 = 18;
|
||||
|
||||
pub const min: RocDec = .{ .num = math.minInt(i128) };
|
||||
pub const max: RocDec = .{ .num = math.maxInt(i128) };
|
||||
pub const min: comptime RocDec = .{ .num = math.minInt(i128) };
|
||||
pub const max: comptime RocDec = .{ .num = math.maxInt(i128) };
|
||||
|
||||
pub const one_point_zero: RocDec = .{ .num = comptime math.pow(i128, 10, RocDec.decimal_places) };
|
||||
pub const one_point_zero_i128: comptime i128 = comptime math.pow(i128, 10, RocDec.decimal_places);
|
||||
pub const one_point_zero: comptime RocDec = .{ .num = one_point_zero_i128 };
|
||||
|
||||
pub fn fromU64(num: u64) RocDec {
|
||||
return .{ .num = num * one_point_zero_i128 };
|
||||
}
|
||||
|
||||
pub fn fromString(bytes_ptr: [*]const u8, length: usize) ?RocDec {
|
||||
if (length == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var is_negative: bool = bytes_ptr[0] == '-';
|
||||
var initial_index: usize = if (is_negative) 1 else 0;
|
||||
|
||||
var point_index: ?usize = null;
|
||||
var index: usize = 0;
|
||||
while (index < length) {
|
||||
var byte: u8 = bytes_ptr[index];
|
||||
if (byte == '.' and point_index == null) {
|
||||
point_index = index;
|
||||
index += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isDigit(byte)) {
|
||||
return null;
|
||||
}
|
||||
index += 1;
|
||||
}
|
||||
|
||||
var before_str_length = length;
|
||||
var after_val_i128: ?i128 = null;
|
||||
if (point_index) |pi| {
|
||||
before_str_length = pi;
|
||||
|
||||
var after_str_len = (length - 1) - pi;
|
||||
if (after_str_len > decimal_places) {
|
||||
std.debug.panic("TODO runtime exception for too many decimal places!", .{});
|
||||
}
|
||||
var diff_decimal_places = decimal_places - after_str_len;
|
||||
|
||||
var after_str = bytes_ptr[pi + 1 .. length];
|
||||
var after_u64 = std.fmt.parseUnsigned(u64, after_str, 10) catch null;
|
||||
after_val_i128 = if (after_u64) |f| @intCast(i128, f) * math.pow(i128, 10, diff_decimal_places) else null;
|
||||
}
|
||||
|
||||
var before_str = bytes_ptr[initial_index..before_str_length];
|
||||
var before_val_not_adjusted = std.fmt.parseUnsigned(i128, before_str, 10) catch null;
|
||||
|
||||
var before_val_i128: ?i128 = null;
|
||||
if (before_val_not_adjusted) |before| {
|
||||
var result: i128 = undefined;
|
||||
var overflowed = @mulWithOverflow(i128, before, one_point_zero_i128, &result);
|
||||
if (overflowed) {
|
||||
std.debug.panic("TODO runtime exception for overflow!", .{});
|
||||
}
|
||||
before_val_i128 = result;
|
||||
}
|
||||
|
||||
var dec: ?RocDec = null;
|
||||
if (before_val_i128) |before| {
|
||||
if (after_val_i128) |after| {
|
||||
var result: i128 = undefined;
|
||||
var overflowed = @addWithOverflow(i128, before, after, &result);
|
||||
if (overflowed) {
|
||||
std.debug.panic("TODO runtime exception for overflow!", .{});
|
||||
}
|
||||
dec = .{ .num = result };
|
||||
} else {
|
||||
dec = .{ .num = before };
|
||||
}
|
||||
} else if (after_val_i128) |after| {
|
||||
dec = .{ .num = after };
|
||||
}
|
||||
|
||||
if (dec) |d| {
|
||||
if (is_negative) {
|
||||
dec = d.negate();
|
||||
}
|
||||
}
|
||||
|
||||
return dec;
|
||||
}
|
||||
|
||||
fn isDigit(c: u8) bool {
|
||||
return switch (c) {
|
||||
'0'...'9' => true,
|
||||
else => false,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn negate(self: RocDec) ?RocDec {
|
||||
var negated = math.negate(self.num) catch null;
|
||||
return if (negated) |n| .{ .num = n } else null;
|
||||
}
|
||||
|
||||
pub fn add(self: RocDec, other: RocDec) RocDec {
|
||||
var answer: i128 = undefined;
|
||||
@ -218,16 +312,98 @@ fn mul_u128(a: u128, b: u128) U256 {
|
||||
|
||||
const one_e20: i256 = 100000000000000000000;
|
||||
|
||||
const expectEqual = std.testing.expectEqual;
|
||||
const testing = std.testing;
|
||||
const expectEqual = testing.expectEqual;
|
||||
|
||||
test "add" {
|
||||
const dec: RocDec = .{ .num = 0 };
|
||||
|
||||
expectEqual(RocDec{ .num = 0 }, dec.add(.{ .num = 0 }));
|
||||
test "fromU64" {
|
||||
var dec = RocDec.fromU64(25);
|
||||
try expectEqual(RocDec{ .num = 25000000000000000000 }, dec);
|
||||
}
|
||||
|
||||
test "mul" {
|
||||
var dec1: RocDec = .{ .num = 0 };
|
||||
|
||||
expectEqual(RocDec{ .num = 0 }, dec1.mul(.{ .num = 0 }));
|
||||
test "fromString: 0" {
|
||||
var dec = RocDec.fromString("", 0);
|
||||
if (dec) |_| {
|
||||
unreachable;
|
||||
}
|
||||
}
|
||||
|
||||
test "fromString: 123.45" {
|
||||
var dec = RocDec.fromString("123.45", 6);
|
||||
if (dec) |d| {
|
||||
try expectEqual(RocDec{ .num = 123450000000000000000 }, d);
|
||||
} else {
|
||||
unreachable;
|
||||
}
|
||||
}
|
||||
|
||||
test "fromString: .45" {
|
||||
var dec = RocDec.fromString(".45", 3);
|
||||
if (dec) |d| {
|
||||
try expectEqual(RocDec{ .num = 450000000000000000 }, d);
|
||||
} else {
|
||||
unreachable;
|
||||
}
|
||||
}
|
||||
|
||||
test "fromString: 123" {
|
||||
var dec = RocDec.fromString("123", 3);
|
||||
if (dec) |d| {
|
||||
try expectEqual(RocDec{ .num = 123000000000000000000 }, d);
|
||||
} else {
|
||||
unreachable;
|
||||
}
|
||||
}
|
||||
|
||||
test "fromString: abc" {
|
||||
var dec = RocDec.fromString("abc", 3);
|
||||
if (dec) |_| {
|
||||
unreachable;
|
||||
}
|
||||
}
|
||||
|
||||
test "fromString: 123.abc" {
|
||||
var dec = RocDec.fromString("123.abc", 7);
|
||||
if (dec) |_| {
|
||||
unreachable;
|
||||
}
|
||||
}
|
||||
|
||||
test "fromString: abc.123" {
|
||||
var dec = RocDec.fromString("abc.123", 7);
|
||||
if (dec) |_| {
|
||||
unreachable;
|
||||
}
|
||||
}
|
||||
|
||||
test "fromString: .123.1" {
|
||||
var dec = RocDec.fromString(".123.1", 6);
|
||||
if (dec) |d| {
|
||||
std.debug.print("d: {}", .{d});
|
||||
unreachable;
|
||||
}
|
||||
}
|
||||
|
||||
test "add: 0" {
|
||||
var dec: RocDec = .{ .num = 0 };
|
||||
try expectEqual(RocDec{ .num = 0 }, dec.add(.{ .num = 0 }));
|
||||
}
|
||||
|
||||
test "add: 1" {
|
||||
var dec: RocDec = .{ .num = 0 };
|
||||
try expectEqual(RocDec{ .num = 1 }, dec.add(.{ .num = 1 }));
|
||||
}
|
||||
|
||||
test "mul: by 0" {
|
||||
var dec: RocDec = .{ .num = 0 };
|
||||
try expectEqual(RocDec{ .num = 0 }, dec.mul(.{ .num = 0 }));
|
||||
}
|
||||
|
||||
test "mul: by 1" {
|
||||
var dec: RocDec = RocDec.fromU64(15);
|
||||
try expectEqual(RocDec.fromU64(15), dec.mul(RocDec.fromU64(1)));
|
||||
}
|
||||
|
||||
test "mul: by 2" {
|
||||
var dec: RocDec = RocDec.fromU64(15);
|
||||
try expectEqual(RocDec.fromU64(30), dec.mul(RocDec.fromU64(2)));
|
||||
}
|
||||
|
50
nix/zig-unstable.nix
Normal file
50
nix/zig-unstable.nix
Normal file
@ -0,0 +1,50 @@
|
||||
{ pkgs }:
|
||||
|
||||
let
|
||||
# system helpers
|
||||
splitSystem = builtins.split "-" builtins.currentSystem;
|
||||
arch = builtins.elemAt splitSystem 0;
|
||||
isAarch64 = arch == "aarch64";
|
||||
setForSystem = { darwin, darwinAarch64, linux, linuxAarch64 }:
|
||||
if pkgs.stdenv.isDarwin
|
||||
then (
|
||||
if isAarch64
|
||||
then darwinAarch64
|
||||
else darwin
|
||||
)
|
||||
else (
|
||||
if isAarch64
|
||||
then linuxAarch64
|
||||
else linux
|
||||
);
|
||||
|
||||
version = "0.8.0-dev.2711+11ae6c42c";
|
||||
osName =
|
||||
if pkgs.stdenv.isDarwin
|
||||
then "macos" else "linux";
|
||||
archiveName = "zig-${osName}-${arch}-${version}";
|
||||
sha256 = setForSystem {
|
||||
darwin = "bf2a4cd1516d202cfbbcaa7b1308d36aa21a9f9284b39297e70f98c003f479e3";
|
||||
darwinAarch64 = "6bc35c3b40b853cd351c890c94c4a6043f5ca492ff6d704bdb1544fe1fe54d9a";
|
||||
linux = "b443cc2259fe7712ffc954745266e3ec846e27854713d817bcec35fefd655a8c";
|
||||
linuxAarch64 = "229830e6dc92f641a1106af3a8ee96fdef379ffd3a3d7db7ed62d2b46bd8ed45";
|
||||
};
|
||||
in
|
||||
pkgs.stdenv.mkDerivation {
|
||||
pname = "zig-unstable";
|
||||
version = version;
|
||||
src = pkgs.fetchurl {
|
||||
inherit sha256;
|
||||
name = "${archiveName}.tar.xz";
|
||||
url = "https://ziglang.org/builds/${archiveName}.tar.xz";
|
||||
};
|
||||
phases = [ "unpackPhase" ];
|
||||
unpackPhase = ''
|
||||
mkdir -p $out/bin
|
||||
tar -xf $src
|
||||
cp ${archiveName}/zig $out/zig
|
||||
cp -r ${archiveName}/lib $out/lib
|
||||
ln -s "$out/zig" "$out/bin/zig"
|
||||
chmod +x $out/bin/zig
|
||||
'';
|
||||
}
|
Loading…
Reference in New Issue
Block a user