(********************************************************************) (* *) (* integer.s7i Integer support library *) (* Copyright (C) 1989 - 2016, 2018 - 2021, 2024 Thomas Mertes *) (* *) (* This file is part of the Seed7 Runtime Library. *) (* *) (* The Seed7 Runtime Library is free software; you can *) (* redistribute it and/or modify it under the terms of the GNU *) (* Lesser General Public License as published by the Free Software *) (* Foundation; either version 2.1 of the License, or (at your *) (* option) any later version. *) (* *) (* The Seed7 Runtime Library 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 Lesser General Public License for more *) (* details. *) (* *) (* You should have received a copy of the GNU Lesser General *) (* Public License along with this program; if not, write to the *) (* Free Software Foundation, Inc., 51 Franklin Street, *) (* Fifth Floor, Boston, MA 02110-1301, USA. *) (* *) (********************************************************************) $ system "integer" is integer; const proc: (ref integer: dest) ::= (ref integer: source) is action "INT_CREATE"; const proc: (inout integer: dest) := (in integer: source) is action "INT_CPY"; (** * Default value of ''integer'' (0). *) const integer: (attr integer) . value is 0; (** * Minimum value of ''integer'' (-9223372036854775808). *) const integer: (attr integer) . first is forward; (** * Maximum value of ''integer'' (9223372036854775807). *) const integer: (attr integer) . last is 9223372036854775807; (** * Plus sign for integer numbers. * @return its operand unchanged. *) const func integer: + (in integer: number) is action "INT_PLUS"; (** * Minus sign, negate an integer number. * @return the negated value of the number. * @exception OVERFLOW_ERROR If an integer overflow occurs. *) const func integer: - (in integer: number) is action "INT_NEGATE"; (** * Compute the factorial of a number. * @return the factorial of the number. * @exception NUMERIC_ERROR The number is negative or the result * does not fit into an integer. *) const func integer: ! (in integer: number) is action "INT_FACT"; (** * Add two integer numbers. * @return the sum of the two numbers. * @exception OVERFLOW_ERROR If an integer overflow occurs. *) const func integer: (in integer: summand1) + (in integer: summand2) is action "INT_ADD"; (** * Compute the subtraction of two integer numbers. * @return the difference of the two numbers. * @exception OVERFLOW_ERROR If an integer overflow occurs. *) const func integer: (in integer: minuend) - (in integer: subtrahend) is action "INT_SBTR"; const integer: (attr integer) . first is -9223372036854775807 - 1; (** * Multiply two integer numbers. * @return the product of the two numbers. * @exception OVERFLOW_ERROR If an integer overflow occurs. *) const func integer: (in integer: factor1) * (in integer: factor2) is action "INT_MULT"; (** * Integer division truncated towards zero. * The remainder of this division is computed with ''rem''. * For the operations ''div'' and ''rem'' holds for all A: * (A div B) * B + A rem B = A when B <> 0 * -A div B = -(A div B) when B <> 0 * -A rem B = -(A rem B) when B <> 0 * A rem B >= 0 and A rem B < abs(B) when B <> 0 and A >= 0 * A rem B <= 0 and A rem B > -abs(B) when B <> 0 and A <= 0 * @return the quotient of the integer division. * @exception NUMERIC_ERROR If a division by zero occurs. * @exception OVERFLOW_ERROR If an integer overflow occurs. *) const func integer: (in integer: dividend) div (in integer: divisor) is action "INT_DIV"; (** * Compute the remainder of the integer division ''div''. * The remainder has the same sign as the dividend. * A rem B * is equivalent to * A - (A div B) * B * @return the remainder of the integer division. * @exception NUMERIC_ERROR If a division by zero occurs. * @exception OVERFLOW_ERROR If an integer overflow occurs. *) const func integer: (in integer: dividend) rem (in integer: divisor) is action "INT_REM"; (** * Integer division truncated towards negative infinity. * The modulo (remainder) of this division is computed with ''mod''. * Therefore this division is called modulo division (''mdiv''). * For the operations ''mdiv'' and ''mod'' holds for all A: * (A mdiv B) * B + A mod B = A when B <> 0 * -A mdiv B = A mdiv -B when B <> 0 * -A mod -B = -(A mod B) when B <> 0 * A mod B >= 0 and A mod B < B when B > 0 * A mod B <= 0 and A mod B > B when B < 0 * @return the quotient of the integer division. * @exception NUMERIC_ERROR If a division by zero occurs. * @exception OVERFLOW_ERROR If an integer overflow occurs. *) const func integer: (in integer: dividend) mdiv (in integer: divisor) is action "INT_MDIV"; (** * Compute the modulo (remainder) of the integer division ''mdiv''. * The modulo has the same sign as the divisor. * A mod B * is equivalent to * A - (A mdiv B) * B * @return the modulo of the integer division. * @exception NUMERIC_ERROR If a division by zero occurs. * @exception OVERFLOW_ERROR If an integer overflow occurs. *) const func integer: (in integer: dividend) mod (in integer: divisor) is action "INT_MOD"; (** * Compute the exponentiation of an integer base with an integer exponent. * A ** 0 returns 1 for every A, even for A = 0 * 1 ** B returns 1 for B >= 0 * A ** B returns -(-A) ** B for A <= 0 and B >= 0 and odd(B) * A ** B returns (-A) ** B for A <= 0 and B >= 0 and not odd(B) * @return the result of the exponentiation. * @exception NUMERIC_ERROR If the exponent is negative. * @exception OVERFLOW_ERROR If an integer overflow occurs. *) const func integer: (in integer: base) ** (in integer: exponent) is action "INT_POW"; (** * Shift an integer number left by lshift bits. * A << B is equivalent to A * 2 ** B * @return the left shifted number. * @exception OVERFLOW_ERROR If the shift amount is * negative or greater equal 64 or * if an integer overflow occurs. *) const func integer: (in integer: number) << (in integer: lshift) is action "INT_LSHIFT"; (** * Shift an integer number right by rshift bits. * A >> B is equivalent to A mdiv 2 ** B * @return the right shifted number. * @exception OVERFLOW_ERROR If the shift amount is * negative or greater equal 64. *) const func integer: (in integer: number) >> (in integer: rshift) is action "INT_RSHIFT"; (** * Increment an integer variable by a delta. * @exception OVERFLOW_ERROR If an integer overflow occurs. *) const proc: (inout integer: number) +:= (in integer: delta) is action "INT_ADD_ASSIGN"; (** * Decrement an integer variable by a delta. * @exception OVERFLOW_ERROR If an integer overflow occurs. *) const proc: (inout integer: number) -:= (in integer: delta) is action "INT_SBTR_ASSIGN"; (** * Multiply an integer number by a factor and assign the result back to number. * @exception OVERFLOW_ERROR If an integer overflow occurs. *) const proc: (inout integer: number) *:= (in integer: factor) is action "INT_MULT_ASSIGN"; (** * Shift a number left by lshift bits and assign the result back to number. * @exception OVERFLOW_ERROR If the shift amount is * negative or greater equal 64 or * if an integer overflow occurs. *) const proc: (inout integer: number) <<:= (in integer: lshift) is action "INT_LSHIFT_ASSIGN"; (** * Shift a number right by rshift bits and assign the result back to number. * @exception OVERFLOW_ERROR If the shift amount is * negative or greater equal 64. *) const proc: (inout integer: number) >>:= (in integer: rshift) is action "INT_RSHIFT_ASSIGN"; (** * Binomial coefficient * n ! k returns 0 for k < 0, * n ! 0 returns 1, * n ! 1 returns n, * n ! k returns 0 for n >= 0 and k > n, * n ! k returns !n div (!k * !(n - k)) for k >= 0 and k <= n, * n ! k returns (-1) ** k * (n + k - 1 ! k) for n < 0 and k >= 0 * @return the binomial coefficient n over k * @exception OVERFLOW_ERROR If the result would be less than * integer.first or greater than integer.last. *) const func integer: (in integer: n) ! (in integer: k) is action "INT_BINOM"; (** * Check if two integer numbers are equal. * @return TRUE if the two numbers are equal, * FALSE otherwise. *) const func boolean: (in integer: number1) = (in integer: number2) is action "INT_EQ"; (** * Check if two integer numbers are not equal. * @return FALSE if the two numbers are equal, * TRUE otherwise. *) const func boolean: (in integer: number1) <> (in integer: number2) is action "INT_NE"; (** * Check if number1 is less than number2. * @return TRUE if number1 is less than number2, * FALSE otherwise. *) const func boolean: (in integer: number1) < (in integer: number2) is action "INT_LT"; (** * Check if number1 is greater than number2. * @return TRUE if number1 is greater than number2, * FALSE otherwise. *) const func boolean: (in integer: number1) > (in integer: number2) is action "INT_GT"; (** * Check if number1 is less than or equal to number2. * @return TRUE if number1 is less than or equal to number2, * FALSE otherwise. *) const func boolean: (in integer: number1) <= (in integer: number2) is action "INT_LE"; (** * Check if number1 is greater than or equal to number2. * @return TRUE if number1 is greater than or equal to number2, * FALSE otherwise. *) const func boolean: (in integer: number1) >= (in integer: number2) is action "INT_GE"; (** * Compare two integer numbers. * @return -1, 0 or 1 if the first argument is considered to be * respectively less than, equal to, or greater than the * second. *) const func integer: compare (in integer: number1, in integer: number2) is action "INT_CMP"; (** * Compute the hash value of an integer number. * @return the hash value. *) const func integer: hashCode (in integer: number) is action "INT_HASHCODE"; (** * Successor of an integer number. * @return number + 1 * @exception OVERFLOW_ERROR If an integer overflow occurs. *) const func integer: succ (in integer: number) is action "INT_SUCC"; (** * Predecessor of an integer number. * @return number - 1 * @exception OVERFLOW_ERROR If an integer overflow occurs. *) const func integer: pred (in integer: number) is action "INT_PRED"; (** * Compute the absolute value of an integer number. * @return the absolute value. * @exception OVERFLOW_ERROR If an integer overflow occurs. *) const func integer: abs (in integer: number) is action "INT_ABS"; (** * Compute the integer square root of an integer radicand. * @return the integer square root. * @exception NUMERIC_ERROR If the radicand is negative. *) const func integer: sqrt (in integer: radicand) is action "INT_SQRT"; (** * Compute the truncated base 10 logarithm of an integer number. * The definition of ''log10'' is extended by defining log10(0) = -1. * log10(10 ** A) returns A for A >= 0 * log10(pred(10 ** A)) returns pred(A) for A >= 0 * log10(10) returns 1 * log10(1) returns 0 * log10(0) returns -1 * @return the truncated base 10 logarithm. * @exception NUMERIC_ERROR The number is negative. *) const func integer: log10 (in integer: number) is action "INT_LOG10"; (** * Compute the truncated base 2 logarithm of an integer number. * The definition of ''log2'' is extended by defining log2(0) = -1. * log2(2 ** A) returns A for A >= 0 * log2(pred(2 ** A)) returns pred(A) for A >= 0 * log2(2) returns 1 * log2(1) returns 0 * log2(0) returns -1 * @return the truncated base 2 logarithm. * @exception NUMERIC_ERROR The number is negative. *) const func integer: log2 (in integer: number) is action "INT_LOG2"; (** * Determine if an integer number is odd. * @return TRUE if the number is odd, * FALSE otherwise. *) const func boolean: odd (in integer: number) is action "INT_ODD"; (** * Convert to integer. * @return the unchanged number. *) const func integer: ord (in integer: number) is action "INT_ICONV1"; (** * Convert to integer. * @return the unchanged number. *) const func integer: (attr integer) conv (in integer: number) is action "INT_ICONV3"; (** * Convert an ''integer'' number to a [[string]]. * The number is converted to a string with decimal representation. * For negative numbers a minus sign is prepended. * @param number Number to be converted to a [[string]]. * @return the string result of the conversion. * @exception MEMORY_ERROR Not enough memory to represent the result. *) const func string: str (in integer: number) is action "INT_STR"; (** * Convert an ''integer'' number to a [[string]]. * The number is converted to a string with decimal representation. * For negative numbers a minus sign is prepended. * @param number Number to be converted to a [[string]]. * @return the string result of the conversion. * @exception MEMORY_ERROR Not enough memory to represent the result. *) const func string: string (in integer: number) is action "INT_STR"; (** * Convert an ''integer'' number to a [[string]]. * The number is converted to a string with decimal representation. * For negative numbers a minus sign is prepended. * @param number Number to be converted to a [[string]]. * @return the string result of the conversion. * @exception MEMORY_ERROR Not enough memory to represent the result. *) const func string: literal (in integer: number) is action "INT_STR"; (** * Convert an ''integer'' number to a [[string]] using a radix. * The conversion uses the numeral system with the given ''base''. * Digit values from 10 upward are encoded with lower case letters. * E.g.: 10 is encoded with a, 11 with b, etc. * For negative numbers a minus sign is prepended. * 48879 radix 16 returns "beef" * -48879 radix 16 returns "-beef" * @param number Number to be converted to a [[string]]. * @param base Base of the numeral system used for the conversion. * @return the string result of the conversion. * @exception RANGE_ERROR If base < 2 or base > 36 holds. * @exception MEMORY_ERROR Not enough memory to represent the result. *) const func string: (in integer: number) radix (in integer: base) is action "INT_radix"; (** * Convert an ''integer'' number to a [[string]] using a radix. * The conversion uses the numeral system with the given ''base''. * Digit values from 10 upward are encoded with upper case letters. * E.g.: 10 is encoded with A, 11 with B, etc. * For negative numbers a minus sign is prepended. * 48879 RADIX 16 returns "BEEF" * -48879 RADIX 16 returns "-BEEF" * @param number Number to be converted to a [[string]]. * @param base Base of the numeral system used for the conversion. * @return the string result of the conversion. * @exception RANGE_ERROR If base < 2 or base > 36 holds. * @exception MEMORY_ERROR Not enough memory to represent the result. *) const func string: (in integer: number) RADIX (in integer: base) is action "INT_RADIX"; (** * Convert ''integer'' to [[string]] and pad it with zeros at the left side. * The number is converted to a string with decimal representation. * For negative numbers a minus sign is prepended. * 123 lpad0 5 returns "00123" * -123 lpad0 5 returns "-0123" * 123 lpad0 2 returns "123" * -123 lpad0 2 returns "-123" * @param number Number to be converted to a [[string]]. * @param length Minimum length of the result. * @return number as decimal [[string]] left padded with zeroes. * @exception MEMORY_ERROR Not enough memory to represent the result. *) const func string: (in integer: number) lpad0 (in integer: length) is action "INT_LPAD0"; (** * Increment an integer variable. * Increments ''number'' by 1. * This is equivalent to: * number := succ(number); * @exception OVERFLOW_ERROR If an integer overflow occurs. *) const proc: incr (inout integer: number) is action "INT_INCR"; (** * Decrement an integer variable. * Decrements ''number'' by 1. * This is equivalent to: * number := pred(number); * @exception OVERFLOW_ERROR If an integer overflow occurs. *) const proc: decr (inout integer: number) is action "INT_DECR"; (** * Compute pseudo-random number in the range [low, high]. * The random values are uniform distributed. * @return a random number such that low <= rand(low, high) and * rand(low, high) <= high holds. * @exception RANGE_ERROR The range is empty (low > high holds). *) const func integer: rand (in integer: low, in integer: high) is action "INT_RAND"; (** * Number of bits in the minimum two's-complement representation. * The high bits equivalent to the sign bit are not part of the * minimum two's-complement representation. * bitLength(0) returns 0 * bitLength(1) returns 1 * bitLength(4) returns 3 * bitLength(-1) returns 0 * bitLength(-2) returns 1 * bitLength(-4) returns 2 * @return the number of bits. *) const func integer: bitLength (in integer: number) is action "INT_BIT_LENGTH"; (** * Number of lowest-order zero bits in the two's-complement representation. * This is equal to the index of the lowest-order one bit (indices start with 0). * If there are only zero bits (''number'' is 0) the result is -1. * lowestSetBit(0) returns -1 * lowestSetBit(1) returns 0 * lowestSetBit(4) returns 2 * lowestSetBit(-1) returns 0 * lowestSetBit(-2) returns 1 * lowestSetBit(-4) returns 2 * @return the number of lowest-order zero bits or -1 for lowestSetBit(0). *) const func integer: lowestSetBit (in integer: number) is action "INT_LOWEST_SET_BIT"; (** * Convert a [[string]] to an ''integer'' number. * The [[string]] must contain an integer literal consisting of an * optional + or - sign, followed by a sequence of digits. Other * characters as well as leading or trailing whitespace characters * are not allowed. The sequence of digits is taken to be decimal. * integer("12345") returns 12345 * integer("-12345") returns -12345 * integer("+12345") returns 12345 * integer(" 12345") raises RANGE_ERROR * integer("12345 ") raises RANGE_ERROR * integer("-") raises RANGE_ERROR * integer("zero") raises RANGE_ERROR * integer("9223372036854775807") returns 9223372036854775807 * integer("9223372036854775808") raises RANGE_ERROR * @return the ''integer'' result of the conversion. * @exception RANGE_ERROR If the string is empty or it does not contain * an integer literal or if the integer literal is too big * or too small to be represented as ''integer'' value. *) const func integer: integer (in string: stri) is action "INT_PARSE1"; (** * Convert a [[string]] to an ''integer'' number. * The [[string]] must contain an integer literal consisting of an * optional + or - sign, followed by a sequence of digits. Other * characters as well as leading or trailing whitespace characters * are not allowed. The sequence of digits is taken to be decimal. * integer parse "12345" returns 12345 * integer parse "-12345" returns -12345 * integer parse "+12345" returns 12345 * integer parse " 12345" raises RANGE_ERROR * integer parse "12345 " raises RANGE_ERROR * integer parse "-" raises RANGE_ERROR * integer parse "zero" raises RANGE_ERROR * integer parse "9223372036854775807" returns 9223372036854775807 * integer parse "9223372036854775808" raises RANGE_ERROR * @return the ''integer'' result of the conversion. * @exception RANGE_ERROR If the string is empty or it does not contain * an integer literal or if the integer literal is too big * or too small to be represented as ''integer'' value. *) const func integer: (attr integer) parse (in string: stri) is return integer(stri); (** * Convert a numeric [[string]], with a specified radix, to an ''integer''. * The numeric [[string]] must contain the representation of an integer * in the specified radix. It consists of an optional + or - sign, * followed by a sequence of digits in the specified radix. Digit values * from 10 upward can be encoded with upper or lower case letters. * E.g.: 10 can be encoded with A or a, 11 with B or b, etc. Other * characters as well as leading or trailing whitespace characters * are not allowed. * integer("beef", 16) returns 48879 * integer("-177", 8) returns -127 * integer("10101010", 2) returns 170 * integer("Cafe", 16) returns 51966 * @param stri Numeric string to be converted to an integer. * @param base Radix of the integer in the ''stri'' parameter. * @return the ''integer'' result of the conversion. * @exception RANGE_ERROR If base < 2 or base > 36 holds or * the string is empty or it does not contain an integer * literal with the specified base. *) const func integer: integer (in string: stri, in integer: base) is forward; (** * Convert an ''integer'' number to a [[string]] in scientific notation. * Scientific notation uses a decimal significand and a decimal exponent. * The significand has an optional sign and exactly one digit before the * decimal point. The fractional part of the significand is rounded * to the specified number of digits (''precision''). Halfway cases are * rounded away from zero. The fractional part is followed by the * letter e and an exponent, which is always signed. The value zero is * never written with a negative sign. * 12345 sci 4 returns "1.2345e+4" * 12345 sci 3 returns "1.235e+4" * 12345 sci 2 returns "1.23e+4" * 3141592 sci 0 returns "3e+6" * 27182818 sci 0 returns "3e+7" * 2**62 sci 6 returns "4.611686e+18" * -1 sci 3 returns "-1.000e+0" * -0 sci 2 returns "0.00e+0" * @param number Number to be converted to a string. * @param precision Number of digits after the decimal point. * If the ''precision'' is zero the decimal point is omitted. * @return the string result of the conversion. * @exception RANGE_ERROR If the ''precision'' is negative. *) const func string: (in integer: number) sci (in integer: precision) is forward; const proc: DECLARE_MIN_MAX (in type: aType) is func begin (** * Determine the minimum of two values. * @return the minimum of the two values. *) const func aType: min (in aType: value1, in aType: value2) is return value1 < value2 ? value1 : value2; (** * Determine the maximum of two values. * @return the maximum of the two values. *) const func aType: max (in aType: value1, in aType: value2) is return value1 > value2 ? value1 : value2; end func; DECLARE_TERNARY(integer); DECLARE_MIN_MAX(integer);