subroutine aptmord (i, n, m, ir, nerr) ccbeg. cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc c c SUBROUTINE APTMORD c c call aptmord (i, n, m, ir, nerr) c c Version: aptmord Updated 2003 September 4 17:30. c aptmord Originated 2003 September 4 17:30. c c Authors: Arthur L. Edwards, LLNL, L-298, Telephone (925) 422-4123. c c c Purpose: If the integers i and n have no common factors other than 1, c find the order m of i modulo n, and the multiplicative inverse c ir of i modulo n. c c Flag nerr indicates any input error or limited results. c c Input: i, n. c c Output: m, ir, nerr. c c Calls: aptpfac c c Glossary: c c i Input An integer in arithmetic modulo n. c c ir Output If integers i and n have no common factors other than c 1, ir is the multiplicative inverse of i modulo n, c that is, i * ir = 1 mod n. c Also, ir = i^(m-1) mod n. c If ir exists, it cannot exceed n - 1, and the c multiplicative inverse of ir is i. c Set to -999999999 if none exists. c c m Output If integers i and n have no common factors other than c 1, m is the order of i mod n, that is, the least c power of i such that i^m = 1 mod n. c If m exists, it cannot exceed n - 1, and the c multiplicative inverse ir is i^(m-1) mod n. c Set to -999999999 if none exists. c c n Input The modulus for modular arithmetic. Must be > 1. c c nerr Output Indicates an error or no result, if not zero. c -1 if i has no order in modulo n. m = -999999999. c 0 if i has an order in modulo n. c 1 if n < 2. c 2 if error in aptpfac factoring n. c 3 if error in aptpfac factoring i. c cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc ccend. c.... Declarations for arguments. integer i ! An integer in arithmetic modulo n. integer ir ! The multiplicative inverse of i. integer m ! The order of i mudulo n. integer n ! The modulus for mudular arithmetic. integer nerr ! Error indicator, none if zero. c.... Declarations for local variables. integer ifacti(18) ! A prime factor of im. integer ifactn(18) ! A prime factor of n. integer im ! Normalized i, in range 1 to n - 1. integer ipowi(18) ! Largest power of ifacti(n) dividing i. integer ipown(18) ! Largest power of ifactn(n) dividing n. integer iresi ! Unfactored residue of i. integer iresn ! Unfactored residue of n. integer j ! Index in arrays ifacti, ipowi. integer k ! Index in arrays ifactn, ipown. integer ncomm ! The number of factors im and n share. integer nerrn ! Indicates aptpfac error, if not zero. integer nerri ! Indicates aptpfac error, if not zero. integer nfacti ! Number of prime factors of im found. integer nfactn ! Number of prime factors of n found. integer nfcomm(18) ! A factor i and n have in common. integer npi ! Index in arrays ifacti, ipowi. integer npn ! Index in arrays ifactn, ipown. integer ntoti ! Euler's totient function for mod i. integer ntotn ! Euler's totient function for mod n. cbugc***DEBUG begins. cbug 9901 format (/ 'aptmord finding order and inverse of' / cbug & ' integer',i12,' in modulus',i12 ) cbug write ( 3, 9901) i, n cbugc***DEBUG ends. c.... Initialize. nerr = 0 m = -999999999 ir = -999999999 c.... Test for input errors. if (n .lt. 2) then nerr = 1 go to 210 endif c.... Move i to the range from 0 to n - 1, if necessary, with new name im. im = mod (i, n) if (im .lt. 0) im = im + n np = 1 imp = im cbugcbugc***DEBUG begins. cbugcbug 9801 format ('DEBUG. np =',i12,' imp =',i12) cbugcbug write ( 3, 9801) np, imp cbugcbug ntoti = -999999999 cbugcbug ntotn = -999999999 cbugcbugc***DEBUG ends. c.... Find factors and Euler's totient function of n. cbugcbugc***DEBUG begins. cbugcbug 9921 format (/ 'aptpfac finding prime factors of n =',i12 ) cbugcbug write ( 3, 9921) n cbugcbugc***DEBUG ends. call aptpfac (n, 18, ifactn, ipown, nfactn, ntotn, iresn, nerrn) cbugcbugc***DEBUG begins. cbugcbug 9922 format (/ 'aptpfac found',i12,' factors. nerr =',i3,'.' ) cbugcbug 9923 format (' k =',i3,' ifactn(k) =',i22,'^',i2) cbugcbug 9924 format (' Totient function n ',i12) cbugcbug 9925 format (' Unfactored residue =',i12) cbugcbug write ( 3, 9922) nfactn, nerrn cbugcbug if (nfactn .gt. 0) then cbugcbug write ( 3, 9923) (k, ifactn(k), ipown(k), k = 1, nfactn) cbugcbug endif cbugcbug write ( 3, 9924) ntotn cbugcbug if (nerrn .eq. 3) then cbugcbug write ( 3, 9925) iresn cbugcbug endif cbugcbugc***DEBUG ends. if (nerrn .ne. 0) then nerr = 2 go to 210 endif c.... See if im = 0. if (im .eq. 0) then nerr = -1 go to 210 endif c.... See if im = 1. if (im .eq. 1) then m = 1 ir = 1 go to 210 endif c.... Find factors and Euler's totient function of i and n. cbugcbugc***DEBUG begins. cbugcbug 9911 format (/ 'aptpfac finding prime factors of i =',i12 ) cbugcbug write ( 3, 9911) i cbugcbugc***DEBUG ends. call aptpfac (i, 18, ifacti, ipowi, nfacti, ntoti, iresi, nerri) cbugcbugc***DEBUG begins. cbugcbug 9912 format (/ 'aptpfac found',i12,' factors. nerri =',i3,'.' ) cbugcbug 9913 format (' n =',i3,' ifacti(n) =',i22,'^',i2) cbugcbug 9914 format (' Totient function i ',i12) cbugcbug 9915 format (' Unfactored residue =',i12) cbugcbug write ( 3, 9912) nfacti, nerri cbugcbug if (nfacti .gt. 0) then cbugcbug write ( 3, 9913) (j, ifacti(j), ipowi(j), j = 1, nfactn) cbugcbug endif cbugcbug write ( 3, 9914) ntoti cbugcbug if (nerri .eq. 3) then cbugcbug write ( 3, 9915) iresi cbugcbug endif cbugcbugc***DEBUG ends. if (nerri .ne. 0) then nerr = 3 go to 210 endif c.... Find any common factors of n and im. ncomm = 0 ndiff = 0 do 120 ki = 1, nfacti do 110 kn = 1, nfactn if (ifacti(ki) .eq. ifactn(kn)) then ncomm = ncomm + 1 nfcomm(ncomm) = ifacti(ki) endif 110 continue 120 continue cbugcbugc***DEBUG begins. cbugcbug 9331 format ('DEBUG common factors:' / (4i12)) cbugcbug if (ncomm .gt. 0) then cbugcbug write ( 3, 9331) (nfcomm(kk), kk = 1, ncomm) cbugcbug endif cbugcbugc***DEBUG ends. if (ncomm .ne. 0) then ! No order possible. nerr = -1 go to 210 endif c.... Find any order of im mod n. do 150 np = 2, ntotn implast = imp imp = imp * im imp = mod (imp, n) cbugcbugc***DEBUG begins. cbugcbug write ( 3, 9801) np, imp cbugcbugc***DEBUG ends. if (imp .eq. 1) then ! Found an order. m = np ir = implast go to 210 endif if (imp .eq. 0) then ! Repeating zero. go to 210 endif if (imp .eq. implast) then ! Repeating value not 1 or zero. go to 210 endif 150 continue 210 continue cbugc***DEBUG begins. cbug 9902 format (/ 'aptmord results: nerr =',i3, cbug & ' order =',i12,' inverse =',i12 ) cbug write ( 3, 9902) nerr, m, ir cbugc***DEBUG ends. return c.... End of subroutine aptmord. (+1 line.) end UCRL-WEB-209832