i32.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 i32
#
# Author: Fridtjof Siebert (siebert@tokiwa.software)
#
# -----------------------------------------------------------------------
# i32 -- 32-bit signed integer values
#
public i32(public val i32) : num.wrap_around, has_interval, java_primitive is
# overflow checking
# would negation cause an overflow?
redef wrapped_on_neg => is_min
# would addition + other cause an overflow or underflow?
public fixed redef overflow_on_add (other i32) => val > 0 && i32.max -° val < other
public fixed redef underflow_on_add(other i32) => val < 0 && i32.min -° val > other
# would subtraction - other cause an overflow or underflow?
public fixed redef overflow_on_sub (other i32) => val > 0 && val -° i32.max > other
public fixed redef underflow_on_sub(other i32) => val < 0 && val -° i32.min < other
# would multiplication * other cause an overflow or underflow?
public fixed redef overflow_on_mul (other i32) => as_i64 *° other.as_i64 > i32.max.as_i64
public fixed redef underflow_on_mul(other i32) => as_i64 *° other.as_i64 < i32.min.as_i64
# neg, add, sub, mul with wrap-around semantics
public fixed redef prefix -° i32 => intrinsic
public fixed redef infix +° (other i32) i32 => intrinsic
public fixed redef infix -° (other i32) i32 => intrinsic
public fixed redef infix *° (other i32) i32 => intrinsic
# division and remainder with check for div-by-zero
public fixed redef infix / (other i32)
pre else
# NYI: #3051 precondition inheritance does not work yet
# remove this redundant precondition once #3051 is fixed
safety: other != 0
=> div other
public fixed redef infix % (other i32)
pre else
# NYI: #3051 precondition inheritance does not work yet
# remove this redundant precondition once #3051 is fixed
safety: other != 0
=> mod other
# division and remainder with crash in case of div-by-zero
div (other i32) i32 => intrinsic
mod (other i32) i32 => intrinsic
# bitwise and, or and xor operations
public fixed redef infix & (other i32) i32 => intrinsic
public fixed redef infix | (other i32) i32 => intrinsic
public fixed redef infix ^ (other i32) i32 => intrinsic
# shift operations (signed)
public fixed redef infix >> (other i32) i32 => intrinsic
public fixed redef infix << (other i32) i32 => intrinsic
# does this i32 fit into an u8?
#
public fixed redef fits_in_u8 => 0 ≤ val ≤ u8.max.as_i32
# conversion to u32, i64 and u64, with range check
public as_i8 i8
pre
debug: val ≥ i8.min.as_i32
debug: val ≤ i8.max.as_i32
=>
low8bits.cast_to_i8
public as_i16 i16
pre
debug: val ≥ i16.min.as_i32
debug: val ≤ i16.max.as_i32
=>
low16bits.cast_to_i16
public as_i64 i64 => intrinsic
public as_i128 =>
as_i64.as_i128
public redef as_u8 u8 => low8bits
public as_u16 u16
pre
debug: val ≥ u16.min.as_i32
debug: val ≤ u16.max.as_i32
=>
low16bits
public as_u32 u32
pre
debug: val ≥ 0
=>
cast_to_u32
public as_u64 u64
pre
debug: val ≥ 0
=>
as_i64.as_u64
public as_u128 u128
pre
debug: val ≥ 0
=>
u128 0 as_i64.as_u64
public as_int int =>
int as_i64
# casting bit representation to unsigned
public redef low8bits u8 => cast_to_u32.low8bits # 0x1234_5678 -> 0x78, -0x1234_5678 -> 0x88
public low16bits u16 => cast_to_u32.low16bits # 0x1234_5678 -> 0x5678, -0x1234_5678 -> 0xa988
public cast_to_u32 u32 => intrinsic # 0x1234_5678 -> 0x1234_5678, -0x1234_5678 -> 0xedcb_a988
public cast_to_u64 u64 => cast_to_u32.as_u64 # 0x1234_5678 -> 0x1234_5678, -0x1234_5678 -> 0x0000_0000_edcb_a988
public cast_to_u128 u128 => cast_to_u32.as_u128 # 0x1234_5678 -> 0x1234_5678, -0x1234_5678 -> 0x0000_0000_0000_0000_0000_0000_edcb_a988
# conversion to float
public as_f64 f64 => intrinsic
public as_f32 => as_f64.as_f32
# create hash code from this number
public redef type.hash_code(a i32.this) u64 =>
hash a.cast_to_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 i32 =>
val.cast_to_u32.highest_one_bit.cast_to_i32
# count the number of trailing zeros in this integer.
#
public trailing_zeros i32 =>
val.cast_to_u32.trailing_zeros
# count the number of 1 bits in the binary representation of this
# integer.
#
public redef ones_count i32 =>
val.cast_to_u32.ones_count
# -----------------------------------------------------------------------
#
# type features:
# identity element for 'infix +'
#
fixed redef type.zero i32 => 0
# identity element for 'infix *'
#
fixed redef type.one i32 => 1
# equality
#
public fixed redef type.equality(a, b i32) bool => intrinsic
# total order
#
public fixed redef type.lteq(a, b i32) bool => intrinsic
# returns the number in whose bit representation all bits are ones
public fixed redef type.all_bits_set => i32 -1
# minimum
#
public fixed redef type.min => i32 -0x_8000_0000
# maximum
#
public fixed redef type.max => i32 0x_7fff_ffff
last changed: 2025-01-23