@head @title Int operations
The functions, types and constants described in this section are useful for dealing with Int objects. Two basic modes of operation are supported:
The first mode is usually sufficient, and when dealing with existing C interfaces, it is usually the only realistic approach. It also makes dealing with integer objects in C code relatively simple. Thus this mode is recommended unless arbitrary precision is specifically required. An overview of using this mode is given below:
This approach usually results in efficient and easy-to-understand code, since the number of API function calls is minimized. A major downside of this approach is the loss of Alore integer semantics, which are replaced with the often less desirable C semantics that include integer truncation and the limited range of integers. @see Operations described in sections @href{Arithmetic operations} and @href{Comparison operations} such as @ref{AAdd}, @ref{AMul} and @ref{AIsEq} can be used with Int objects as well. They are useful especially when dealing with arbitrary-precision integers. @end
The previous operations mostly deal with fixed-size integers. Alore integers have an unbounded size, and the functions described below are useful for dealing efficiently with arbitrary-precision integers.
Alore supports two different memory representations of Int objects. A long integer representation must be used for integers that are larger than the constant A_SHORT_INT_MAX or smaller than A_SHORT_INT_MIN. Other integers are always represented using the fixed-size short integer representation.
A long Int object is composed of "digits", fixed-size binary integers, whose range is from 0 to 2**A_LONG_INT_DIGIT_BITS-1. The digits are numbered starting from 0 (the least significant digit) to n-1 (the most significant digit), where n is the length of the long Int object. The most significant digit must always be non-zero.
The magnitude of a long Int object can be calculated using this formula: @example value = digit[0] * B**0 + digit[1] * B**1 + ... + digit[n - 1] * B**(n - 1) @end
Here B is the base or radix (2**A_LONG_INT_DIGIT_BITS). Note that we use ** to mean exponentiation. Negative long Int objects have a sign flag set, so two's complement representation is not used internally to represent negative long integers, although Alore code generally sees integers following two's complement semantics.
Example: If each digit is 16 bits wide, B is 2**16 or 65536, and the value of each digit must be between 0 and 65535. Then consider a negative long Int object with the following digits, starting from digit 0: 5, 4 and 3. The integer value of this object is -5 - 4 * 65536 - 3 * 65536**2 == -12885164037.
API functions that are useful for dealing with long Int objects are described below. @note It is an error to create a long Int object if it is in the short Int range, but the API does not enforce this constraint. Therefore you have to be very careful or try to use higher-level operations such as @ref{AAdd} or @ref{AIsLt} that work with both short and long forms transparently. @end @fun ABool AIsShortInt(AValue v) @desc Return a boolean indicating whether v is an Int object within the range of a short Int object (i.e. A_SHORT_INT_MIN to A_SHORT_INT_MAX). @end @fun ABool AIsLongInt(AValue v) @desc Return a boolean indicating whether v is an Int object outside the range of a short Int object (i.e. A_SHORT_INT_MIN to A_SHORT_INT_MAX). Note that if v is Int, either AIsShortInt or AIsLongInt is true, but never both. @end @fun AValue AMakeLongInt(AThread *t, int len, ABool isNeg) @desc Create an uninitialized long Int object with len digits (each A_LONG_INT_DIGIT_BITS bits wide), optionally negative. Use ASetLongIntDigit to initialize the contents of the object. After initialization, the most significant digit must not be zero, and the overall value of the object must be outside the short int range. You must fully initialize a long Int object before exposing it to Alore code. @end @fun void ASetLongIntDigit(AValue longInt, int num, ALongIntDigit digitValue) @desc Initialize digit num in a long Int object to the specified value. The long Int object must have been created using AMakeLongInt. The least significant digit is numbered 0. Note that the value argument must refer to a long Int object and num must be in the valid range, since no error checking is performed. After a long Int object has been initialized, its contents must not be modified. @end @fun ABool AIsNegLongInt(AValue longInt) @desc Return a boolean indicating whether a long Int object is negative. Note that the argument must refer to a long Int object, since no error checking is performed. @end @fun int ALongIntLen(AValue longInt) @desc Return the number of digits in a long Int object. Note that the argument must point to a long Int object, since no error checking is performed. @end @fun ALongIntDigit AGetLongIntDigit(AValue longInt, int num) @desc Return the digit num of a long Int object. The least significant digit is numbered 0. Note that the value argument must refer to a long Int object and num must be in the valid range, since no error checking is performed. @end