/*---------------------------------------------------------------------------
  Copyright 2012-2024, Microsoft Research, Daan Leijen.

  This is free software; you can redistribute it and/or modify it under the
  terms of the Apache License, Version 2.0. A copy of the License can be
  found in the LICENSE file at the root of this distribution.
---------------------------------------------------------------------------*/

// Standard integer `:int` functions.
//
// These are arbitrary precision signed integer with an efficient runtime representation.
// For more details, see:
//
// >   "What About the Integer Numbers?
// >   "Fast Arithmetic with Tagged Integers -- A Plea for Hardware Support"
// >   Daan Leijen, Technical report MSR-TR-2022-17, 2022-07-11, v1.0. Presented at the ML workshop 2022."
// >   <https://www.microsoft.com/en-us/research/uploads/prod/2022/07/int.pdf>
//
module std/core/intstd/core/int

import std/core/typesstd/core/types

extern import
  c  file "inline/int.h"
  js file "inline/int.js"

pub fip fun orderstd/core/int/order: (i : int) -> order( ii: int : intstd/core/types/int: V )result: -> total order : orderstd/core/types/order: V
  if ii: int <std/core/int/(<): (x : int, y : int) -> bool 0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
then Ltstd/core/types/Lt: order elif ii: int >std/core/int/(>): (x : int, y : int) -> bool 0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
then Gtstd/core/types/Gt: order else Eqstd/core/types/Eq: order
// Compare two integers pub inline fip fun cmpstd/core/int/cmp: (x : int, y : int) -> order(^xx: int : intstd/core/types/int: V, ^yy: int : intstd/core/types/int: V)result: -> total order : orderstd/core/types/order: V if (xx: int==std/core/int/(==): (x : int, y : int) -> boolyy: int) then Eqstd/core/types/Eq: order elif (xx: int>std/core/int/(>): (x : int, y : int) -> boolyy: int) then Gtstd/core/types/Gt: order else Ltstd/core/types/Lt: order // c inline "kk_int_as_order(kk_integer_cmp_borrow(#1,#2,kk_context()),kk_context())" // cs "Primitive.IntCompare" // js "$std_core_types._int_compare" // Order two integers in ascending order. pub inline fip fun order2std/core/int/order2: (x : int, y : int) -> order2<int>(xx: int : intstd/core/types/int: V, yy: int : intstd/core/types/int: V)result: -> total order2<int> : order2std/core/types/order2: V -> V<intstd/core/types/int: V> if (xx: int==std/core/int/(==): (x : int, y : int) -> boolyy: int) then Eq2std/core/types/Eq2: forall<a> (eq : a) -> order2<a>(xx: int) elif (xx: int <std/core/int/(<): (x : int, y : int) -> bool yy: int) then Lt2std/core/types/Lt2: forall<a> (lt : a, gt : a) -> order2<a>(xx: int,yy: int) else Gt2std/core/types/Gt2: forall<a> (lt : a, gt : a) -> order2<a>(yy: int,xx: int) // Are two integers equal? pub inline fip extern (==)std/core/int/(==): (x : int, y : int) -> bool(^x : intstd/core/types/int: V, ^y : intstd/core/types/int: V) : boolstd/core/types/bool: V c "kk_integer_eq_borrow" cs inline "(#1 == #2)" js "$std_core_types._int_eq" // Are two integers not equal? pub inline fip extern (!=)std/core/int/(!=): (x : int, y : int) -> bool(^x : intstd/core/types/int: V, ^y : intstd/core/types/int: V) : boolstd/core/types/bool: V c "kk_integer_neq_borrow" cs inline "(#1 != #2)" js "$std_core_types._int_ne" // Is the first integer smaller or equal to the second? pub inline fip extern (<=)std/core/int/(<=): (x : int, y : int) -> bool(^x : intstd/core/types/int: V, ^y : intstd/core/types/int: V) : boolstd/core/types/bool: V c "kk_integer_lte_borrow" cs inline "(#1 <= #2)" js "$std_core_types._int_le" // Is the first integer greater or equal to the second? pub inline fip extern (>=)std/core/int/(>=): (x : int, y : int) -> bool(^x : intstd/core/types/int: V, ^y : intstd/core/types/int: V) : boolstd/core/types/bool: V c "kk_integer_gte_borrow" cs inline "(#1 >= #2)" js "$std_core_types._int_ge" // Is the first integer smaller than the second? pub inline fip extern (<)std/core/int/(<): (x : int, y : int) -> bool(^x : intstd/core/types/int: V, ^y : intstd/core/types/int: V) : boolstd/core/types/bool: V c "kk_integer_lt_borrow" cs inline "(#1 < #2)" js "$std_core_types._int_lt" // Is the first integer greater than the second? pub inline fip extern (>)std/core/int/(>): (x : int, y : int) -> bool(^x : intstd/core/types/int: V, ^y : intstd/core/types/int: V) : boolstd/core/types/bool: V c "kk_integer_gt_borrow" cs inline "(#1 > #2)" js "$std_core_types._int_gt" inline fip extern int-addstd/core/int/int-add: (int, int) -> int : (intstd/core/types/int: V,intstd/core/types/int: V) -> intstd/core/types/int: V c "kk_integer_add" cs inline "(#1 + #2)" js "$std_core_types._int_add" // Add two integers. pub fip fun (+)std/core/int/(+): (x : int, y : int) -> int(xx: int : intstd/core/types/int: V, yy: int : intstd/core/types/int: V )result: -> total int : intstd/core/types/int: V int-addstd/core/int/int-add: (int, int) -> int(xx: int,yy: int) inline fip extern int-substd/core/int/int-sub: (int, int) -> int : (intstd/core/types/int: V,intstd/core/types/int: V) -> intstd/core/types/int: V c "kk_integer_sub" cs inline "(#1 - #2)" js "$std_core_types._int_sub" // Substract two integers. pub fip fun (-)std/core/int/(-): (x : int, y : int) -> int(xx: int : intstd/core/types/int: V, yy: int : intstd/core/types/int: V )result: -> total int : intstd/core/types/int: V int-substd/core/int/int-sub: (int, int) -> int(xx: int,yy: int) // Multiply two integers. pub inline fip extern (*)std/core/int/(*): (int, int) -> int : (intstd/core/types/int: V,intstd/core/types/int: V) -> intstd/core/types/int: V c "kk_integer_mul" cs inline "(#1 * #2)" js "$std_core_types._int_mul" // Euclidean-0 division of two integers. See also `divmod:(x : int, y : int) -> (int,int)`. pub inline fip extern (/)std/core/int/(/): (x : int, y : int) -> int(x:intstd/core/types/int: V,y:intstd/core/types/int: V) : intstd/core/types/int: V c "kk_integer_div" cs "Primitive.IntDiv" js "$std_core_types._int_div" // Euclidean modulus of two integers; always a non-negative number. See also `divmod:(x : int, y : int) -> (int,int)`. pub inline fip extern (%)std/core/int/(%): (int, int) -> int : (intstd/core/types/int: V,intstd/core/types/int: V) -> intstd/core/types/int: V c "kk_integer_mod" cs "Primitive.IntMod" js "$std_core_types._int_mod" /* Euclidean-0 division & modulus. Euclidean division is defined as: For any `D` and `d` where ``d!=0`` , we have: 1. ``D == d*(D/d) + (D%d)`` 2. ``D%d`` is always positive where ``0 <= D%d < abs(d)`` Moreover, Euclidean-0 is a total function, for the case where `d==0` we have that ``D%0 == D`` and ``D/0 == 0`` . So property (1) still holds, but not property (2). Useful laws that hold for Euclidean-0 division: * ``D/(-d) == -(D/d)`` * ``D%(-d) == D%d`` * ``D/(2^n) == sar(D,n) `` (where ``2^n`` means ``2`` to the power of ``n``) * ``D%(2^n) == D & ((2^n) - 1) `` See also _Division and modulus for computer scientists, Daan Leijen, 2001_ for further information (available at: <https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/divmodnote-letter.pdf>). */ pub fip extern divmodstd/core/int/divmod: (x : int, y : int) -> (int, int)(xx: int:intstd/core/types/int: V,yy: int:intstd/core/types/int: V) : (std/core/types/tuple2: (V, V) -> Vintstd/core/types/int: V,intstd/core/types/int: V) c "kk_integer_div_mod_tuple" cs "Primitive.IntDivMod" js "$std_core_types._int_divmod" pub fip fun negatestd/core/int/negate: (i : int) -> int(ii: int : intstd/core/types/int: V)result: -> total int : intstd/core/types/int: V ~std/core/int/(~): (i : int) -> intii: int // Negate an integer. pub inline fip extern (~)std/core/int/(~): (i : int) -> int(i:intstd/core/types/int: V) : intstd/core/types/int: V c "kk_integer_neg" cs inline "(-#1)" js "$std_core_types._int_negate" // Is this an odd integer? pub inline fip extern is-oddstd/core/int/is-odd: (i : int) -> bool( i : intstd/core/types/int: V ) : boolstd/core/types/bool: V c "kk_integer_is_odd" cs inline "!(#1.IsEven)" js "$std_core_types._int_isodd" // Is this equal to zero? pub inline fip extern is-zerostd/core/int/is-zero: (x : int) -> bool( ^x : intstd/core/types/int: V) : boolstd/core/types/bool: V c inline "kk_integer_is_zero_borrow(#1)" cs inline "(#1.IsZero)" js "$std_core_types._int_iszero" // Return the absolute value of an integer. pub inline fip extern absstd/core/int/abs: (i : int) -> int(i : intstd/core/types/int: V) : intstd/core/types/int: V c "kk_integer_abs" cs "BigInteger.Abs" js "$std_core_types._int_abs" // Increment pub fip fun incstd/core/int/inc: (i : int) -> int( ii: int : intstd/core/types/int: V )result: -> total int : intstd/core/types/int: V ii: int +std/core/int/(+): (x : int, y : int) -> int 1literal: int
dec = 1
hex8 = 0x01
bit8 = 0b00000001
// Decrement pub fip fun decstd/core/int/dec: (i : int) -> int( ii: int : intstd/core/types/int: V )result: -> total int : intstd/core/types/int: V ii: int -std/core/int/(-): (x : int, y : int) -> int 1literal: int
dec = 1
hex8 = 0x01
bit8 = 0b00000001
// Calculate ``10^exp`` pub fip fun exp10std/core/int/exp10: (exp : int) -> int( expexp: int : intstd/core/types/int: V )result: -> total int : intstd/core/types/int: V 1literal: int
dec = 1
hex8 = 0x01
bit8 = 0b00000001
.mul-exp10std/core/int/mul-exp10: (i : int, n : int) -> int(expexp: int
) // Raise an integer `i` to the power of `exp`. pub fip extern powstd/core/int/pow: (i : int, exp : int) -> int( ii: int : intstd/core/types/int: V, expexp: int : intstd/core/types/int: V ) : intstd/core/types/int: V c "kk_integer_pow" cs "Primitive.IntPow" js "$std_core_types._int_pow" // Raise an integer `i` to the power of `exp`. pub fip fun (^)std/core/int/(^): (i : int, exp : int) -> int(ii: int : intstd/core/types/int: V, expexp: int : intstd/core/types/int: V )result: -> total int : intstd/core/types/int: V powstd/core/int/pow: (i : int, exp : int) -> int(ii: int,expexp: int) // Calculate ``2^exp``. pub fip fun exp2std/core/int/exp2: (exp : int) -> int( expexp: int : intstd/core/types/int: V )result: -> total int : intstd/core/types/int: V powstd/core/int/pow: (i : int, exp : int) -> int(2literal: int
dec = 2
hex8 = 0x02
bit8 = 0b00000010
,expexp: int
) // Return the number of ending `0` digits of `i`. Return `0` when `i==0`. pub fip extern is-exp10std/core/int/is-exp10: (i : int) -> int( ii: int : intstd/core/types/int: V ) : intstd/core/types/int: V c "kk_integer_ctz" cs "Primitive.IntCountPow10" js "$std_core_types._int_count_pow10" // Return the number of decimal digits of `i`. Return `0` when `i==0`. pub fip extern count-digitsstd/core/int/count-digits: (i : int) -> int( ii: int : intstd/core/types/int: V ) : intstd/core/types/int: V c "kk_integer_count_digits" cs "Primitive.IntCountDigits" js "$std_core_types._int_count_digits" pub fip extern mul-exp10std/core/int/mul-exp10: (i : int, n : int) -> int( ii: int : intstd/core/types/int: V, nn: int : intstd/core/types/int: V ) : intstd/core/types/int: V c "kk_integer_mul_pow10" cs "Primitive.IntMulPow10" js "$std_core_types._int_mul_pow10" pub fip extern cdiv-exp10std/core/int/cdiv-exp10: (i : int, n : int) -> int( ii: int : intstd/core/types/int: V, nn: int : intstd/core/types/int: V ) : intstd/core/types/int: V c "kk_integer_cdiv_pow10" cs "Primitive.IntCDivPow10" js "$std_core_types._int_cdiv_pow10" pub fun cdivmod-exp10std/core/int/cdivmod-exp10: (i : int, n : int) -> (int, int)( ii: int : intstd/core/types/int: V, nn: int : intstd/core/types/int: V )result: -> total (int, int) : (std/core/types/tuple2: (V, V) -> Vintstd/core/types/int: V,intstd/core/types/int: V) if nn: int <=std/core/int/(<=): (x : int, y : int) -> bool 0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
returnreturn: (int, int) (std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b)ii: int,0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
)std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b) val cqcq: int = ii: int.cdiv-exp10std/core/int/cdiv-exp10: (i : int, n : int) -> int(nn: int) val crcr: int = ii: int -std/core/int/(-): (x : int, y : int) -> int cqcq: int.mul-exp10std/core/int/mul-exp10: (i : int, n : int) -> int(nn: int) (std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b)cqcq: int,crcr: int
)std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b) pub fun divmod-exp10std/core/int/divmod-exp10: (i : int, n : int) -> (int, int)( ii: int : intstd/core/types/int: V, nn: int : intstd/core/types/int: V )result: -> total (int, int) : (std/core/types/tuple2: (V, V) -> Vintstd/core/types/int: V,intstd/core/types/int: V) val (std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b)cqcq: int,crcr: int)std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b) = cdivmod-exp10std/core/int/cdivmod-exp10: (i : int, n : int) -> (int, int)(ii: int,nn: int) if !std/core/types/bool/(!): (b : bool) -> boolcrcr: int.is-negstd/core/int/is-neg: (i : int) -> bool then (std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b)cqcq: int,crcr: int)std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b) else (std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b)cqcq: int.decstd/core/int/dec: (i : int) -> int, crcr: int +std/core/int/(+): (x : int, y : int) -> int exp10std/core/int/exp10: (exp : int) -> int(nn: int))std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b) // Is this an even integer? pub fip fun is-evenstd/core/int/is-even: (i : int) -> bool(ii: int:intstd/core/types/int: V)result: -> total bool : boolstd/core/types/bool: V !std/core/types/bool/(!): (b : bool) -> boolis-oddstd/core/int/is-odd: (i : int) -> bool(ii: int) // Is the integer positive (strictly greater than zero) pub fip fun is-posstd/core/int/is-pos: (i : int) -> bool(ii: int : intstd/core/types/int: V )result: -> total bool : boolstd/core/types/bool: V ii: int >std/core/int/(>): (x : int, y : int) -> bool 0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
// Is the integer negative (strictly smaller than zero) pub fip fun is-negstd/core/int/is-neg: (i : int) -> bool(ii: int : intstd/core/types/int: V )result: -> total bool : boolstd/core/types/bool: V ii: int <std/core/int/(<): (x : int, y : int) -> bool 0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
// Compare an integer `i` with zero pub inline fip fun signstd/core/int/sign: (i : int) -> order( ^ii: int : intstd/core/types/int: V )result: -> total order : orderstd/core/types/order: V cmpstd/core/int/cmp: (x : int, y : int) -> order(ii: int,0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
) // c inline "kk_int_as_order(kk_integer_signum_borrow(#1,kk_context()),kk_context())" // cs "Primitive.IntSign" // js "$std_core_types._int_sign" // Return the minimum of two integers pub fip fun minstd/core/int/min: (i : int, j : int) -> int( ii: int : intstd/core/types/int: V, jj: int : intstd/core/types/int: V )result: -> total int : intstd/core/types/int: V if ii: int <=std/core/int/(<=): (x : int, y : int) -> bool jj: int then ii: int else jj: int // Return the maximum of two integers pub fip fun maxstd/core/int/max: (i : int, j : int) -> int( ii: int : intstd/core/types/int: V, jj: int : intstd/core/types/int: V )result: -> total int : intstd/core/types/int: V if ii: int >=std/core/int/(>=): (x : int, y : int) -> bool jj: int then ii: int else jj: int // Transform an integer to a maybe type, using `Nothing` for `0` pub fun maybestd/core/int/maybe: (i : int) -> maybe<int>( ii: int : intstd/core/types/int: V )result: -> total maybe<int> : maybestd/core/types/maybe: V -> V<intstd/core/types/int: V> if ii: int==std/core/int/(==): (x : int, y : int) -> bool0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
then Nothingstd/core/types/Nothing: forall<a> maybe<a> else Juststd/core/types/Just: forall<a> (value : a) -> maybe<a>(ii: int
) // Convert an `:int` to a string pub extern showstd/core/int/show: (i : int) -> string( ii: int : intstd/core/types/int: V ) : stringstd/core/types/string: V c "kk_integer_to_string" cs inline "#1.ToString()" js inline "#1.toString()" // Convert an int to a boolean, using `False` for 0 and `True` otherwise. pub fun boolstd/core/int/bool: (i : int) -> bool( ii: int : intstd/core/types/int: V )result: -> total bool : boolstd/core/types/bool: V ii: int !=std/core/int/(!=): (x : int, y : int) -> bool 0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
// Convert a `:maybe<int>` to an `:int` using zero for `Nothing` pub fip fun mbintstd/core/int/mbint: (m : maybe<int>) -> int( mm: maybe<int> : maybestd/core/types/maybe: V -> V<intstd/core/types/int: V> )result: -> total int : intstd/core/types/int: V match mm: maybe<int> Nothingstd/core/types/Nothing: forall<a> maybe<a> -> 0literal: int
dec = 0
hex8 = 0x00
bit8 = 0b00000000
Juststd/core/types/Just: forall<a> (value : a) -> maybe<a>(ii: int) ->
ii: int // ---------------------------------------------------------------------------- // Parse numbers // ---------------------------------------------------------------------------- // Parse an integer using `parseInt`. If an illegal digit character is encountered the // `default` value is returned. An empty string will also result in `default`. // pub fun parse-int-default( s : string, def : int = 0, hex : bool = False ) : int // if s.is-empty then def else s.parse-int(hex).default(def) // Parse an integer. // If an illegal digit character is encountered `Nothing` is returned. // An empty string, or a string starting with white space will result in `Nothing` // A string can start with a `-` sign for negative numbers, // and with `0x` or `0X` for hexadecimal numbers (in which case the `hex` parameter is ignored). pub fun parse-intstd/core/int/parse-int: (s : string, hex : ? bool) -> maybe<int>( ss: string : stringstd/core/types/string: V, hexhex: ? bool : boolstd/core/types/bool: V = Falsestd/core/types/False: bool)result: -> total maybe<int> : maybestd/core/types/maybe: V -> V<intstd/core/types/int: V> ss: string.xparsestd/core/int/xparse: (s : string, hex : bool) -> maybe<int>(hexhex: bool) noinline extern xparsestd/core/int/xparse: (s : string, hex : bool) -> maybe<int>( ss: string : stringstd/core/types/string: V, hexhex: bool : boolstd/core/types/bool: V ) : maybestd/core/types/maybe: V -> V<intstd/core/types/int: V> c "kk_integer_xparse" cs "Primitive.IntParse" js "_int_parse" // ---------------------------------------------------------------------------- // int8, int16, intptr_t // ---------------------------------------------------------------------------- // clamp an `:int` to fit in an `:int8`. pub fip extern int8std/core/int/int8: (i : int) -> int8( ii: int : intstd/core/types/int: V) : int8std/core/types/int8: V c "kk_integer_clamp_int8" cs "Primitive.IntToInt8" js "$std_core_types._int_clamp8" // Convert an `:int8` to an `:int`. pub inline fip extern int8/intstd/core/int/int8/int: (i : int8) -> int( i : int8std/core/types/int8: V ) : intstd/core/types/int: V c "kk_integer_from_int8" cs inline "(new BigInteger(#1))" js "$std_core_types._int_from_int32" // clamp an `:int` to fit in an `:int8` but interpret the `:int` as an unsigned 8-bit value, // and clamp between 0 and 255. pub fip extern uint8std/core/int/uint8: (i : int) -> int8( ii: int : intstd/core/types/int: V) : int8std/core/types/int8: V c "kk_integer_clamp_byte" cs "Primitive.IntToUInt8" js "$std_core_types._int_clamp_byte" // Convert an `:int8` to an `:int` but interpret the `:int8` as an unsigned 8-bit value between 0 and 255. pub inline fip extern int8/uintstd/core/int/int8/uint: (i : int8) -> int( i : int8std/core/types/int8: V ) : intstd/core/types/int: V c "kk_integer_from_uint8" cs inline "(new BigInteger(#1 >= 0 ? #1 : 256 + #1))" js "$std_core_types._int_from_int32" // clamp an `:int` to fit in an `:int16`. pub fip extern int16std/core/int/int16: (i : int) -> int16( ii: int : intstd/core/types/int: V) : int16std/core/types/int16: V c "kk_integer_clamp_int16" cs "Primitive.IntToInt16" js "$std_core_types._int_clamp16" // Convert an `:int16` to an `:int`. pub inline fip extern int16/intstd/core/int/int16/int: (i : int16) -> int( i : int16std/core/types/int16: V ) : intstd/core/types/int: V c "kk_integer_from_int16" cs inline "(new BigInteger(#1))" js "$std_core_types._int_from_int32" // clamp an `:int` to fit in an `:intptr_t`. pub fip extern intptr_tstd/core/int/intptr_t: (i : int) -> intptr_t( ii: int : intstd/core/types/int: V) : intptr_tstd/core/types/intptr_t: V c "kk_integer_clamp_intptr_t" cs "Primitive.IntToInt64" js "$std_core_types._int_clamp64" // Convert an `:intptr_t` to an `:int`. pub inline fip extern intptr_t/intstd/core/int/intptr_t/int: (i : intptr_t) -> int( i : intptr_tstd/core/types/intptr_t: V ) : intstd/core/types/int: V c "kk_integer_from_intptr_t" cs inline "(new BigInteger(#1))" js "$std_core_types._int_from_int64" // Convert an integer to an `:ssize_t`. The number is _clamped_ to the maximal or minimum `:ssize_t` // value if it is outside the range of an `:ssize_t`. // Needed for evidence indices in `module std/core/hnd` pub fip extern ssize_tstd/core/int/ssize_t: (i : int) -> ssize_t( ii: int : intstd/core/types/int: V) : ssize_tstd/core/types/ssize_t: V c "kk_integer_clamp_ssize_t" cs "Primitive.IntToInt32" js "$std_core_types._int_clamp32" // Convert an `:ssize_t` to an `:int`. pub inline fip extern ssize_t/intstd/core/int/ssize_t/int: (i : ssize_t) -> int( i : ssize_tstd/core/types/ssize_t: V ) : intstd/core/types/int: V c "kk_integer_from_ssize_t" cs inline "(new BigInteger(#1))" js "$std_core_types._int_from_int32"