mpdivi.f 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. *DECK MPDIVI
  2. SUBROUTINE MPDIVI (X, IY, Z)
  3. C***BEGIN PROLOGUE MPDIVI
  4. C***SUBSIDIARY
  5. C***PURPOSE Subsidiary to DQDOTA and DQDOTI
  6. C***LIBRARY SLATEC
  7. C***TYPE ALL (MPDIVI-A)
  8. C***AUTHOR (UNKNOWN)
  9. C***DESCRIPTION
  10. C
  11. C Divides 'mp' X by the single-precision integer IY giving 'mp' Z.
  12. C This is much faster than division by an 'mp' number.
  13. C
  14. C The arguments X(*) and Z(*), and the variable R in COMMON are all
  15. C INTEGER arrays of size 30. See the comments in the routine MPBLAS
  16. C for the reason for this choice.
  17. C
  18. C***SEE ALSO DQDOTA, DQDOTI, MPBLAS
  19. C***ROUTINES CALLED MPCHK, MPERR, MPNZR, MPSTR, MPUNFL
  20. C***COMMON BLOCKS MPCOM
  21. C***REVISION HISTORY (YYMMDD)
  22. C 791001 DATE WRITTEN
  23. C ?????? Modified for use with BLAS. Blank COMMON changed to named
  24. C COMMON. R given dimension 12.
  25. C 890531 Changed all specific intrinsics to generic. (WRB)
  26. C 891214 Prologue converted to Version 4.0 format. (BAB)
  27. C 900402 Added TYPE section. (WRB)
  28. C 930124 Increased Array size in MPCON for SUN -r8. (RWC)
  29. C***END PROLOGUE MPDIVI
  30. COMMON /MPCOM/ B, T, M, LUN, MXR, R(30)
  31. INTEGER B, T, R, X(*), Z(*), RS, RE, R1, C, C2, B2
  32. C***FIRST EXECUTABLE STATEMENT MPDIVI
  33. RS = X(1)
  34. J = IY
  35. IF (J) 30, 10, 40
  36. 10 WRITE (LUN, 20)
  37. 20 FORMAT (' *** ATTEMPTED DIVISION BY ZERO IN CALL TO MPDIVI ***')
  38. GO TO 230
  39. 30 J = -J
  40. RS = -RS
  41. 40 RE = X(2)
  42. C CHECK FOR ZERO DIVIDEND
  43. IF (RS.EQ.0) GO TO 120
  44. C CHECK FOR DIVISION BY B
  45. IF (J.NE.B) GO TO 50
  46. CALL MPSTR (X, Z)
  47. IF (RE.LE.(-M)) GO TO 240
  48. Z(1) = RS
  49. Z(2) = RE - 1
  50. RETURN
  51. C CHECK FOR DIVISION BY 1 OR -1
  52. 50 IF (J.NE.1) GO TO 60
  53. CALL MPSTR (X, Z)
  54. Z(1) = RS
  55. RETURN
  56. 60 C = 0
  57. I2 = T + 4
  58. I = 0
  59. C IF J*B NOT REPRESENTABLE AS AN INTEGER HAVE TO SIMULATE
  60. C LONG DIVISION. ASSUME AT LEAST 16-BIT WORD.
  61. B2 = MAX(8*B,32767/B)
  62. IF (J.GE.B2) GO TO 130
  63. C LOOK FOR FIRST NONZERO DIGIT IN QUOTIENT
  64. 70 I = I + 1
  65. C = B*C
  66. IF (I.LE.T) C = C + X(I+2)
  67. R1 = C/J
  68. IF (R1) 210, 70, 80
  69. C ADJUST EXPONENT AND GET T+4 DIGITS IN QUOTIENT
  70. 80 RE = RE + 1 - I
  71. R(1) = R1
  72. C = B*(C - J*R1)
  73. KH = 2
  74. IF (I.GE.T) GO TO 100
  75. KH = 1 + T - I
  76. DO 90 K = 2, KH
  77. I = I + 1
  78. C = C + X(I+2)
  79. R(K) = C/J
  80. 90 C = B*(C - J*R(K))
  81. IF (C.LT.0) GO TO 210
  82. KH = KH + 1
  83. 100 DO 110 K = KH, I2
  84. R(K) = C/J
  85. 110 C = B*(C - J*R(K))
  86. IF (C.LT.0) GO TO 210
  87. C NORMALIZE AND ROUND RESULT
  88. 120 CALL MPNZR (RS, RE, Z, 0)
  89. RETURN
  90. C HERE NEED SIMULATED DOUBLE-PRECISION DIVISION
  91. 130 C2 = 0
  92. J1 = J/B
  93. J2 = J - J1*B
  94. J11 = J1 + 1
  95. C LOOK FOR FIRST NONZERO DIGIT
  96. 140 I = I + 1
  97. C = B*C + C2
  98. C2 = 0
  99. IF (I.LE.T) C2 = X(I+2)
  100. IF (C-J1) 140, 150, 160
  101. 150 IF (C2.LT.J2) GO TO 140
  102. C COMPUTE T+4 QUOTIENT DIGITS
  103. 160 RE = RE + 1 - I
  104. K = 1
  105. GO TO 180
  106. C MAIN LOOP FOR LARGE ABS(IY) CASE
  107. 170 K = K + 1
  108. IF (K.GT.I2) GO TO 120
  109. I = I + 1
  110. C GET APPROXIMATE QUOTIENT FIRST
  111. 180 IR = C/J11
  112. C NOW REDUCE SO OVERFLOW DOES NOT OCCUR
  113. IQ = C - IR*J1
  114. IF (IQ.LT.B2) GO TO 190
  115. C HERE IQ*B WOULD POSSIBLY OVERFLOW SO INCREASE IR
  116. IR = IR + 1
  117. IQ = IQ - J1
  118. 190 IQ = IQ*B - IR*J2
  119. IF (IQ.GE.0) GO TO 200
  120. C HERE IQ NEGATIVE SO IR WAS TOO LARGE
  121. IR = IR - 1
  122. IQ = IQ + J
  123. 200 IF (I.LE.T) IQ = IQ + X(I+2)
  124. IQJ = IQ/J
  125. C R(K) = QUOTIENT, C = REMAINDER
  126. R(K) = IQJ + IR
  127. C = IQ - J*IQJ
  128. IF (C.GE.0) GO TO 170
  129. C CARRY NEGATIVE SO OVERFLOW MUST HAVE OCCURRED
  130. 210 CALL MPCHK (1, 4)
  131. WRITE (LUN, 220)
  132. 220 FORMAT (' *** INTEGER OVERFLOW IN MPDIVI, B TOO LARGE ***')
  133. 230 CALL MPERR
  134. Z(1) = 0
  135. RETURN
  136. C UNDERFLOW HERE
  137. 240 CALL MPUNFL(Z)
  138. RETURN
  139. END