| [4d61ad0] | 1 | C TREEVERSE MECHANISM V2
|
|---|
| 2 | C ========================
|
|---|
| 3 |
|
|---|
| 4 | c New version of TreeVerse that does not store the entire
|
|---|
| 5 | c reversal sequence, but rather uses a stack automaton to
|
|---|
| 6 | c generate the reversal actions one at a time.
|
|---|
| 7 | c Allows for nested calls to Treeverse, i.e.
|
|---|
| 8 | C nested iterative loops that use treeverse.
|
|---|
| 9 | c Uses a small enough stack,
|
|---|
| 10 | c allowing for 5 nested calls to TRV_INIT,
|
|---|
| 11 | c and for a cumulated number of snapshots of 99.
|
|---|
| 12 |
|
|---|
| 13 | c Usage:
|
|---|
| 14 | c Call TRV_INIT(length, nbSnap, firstStep)
|
|---|
| 15 | c giving to it:
|
|---|
| 16 | c -- the length of the sequence you need to inverse, including the
|
|---|
| 17 | c last step, the one that exits. E.g "do i=1,10" has length 11 !!
|
|---|
| 18 | c -- the number of snapshots your machine can accomodate,
|
|---|
| 19 | c -- the index of the first step in the sequence you need to inverse.
|
|---|
| 20 | c Then repeated calls to TRV_NEXT_ACTION(action, step)
|
|---|
| 21 | c return the successive actions the treeverse loop must perform.
|
|---|
| 22 | c Also return in "step" the time step on which the action operates.
|
|---|
| 23 | c When all actions are done, TRV_NEXT_ACTION returns .FALSE.
|
|---|
| 24 |
|
|---|
| 25 | c Global memory used to remember the state
|
|---|
| 26 | c when the stack automaton runs:
|
|---|
| 27 | c -STACK1 (one level (index is1) per nested treeverse session) :
|
|---|
| 28 | c STACK1(1,is1): index of initial level in STACK2 for this session
|
|---|
| 29 | c STACK1(2,is1): max number of snapshots allowed for this session
|
|---|
| 30 | c STACK1(3,is1): offset for step numbers in this session
|
|---|
| 31 | c -STACK2 (one level (index is2) per nested (simultaneous) snapshot) :
|
|---|
| 32 | c STACK2(1,is2): number of steps to be reversed by this snapshot level
|
|---|
| 33 | c STACK2(2,is2): rank of the current step in STACK2(1,is2)
|
|---|
| 34 | c STACK2(3,is2): rank of the chosen recursive cut in STACK2(1,is2)
|
|---|
| 35 | BLOCK DATA TRV_GLOBAL_DATA
|
|---|
| 36 | INTEGER STACK1(3,5), is1, STACK2(3,99), is2
|
|---|
| 37 | COMMON /TRV_GLOBALS/ STACK1, is1, STACK2, is2
|
|---|
| 38 | DATA is1/0/
|
|---|
| 39 | DATA is2/0/
|
|---|
| 40 | END
|
|---|
| 41 |
|
|---|
| 42 | c Initialize one nested session of treeverse commands,
|
|---|
| 43 | c using at most "nbSnap" snapshots, to reverse a sequence
|
|---|
| 44 | c of length "length", in which the first step in numbered "firstStep"
|
|---|
| 45 | c Does not alter its arguments, but modifies STACK1 and STACK2.
|
|---|
| 46 | SUBROUTINE TRV_INIT(length, nbSnap, firstStep)
|
|---|
| 47 | IMPLICIT NONE
|
|---|
| 48 | INTEGER nbSnap, length, firstStep
|
|---|
| 49 | INTEGER STACK1(3,5), is1, STACK2(3,99), is2
|
|---|
| 50 | COMMON /TRV_GLOBALS/ STACK1, is1, STACK2, is2
|
|---|
| 51 |
|
|---|
| 52 | IF (length.le.0) THEN
|
|---|
| 53 | PRINT*,"Error: Cannot reverse a sequence of length ", length
|
|---|
| 54 | STOP
|
|---|
| 55 | ELSE IF (nbSnap.eq.0.and.length.ge.2) THEN
|
|---|
| 56 | PRINT*,"Error: Cannot reverse a sequence of length ", length,
|
|---|
| 57 | + " with no snapshot"
|
|---|
| 58 | STOP
|
|---|
| 59 | ELSE IF (is1.ge.5.or.is2+nbsnap+1.ge.99) THEN
|
|---|
| 60 | PRINT*,"Error: Treeverse memory exceeded !"
|
|---|
| 61 | STOP
|
|---|
| 62 | ELSE
|
|---|
| 63 | is1 = is1+1
|
|---|
| 64 | is2 = is2+1
|
|---|
| 65 | STACK1(1,is1) = is2
|
|---|
| 66 | STACK1(2,is1) = nbSnap
|
|---|
| 67 | STACK1(3,is1) = firstStep
|
|---|
| 68 | STACK2(1,is2) = length
|
|---|
| 69 | STACK2(2,is2) = 0
|
|---|
| 70 | STACK2(3,is2) = 0
|
|---|
| 71 | END IF
|
|---|
| 72 | END
|
|---|
| 73 |
|
|---|
| 74 | c Finds the next action in the process of reversing the current
|
|---|
| 75 | c sequence of steps, i.e. running the current treeverse session.
|
|---|
| 76 | c Overwrites "action" withthis next action to perform,
|
|---|
| 77 | c and overwrites step with the index of the iteration step
|
|---|
| 78 | c that corresponds to this action. Also returns .TRUE. if there
|
|---|
| 79 | c is such an action waiting, and .FALSE. otherwise, i.e. the
|
|---|
| 80 | c current reversal session is terminated.
|
|---|
| 81 | LOGICAL FUNCTION TRV_NEXT_ACTION(action, step)
|
|---|
| 82 | IMPLICIT NONE
|
|---|
| 83 | INTEGER action, step, i
|
|---|
| 84 | INTEGER STACK1(3,5), is1, STACK2(3,99), is2
|
|---|
| 85 | COMMON /TRV_GLOBALS/ STACK1, is1, STACK2, is2
|
|---|
| 86 | INTEGER PUSHSNAP, LOOKSNAP, POPSNAP, ADVANCE, FIRSTTURN, TURN
|
|---|
| 87 | PARAMETER (PUSHSNAP=1)
|
|---|
| 88 | PARAMETER (LOOKSNAP=2)
|
|---|
| 89 | PARAMETER (POPSNAP=3)
|
|---|
| 90 | PARAMETER (ADVANCE=4)
|
|---|
| 91 | PARAMETER (FIRSTTURN=5)
|
|---|
| 92 | PARAMETER (TURN=6)
|
|---|
| 93 |
|
|---|
| 94 | c Part "only for debug":
|
|---|
| 95 | c PRINT*, ""
|
|---|
| 96 | c PRINT*, "STACK1:"
|
|---|
| 97 | c DO i=is1,1,-1
|
|---|
| 98 | c WRITE(*,910) STACK1(2,i), STACK1(1,i), STACK1(3,i)
|
|---|
| 99 | c ENDDO
|
|---|
| 100 | c PRINT*, "-------------------"
|
|---|
| 101 | c PRINT*, "STACK2:"
|
|---|
| 102 | c DO i=is2,1,-1
|
|---|
| 103 | c WRITE(*,920) i,STACK2(1,i), STACK2(2,i), STACK2(3,i)
|
|---|
| 104 | c ENDDO
|
|---|
| 105 | c PRINT*, "-------------------"
|
|---|
| 106 | c 910 format(i2," snapshots, stack2 bottom:",i2," (offset:",i3,")")
|
|---|
| 107 | c 920 format(i2,": R( ,",i3,") ",i3,"/",i3)
|
|---|
| 108 | c End of "only for debug" part
|
|---|
| 109 |
|
|---|
| 110 | IF (STACK2(1,is2).le.0.and.is2.eq.STACK1(1,is1)) THEN
|
|---|
| 111 | c If we are at the top snapshot level and no step remains to be
|
|---|
| 112 | c reversed, then this inversion session is terminated.
|
|---|
| 113 | c Pop to the enclosing inversion session. Return .FALSE.
|
|---|
| 114 | step = -1
|
|---|
| 115 | action = -1
|
|---|
| 116 | is1 = is1-1
|
|---|
| 117 | is2 = is2-1
|
|---|
| 118 | TRV_NEXT_ACTION = .FALSE.
|
|---|
| 119 | ELSE
|
|---|
| 120 | c compute the index of the step to which the next action
|
|---|
| 121 | c corresponds or will apply:
|
|---|
| 122 | step = 1 ;
|
|---|
| 123 | DO i=STACK1(1,is1)+1,is2
|
|---|
| 124 | step = step+STACK2(2,i)
|
|---|
| 125 | ENDDO
|
|---|
| 126 | IF (STACK2(2,is2).eq.-1) THEN
|
|---|
| 127 | c If the present position is -1, i.e. the current state does not
|
|---|
| 128 | c correspond to the next time step we are going to execute,
|
|---|
| 129 | c then take the correct state back from the snapshot.
|
|---|
| 130 | IF (STACK2(1,is2).eq.1) THEN
|
|---|
| 131 | c POP the snapshot we are at last reversing the 1st step after it...
|
|---|
| 132 | action = POPSNAP
|
|---|
| 133 | ELSE
|
|---|
| 134 | c ... otherwise only LOOK at the snapshot, and keep it for later use.
|
|---|
| 135 | action = LOOKSNAP
|
|---|
| 136 | ENDIF
|
|---|
| 137 | STACK2(2,is2) = 0
|
|---|
| 138 | ELSE
|
|---|
| 139 | c Now the current state corresponds to the next time step to run on.
|
|---|
| 140 | IF (STACK2(2,is2).eq.STACK2(1,is2)-1) THEN
|
|---|
| 141 | c if the current position is just before the end of the current
|
|---|
| 142 | c subsequence to reverse by this snapshot level. Then just TURN ...
|
|---|
| 143 | IF (step.eq.STACK2(1,STACK1(1,is1))) THEN
|
|---|
| 144 | action = FIRSTTURN
|
|---|
| 145 | ELSE
|
|---|
| 146 | action = TURN
|
|---|
| 147 | ENDIF
|
|---|
| 148 | c ... and update the stack, popping the current snapshot level
|
|---|
| 149 | c if its work is finished, i.e. its remaining length to reverse is 0.
|
|---|
| 150 | c Attention do not pop the initial level of the current session.
|
|---|
| 151 | IF (STACK2(2,is2).eq.0.and.is2.gt.STACK1(1,is1)) THEN
|
|---|
| 152 | is2 = is2-1
|
|---|
| 153 | STACK2(1,is2) = STACK2(3,is2)
|
|---|
| 154 | ELSE
|
|---|
| 155 | STACK2(1,is2) = STACK2(2,is2)
|
|---|
| 156 | ENDIF
|
|---|
| 157 | c mark that the current state in memory is out of date
|
|---|
| 158 | STACK2(2,is2) = -1
|
|---|
| 159 | c compute the new position for the deeper level snapshot
|
|---|
| 160 | CALL TRV_SETCUT()
|
|---|
| 161 | ELSE
|
|---|
| 162 | IF (STACK2(2,is2).eq.STACK2(3,is2)) THEN
|
|---|
| 163 | c if we just reached the end of this level advance sequence,
|
|---|
| 164 | c then me must PUSH a snapshot and begin a new nested level of
|
|---|
| 165 | c snapshot in the current reversal session.
|
|---|
| 166 | action = PUSHSNAP
|
|---|
| 167 | is2 = is2+1
|
|---|
| 168 | STACK2(1,is2) = STACK2(1,is2-1)-STACK2(2,is2-1)
|
|---|
| 169 | STACK2(2,is2) = 0
|
|---|
| 170 | CALL TRV_SETCUT()
|
|---|
| 171 | step = step-1
|
|---|
| 172 | ELSE
|
|---|
| 173 | c else we still need to ADVANCE to reach the next checkpoint
|
|---|
| 174 | action = ADVANCE
|
|---|
| 175 | STACK2(2,is2) = STACK2(2,is2)+1
|
|---|
| 176 | ENDIF
|
|---|
| 177 | ENDIF
|
|---|
| 178 | ENDIF
|
|---|
| 179 | TRV_NEXT_ACTION = .TRUE.
|
|---|
| 180 | ENDIF
|
|---|
| 181 | END
|
|---|
| 182 |
|
|---|
| 183 | c Find the index of the next CKP cut at the current checkpoint level.
|
|---|
| 184 | c Store this index into the current STACK2(3, is2).
|
|---|
| 185 | c Computation depends on the current length to reverse STACK2(1, is2)
|
|---|
| 186 | c and of the current number of available snapshots, computed as
|
|---|
| 187 | c STACK1(2,is1)-(is2-STACK1(1,is1))+1, i.e. the initial number of
|
|---|
| 188 | c snapshots for this session, minus the number of used snapshots,
|
|---|
| 189 | c i.e. the number of snapshot levels pushed onto STACK2 (minus 1).
|
|---|
| 190 | c Algorithm is first to find "minRecomp", the minimum number of
|
|---|
| 191 | c recomputations that allow reversing a sequence of this "length",
|
|---|
| 192 | c i.e. such that eta(nbSnap,minRecomp) is greater or equal to length.
|
|---|
| 193 | c By def, eta(nbSnap,recomp)=(nbSnap+recomp)!/(nbSnap!*recomp!)
|
|---|
| 194 | c Then this "minRecomp" defines the proportion of the length
|
|---|
| 195 | c which is before the CKP cut, which is
|
|---|
| 196 | c eta(nbSnap,minRecomp-1)/eta(nbSnap,minRecomp) which is
|
|---|
| 197 | c (by definition of eta) minRecomp/(minRecomp+nbSnap).
|
|---|
| 198 | c We find the cut index that approaches this proportion best.
|
|---|
| 199 | c Assert: length>=1 , nbSnap>=0
|
|---|
| 200 | c Alters the STACKs.
|
|---|
| 201 | SUBROUTINE TRV_SETCUT()
|
|---|
| 202 | IMPLICIT NONE
|
|---|
| 203 | INTEGER STACK1(3,5), is1, STACK2(3,99), is2
|
|---|
| 204 | COMMON /TRV_GLOBALS/ STACK1, is1, STACK2, is2
|
|---|
| 205 | INTEGER length, nbSnap, eta, minRecomp
|
|---|
| 206 |
|
|---|
| 207 | length = STACK2(1,is2)
|
|---|
| 208 | nbSnap = STACK1(2,is1)-(is2-STACK1(1,is1))+1
|
|---|
| 209 | IF (length.le.1) THEN
|
|---|
| 210 | STACK2(3,is2) = 0
|
|---|
| 211 | ELSE IF (nbSnap.eq.1) THEN
|
|---|
| 212 | STACK2(3,is2) = length-1
|
|---|
| 213 | ELSE
|
|---|
| 214 | eta = nbSnap+1
|
|---|
| 215 | minRecomp = 1
|
|---|
| 216 | DO WHILE (eta.LT.length)
|
|---|
| 217 | minRecomp = minRecomp+1
|
|---|
| 218 | eta = (eta*(nbSnap+minRecomp))/minRecomp
|
|---|
| 219 | END DO
|
|---|
| 220 | STACK2(3,is2) = (length*minRecomp)/(minRecomp+nbSnap)
|
|---|
| 221 | IF (STACK2(3,is2).eq.0) THEN
|
|---|
| 222 | STACK2(3,is2) = 1
|
|---|
| 223 | ELSE IF (STACK2(3,is2).ge.length) THEN
|
|---|
| 224 | STACK2(3,is2) = length-1
|
|---|
| 225 | END IF
|
|---|
| 226 | ENDIF
|
|---|
| 227 | END
|
|---|
| 228 |
|
|---|
| 229 | SUBROUTINE TRV_RESIZE()
|
|---|
| 230 | IMPLICIT NONE
|
|---|
| 231 | INTEGER step, i
|
|---|
| 232 | INTEGER STACK1(3,5), is1, STACK2(3,99), is2
|
|---|
| 233 | COMMON /TRV_GLOBALS/ STACK1, is1, STACK2, is2
|
|---|
| 234 |
|
|---|
| 235 | step = 1 ;
|
|---|
| 236 | DO i=STACK1(1,is1)+1,is2
|
|---|
| 237 | step = step+STACK2(2,i)
|
|---|
| 238 | ENDDO
|
|---|
| 239 | WRITE(*,930) "Binomial iteration exits on step",step-1,
|
|---|
| 240 | + " before expected",STACK2(1,STACK1(1,is1))
|
|---|
| 241 | 930 format(a,i6,a,i6)
|
|---|
| 242 | STACK2(1,STACK1(1,is1)) = step-1
|
|---|
| 243 | STACK2(1,is2) = STACK2(2,is2)
|
|---|
| 244 | STACK2(2,is2) = STACK2(2,is2)-1
|
|---|
| 245 | END
|
|---|