Fuzion Logo
fuzion-lang.dev — The Fuzion Language Portal
JavaScript seems to be disabled. Functionality is limited.

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

  # overflow checking

  # would negation cause an overflow?
  public redef wrapped_on_neg bool => !is_zero

  # would addition + other cause an overflow or underflow?
  public fixed redef overflow_on_add (other u32) bool => u32.max -° val < other
  public fixed redef underflow_on_add(other u32) bool => false

  # would subtraction - other cause an overflow or underflow?
  public fixed redef overflow_on_sub (other u32) bool => false
  public fixed redef underflow_on_sub(other u32) bool => val < other

  # would multiplication * other cause an overflow or underflow?
  public fixed redef overflow_on_mul (other u32) bool => as_i64 *° other.as_i64 > u32.max.as_i64
  public fixed redef underflow_on_mul(other u32) bool => false

  # neg, add, sub, mul with wrap-around semantics
  public fixed redef prefix -° u32 => intrinsic
  public fixed redef infix +° (other u32) u32 => intrinsic
  public fixed redef infix -° (other u32) u32 => intrinsic
  public fixed redef infix *° (other u32) u32 => intrinsic

  # division and remainder with check for div-by-zero
  public fixed redef infix / (other u32) u32 => div other
  public fixed redef infix % (other u32) u32 => mod other

  # division and remainder with crash in case of div-by-zero
  div (other u32) u32 => intrinsic
  mod (other u32) u32 => intrinsic

  # bitwise and, or and xor operations
  public fixed redef infix &  (other u32) u32 => intrinsic
  public fixed redef infix |  (other u32) u32 => intrinsic
  public fixed redef infix ^  (other u32) u32 => intrinsic

  # shift operations (unsigned)
  public fixed redef infix >> (other u32) u32 => intrinsic
  public fixed redef infix << (other u32) u32 => intrinsic

  # does this u32 fit into an u8?
  #
  public fixed redef fits_in_u8 bool  => val ≤ u8.max.as_u32


  # this u32 as an i8
  public as_i8 i8
    pre
      debug: val ≤ i8.max.as_u32
    =>
      cast_to_i32.as_i8


  # this u32 as an i16
  public as_i16 i16
    pre
      debug: val ≤ i16.max.as_u32
    =>
      cast_to_i32.as_i16


  # this u32 as an i32
  public as_i32 i32
    pre
      debug: val ≤ i32.max.as_u32
    =>
      cast_to_i32


  # this u32 as an i64
  public as_i64 i64 => intrinsic


  # this u32 as an i128
  public as_i128 i128 =>
    as_u64.as_i128


  # this u32 as an u8
  public redef as_u8 u8 => cast_to_i32.as_u8


  # this u32 as an u16
  public as_u16 u16
    pre
      debug: val ≤ u16.max.as_u32
    =>
      cast_to_i32.as_u16


  # this u32 as an u64
  public as_u64 u64
    =>
      val.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 => int as_i64


  # this u32 as an uint
  public as_uint uint => uint as_u64


  public redef 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 f32 => as_f64.as_f32


  # create hash code from this number
  public redef 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 =>
    v, s   := (val, u32 0)
    v1, s1 := if ((v ≥ 0) && (v  < 0x10000)) (v , s)  else (v  >> 16, s  + 16)
    v2, s2 := if (            v1 < 0x100 )   (v1, s1) else (v1 >>  8, s1 +  8)
    v3, s3 := if (            v2 < 0x10 )    (v2, s2) else (v2 >>  4, s2 +  4)
    v4, s4 := if (            v3 < 4 )       (v3, s3) else (v3 >>  2, s3 +  2)
    v5, s5 := if (            v4 < 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
      v, s   := (val, u32 0)
      v1, s1 := if ((v ≥ 0) &&     (v  < 0x10000 )) (v , s ) else (v  >> 16, s  + 16)
      v2, s2 := if (                v1 < 0x100   )  (v1, s1) else (v1 >>  8, s1 +  8)
      v3, s3 := if (                v2 < 0x10    )  (v2, s2) else (v2 >>  4, s2 +  4)
      v4, s4 := if (                v3 < 4       )  (v3, s3) else (v3 >>  2, s3 +  2)
      _, s5  := if (                v4 < 2       )  (v4, s4) else (v4 >>  1, s4 +  1)
      s5 + 1


  # count the number of trailing zeros in this integer.
  #
  public trailing_zeros i32 =>
    v, s := (val, 0)
    v1, s1 := if ((v  &     0xffff) != 0) (v , s ) else (v  >> 16, s  + 16)
    v2, s2 := if ((v1 &       0xff) != 0) (v1, s1) else (v1 >>  8, s1 +  8)
    v3, s3 := if ((v2 &        0xf) != 0) (v2, s2) else (v2 >>  4, s2 +  4)
    v4, s4 := if ((v3 &          3) != 0) (v3, s3) else (v3 >>  2, s3 +  2)
    v5, s5 := if ((v4 &          1) != 0) (v4, s4) else (v4 >>  1, s4 +  1)
    if             ((v5 &          1) != 0)      s5  else                32


  # count the number of 1 bits in the binary representation of this
  # integer.
  #
  public redef ones_count i32 =>
    v := val;
    m  := v  & 0xaaaaaaaa; v1 := v  - m  + (m  >> 1)
    m1 := v1 & 0xcccccccc; v2 := v1 - m1 + (m1 >> 2)
    m2 := v2 & 0xf0f0f0f0; v3 := v2 - m2 + (m2 >> 4)
    (v3 *° 0x01010101 >> 24).as_i32


  # -----------------------------------------------------------------------
  #
  # type features:


  # identity element for 'infix +'
  #
  public fixed redef type.zero u32 => 0


  # identity element for 'infix *'
  #
  public fixed redef type.one  u32 => 1


  # equality
  #
  public fixed redef type.equality(a, b u32) bool => intrinsic


  # total order
  #
  public fixed redef type.lteq(a, b u32) bool => intrinsic


  # returns the number in whose bit representation all bits are ones
  public fixed redef type.all_bits_set u32 => u32 0x_ffff_ffff


  # minimum
  #
  public fixed redef type.min u32 => u32 0


  # maximum
  #
  public fixed redef type.max u32 => u32 0x_ffff_ffff

last changed: 2025-07-10