u32.fz
# This file is part of the Fuzion language implementation.
#
# The Fuzion language implementation is free software: you can redistribute it
# and/or modify it under the terms of the GNU General Public License as published
# by the Free Software Foundation, version 3 of the License.
#
# The Fuzion language implementation is distributed in the hope that it will be
# useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
# License for more details.
#
# You should have received a copy of the GNU General Public License along with The
# Fuzion language implementation. If not, see <https://www.gnu.org/licenses/>.
# -----------------------------------------------------------------------
#
# Tokiwa Software GmbH, Germany
#
# Source code of Fuzion standard library feature u32
#
# Author: Fridtjof Siebert (siebert@tokiwa.software)
#
# -----------------------------------------------------------------------
# u32 -- 32-bit unsigned integer values
#
public u32(public val u32) : num.wrap_around, has_interval is
public thiz => u32.this.val
# overflow checking
# would negation -thiz cause an overflow?
redef wrapped_on_neg => !is_zero
# would addition thiz + other cause an overflow or underflow?
public fixed overflow_on_add (other u32) => u32.max -° thiz < other
public fixed underflow_on_add(other u32) => false
# would subtraction thiz - other cause an overflow or underflow?
public fixed overflow_on_sub (other u32) => false
public fixed underflow_on_sub(other u32) => thiz < other
# would multiplication thiz * other cause an overflow or underflow?
public fixed overflow_on_mul (other u32) => as_i64 *° other.as_i64 > u32.max.as_i64
public fixed underflow_on_mul(other u32) => false
# neg, add, sub, mul with wrap-around semantics
public fixed prefix -° u32 => intrinsic
public fixed infix +° (other u32) u32 => intrinsic
public fixed infix -° (other u32) u32 => intrinsic
public fixed infix *° (other u32) u32 => intrinsic
# division and remainder with check for div-by-zero
public fixed infix / (other u32)
pre
safety: other != u32 0
=> div other
public fixed infix % (other u32)
pre
safety: other != u32 0
=> mod other
# private division and remainder with crash in case of div-by-zero
private div (other u32) u32 => intrinsic
private mod (other u32) u32 => intrinsic
# bitwise and, or and xor operations
public fixed infix & (other u32) u32 => intrinsic
public fixed infix | (other u32) u32 => intrinsic
public fixed infix ^ (other u32) u32 => intrinsic
# shift operations (unsigned)
public fixed infix >> (other u32) u32 => intrinsic
public fixed infix << (other u32) u32 => intrinsic
# this u32 as an i8
public as_i8 i8
pre
debug: thiz ≤ i8.max.as_u32
=>
cast_to_i32.as_i8
# this u32 as an i16
public as_i16 i16
pre
debug: thiz ≤ i16.max.as_u32
=>
cast_to_i32.as_i16
# this u32 as an i32
public as_i32 i32
pre
debug: thiz ≤ i32.max.as_u32
=>
cast_to_i32
# this u32 as an i64
public as_i64 i64 => intrinsic
# NYI
# # this u32 as an i128
# as_i128 i128 is
# as_i64.as_i128
# this u32 as an u8
public as_u8 u8
pre
debug: thiz ≤ u8.max.as_u32
=>
cast_to_i32.as_u8
# this u32 as an u16
public as_u16 u16
pre
debug: thiz ≤ u16.max.as_u32
=>
cast_to_i32.as_u16
# this u32 as an u64
public as_u64 u64
=>
thiz.as_i64.as_u64
# this u32 as an u128
public as_u128 u128
=>
u128 0 as_u64
# this u32 as an int
public as_int => int as_i64
# this u32 as an uint
public as_uint => uint as_u64
public low8bits u8 => intrinsic
public low16bits u16 => intrinsic
public cast_to_i32 i32 => intrinsic
public cast_to_f32 f32 => intrinsic
# conversion to float
public as_f64 f64 => intrinsic
public as_f32 => as_f64.as_f32
# create hash code from this number
public type.hash_code(a u32.this) u64 =>
hash a.as_u64
# find the highest 1 bit in this integer and return integer with
# this single bit set or 0 if this is 0.
#
public highest_one_bit u32 =>
// NYI: should be possible to reuse v, s names
(v0, s0) := (val, u32 0)
(v1, s1) := if ((v0 ≥ u32 0) && (v0 < u32 0x10000)) (v0, s0) else (v0 >> 16, s0 + 16)
(v2, s2) := if ( v1 < u32 0x100 ) (v1, s1) else (v1 >> 8, s1 + 8)
(v3, s3) := if ( v2 < u32 0x10 ) (v2, s2) else (v2 >> 4, s2 + 4)
(v4, s4) := if ( v3 < u32 4 ) (v3, s3) else (v3 >> 2, s3 + 2)
(v5, s5) := if ( v4 < u32 2 ) (v4, s4) else (v4 >> 1, s4 + 1)
v5 << s5
# the highest 1 bit in this integer
#
public highest_bit u32 =>
if val = u32.zero
0
else
// NYI: should be possible to reuse v, s names
(v0, s0) := (val, u32 0)
(v1, s1) := if ((v0 ≥ u32 0) && (v0 < u32 0x10000)) (v0, s0) else (v0 >> 16, s0 + 16)
(v2, s2) := if ( v1 < u32 0x100 ) (v1, s1) else (v1 >> 8, s1 + 8)
(v3, s3) := if ( v2 < u32 0x10 ) (v2, s2) else (v2 >> 4, s2 + 4)
(v4, s4) := if ( v3 < u32 4 ) (v3, s3) else (v3 >> 2, s3 + 2)
(v5, s5) := if ( v4 < u32 2 ) (v4, s4) else (v4 >> 1, s4 + 1)
s5 + 1
# count the number of trailing zeros in this integer.
#
public trailing_zeros i32 =>
// NYI: should be possible to reuse v, s names
(v0, s0) := (val, 0)
(v1, s1) := if ((v0 & 0xffff) != u32 0) (v0, s0) else (v0 >> 16, s0 + 16)
(v2, s2) := if ((v1 & 0xff) != u32 0) (v1, s1) else (v1 >> 8, s1 + 8)
(v3, s3) := if ((v2 & 0xf) != u32 0) (v2, s2) else (v2 >> 4, s2 + 4)
(v4, s4) := if ((v3 & 3) != u32 0) (v3, s3) else (v3 >> 2, s3 + 2)
(v5, s5) := if ((v4 & 1) != u32 0) (v4, s4) else (v4 >> 1, s4 + 1)
s6 := if ((v5 & 1) != u32 0) s5 else 32
s6
# count the number of 1 bits in the binary representation of this
# integer.
#
public ones_count i32 =>
v := val;
m := v & 0xaaaaaaaa; v := v - m + (m >> 1)
m := v & 0xcccccccc; v := v - m + (m >> 2)
m := v & 0xf0f0f0f0; v := v - m + (m >> 4)
(v *° 0x01010101 >> 24).as_i32
# -----------------------------------------------------------------------
#
# type features:
# identity element for 'infix +'
#
fixed type.zero u32 => 0
# identity element for 'infix *'
#
fixed type.one u32 => 1
# equality
#
fixed type.equality(a, b u32) bool => intrinsic_constructor
# total order
#
fixed type.lteq(a, b u32) bool => intrinsic_constructor
# returns the number in whose bit representation all bits are ones
public fixed redef type.all_bits_set => u32 0x_ffff_ffff
# minimum
#
public fixed type.min => u32 0
# maximum
#
public fixed type.max => u32 0x_ffff_ffff