mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-28 18:30:06 +00:00
bit_field; Lexical sugar operators ≠ ≤ ≥
Example below: // See: https://en.wikipedia.org/wiki/Bit_field BoxProps :: bit_field { opaque : 1, fill_colour : 3, _ : 4, show_border : 1, border_colour : 3, border_style : 2, _ : 2, width : 4, height : 4, _ : 8, }
This commit is contained in:
@@ -98,6 +98,11 @@ TypeInfo :: union {
|
||||
generated_struct: ^TypeInfo,
|
||||
count: int, // == 0 if dynamic
|
||||
},
|
||||
BitField{
|
||||
names: []string,
|
||||
bits: []i32,
|
||||
offsets: []i32,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -67,3 +67,126 @@ __u128_quo_mod :: proc(a, b: u128, rem: ^u128) -> (quo: u128) #cc_odin #link_nam
|
||||
return q;
|
||||
}
|
||||
|
||||
/*
|
||||
__f16_to_f32 :: proc(f: f16) -> f32 #cc_odin #no_inline #link_name "__gnu_h2f_ieee" {
|
||||
when true {
|
||||
// Source: https://fgiesen.wordpress.com/2012/03/28/half-to-float-done-quic/
|
||||
FP32 :: raw_union {u: u32, f: f32};
|
||||
|
||||
magic, was_infnan: FP32;
|
||||
magic.u = (254-15) << 23;
|
||||
was_infnan.u = (127+16) << 23;
|
||||
|
||||
hu := transmute(u16, f);
|
||||
|
||||
o := FP32{};
|
||||
|
||||
o.u = u32((hu & 0x7fff) << 13);
|
||||
o.f *= magic.f;
|
||||
if o.f >= was_infnan.f {
|
||||
o.u |= 255 << 23;
|
||||
}
|
||||
o.u |= u32(hu & 0x8000) << 16;
|
||||
return o.f;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
__f32_to_f16 :: proc(f_: f32) -> f16 #cc_odin #no_inline #link_name "__gnu_f2h_ieee" {
|
||||
when false {
|
||||
// Source: https://gist.github.com/rygorous/2156668
|
||||
FP16 :: raw_union {u: u16, f: f16};
|
||||
FP32 :: raw_union {u: u32, f: f32};
|
||||
|
||||
f32infty, f16infty, magic: FP32;
|
||||
f32infty.u = 255<<23;
|
||||
f16infty.u = 31<<23;
|
||||
magic.u = 15<<23;
|
||||
|
||||
sign_mask :: u32(0x80000000);
|
||||
round_mask :: ~u32(0x0fff);
|
||||
|
||||
f := transmute(FP32, f_);
|
||||
|
||||
o: FP16;
|
||||
sign := f.u & sign_mask;
|
||||
f.u ~= sign;
|
||||
|
||||
// NOTE all the integer compares in this function can be safely
|
||||
// compiled into signed compares since all operands are below
|
||||
// 0x80000000. Important if you want fast straight SSE2 code
|
||||
// (since there's no unsigned PCMPGTD).
|
||||
|
||||
if f.u >= f32infty.u { // Inf or NaN (all exponent bits set)
|
||||
o.u = f.u > f32infty.u ? 0x7e00 : 0x7c00; // NaN->qNaN and Inf->Inf
|
||||
} else { // (De)normalized number or zero
|
||||
f.u &= round_mask;
|
||||
f.f *= magic.f;
|
||||
f.u -= round_mask;
|
||||
if f.u > f16infty.u {
|
||||
f.u = f16infty.u; // Clamp to signed infinity if overflowed
|
||||
}
|
||||
|
||||
o.u = u16(f.u >> 13); // Take the bits!
|
||||
}
|
||||
|
||||
o.u |= u16(sign >> 16);
|
||||
return o.f;
|
||||
} else {
|
||||
f := transmute(u32, f_);
|
||||
h: u16;
|
||||
hs, he, hf: u16;
|
||||
|
||||
fs := (f >> 31) & 1;
|
||||
fe := (f >> 23) & 0b1111_1111;
|
||||
ff := (f >> 0) & 0b0111_1111_1111_1111_1111_1111;
|
||||
|
||||
add_one := false;
|
||||
|
||||
if (fe == 0) {
|
||||
he = 0;
|
||||
} else if (fe == 255) {
|
||||
he = 31;
|
||||
hf = ff != 0 ? 0x200 : 0;
|
||||
} else {
|
||||
ne := fe - 127 + 15;
|
||||
if ne >= 31 {
|
||||
he = 31;
|
||||
} else if ne <= 0 {
|
||||
if (14-ne) <= 24 {
|
||||
mant := ff | 0x800000;
|
||||
hf = u16(mant >> (14-ne));
|
||||
|
||||
if (mant >> (13-ne)) & 1 != 0 {
|
||||
add_one = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
he = u16(ne);
|
||||
hf = u16(ff >> 13);
|
||||
if ff&0x1000 != 0 {
|
||||
add_one = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
hs = u16(hs);
|
||||
h |= (he&0b0001_1111)<<10;
|
||||
h |= (hf&0b0011_1111_1111);
|
||||
if add_one {
|
||||
h++;
|
||||
}
|
||||
h |= (hs&1) << 15;
|
||||
return transmute(f16, h);
|
||||
}
|
||||
}
|
||||
|
||||
__f64_to_f16 :: proc(f: f64) -> f16 #cc_odin #no_inline #link_name "__truncdfhf2" {
|
||||
return __f32_to_f16(f32(f));
|
||||
}
|
||||
|
||||
__f16_to_f64 :: proc(f: f16) -> f64 #cc_odin #no_inline {
|
||||
return f64(__f16_to_f32(f));
|
||||
}
|
||||
*/
|
||||
|
||||
+10
-2
@@ -197,11 +197,13 @@ write_type :: proc(buf: ^StringBuffer, ti: ^TypeInfo) {
|
||||
}
|
||||
case Float:
|
||||
match info.size {
|
||||
case 2: write_string(buf, "f16");
|
||||
case 4: write_string(buf, "f32");
|
||||
case 8: write_string(buf, "f64");
|
||||
}
|
||||
case Complex:
|
||||
match info.size {
|
||||
case 4: write_string(buf, "complex32");
|
||||
case 8: write_string(buf, "complex64");
|
||||
case 16: write_string(buf, "complex128");
|
||||
}
|
||||
@@ -625,7 +627,6 @@ fmt_float :: proc(fi: ^FmtInfo, v: f64, bit_size: int, verb: rune) {
|
||||
|
||||
case:
|
||||
fmt_bad_verb(fi, verb);
|
||||
return;
|
||||
}
|
||||
}
|
||||
fmt_string :: proc(fi: ^FmtInfo, s: string, verb: rune) {
|
||||
@@ -928,6 +929,11 @@ fmt_complex :: proc(fi: ^FmtInfo, c: complex128, bits: int, verb: rune) {
|
||||
_u128_to_lo_hi :: proc(a: u128) -> (lo, hi: u64) { return u64(a), u64(a>>64); }
|
||||
_i128_to_lo_hi :: proc(a: u128) -> (lo: u64 hi: i64) { return u64(a), i64(a>>64); }
|
||||
|
||||
|
||||
do_foo :: proc(fi: ^FmtInfo, f: f64) {
|
||||
fmt_string(fi, "Hellope$%!", 'v');
|
||||
}
|
||||
|
||||
fmt_arg :: proc(fi: ^FmtInfo, arg: any, verb: rune) {
|
||||
if arg == nil {
|
||||
write_string(fi.buf, "<nil>");
|
||||
@@ -950,8 +956,10 @@ fmt_arg :: proc(fi: ^FmtInfo, arg: any, verb: rune) {
|
||||
match a in base_arg {
|
||||
case any: fmt_arg(fi, a, verb);
|
||||
case bool: fmt_bool(fi, a, verb);
|
||||
|
||||
case f32: fmt_float(fi, f64(a), 32, verb);
|
||||
case f64: fmt_float(fi, a, 64, verb);
|
||||
case f64: fmt_float(fi, a, 64, verb);
|
||||
|
||||
case complex64: fmt_complex(fi, complex128(a), 64, verb);
|
||||
case complex128: fmt_complex(fi, a, 128, verb);
|
||||
|
||||
|
||||
+5
-6
@@ -43,16 +43,15 @@ pow :: proc(x, power: f32) -> f32 #foreign __llvm_core "llvm.pow.f32";
|
||||
pow :: proc(x, power: f64) -> f64 #foreign __llvm_core "llvm.pow.f64";
|
||||
|
||||
|
||||
lerp :: proc(a, b, t: f32) -> f32 { return a*(1-t) + b*t; }
|
||||
lerp :: proc(a, b, t: f64) -> f64 { return a*(1-t) + b*t; }
|
||||
lerp :: proc(a, b, t: f32) -> (x: f32) { return a*(1-t) + b*t; }
|
||||
lerp :: proc(a, b, t: f64) -> (x: f64) { return a*(1-t) + b*t; }
|
||||
unlerp :: proc(a, b, x: f32) -> (t: f32) { return (x-a)/(b-a); }
|
||||
unlerp :: proc(a, b, x: f64) -> (t: f64) { return (x-a)/(b-a); }
|
||||
|
||||
|
||||
sign :: proc(x: f32) -> f32 { return x >= 0 ? +1 : -1; }
|
||||
sign :: proc(x: f64) -> f64 { return x >= 0 ? +1 : -1; }
|
||||
|
||||
bit_reverse :: proc(b: u16) -> u16 #foreign __llvm_core "llvm.bitreverse.i16";
|
||||
bit_reverse :: proc(b: u32) -> u32 #foreign __llvm_core "llvm.bitreverse.i32";
|
||||
bit_reverse :: proc(b: u64) -> u64 #foreign __llvm_core "llvm.bitreverse.i64";
|
||||
|
||||
fmuladd :: proc(a, b, c: f32) -> f32 #foreign __llvm_core "llvm.fmuladd.f32";
|
||||
fmuladd :: proc(a, b, c: f64) -> f64 #foreign __llvm_core "llvm.fmuladd.f64";
|
||||
|
||||
|
||||
+155
-25
@@ -28,35 +28,164 @@ _digit_value :: proc(r: rune) -> (int) {
|
||||
return v;
|
||||
}
|
||||
|
||||
parse_i64 :: proc(s: string, base: int) -> i64 {
|
||||
result: i64;
|
||||
parse_i128 :: proc(s: string) -> i128 {
|
||||
neg := false;
|
||||
if len(s) > 1 {
|
||||
match s[0] {
|
||||
case '-':
|
||||
neg = true;
|
||||
s = s[1..];
|
||||
case '+':
|
||||
s = s[1..];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
base: i128 = 10;
|
||||
if len(s) > 2 && s[0] == '0' {
|
||||
match s[1] {
|
||||
case 'b': base = 2; s = s[2..];
|
||||
case 'o': base = 8; s = s[2..];
|
||||
case 'd': base = 10; s = s[2..];
|
||||
case 'z': base = 12; s = s[2..];
|
||||
case 'x': base = 16; s = s[2..];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
value: i128;
|
||||
for r in s {
|
||||
v := _digit_value(r);
|
||||
if r == '_' {
|
||||
continue;
|
||||
}
|
||||
|
||||
v := i128(_digit_value(r));
|
||||
if v >= base {
|
||||
break;
|
||||
}
|
||||
result *= i64(base);
|
||||
result += i64(v);
|
||||
value *= base;
|
||||
value += v;
|
||||
}
|
||||
return result;
|
||||
|
||||
return neg ? -value : value;
|
||||
}
|
||||
parse_u64 :: proc(s: string, base: int) -> u64 {
|
||||
result: u64;
|
||||
|
||||
parse_u128 :: proc(s: string) -> u128 {
|
||||
neg := false;
|
||||
if len(s) > 1 && s[0] == '+' {
|
||||
s = s[1..];
|
||||
}
|
||||
|
||||
|
||||
base: = u128(10);
|
||||
if len(s) > 2 && s[0] == '0' {
|
||||
match s[1] {
|
||||
case 'b': base = 2; s = s[2..];
|
||||
case 'o': base = 8; s = s[2..];
|
||||
case 'd': base = 10; s = s[2..];
|
||||
case 'z': base = 12; s = s[2..];
|
||||
case 'x': base = 16; s = s[2..];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
value: u128;
|
||||
for r in s {
|
||||
v := _digit_value(r);
|
||||
if r == '_' {
|
||||
continue;
|
||||
}
|
||||
|
||||
v := u128(_digit_value(r));
|
||||
if v >= base {
|
||||
break;
|
||||
}
|
||||
result *= u64(base);
|
||||
result += u64(v);
|
||||
value *= base;
|
||||
value += u128(v);
|
||||
}
|
||||
return result;
|
||||
|
||||
return neg ? -value : value;
|
||||
}
|
||||
parse_int :: proc(s: string, base: int) -> int {
|
||||
return int(parse_i64(s, base));
|
||||
|
||||
|
||||
parse_int :: proc(s: string) -> int {
|
||||
return int(parse_i128(s));
|
||||
}
|
||||
parse_uint :: proc(s: string, base: int) -> uint {
|
||||
return uint(parse_u64(s, base));
|
||||
return uint(parse_u128(s));
|
||||
}
|
||||
|
||||
parse_f64 :: proc(s: string) -> f64 {
|
||||
i := 0;
|
||||
|
||||
sign: f64 = 1;
|
||||
match s[i] {
|
||||
case '-': i++; sign = -1;
|
||||
case '+': i++;
|
||||
}
|
||||
|
||||
value: f64 = 0;
|
||||
for ; i < len(s); i++ {
|
||||
r := rune(s[i]);
|
||||
if r == '_' {
|
||||
continue;
|
||||
}
|
||||
v := _digit_value(r);
|
||||
if v >= 10 {
|
||||
break;
|
||||
}
|
||||
value *= 10;
|
||||
value += f64(v);
|
||||
}
|
||||
|
||||
if s[i] == '.' {
|
||||
pow10: f64 = 10;
|
||||
i++;
|
||||
|
||||
for ; i < len(s); i++ {
|
||||
r := rune(s[i]);
|
||||
if r == '_' {
|
||||
continue;
|
||||
}
|
||||
v := _digit_value(r);
|
||||
if v >= 10 {
|
||||
break;
|
||||
}
|
||||
value += f64(v)/pow10;
|
||||
pow10 *= 10;
|
||||
}
|
||||
}
|
||||
|
||||
frac := false;
|
||||
scale: f64 = 1;
|
||||
|
||||
if s[i] == 'e' || s[i] == 'E' {
|
||||
i++;
|
||||
|
||||
match s[i] {
|
||||
case '-': i++; frac = true;
|
||||
case '+': i++;
|
||||
}
|
||||
|
||||
exp: u32 = 0;
|
||||
for ; i < len(s); i++ {
|
||||
r := rune(s[i]);
|
||||
if r == '_' {
|
||||
continue;
|
||||
}
|
||||
d := u32(_digit_value(r));
|
||||
if d >= 10 {
|
||||
break;
|
||||
}
|
||||
exp = exp * 10 + d;
|
||||
}
|
||||
if exp > 308 { exp = 308; }
|
||||
|
||||
for exp >= 50 { scale *= 1e50; exp -= 50; }
|
||||
for exp >= 8 { scale *= 1e8; exp -= 8; }
|
||||
for exp > 0 { scale *= 10; exp -= 1; }
|
||||
}
|
||||
|
||||
return sign * (frac ? (value/scale) : (value*scale));
|
||||
}
|
||||
|
||||
|
||||
@@ -81,7 +210,7 @@ append_float :: proc(buf: []byte, f: f64, fmt: byte, prec, bit_size: int) -> str
|
||||
|
||||
|
||||
|
||||
Decimal_Slice :: struct {
|
||||
DecimalSlice :: struct {
|
||||
digits: []byte,
|
||||
count: int,
|
||||
decimal_point: int,
|
||||
@@ -94,8 +223,9 @@ Float_Info :: struct {
|
||||
bias: int,
|
||||
}
|
||||
|
||||
f32_info := Float_Info{23, 8, -127};
|
||||
f64_info := Float_Info{52, 11, -1023};
|
||||
_f16_info := Float_Info{10, 5, -15};
|
||||
_f32_info := Float_Info{23, 8, -127};
|
||||
_f64_info := Float_Info{52, 11, -1023};
|
||||
|
||||
|
||||
generic_ftoa :: proc(buf: []byte, val: f64, fmt: byte, prec, bit_size: int) -> []byte {
|
||||
@@ -104,10 +234,10 @@ generic_ftoa :: proc(buf: []byte, val: f64, fmt: byte, prec, bit_size: int) -> [
|
||||
match bit_size {
|
||||
case 32:
|
||||
bits = u64(transmute(u32, f32(val)));
|
||||
flt = &f32_info;
|
||||
flt = &_f32_info;
|
||||
case 64:
|
||||
bits = transmute(u64, val);
|
||||
flt = &f64_info;
|
||||
flt = &_f64_info;
|
||||
case:
|
||||
panic("strconv: invalid bit_size");
|
||||
}
|
||||
@@ -142,11 +272,11 @@ generic_ftoa :: proc(buf: []byte, val: f64, fmt: byte, prec, bit_size: int) -> [
|
||||
d := &d_;
|
||||
assign(d, mant);
|
||||
shift(d, exp - int(flt.mantbits));
|
||||
digs: Decimal_Slice;
|
||||
digs: DecimalSlice;
|
||||
shortest := prec < 0;
|
||||
if shortest {
|
||||
round_shortest(d, mant, exp, flt);
|
||||
digs = Decimal_Slice{digits = d.digits[..], count = d.count, decimal_point = d.decimal_point};
|
||||
digs = DecimalSlice{digits = d.digits[..], count = d.count, decimal_point = d.decimal_point};
|
||||
match fmt {
|
||||
case 'e', 'E': prec = digs.count-1;
|
||||
case 'f', 'F': prec = max(digs.count-digs.decimal_point, 0);
|
||||
@@ -163,14 +293,14 @@ generic_ftoa :: proc(buf: []byte, val: f64, fmt: byte, prec, bit_size: int) -> [
|
||||
round(d, prec);
|
||||
}
|
||||
|
||||
digs = Decimal_Slice{digits = d.digits[..], count = d.count, decimal_point = d.decimal_point};
|
||||
digs = DecimalSlice{digits = d.digits[..], count = d.count, decimal_point = d.decimal_point};
|
||||
}
|
||||
return format_digits(buf, shortest, neg, digs, prec, fmt);
|
||||
}
|
||||
|
||||
|
||||
|
||||
format_digits :: proc(buf: []byte, shortest: bool, neg: bool, digs: Decimal_Slice, prec: int, fmt: byte) -> []byte {
|
||||
format_digits :: proc(buf: []byte, shortest: bool, neg: bool, digs: DecimalSlice, prec: int, fmt: byte) -> []byte {
|
||||
match fmt {
|
||||
case 'f', 'F':
|
||||
append(buf, neg ? '-' : '+');
|
||||
@@ -190,7 +320,7 @@ format_digits :: proc(buf: []byte, shortest: bool, neg: bool, digs: Decimal_Slic
|
||||
// fractional part
|
||||
if prec > 0 {
|
||||
append(buf, '.');
|
||||
for i in 0..prec {
|
||||
for i in 0..<prec {
|
||||
c: byte = '0';
|
||||
if j := digs.decimal_point + i; 0 <= j && j < digs.count {
|
||||
c = digs.digits[j];
|
||||
|
||||
Reference in New Issue
Block a user