aboutsummaryrefslogtreecommitdiff
path: root/sys/plio/plrio.x
diff options
context:
space:
mode:
authorJoe Hunkeler <jhunkeler@gmail.com>2015-08-11 16:51:37 -0400
committerJoe Hunkeler <jhunkeler@gmail.com>2015-08-11 16:51:37 -0400
commit40e5a5811c6ffce9b0974e93cdd927cbcf60c157 (patch)
tree4464880c571602d54f6ae114729bf62a89518057 /sys/plio/plrio.x
downloadiraf-osx-40e5a5811c6ffce9b0974e93cdd927cbcf60c157.tar.gz
Repatch (from linux) of OSX IRAF
Diffstat (limited to 'sys/plio/plrio.x')
-rw-r--r--sys/plio/plrio.x350
1 files changed, 350 insertions, 0 deletions
diff --git a/sys/plio/plrio.x b/sys/plio/plrio.x
new file mode 100644
index 00000000..0cf2b8d9
--- /dev/null
+++ b/sys/plio/plrio.x
@@ -0,0 +1,350 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <syserr.h>
+include <plio.h>
+
+.help PLRIO
+.nf ---------------------------------------------------------------------------
+PLRIO -- A small package used to provide a means for efficient random
+sampling (at the pixel level) of large PLIO masks. In other words, if we have
+a large mask and want to determine the values of successive mask pixels at
+random locations in the mask, this package provides a more efficient means
+for doing so than calling a routine such as PL_GLPI. The mask must already
+exist; means are not provided within this package for creating or editing
+masks, only for reading them.
+
+ plr = plr_open (pl, plane, buflimit)
+ plr_setrect (plr, x1,y1, x2,y2)
+ mval = plr_getpix (plr, x, y)
+ plr_getlut (plr, bufp, xsize,ysize, xblock,yblock)
+ plr_close (plr)
+
+PLR_OPEN opens the indicated 2 dimensional plane of the N dimensional mask PL.
+Buffer space used to provide an efficient means of randomly sampling the mask
+will be kept to within approximately BUFLIMIT integer units of storage (the
+internal table used to sample the mask is type integer, so BUFLIMIT is the
+approximate number of entries in the table). Random sampling of the mask is
+provided by the integer function PLR_GETPIX, which returns the mask value at
+the point [i,j] within the specified plane. PLR_SETRECT may be called before
+calling PLR_GETPIX to set the clipping rectangle, which defaults to the
+boundaries of the mask. If a PLR_GETPIX call references outside the clipping
+region, ERR will be returned as the mask value (normal mask values are >= 0).
+Use of a clipping region other than the boundaries of the full mask can avoid
+the need for redundant clipping operations in the client. For cases when
+even the function call overhead of PLR_GETPIX is too much, the lookup table
+may be directly accessed via a call to PLR_GETLUT. Table references which
+resolve to a negative valued table entry should call PLR_GETPIX to get the
+mask value, otherwise the table value is the mask value. PLR_CLOSE should
+be called to free the PLRIO table space (which can be extensive) when no longer
+needed.
+.endhelp ----------------------------------------------------------------------
+
+define DEF_BUFLIMIT (128*128) # internal buffer size
+define LEN_STACK (4*32) # max mask size = 2**LEN_STACK
+
+# If any of the following are changed check that pmio$pmrio.x is consistent.
+define LEN_PLRDES 20
+define PLR_PL Memi[$1] # main PLIO descriptor
+define PLR_NCOLS Memi[$1+1] # table width
+define PLR_NLINES Memi[$1+2] # table height
+define PLR_XBLOCK Memi[$1+3] # table blocking factor, X
+define PLR_YBLOCK Memi[$1+4] # table blocking factor, Y
+define PLR_BUFP Memi[$1+5] # buffer pointer
+define PLR_X1 Memi[$1+6] # clipping rectangle
+define PLR_Y1 Memi[$1+7] # clipping rectangle
+define PLR_X2 Memi[$1+8] # clipping rectangle
+define PLR_Y2 Memi[$1+9] # clipping rectangle
+define PLR_PLANE Memi[$1+10+($2)-1] # plane to be accessed
+
+define COMPLEX -1 # table bin -> compex region
+define LEN_REGDES 4 # region descriptor
+define V1 Memi[$1+($2)-1]
+define V2 Memi[$1+2+($2)-1]
+
+
+# PLR_OPEN -- Open a PLIO mask for random pixel access. Provides efficient
+# random pixel level access to any size mask. This is a 2-dimensional
+# operator, but can be used to sample any 2-dim plane of an N-dim mask.
+
+pointer procedure plr_open (pl, plane, buflimit)
+
+pointer pl #I PLIO descriptor
+int plane[ARB] #I 2-dim plane to be accessed
+int buflimit #I approximate table size, or 0 if don't care
+
+int v1[PL_MAXDIM], v2[PL_MAXDIM]
+int maxpix, ndim, npix, mval, i, j
+int msize[2], tsize[2], block[2], vm[2]
+pointer sp, stack, plr, bufp, el, rp
+errchk calloc, malloc, plvalid
+bool pl_sectnotconst()
+
+begin
+ call plvalid (pl)
+ call smark (sp)
+ call salloc (stack, LEN_STACK * LEN_REGDES, TY_STRUCT)
+
+ # Allocate the PLRIO descriptor.
+ call calloc (plr, LEN_PLRDES, TY_STRUCT)
+
+ # Set the plane to be accessed.
+ ndim = PL_NAXES(pl)
+ do i = 1, 2
+ msize[i] = PL_AXLEN(pl,i)
+
+ do i = 1, PL_MAXDIM
+ if (i > ndim) {
+ PLR_PLANE(pl,i) = 1
+ v1[i] = 1
+ v2[i] = 1
+ } else if (i > 2) {
+ PLR_PLANE(pl,i) = plane[i]
+ v1[i] = plane[i]
+ v2[i] = plane[i]
+ }
+
+ # Get the maximum table size in pixels.
+ if (buflimit <= 0)
+ maxpix = DEF_BUFLIMIT
+ else
+ maxpix = buflimit
+
+ # Determine the blocking factors required to keep the lookup table
+ # within the given size limit.
+
+ block[1] = 1; block[2] = 1
+ while ((msize[1] / block[1]) * (msize[2] / block[2]) > maxpix)
+ do i = 1, 2
+ block[i] = min (msize[i], block[i]*2)
+
+ # Compute the lookup table size.
+ do i = 1, 2
+ tsize[i] = (msize[i] + block[i]-1) / block[i]
+
+ # Allocate the table space.
+ call malloc (bufp, tsize[1] * tsize[2], TY_INT)
+
+ # Compute the lookup table. Since the lookup table can be large,
+ # e.g., a quarter million elements for a 512sq table, we don't want
+ # to directly compute the value of each bufp[i,j]. Instead, we examine
+ # a region of the table, starting with the entire table, and if the
+ # corresponding region of the mask is not filled with the same mask
+ # value, we divide the region into 4 quadrants and examine each in
+ # turn, and so on until the nonconstant regions are the size of one
+ # table bin (pixel), which we conclude maps to a COMPLEX (nonconstant)
+ # region of the mask. By this technique, only table bins which map
+ # to complex mask regions need be evaluated, and entire large regions
+ # of the mask are quickly dealt with.
+
+ # Push the entire mask area on the stack as the first region.
+ el = stack
+ do i = 1, 2 {
+ V1(el,i) = 1
+ V2(el,i) = tsize[i]
+ }
+
+ repeat {
+ # Get the mask coordinates of the next region on the stack.
+ do i = 1, 2 {
+ v1[i] = (V1(el,i) - 1) * block[i] + 1
+ v2[i] = min (msize[i], V2(el,i) * block[i])
+ }
+
+ # Examine the region to see if the associated region of the mask
+ # consists entirely of a single mask value.
+
+ if (pl_sectnotconst (pl, v1, v2, ndim, mval)) {
+ if (V1(el,1) == V2(el,1) && V1(el,2) == V2(el,2)) {
+ # This single table pixel maps to a complex mask region.
+ Memi[bufp+(V1(el,2)-1)*tsize[1]+V1(el,1)-1] = COMPLEX
+
+ } else {
+ # Divide the nonzero mask region into four quadrants
+ # and recursively examine each in turn.
+
+ # Compute the coordinates of the central pixel in vm.
+ do i = 1, 2
+ vm[i] = (V1(el,i) + V2(el,i) + 1) / 2
+
+ # Save the currently stacked region in v1/v2.
+ v1[1] = V1(el,1); v1[2] = V1(el,2)
+ v2[1] = V2(el,1); v2[2] = V2(el,2)
+
+ if ((el-stack)/LEN_REGDES+4 >= LEN_STACK)
+ call syserrs (SYS_PLSTKOVFL, "plr_open")
+
+ # Push the four quadrants of this region on the stack.
+ # If the region we are subdividing is only one pixel
+ # wide in either axis then only two of the regions will
+ # be valid. The invalid regions will have zero pixels
+ # in one axis or the other, i.e. (v2[i] < v1[i]). If
+ # a region is invalid discard it by not advancing the
+ # stack pointer.
+
+ V1(el,1) = v1[1]; V1(el,2) = vm[2]
+ V2(el,1) = vm[1]-1; V2(el,2) = v2[2]
+ if (V1(el,1) <= V2(el,1) && V1(el,2) <= V2(el,2))
+ el = el + LEN_REGDES
+
+ V1(el,1) = vm[1]; V1(el,2) = vm[2]
+ V2(el,1) = v2[1]; V2(el,2) = v2[2]
+ if (V1(el,1) <= V2(el,1) && V1(el,2) <= V2(el,2))
+ el = el + LEN_REGDES
+
+ V1(el,1) = v1[1]; V1(el,2) = v1[2]
+ V2(el,1) = vm[1]-1; V2(el,2) = vm[2]-1
+ if (V1(el,1) <= V2(el,1) && V1(el,2) <= V2(el,2))
+ el = el + LEN_REGDES
+
+ V1(el,1) = vm[1]; V1(el,2) = v1[2]
+ V2(el,1) = v2[1]; V2(el,2) = vm[2]-1
+ if (V1(el,1) <= V2(el,1) && V1(el,2) <= V2(el,2))
+ el = el + LEN_REGDES
+ }
+ } else {
+ # Set entire region to a constant mask value.
+ npix = V2(el,1) - V1(el,1) + 1
+ do j = V1(el,2), V2(el,2) {
+ rp = bufp + (j-1) * tsize[1] + V1(el,1) - 1
+ if (npix == 1) {
+ Memi[rp] = mval
+ } else if (npix < 8) {
+ do i = 1, npix
+ Memi[rp+i-1] = mval
+ } else {
+ if (mval == 0)
+ call aclri (Memi[rp], npix)
+ else
+ call amovki (mval, Memi[rp], npix)
+ }
+ }
+ }
+
+ # Pop stack.
+ el = el - LEN_REGDES
+
+ } until (el < stack)
+
+ # Initialize the PLRIO descriptor.
+ PLR_PL(plr) = pl
+ PLR_NCOLS(plr) = tsize[1]
+ PLR_NLINES(plr) = tsize[2]
+ PLR_XBLOCK(plr) = block[1]
+ PLR_YBLOCK(plr) = block[2]
+ PLR_BUFP(plr) = bufp
+ PLR_X1(plr) = 1
+ PLR_Y1(plr) = 1
+ PLR_X2(plr) = msize[1]
+ PLR_Y2(plr) = msize[2]
+
+ call sfree (sp)
+ return (plr)
+end
+
+
+# PLR_GETPIX -- Return the value of the given mask pixel, identified by the
+# 2-dim coordinates of the pixel relative to the plane of the N-dim mask
+# specified at open time.
+
+int procedure plr_getpix (plr, i, j)
+
+pointer plr #I PLR descriptor
+int i, j #I plane-relative coordinates of pixel
+
+pointer pl, ll_src
+int ii, jj, mval, np
+pointer pl_access()
+int pl_l2pi()
+errchk pl_access
+
+begin
+ # Clip to the specified region of the mask.
+ if (i < PLR_X1(plr) || i > PLR_X2(plr))
+ return (ERR)
+ if (j < PLR_Y1(plr) || j > PLR_Y2(plr))
+ return (ERR)
+
+ # Map mask pixel coordinates to lookup table bin.
+ ii = (i - 1) / PLR_XBLOCK(plr)
+ jj = (j - 1) / PLR_YBLOCK(plr)
+
+ # Get the lookup table value of the given bin.
+ mval = Memi[PLR_BUFP(plr)+jj*PLR_NCOLS(plr)+ii]
+
+ # Access the original mask to get value if complex region.
+ if (mval == COMPLEX) {
+ pl = PLR_PL(plr)
+ PLR_PLANE(plr,2) = j
+ ll_src = pl_access (pl, PLR_PLANE(plr,1))
+ np = pl_l2pi (Mems[ll_src], i, mval, 1)
+ }
+
+ return (mval)
+end
+
+
+# PLR_GETLUT -- Obtain the buffer pointer and scaling information of the
+# internal lookup table, so that direct table references may be made to
+# minimize overhead in particularly demanding applications. This is not
+# recommended unless absolutely necessary, as PLR_GETPIX is easier and
+# safer to use and nearly as efficient. The strategy for using the table
+# is to use the blocking factors and XSIZE to map a 2dim mask coordinate
+# into a table offset, and access the table to get the table value.
+# If this is negative PLR_GETPIX should be called to compute the mask
+# value, else the table value is the mask value.
+
+procedure plr_getlut (plr, bufp, xsize,ysize, xblock,yblock)
+
+pointer plr #I PLR descriptor
+pointer bufp #O lookup table buffer pointer (int *)
+int xsize,ysize #O table size
+int xblock,yblock #O blocking factors
+
+begin
+ bufp = PLR_BUFP(plr)
+ xsize = PLR_NCOLS(plr)
+ ysize = PLR_NLINES(plr)
+ xblock = PLR_XBLOCK(plr)
+ yblock = PLR_YBLOCK(plr)
+end
+
+
+# PLR_SETRECT -- Set the clipping region for PLR_GETPIX.
+
+procedure plr_setrect (plr, x1,y1, x2,y2)
+
+pointer plr #I PLR descriptor
+int x1,y1 #I lower left corner of region
+int x2,y2 #I upper right corner of region
+
+pointer pl
+define oob_ 91
+errchk syserrs
+
+begin
+ pl = PLR_PL(plr)
+
+ if (x1 < 1 || x1 > PL_AXLEN(pl,1))
+ goto oob_
+ if (x2 < 1 || x2 > PL_AXLEN(pl,1))
+ goto oob_
+ if (y1 < 1 || y1 > PL_AXLEN(pl,2))
+ goto oob_
+ if (y2 < 1 || y2 > PL_AXLEN(pl,2))
+oob_ call syserrs (SYS_PLREFOOB, "plr_setrect")
+
+ PLR_X1(plr) = x1; PLR_Y1(plr) = y1
+ PLR_X2(plr) = x2; PLR_Y2(plr) = y2
+end
+
+
+# PLR_CLOSE -- Free a PLRIO descriptor.
+
+procedure plr_close (plr)
+
+pointer plr #I PLR descriptor
+
+begin
+ call mfree (PLR_BUFP(plr), TY_INT)
+ call mfree (plr, TY_STRUCT)
+end