function [ZZ] = extendZ(Z,n,m,np)
% this function takes a 2-D array (matrix Z[n,m]) and extends it in all
% directions by enlarging by np points (rows and columns) in all
% directions.  The values are extended from the closest point at the 
% edges of the original array.  In this way, the matrix is "padded" with 
% reasonable values so that a 2-D convolutional operator of size 2*np-1
% (square; odd dimmension such as 3x3 [np=1], 5x5 [np=2], or 7x7 [np=3])
% can be used to filter the entire array with minimal edge effects.  When 
% applying the convolution operator, use the form:
% ZF = conv2(ZZ,F,'valid') where ZZ is the enlarged original matrix, F is
% the filter and ZF is the filtered array that will be the same size as the
% original Z array.  
nZZ = n+2*np;
mZZ = m+2*np;
ZZ = zeros(nZZ,mZZ); % preassign size of ZZ
% form central portion of ZZ by copying Z
for i = np+1:n+np
    for j = np+1:m+np
        ZZ(i,j) = Z(i-np,j-np);
    end
end
% lower edge
for i = 1:np
    for j = np+1:m+np
        ZZ(i,j) = Z(1,j-np);
    end
end
% upper edge
for i = n+np+1:n+np+np
    for j = np+1:m+np
        ZZ(i,j) = Z(n,j-np);
    end
end
% left edge
for i = 1+np:n+np
    for j = 1:np
        ZZ(i,j) = Z(i-np,1);
    end
end
% right edge
for i = 1+np:n+np
    for j = m+np+1:m+2*np
        ZZ(i,j) = Z(i-np,m);
    end
end
% lower left hand corner
for i = 1:np
    for j = 1:np
        ZZ(i,j) = Z(1,1);
    end
end
% upper left hand corner
for i = n+np+1:n+2*np
    for j = 1:np
        ZZ(i,j) = Z(n,1);
    end
end
% lower right hand corner
for i = 1:np
    for j = m+np+1:m+2*np
        ZZ(i,j) = Z(1,m);
    end
end
% upper right hand corner
for i = n+np+1:n+2*np
    for j = m+np+1:m+2*np
        ZZ(i,j) = Z(n,m);
    end
end
% end of extendZ