aboutsummaryrefslogtreecommitdiff
path: root/sys/plio/plr2l.gx
diff options
context:
space:
mode:
Diffstat (limited to 'sys/plio/plr2l.gx')
-rw-r--r--sys/plio/plr2l.gx130
1 files changed, 130 insertions, 0 deletions
diff --git a/sys/plio/plr2l.gx b/sys/plio/plr2l.gx
new file mode 100644
index 00000000..d0a98e92
--- /dev/null
+++ b/sys/plio/plr2l.gx
@@ -0,0 +1,130 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <plset.h>
+include <plio.h>
+
+# PL_R2L -- Convert a range list to a line list. The length of the output
+# line list is returned as the function value.
+
+int procedure pl_r2l$t (rl_src, xs, ll_dst, npix)
+
+PIXEL rl_src[3,ARB] #I input range list
+int xs #I starting pixel index in range list
+short ll_dst[ARB] #O destination line list
+int npix #I number of pixels to convert
+
+PIXEL hi, pv
+int last, xe, x1, x2, iz, op, np, nz, nr, dv, v, i
+define done_ 91
+
+begin
+ # No input pixels?
+ nr = RL_LEN(rl_src)
+ if (npix <= 0 || nr <= 0)
+ return (0)
+
+ # Initialize the linelist header.
+ LL_VERSION(ll_dst) = LL_CURVERSION
+ LL_HDRLEN(ll_dst) = LL_CURHDRLEN
+ LL_NREFS(ll_dst) = 0
+ LL_SETBLEN(ll_dst,0)
+
+ xe = xs + npix - 1
+ op = LL_CURHDRLEN + 1
+ iz = xs
+ hi = 1
+
+ # Process the array of range lists.
+ do i = RL_FIRST, nr + 1 {
+ if (i <= nr) {
+ # Load next range.
+ x1 = rl_src[1,i]
+ np = rl_src[2,i]
+ pv = rl_src[3,i]
+ x2 = x1 + np - 1
+ last = x2
+
+ # Get an inbounds range.
+ if (x1 > xe)
+ break
+ else if (xs > x2)
+ next
+ else if (x1 < xs)
+ x1 = xs
+ else if (x2 > xe)
+ x2 = xe
+
+ # Go again if nothing inbounds.
+ nz = x1 - iz
+ np = x2 - x1 + 1
+ if (np <= 0)
+ next
+
+ } else if (iz < xe) {
+ # At end of input range list, but need to output a ZN.
+ nz = xe - iz + 1
+ np = 0
+ pv = 0
+ } else
+ break
+
+ # Encode an instruction to regenerate the current range I0-IP
+ # of N data values of nonzero level PV. In the most complex case
+ # we must update the high value and output a range of zeros,
+ # followed by a range of NP high values. If NP is 1, we can
+ # probably use a PN or [ID]S instruction to save space.
+
+ # Change the high value?
+ if (pv > 0) {
+ dv = pv - hi
+ if (dv != 0) {
+ # Output IH or DH instruction?
+ hi = pv
+ if (abs(dv) > I_DATAMAX) {
+ ll_dst[op] = M_SH + and (int(pv), I_DATAMAX)
+ op = op + 1
+ ll_dst[op] = pv / I_SHIFT
+ op = op + 1
+ } else {
+ if (dv < 0)
+ ll_dst[op] = M_DH + (-dv)
+ else
+ ll_dst[op] = M_IH + dv
+ op = op + 1
+
+ # Convert to IS or DS if range is a single pixel.
+ if (np == 1 && nz == 0) {
+ v = ll_dst[op-1]
+ ll_dst[op-1] = or (v, M_MOVE)
+ goto done_
+ }
+ }
+ }
+ }
+
+ # Output range of zeros to catch up to current range?
+ if (nz > 0) {
+ # Output the ZN instruction.
+ for (; nz > 0; nz = nz - (I_DATAMAX-1)) {
+ ll_dst[op] = M_ZN + min(I_DATAMAX-1,nz)
+ op = op + 1
+ }
+ # Convert to PN if range is a single pixel.
+ if (np == 1 && pv > 0 && x2 == last) {
+ ll_dst[op-1] = ll_dst[op-1] + M_PN + 1
+ goto done_
+ }
+ }
+
+ # The only thing left is the HN instruction if we get here.
+ for (; np > 0; np = np - I_DATAMAX) {
+ ll_dst[op] = M_HN + min(I_DATAMAX,np)
+ op = op + 1
+ }
+done_
+ iz = x2 + 1
+ }
+
+ LL_SETLEN(ll_dst, op - 1)
+ return (op - 1)
+end