1 /****************************************************************************
2 **
3 **  This file is part of GAP, a system for computational discrete algebra.
4 **
5 **  Copyright of GAP belongs to its developers, whose names are too numerous
6 **  to list here. Please refer to the COPYRIGHT file for details.
7 **
8 **  SPDX-License-Identifier: GPL-2.0-or-later
9 **
10 **  This file declares the functions that deal with ranges.
11 **
12 **  A *range* is  a list without  holes  consisting  of consecutive integers.
13 **  For the full definition of ranges see chapter "Ranges" in the GAP Manual.
14 **  Read  also   "More about Ranges"  about  the different  representation of
15 **  ranges.
16 **
17 **  Ranges can be accessed through the functions 'NEW_RANGE', 'IS_RANGE',
18 **  'SET_LEN_RANGE', 'GET_LEN_RANGE', 'SET_LOW_RANGE', 'GET_LOW_RANGE',
19 **  'SET_INC_RANGE', 'GET_INC_RANGE', and 'GET_ELM_RANGE'.
20 **
21 **  This package  also contains  the  list  functions  for ranges, which  are
22 **  installed in the appropriate tables by 'InitRange'.
23 */
24 
25 #ifndef GAP_RANGE_H
26 #define GAP_RANGE_H
27 
28 #include "objects.h"
29 
30 /****************************************************************************
31 **
32 *F  NEW_RANGE() . . . . . . . . . . . . . . . . . . . . . .  make a new range
33 **
34 **  'NEW_RANGE' returns a new range.  Note that  you must set the length, the
35 **  low value, and the increment before you can use the range.
36 */
NEW_RANGE_NSORT(void)37 EXPORT_INLINE Obj NEW_RANGE_NSORT(void)
38 {
39     return NewBag(T_RANGE_NSORT, 3 * sizeof(Obj));
40 }
41 
NEW_RANGE_SSORT(void)42 EXPORT_INLINE Obj NEW_RANGE_SSORT(void)
43 {
44     return NewBag(T_RANGE_SSORT, 3 * sizeof(Obj));
45 }
46 
47 /****************************************************************************
48 **
49 *F  IS_RANGE(<val>) . . . . . . . . . . . . . . .  test if a value is a range
50 **
51 **  'IS_RANGE' returns 1  if the value  <val> is known  to be a range,  and 0
52 **  otherwise.  Note that a list for which 'IS_RANGE' returns  0 may still be
53 **  a range, but  the kernel does not know  this yet.  Use  'IsRange' to test
54 **  whether a list is a range.
55 */
IS_RANGE(Obj val)56 EXPORT_INLINE Int IS_RANGE(Obj val)
57 {
58     return TNUM_OBJ(val) >= T_RANGE_NSORT &&
59            TNUM_OBJ(val) <= T_RANGE_SSORT + IMMUTABLE;
60 }
61 
62 
63 /****************************************************************************
64 **
65 *F  SET_LEN_RANGE(<list>,<len>) . . . . . . . . . . set the length of a range
66 **
67 **  'SET_LEN_RANGE' sets the length  of the range <list>  to the value <len>,
68 **  which must be a C integer larger than 1.
69 */
SET_LEN_RANGE(Obj list,Int len)70 EXPORT_INLINE void SET_LEN_RANGE(Obj list, Int len)
71 {
72     GAP_ASSERT(IS_RANGE(list));
73     ADDR_OBJ(list)[0] = INTOBJ_INT(len);
74 }
75 
76 
77 /****************************************************************************
78 **
79 *F  GET_LEN_RANGE(<list>) . . . . . . . . . . . . . . . . . length of a range
80 **
81 **  'GET_LEN_RANGE' returns the  logical length of  the range <list>, as  a C
82 **  integer.
83 */
GET_LEN_RANGE(Obj list)84 EXPORT_INLINE Int GET_LEN_RANGE(Obj list)
85 {
86     GAP_ASSERT(IS_RANGE(list));
87     return INT_INTOBJ(CONST_ADDR_OBJ(list)[0]);
88 }
89 
90 
91 /****************************************************************************
92 **
93 *F  SET_LOW_RANGE(<list>,<low>) . . . . . .  set the first element of a range
94 **
95 **  'SET_LOW_RANGE' sets the  first element of the range  <list> to the value
96 **  <low>, which must be a C integer.
97 */
SET_LOW_RANGE(Obj list,Int low)98 EXPORT_INLINE void SET_LOW_RANGE(Obj list, Int low)
99 {
100     GAP_ASSERT(IS_RANGE(list));
101     ADDR_OBJ(list)[1] = INTOBJ_INT(low);
102 }
103 
104 
105 /****************************************************************************
106 **
107 *F  GET_LOW_RANGE(<list>) . . . . . . . . . . . . .  first element of a range
108 **
109 **  'GET_LOW_RANGE' returns the first  element  of the  range  <list> as a  C
110 **  integer.
111 */
GET_LOW_RANGE(Obj list)112 EXPORT_INLINE Int GET_LOW_RANGE(Obj list)
113 {
114     GAP_ASSERT(IS_RANGE(list));
115     return INT_INTOBJ(CONST_ADDR_OBJ(list)[1]);
116 }
117 
118 
119 /****************************************************************************
120 **
121 *F  SET_INC_RANGE(<list>,<inc>) . . . . . . . .  set the increment of a range
122 **
123 **  'SET_INC_RANGE' sets  the  increment of  the range  <list>   to the value
124 **  <inc>, which must be a C integer.
125 */
SET_INC_RANGE(Obj list,Int inc)126 EXPORT_INLINE void SET_INC_RANGE(Obj list, Int inc)
127 {
128     GAP_ASSERT(IS_RANGE(list));
129     ADDR_OBJ(list)[2] = INTOBJ_INT(inc);
130 }
131 
132 
133 /****************************************************************************
134 **
135 *F  GET_INC_RANGE(<list>) . . . . . . . . . . . . . . .  increment of a range
136 **
137 **  'GET_INC_RANGE' returns the increment of the range <list> as a C integer.
138 */
GET_INC_RANGE(Obj list)139 EXPORT_INLINE Int GET_INC_RANGE(Obj list)
140 {
141     GAP_ASSERT(IS_RANGE(list));
142     return INT_INTOBJ(CONST_ADDR_OBJ(list)[2]);
143 }
144 
145 
146 /****************************************************************************
147 **
148 *F  GET_ELM_RANGE(<list>,<pos>) . . . . . . . . . . . . .  element of a range
149 **
150 **  'GET_ELM_RANGE' return  the <pos>-th element  of the range <list>.  <pos>
151 **  must be a positive integer less than or equal to the length of <list>.
152 */
GET_ELM_RANGE(Obj list,Int pos)153 EXPORT_INLINE Obj GET_ELM_RANGE(Obj list, Int pos)
154 {
155     Int val;
156     GAP_ASSERT(IS_RANGE(list));
157     val = GET_LOW_RANGE(list) + ((pos)-1) * GET_INC_RANGE(list);
158     GAP_ASSERT(pos >= 1 && pos <= GET_LEN_RANGE(list));
159     return INTOBJ_INT(val);
160 }
161 
162 /****************************************************************************
163 **
164 *F  PosRange(<list>,<val>,<start>)  . . . . position of an element in a range
165 **
166 **  'PosRange' returns the position  of the value <val>  in the range  <list>
167 **  after the first position <start> as a GAP integer. Fail is returned if <val>
168 **  is not in the list.
169 **
170 **  'PosRange' is the function in 'PosListFuncs' for ranges.
171 */
172 Obj PosRange(Obj list, Obj val, Obj start);
173 
174 
175 /****************************************************************************
176 **
177 *F  Range2Check( <first>, <last> )  . . . . . . . . . . . . . construct range
178 */
179 Obj Range2Check(Obj first, Obj last);
180 
181 
182 /****************************************************************************
183 **
184 *F  Range3Check( <first>, <second>, <last> )  . . . . . . . . construct range
185 */
186 Obj Range3Check(Obj first, Obj second, Obj last);
187 
188 
189 /****************************************************************************
190 **
191 *F * * * * * * * * * * * * * initialize module * * * * * * * * * * * * * * *
192 */
193 
194 
195 /****************************************************************************
196 **
197 *F  InitInfoRange() . . . . . . . . . . . . . . . . . table of init functions
198 */
199 StructInitInfo * InitInfoRange ( void );
200 
201 
202 #endif // GAP_RANGE_H
203