mirror of
https://github.com/lcn2/calc.git
synced 2025-08-16 01:03:29 +03:00
Updated COPYING file to indicate that these files are now covered under "The Unlicense" (see https://unlicense.org): sha1.c sha1.h cal/dotest.cal cal/screen.cal Updated help/credit to match the above changes to COPYING. Updated CONTRIB-CODE and calc.man to refer to using GitHub pull requests for contributing to calc (instead of using Email). Updated BUGS and calc.man to refer to using GitHub issues for reporting calc bugs (instead of using Email). Updated QUESTIONS and calc.man to refer to using GitHub issues for asking calc questions (instead of using Email). Fixed Makefile.local command example to refer to overriding the Makefile variable DEBUG (instead of CDEBUG). Fixed all make chk ASAN warnings under macOS 13.2.1 when calc is compiled with the following uncommented lines in Makefile.local: DEBUG:= -O0 -g CFLAGS+= -fsanitize=address -fno-omit-frame-pointer -fsanitize=undefined LDFLAGS+= -fsanitize=address -fno-omit-frame-pointer -fsanitize=undefined CALC_ENV+= ASAN_OPTIONS=detect_stack_use_after_return=1 Improved how pointers to functions are declared for the builtins array in func.c to avoid function declarations without a prototype that is now deprecated in C. Improved how pointers to functions are declared for the opcodes array in opcodes.c to avoid function declarations without a prototype Replaced use of egrep with grep -E in Makefiles. Fixed cases where variables were set but not used in symbol.c, calc.c, and the main function in func.c as used by funclist.c. Added rule name to "DO NOT EDIT -- generated by the Makefile" lines in constructed files. Test if <sys/vfs.h> exists and set HAVE_SYS_VFS_H accordingly in have_sys_vfs.h. Added HAVE_SYS_VFS_H to allow one to force this value. Test if <sys/param.h> exists and set HAVE_SYS_PARAM_H accordingly in have_sys_param.h. Added HAVE_SYS_PARAM_H to allow one to force this value. Test if <sys/mount.h> exists and set HAVE_SYS_MOUNT_H accordingly in have_sys_mount.h. Added HAVE_SYS_MOUNT_H to allow one to force this value. Test if the system as the statfs() system call and set HAVE_STATFS accordingly in have_statfs.h. Added HAVE_STATFS to allow one to force this value. The pseudo_seed() function will also try to call statfs() if possible and permitted by the HAVE_STATFS value.
2023 lines
36 KiB
C
2023 lines
36 KiB
C
/*
|
|
* zmath - extended precision integral arithmetic primitives
|
|
*
|
|
* Copyright (C) 1999-2007,2021,2022 David I. Bell and Ernest Bowen
|
|
*
|
|
* Primary author: David I. Bell
|
|
*
|
|
* Calc is open software; you can redistribute it and/or modify it under
|
|
* the terms of the version 2.1 of the GNU Lesser General Public License
|
|
* as published by the Free Software Foundation.
|
|
*
|
|
* Calc 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.
|
|
*
|
|
* A copy of version 2.1 of the GNU Lesser General Public License is
|
|
* distributed with calc under the filename COPYING-LGPL. You should have
|
|
* received a copy with calc; if not, write to Free Software Foundation, Inc.
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
* Under source code control: 1990/02/15 01:48:28
|
|
* File existed as early as: before 1990
|
|
*
|
|
* Share and enjoy! :-) http://www.isthe.com/chongo/tech/comp/calc/
|
|
*/
|
|
|
|
|
|
#include <stdio.h>
|
|
#include "alloc.h"
|
|
#include "zmath.h"
|
|
|
|
|
|
#include "attribute.h"
|
|
#include "banned.h" /* include after system header <> includes */
|
|
|
|
|
|
HALF _zeroval_[] = { 0 };
|
|
ZVALUE _zero_ = { _zeroval_, 1, 0};
|
|
|
|
HALF _oneval_[] = { 1 };
|
|
ZVALUE _one_ = { _oneval_, 1, 0 };
|
|
ZVALUE _neg_one_ = { _oneval_, 1, 1 };
|
|
|
|
HALF _twoval_[] = { 2 };
|
|
ZVALUE _two_ = { _twoval_, 1, 0 };
|
|
|
|
HALF _tenval_[] = { 10 };
|
|
ZVALUE _ten_ = { _tenval_, 1, 0 };
|
|
|
|
HALF _sqbaseval_[] = { 0, 1 };
|
|
ZVALUE _sqbase_ = { _sqbaseval_, 2, 0 };
|
|
|
|
HALF _pow4baseval_[] = { 0, 0, 1 };
|
|
ZVALUE _pow4base_ = { _pow4baseval_, 4, 0 };
|
|
|
|
HALF _pow8baseval_[] = { 0, 0, 0, 0, 1 };
|
|
ZVALUE _pow8base_ = { _pow8baseval_, 4, 0 };
|
|
|
|
/*
|
|
* 2^64 as a ZVALUE
|
|
*/
|
|
#if BASEB == 32
|
|
ZVALUE _b32_ = { _sqbaseval_, 2, 0 };
|
|
ZVALUE _b64_ = { _pow4baseval_, 3, 0 };
|
|
#elif BASEB == 16
|
|
ZVALUE _b32_ = { _pow4baseval_, 3, 0 };
|
|
ZVALUE _b64_ = { _pow8baseval_, 5, 0 };
|
|
#else
|
|
-=@=- BASEB not 16 or 32 -=@=-
|
|
#endif
|
|
|
|
/*
|
|
* ZVALUE - values that should not be freed
|
|
*/
|
|
HALF *half_tbl[] = {
|
|
_zeroval_,
|
|
_oneval_,
|
|
_twoval_,
|
|
_tenval_,
|
|
_sqbaseval_,
|
|
_pow4baseval_,
|
|
_pow8baseval_,
|
|
NULL /* must be last */
|
|
};
|
|
|
|
|
|
/*
|
|
* highhalf[i] - masks off the upper i bits of a HALF
|
|
* rhighhalf[i] - masks off the upper BASEB-i bits of a HALF
|
|
* lowhalf[i] - masks off the lower i bits of a HALF
|
|
* rlowhalf[i] - masks off the lower BASEB-i bits of a HALF
|
|
* bitmask[i] - (1 << i) for 0 <= i <= BASEB*2
|
|
*
|
|
* NOTE: In all cases 0 <= i <= BASEB
|
|
*/
|
|
HALF highhalf[BASEB+1] = {
|
|
#if BASEB == 32
|
|
0x00000000,
|
|
0x80000000, 0xC0000000, 0xE0000000, 0xF0000000,
|
|
0xF8000000, 0xFC000000, 0xFE000000, 0xFF000000,
|
|
0xFF800000, 0xFFC00000, 0xFFE00000, 0xFFF00000,
|
|
0xFFF80000, 0xFFFC0000, 0xFFFE0000, 0xFFFF0000,
|
|
0xFFFF8000, 0xFFFFC000, 0xFFFFE000, 0xFFFFF000,
|
|
0xFFFFF800, 0xFFFFFC00, 0xFFFFFE00, 0xFFFFFF00,
|
|
0xFFFFFF80, 0xFFFFFFC0, 0xFFFFFFE0, 0xFFFFFFF0,
|
|
0xFFFFFFF8, 0xFFFFFFFC, 0xFFFFFFFE, 0xFFFFFFFF
|
|
#elif BASEB == 16
|
|
0x0000,
|
|
0x8000, 0xC000, 0xE000, 0xF000,
|
|
0xF800, 0xFC00, 0xFE00, 0xFF00,
|
|
0xFF80, 0xFFC0, 0xFFE0, 0xFFF0,
|
|
0xFFF8, 0xFFFC, 0xFFFE, 0xFFFF
|
|
#else
|
|
-=@=- BASEB not 16 or 32 -=@=-
|
|
#endif
|
|
};
|
|
HALF rhighhalf[BASEB+1] = {
|
|
#if BASEB == 32
|
|
0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFC, 0xFFFFFFF8,
|
|
0xFFFFFFF0, 0xFFFFFFE0, 0xFFFFFFC0, 0xFFFFFF80,
|
|
0xFFFFFF00, 0xFFFFFE00, 0xFFFFFC00, 0xFFFFF800,
|
|
0xFFFFF000, 0xFFFFE000, 0xFFFFC000, 0xFFFF8000,
|
|
0xFFFF0000, 0xFFFE0000, 0xFFFC0000, 0xFFF80000,
|
|
0xFFF00000, 0xFFE00000, 0xFFC00000, 0xFF800000,
|
|
0xFF000000, 0xFE000000, 0xFC000000, 0xF8000000,
|
|
0xF0000000, 0xE0000000, 0xC0000000, 0x80000000,
|
|
0x00000000
|
|
#elif BASEB == 16
|
|
0xFFFF, 0xFFFE, 0xFFFC, 0xFFF8,
|
|
0xFFF0, 0xFFE0, 0xFFC0, 0xFF80,
|
|
0xFF00, 0xFE00, 0xFC00, 0xF800,
|
|
0xF000, 0xE000, 0xC000, 0x8000,
|
|
0x0000
|
|
#else
|
|
-=@=- BASEB not 16 or 32 -=@=-
|
|
#endif
|
|
};
|
|
HALF lowhalf[BASEB+1] = {
|
|
0x0,
|
|
0x1, 0x3, 0x7, 0xF,
|
|
0x1F, 0x3F, 0x7F, 0xFF,
|
|
0x1FF, 0x3FF, 0x7FF, 0xFFF,
|
|
0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF
|
|
#if BASEB == 32
|
|
,0x1FFFF, 0x3FFFF, 0x7FFFF, 0xFFFFF,
|
|
0x1FFFFF, 0x3FFFFF, 0x7FFFFF, 0xFFFFFF,
|
|
0x1FFFFFF, 0x3FFFFFF, 0x7FFFFFF, 0xFFFFFFF,
|
|
0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF
|
|
#endif
|
|
};
|
|
HALF rlowhalf[BASEB+1] = {
|
|
#if BASEB == 32
|
|
0xFFFFFFFF, 0x7FFFFFFF, 0x3FFFFFFF, 0x1FFFFFFF,
|
|
0xFFFFFFF, 0x7FFFFFF, 0x3FFFFFF, 0x1FFFFFF,
|
|
0xFFFFFF, 0x7FFFFF, 0x3FFFFF, 0x1FFFFF,
|
|
0xFFFFF, 0x7FFFF, 0x3FFFF, 0x1FFFF,
|
|
#endif
|
|
0xFFFF, 0x7FFF, 0x3FFF, 0x1FFF,
|
|
0xFFF, 0x7FF, 0x3FF, 0x1FF,
|
|
0xFF, 0x7F, 0x3F, 0x1F,
|
|
0xF, 0x7, 0x3, 0x1,
|
|
0x0
|
|
};
|
|
HALF bitmask[(2*BASEB)+1] = {
|
|
#if BASEB == 32
|
|
0x00000001, 0x00000002, 0x00000004, 0x00000008,
|
|
0x00000010, 0x00000020, 0x00000040, 0x00000080,
|
|
0x00000100, 0x00000200, 0x00000400, 0x00000800,
|
|
0x00001000, 0x00002000, 0x00004000, 0x00008000,
|
|
0x00010000, 0x00020000, 0x00040000, 0x00080000,
|
|
0x00100000, 0x00200000, 0x00400000, 0x00800000,
|
|
0x01000000, 0x02000000, 0x04000000, 0x08000000,
|
|
0x10000000, 0x20000000, 0x40000000, 0x80000000,
|
|
0x00000001, 0x00000002, 0x00000004, 0x00000008,
|
|
0x00000010, 0x00000020, 0x00000040, 0x00000080,
|
|
0x00000100, 0x00000200, 0x00000400, 0x00000800,
|
|
0x00001000, 0x00002000, 0x00004000, 0x00008000,
|
|
0x00010000, 0x00020000, 0x00040000, 0x00080000,
|
|
0x00100000, 0x00200000, 0x00400000, 0x00800000,
|
|
0x01000000, 0x02000000, 0x04000000, 0x08000000,
|
|
0x10000000, 0x20000000, 0x40000000, 0x80000000,
|
|
0x00000001
|
|
#elif BASEB == 16
|
|
0x0001, 0x0002, 0x0004, 0x0008,
|
|
0x0010, 0x0020, 0x0040, 0x0080,
|
|
0x0100, 0x0200, 0x0400, 0x0800,
|
|
0x1000, 0x2000, 0x4000, 0x8000,
|
|
0x0001, 0x0002, 0x0004, 0x0008,
|
|
0x0010, 0x0020, 0x0040, 0x0080,
|
|
0x0100, 0x0200, 0x0400, 0x0800,
|
|
0x1000, 0x2000, 0x4000, 0x8000,
|
|
0x0001
|
|
#else
|
|
-=@=- BASEB not 16 or 32 -=@=-
|
|
#endif
|
|
}; /* actual rotation thru 8 cycles */
|
|
|
|
BOOL _math_abort_; /* nonzero to abort calculations */
|
|
|
|
|
|
/*
|
|
* popcnt - popcnt[x] number of 1 bits in 0 <= x < 256
|
|
*/
|
|
char popcnt[256] = {
|
|
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
|
|
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
|
|
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
|
|
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
|
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
|
|
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
|
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
|
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
|
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
|
|
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
|
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
|
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
|
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
|
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
|
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
|
4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
|
|
};
|
|
|
|
|
|
|
|
#ifdef ALLOCTEST
|
|
STATIC long nalloc = 0;
|
|
STATIC long nfree = 0;
|
|
#endif
|
|
|
|
|
|
HALF *
|
|
alloc(LEN len)
|
|
{
|
|
HALF *hp;
|
|
|
|
if (_math_abort_) {
|
|
math_error("Calculation aborted");
|
|
not_reached();
|
|
}
|
|
hp = (HALF *) malloc((len+1) * sizeof(HALF));
|
|
if (hp == 0) {
|
|
math_error("Not enough memory");
|
|
not_reached();
|
|
}
|
|
#ifdef ALLOCTEST
|
|
++nalloc;
|
|
#endif
|
|
return hp;
|
|
}
|
|
|
|
|
|
/*
|
|
* is_const - determine if a HALF array is an pre-allocated array
|
|
*
|
|
* given:
|
|
* h pointer to the beginning of the HALF array
|
|
*
|
|
* returns:
|
|
* TRUE - h is found in the half_tbl array
|
|
* FALSE - is is not found in the half_tbl array
|
|
*/
|
|
int
|
|
is_const(HALF* h)
|
|
{
|
|
HALF **h_p; /* half_tbl array pointer */
|
|
|
|
/* search the half_tbl for h */
|
|
for (h_p = &half_tbl[0]; *h_p != NULL; ++h_p) {
|
|
if (h == *h_p) {
|
|
return TRUE; /* found in the half_tbl array */
|
|
}
|
|
}
|
|
|
|
/* not found in the half_tbl array */
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
#ifdef ALLOCTEST
|
|
void
|
|
freeh(HALF *h)
|
|
{
|
|
if (!is_const(h)) {
|
|
free(h);
|
|
++nfree;
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
allocStat(void)
|
|
{
|
|
fprintf(stderr, "nalloc: %ld nfree: %ld kept: %ld\n",
|
|
nalloc, nfree, nalloc - nfree);
|
|
}
|
|
#endif
|
|
|
|
|
|
/*
|
|
* Convert a normal integer to a number.
|
|
*/
|
|
void
|
|
itoz(long i, ZVALUE *res)
|
|
{
|
|
long diddle, len;
|
|
|
|
res->len = 1;
|
|
res->sign = 0;
|
|
diddle = 0;
|
|
if (i == 0) {
|
|
res->v = _zeroval_;
|
|
return;
|
|
}
|
|
if (i < 0) {
|
|
res->sign = 1;
|
|
i = -i;
|
|
if (i < 0) { /* fix most negative number */
|
|
diddle = 1;
|
|
i--;
|
|
}
|
|
}
|
|
if (i == 1) {
|
|
res->v = _oneval_;
|
|
return;
|
|
}
|
|
len = 1 + (((FULL) i) >= BASE);
|
|
res->len = (LEN)len;
|
|
res->v = alloc((LEN)len);
|
|
res->v[0] = (HALF) (i + diddle);
|
|
if (len == 2)
|
|
res->v[1] = (HALF) (i / BASE);
|
|
}
|
|
|
|
|
|
/*
|
|
* Convert a number to a normal integer, as far as possible.
|
|
* If the number is out of range, the largest number is returned.
|
|
*/
|
|
long
|
|
ztoi(ZVALUE z)
|
|
{
|
|
long i;
|
|
|
|
if (zgtmaxlong(z)) {
|
|
i = MAXLONG;
|
|
return (z.sign ? -i : i);
|
|
}
|
|
i = ztolong(z);
|
|
return (z.sign ? -i : i);
|
|
}
|
|
|
|
|
|
/*
|
|
* Convert a normal unsigned integer to a number.
|
|
*/
|
|
void
|
|
utoz(FULL i, ZVALUE *res)
|
|
{
|
|
long len;
|
|
|
|
res->len = 1;
|
|
res->sign = 0;
|
|
if (i == 0) {
|
|
res->v = _zeroval_;
|
|
return;
|
|
}
|
|
if (i == 1) {
|
|
res->v = _oneval_;
|
|
return;
|
|
}
|
|
len = 1 + (((FULL) i) >= BASE);
|
|
res->len = (LEN)len;
|
|
res->v = alloc((LEN)len);
|
|
res->v[0] = (HALF)i;
|
|
if (len == 2)
|
|
res->v[1] = (HALF) (i / BASE);
|
|
}
|
|
|
|
|
|
/*
|
|
* Convert a normal signed integer to a number.
|
|
*/
|
|
void
|
|
stoz(SFULL i, ZVALUE *res)
|
|
{
|
|
long diddle, len;
|
|
|
|
res->len = 1;
|
|
res->sign = 0;
|
|
diddle = 0;
|
|
if (i == 0) {
|
|
res->v = _zeroval_;
|
|
return;
|
|
}
|
|
if (i < 0) {
|
|
res->sign = 1;
|
|
i = -i;
|
|
if (i < 0) { /* fix most negative number */
|
|
diddle = 1;
|
|
i--;
|
|
}
|
|
}
|
|
if (i == 1) {
|
|
res->v = _oneval_;
|
|
return;
|
|
}
|
|
len = 1 + (((FULL) i) >= BASE);
|
|
res->len = (LEN)len;
|
|
res->v = alloc((LEN)len);
|
|
res->v[0] = (HALF) (i + diddle);
|
|
if (len == 2)
|
|
res->v[1] = (HALF) (i / BASE);
|
|
}
|
|
|
|
|
|
/*
|
|
* Convert a number to a unsigned normal integer, as far as possible.
|
|
* If the number is out of range, the largest number is returned.
|
|
* The absolute value of z is converted.
|
|
*/
|
|
FULL
|
|
ztou(ZVALUE z)
|
|
{
|
|
if (z.len > 2) {
|
|
return MAXUFULL;
|
|
}
|
|
return ztofull(z);
|
|
}
|
|
|
|
|
|
/*
|
|
* Convert a number to a signed normal integer, as far as possible.
|
|
*
|
|
* If the number is too large to fit into an integer, than the largest
|
|
* positive or largest negative integer is returned depending on the sign.
|
|
*/
|
|
SFULL
|
|
ztos(ZVALUE z)
|
|
{
|
|
FULL val; /* absolute value of the return value */
|
|
|
|
/* negative value processing */
|
|
if (z.sign) {
|
|
if (z.len > 2) {
|
|
return MINSFULL;
|
|
}
|
|
val = ztofull(z);
|
|
if (val > TOPFULL) {
|
|
return MINSFULL;
|
|
}
|
|
return (SFULL)(-val);
|
|
}
|
|
|
|
/* positive value processing */
|
|
if (z.len > 2) {
|
|
return (SFULL)MAXFULL;
|
|
}
|
|
val = ztofull(z);
|
|
if (val > MAXFULL) {
|
|
return (SFULL)MAXFULL;
|
|
}
|
|
return (SFULL)val;
|
|
}
|
|
|
|
|
|
/*
|
|
* Make a copy of an integer value
|
|
*/
|
|
void
|
|
zcopy(ZVALUE z, ZVALUE *res)
|
|
{
|
|
res->sign = z.sign;
|
|
res->len = z.len;
|
|
if (zisabsleone(z)) { /* zero or plus or minus one are easy */
|
|
res->v = (z.v[0] ? _oneval_ : _zeroval_);
|
|
return;
|
|
}
|
|
res->v = alloc(z.len);
|
|
zcopyval(z, *res);
|
|
}
|
|
|
|
|
|
/*
|
|
* Add together two integers.
|
|
*/
|
|
void
|
|
zadd(ZVALUE z1, ZVALUE z2, ZVALUE *res)
|
|
{
|
|
ZVALUE dest;
|
|
HALF *p1, *p2, *pd;
|
|
long len;
|
|
FULL carry;
|
|
SIUNION sival;
|
|
|
|
if (z1.sign && !z2.sign) {
|
|
z1.sign = 0;
|
|
zsub(z2, z1, res);
|
|
return;
|
|
}
|
|
if (z2.sign && !z1.sign) {
|
|
z2.sign = 0;
|
|
zsub(z1, z2, res);
|
|
return;
|
|
}
|
|
if (z2.len > z1.len) {
|
|
pd = z1.v; z1.v = z2.v; z2.v = pd;
|
|
len = z1.len; z1.len = z2.len; z2.len = (LEN)len;
|
|
}
|
|
dest.len = z1.len + 1;
|
|
dest.v = alloc(dest.len);
|
|
dest.sign = z1.sign;
|
|
carry = 0;
|
|
pd = dest.v;
|
|
p1 = z1.v;
|
|
p2 = z2.v;
|
|
len = z2.len;
|
|
while (len--) {
|
|
sival.ivalue = ((FULL) *p1++) + ((FULL) *p2++) + carry;
|
|
/* ignore Saber-C warning #112 - get ushort from uint */
|
|
/* OK to ignore on name zadd`sival */
|
|
*pd++ = sival.silow;
|
|
carry = sival.sihigh;
|
|
}
|
|
len = z1.len - z2.len;
|
|
while (len--) {
|
|
sival.ivalue = ((FULL) *p1++) + carry;
|
|
*pd++ = sival.silow;
|
|
carry = sival.sihigh;
|
|
}
|
|
*pd = (HALF)carry;
|
|
zquicktrim(dest);
|
|
*res = dest;
|
|
}
|
|
|
|
|
|
/*
|
|
* Subtract two integers.
|
|
*/
|
|
void
|
|
zsub(ZVALUE z1, ZVALUE z2, ZVALUE *res)
|
|
{
|
|
register HALF *h1, *h2, *hd;
|
|
long len1, len2;
|
|
FULL carry;
|
|
SIUNION sival;
|
|
ZVALUE dest;
|
|
|
|
if (z1.sign != z2.sign) {
|
|
z2.sign = z1.sign;
|
|
zadd(z1, z2, res);
|
|
return;
|
|
}
|
|
len1 = z1.len;
|
|
len2 = z2.len;
|
|
if (len1 == len2) {
|
|
h1 = z1.v + len1;
|
|
h2 = z2.v + len2;
|
|
while ((len1 > 0) && ((FULL)*--h1 == (FULL)*--h2)) {
|
|
len1--;
|
|
}
|
|
if (len1 == 0) {
|
|
*res = _zero_;
|
|
return;
|
|
}
|
|
len2 = len1;
|
|
carry = ((FULL)*h1 < (FULL)*h2);
|
|
} else {
|
|
carry = (len1 < len2);
|
|
}
|
|
dest.sign = z1.sign;
|
|
h1 = z1.v;
|
|
h2 = z2.v;
|
|
if (carry) {
|
|
carry = len1;
|
|
len1 = len2;
|
|
len2 = (long)carry;
|
|
h1 = z2.v;
|
|
h2 = z1.v;
|
|
dest.sign = !dest.sign;
|
|
}
|
|
hd = alloc((LEN)len1);
|
|
dest.v = hd;
|
|
dest.len = (LEN)len1;
|
|
len1 -= len2;
|
|
carry = 0;
|
|
while (--len2 >= 0) {
|
|
/* ignore Saber-C warning #112 - get ushort from uint */
|
|
/* OK to ignore on name zsub`sival */
|
|
sival.ivalue = (BASE1 - ((FULL) *h1++)) + *h2++ + carry;
|
|
*hd++ = (HALF)(BASE1 - sival.silow);
|
|
carry = sival.sihigh;
|
|
}
|
|
while (--len1 >= 0) {
|
|
sival.ivalue = (BASE1 - ((FULL) *h1++)) + carry;
|
|
*hd++ = (HALF)(BASE1 - sival.silow);
|
|
carry = sival.sihigh;
|
|
}
|
|
if (hd[-1] == 0)
|
|
ztrim(&dest);
|
|
*res = dest;
|
|
}
|
|
|
|
|
|
/*
|
|
* Multiply an integer by a small number.
|
|
*/
|
|
void
|
|
zmuli(ZVALUE z, long n, ZVALUE *res)
|
|
{
|
|
register HALF *h1, *sd;
|
|
FULL low;
|
|
FULL high;
|
|
FULL carry;
|
|
long len;
|
|
SIUNION sival;
|
|
ZVALUE dest;
|
|
|
|
if ((n == 0) || ziszero(z)) {
|
|
*res = _zero_;
|
|
return;
|
|
}
|
|
if (n < 0) {
|
|
n = -n;
|
|
z.sign = !z.sign;
|
|
}
|
|
if (n == 1) {
|
|
zcopy(z, res);
|
|
return;
|
|
}
|
|
#if LONG_BITS > BASEB
|
|
low = ((FULL) n) & BASE1;
|
|
high = ((FULL) n) >> BASEB;
|
|
#else
|
|
low = (FULL)n;
|
|
high = 0;
|
|
#endif
|
|
dest.len = z.len + 2;
|
|
dest.v = alloc(dest.len);
|
|
dest.sign = z.sign;
|
|
/*
|
|
* Multiply by the low digit.
|
|
*/
|
|
h1 = z.v;
|
|
sd = dest.v;
|
|
len = z.len;
|
|
carry = 0;
|
|
while (len--) {
|
|
/* ignore Saber-C warning #112 - get ushort from uint */
|
|
/* OK to ignore on name zmuli`sival */
|
|
sival.ivalue = ((FULL) *h1++) * low + carry;
|
|
*sd++ = sival.silow;
|
|
carry = sival.sihigh;
|
|
}
|
|
*sd = (HALF)carry;
|
|
/*
|
|
* If there was only one digit, then we are all done except
|
|
* for trimming the number if there was no last carry.
|
|
*/
|
|
if (high == 0) {
|
|
dest.len--;
|
|
if (carry == 0)
|
|
dest.len--;
|
|
*res = dest;
|
|
return;
|
|
}
|
|
/*
|
|
* Need to multiply by the high digit and add it into the
|
|
* previous value. Clear the final word of rubbish first.
|
|
*/
|
|
*(++sd) = 0;
|
|
h1 = z.v;
|
|
sd = dest.v + 1;
|
|
len = z.len;
|
|
carry = 0;
|
|
while (len--) {
|
|
sival.ivalue = ((FULL) *h1++) * high + ((FULL) *sd) + carry;
|
|
*sd++ = sival.silow;
|
|
carry = sival.sihigh;
|
|
}
|
|
*sd = (HALF)carry;
|
|
zquicktrim(dest);
|
|
*res = dest;
|
|
}
|
|
|
|
|
|
/*
|
|
* Divide two numbers by their greatest common divisor.
|
|
* This is useful for reducing the numerator and denominator of
|
|
* a fraction to its lowest terms.
|
|
*/
|
|
void
|
|
zreduce(ZVALUE z1, ZVALUE z2, ZVALUE *z1res, ZVALUE *z2res)
|
|
{
|
|
ZVALUE tmp;
|
|
|
|
if (zisabsleone(z1) || zisabsleone(z2))
|
|
tmp = _one_;
|
|
else
|
|
zgcd(z1, z2, &tmp);
|
|
if (zisunit(tmp)) {
|
|
zcopy(z1, z1res);
|
|
zcopy(z2, z2res);
|
|
} else {
|
|
zequo(z1, tmp, z1res);
|
|
zequo(z2, tmp, z2res);
|
|
}
|
|
zfree(tmp);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* Compute the quotient and remainder for division of an integer by an
|
|
* integer, rounding criteria determined by rnd. Returns the sign of
|
|
* the remainder.
|
|
*/
|
|
long
|
|
zdiv(ZVALUE z1, ZVALUE z2, ZVALUE *quo, ZVALUE *rem, long rnd)
|
|
{
|
|
register HALF *a, *b;
|
|
HALF s, u;
|
|
HALF *A, *B, *a1, *b0;
|
|
FULL f, g, h, x;
|
|
BOOL adjust, onebit;
|
|
LEN m, n, len, i, p, j1, j2, k;
|
|
long t, val;
|
|
|
|
if (ziszero(z2)) {
|
|
math_error("Division by zero in zdiv");
|
|
not_reached();
|
|
}
|
|
m = z1.len;
|
|
n = z2.len;
|
|
B = z2.v;
|
|
s = 0;
|
|
if (m < n) {
|
|
A = alloc(n + 1);
|
|
memcpy(A, z1.v, m * sizeof(HALF));
|
|
for (i = m; i <= n; i++)
|
|
A[i] = 0;
|
|
a1 = A + n;
|
|
len = 1;
|
|
goto done;
|
|
}
|
|
A = alloc(m + 2);
|
|
memcpy(A, z1.v, m * sizeof(HALF));
|
|
A[m] = 0;
|
|
A[m + 1] = 0;
|
|
len = m - n + 1; /* quotient length will be len or len +/- 1 */
|
|
a1 = A + n; /* start of digits for quotient */
|
|
b0 = B;
|
|
p = n;
|
|
while (!*b0) { /* b0: working start for divisor */
|
|
++b0;
|
|
--p;
|
|
}
|
|
if (p == 1) {
|
|
u = *b0;
|
|
if (u == 1) {
|
|
for (; m >= n; m--)
|
|
A[m] = A[m - 1];
|
|
A[m] = 0;
|
|
goto done;
|
|
}
|
|
f = 0;
|
|
a = A + m;
|
|
i = len;
|
|
while (i--) {
|
|
f = f << BASEB | *--a;
|
|
a[1] = (HALF)(f / u);
|
|
f = f % u;
|
|
}
|
|
*a = (HALF)f;
|
|
m = n;
|
|
goto done;
|
|
}
|
|
f = B[n - 1];
|
|
k = 1;
|
|
while (f >>= 1)
|
|
k++; /* k: number of bits in top divisor digit */
|
|
j1 = BASEB - k;
|
|
j2 = BASEB + j1;
|
|
h = j1 ? ((FULL) B[n - 1] << j1 | B[n - 2] >> k) : B[n-1];
|
|
onebit = (BOOL)((B[n - 2] >> (k - 1)) & 1);
|
|
m++;
|
|
while (m > n) {
|
|
m--;
|
|
f = (FULL) A[m] << j2 | (FULL) A[m - 1] << j1;
|
|
if (j1) f |= A[m - 2] >> k;
|
|
if (s) f = ~f;
|
|
x = f / h;
|
|
if (x) {
|
|
if (onebit && x > TOPHALF + f % h)
|
|
x--;
|
|
a = A + m - p;
|
|
b = b0;
|
|
u = 0;
|
|
i = p;
|
|
if (s) {
|
|
while (i--) {
|
|
f = (FULL) *a + u + x * *b++;
|
|
*a++ = (HALF) f;
|
|
u = (HALF) (f >> BASEB);
|
|
}
|
|
s = *a + u;
|
|
A[m] = (HALF) (~x + !s);
|
|
} else {
|
|
while (i--) {
|
|
f = (FULL) *a - u - x * *b++;
|
|
*a++ = (HALF) f;
|
|
u = -(HALF)(f >> BASEB);
|
|
}
|
|
s = *a - u;
|
|
A[m] = (HALF)(x + s);
|
|
}
|
|
}
|
|
else
|
|
A[m] = s;
|
|
}
|
|
done: while (m > 0 && A[m - 1] == 0)
|
|
m--;
|
|
if (m == 0 && s == 0) {
|
|
*rem = _zero_;
|
|
val = 0;
|
|
if (a1[len - 1] == 0)
|
|
len--;
|
|
if (len == 0) {
|
|
*quo = _zero_;
|
|
} else {
|
|
quo->len = len;
|
|
quo->v = alloc(len);
|
|
memcpy(quo->v, a1, len * sizeof(HALF));
|
|
quo->sign = z1.sign ^ z2.sign;
|
|
}
|
|
freeh(A);
|
|
return val;
|
|
}
|
|
if (rnd & 8)
|
|
adjust = (((*a1 ^ rnd) & 1) ? TRUE : FALSE);
|
|
else
|
|
adjust = (((rnd & 1) ^ z1.sign ^ z2.sign) ? TRUE : FALSE);
|
|
if (rnd & 2)
|
|
adjust ^= z1.sign ^ z2.sign;
|
|
if (rnd & 4)
|
|
adjust ^= z2.sign;
|
|
if (rnd & 16) { /* round-off case */
|
|
a = A + n;
|
|
b = B + n;
|
|
i = n + 1;
|
|
f = g = 0;
|
|
t = -1;
|
|
if (s) {
|
|
while (--i > 0) {
|
|
g = (FULL) *--a + (*--b >> 1 | f);
|
|
f = *b & 1 ? TOPHALF : 0;
|
|
if (g != BASE1)
|
|
break;
|
|
}
|
|
if (g == BASE && f == 0) {
|
|
while ((--i > 0) && ((*--a | *--b) == 0));
|
|
t = (i > 0);
|
|
} else if (g >= BASE) {
|
|
t = 1;
|
|
}
|
|
} else {
|
|
while (--i > 0) {
|
|
g = (FULL) *--a - (*--b >> 1 | f);
|
|
f = *b & 1 ? TOPHALF : 0;
|
|
if (g != 0)
|
|
break;
|
|
}
|
|
if (g > 0 && g < BASE)
|
|
t = 1;
|
|
else if (g == 0 && f == 0)
|
|
t = 0;
|
|
}
|
|
if (t)
|
|
adjust = (t > 0);
|
|
}
|
|
if (adjust) {
|
|
i = len;
|
|
a = a1;
|
|
while (i > 0 && *a == BASE1) {
|
|
i--;
|
|
*a++ = 0;
|
|
}
|
|
(*a)++;
|
|
if (i == 0)
|
|
len++;
|
|
}
|
|
if (s && adjust) {
|
|
i = 0;
|
|
while (A[i] == 0)
|
|
i++;
|
|
A[i] = -A[i];
|
|
while (++i < n)
|
|
A[i] = ~A[i];
|
|
m = n;
|
|
while (A[m - 1] == 0)
|
|
m--;
|
|
}
|
|
if (!s && adjust) {
|
|
a = A;
|
|
b = B;
|
|
i = n;
|
|
u = 0;
|
|
while (i--) {
|
|
f = (FULL) *b++ - *a - (FULL) u;
|
|
*a++ = (HALF) f;
|
|
u = -(HALF)(f >> BASEB);
|
|
}
|
|
m = n;
|
|
while (A[m - 1] == 0)
|
|
m--;
|
|
}
|
|
if (s && !adjust) {
|
|
a = A;
|
|
b = B;
|
|
i = n;
|
|
f = 0;
|
|
while (i--) {
|
|
f = (FULL) *b++ + *a + (f >> BASEB);
|
|
*a++ = (HALF) f;
|
|
}
|
|
m = n;
|
|
while (A[m-1] == 0)
|
|
m--;
|
|
}
|
|
rem->len = m;
|
|
rem->v = alloc(m);
|
|
memcpy(rem->v, A, m * sizeof(HALF));
|
|
rem->sign = z1.sign ^ adjust;
|
|
val = rem->sign ? -1 : 1;
|
|
if (a1[len - 1] == 0)
|
|
len--;
|
|
if (len == 0) {
|
|
*quo = _zero_;
|
|
} else {
|
|
quo->len = len;
|
|
quo->v = alloc(len);
|
|
memcpy(quo->v, a1, len * sizeof(HALF));
|
|
quo->sign = z1.sign ^ z2.sign;
|
|
}
|
|
freeh(A);
|
|
return val;
|
|
}
|
|
|
|
|
|
/*
|
|
* Compute and store at a specified location the integer quotient
|
|
* of two integers, the type of rounding being determined by rnd.
|
|
* Returns the sign of z1/z2 - calculated quotient.
|
|
*/
|
|
long
|
|
zquo(ZVALUE z1, ZVALUE z2, ZVALUE *res, long rnd)
|
|
{
|
|
ZVALUE tmp;
|
|
long val;
|
|
|
|
val = zdiv(z1, z2, res, &tmp, rnd);
|
|
if (z2.sign)
|
|
val = -val;
|
|
zfree(tmp);
|
|
return val;
|
|
}
|
|
|
|
|
|
/*
|
|
* Compute and store at a specified location the remainder for
|
|
* division of an integer by an integer, the type of rounding
|
|
* used being determined by rnd. Returns the sign of the remainder.
|
|
*/
|
|
long
|
|
zmod(ZVALUE z1, ZVALUE z2, ZVALUE *res, long rnd)
|
|
{
|
|
ZVALUE tmp;
|
|
long val;
|
|
|
|
val = zdiv(z1, z2, &tmp, res, rnd);
|
|
zfree(tmp);
|
|
return val;
|
|
}
|
|
|
|
|
|
/*
|
|
* Computes the quotient z1/z2 on the assumption that this is exact.
|
|
* There is no thorough check on the exactness of the division
|
|
* so this should not be called unless z1/z2 is an integer.
|
|
*/
|
|
void
|
|
zequo(ZVALUE z1, ZVALUE z2, ZVALUE *res)
|
|
{
|
|
LEN i, j, k, len, m, n, o, p;
|
|
HALF *a, *a0, *A, *b, *B, u, v, w, x;
|
|
FULL f, g;
|
|
|
|
if (ziszero(z1)) {
|
|
*res = _zero_;
|
|
return;
|
|
}
|
|
if (ziszero(z2)) {
|
|
math_error("Division by zero");
|
|
not_reached();
|
|
}
|
|
if (zisone(z2)) {
|
|
zcopy(z1, res);
|
|
return;
|
|
}
|
|
if (zhighbit(z1) < zhighbit(z2)) {
|
|
math_error("Bad call to zequo");
|
|
not_reached();
|
|
}
|
|
B = z2.v;
|
|
o = 0;
|
|
while (!*B) {
|
|
++B;
|
|
++o;
|
|
}
|
|
m = z1.len - o;
|
|
n = z2.len - o;
|
|
len = m - n + 1; /* Maximum length of quotient */
|
|
v = *B;
|
|
A = alloc(len+1);
|
|
memcpy(A, z1.v + o, len * sizeof(HALF));
|
|
A[len] = 0;
|
|
if (n == 1) {
|
|
if (v > 1) {
|
|
a = A + len;
|
|
i = len;
|
|
f = 0;
|
|
while (i--) {
|
|
f = f << BASEB | *--a;
|
|
*a = (HALF)(f / v);
|
|
f %= v;
|
|
}
|
|
}
|
|
} else {
|
|
k = 0;
|
|
while (!(v & 1)) {
|
|
k++;
|
|
v >>= 1;
|
|
}
|
|
j = BASEB - k;
|
|
if (n > 1 && k > 0)
|
|
v |= B[1] << j;
|
|
u = v - 1;
|
|
w = x = 1;
|
|
while (u) { /* To find w = inverse of v modulo BASE */
|
|
do {
|
|
v <<= 1;
|
|
x <<= 1;
|
|
}
|
|
while (!(u & x));
|
|
u += v;
|
|
w |= x;
|
|
}
|
|
a0 = A;
|
|
p = len;
|
|
while (p > 1) {
|
|
if (!*a0) {
|
|
while (!*++a0 && p > 1)
|
|
p--;
|
|
--a0;
|
|
}
|
|
if (p == 1)
|
|
break;
|
|
x = k ? w * (*a0 >> k | a0[1] << j) : w * *a0;
|
|
g = x;
|
|
if (x) {
|
|
a = a0;
|
|
b = B;
|
|
u = 0;
|
|
i = n;
|
|
if (i > p)
|
|
i = p;
|
|
while (i--) {
|
|
f = (FULL) *a - g * *b++ - (FULL) u;
|
|
*a++ = (HALF)f;
|
|
u = -(HALF)(f >> BASEB);
|
|
}
|
|
if (u && p > n) {
|
|
i = p - n;
|
|
while (u && i--) {
|
|
f = (FULL) *a - u;
|
|
*a++ = (HALF) f;
|
|
u = -(HALF)(f >> BASEB);
|
|
}
|
|
}
|
|
}
|
|
*a0++ = x;
|
|
p--;
|
|
}
|
|
if (k == 0) {
|
|
*a0 = w * *a0;
|
|
} else {
|
|
u = (HALF)(w * *a0) >> k;
|
|
x = (HALF)(((FULL) z1.v[z1.len - 1] << BASEB
|
|
| z1.v[z1.len - 2])
|
|
/((FULL) B[n-1] << BASEB | B[n-2]));
|
|
if ((x ^ u) & 1) x--;
|
|
*a0 = x;
|
|
}
|
|
}
|
|
if (!A[len - 1]) len--;
|
|
res->v = A;
|
|
res->len = len;
|
|
res->sign = z1.sign != z2.sign;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* Return the quotient and remainder of an integer divided by a small
|
|
* number. A nonzero remainder is only meaningful when both numbers
|
|
* are positive.
|
|
*/
|
|
long
|
|
zdivi(ZVALUE z, long n, ZVALUE *res)
|
|
{
|
|
HALF *h1, *sd;
|
|
FULL val;
|
|
HALF divval[2];
|
|
ZVALUE div;
|
|
ZVALUE dest;
|
|
LEN len;
|
|
|
|
if (n == 0) {
|
|
math_error("Division by zero");
|
|
not_reached();
|
|
}
|
|
if (ziszero(z)) {
|
|
*res = _zero_;
|
|
return 0;
|
|
}
|
|
if (n < 0) {
|
|
n = -n;
|
|
z.sign = !z.sign;
|
|
}
|
|
if (n == 1) {
|
|
zcopy(z, res);
|
|
return 0;
|
|
}
|
|
/*
|
|
* If the division is by a large number, then call the normal
|
|
* divide routine.
|
|
*/
|
|
if (n & ~BASE1) {
|
|
div.sign = 0;
|
|
div.v = divval;
|
|
divval[0] = (HALF) n;
|
|
#if LONG_BITS > BASEB
|
|
divval[1] = (HALF)(((FULL) n) >> BASEB);
|
|
div.len = 2;
|
|
#else
|
|
div.len = 1;
|
|
#endif
|
|
zdiv(z, div, res, &dest, 0);
|
|
n = ztolong(dest);
|
|
zfree(dest);
|
|
return n;
|
|
}
|
|
/*
|
|
* Division is by a small number, so we can be quick about it.
|
|
*/
|
|
len = z.len;
|
|
dest.sign = z.sign;
|
|
dest.len = len;
|
|
dest.v = alloc(len);
|
|
h1 = z.v + len;
|
|
sd = dest.v + len;
|
|
val = 0;
|
|
while (len--) {
|
|
val = ((val << BASEB) + ((FULL) *--h1));
|
|
*--sd = (HALF)(val / n);
|
|
val %= n;
|
|
}
|
|
zquicktrim(dest);
|
|
*res = dest;
|
|
return (long)val;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* Calculate the mod of an integer by a small number.
|
|
* This is only defined for positive moduli.
|
|
*/
|
|
long
|
|
zmodi(ZVALUE z, long n)
|
|
{
|
|
register HALF *h1;
|
|
FULL val;
|
|
HALF divval[2];
|
|
ZVALUE div;
|
|
ZVALUE temp;
|
|
long len;
|
|
|
|
if (n == 0) {
|
|
math_error("Division by zero");
|
|
not_reached();
|
|
}
|
|
if (n < 0) {
|
|
math_error("Non-positive modulus");
|
|
not_reached();
|
|
}
|
|
if (ziszero(z) || (n == 1))
|
|
return 0;
|
|
if (zisone(z))
|
|
return 1;
|
|
/*
|
|
* If the modulus is by a large number, then call the normal
|
|
* modulo routine.
|
|
*/
|
|
if (n & ~BASE1) {
|
|
div.sign = 0;
|
|
div.v = divval;
|
|
divval[0] = (HALF) n;
|
|
#if LONG_BITS > BASEB
|
|
divval[1] = (HALF)(((FULL) n) >> BASEB);
|
|
div.len = 2;
|
|
#else
|
|
div.len = 1;
|
|
#endif
|
|
zmod(z, div, &temp, 0);
|
|
n = ztolong(temp);
|
|
zfree(temp);
|
|
return n;
|
|
}
|
|
/*
|
|
* The modulus is by a small number, so we can do this quickly.
|
|
*/
|
|
len = z.len;
|
|
h1 = z.v + len;
|
|
val = 0;
|
|
while (len-- > 0)
|
|
val = ((val << BASEB) + ((FULL) *--h1)) % n;
|
|
if (val && z.sign)
|
|
val = n - val;
|
|
return (long)val;
|
|
}
|
|
|
|
|
|
/*
|
|
* Return whether or not one number exactly divides another one.
|
|
* Returns TRUE if division occurs with no remainder.
|
|
* z1 is the number to be divided by z2.
|
|
*/
|
|
|
|
BOOL
|
|
zdivides(ZVALUE z1, ZVALUE z2)
|
|
{
|
|
LEN i, j, k, m, n;
|
|
HALF u, v, w, x;
|
|
HALF *a, *a0, *A, *b, *B, *c, *d;
|
|
FULL f;
|
|
BOOL ans;
|
|
|
|
if (zisunit(z2) || ziszero(z1)) return TRUE;
|
|
if (ziszero(z2)) return FALSE;
|
|
|
|
m = z1.len;
|
|
n = z2.len;
|
|
if (m < n) return FALSE;
|
|
|
|
c = z1.v;
|
|
d = z2.v;
|
|
|
|
while (!*d) {
|
|
if (*c++) return FALSE;
|
|
d++;
|
|
m--;
|
|
n--;
|
|
}
|
|
|
|
j = 0;
|
|
u = *c;
|
|
v = *d;
|
|
while (!(v & 1)) { /* Counting and checking zero bits */
|
|
if (u & 1) return FALSE;
|
|
u >>= 1;
|
|
v >>= 1;
|
|
j++;
|
|
}
|
|
|
|
if (n == 1 && v == 1) return TRUE;
|
|
if (!*c) { /* Removing any further zeros */
|
|
while(!*++c)
|
|
m--;
|
|
c--;
|
|
}
|
|
|
|
if (m < n) return FALSE;
|
|
|
|
if (j) {
|
|
B = alloc((LEN)n); /* Array for shifted z2 */
|
|
d += n;
|
|
b = B + n;
|
|
i = n;
|
|
f = 0;
|
|
while(i--) {
|
|
f = f << BASEB | *--d;
|
|
*--b = (HALF)(f >> j);
|
|
}
|
|
if (!B[n - 1]) n--;
|
|
}
|
|
else B = d;
|
|
u = *B;
|
|
v = x = 1;
|
|
w = 0;
|
|
while (x) { /* Finding minv(*B, BASE) */
|
|
if (v & x) {
|
|
v -= x * u;
|
|
w |= x;
|
|
}
|
|
x <<= 1;
|
|
}
|
|
|
|
A = alloc((LEN)(m + 2)); /* Main working array */
|
|
memcpy(A, c, m * sizeof(HALF));
|
|
A[m + 1] = 1;
|
|
A[m] = 0;
|
|
|
|
k = m - n + 1; /* Length of presumed quotient */
|
|
|
|
a0 = A;
|
|
|
|
while (k--) {
|
|
if (*a0) {
|
|
x = w * *a0;
|
|
a = a0;
|
|
b = B;
|
|
i = n;
|
|
u = 0;
|
|
while (i--) {
|
|
f = (FULL) *a - (FULL) x * *b++ - u;
|
|
*a++ = (HALF)f;
|
|
u = -(HALF)(f >> BASEB);
|
|
}
|
|
f = (FULL) *a - u;
|
|
*a++ = (HALF)f;
|
|
u = -(HALF)(f >> BASEB);
|
|
if (u) {
|
|
while (*a == 0) *a++ = BASE1;
|
|
(*a)--;
|
|
}
|
|
}
|
|
a0++;
|
|
}
|
|
ans = FALSE;
|
|
if (A[m + 1]) {
|
|
a = A + m;
|
|
while (--n && !*--a);
|
|
if (!n) ans = TRUE;
|
|
}
|
|
freeh(A);
|
|
if (j) freeh(B);
|
|
return ans;
|
|
}
|
|
|
|
|
|
/*
|
|
* Compute the bitwise OR of two integers
|
|
*/
|
|
void
|
|
zor(ZVALUE z1, ZVALUE z2, ZVALUE *res)
|
|
{
|
|
register HALF *sp, *dp;
|
|
long len;
|
|
ZVALUE bz, lz, dest;
|
|
|
|
if (z1.len >= z2.len) {
|
|
bz = z1;
|
|
lz = z2;
|
|
} else {
|
|
bz = z2;
|
|
lz = z1;
|
|
}
|
|
dest.len = bz.len;
|
|
dest.v = alloc(dest.len);
|
|
dest.sign = 0;
|
|
zcopyval(bz, dest);
|
|
len = lz.len;
|
|
sp = lz.v;
|
|
dp = dest.v;
|
|
while (len--)
|
|
*dp++ |= *sp++;
|
|
*res = dest;
|
|
}
|
|
|
|
|
|
/*
|
|
* Compute the bitwise AND of two integers
|
|
*/
|
|
void
|
|
zand(ZVALUE z1, ZVALUE z2, ZVALUE *res)
|
|
{
|
|
HALF *h1, *h2, *hd;
|
|
LEN len;
|
|
ZVALUE dest;
|
|
|
|
len = ((z1.len <= z2.len) ? z1.len : z2.len);
|
|
h1 = &z1.v[len-1];
|
|
h2 = &z2.v[len-1];
|
|
while ((len > 1) && ((*h1 & *h2) == 0)) {
|
|
h1--;
|
|
h2--;
|
|
len--;
|
|
}
|
|
dest.len = len;
|
|
dest.v = alloc(len);
|
|
dest.sign = 0;
|
|
h1 = z1.v;
|
|
h2 = z2.v;
|
|
hd = dest.v;
|
|
while (len--)
|
|
*hd++ = (*h1++ & *h2++);
|
|
*res = dest;
|
|
}
|
|
|
|
|
|
/*
|
|
* Compute the bitwise XOR of two integers.
|
|
*/
|
|
void
|
|
zxor(ZVALUE z1, ZVALUE z2, ZVALUE *res)
|
|
{
|
|
HALF *dp, *h1, *h2;
|
|
LEN len, j, k;
|
|
ZVALUE dest;
|
|
|
|
h1 = z1.v;
|
|
h2 = z2.v;
|
|
len = z1.len;
|
|
j = z2.len;
|
|
if (z1.len < z2.len) {
|
|
len = z2.len;
|
|
j = z1.len;
|
|
h1 = z2.v;
|
|
h2 = z1.v;
|
|
} else if (z1.len == z2.len) {
|
|
while (len > 1 && z1.v[len-1] == z2.v[len-1])
|
|
len--;
|
|
j = len;
|
|
}
|
|
k = len - j;
|
|
dest.len = len;
|
|
dest.v = alloc(len);
|
|
dest.sign = 0;
|
|
dp = dest.v;
|
|
while (j-- > 0)
|
|
*dp++ = *h1++ ^ *h2++;
|
|
while (k-- > 0)
|
|
*dp++ = *h1++;
|
|
*res = dest;
|
|
}
|
|
|
|
|
|
/*
|
|
* Compute the bitwise AND NOT of two integers.
|
|
*/
|
|
void
|
|
zandnot(ZVALUE z1, ZVALUE z2, ZVALUE *res)
|
|
{
|
|
HALF *dp, *h1, *h2;
|
|
LEN len, j, k;
|
|
ZVALUE dest;
|
|
|
|
len = z1.len;
|
|
if (z2.len >= len) {
|
|
while (len > 1 && (z1.v[len-1] & ~z2.v[len-1]) == 0)
|
|
len--;
|
|
j = len;
|
|
k = 0;
|
|
} else {
|
|
j = z2.len;
|
|
k = len - z2.len;
|
|
}
|
|
dest.len = len;
|
|
dest.v = alloc(len);
|
|
dest.sign = 0;
|
|
dp = dest.v;
|
|
h1 = z1.v;
|
|
h2 = z2.v;
|
|
while (j-- > 0)
|
|
*dp++ = *h1++ & ~*h2++;
|
|
while (k-- > 0)
|
|
*dp++ = *h1++;
|
|
*res = dest;
|
|
}
|
|
|
|
|
|
/*
|
|
* Shift a number left (or right) by the specified number of bits.
|
|
* Positive shift means to the left. When shifting right, rightmost
|
|
* bits are lost. The sign of the number is preserved.
|
|
*/
|
|
void
|
|
zshift(ZVALUE z, long n, ZVALUE *res)
|
|
{
|
|
ZVALUE ans;
|
|
LEN hc; /* number of halfwords shift is by */
|
|
|
|
if (ziszero(z)) {
|
|
*res = _zero_;
|
|
return;
|
|
}
|
|
if (n == 0) {
|
|
zcopy(z, res);
|
|
return;
|
|
}
|
|
/*
|
|
* If shift value is negative, then shift right.
|
|
* Check for large shifts, and handle word-sized shifts quickly.
|
|
*/
|
|
if (n < 0) {
|
|
n = -n;
|
|
if ((n < 0) || (n >= (z.len * BASEB))) {
|
|
*res = _zero_;
|
|
return;
|
|
}
|
|
hc = (LEN)(n / BASEB);
|
|
n %= BASEB;
|
|
z.v += hc;
|
|
z.len -= hc;
|
|
ans.len = z.len;
|
|
ans.v = alloc(ans.len);
|
|
ans.sign = z.sign;
|
|
zcopyval(z, ans);
|
|
if (n > 0) {
|
|
zshiftr(ans, n);
|
|
ztrim(&ans);
|
|
}
|
|
if (ziszero(ans)) {
|
|
zfree(ans);
|
|
ans = _zero_;
|
|
}
|
|
*res = ans;
|
|
return;
|
|
}
|
|
/*
|
|
* Shift value is positive, so shift leftwards.
|
|
* Check specially for a shift of the value 1, since this is common.
|
|
* Also handle word-sized shifts quickly.
|
|
*/
|
|
if (zisunit(z)) {
|
|
zbitvalue(n, res);
|
|
res->sign = z.sign;
|
|
return;
|
|
}
|
|
hc = (LEN)(n / BASEB);
|
|
n %= BASEB;
|
|
ans.len = z.len + hc + 1;
|
|
ans.v = alloc(ans.len);
|
|
ans.sign = z.sign;
|
|
if (hc > 0)
|
|
memset((char *) ans.v, 0, hc * sizeof(HALF));
|
|
memcpy((char *) (ans.v + hc),
|
|
(char *) z.v, z.len * sizeof(HALF));
|
|
ans.v[ans.len - 1] = 0;
|
|
if (n > 0) {
|
|
ans.v += hc;
|
|
ans.len -= hc;
|
|
zshiftl(ans, n);
|
|
ans.v -= hc;
|
|
ans.len += hc;
|
|
}
|
|
ztrim(&ans);
|
|
*res = ans;
|
|
}
|
|
|
|
|
|
/*
|
|
* Return the position of the lowest bit which is set in the binary
|
|
* representation of a number (counting from zero). This is the highest
|
|
* power of two which evenly divides the number.
|
|
*/
|
|
long
|
|
zlowbit(ZVALUE z)
|
|
{
|
|
register HALF *zp;
|
|
long n;
|
|
HALF dataval;
|
|
HALF *bitval;
|
|
|
|
n = 0;
|
|
for (zp = z.v; *zp == 0; zp++)
|
|
if (++n >= z.len)
|
|
return 0;
|
|
dataval = *zp;
|
|
bitval = bitmask;
|
|
/* ignore Saber-C warning #530 about empty while statement */
|
|
/* OK to ignore in proc zlowbit */
|
|
while ((*(bitval++) & dataval) == 0) {
|
|
}
|
|
return (n*BASEB)+(bitval-bitmask-1);
|
|
}
|
|
|
|
|
|
/*
|
|
* Return the position of the highest bit which is set in the binary
|
|
* representation of a number (counting from zero). This is the highest power
|
|
* of two which is less than or equal to the number (which is assumed nonzero).
|
|
*/
|
|
LEN
|
|
zhighbit(ZVALUE z)
|
|
{
|
|
HALF dataval;
|
|
HALF *bitval;
|
|
|
|
dataval = z.v[z.len-1];
|
|
if (dataval == 0) {
|
|
return 0;
|
|
}
|
|
bitval = bitmask+BASEB;
|
|
if (dataval) {
|
|
/* ignore Saber-C warning #530 about empty while statement */
|
|
/* OK to ignore in proc zhighbit */
|
|
while ((*(--bitval) & dataval) == 0) {
|
|
}
|
|
}
|
|
return (z.len*BASEB)+(LEN)(bitval-bitmask-BASEB);
|
|
}
|
|
|
|
|
|
/*
|
|
* Return whether or not the specified bit number is set in a number.
|
|
* Rightmost bit of a number is bit 0.
|
|
*/
|
|
BOOL
|
|
zisset(ZVALUE z, long n)
|
|
{
|
|
if ((n < 0) || ((n / BASEB) >= z.len))
|
|
return FALSE;
|
|
return ((z.v[n / BASEB] & (((HALF) 1) << (n % BASEB))) != 0);
|
|
}
|
|
|
|
|
|
/*
|
|
* Check whether or not a number has exactly one bit set, and
|
|
* thus is an exact power of two. Returns TRUE if so.
|
|
*/
|
|
BOOL
|
|
zisonebit(ZVALUE z)
|
|
{
|
|
register HALF *hp;
|
|
register LEN len;
|
|
|
|
if (ziszero(z) || zisneg(z))
|
|
return FALSE;
|
|
hp = z.v;
|
|
len = z.len;
|
|
while (len > 4) {
|
|
len -= 4;
|
|
if (*hp++ || *hp++ || *hp++ || *hp++)
|
|
return FALSE;
|
|
}
|
|
while (--len > 0) {
|
|
if (*hp++)
|
|
return FALSE;
|
|
}
|
|
return ((*hp & -*hp) == *hp); /* NEEDS 2'S COMPLEMENT */
|
|
}
|
|
|
|
|
|
/*
|
|
* Check whether or not a number has all of its bits set below some
|
|
* bit position, and thus is one less than an exact power of two.
|
|
* Returns TRUE if so.
|
|
*/
|
|
BOOL
|
|
zisallbits(ZVALUE z)
|
|
{
|
|
register HALF *hp;
|
|
register LEN len;
|
|
HALF digit;
|
|
|
|
if (ziszero(z) || zisneg(z))
|
|
return FALSE;
|
|
hp = z.v;
|
|
len = z.len;
|
|
while (len > 4) {
|
|
len -= 4;
|
|
if ((*hp++ != BASE1) || (*hp++ != BASE1) ||
|
|
(*hp++ != BASE1) || (*hp++ != BASE1))
|
|
return FALSE;
|
|
}
|
|
while (--len > 0) {
|
|
if (*hp++ != BASE1)
|
|
return FALSE;
|
|
}
|
|
digit = (HALF)(*hp + 1);
|
|
return ((digit & -digit) == digit); /* NEEDS 2'S COMPLEMENT */
|
|
}
|
|
|
|
|
|
/*
|
|
* Return the number whose binary representation contains only one bit which
|
|
* is in the specified position (counting from zero). This is equivalent
|
|
* to raising two to the given power.
|
|
*/
|
|
void
|
|
zbitvalue(long n, ZVALUE *res)
|
|
{
|
|
ZVALUE z;
|
|
|
|
if (n < 0) n = 0;
|
|
z.sign = 0;
|
|
z.len = (LEN)((n / BASEB) + 1);
|
|
z.v = alloc(z.len);
|
|
zclearval(z);
|
|
z.v[z.len-1] = (((HALF) 1) << (n % BASEB));
|
|
*res = z;
|
|
}
|
|
|
|
|
|
/*
|
|
* Compare a number against zero.
|
|
* Returns the sgn function of the number (-1, 0, or 1).
|
|
*/
|
|
FLAG
|
|
ztest(ZVALUE z)
|
|
{
|
|
register int sign;
|
|
register HALF *h;
|
|
register long len;
|
|
|
|
sign = 1;
|
|
if (z.sign)
|
|
sign = -sign;
|
|
h = z.v;
|
|
len = z.len;
|
|
while (len--)
|
|
if (*h++)
|
|
return sign;
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* Return the sign of z1 - z2, i.e. 1 if the first integer is greater,
|
|
* 0 if they are equal, -1 otherwise.
|
|
*/
|
|
FLAG
|
|
zrel(ZVALUE z1, ZVALUE z2)
|
|
{
|
|
HALF *h1, *h2;
|
|
LEN len;
|
|
int sign;
|
|
|
|
sign = 1;
|
|
if (z1.sign < z2.sign)
|
|
return 1;
|
|
if (z2.sign < z1.sign)
|
|
return -1;
|
|
if (z2.sign)
|
|
sign = -1;
|
|
if (z1.len != z2.len)
|
|
return (z1.len > z2.len) ? sign : -sign;
|
|
len = z1.len;
|
|
h1 = z1.v + len;
|
|
h2 = z2.v + len;
|
|
|
|
while (len > 0) {
|
|
if (*--h1 != *--h2)
|
|
break;
|
|
len--;
|
|
}
|
|
if (len > 0)
|
|
return (*h1 > *h2) ? sign : -sign;
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* Return the sign of abs(z1) - abs(z2), i.e. 1 if the first integer
|
|
* has greater absolute value, 0 is they have equal absolute value,
|
|
* -1 otherwise.
|
|
*/
|
|
FLAG
|
|
zabsrel(ZVALUE z1, ZVALUE z2)
|
|
{
|
|
HALF *h1, *h2;
|
|
LEN len;
|
|
|
|
if (z1.len != z2.len)
|
|
return (z1.len > z2.len) ? 1 : -1;
|
|
|
|
len = z1.len;
|
|
h1 = z1.v + len;
|
|
h2 = z2.v + len;
|
|
while (len > 0) {
|
|
if (*--h1 != *--h2)
|
|
break;
|
|
len--;
|
|
}
|
|
if (len > 0)
|
|
return (*h1 > *h2) ? 1 : -1;
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* Compare two numbers to see if they are equal or not.
|
|
* Returns TRUE if they differ.
|
|
*/
|
|
BOOL
|
|
zcmp(ZVALUE z1, ZVALUE z2)
|
|
{
|
|
register HALF *h1, *h2;
|
|
register long len;
|
|
|
|
if ((z1.sign != z2.sign) || (z1.len != z2.len) || (*z1.v != *z2.v))
|
|
return TRUE;
|
|
len = z1.len;
|
|
h1 = z1.v;
|
|
h2 = z2.v;
|
|
while (--len > 0) {
|
|
if (*++h1 != *++h2)
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/*
|
|
* Utility to calculate the gcd of two FULL integers.
|
|
*/
|
|
FULL
|
|
uugcd(FULL f1, FULL f2)
|
|
{
|
|
FULL temp;
|
|
|
|
while (f1) {
|
|
temp = f2 % f1;
|
|
f2 = f1;
|
|
f1 = temp;
|
|
}
|
|
return (FULL) f2;
|
|
}
|
|
|
|
|
|
/*
|
|
* Utility to calculate the gcd of two small integers.
|
|
*/
|
|
long
|
|
iigcd(long i1, long i2)
|
|
{
|
|
FULL f1, f2, temp;
|
|
|
|
f1 = (FULL) ((i1 >= 0) ? i1 : -i1);
|
|
f2 = (FULL) ((i2 >= 0) ? i2 : -i2);
|
|
while (f1) {
|
|
temp = f2 % f1;
|
|
f2 = f1;
|
|
f1 = temp;
|
|
}
|
|
return (long) f2;
|
|
}
|
|
|
|
|
|
void
|
|
ztrim(ZVALUE *z)
|
|
{
|
|
HALF *h;
|
|
LEN len;
|
|
|
|
h = z->v + z->len - 1;
|
|
len = z->len;
|
|
while (*h == 0 && len > 1) {
|
|
--h;
|
|
--len;
|
|
}
|
|
z->len = len;
|
|
}
|
|
|
|
|
|
/*
|
|
* Utility routine to shift right.
|
|
*
|
|
* NOTE: The ZVALUE length is not adjusted instead, the value is
|
|
* zero padded from the left. One may need to call ztrim()
|
|
* or use zshift() instead.
|
|
*/
|
|
void
|
|
zshiftr(ZVALUE z, long n)
|
|
{
|
|
register HALF *h, *lim;
|
|
FULL mask, maskt;
|
|
long len;
|
|
|
|
if (n >= BASEB) {
|
|
len = n / BASEB;
|
|
h = z.v;
|
|
lim = z.v + z.len - len;
|
|
while (h < lim) {
|
|
h[0] = h[len];
|
|
++h;
|
|
}
|
|
n -= BASEB * len;
|
|
lim = z.v + z.len;
|
|
while (h < lim)
|
|
*h++ = 0;
|
|
}
|
|
if (n) {
|
|
len = z.len;
|
|
h = z.v + len;
|
|
mask = 0;
|
|
while (len--) {
|
|
maskt = (((FULL) *--h) << (BASEB - n)) & BASE1;
|
|
*h = ((*h >> n) | (HALF)mask);
|
|
mask = maskt;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* Utility routine to shift left.
|
|
*
|
|
* NOTE: The ZVALUE length is not adjusted. The bits in the upper
|
|
* HALF are simply tossed. You may want to use zshift() instead.
|
|
*/
|
|
void
|
|
zshiftl(ZVALUE z, long n)
|
|
{
|
|
register HALF *h;
|
|
FULL mask, i;
|
|
long len;
|
|
|
|
if (n >= BASEB) {
|
|
len = n / BASEB;
|
|
h = z.v + z.len - 1;
|
|
while (!*h)
|
|
--h;
|
|
while (h >= z.v) {
|
|
h[len] = h[0];
|
|
--h;
|
|
}
|
|
n -= BASEB * len;
|
|
while (len)
|
|
h[len--] = 0;
|
|
}
|
|
if (n > 0) {
|
|
len = z.len;
|
|
h = z.v;
|
|
mask = 0;
|
|
while (len--) {
|
|
i = (((FULL) *h) << n) | mask;
|
|
if (i > BASE1) {
|
|
mask = i >> BASEB;
|
|
i &= BASE1;
|
|
} else {
|
|
mask = 0;
|
|
}
|
|
*h = (HALF) i;
|
|
++h;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* popcnt - count the number of 0 or 1 bits in an integer
|
|
*
|
|
* We ignore all 0 bits above the highest bit.
|
|
*/
|
|
long
|
|
zpopcnt(ZVALUE z, int bitval)
|
|
{
|
|
long cnt = 0; /* number of times found */
|
|
HALF h; /* HALF to count */
|
|
int i;
|
|
|
|
/*
|
|
* count 1's
|
|
*/
|
|
if (bitval) {
|
|
|
|
/*
|
|
* count each HALF
|
|
*/
|
|
for (i=0; i < z.len; ++i) {
|
|
/* count each octet */
|
|
for (h = z.v[i]; h; h >>= 8) {
|
|
cnt += (long)popcnt[h & 0xff];
|
|
}
|
|
}
|
|
|
|
/*
|
|
* count 0's
|
|
*/
|
|
} else {
|
|
|
|
/*
|
|
* count each HALF up until the last
|
|
*/
|
|
for (i=0; i < z.len-1; ++i) {
|
|
|
|
/* count each octet */
|
|
cnt += BASEB;
|
|
for (h = z.v[i]; h; h >>= 8) {
|
|
cnt -= (long)popcnt[h & 0xff];
|
|
}
|
|
}
|
|
|
|
/*
|
|
* count the last octet up until the highest 1 bit
|
|
*/
|
|
for (h = z.v[z.len-1]; h; h>>=1) {
|
|
/* count each 0 bit */
|
|
if ((h & 0x1) == 0) {
|
|
++cnt;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* return count
|
|
*/
|
|
return cnt;
|
|
}
|