int.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 int
#
# Author: Michael Lill (michael.lill@tokiwa.software)
#
# -----------------------------------------------------------------------
# int -- signed integer values of arbitrary size
#
module:public int (public s num.sign, public n uint) : has_interval
is
# normalize the sign => no minus zero
ns := if n = uint.zero then num.plus else s
public thiz => int ns n
name String =>
"int"
public fixed type.zero int =>
int num.plus uint.zero
public fixed type.one int =>
int num.plus uint.one
fixed redef prefix - int =>
match ns
num.plus => int num.minus n
num.minus => int num.plus n
# add this int to other
public fixed infix + (other int) int =>
if ns = other.ns
int ns n+other.n
else
match ns
num.plus => thiz - (-other)
num.minus => other - (-thiz)
# subtract other from this int
public fixed infix - (other int) int =>
match other.ns
num.plus =>
match ns
num.plus =>
if n ≥ other.n
int num.plus (n - other.n)
else
int num.minus (other.n - n)
num.minus => -(-int.this + other)
# minus, minus => plus
num.minus => int.this + -other
# the sign of the result of the
# multiplication or division of thiz and other
private result_sign_mul_div(other int) num.sign =>
if ns = other.ns then num.plus else num.minus
# multiply this int by other
public fixed infix * (other int) int =>
int (result_sign_mul_div other) n*other.n
# divide this int by other
public fixed infix / (other int) int
pre other != int.zero
=>
s num.sign := result_sign_mul_div other
int s n/other.n
# modulo, returns the remainder of the
# division of this int by other
public fixed infix % (other int) int =>
int ns n%other.n
# exponentation operator:
# this int to the power of other
public fixed infix ** (other int) int
pre other ≥ int.zero
=>
match s
num.plus => int num.plus (n ** other.n)
num.minus =>
s num.sign := if other %% (int 2) then num.plus else num.minus
int s (n ** other.n)
# all operations are allowed for all ints
# except for division where we need to
# check for division by zero
public fixed prefix -! bool => true
public fixed infix +! (other int) bool => true
public fixed infix -! (other int) bool => true
public fixed infix *! (other int) bool => true
public fixed infix /! (other int) bool =>
other != int.zero
public fixed infix %! (other int) bool => true
public fixed infix **!(other int) bool =>
other ≥ int.zero # 0 and 1 ** -other would be okay but we disallow nonetheless
public fixed infix **?(other int) num_option int =>
match other.ns
num.plus => thiz ** other
num.minus => nil # 0 and 1 ** -other would be okay but we disallow nonetheless
public fixed infix **^(other int) int =>
match other.ns
num.plus => thiz ** other
num.minus => panic "negativ exponent is not allowed." # 0 or 1 ** -other would be okay but we disallow nonetheless
# equality: are these two ints equal?
#
fixed type.equality(a, b int) bool =>
(a.ns = b.ns) & (a.n = b.n)
# total order
#
fixed type.lteq(a, b int) bool =>
match a.ns
num.plus =>
match b.ns
num.plus => a.n ≤ b.n
num.minus => false
num.minus =>
match b.ns
num.plus => true
num.minus => b.n ≤ a.n
public redef as_string String =>
s.as_string + n.as_string
# this int as an i32
public as_i32 i32 =>
n.as_i32
# this int as an i64
public as_i64 i64 =>
n.as_i64
# this int as an u8
public as_u8 u8
# NYI pre int.this >= 0
=>
n.as_u8
# this int as an u32
public as_u32 u32
# NYI pre int.this >= 0
=>
n.as_u32
# this int as an u64
public as_u64 u64
# NYI pre int.this >= 0
=>
n.as_u64
# this int as an uint
public as_uint uint
# NYI pre int.this >= 0
=>
n
# helper feature to init int via an i64
type.from_i64(val i64) int =>
s num.sign := if val < (i64 0) then num.minus else num.plus
n u64 := if val = i64.min
i64.max.as_u64 + 1
else if val < (i64 0)
(-val).as_u64
else val.as_u64
int s (uint n)
# helper feature to init int via a u64
public type.from_u64(val u64) int =>
int num.plus (uint val)
# helper feature to init int via an i32
public type.from_i32(val i32) int =>
from_i64 val.as_i64
# shorthand to create an int via an i64
public int (val i64) int =>
int.from_i64 val
last changed: 2024-03-07