/*
FILE NAME: arithm.c
TITLE: Package for arbitrary precision integer arithmetic
DESCRIPTION: This abstract data implements arbitrary precision
integer and unsigned integer numbers by machine independent
way. The implementation of the package functions are not
sufficiently efficient in order to use for run-time. The
package functions are oriented to implement constant-folding in
compilers. This package is necessary because host machine may
not support such arithmetic for target machine. For example,
VAX does not support does not support more 32-bits integer
numbers arithmetic. The numbers are represented by bytes in
big endian mode, negative integer numbers are represented in
complementary code. All sizes are given in bytes and must be
positive. Results of executions of all functions can coincide
with a operand(s). All functions of addition, subtraction,
multiplication, division, evaluation of remainder, shift,
changing size and transformation of string into number fix
overflow. The overflow is fixed when result can not be
represented by number of given size.
*/
#include "arithm.h"
#include "ammunition_string.h"
/* This variable can have only two values 0 or 1. The value `1'
corresponds to overflow. The variable value are modified by all
functions of addition, subtract, multiplication, division,
evaluation of remainder, shift, changing size and transformation of
string into number fix overflow. */
int ammunition_overflow_bit;
/* The following function adds unsigned integers. The function
returns 1 if unsigned integer overflow is fixed, 0 otherwise.
Result can be placed in any operand. */
int ammunition_add_unsigned_integer_without_overflow_reaction
( int size, const void *op1, const void *op2, void *result )
{
int digit_num;
int carry;
unsigned int sum;
_Pragma( "loopbound min 4 max 4" )
for ( digit_num = size - 1, carry = 0; digit_num >= 0; digit_num-- ) {
sum = ( ( ( unsigned char * ) op1 ) [digit_num]
+ ( ( unsigned char * ) op2 ) [digit_num] + carry );
if ( sum > UCHAR_MAX ) {
sum -= UCHAR_MAX + 1;
carry = 1;
} else
carry = 0;
( ( unsigned char * ) result ) [digit_num] = sum;
}
return carry != 0;
}
/* The following function adds unsigned integers. The function
returns 1 if unsigned integer overflow (the first operand is less
than the second) is fixed, 0 otherwise. Result can be placed in
any operand. */
int ammunition_subtract_unsigned_integer_without_overflow_reaction
( int size, const void *op1, const void *op2, void *result )
{
int digit_num;
int carry;
int subtraction;
_Pragma( "loopbound min 4 max 4" )
for ( digit_num = size - 1, carry = 0; digit_num >= 0; digit_num-- ) {
subtraction = ( ( ( unsigned char * ) op1 ) [digit_num]
- ( ( unsigned char * ) op2 ) [digit_num] - carry );
if ( subtraction < 0 ) {
subtraction += UCHAR_MAX + 1;
carry = 1;
} else
carry = 0;
( ( unsigned char * ) result ) [digit_num] = subtraction;
}
return carry != 0;
}
/* The following function makes complementary code of number. Result
can be placed in operand. */
void ammunition_make_complementary_code
( int size, const void *operand, void *result )
{
int digit_num;
int carry;
int subtraction;
_Pragma( "loopbound min 2 max 6" )
for ( digit_num = size - 1, carry = 0; digit_num >= 0; digit_num-- ) {
subtraction = ( 0 - ( ( unsigned char * ) operand ) [digit_num] - carry );
if ( subtraction != 0 ) {
subtraction += UCHAR_MAX + 1;
carry = 1;
} else
carry = 0;
( ( unsigned char * ) result ) [digit_num] = subtraction;
}
}
/* The following function multiplys unsigned integer by digit (byte
size). The function returns 1 if unsigned integer overflow is
fixed, 0 otherwise. */
int ammunition_multiply_unsigned_integer_by_digit_without_overflow_reaction
( int size, void *operand, unsigned int digit )
{
int digit_num;
unsigned int carry;
unsigned int sum;
_Pragma( "loopbound min 4 max 4" )
for ( digit_num = size - 1, carry = 0; digit_num >= 0; digit_num-- ) {
sum = ( ( ( unsigned char * ) operand ) [digit_num] * digit + carry );
if ( sum ><
|