3 * Copyright (C) 2002-2009, Parrot Foundation.
14 An implementation of sets -- used for tracking register usage.
27 /* HEADERIZER HFILE: compilers/imcc/sets.h */
30 #define fatal(e, s1, s2) do { \
31 fprintf(stderr, "%s: %s", (s1), (s2)); \
35 #define NUM_BYTES(length) (((length) / 8) + 1)
36 #define BYTE_IN_SET(element) ((element) >> 3)
37 #define BIT_IN_BYTE(element) (1 << ((element) & 7))
41 =item C<Set* set_make(PARROT_INTERP, unsigned int length)>
43 Creates a new Set object.
50 PARROT_CANNOT_RETURN_NULL
52 set_make(PARROT_INTERP
, unsigned int length
)
55 Set
* const s
= mem_gc_allocate_zeroed_typed(interp
, Set
);
57 s
->bmp
= mem_gc_allocate_n_zeroed_typed(interp
,
58 NUM_BYTES(length
), unsigned char);
66 =item C<Set* set_make_full(PARROT_INTERP, unsigned int length)>
68 Creates a new Set object of C<length> items, setting them all to full.
75 PARROT_CANNOT_RETURN_NULL
77 set_make_full(PARROT_INTERP
, unsigned int length
)
79 ASSERT_ARGS(set_make_full
)
80 Set
* const s
= set_make(interp
, length
);
81 const size_t bytes
= NUM_BYTES(length
);
84 memset(s
->bmp
, 0xff, bytes
);
92 =item C<void set_free(Set *s)>
94 Frees the given Set and its allocated memory.
101 set_free(ARGMOD(Set
*s
))
103 ASSERT_ARGS(set_free
)
105 mem_sys_free(s
->bmp
);
113 =item C<void set_clear(Set *s)>
115 Clears all bits in the Set.
122 set_clear(ARGMOD(Set
*s
))
124 ASSERT_ARGS(set_clear
)
125 memset(s
->bmp
, 0, NUM_BYTES(s
->length
));
131 =item C<Set* set_copy(PARROT_INTERP, const Set *s)>
133 Copies the set C<s>, returning a new set pointer.
140 PARROT_CANNOT_RETURN_NULL
142 set_copy(PARROT_INTERP
, ARGIN(const Set
*s
))
144 ASSERT_ARGS(set_copy
)
145 Set
* const d
= set_make(interp
, s
->length
);
147 memcpy(d
->bmp
, s
->bmp
, NUM_BYTES(d
->length
));
154 =item C<int set_equal(const Set *s1, const Set *s2)>
156 Compares two sets for equality; sets are equal if they contain the same
159 Raises a fatal error if the two Sets have different lengths.
166 set_equal(ARGIN(const Set
*s1
), ARGIN(const Set
*s2
))
168 ASSERT_ARGS(set_equal
)
170 const size_t bytes
= s1
->length
/ 8;
172 if (s1
->length
!= s2
->length
)
173 fatal(1, "set_equal", "Sets don't have the same length\n");
176 if (memcmp(s1
->bmp
, s2
->bmp
, bytes
) != 0)
179 if (s1
->length
% 8 == 0)
182 mask
= (1 << (s1
->length
% 8)) - 1;
184 if ((s1
->bmp
[bytes
] & mask
) != (s2
->bmp
[bytes
] & mask
))
193 =item C<void set_add(Set *s, unsigned int element)>
195 Adds to set C<s> the element C<element>.
202 set_add(ARGMOD(Set
*s
), unsigned int element
)
205 const int elem_byte_in_set
= BYTE_IN_SET(element
);
206 const int bytes_in_set
= BYTE_IN_SET(s
->length
);
208 if (bytes_in_set
< elem_byte_in_set
) {
209 s
->bmp
= (unsigned char *)mem_sys_realloc_zeroed(s
->bmp
,
210 NUM_BYTES(element
), NUM_BYTES(s
->length
));
214 s
->bmp
[elem_byte_in_set
] |= BIT_IN_BYTE(element
);
220 =item C<unsigned int set_first_zero(const Set *s)>
222 Sets the first unused item in the set.
228 PARROT_WARN_UNUSED_RESULT
231 set_first_zero(ARGIN(const Set
*s
))
233 ASSERT_ARGS(set_first_zero
)
237 for (i
= 0; i
< NUM_BYTES(s
->length
); ++i
) {
238 const int set_byte
= s
->bmp
[i
];
241 if (set_byte
== 0xFF)
244 for (j
= 0; j
< 8; ++j
) {
245 unsigned int element
= i
* 8 + j
;
247 if (!set_contains(s
, element
))
258 =item C<int set_contains(const Set *s, unsigned int element)>
260 Checks whether the specified element is present in the specified Set argument.
261 Returns 1 if it is, 0 otherwise.
267 PARROT_WARN_UNUSED_RESULT
270 set_contains(ARGIN(const Set
*s
), unsigned int element
)
272 ASSERT_ARGS(set_contains
)
274 if (element
> s
->length
)
277 /* workaround for another lcc bug.. */
278 const int byte_in_set
= element
>> 3;
279 const int pos_in_byte
= BIT_IN_BYTE(element
);
282 return s
->bmp
[byte_in_set
] & pos_in_byte
;
289 =item C<Set * set_union(PARROT_INTERP, const Set *s1, const Set *s2)>
291 Computes the union of the two Set arguments, returning it as a new Set.
293 Raises a fatal error if the two Sets have different lengths.
300 PARROT_CANNOT_RETURN_NULL
302 set_union(PARROT_INTERP
, ARGIN(const Set
*s1
), ARGIN(const Set
*s2
))
304 ASSERT_ARGS(set_union
)
306 Set
* const s
= set_make(interp
, s1
->length
);
308 if (s1
->length
!= s2
->length
)
309 fatal(1, "set_union", "Sets don't have the same length\n");
311 for (i
= 0; i
< BYTE_IN_SET(s1
->length
); i
++) {
312 s
->bmp
[i
] = s1
->bmp
[i
] | s2
->bmp
[i
];
321 =item C<Set * set_intersec(PARROT_INTERP, const Set *s1, const Set *s2)>
323 Creates a new Set object that is the intersection of the Set arguments (defined
324 through the binary C<and> operator.)
326 Raises a fatal error if the two Sets have different lengths.
333 PARROT_CANNOT_RETURN_NULL
335 set_intersec(PARROT_INTERP
, ARGIN(const Set
*s1
), ARGIN(const Set
*s2
))
337 ASSERT_ARGS(set_intersec
)
339 Set
* const s
= set_make(interp
, s1
->length
);
341 if (s1
->length
!= s2
->length
)
342 fatal(1, "set_intersec", "Sets don't have the same length\n");
344 for (i
= 0; i
< BYTE_IN_SET(s1
->length
); i
++) {
345 s
->bmp
[i
] = s1
->bmp
[i
] & s2
->bmp
[i
];
354 =item C<void set_intersec_inplace(Set *s1, const Set *s2)>
356 Performs a set intersection in place -- the first Set argument changes to
364 set_intersec_inplace(ARGMOD(Set
*s1
), ARGIN(const Set
*s2
))
366 ASSERT_ARGS(set_intersec_inplace
)
369 if (s1
->length
!= s2
->length
)
370 fatal(1, "set_intersec_inplace", "Sets don't have the same length\n");
372 for (i
= 0; i
< BYTE_IN_SET(s1
->length
); i
++) {
373 s1
->bmp
[i
] &= s2
->bmp
[i
];
387 * c-file-style: "parrot"
389 * vim: expandtab shiftwidth=4: