Commit 5beb2272 authored by Sebastian Hack's avatar Sebastian Hack
Browse files

Removed the "specializable" arrayset

instead arraysets can now be done with normal firm sets (see array.h)
but beware it's not yet thoroughly tested.

[r15428]
parent 0b92932d
......@@ -20,7 +20,7 @@
/**
* @file
* @brief Dynamic and flexible arrays for C.
* @author Markus Armbruster
* @author Markus Armbruster, Michael Beck, Matthias Braun, Sebastian Hack
* @version $Id$
*/
#ifndef FIRM_ADT_ARRAY_H
......@@ -29,6 +29,7 @@
#include <assert.h>
#include <stddef.h>
#include "firm_config.h"
#include "obst.h"
#include "fourcc.h"
#include "align.h"
......@@ -284,7 +285,6 @@
#define ARR_APP1(type, arr, elt) \
(ARR_EXTEND (type, (arr), 1), (arr)[ARR_LEN ((arr))-1] = (elt))
#ifdef NDEBUG
# define ARR_VRFY(arr) ((void)0)
# define ARR_IDX_VRFY(arr, idx) ((void)0)
......@@ -346,4 +346,90 @@ void *_arr_setlen (void *, int, size_t);
#define _ARR_ELTS_OFFS offsetof (_arr_descr, v.elts)
#define _ARR_DESCR(elts) ((_arr_descr *)(void *)((char *)(elts) - _ARR_ELTS_OFFS))
/*
____ _ _ _
/ ___| ___ _ __| |_ ___ __| | / \ _ __ _ __ __ _ _ _ ___
\___ \ / _ \| '__| __/ _ \/ _` | / _ \ | '__| '__/ _` | | | / __|
___) | (_) | | | || __/ (_| | / ___ \| | | | | (_| | |_| \__ \
|____/ \___/|_| \__\___|\__,_| /_/ \_\_| |_| \__,_|\__, |___/
|___/
*/
typedef int (_arr_cmp_func_t)(const void *a, const void *b);
/**
* Do a binary search in an array.
* @param arr The array.
* @param elm_size The size of an array element.
* @param cmp A comparison function for two array elements (see qsort(3) for example).
* @param elm A pointer to the element we are looking for.
* @return This is somewhat tricky. Let <code>res</code> be the return value.
* If the return value is negative, then <code>elm</code> was not in the array
* but <code>-res - 1</code> gives the proper location where it should be inserted.
* If <code>res >= 0</code> then the element is in the array and <code>res</code>
* represents its index.
* That allows for testing membership and finding proper insertion indices.
* @note The differences to bsearch(3) which does not give proper insert locations
* in the case that the element is not conatined in the array.
*/
static INLINE __attribute__((const, unused)) int
_arr_bsearch(const void *arr, size_t elm_size, _arr_cmp_func_t *cmp, const void *elm)
{
int hi = ARR_LEN(arr);
int lo = 0;
while(lo < hi) {
int md = lo + ((hi - lo) >> 1);
int res = cmp((char *) arr + md * elm_size, elm);
if(res < 0)
lo = md + 1;
else if(res > 0)
hi = md;
else
return md;
}
return -(lo + 1);
}
#define ARR_SET_INSERT(arr, cmp, elm) \
do { \
int idx = _arr_bsearch((arr), sizeof((arr)[0]), (cmp), (elm)); \
if (idx < 0) { \
idx = -idx - 1; \
memmove(&(arr)[idx+1], &(arr)[idx], sizeof((arr)[0]) * (_ARR_DESCR((arr))->nelts - idx)); \
(arr)[idx] = (elm); \
++_ARR_DESCR((arr))->nelts; \
} \
} while(0)
#define ARR_SET_REMOVE(arr, cmp, elm) \
do { \
int idx = _arr_bsearch((arr), sizeof((arr)[0]), (cmp), (elm)); \
if (idx >= 0) { \
--_ARR_DESCR((arr))->nelts; \
memmove(&(arr)[idx], &(arr)[idx+1], sizeof((arr)[0]) * (_ARR_DESCR((arr))->nelts - idx)); \
} \
} while(0)
/**
* Return the index of an element in an array set.
* To check for containment, use the expression:
* (ARR_SET_GET_IDX(arr, cmp, elm) >= 0)
*
* @return The index or some value < 0 if the element was not in the set.
*/
#define ARR_SET_GET_IDX(arr, cmp, elm) \
(ARR_VRFY((arr)), _arr_bsearch((arr), sizeof((arr)[0]), cmp, elm))
#define ARR_SET_CONTAINS(arr, cmp, elm) \
(ARR_SET_GET_IDX((arr), (cmp), (elm)) >= 0)
/**
* Reset the array set.
* This just initializes the size to zero but does not wipe out any element.
*/
#define ARR_SET_CLEAR(arr) ARR_SHRINKLEN(arr, 0)
#endif /* FIRM_ADT_ARRAY_H */
/*
* Copyright (C) 1995-2007 University of Karlsruhe. All right reserved.
*
* This file is part of libFirm.
*
* This file may be distributed and/or modified under the terms of the
* GNU General Public License version 2 as published by the Free Software
* Foundation and appearing in the file LICENSE.GPL included in the
* packaging of this file.
*
* Licensees holding valid libFirm Professional Edition licenses may use
* this file in accordance with the libFirm Commercial License.
* Agreement provided with the Software.
*
* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
* WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE.
*/
/**
* @file arrayset.h
* @date 11.07.2007
* @author Sebastian Hack
*/
struct HashSet {
ValueType *arr;
#ifndef NDEBUG
unsigned in_order : 1;
#endif
#ifdef ADDITIONAL_DATA
ADDITIONAL_DATA
#endif
};
struct HashSetIterator {
ValueType *arr;
int curr;
};
/*
* Copyright (C) 1995-2007 University of Karlsruhe. All right reserved.
*
* This file is part of libFirm.
*
* This file may be distributed and/or modified under the terms of the
* GNU General Public License version 2 as published by the Free Software
* Foundation and appearing in the file LICENSE.GPL included in the
* packaging of this file.
*
* Licensees holding valid libFirm Professional Edition licenses may use
* this file in accordance with the libFirm Commercial License.
* Agreement provided with the Software.
*
* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
* WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE.
*/
/**
* @file arrayset.c
* @brief Implementation of sets with sorted arrays.
* @date 11.07.2007
* @author Sebastian Hack
*
* Follows the same API/specialization scheme as hashset.c and is thus interchangable.
* To remain compatible, all specializations as in hashset.c must be done.
* Additionally, we need a ValueCmp macro comapring two values not only for equality.
* That macro follows the same scheme as the compare functions in qsort(3).
*/
#ifdef HashSet
#include "firm_config.h"
#include "array.h"
static INLINE int hashset_bsearch(ValueType *arr, const ValueType elm)
{
int res = 0;
int lo = 0;
int hi = ARR_LEN(arr);
while(lo < hi) {
int md = lo + ((hi - lo) >> 1);
int cmp = ValueCmp(arr[md], elm);
if(cmp < 0)
lo = md + 1;
else if(cmp > 0)
hi = md;
else {
res = md;
break;
}
res = lo;
}
return res;
}
static INLINE int hashset_is_at(ValueType *arr, int idx, const ValueType what)
{
return idx < ARR_LEN(arr) && ValueCmp(arr[idx], what) == 0;
}
void hashset_init_size(HashSet *set, size_t expected_elements)
{
set->arr = NEW_ARR_F(ValueType, expected_elements);
#ifndef NDEBUG
set->in_order = 1;
#endif
ARR_SHRINKLEN(set->arr, 0);
}
void hashset_init(HashSet *set)
{
hashset_init_size(set, 16);
}
void hashset_destroy(HashSet *set)
{
DEL_ARR_F(set->arr);
}
int hashset_insert(HashSet *set, ValueType elt)
{
ValueType *arr = set->arr;
int i, idx = hashset_bsearch(arr, elt);
#ifndef NDEBUG
assert(set->in_order);
#endif
if (!hashset_is_at(arr, idx, elt)) {
ARR_EXTEND(ValueType, set->arr, 1);
arr = set->arr;
for (i = ARR_LEN(arr) - 1; i > idx; --i)
arr[i] = arr[i - 1];
arr[idx] = elt;
return 1;
}
return 0;
}
void hashset_insert_quick(HashSet *set, ValueType elt)
{
ValueType *arr = set->arr;
ARR_EXTEND(ValueType, set->arr, 1);
arr = set->arr;
arr[ARR_LEN(arr) - 1] = elt;
}
static INLINE int _hashset_remove_idx(ValueType *arr, int idx)
{
int n;
for (n = ARR_LEN(arr) - 1; idx < n; ++idx)
arr[idx] = arr[idx + 1];
return n;
}
void hashset_remove(HashSet *set, const ValueType elt)
{
ValueType *arr = set->arr;
int idx = hashset_bsearch(arr, elt);
#ifndef NDEBUG
assert(set->in_order);
#endif
if (hashset_is_at(arr, idx, elt)) {
int new_len = _hashset_remove_idx(arr, idx);
ARR_SHRINKLEN(arr, new_len);
}
}
void hashset_remove_quick(HashSet *set, const ValueType elt)
{
ValueType *arr = set->arr;
int idx = hashset_bsearch(arr, elt);
#ifndef NDEBUG
set->in_order = 0;
#endif
if (hashset_is_at(arr, idx, elt)) {
int n = ARR_LEN(arr);
if (idx < n - 1)
arr[idx] = arr[n - 1];
ARR_SHRINKLEN(arr, n - 1);
}
}
void hashset_fixup(HashSet *set)
{
ValueType *arr = set->arr;
ValueType *tmp;
int i, n;
CLONE_ARR_A(ValueType, tmp, arr);
memcpy(tmp, arr, n * sizeof(arr[0]));
ARR_SHRINKLEN(arr, 0);
for (i = 0, n = ARR_LEN(arr); i < n; ++i)
hashset_insert(set, tmp[0]);
#ifndef NDEBUG
set->in_order = 1;
#endif
}
ValueType hashset_find(const HashSet *set, const ValueType elt)
{
int idx = hashset_bsearch(set->arr, elt);
#ifndef NDEBUG
assert(set->in_order);
#endif
return hashset_is_at(set->arr, idx, elt) ? set->arr[idx] : NullValue;
}
size_t hashset_size(const HashSet *set)
{
return ARR_LEN(set->arr);
}
void hashset_iterator_init(HashSetIterator *iter, const HashSet *set)
{
iter->arr = set->arr;
iter->curr = -1;
}
ValueType ir_nodeset_iterator_next(HashSetIterator *iter)
{
++iter->curr;
return iter->curr < ARR_LEN(iter->arr) ? iter->arr[iter->curr] : NullValue;
}
void hashset_remove_iterator(HashSet *set, const HashSetIterator *iter)
{
(void) set;
(void) _hashset_remove_idx(iter->arr, iter->curr);
ARR_SHRINKLEN(iter->arr, ARR_LEN(iter->arr) - 1);
}
#endif
......@@ -58,19 +58,8 @@
#define hashset_iterator_next ir_nodeset_iterator_next
#define hashset_remove_iterator ir_nodeset_remove_iterator
#ifdef IR_NODESET_USE_ORDERED_SETS
#define hashset_insert_quick ir_nodeset_insert_quick
#define hashset_remove_quick ir_nodeset_remove_quick
#define hashset_fixup ir_nodeset_fixup
#include "arrayset.c"
#else
#include "hashset.c"
#endif /* IR_NODESET_USE_ORDERED_SETS */
void ir_nodeset_init(ir_nodeset_t *nodeset)
{
ir_nodeset_init_size(nodeset, 16);
......
......@@ -50,11 +50,7 @@
#define ValueType ir_node*
#define DO_REHASH
#ifdef IR_NODESET_USE_ORDERED_SETS
#include "arrayset.h"
#else
#include "hashset.h"
#endif
#undef DO_REHASH
#undef ValueType
......@@ -179,46 +175,4 @@ void ir_nodeset_remove_iterator(ir_nodeset_t *nodeset,
irn = ir_nodeset_iterator_next(&iter); \
irn != NULL; irn = ir_nodeset_iterator_next(&iter))
#ifdef IR_NODESET_USE_ORDERED_SETS
/**
* Insert an element quickly into from the set.
* This method may destroy internal invariats of the set (think of sorted arrays).
* All calls to other routines but
* - iteration
* - get the number of elements in the set
* will not work until ir_nodeset_fixup() was called.
* @param nodeset The nodeset.
* @param node The node to insert.
*/
void ir_nodeset_insert_quick(ir_nodeset_t *nodeset, ir_node *node);
/**
* Remove an element quickly from the set.
* This method may destroy internal invariats of the set (think of sorted arrays).
* All calls to other routines but
* - iteration
* - get the number of elements in the set
* will not work until ir_nodeset_fixup() was called.
* @param nodeset The nodeset.
* @param node The node to delete.
*/
void ir_nodeset_remove_quick(ir_nodeset_t *nodeset, const ir_node *node);
/**
* Fixes up internal state of the set.
* Is needed when one of the _quick functions was called.
* @param nodeset The nodeset.
*/
void ir_nodeset_fixup(ir_nodeset_t *nodeset);
#else
#define ir_nodeset_remove_quick ir_nodeset_remove
#define ir_nodeset_insert_quick ir_nodeset_insert
#define ir_nodeset_fixup(set)
#endif /* IR_NODESET_USE_ORDERED_SETS */
#endif
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment