home *** CD-ROM | disk | FTP | other *** search
Text File | 1988-10-08 | 26.3 KB | 1,291 lines |
- /******************************************************************************
-
- Arbitrary Precision Math Library General Public License
- (Written October 5, 1988)
-
- Copyright (C) 1988 Lloyd Zusman, Master Byte Software, Los
- Gatos, California. Everyone is permitted to copy and distribute
- verbatim copies of this license, but changing it is not allowed.
- You can also use this wording to make the terms for other programs.
-
- The wording of this license is based on that of the
- "GNU EMACS GENERAL PUBLIC LICENSE" by Richard Stallman,
- Copyright (C) 1985, 1987, 1988, version of February 11, 1988,
- but since some of the text has been changed, please be sure to
- READ THIS CAREFULLY!
-
- This general public license is intended to give everyone the right
- to share the Arbitrary Precision Math Library (hereinafter referred to
- as the "APM Library"). To make sure that you get the rights we want
- you to have, I need to make restrictions that forbid anyone to deny
- you these rights or to ask you to surrender the rights.
-
- Specifically, we want to make sure that you have the right to give
- away copies of the APM Library, that you receive source code or else
- can get it if you want it, that you can change the APM Library or use
- pieces of it in new programs, and that you know you can do these
- things.
-
- To make sure that everyone has such rights, we have to forbid you to
- deprive anyone else of these rights. For example, if you distribute
- copies of the APM Library, you must give the recipients all the
- rights that you have. You must make sure that they, too, receive or
- can get the source code. And you must tell them their rights.
-
- Also, for our own protection, we must make certain that everyone
- finds out that there is no warranty for the APM Library. If the APM
- Library is modified by someone else and passed on, we want its
- recipients to know that what they have is not what we distributed, so
- that any problems introduced by others will not reflect on our
- reputation.
-
- Therefore we (Lloyd Zusman and Master Byte Software) make the
- following terms which say what you must do to be allowed to
- distribute or change the APM Library.
-
- COPYING POLICIES
-
- 1. You may copy and distribute verbatim copies of the APM Library
- source code as you receive it, in any medium, provided that you
- conspicuously and appropriately publish on each copy a valid copyright
- notice "Copyright (C) 1988 Lloyd Zusman, Master Byte Software, Los
- Gatos, California" (or with whatever year is appropriate); keep intact
- the notices on all files that refer to this License Agreement and to
- the absence of any warranty; and give any other recipients of the the
- APM Library program a copy of this License Agreement along with the
- program. You may charge a distribution fee for the physical act of
- transferring a copy.
-
- 2. You may modify your copy or copies of the APM Library source code or
- any portion of it, and copy and distribute such modifications under
- the terms of Paragraph 1 above, provided that you also do the following:
-
- a) cause the modified files to carry prominent notices stating
- that you changed the files and the date of any change; and
-
- b) cause the whole of any work that you distribute or publish, that in
- whole or in part contains or is a derivative of the APM Library or any
- part thereof, to be licensed to all third parties on terms identical
- to those contained in this License Agreement (except that you may
- choose to grant more extensive warranty protection to some or all
- third parties, at your option).
-
- c) You may charge a distribution fee for the physical act of
- transferring a copy, and you may at your option offer warranty
- protection in exchange for a fee.
-
- d) You may not charge a license fee for the whole of any work that
- you distribute or publish, that in whole or in part contains or is
- a derivative of the APM library or any part thereof, without the
- express written permission of Lloyd Zusman and Master Byte Software;
- whether this permission is granted for free or in return for goods
- services, royalties, or other compensation will be determined
- solely by Lloyd Zusman and Master Byte Software.
-
- Mere aggregation of another unrelated program with this program (or its
- derivative) on a volume of a storage or distribution medium does not bring
- the other program under the scope of these terms.
-
- 3. You may copy and distribute the APM Library (or a portion or
- derivative of it, under Paragraph 2) in object code or executable form
- under all the terms of Paragraphs 1 and 2 above provided that you also
- do one of the following:
-
- a) accompany it with the complete corresponding machine-readable
- source code, which must be distributed under the terms of
- Paragraphs 1 and 2 above; or,
-
- b) accompany it with a written offer, valid for at least three
- years, to give any third party free (except for a nominal
- shipping charge) a complete machine-readable copy of the
- corresponding source code, to be distributed under the terms of
- Paragraphs 1 and 2 above; or,
-
- c) accompany it with the information you received as to where the
- corresponding source code may be obtained. (This alternative is
- allowed only for noncommercial distribution and only if you
- received the program in object code or executable form alone.)
-
- For an executable file, complete source code means all the source code
- for all modules it contains; but, as a special exception, it need not
- include source code for modules which are standard libraries that
- accompany the operating system on which the executable file runs.
-
- 4. You may not copy, sublicense, distribute or transfer the APM
- Library except as expressly provided under this License Agreement.
- Any attempt otherwise to copy, sublicense, distribute or transfer the
- APM Library is void and your rights to use the APM Library under this
- License agreement shall be automatically terminated. However, parties
- who have received computer software programs from you with this
- License Agreement will not have their licenses terminated so long as
- such parties remain in full compliance.
-
- 5. If you wish to incorporate parts of the APM Library into other
- programs whose distribution conditions are different, write to Lloyd
- Zusman at Master Byte Software. We have not yet worked out a simple
- rule that can be stated here, but we will often permit this. We will
- be guided by the goals of (1) preserving the free status of all
- derivatives of our free software; of (2) promoting the sharing and
- reuse of software; and of (3) not allowing anyone to profit from the
- use of our software without us also having the opportunity to share
- in these profits.
-
- Your comments and suggestions about our licensing policies and our
- software are welcome! Please contact Lloyd Zusman, Master Byte
- Software, 127 Wilder Ave., Los Gatos, California 95030, or call
- (408) 395-5693.
-
- NO WARRANTY
-
- BECAUSE THE APM LIBRARY IS LICENSED FREE OF CHARGE, WE PROVIDE
- ABSOLUTELY NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE
- LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING, MASTER BYTE SOFTWARE,
- LLOYD ZUSMAN AND/OR OTHER PARTIES PROVIDE THE APM LIBRARY "AS IS"
- WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
- BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY
- AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE THE APM
- LIBRARY PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY
- SERVICING, REPAIR OR CORRECTION.
-
- IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL MASTER BYTE
- SOFTWARE, LLOYD ZUSMAN, AND/OR ANY OTHER PARTY WHO MAY MODIFY AND
- REDISTRIBUTE THE APM LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR
- DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR OTHER SPECIAL,
- INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
- INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA
- BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A
- FAILURE OF THE PROGRAM TO OPERATE WITH PROGRAMS NOT DISTRIBUTED BY
- MASTER BYTE SOFTWARE) THE PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF
- THE POSSIBILITY OF SUCH DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY.
-
- ******************************************************************************/
-
-
- /*
- * Low level utilities for the APM library. The user never should call
- * any of these directly.
- *
- * $Log: utils.c,v $
- * Revision 1.0 88/10/05 12:38:16 ljz
- * Initial release.
- *
- */
- #ifndef lint
- static char rcsid[] = "$Header: utils.c,v 1.0 88/10/05 12:38:16 ljz Exp $";
- #endif /* ! lint */
-
- #include <stdio.h>
- #include <varargs.h>
- #include "apm.h"
- #include "apmlocal.h"
-
- int apm_errno = APM_OK;
- int (*APM_error_func)() = (int (*)())NULL;
- int APM_line = 0;
- char *APM_file = "";
- char *APM_func_name = "";
-
- static char APM_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
-
- #define MAX_BASE ((sizeof (APM_digits) / sizeof (APM_digits[0])) - 1)
-
- char *
- APM_error_message(code)
- int code;
- {
- static char localMessage[80];
- char *message;
-
- switch (code) {
- case APM_ENOMEM:
- message = "memory allocation failed";
- break;
- case APM_WNULL:
- message = "null argument";
- break;
- case APM_WDIVBYZERO:
- message = "division by zero";
- break;
- case APM_WTRUNC:
- message = "result truncated";
- break;
- case APM_WNOALLOC:
- message = "attempt to free unallocated APM value";
- break;
- case APM_EPARM:
- message = "invalid function parameter";
- break;
- case APM_ENULL:
- message = "null APM value";
- break;
- case APM_EBADVAL:
- message = "bad APM value";
- break;
- case APM_ENULLVAL:
- message = "null value";
- break;
- case APM_EFMT:
- message = "invalid string format";
- break;
- case APM_EBASE:
- message = "invalid base";
- break;
- case APM_ESIZE:
- message = "destination size is too small";
- break;
- case APM_EOVERLAP:
- message = "result overlaps one or more operands";
- break;
- default:
- sprintf(localMessage, "unknown error code: %d", code);
- message = localMessage;
- break;
- }
-
- return (message);
- }
-
- int
- APM_set_errno(code)
- int code;
- {
- apm_errno = code;
- return (code);
- }
-
- int
- APM_error(code)
- int code;
- {
- code = APM_set_errno(code);
-
- if (code != APM_OK && APM_error_func != (int (*)())NULL) {
- code = (*APM_error_func)(code,
- APM_error_message(code),
- APM_file, APM_line,
- APM_func_name);
- }
- return (code);
- }
-
- char *
- APM_trim_string(string)
- char *string;
- {
- char *orig = string;
- char *sp = string;
-
- if (string != NULL) {
- for (; *string != '\0'; ++string) {
- if (*string != ' ' && *string != '\t') {
- sp = string + 1;
- }
- }
- *sp = '\0';
- }
-
- return (orig);
- }
-
- char *
- APM_left_justify(string, ignore)
- char *string;
- char *ignore;
- {
- if (string != NULL && ignore != NULL) {
- for (; *string != '\0'; ++string) {
- if (APM_index(ignore, *string) == NULL) {
- break;
- }
- }
- }
-
- return (string);
- }
-
- int
- APM_val_format(apm)
- APM apm;
- {
- apm_errno = APM_OK;
-
- if (apm == (APM)NULL) {
- return (APM_set_errno(APM_ENULL));
- }
- if (apm->magic != APM_MAGIC) {
- return (APM_set_errno(APM_EBADVAL));
- }
- return (APM_OK);
- }
-
- int
- APM_val_base(base)
- short base;
- {
- apm_errno = APM_OK;
-
- if (base == SPECIAL_BASE) {
- return (APM_OK);
- }
-
- if (base < 2 || base > MAX_BASE) {
- return (APM_set_errno(APM_EBASE));
- }
-
- return (APM_OK);
- }
-
- short
- APM_get_digit(ch, base)
- char ch;
- short base;
- {
- int ercode;
- short idx;
-
- ercode = APM_val_base(base);
- if (ercode < APM_OK) {
- return (APM_set_errno(ercode));
- }
-
- if (base == SPECIAL_BASE) {
- base = 10;
- }
-
- for (idx = 0; idx < base; ++idx) {
- if (ch == APM_digits[idx]) {
- return (idx);
- }
- }
-
- return (APM_set_errno(APM_EBASE));
- }
-
- int
- APM_radix_pos(string, base)
- char *string;
- short base;
- {
- int dp = -1;
- int nodigits = 1;
- int pos = 0;
- int ercode;
-
- if (string == NULL) {
- return (APM_set_errno(APM_ENULLVAL));
- }
- ercode = APM_val_base(base);
- if (ercode < APM_OK) {
- return (ercode);
- }
-
- for (; string[pos] != '\0'; ++pos) {
- if (string[pos] == '.') {
- if (dp >= 0) {
- return (APM_set_errno(APM_EFMT));
- }
- else {
- dp = pos;
- }
- }
- else if (APM_get_digit(string[pos], base) < 0) {
- return (APM_set_errno(APM_EFMT));
- }
- else {
- nodigits = 0;
- }
- }
-
- if (nodigits) {
- return (APM_set_errno(APM_EFMT));
- }
-
- return (dp + 1);
- }
-
- int
- APM_shift(num, scaleFactor)
- APM num;
- int scaleFactor;
- {
- int ercode;
-
- apm_errno = APM_OK;
-
- if (scaleFactor == 0) {
- return (APM_OK);
- }
- if (num->base != 0 && num->base != SPECIAL_BASE) {
- num->dp -= scaleFactor;
- }
- else {
- /*
- * The following code assumes that
- * (-X) % Y == -(X % Y).
- */
- int factor = scaleFactor / SPECIAL_SCALE;
- int n = scaleFactor % SPECIAL_SCALE;
-
- if (scaleFactor < 0) {
- --factor;
- n += SPECIAL_SCALE;
- }
- num->dp -= factor;
- if (n > 0) {
- int multiplier = 1;
- while (n-- > 0) {
- multiplier *= 10;
- }
- n = (num->length)++;
- ercode = APM_size(num, num->length);
- if (ercode < APM_OK) {
- return (ercode);
- }
- num->data[n] = APM_scalar_mul(num->data,
- num->data, n,
- multiplier,
- num->base);
- }
- }
- return (APM_trim(num, 1, 1));
- }
-
- int
- APM_trimlead(apm)
- APM apm;
- {
- int n;
- int ercode;
-
- apm_errno = APM_OK;
-
- if (apm == (APM)NULL) {
- return (APM_set_errno(APM_ENULL));
- }
-
- if (apm->data == NULL) {
- apm->length = 0;
- return (APM_OK);
- }
-
- ercode = APM_normalize(apm);
- if (ercode < APM_OK) {
- return (APM_set_errno(ercode));
- }
-
- for (n = apm->length; n > 0; --n) {
- if (apm->data[n - 1] != 0) {
- break;
- }
- }
-
- if (n < apm->length) {
- apm->length = n;
- }
-
- return (APM_OK);
- }
-
- int
- APM_trimtrail(apm)
- APM apm;
- {
- int n;
- int ercode;
-
- apm_errno = APM_OK;
-
- if (apm == (APM)NULL) {
- return (APM_set_errno(APM_ENULL));
- }
-
- if (apm->data == NULL) {
- apm->length = 0;
- apm->dp = 0;
- return (APM_OK);
- }
-
- ercode = APM_normalize(apm);
- if (ercode < APM_OK) {
- return (APM_set_errno(ercode));
- }
-
- for (n = 0; n < apm->dp; ++n) {
- if (apm->data[n] != 0) {
- break;
- }
- }
-
- if (n == 0) { /* no trailing zeros */
- return (APM_OK);
- }
-
- /*
- * Shift down by 'n', subtracting this from apm->length and
- * apm->dp.
- */
- apm->length -= n;
- apm->dp -= n;
- APM_copy_shorts(apm->data, &(apm->data[n]), apm->length);
- APM_zero_shorts(&(apm->data[apm->length]), n);
-
- return (APM_OK);
- }
-
- int
- APM_trim(apm, lead, trail)
- APM apm;
- int lead;
- int trail;
- {
- int ercode = APM_OK;
-
- apm_errno = APM_OK;
-
- if (apm == (APM)NULL) {
- return (APM_set_errno(APM_ENULL));
- }
-
- if (ercode >= APM_OK && lead) {
- ercode = APM_trimlead(apm);
- }
-
- if (ercode >= APM_OK && trail) {
- ercode = APM_trimtrail(apm);
- }
-
- if (ercode >= APM_OK) {
- ercode = APM_normalize(apm);
- }
-
- return (APM_set_errno(ercode));
- }
-
- int
- APM_normalize(value)
- APM value;
- {
- static short *localData = (short *)NULL;
- static int localLen = 0;
- int len;
- int dp;
- int offset;
- int ercode;
-
- apm_errno = APM_OK;
-
- ercode = APM_val_format(value);
- if (ercode < APM_OK) {
- return (ercode);
- }
- ercode = APM_val_base(value->base);
- if (ercode < APM_OK) {
- return (ercode);
- }
-
- if (value->dp >= 0 && value->length >= value->dp) {
- return (APM_OK);
- }
-
- len = value->length;
- if (value->length < value->dp) {
- len = value->dp;
- dp = value->dp;
- offset = 0;
- }
- else if (value->dp < 0) {
- len = value->length - value->dp;
- dp = 0;
- offset = -(value->dp);
- }
- else {
- len = value->length;
- dp = value->dp;
- offset = 0;
- }
-
- if (len > localLen) {
- int xlen = len;
- if (xlen < 8) {
- xlen = 8;
- }
- localData = (short *)APM_alloc_mem(localLen < 1 ?
- NULL : localData,
- xlen, sizeof (short));
- if (localData == (short *)NULL) {
- return (APM_set_errno(APM_ENOMEM));
- }
- localLen = xlen;
- }
-
- APM_zero_shorts(localData, len);
- APM_copy_shorts(localData + offset, value->data, value->length);
-
- ercode = APM_size(value, len);
- if (ercode < APM_OK) {
- return (ercode);
- }
-
- APM_copy_shorts(value->data, localData, len);
-
- value->length = len;
- value->dp = dp;
-
- return (APM_OK);
- }
-
- int
- APM_setdp(result, value, dp)
- APM result;
- APM value;
- int dp;
- {
- int oldlen;
- int newlen;
- int voffset;
- int roffset;
- int ercode;
-
- apm_errno = APM_OK;
-
- ercode = APM_val_format(value);
- if (ercode < APM_OK) {
- return (ercode);
- }
- ercode = APM_val_base(value->base);
- if (ercode < APM_OK) {
- return (ercode);
- }
- if (result == value) {
- return (APM_set_errno(APM_EOVERLAP));
- }
-
- ercode = APM_normalize(value);
- if (ercode < APM_OK) {
- return (ercode);
- }
-
- if (dp < 0) {
- dp = value->dp;
- }
-
- oldlen = newlen = value->length;
-
- if (dp <= value->dp) {
- voffset = value->dp - dp;
- roffset = 0;
- oldlen -= voffset;
- }
- else {
- voffset = 0;
- roffset = dp - value->dp;
- newlen += roffset;
- }
-
- ercode = APM_size(result, newlen);
- if (ercode < APM_OK) {
- return(ercode);
- }
-
- APM_zero_shorts(result->data, newlen);
- APM_copy_shorts(result->data + roffset, value->data + voffset, oldlen);
-
- result->sign = SIGNOF(value->sign);
- result->base = value->base;
- result->length = newlen;
- result->dp = dp;
- return (APM_OK);
- }
-
- int
- APM_norm_to_spec(apm)
- APM apm;
- {
- static APM localApm = (APM)NULL;
- int length;
- int locallen;
- int localdp;
- int ercode;
- int n;
- short sign;
-
- apm_errno = APM_OK;
-
- if (apm == (APM)NULL) {
- return (APM_set_errno(APM_ENULL));
- }
-
- if (apm->base != 10) {
- return (APM_set_errno(APM_EFMT));
- }
-
- length = apm->length;
- sign = SIGNOF(apm->sign);
- locallen = length;
- localdp = ((apm->dp + (SPECIAL_SCALE - 1)) / SPECIAL_SCALE)
- * SPECIAL_SCALE;
- locallen += (localdp - apm->dp);
- locallen = ((locallen + (SPECIAL_SCALE - 1)) / SPECIAL_SCALE)
- * SPECIAL_SCALE;
-
- if (localApm == (APM)NULL) {
- localApm = APM_alloc();
- if (localApm == (APM)NULL) {
- return (APM_set_errno(APM_ENOMEM));
- }
- }
- ercode = APM_size(localApm, locallen / SPECIAL_SCALE);
- if (ercode < APM_OK) {
- return (ercode);
- }
-
- for (n = 0; n < locallen; n += SPECIAL_SCALE) {
- int value = 0;
- int tn = n + (apm->dp - localdp);
- if (tn >= 0 && tn < length) {
- value += apm->data[tn];
- }
- ++tn;
- if (tn >= 0 && tn < length) {
- value += apm->data[tn] * 10;
- }
- ++tn;
- if (tn >= 0 && tn < length) {
- value += apm->data[tn] * 100;
- }
- ++tn;
- if (tn >= 0 && tn < length) {
- value += apm->data[tn] * 1000;
- }
- localApm->data[n / SPECIAL_SCALE] = value;
- }
- localApm->length = locallen / SPECIAL_SCALE;
- localApm->dp = localdp / SPECIAL_SCALE;
- localApm->sign = sign;
- localApm->base = SPECIAL_BASE;
-
- ercode = apm_assign(apm, localApm);
-
- return (ercode);
- }
-
- int
- APM_spec_to_norm(apm)
- APM apm;
- {
- static APM localApm = (APM)NULL;
- int length;
- int locallen;
- int n;
- int ercode;
- short sign;
-
- apm_errno = APM_OK;
-
- if (apm == (APM)NULL) {
- return (APM_set_errno(APM_ENULL));
- }
-
- if (apm->base != SPECIAL_BASE) {
- return (APM_set_errno(APM_EFMT));
- }
-
- ercode = APM_trim(apm, 1, 1);
- if (ercode < APM_OK) {
- return (APM_set_errno(APM_EFMT));
- }
-
- length = apm->length;
- sign = SIGNOF(apm->sign);
- if (localApm == (APM)NULL) {
- localApm = APM_alloc();
- if (localApm == (APM)NULL) {
- return (APM_set_errno(APM_ENOMEM));
- }
- }
- locallen = length * SPECIAL_SCALE;
- ercode = APM_size(localApm, locallen);
- if (ercode < APM_OK) {
- return (ercode);
- }
- localApm->length = locallen;
- localApm->sign = sign;
- localApm->dp = apm->dp * SPECIAL_SCALE;
- localApm->base = 10;
-
- for (n = 0; n < length; ++n) {
- int tn = n * SPECIAL_SCALE;
- int value = apm->data[n];
- int newvalue = value / 10;
- localApm->data[tn] = value - (newvalue * 10);
- value = newvalue;
- newvalue = value / 10;
- localApm->data[tn + 1] = value - (newvalue * 10);
- value = newvalue;
- newvalue = value / 10;
- localApm->data[tn + 2] = value - (newvalue * 10);
- value = newvalue;
- newvalue = value / 10;
- localApm->data[tn + 3] = value - (newvalue * 10);
- }
- ercode = apm_assign(apm, localApm);
- if (ercode >= APM_OK) {
- ercode = APM_trim(apm, 1, 1);
- }
- return (ercode);
- }
-
- int
- APM_size(apm, len)
- APM apm;
- int len;
- {
- short *temp;
- apm_errno = APM_OK;
-
- if (len < 0) {
- return (APM_set_errno(APM_EPARM));
- }
- if (apm == (APM)NULL) {
- return (APM_set_errno(APM_ENULL));
- }
-
- if (len > apm->alloclen || apm->alloclen < 1) {
- if (len < 8) {
- len = 8;
- }
- if (apm->alloclen < 1) {
- temp = (short *)APM_alloc_mem(NULL, len,
- sizeof (short));
- }
- else {
- temp = (short *)APM_alloc_mem(apm->data, len,
- sizeof (short));
- }
- if (temp == (short *)NULL) {
- return (APM_set_errno(APM_ENOMEM));
- }
- apm->data = temp;
- apm->alloclen = len;
- }
-
- return (APM_OK);
- }
-
- int
- APM_parse_string(apm, string, base)
- APM apm;
- char *string;
- short base;
- {
- static char *localString = NULL;
- static int localLen = 0;
- int ercode;
- int len;
- int dp;
- int special = 0;
- short sign = 1;
- char *temp;
- short *bp;
- char *tp;
-
- apm_errno = APM_OK;
-
- if (apm == (APM)NULL) {
- return (APM_set_errno(APM_ENULL));
- }
-
- if (string == NULL) {
- return (APM_set_errno(APM_ENULLVAL));
- }
-
- if (base == 0) {
- base = SPECIAL_BASE;
- }
-
- ercode = APM_val_base(base);
- if (ercode < APM_OK) {
- return (ercode);
- }
-
- if (base == SPECIAL_BASE) {
- special = 1;
- base = 10;
- }
-
- len = strlen(string);
- if (localString == NULL || localLen < len + 1) {
- int xlen = len + 1;
- if (xlen < 16) {
- xlen = 16;
- }
- localString = APM_alloc_mem(localLen < 1 ? NULL : localString,
- xlen, sizeof (char));
- if (localString == NULL) {
- return (APM_set_errno(APM_ENOMEM));
- }
- localLen = xlen;
- }
- APM_copy_bytes(localString, string, len + 1);
-
- temp = APM_trim_string(APM_left_justify(localString, " \t"));
- if (*temp == '-') {
- sign = -1;
- ++temp;
- }
- else if (*temp == '+') {
- sign = 1;
- ++temp;
- }
-
- dp = APM_radix_pos(temp, base);
- if (dp < 0) {
- return (APM_set_errno(APM_EFMT));
- }
-
- len = strlen(temp);
- if (dp > 0) {
- char *sp = &temp[dp];
- do {
- sp[-1] = *sp;
- } while (*sp++ != '\0');
- --len;
- dp = len - (dp - 1);
- }
-
- ercode = APM_size(apm, len);
- if (ercode < APM_OK) {
- return (ercode);
- }
-
- apm->base = base;
- apm->length = len;
- apm->dp = dp;
- apm->sign = SIGNOF(sign);
- for (bp = apm->data, tp = &temp[len]; tp-- > temp; ++bp) {
- *bp = APM_get_digit(*tp, apm->base);
- }
-
- if (special) {
- ercode = APM_norm_to_spec(apm);
- }
-
- if (ercode >= APM_OK) {
- ercode = APM_trim(apm, 1, 1);
- }
-
- return (ercode);
- }
-
- char *
- APM_build_string(string, data, length, dpos)
- char *string;
- short *data;
- int length;
- int dpos;
- {
- short *bp;
- int n = 0;
-
- for (bp = &(data[length]); bp-- > data; ++n) {
- if (n == dpos) {
- *string++ = '.';
- }
- *string++ = APM_digits[*bp];
- }
- return (string);
- }
-
- int
- APM_parse_long(apm, value, base)
- APM apm;
- long value;
- short base;
- {
- int ercode;
- int n;
- long temp;
-
- apm_errno = APM_OK;
-
- if (apm == (APM)NULL) {
- return (APM_set_errno(APM_ENULL));
- }
-
- if (base == 0) {
- base = SPECIAL_BASE;
- }
- ercode = APM_val_base(base);
- if (ercode < APM_OK) {
- return (ercode);
- }
-
- apm->sign = 1;
- apm->base = base;
- apm->dp = 0;
-
- if (value < 0) {
- apm->sign = -1;
- value = -value;
- }
-
- for (apm->length = 0, temp = value; temp != 0; temp /= base) {
- ++(apm->length);
- }
- if (apm->length == 0) {
- return (APM_OK);
- }
-
- ercode = APM_size(apm, apm->length);
- if (ercode < APM_OK) {
- return (ercode);
- }
-
- for (n = 0; n < apm->length; ++n) {
- apm->data[n] = value % base;
- value /= base;
- }
-
- return (APM_OK);
- }
-
- short
- APM_array_add(result, addend, length, base)
- short *result;
- short *addend;
- int length;
- short base;
- {
- int n;
- short tempval;
- short carry = 0;
-
- for (n = 0; n < length; ++n) {
- tempval = result[n] + carry + addend[n];
- result[n] = tempval % base;
- carry = tempval / base;
- }
-
- return (carry);
- }
-
- short
- APM_array_sub(result, subtrahend, length, base)
- short *result;
- short *subtrahend;
- int length;
- short base;
- {
- int n;
- short tempval;
- short borrow = 0;
-
- for (n = 0; n < length; ++n) {
- tempval = (result[n] + borrow) - subtrahend[n];
- if (tempval < 0) {
- result[n] = tempval + base;
- borrow = -1;
- }
- else {
- result[n] = tempval;
- borrow = 0;
- }
- }
- return (borrow);
- }
-
- short
- APM_scalar_mul(result, multiplicand, length, multiplier, base)
- short *result;
- short *multiplicand;
- int length;
- short multiplier;
- short base;
- {
- int n;
- long tempval;
- short carry = 0;
-
- for (n = 0; n < length; ++n) {
- tempval = multiplicand[n];
- tempval *= multiplier;
- tempval += carry;
- result[n] = (short)(tempval % base);
- carry = (short)(tempval / base);
- }
- return (carry);
- }
-
- int
- APM_scalar_div(result, dividend, length, dp, sign, base, divisor)
- APM result;
- short *dividend;
- int length;
- int dp;
- short sign;
- short base;
- short divisor;
- {
- static APM apmDividend = (APM)NULL;
- static APM apmDivisor = (APM)NULL;
- int ercode;
-
- apm_errno = APM_OK;
-
- if (result == (APM)NULL || dividend == (short *)NULL) {
- return (APM_set_errno(APM_ENULL));
- }
-
- if (apmDividend == (APM)NULL) {
- apmDividend = APM_alloc();
- if (apmDividend == (APM)NULL) {
- return (APM_set_errno(APM_ENOMEM));
- }
- }
- if (apmDivisor == (APM)NULL) {
- apmDivisor = APM_alloc();
- if (apmDivisor == (APM)NULL) {
- return (APM_set_errno(APM_ENOMEM));
- }
- ercode = APM_size(apmDivisor, 1);
- if (ercode < APM_OK) {
- return (ercode);
- }
- apmDivisor->length = 1;
- apmDivisor->dp = 0;
- }
-
- ercode = APM_size(apmDividend, length);
- if (ercode < APM_OK) {
- return (ercode);
- }
- APM_copy_shorts(apmDividend->data, dividend, length);
-
- apmDividend->sign = sign;
- apmDividend->length = length;
- apmDividend->dp = dp;
- apmDividend->base = base;
-
- if (divisor < 0) {
- apmDivisor->data[0] = -divisor;
- apmDivisor->sign = -1;
- }
- else {
- apmDivisor->data[0] = divisor;
- apmDivisor->sign = 1;
- }
- apmDivisor->base = base;
-
- return (apm_divide(result, length, (APM)NULL,
- apmDividend, apmDivisor));
- }
-
- int
- APM_copy_bytes(to, from, num)
- register char *to;
- register char *from;
- int num;
- {
- register int n = num;
-
- if (to == NULL || from == NULL || num <= 0) {
- return (0);
- }
-
- if (to > from) {
- to += n;
- from += n;
- while (n-- > 0) {
- *(--to) = *(--from);
- }
- }
- else if (to < from) {
- while (n-- > 0) {
- *to++ = *from++;
- }
- }
-
- return (num);
- }
-
- int
- APM_zero_bytes(to, num)
- register char *to;
- int num;
- {
- register int n = num;
-
- if (to == NULL || num <= 0) {
- return (0);
- }
-
- while (n-- > 0) {
- *to++ = 0;
- }
-
- return (num);
- }
-
- int
- APM_copy_shorts(to, from, num)
- short *to;
- short *from;
- int num;
- {
- return (APM_copy_bytes((char *)to, (char *)from,
- num * sizeof (short)) / sizeof (short));
- }
-
- int
- APM_zero_shorts(to, num)
- short *to;
- int num;
- {
- return (APM_zero_bytes((char *)to,
- num * sizeof (short)) / sizeof (short));
- }
-
- char *
- APM_index(s, c)
- register char *s;
- int c;
- {
- if (s != NULL) {
- for (; *s != '\0'; ++s) {
- if (*s == (char)c) {
- return (s);
- }
- }
- }
-
- return (NULL);
- }
-
- void
- APM_debug(va_alist)
- va_dcl
- {
- va_list ap;
- char *format;
- FILE *debug_file = apm_debug_file(NULL);
-
- if (debug_file == (FILE *)NULL) {
- return;
- }
-
- (void)apm_debug_file(debug_file);
-
- va_start(ap);
-
- format = va_arg(ap, char *);
- if (format == NULL) {
- return;
- }
-
- vfprintf(debug_file, format, ap);
- fflush(debug_file);
-
- va_end(ap);
- }
-