rsspice/generated/spicelib/lnkxsl.rs
1//
2// GENERATED FILE
3//
4
5use super::*;
6use crate::SpiceContext;
7use f2rust_std::*;
8
9pub const LBPOOL: i32 = -5;
10const SIZROW: i32 = 1;
11const SIZCOL: i32 = 0;
12const NFRROW: i32 = 2;
13const NFRCOL: i32 = 0;
14const FREROW: i32 = 1;
15const FRECOL: i32 = -1;
16const FORWRD: i32 = 1;
17const BCKWRD: i32 = 2;
18const FREE: i32 = 0;
19
20/// LNK, extract sublist from list
21///
22/// Extract a specified sublist from a list.
23///
24/// # Brief I/O
25///
26/// ```text
27///  VARIABLE  I/O  DESCRIPTION
28///  --------  ---  --------------------------------------------------
29///  HEAD,
30///  TAIL       I   Head and tail nodes of a sublist to be extracted.
31///  POOL      I-O  A doubly linked list pool.
32/// ```
33///
34/// # Detailed Input
35///
36/// ```text
37///  HEAD,
38///  TAIL     are, respectively, the head and tail nodes of a
39///           sublist to be extracted.
40///
41///  POOL     is a doubly linked list pool.
42/// ```
43///
44/// # Detailed Output
45///
46/// ```text
47///  POOL     is the input pool, with the following
48///           modifications:
49///
50///              -- The sublist bounded by HEAD and
51///                 by TAIL is now a separate list from
52///                 the list that originally contained it.
53///
54///              If on input, HEAD was preceded by the node
55///              PREV, and tail was followed by the node
56///              NEXT, then on output
57///
58///              -- The successor of PREV is NEXT.
59///              -- The predecessor of NEXT is PREV.
60/// ```
61///
62/// # Parameters
63///
64/// ```text
65///  LBPOOL   is the lower bound of the column indices of the POOL
66///           array. The columns indexed LBPOOL to 0 are reserved
67///           as a control area for the pool.
68/// ```
69///
70/// # Exceptions
71///
72/// ```text
73///  1)  If either of HEAD or TAIL are not valid node numbers, the
74///      error SPICE(INVALIDNODE) is signaled. POOL will not be
75///      modified.
76///
77///  2)  If either of HEAD or TAIL are valid node numbers but are not
78///      allocated, the error SPICE(UNALLOCATEDNODE) is signaled. POOL
79///      will not be modified.
80///
81///  3)  If TAIL cannot be reached by forward traversal of the list
82///      containing HEAD, the error SPICE(INVALIDSUBLIST) is signaled.
83///      POOL will not be modified.
84/// ```
85///
86/// # Particulars
87///
88/// ```text
89///  Extracting a sublist from a list is necessary when a list is
90///  to be re-arranged in some way. For example, to move a node
91///  in a list to the head of the list, the node (which is a
92///  singleton sublist) is first extracted from the list containing
93///  it, then inserted before the head of the list.
94/// ```
95///
96/// # Examples
97///
98/// ```text
99///  1)  Let POOL be a doubly linked list pool, and let
100///
101///         9 <--> 8 <--> 4 <--> 2000 <--> 1
102///
103///      be a list in POOL. To extract the sublist
104///
105///         4 <--> 2000
106///
107///      the call
108///
109///         CALL LNKXSL ( 4, 2000, POOL )
110///
111///      can be used. After the call is made, POOL will contain the
112///      separate lists
113///
114///         9 <--> 8 <--> 1
115///
116///      and
117///
118///         4 <--> 2000
119///
120///
121///  2)  Let POOL be a doubly linked list pool, and let
122///
123///         9 <--> 8 <--> 4 <--> 2000 <--> 1
124///
125///      be a list in POOL. To move the node 2000 to the
126///      head of the list, the code fragment
127///
128///         CALL LNKXSL ( 2000, 2000, POOL )
129///         CALL LNKILB ( 2000, 9,    POOL )
130///
131///      can be used. The resulting list will be
132///
133///         2000 <--> 9 <--> 8 <--> 4 <--> 1
134/// ```
135///
136/// # Restrictions
137///
138/// ```text
139///  1)  Linked list pools must be initialized via the routine
140///      LNKINI. Failure to initialize a linked list pool
141///      will almost certainly lead to confusing results.
142/// ```
143///
144/// # Author and Institution
145///
146/// ```text
147///  N.J. Bachman       (JPL)
148///  J. Diaz del Rio    (ODC Space)
149///  W.L. Taber         (JPL)
150/// ```
151///
152/// # Version
153///
154/// ```text
155/// -    SPICELIB Version 1.0.1, 24-NOV-2021 (JDR)
156///
157///         Edited the header to comply with NAIF standard.
158///
159/// -    SPICELIB Version 1.0.0, 19-DEC-1995 (NJB) (WLT)
160/// ```
161pub fn lnkxsl(
162    ctx: &mut SpiceContext,
163    head: i32,
164    tail: i32,
165    pool: &mut [[i32; 2]],
166) -> crate::Result<()> {
167    LNKXSL(head, tail, pool.as_flattened_mut(), ctx.raw_context())?;
168    ctx.handle_errors()?;
169    Ok(())
170}
171
172//$Procedure LNKXSL ( LNK, extract sublist from list  )
173pub fn LNKXSL(HEAD: i32, TAIL: i32, POOL: &mut [i32], ctx: &mut Context) -> f2rust_std::Result<()> {
174    let mut POOL = DummyArrayMut2D::new(POOL, 1..=2, LBPOOL..);
175    let mut NEXT: i32 = 0;
176    let mut NODE: i32 = 0;
177    let mut PREV: i32 = 0;
178
179    //
180    // Local parameters
181    //
182
183    //
184    // The control area contains 3 elements.  They are:
185    //
186    //    The "size" of the pool, that is, the number
187    //    of nodes in the pool.
188    //
189    //    The number of free nodes in the pool.
190    //
191    //    The "free pointer," which is the column index of the first free
192    //    node.
193    //
194    // Parameters defining the row and column indices of these control
195    // elements are given below.
196    //
197
198    //
199    // Each assigned node consists of a backward pointer and a forward
200    // pointer.
201    //
202    //    +-------------+       +-------------+       +-------------+
203    //    |  forward--> |       |  forward--> |       |  forward--> |
204    //    +-------------+  ...  +-------------+  ...  +-------------+
205    //    | <--backward |       | <--backward |       | <--backward |
206    //    +-------------+       +-------------+       +-------------+
207    //
208    //        node 1                 node I              node SIZE
209    //
210    //
211    //
212
213    //
214    // Free nodes say that that's what they are.  The way they say it
215    // is by containing the value FREE in their backward pointers.
216    // Needless to say, FREE is a value that cannot be a valid pointer.
217    //
218
219    //
220    // Local variables
221    //
222
223    //
224    // HEAD and TAIL must be valid node numbers.  These nodes
225    // must be allocated as well.
226    //
227    if ((((HEAD < 1) || (HEAD > POOL[[SIZROW, SIZCOL]])) || (TAIL < 1))
228        || (TAIL > POOL[[SIZROW, SIZCOL]]))
229    {
230        CHKIN(b"LNKXSL", ctx)?;
231        SETMSG(b"HEAD was #.  TAIL was #. Valid range is 1 to #.", ctx);
232        ERRINT(b"#", HEAD, ctx);
233        ERRINT(b"#", TAIL, ctx);
234        ERRINT(b"#", POOL[[SIZROW, SIZCOL]], ctx);
235        SIGERR(b"SPICE(INVALIDNODE)", ctx)?;
236        CHKOUT(b"LNKXSL", ctx)?;
237        return Ok(());
238    } else if ((POOL[[BCKWRD, HEAD]] == FREE) || (POOL[[BCKWRD, TAIL]] == FREE)) {
239        CHKIN(b"LNKXSL", ctx)?;
240        SETMSG(b"Node HEAD: node number = #; backward pointer = #;  forward pointer = #. Node TAIL: node number = #; backward pointer = #;  forward pointer = #. (\"FREE\" is #)", ctx);
241        ERRINT(b"#", HEAD, ctx);
242        ERRINT(b"#", POOL[[BCKWRD, HEAD]], ctx);
243        ERRINT(b"#", POOL[[FORWRD, HEAD]], ctx);
244        ERRINT(b"#", TAIL, ctx);
245        ERRINT(b"#", POOL[[BCKWRD, TAIL]], ctx);
246        ERRINT(b"#", POOL[[FORWRD, TAIL]], ctx);
247        ERRINT(b"#", FREE, ctx);
248        SIGERR(b"SPICE(UNALLOCATEDNODE)", ctx)?;
249        CHKOUT(b"LNKXSL", ctx)?;
250        return Ok(());
251    }
252
253    //
254    // Starting at HEAD, search forward, looking for TAIL (apologies to
255    // ZZ Top).
256    //
257    NODE = HEAD;
258
259    while ((NODE != TAIL) && (NODE > 0)) {
260        NODE = POOL[[FORWRD, NODE]];
261    }
262
263    //
264    // If we didn't find TAIL, that's an error.
265    //
266    if (NODE != TAIL) {
267        CHKIN(b"LNKXSL", ctx)?;
268        SETMSG(
269            b"Node # cannot be found by forward traversal, starting at node #.",
270            ctx,
271        );
272        ERRINT(b"#", TAIL, ctx);
273        ERRINT(b"#", HEAD, ctx);
274        SIGERR(b"SPICE(INVALIDSUBLIST)", ctx)?;
275        CHKOUT(b"LNKXSL", ctx)?;
276        return Ok(());
277    }
278
279    //
280    // We reached TAIL.  Extract the sublist between HEAD and TAIL
281    // inclusive.
282    //
283    // Find the predecessor of HEAD and the successor of TAIL.
284    //
285    PREV = POOL[[BCKWRD, HEAD]];
286    NEXT = POOL[[FORWRD, TAIL]];
287
288    //
289    // If the input list did not start with HEAD, then we must update
290    // the forward pointer of the tail node, as well as the backward
291    // pointer of the head node, of the sublist that preceded HEAD.
292    //
293    if (PREV > 0) {
294        //
295        // Update the forward pointer of PREV with the forward pointer of
296        // TAIL.
297        //
298        // If TAIL had a successor, the predecessor of HEAD will now
299        // point forward to it.  If TAIL was the tail of the input list,
300        // the forward pointer of TAIL was the negative of the head of
301        // the input list---this is the correct forward pointer for the
302        // predecessor of HEAD in this case, since the predecessor of
303        // HEAD will become the tail of the main list after the sublist
304        // ranging from HEAD to TAIL is removed.
305        //
306        POOL[[FORWRD, PREV]] = NEXT;
307
308        //
309        // If TAIL is the tail of the input list, we must update the
310        // backward pointer of the head of the input list to point to
311        // the negative of the new tail of the list, which now is PREV.
312        //
313        if (NEXT <= 0) {
314            //
315            // In this case, we can read off the number of the head
316            // node from NEXT:  it is just -NEXT.
317            //
318            POOL[[BCKWRD, -NEXT]] = -PREV;
319        }
320    }
321
322    //
323    // The portion of the input list that preceded HEAD (if such
324    // portion existed) has now been taken care of.
325    //
326    // We now must perform the analogous updates to the portion of
327    // the input list that followed TAIL.
328    //
329    // If the input list did not end with TAIL, then we must update
330    // the backward pointer of the head node, as well as the forward
331    // pointer of the tail node, of the sublist that followed TAIL.
332    //
333    if (NEXT > 0) {
334        //
335        // Update the backward pointer of NEXT with the backward pointer
336        // of HEAD.
337        //
338        // If HEAD had a predecessor, the successor of TAIL will now
339        // point backward to it.  If HEAD was the head of the input list,
340        // the backward pointer of HEAD was the negative of the tail of
341        // the input list---this is the correct backward pointer for the
342        // successor of TAIL in this case, since the successor of TAIL
343        // will become the head of the main list after the sublist
344        // ranging from HEAD to TAIL is removed.
345        //
346        POOL[[BCKWRD, NEXT]] = PREV;
347
348        //
349        // If HEAD is the head of the input list, we must update the
350        // forward pointer of the tail of the input list to point to
351        // the negative of the new head of the list, which now is NEXT.
352        //
353        if (PREV <= 0) {
354            //
355            // In this case, we can read off the number of the tail
356            // node from PREV:  it is just -PREV.
357            //
358            POOL[[FORWRD, -PREV]] = -NEXT;
359        }
360    }
361    //
362    // The portion of the input list that followed TAIL (if such
363    // portion existed) has now been taken care of.
364    //
365
366    //
367    // Cauterize the sublist.
368    //
369    POOL[[BCKWRD, HEAD]] = -TAIL;
370    POOL[[FORWRD, TAIL]] = -HEAD;
371
372    Ok(())
373}