To clarify all this talk of operators which push and pull, here are a few
samples of code to show exactly what pushing and pulling mean from an
operator design perspective. Below is the computational part of
the subroutine `nmo1` from Jon's book *Basic Earth Imaging*.

do iz= 1, n {z = t0 + dt*(iz-1) xs = x * slow(iz) t = sqrt ( z * z + xs * xs ) + 1.e-20 wt = z/t * (1./sqrt(t)) #weighting function it = 1 + .5 + (t - t0) / dt if( it <= n ) if( conj == 0 ) tt(it) = tt(it) + zz(iz) * wt else zz(iz) = zz(iz) + tt(it) * wt }

One can see that in both the forward (`conj == 0` ) and adjoint
operation, a loop over `z` (which represents vertical travel time
) is performed. This means that each sample along the zero
offset trace is visited once. Time *t* is calculated and nearest-neighbor
interpolation is performed to find the correct sample along the non-zero
offset trace. A given sample along the non-zero offset trace may be
visited multiple times or not at all.

An alternative is to use two subroutines. The first performs the adjoint
operation exactly as above (I will avoid reprinting it and just
say that the differences are that there is no test for `conj`,
and the weighting function is different).
The second subroutine performs the forward operation. In the
forward operation, discretizing in the output space means looping
over time *t*.

do it= 2, n { t = t0 + dt*(it-1) xs = x * slow(it) z = sqrt ( t * t - xs * xs ) iz = 1 + .5 + (z - t0) / dt if( iz >=1 ) tt(it) = tt(it) + zz(iz) * z/t }

Here the non-zero offset trace is sampled evenly, just as the zero-offset
trace is above. There is, however, one serious complication to the
computation shown directly above. Calculating `z` requires knowing
the velocity as a function of travel time *t* rather than vertical
travel time . The equation for moveout in a vertically varying
velocity field doesn't permit an explicit solution for *v*(*t*). This
is an important future project. For now I stick to constant velocity.

11/12/1997