Family: sp
Authors: KSB Braunsdorf
Mail: ksb@npcguild.org
Version: 1.5
Bugs: None known.

Introduction

We need to hold a list of integers in memory as we process an expensive operation. At the end we need to traverse the list of the few integers which "hit" in the expensive search, and maybe recover a clue as to "how" it hit.

This module assumes that hits in the scan process are at random, and are very unlikely.

Configuration

Provide a standard machine.h which optionally defines:
#define SP_ALLOC_CACHE 2048
Gather sp_init function calls to calloc(3) into larger cached slabs. Since we never free the memory we allocate for the space this saves a lot of malloc headers and such. Suggested value of 4096 for a medium application hit rate, smaller for very rare hit rates.

By default no cache is enabled.

#define SP_ALLOC_TRIM 8
Declare how much space you are willing to discard to avoid calling calloc(3). Many of the calls we make to calloc are for 2 and 3 element vectors (12 bytes or less), this cache reduces the overhead consumed by that pattern. By allowing the rare request for 20 to 44 element vectors to fall directory to calloc we can save the small "trim part" for the next request for a short vector.
#define SP_RECURSE 0
Use the recursive version of sp_walk, rather than the iterative one when set to non-zero. The recursive one is more complex and slower, as far as I can tell.
#define SP_VERBOSE 0
When set to a non-zero value each function outputs a trace of the major plays in the game. Helps a new coder understand how this all works. Of course a picture helps a lot more.

Synopsis

#include "machine.h"
#include "sparse.h"

Description

Most of the configuration is done at run-time. The compile-time options are limited at present.

These functions are limited to construction of the sparse space, not mechanism (short of calling exit) is provided to remove any allocated space. This is fine for the use intended, and an implemenation via AVL trees would trivially provide a "clean" implementation.

More modern allocation system will also fix this issue.

Provides

extern sp_key sp_fibs[48];
The list of the unique 32 bit Fibonacci number, with a leading 0 and a trailing value of (2**32-1). This is used in the code to quickly lookup the next or previous Fibonacci number.
extern size_t sp_unfib(sp_key wN);
Find the position in the sp_key array which contains the Fibonacci that is closest the wN without going over.
extern void **sp_init(sp_key wRange);
Return a (void **) which can represent unsigned integers upto and including wRange (starting at zero).
extern void **sp_index(void **ppvFrom, sp_key wFind);
Return a (void **) which is bound to the integer wFind in the sparse space ppcFrom. To mark the value as used set the (void *) indexed by the return value to a non-NULL value (any one works).

Later, when sp_walking the space this (void *) is the second parameter passed to the Map function.

extern int sp_walk(void **ppvFrom, sp_key wLow, sp_key wHi, int (*pfiMap)(sp_key, void *));
Walk the sparse space given by From from wLow to wHi calling Map on each integer that has a non-NULL (void *) bound to it.
YourMap(sp_key wN, void *pvData)
The formal parameters that the Map parameter to sp_walk expects.
extern int sp_exists(void **ppvFrom, sp_key wTest);
Test fot the existence of Test in the sparse space given by From. Return zero for "not in the space" and non-zero for "included".

EXAMPLE

See the test driver embedded in the module.

This test driver inserts a few (unsigned long) integers into a sparse space instance with alternating colors ("red" and "blue"), then walks the space to output each integer and the color it was recorded with.

The integers in the test data were selected to test the corner cases in the walk and index functions.

Diagnostics

None.

See Also

avl(3)

To Do List

None.
$Id: sparse.html,v 1.9 2010/08/13 17:26:00 ksb Exp $