subroutine aptbsub (nbase, idiga, ndiga, idigb, ndigb, & idigcw, ndigm, idigc, ndigc, isign, nerr) ccbeg. cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc c c SUBROUTINE APTBSUB c c call aptbsub (nbase, idiga, ndiga, idigb, ndigb, c & idigcw, ndigm, idigc, ndigc, isign, nerr) c c Version: aptbsub Updated 2006 May 19 15:20. c aptbsub Originated 2005 May 23 14:50. c c Author: Arthur L. Edwards, LLNL, L-298, Telephone (925) 422-4123. c c c Purpose: To subtract from big integer "a", big integer "b", stored as the c arrays of non-negative base nbase digits idiga and idigb, of c lengths ndiga and ndigb, respectively, to get the big c integer "c", stored as the array of non-negative base nbase c digits idigc, of length ndigc. If "c" is negative, c isign is returned as -1. c c The digits of idiga, idigb and idigc are the base nbase c digits representing the non-negative decimal integers ideca, c idecb and idecc, in order from most significant to least c significant, using the equations: c ideca = sum (idiga(n) * nbase**(N-n), n = 1, N = ndiga). c idecb = sum (idigb(n) * nbase**(N-n), n = 1, N = ndigb). c idecc = sum (idigc(n) * nbase**(N-n), n = 1, N = ndigc). c c Flag nerr indicates any input error. c c See aptbtod, aptdtob, aptbadd, aptbmul, aptbdiv, aptbpow, c aptbrtn, aptbfac. c c Input: nbase, idiga, ndiga, idigb, ndigb, idigcw, ndigm. c c Output: idigc, ndigc, isign, nerr. c c Glossary: c c idiga Input A big integer "a", stored as an array of ndiga c non-negative base nbase digits, in order from most c to least significant. If nbase exceeds 10, each c "digit" may require 2 or more integers. For example, c for decimal integer 4821, nbase = 16 (hexadecimal), c idiga(n) = (5, 13, 2, 1), with ndiga = 4, or c 4821 (dec) = 5 * 1 + 13 * 16 + 2 * 256 + 1 * 4096 c c idigb Input See idiga. Array idigb may be idiga or idigc. c c idigc Input See idiga. Array idigc may be idiga or idigb. c Big integer "c" is "a" - "b", unless isign = -1, c when "c" is "b" - "a". c c idigcw Input Temporary working space for idigc. See idiga. c Array idigcw must not be idiga, idigb or idigc, c but must have its own memory space, which must be c at least ndigm. c c isign Output The sign of the result, +1 if "a" => "b", c -1 if "b" > "a". c c nbase Input The number base for which the digits of integer arrays c idiga, idigb and idigc are the coefficients of c the powers of nbase, in order from most to least c significant. c c ndiga Input The length of the integer array idiga. c c ndigb Input The length of the integer array idigb. c c ndigc Output The length of the integer array idigc. c If "a" = "b", ndigc = 1, with idigc(1) = 0. c c ndigm Input The maximum number of words allowed in integer array c idigc. Memory space for idigc must be at least c ndigm, and ndigm must be at least as big as c max (ndiga, ndigb). c c nerr Output Indicates an input or a result error, if not zero. c -1 if "b" is bigger than "a". c 1 if nbase is less than 2. c 2 if ndiga is not positive. c 3 if any digits of idiga are negative. c 4 if ndigb is not positive. c 5 if any digits of idigb are negative. c 6 if ndigm is less than 1 + max (ndiga, ndigb). c cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc ccend. implicit none c.... Arguments. integer idiga(1) ! Digits of big integer "a". integer idigb(1) ! Digits of big integer "b". integer idigc(1) ! Digits of big integer "c". integer idigcw(1) ! Digits of big integer "cw". integer isign ! -1 if "b" exceedds "a". integer nbase ! Number base of "a", "b", "c", "cw". integer ndiga ! Number of digits of big integer "a". integer ndigb ! Number of digits of big integer "b". integer ndigc ! Number of digits of big integer "c". integer ndigm ! Max number of digits of big integers. integer nerr ! Non-zero if input error(s) found. c.... Local variables. integer icarry ! Integer carried to next digit. integer itotal ! Digit difference plus carry. integer n ! Index in arrays. integer na ! Index in array "a". integer nb ! Index in array "b". integer ndigcw ! Number of digits of big integer "cw". integer nmax ! Max number of digits in big integer "c". integer nw ! Index in array "cw". cbugc***DEBUG begins. cbug 9900 format (/) cbug 9901 format (/ 'aptbsub subtracting the base nbase digit array', cbug & ' idigb from idiga' / cbug & ' to get base nbase digit array idigc.' / cbug & ' nbase =',i7,', ndiga =',i7,', ndigb =',i7,'.' ) cbug 9902 format (' a n =',i7,', idiga =',i7,'.') cbug 9903 format (' b n =',i7,', idigb =',i7,'.') cbug write ( 3, 9901) nbase, ndiga, ndigb cbug write ( 3, 9900) cbug write ( 3, 9902) (n, idiga(n), n = 1, ndiga) cbug write ( 3, 9900) cbug write ( 3, 9903) (n, idigb(n), n = 1, ndigb) cbugc***DEBUG ends. c.... Test for input errors. nerr = 0 if (nbase .lt. 2) then nerr = 1 go to 210 endif if (ndiga .lt. 0) then nerr = 2 go to 210 endif if (ndiga .gt. 0) then do n = 1, ndiga if (idiga(n) .lt. 0) then nerr = 3 go to 210 endif enddo endif if (ndigb .lt. 0) then nerr = 4 go to 210 endif if (ndigb .gt. 0) then do n = 1, ndigb if (idigb(n) .lt. 0) then nerr = 5 go to 210 endif enddo endif nmax = max (ndiga, ndigb) if (nmax .gt. ndigm) then nerr = 6 go to 210 endif c.... Initialize. isign = 1 c.... Initialize temporary difference "cw". ndigcw = 1 do n = 1, ndigm idigcw(n) = 0 enddo c.... Subtract "b" from "a" to get temporary difference "cw". icarry = 0 do n = 1, nmax na = ndiga + 1 - n nb = ndigb + 1 - n itotal = icarry if ((na .ge. 1) .and. (na .le. ndiga)) then itotal = itotal + idiga(na) endif if ((nb .ge. 1) .and. (nb .le. ndigb)) then itotal = itotal - idigb(nb) endif if (itotal .lt. 0) then itotal = itotal + nbase icarry = -1 else icarry = 0 endif idigcw(n) = itotal if (idigcw(n) .gt. 0) then ndigcw = n endif enddo if (icarry .eq. -1) then isign = -1 nerr = -1 ndigcw = 1 do n = 1, nmax idigcw(n) = nbase - idigcw(n) - 1 if (idigcw(n) .gt. 0) then ndigcw = n endif enddo idigcw(1) = idigcw(1) + 1 endif if (ndigcw .eq. 0) then ndigcw = 1 idigcw(1) = 0 endif c.... Convert temporary difference "cw" to base nbase. icarry = 0 do nw = 1, ndigcw itotal = idigcw(nw) + icarry idigcw(nw) = mod (itotal, nbase) icarry = itotal / nbase enddo if (icarry .ne. 0) then ndigcw = ndigcw + 1 idigcw(ndigcw) = icarry endif if (ndigcw .eq. 0) then ndigcw = 1 idigcw(1) = 0 endif c.... Store reversed difference "cw" into "c". Zero out "cw". ndigc = ndigcw do n = 1, ndigc idigc(ndigc+1-n) = idigcw(n) idigcw(n) = 0 enddo 210 continue if (nerr .gt. 0) then ndigc = 0 do n = 1, ndigm idigc(n) = -999999 enddo endif cbugc***DEBUG begins. cbug 9700 format (/) cbug 9911 format (/ 'aptbsub results: nerr =',i2,', ndigc =',i7, cbug & ', isign =',i2,'.') cbug 9913 format (' a-b n =',i7,', idigc =',i7,'.') cbug write ( 3, 9911) nerr, ndigc, isign cbug write ( 3, 9700) cbug write ( 3, 9913) (n, idigc(n), n = 1, ndigc) cbugc***DEBUG ends. return c.... End of subroutine aptbsub. (+1 line.) end UCRL-WEB-209832