X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Flibpspp%2Fsparse-array.c;h=7af219bcb080cd0a75b8b6bf9f823d2f397618a1;hb=124dea11f9542304e35bef92b7f3a46d5afca4d7;hp=2a0a206e8f96e93cee8876bd2d35bf9e33c51aaa;hpb=c97f6581b874c6057dbd4d581552774a3ed56ac5;p=pspp-builds.git diff --git a/src/libpspp/sparse-array.c b/src/libpspp/sparse-array.c index 2a0a206e..7af219bc 100644 --- a/src/libpspp/sparse-array.c +++ b/src/libpspp/sparse-array.c @@ -1,20 +1,18 @@ -/* PSPP - computes sample statistics. +/* PSPP - a program for statistical analysis. Copyright (C) 2007 Free Software Foundation, Inc. - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. */ + along with this program. If not, see . */ #include @@ -58,14 +56,14 @@ /* Pointer to an internal node or a leaf node. Pointers in internal nodes at level 1 point to leaf nodes; other pointers point to internal nodes. */ -union pointer +union pointer { struct internal_node *internal; struct leaf_node *leaf; }; /* A sparse array. */ -struct sparse_array +struct sparse_array { struct pool *pool; /* Pool used for allocations. */ size_t elem_size; /* Element size, rounded for alignment. */ @@ -90,7 +88,7 @@ struct sparse_array /* An internal node in the radix tree. */ struct internal_node { - int count; /* Number of nonnul children. */ + int count; /* Number of nonnull children. */ union pointer down[PTRS_PER_LEVEL]; /* Children. */ }; @@ -123,7 +121,7 @@ static inline size_t leaf_size (const struct sparse_array *); static struct leaf_node *find_leaf_node (const struct sparse_array *, unsigned long int); static void decrease_height (struct sparse_array *); -static void *scan_leaf (struct sparse_array *, struct leaf_node *, +static void *scan_leaf (struct sparse_array *, struct leaf_node *, unsigned long int, unsigned long int *); static void *do_scan (struct sparse_array *, union pointer *, int, unsigned long int, unsigned long int *); @@ -131,7 +129,7 @@ static void *do_scan (struct sparse_array *, union pointer *, int, /* Creates and returns a new sparse array that will contain elements that are ELEM_SIZE bytes in size. */ struct sparse_array * -sparse_array_create (size_t elem_size) +sparse_array_create (size_t elem_size) { return sparse_array_create_pool (NULL, elem_size); } @@ -140,7 +138,7 @@ sparse_array_create (size_t elem_size) elements that are ELEM_SIZE bytes in size. Data in the sparse array will be allocated from POOL, which may be null. */ struct sparse_array * -sparse_array_create_pool (struct pool *pool, size_t elem_size) +sparse_array_create_pool (struct pool *pool, size_t elem_size) { struct sparse_array *spar = pool_malloc (pool, sizeof *spar); spar->pool = pool; @@ -154,22 +152,22 @@ sparse_array_create_pool (struct pool *pool, size_t elem_size) /* Destroys SPAR node pointed to by P at the given LEVEL. */ static void -do_destroy (struct sparse_array *spar, union pointer *p, int level) +do_destroy (struct sparse_array *spar, union pointer *p, int level) { - if (level > 0) + if (level > 0) { struct internal_node *node = p->internal; int count = node->count; int i; - for (i = 0; ; i++) + for (i = 0; ; i++) { union pointer *q = &p->internal->down[i]; - if (level > 1 ? q->internal != NULL : q->leaf != NULL) + if (level > 1 ? q->internal != NULL : q->leaf != NULL) { do_destroy (spar, q, level - 1); if (--count == 0) - break; + break; } } pool_free (spar->pool, p->internal); @@ -183,7 +181,7 @@ do_destroy (struct sparse_array *spar, union pointer *p, int level) destruction is necessary, it should be done before destroying the sparse array. */ void -sparse_array_destroy (struct sparse_array *spar) +sparse_array_destroy (struct sparse_array *spar) { do_destroy (spar, &spar->root, spar->height - 1); pool_free (spar->pool, spar); @@ -191,7 +189,7 @@ sparse_array_destroy (struct sparse_array *spar) /* Returns the number of elements in SPAR. */ unsigned long int -sparse_array_count (const struct sparse_array *spar) +sparse_array_count (const struct sparse_array *spar) { return spar->count; } @@ -199,13 +197,13 @@ sparse_array_count (const struct sparse_array *spar) /* Increases SPAR's height by 1, allowing it to hold PTRS_PER_LEVEL times more elements. */ static void -increase_height (struct sparse_array *spar) +increase_height (struct sparse_array *spar) { assert (spar->height < MAX_HEIGHT); spar->height++; - if (spar->height == 1) + if (spar->height == 1) spar->root.leaf = pool_zalloc (spar->pool, leaf_size (spar)); - else + else { struct internal_node *new_root; new_root = pool_zalloc (spar->pool, sizeof *new_root); @@ -235,10 +233,10 @@ create_leaf_node (struct sparse_array *spar, unsigned long int key) p = &spar->root; for (level = spar->height - 1; level > 0; level--) { - if (p->internal == NULL) + if (p->internal == NULL) { p->internal = pool_zalloc (spar->pool, sizeof *p->internal); - ++*count; + ++*count; } count = &p->internal->count; @@ -246,7 +244,7 @@ create_leaf_node (struct sparse_array *spar, unsigned long int key) } /* Create leaf if necessary. */ - if (p->leaf == NULL) + if (p->leaf == NULL) { p->leaf = pool_zalloc (spar->pool, leaf_size (spar)); ++*count; @@ -261,12 +259,12 @@ create_leaf_node (struct sparse_array *spar, unsigned long int key) /* Inserts into SPAR an element with the given KEY, which must not already exist in SPAR. - Returns the new element for the caller to initialize. */ + Returns the new element for the caller to initialize. */ void * -sparse_array_insert (struct sparse_array *spar, unsigned long int key) +sparse_array_insert (struct sparse_array *spar, unsigned long int key) { struct leaf_node *leaf; - + while (!index_in_range (spar, key)) increase_height (spar); @@ -281,9 +279,9 @@ sparse_array_insert (struct sparse_array *spar, unsigned long int key) /* Finds and returns the element in SPAR with the given KEY. Returns a null pointer if KEY does not exist in SPAR. */ void * -sparse_array_get (const struct sparse_array *spar, unsigned long int key) +sparse_array_get (const struct sparse_array *spar, unsigned long int key) { - if (index_in_range (spar, key)) + if (index_in_range (spar, key)) { struct leaf_node *leaf = find_leaf_node (spar, key); if (leaf != NULL && is_in_use (leaf, key)) @@ -301,13 +299,13 @@ sparse_array_get (const struct sparse_array *spar, unsigned long int key) element's content must be considered freed and of indeterminate value after it is removed. */ bool -sparse_array_remove (struct sparse_array *spar, unsigned long int key) +sparse_array_remove (struct sparse_array *spar, unsigned long int key) { union pointer *path[MAX_HEIGHT], **last; struct leaf_node *leaf; union pointer *p; int level; - + if (!index_in_range (spar, key)) return false; @@ -365,7 +363,7 @@ sparse_array_remove (struct sparse_array *spar, unsigned long int key) not modify *FOUND. */ void * sparse_array_scan (const struct sparse_array *spar_, unsigned long int *skip, - unsigned long int *found) + unsigned long int *found) { struct sparse_array *spar = (struct sparse_array *) spar_; unsigned long int start; @@ -381,7 +379,7 @@ sparse_array_scan (const struct sparse_array *spar_, unsigned long int *skip, start = 0; /* Check the cache. */ - if (start >> BITS_PER_LEVEL == spar->cache_ofs) + if (start >> BITS_PER_LEVEL == spar->cache_ofs) { void *p = scan_leaf (spar, spar->cache, start, found); if (p) @@ -401,7 +399,7 @@ sparse_array_scan (const struct sparse_array *spar_, unsigned long int *skip, /* Returns true iff KEY is in the range of keys currently represented by SPAR. */ static inline bool -index_in_range (const struct sparse_array *spar, unsigned long int key) +index_in_range (const struct sparse_array *spar, unsigned long int key) { return (spar->height == 0 ? false : spar->height >= MAX_HEIGHT ? true @@ -411,15 +409,15 @@ index_in_range (const struct sparse_array *spar, unsigned long int key) /* Returns true iff LEAF contains an in-use element with the given KEY. */ static inline bool -is_in_use (const struct leaf_node *leaf, unsigned int key) +is_in_use (const struct leaf_node *leaf, unsigned int key) { key &= LEVEL_MASK; return (leaf->in_use[key / LONG_BITS] & (1ul << (key % LONG_BITS))) != 0; } -/* Returns true iff LEAF contains any in-use elements. */ +/* Returns true iff LEAF contains any in-use elements. */ static inline bool -any_in_use (const struct leaf_node *leaf) +any_in_use (const struct leaf_node *leaf) { size_t i; for (i = 0; i < sizeof leaf->in_use / sizeof *leaf->in_use; i++) @@ -430,7 +428,7 @@ any_in_use (const struct leaf_node *leaf) /* Marks element KEY in LEAF as in-use. */ static inline void -set_in_use (struct leaf_node *leaf, unsigned int key) +set_in_use (struct leaf_node *leaf, unsigned int key) { key &= LEVEL_MASK; leaf->in_use[key / LONG_BITS] |= 1ul << (key % LONG_BITS); @@ -438,7 +436,7 @@ set_in_use (struct leaf_node *leaf, unsigned int key) /* Marks element KEY in LEAF as not in-use. */ static inline void -unset_in_use (struct leaf_node *leaf, unsigned int key) +unset_in_use (struct leaf_node *leaf, unsigned int key) { key &= LEVEL_MASK; leaf->in_use[key / LONG_BITS] &= ~(1ul << (key % LONG_BITS)); @@ -447,7 +445,7 @@ unset_in_use (struct leaf_node *leaf, unsigned int key) /* Returns the number of trailing 0-bits in X. Undefined if X is zero. */ static inline int -count_trailing_zeros (unsigned long int x) +count_trailing_zeros (unsigned long int x) { /* This algorithm is from _Hacker's Delight_ section 5.4. */ int n = 1; @@ -478,7 +476,7 @@ count_trailing_zeros (unsigned long int x) static inline int scan_in_use (struct leaf_node *leaf, unsigned int idx) { - for (; idx < PTRS_PER_LEVEL; idx = (idx & ~(LONG_BITS - 1)) + LONG_BITS) + for (; idx < PTRS_PER_LEVEL; idx = (idx & ~(LONG_BITS - 1)) + LONG_BITS) { int ofs = idx % LONG_BITS; unsigned long int in_use = leaf->in_use[idx / LONG_BITS] >> ofs; @@ -493,7 +491,7 @@ scan_in_use (struct leaf_node *leaf, unsigned int idx) which is a node in SPAR. */ static inline void * leaf_element (const struct sparse_array *spar, struct leaf_node *leaf, - unsigned int key) + unsigned int key) { key &= LEVEL_MASK; return (char *) leaf + SIZEOF_ALIGNED (*leaf) + (spar->elem_size * key); @@ -501,7 +499,7 @@ leaf_element (const struct sparse_array *spar, struct leaf_node *leaf, /* Returns the size of a leaf node in SPAR. */ static inline size_t -leaf_size (const struct sparse_array *spar) +leaf_size (const struct sparse_array *spar) { return SIZEOF_ALIGNED (struct leaf_node) + spar->elem_size * PTRS_PER_LEVEL; } @@ -534,7 +532,7 @@ find_leaf_node (const struct sparse_array *spar_, unsigned long int key) /* Update cache. */ spar->cache = p->leaf; spar->cache_ofs = key >> BITS_PER_LEVEL; - + return p->leaf; } @@ -542,11 +540,11 @@ find_leaf_node (const struct sparse_array *spar_, unsigned long int key) eliminating levels that contain only a single entry for all 0-bits. */ static void -decrease_height (struct sparse_array *spar) +decrease_height (struct sparse_array *spar) { while (spar->height > 1 && spar->root.internal->count == 1 - && spar->root.internal->down[0].internal) + && spar->root.internal->down[0].internal) { struct internal_node *p = spar->root.internal; spar->height--; @@ -561,7 +559,7 @@ decrease_height (struct sparse_array *spar) in *FOUND; otherwise, returns a null pointer and does not modify *FOUND. */ static void * -scan_leaf (struct sparse_array *spar, struct leaf_node *leaf, +scan_leaf (struct sparse_array *spar, struct leaf_node *leaf, unsigned long int start, unsigned long int *found) { int idx = scan_in_use (leaf, start & LEVEL_MASK); @@ -572,7 +570,7 @@ scan_leaf (struct sparse_array *spar, struct leaf_node *leaf, spar->cache_ofs = *found >> BITS_PER_LEVEL; return leaf_element (spar, leaf, idx); } - + return NULL; } @@ -584,13 +582,13 @@ scan_leaf (struct sparse_array *spar, struct leaf_node *leaf, static inline void * scan_internal_node (struct sparse_array *spar, struct internal_node *node, int level, unsigned long int start, - unsigned long int *found) + unsigned long int *found) { int shift = level * BITS_PER_LEVEL; int count = node->count; int i; - for (i = (start >> shift) & LEVEL_MASK; i < PTRS_PER_LEVEL; i++) + for (i = (start >> shift) & LEVEL_MASK; i < PTRS_PER_LEVEL; i++) { union pointer *q = &node->down[i]; if (level > 1 ? q->internal != NULL : q->leaf != NULL) @@ -600,7 +598,7 @@ scan_internal_node (struct sparse_array *spar, struct internal_node *node, return element; if (--count == 0) return NULL; - } + } start &= ~((1ul << shift) - 1); start += 1ul << shift;