subroutine aptbfac (nbase, idiga, ndiga, idigf, idigg, idigbw, & idiggw, ndigm, idigb, ndigb, nerr) ccbeg. cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc c c SUBROUTINE APTBFAC c c call aptbfac (nbase, idiga, ndiga, idigf, idigg, idigbw, c idiggw, ndigm, idigb, ndigb, nerr) c c Version: aptbfac Updated 2006 May 19 14:20. c aptbfac Originated 2005 June 7 15:20. c c Author: Arthur L. Edwards, LLNL, L-298, Telephone (925) 422-4123. c c c Purpose: To find the factorial function of the big integer "a", stored as c the array of non-negative base nbase digits idiga, of length c ndiga, and store the result as the array of non-negative base c nbase digits idigb, of length ndigb. Integer arrays idigf c and idigg, of length ndigm, are needed for intermediate c results. c c The digits of idiga and idigb are the base nbase c digits representing the non-negative decimal integers ideca c and idecb, 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 idecb = ideca!. c c Working arrays idigf, idigg, idiggw and idigbw are needed for c intermediate results, and must each have its own memory space, c of length ndigm or more. c c Flag nerr indicates any input error. c c See aptbtod, aptdtob, aptbadd, aptbsub, aptbmul, aptbdiv, c aptbrev, aptbrtn, aptbfac. c c Input: nbase, idiga, ndiga, idigf, idigg, idigbw, idiggw, ndigm. c c Output: idigb, ndigb, nerr. c c Calls: aptbmul, aptbsub c c Glossary: c c idiga Input A big integer "a", stored as an array of ndiga c non-negative base nbase digits, each representing a c single "digit" in the base nbase representation of c "a", from most to least significant. If nbase > 10, c each "digit" may require 2 or more integers. c For example, for decimal integer 4821 and c nbase = 16 (hexadecimal), idiga(n) = (5, 13, 2, 1), c with ndiga = 4, or c 4821 (dec) = 5 * 1 + 13 * 16 + 2 * 256 + 1 * 4096 c Big integer "a" must not be negative. c c idigb Output See idiga. Big integer "b" is the factorial function c of "a". c c idigf-h Input See idiga. Arrays idigf, idigg, idiggw and idigbw are c needed for temporary results, and must each have its c own memory space, at least ndigm. c c nbase Input The number base for which the digits of integer arrays c idiga, idigf, idigg and idigb are the c coefficients of the powers of nbase, in order from c most to least significant. c c ndiga Input The length of the integer array idiga. c c ndigb Output The length of the integer array idigb. c Must be at big enough for the factorial of "a". c c ndigm Input The maximum number of words allowed in integer arrays c idiga, idigf, idigg, idigbw and idigb. Memory space c for idigf must be at least ndiga, and for idigg c and idigb at least ndigm, and ndigm must be big c enough to contain all of the digits of the factorial c of "a". c c nerr Output Indicates an input or a result error, if not zero. c 1 if nbase is less than 2. c 2 if ndiga is negative. c 3 if any digits idiga are negative. c 4 if ndigm is too small. c cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc ccend. c.... Dimensioned arguments. integer idiga(1) ! Big integer "a". integer idigb(1) ! Factorial of "a". integer idigbw(1) ! Temporary "b", the factorial of "a". integer idigf(1) ! Current factor. integer idigg(1) ! Current result, "f" - 1. integer idiggw(1) ! Working space for aptbmul. c.... Local variables. integer n ! Index in big number array. cbugc***DEBUG begins. cbug 9900 format (/) cbug 9901 format (/ 'aptbfac finding factorial of the base nbase =',i7 / cbug & ' digit array idiga of length',i7 / cbug & ' to get base nbase digit array idigb.' / cbug & ' ndigm =',i7,'.') cbug 9902 format ('nbug=',i3,' a n =',i7,', idiga =',i7,'.') cbug write ( 3, 9901) nbase, ndiga, ndigm cbug nbug = 0 cbug if (ndiga .ne. 0) then cbug write ( 3, 9900) cbug write ( 3, 9902) (nbug, n, idiga(n), n = 1, ndiga) cbug endif cbugc***DEBUG ends. c.... Initialize. 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 .ge. 1) then do n = 1, ndiga if (idiga(n) .lt. 0) then nerr = 3 go to 210 endif enddo endif c.... Initialize. ndigbw = 1 ndigf = 1 ndiggw = 1 ndigg = 1 do n = 1, ndigm idigbw(n) = 0 idigf(n) = 0 idiggw(n) = 0 idigg(n) = 0 enddo cbugcbugc***DEBUG begins. cbugcbug 9974 format ('nbug=',i3,' bw n =',i7,', idigbw =',i7,'.') cbugcbug 9976 format ('nbug=',i3,' f n =',i7,', idigf =',i7,'.') cbugcbug 9977 format ('nbug=',i3,' gw n =',i7,', idiggw =',i7,'.') cbugcbug 9978 format ('nbug=',i3,' g n =',i7,', idigg =',i7,'.') cbugcbug nbug = 1 cbugcbug if (ndigbw .ne. 0) then cbugcbug write ( 3, 9900) cbugcbug write ( 3, 9974) (nbug, n, idigbw(n), n = 1, ndigbw) cbugcbug endif cbugcbug if (ndigf .ne. 0) then cbugcbug write ( 3, 9900) cbugcbug write ( 3, 9976) (nbug, n, idigf(n), n = 1, ndigf) cbugcbug endif cbugcbug if (ndigg .ne. 0) then cbugcbug write ( 3, 9900) cbugcbug write ( 3, 9978) (nbug, n, idigg(n), n = 1, ndigg) cbugcbug endif cbugcbugc***DEBUG ends. c.... Find "b", the factorial of "a". c.... Test for "a" = 0. The factorial of zero is 1. if ((ndiga .eq. 0) .or. & ((ndiga .eq. 1) .and. (idiga(1) .eq. 0))) then ndigbw = 1 idigbw(1) = 1 cbugcbugc***DEBUG begins. cbugcbug nbug = 2 cbugcbug if (ndigbw .ne. 0) then cbugcbug write ( 3, 9900) cbugcbug write ( 3, 9974) (nbug, n, idigbw(n), n = 1, ndigbw) cbugcbug endif cbugcbugc***DEBUG ends. go to 210 endif cbugcbugc***DEBUG begins. cbugcbug nbug = 3 cbugcbug if (ndigbw .ne. 0) then cbugcbug write ( 3, 9900) cbugcbug write ( 3, 9974) (nbug, n, idigbw(n), n = 1, ndigbw) cbugcbug endif cbugcbugc***DEBUG ends. c.... Put "a" (reversed) into "bw" and "f". ndigbw = ndiga ndigf = ndiga do n = 1, ndiga na = ndiga + 1 - n idigbw(n) = idiga(na) idigf(n) = idiga(na) enddo cbugcbugc***DEBUG begins. cbugcbug nbug = 4 cbugcbug if (ndiga .ne. 0) then cbugcbug write ( 3, 9900) cbugcbug write ( 3, 9902) (nbug, n, idiga(n), n = 1, ndiga) cbugcbug endif cbugcbug if (ndigbw .ne. 0) then cbugcbug write ( 3, 9900) cbugcbug write ( 3, 9974) (nbug, n, idigbw(n), n = 1, ndigbw) cbugcbug endif cbugcbug if (ndigf .ne. 0) then cbugcbug write ( 3, 9900) cbugcbug write ( 3, 9976) (nbug, n, idigf(n), n = 1, ndigf) cbugcbug endif cbugcbugc***DEBUG ends. c.... Return here for each factor. nfact = 1 110 nfact = nfact + 1 cbugcbugc***DEBUG begins. cbugcbug 9777 format (/ 'nfact=',i5) cbugcbug write ( 3, 9777) nfact cbugcbugc***DEBUG ends. c.... Change "f" to most significant digit first. call aptbrev (idigf, ndigf, nerrb) cbugcbugc***DEBUG begins. cbugcbug nbug = 5 cbugcbug if (ndigf .ne. 0) then cbugcbug write ( 3, 9900) cbugcbug write ( 3, 9976) (nbug, n, idigf(n), n = 1, ndigf) cbugcbug endif cbugcbugc***DEBUG ends. c.... Subtract 1 from factor "f" to get factor "g". call aptbsub (nbase, idigf, ndigf, 1, 1, idiggw, ndigm, & idigg, ndigg, isign, nerra) cbugcbugc***DEBUG begins. cbugcbug nbug = 6 cbugcbug if (ndigf .ne. 0) then cbugcbug write ( 3, 9900) cbugcbug write ( 3, 9976) (nbug, n, idigf(n), n = 1, ndigf) cbugcbug endif cbugcbug if (ndigg .ne. 0) then cbugcbug write ( 3, 9900) cbugcbug write ( 3, 9978) (nbug, n, idigg(n), n = 1, ndigg) cbugcbug endif cbugcbugc***DEBUG ends. c.... Change "f", "g" to least significant digit first. call aptbrev (idigf, ndigf, nerrb) call aptbrev (idigg, ndigg, nerrb) cbugcbugc***DEBUG begins. cbugcbug nbug = 7 cbugcbug if (ndigf .ne. 0) then cbugcbug write ( 3, 9900) cbugcbug write ( 3, 9976) (nbug, n, idigf(n), n = 1, ndigf) cbugcbug endif cbugcbug if (ndigg .ne. 0) then cbugcbug write ( 3, 9900) cbugcbug write ( 3, 9978) (nbug, n, idigg(n), n = 1, ndigg) cbugcbug endif cbugcbugc***DEBUG ends. c.... Stop when "g" is 1. if ((ndigg .eq. 1) .and. (idigg(1) .eq. 0)) then go to 210 endif c.... Put new factor "g" into old factor "f". ndigf = ndigg do n = 1, ndigg idigf(n) = idigg(n) enddo cbugcbugc***DEBUG begins. cbugcbug nbug = 8 cbugcbug if (ndigg .ne. 0) then cbugcbug write ( 3, 9900) cbugcbug write ( 3, 9978) (nbug, n, idigg(n), n = 1, ndigg) cbugcbug endif cbugcbug if (ndigf .ne. 0) then cbugcbug write ( 3, 9900) cbugcbug write ( 3, 9976) (nbug, n, idigf(n), n = 1, ndigf) cbugcbug endif cbugcbugc***DEBUG ends. c.... Change "bw" and "f" to most significant digit first. call aptbrev (idigbw, ndigbw, nerrb) call aptbrev (idigf, ndigf, nerrb) cbugcbugc***DEBUG begins. cbugcbug nbug = 9 cbugcbug if (ndigbw .ne. 0) then cbugcbug write ( 3, 9900) cbugcbug write ( 3, 9974) (nbug, n, idigbw(n), n = 1, ndigbw) cbugcbug endif cbugcbug if (ndigf .ne. 0) then cbugcbug write ( 3, 9900) cbugcbug write ( 3, 9976) (nbug, n, idigf(n), n = 1, ndigf) cbugcbug endif cbugcbugc***DEBUG ends. c.... Find new product "g" = "bw" * "f". call aptbmul (nbase, idigbw, ndigbw, idigf, ndigf, idiggw, ndigm, & idigg, ndigg, nerra) cbugcbugc***DEBUG begins. cbugcbug nbug = 10 cbugcbug if (ndigg .ne. 0) then cbugcbug write ( 3, 9900) cbugcbug write ( 3, 9978) (nbug, n, idigg(n), n = 1, ndigg) cbugcbug endif cbugcbugc***DEBUG ends. c.... Change "bw", "f" and "g" (if OK) to least significant digit first. call aptbrev (idigbw, ndigbw, nerrb) call aptbrev (idigf, ndigf, nerrb) cbugcbugc***DEBUG begins. cbugcbug nbug = 11 cbugcbug if (ndigbw .ne. 0) then cbugcbug write ( 3, 9900) cbugcbug write ( 3, 9974) (nbug, n, idigbw(n), n = 1, ndigbw) cbugcbug endif cbugcbug if (ndigf .ne. 0) then cbugcbug write ( 3, 9900) cbugcbug write ( 3, 9976) (nbug, n, idigf(n), n = 1, ndigf) cbugcbug endif cbugcbugc***DEBUG ends. c.... Test for too many digits in "g". if (nerra .eq. 0) then call aptbrev (idigg, ndigg, nerrb) cbugcbugc***DEBUG begins. cbugcbug nbug = 12 cbugcbug if (ndigg .ne. 0) then cbugcbug write ( 3, 9900) cbugcbug write ( 3, 9978) (nbug, n, idigg(n), n = 1, ndigg) cbugcbug endif cbugcbugc***DEBUG ends. else nerr = 4 go to 210 endif cbugcbugc***DEBUG begins. cbugcbug if (nerra .ne. 0) then cbugcbug write ( 3, 9911) nerra, ndigbw cbugcbug endif cbugcbug nbug = 13 cbugcbug if (ndigbw .ne. 0) then cbugcbug write ( 3, 9900) cbugcbug write ( 3, 9974) (nbug, n, idigbw(n), n = 1, ndigbw) cbugcbug endif cbugcbug if (ndigf .ne. 0) then cbugcbug write ( 3, 9900) cbugcbug write ( 3, 9976) (nbug, n, idigf(n), n = 1, ndigf) cbugcbug endif cbugcbug if (ndigg .ne. 0) then cbugcbug write ( 3, 9900) cbugcbug write ( 3, 9978) (nbug, n, idigg(n), n = 1, ndigg) cbugcbug endif cbugcbugc***DEBUG ends. c.... Put product "g" into "bw". ndigbw = ndigg do n = 1, ndigg idigbw(n) = idigg(n) enddo cbugcbugc***DEBUG begins. cbugcbug nbug = 14 cbugcbug if (ndigg .ne. 0) then cbugcbug write ( 3, 9900) cbugcbug write ( 3, 9978) (nbug, n, idigg(n), n = 1, ndigg) cbugcbug endif cbugcbugc***DEBUG ends. c.... Repeat until done. go to 110 210 continue c.... Put final product "bw" into factorial "b". if (nerr .eq. 0) then ndigb = ndigbw do n = 1, ndigb nb = ndigb + 1 - n idigb(nb) = idigbw(n) enddo endif cbugcbugc***DEBUG begins. cbugcbug nbug = 15 cbugcbug if (ndigbw .ne. 0) then cbugcbug write ( 3, 9900) cbugcbug write ( 3, 9974) (nbug, n, idigbw(n), n = 1, ndigbw) cbugcbug endif cbugcbug if (ndigb .ne. 0) then cbugcbug write ( 3, 9900) cbugcbug write ( 3, 9913) (nbug, n, idigb(n), n = 1, ndigb) cbugcbug endif cbugcbugc***DEBUG ends. c.... Zero out working arrays. ndigbw = 1 ndigf = 1 ndigg = 1 ndiggw = 1 do n = 1, ndigm idigbw(n) = 0 idigf(n) = 0 idigg(n) = 0 idiggw(n) = 0 enddo if (nerr .ne. 0) then ndigb = 0 do n = 1, ndigm idigb(n) = -999999 enddo endif cbugc***DEBUG begins. cbug 9911 format (/ 'aptbfac results: nerr=',i2,', ndigb =',i7,'.') cbug 9913 format (' a! n =',i7,', idigb =',i7,'.') cbug write ( 3, 9911) nerr, ndigb cbug if (ndigb .ne. 0) then cbug write ( 3, 9900) cbug write ( 3, 9913) (nbug, n, idigb(n), n = 1, ndigb) cbug endif cbugc***DEBUG ends. return c.... End of subroutine aptbfac. (+1 line.) end UCRL-WEB-209832