1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-01-30 04:10:54 -08:00

Use cbs subclasses to implement the fast-find and find-in-zones features. this avoids the need to control behaviour by passing booleans, and it means that there is no wasted space in the cbs block structure when these features are not used.

Bring splay tree design up to date; add missing diagrams; move it to the "current" section of the manual.

Copied from Perforce
 Change: 185294
 ServerID: perforce.ravenbrook.com
This commit is contained in:
Gareth Rees 2014-04-07 15:36:18 +01:00
commit b90f8b9bcd
20 changed files with 2611 additions and 393 deletions

View file

@ -224,7 +224,7 @@ Res ArenaInit(Arena arena, ArenaClass class, Align alignment, ArgList args)
handled where the Land is used. */
MPS_ARGS_BEGIN(piArgs) {
MPS_ARGS_ADD(piArgs, MPS_KEY_MFS_UNIT_SIZE, sizeof(CBSBlockStruct));
MPS_ARGS_ADD(piArgs, MPS_KEY_MFS_UNIT_SIZE, sizeof(CBSZonedBlockStruct));
MPS_ARGS_ADD(piArgs, MPS_KEY_EXTEND_BY, arena->alignment);
MPS_ARGS_ADD(piArgs, MFSExtendSelf, FALSE);
res = PoolInit(ArenaCBSBlockPool(arena), arena, PoolClassMFS(), piArgs);
@ -236,9 +236,7 @@ Res ArenaInit(Arena arena, ArenaClass class, Align alignment, ArgList args)
/* Initialise the freeLand. */
MPS_ARGS_BEGIN(liArgs) {
MPS_ARGS_ADD(liArgs, CBSBlockPool, ArenaCBSBlockPool(arena));
MPS_ARGS_ADD(liArgs, CBSFastFind, TRUE);
MPS_ARGS_ADD(liArgs, CBSZoned, arena->zoned);
res = LandInit(ArenaFreeLand(arena), CBSLandClassGet(), arena,
res = LandInit(ArenaFreeLand(arena), CBSZonedLandClassGet(), arena,
alignment, arena, liArgs);
} MPS_ARGS_END(liArgs);
AVER(res == ResOK); /* no allocation, no failure expected */
@ -388,7 +386,7 @@ void ArenaDestroy(Arena arena)
LandFinish(ArenaFreeLand(arena));
/* The CBS block pool can't free its own memory via ArenaFree because
that would use the ZonedCBS. */
that would use the CBSZoned. */
MFSFinishTracts(ArenaCBSBlockPool(arena),
arenaMFSPageFreeVisitor, NULL, 0);
PoolFinish(ArenaCBSBlockPool(arena));

View file

@ -32,6 +32,10 @@ SRCID(cbs, "$Id$");
#define cbsOfSplay(_splay) PARENT(CBSStruct, splayTreeStruct, _splay)
#define cbsBlockTree(block) (&((block)->treeStruct))
#define cbsBlockOfTree(_tree) TREE_ELT(CBSBlock, treeStruct, _tree)
#define cbsFastBlockOfTree(_tree) \
PARENT(CBSFastBlockStruct, cbsBlockStruct, cbsBlockOfTree(_tree))
#define cbsZonedBlockOfTree(_tree) \
PARENT(CBSZonedBlockStruct, cbsFastBlockStruct, cbsFastBlockOfTree(_tree))
#define cbsBlockKey(block) (&((block)->base))
#define cbsBlockPool(cbs) RVALUE((cbs)->blockPool)
@ -71,10 +75,8 @@ Bool CBSCheck(CBS cbs)
CHECKD(SplayTree, cbsSplay(cbs));
/* nothing to check about treeSize */
CHECKD(Pool, cbs->blockPool);
CHECKL(BoolCheck(cbs->fastFind));
CHECKL(BoolCheck(cbs->inCBS));
CHECKL(BoolCheck(cbs->ownPool));
CHECKL(BoolCheck(cbs->zoned));
return TRUE;
}
@ -139,7 +141,7 @@ static Bool cbsTestNode(SplayTree splay, Tree tree,
AVERT(Tree, tree);
AVER(closureP == NULL);
AVER(size > 0);
AVER(cbsOfSplay(splay)->fastFind);
AVER(IsLandSubclass(cbsLand(cbsOfSplay(splay)), CBSFastLandClass));
block = cbsBlockOfTree(tree);
@ -149,7 +151,7 @@ static Bool cbsTestNode(SplayTree splay, Tree tree,
static Bool cbsTestTree(SplayTree splay, Tree tree,
void *closureP, Size size)
{
CBSBlock block;
CBSFastBlock block;
AVERT(SplayTree, splay);
AVERT(Tree, tree);
@ -159,41 +161,39 @@ static Bool cbsTestTree(SplayTree splay, Tree tree,
#endif
UNUSED(closureP);
UNUSED(size);
AVER(cbsOfSplay(splay)->fastFind);
AVER(IsLandSubclass(cbsLand(cbsOfSplay(splay)), CBSFastLandClass));
block = cbsBlockOfTree(tree);
block = cbsFastBlockOfTree(tree);
return block->maxSize >= size;
}
/* cbsUpdateNode -- update size info after restructuring */
/* cbsUpdateFastNode -- update size info after restructuring */
static void cbsUpdateNode(SplayTree splay, Tree tree)
static void cbsUpdateFastNode(SplayTree splay, Tree tree)
{
Size maxSize;
CBSBlock block;
AVERT_CRITICAL(SplayTree, splay);
AVERT_CRITICAL(Tree, tree);
AVER_CRITICAL(cbsOfSplay(splay)->fastFind);
AVER_CRITICAL(IsLandSubclass(cbsLand(cbsOfSplay(splay)), CBSFastLandClass));
block = cbsBlockOfTree(tree);
maxSize = CBSBlockSize(block);
maxSize = CBSBlockSize(cbsBlockOfTree(tree));
if (TreeHasLeft(tree)) {
Size size = cbsBlockOfTree(TreeLeft(tree))->maxSize;
Size size = cbsFastBlockOfTree(TreeLeft(tree))->maxSize;
if (size > maxSize)
maxSize = size;
}
if (TreeHasRight(tree)) {
Size size = cbsBlockOfTree(TreeRight(tree))->maxSize;
Size size = cbsFastBlockOfTree(TreeRight(tree))->maxSize;
if (size > maxSize)
maxSize = size;
}
block->maxSize = maxSize;
cbsFastBlockOfTree(tree)->maxSize = maxSize;
}
@ -202,27 +202,28 @@ static void cbsUpdateNode(SplayTree splay, Tree tree)
static void cbsUpdateZonedNode(SplayTree splay, Tree tree)
{
ZoneSet zones;
CBSZonedBlock zonedBlock;
CBSBlock block;
Arena arena;
AVERT_CRITICAL(SplayTree, splay);
AVERT_CRITICAL(Tree, tree);
AVER_CRITICAL(cbsOfSplay(splay)->fastFind);
AVER_CRITICAL(cbsOfSplay(splay)->zoned);
AVER_CRITICAL(IsLandSubclass(cbsLand(cbsOfSplay(splay)), CBSZonedLandClass));
cbsUpdateNode(splay, tree);
cbsUpdateFastNode(splay, tree);
block = cbsBlockOfTree(tree);
zonedBlock = cbsZonedBlockOfTree(tree);
block = &zonedBlock->cbsFastBlockStruct.cbsBlockStruct;
arena = LandArena(cbsLand(cbsOfSplay(splay)));
zones = ZoneSetOfRange(arena, CBSBlockBase(block), CBSBlockLimit(block));
if (TreeHasLeft(tree))
zones = ZoneSetUnion(zones, cbsBlockOfTree(TreeLeft(tree))->zones);
zones = ZoneSetUnion(zones, cbsZonedBlockOfTree(TreeLeft(tree))->zones);
if (TreeHasRight(tree))
zones = ZoneSetUnion(zones, cbsBlockOfTree(TreeRight(tree))->zones);
zones = ZoneSetUnion(zones, cbsZonedBlockOfTree(TreeRight(tree))->zones);
block->zones = zones;
zonedBlock->zones = zones;
}
@ -233,21 +234,17 @@ static void cbsUpdateZonedNode(SplayTree splay, Tree tree)
ARG_DEFINE_KEY(cbs_extend_by, Size);
ARG_DEFINE_KEY(cbs_block_pool, Pool);
ARG_DEFINE_KEY(cbs_fast_find, Bool);
ARG_DEFINE_KEY(cbs_zoned, Bool);
static Res cbsInit(Land land, ArgList args)
static Res cbsInitComm(Land land, ArgList args, SplayUpdateNodeMethod update,
Size blockStructSize)
{
CBS cbs;
LandClass super;
Size extendBy = CBS_EXTEND_BY_DEFAULT;
Bool extendSelf = TRUE;
Bool fastFind = FALSE;
Bool zoned = FALSE;
ArgStruct arg;
Res res;
Pool blockPool = NULL;
SplayUpdateNodeMethod update;
AVERT(Land, land);
super = LAND_SUPERCLASS(CBSLandClass);
@ -261,18 +258,6 @@ static Res cbsInit(Land land, ArgList args)
extendBy = arg.val.size;
if (ArgPick(&arg, args, MFSExtendSelf))
extendSelf = arg.val.b;
if (ArgPick(&arg, args, CBSFastFind))
fastFind = arg.val.b;
if (ArgPick(&arg, args, CBSZoned))
zoned = arg.val.b;
update = SplayTrivUpdate;
if (fastFind)
update = cbsUpdateNode;
if (zoned) {
AVER(fastFind);
update = cbsUpdateZonedNode;
}
cbs = cbsOfLand(land);
SplayTreeInit(cbsSplay(cbs), cbsCompare, cbsKey, update);
@ -282,7 +267,7 @@ static Res cbsInit(Land land, ArgList args)
cbs->ownPool = FALSE;
} else {
MPS_ARGS_BEGIN(pcArgs) {
MPS_ARGS_ADD(pcArgs, MPS_KEY_MFS_UNIT_SIZE, sizeof(CBSBlockStruct));
MPS_ARGS_ADD(pcArgs, MPS_KEY_MFS_UNIT_SIZE, blockStructSize);
MPS_ARGS_ADD(pcArgs, MPS_KEY_EXTEND_BY, extendBy);
MPS_ARGS_ADD(pcArgs, MFSExtendSelf, extendSelf);
res = PoolCreate(&cbs->blockPool, LandArena(land), PoolClassMFS(), pcArgs);
@ -293,8 +278,7 @@ static Res cbsInit(Land land, ArgList args)
}
cbs->treeSize = 0;
cbs->fastFind = fastFind;
cbs->zoned = zoned;
cbs->blockStructSize = blockStructSize;
cbs->inCBS = TRUE;
METER_INIT(cbs->treeSearch, "size of tree", (void *)cbs);
@ -306,6 +290,24 @@ static Res cbsInit(Land land, ArgList args)
return ResOK;
}
static Res cbsInit(Land land, ArgList args)
{
return cbsInitComm(land, args, SplayTrivUpdate,
sizeof(CBSBlockStruct));
}
static Res cbsInitFast(Land land, ArgList args)
{
return cbsInitComm(land, args, cbsUpdateFastNode,
sizeof(CBSFastBlockStruct));
}
static Res cbsInitZoned(Land land, ArgList args)
{
return cbsInitComm(land, args, cbsUpdateZonedNode,
sizeof(CBSZonedBlockStruct));
}
/* CBSFinish -- Finish a CBS structure
*
@ -353,7 +355,7 @@ static void cbsBlockDelete(CBS cbs, CBSBlock block)
/* make invalid */
block->limit = block->base;
PoolFree(cbsBlockPool(cbs), (Addr)block, sizeof(CBSBlockStruct));
PoolFree(cbsBlockPool(cbs), (Addr)block, cbs->blockStructSize);
}
static void cbsBlockShrunk(CBS cbs, CBSBlock block, Size oldSize)
@ -366,10 +368,7 @@ static void cbsBlockShrunk(CBS cbs, CBSBlock block, Size oldSize)
newSize = CBSBlockSize(block);
AVER(oldSize > newSize);
if (cbs->fastFind) {
SplayNodeRefresh(cbsSplay(cbs), cbsBlockTree(block));
AVER(CBSBlockSize(block) <= block->maxSize);
}
SplayNodeRefresh(cbsSplay(cbs), cbsBlockTree(block));
}
static void cbsBlockGrew(CBS cbs, CBSBlock block, Size oldSize)
@ -382,10 +381,7 @@ static void cbsBlockGrew(CBS cbs, CBSBlock block, Size oldSize)
newSize = CBSBlockSize(block);
AVER(oldSize < newSize);
if (cbs->fastFind) {
SplayNodeRefresh(cbsSplay(cbs), cbsBlockTree(block));
AVER(CBSBlockSize(block) <= block->maxSize);
}
SplayNodeRefresh(cbsSplay(cbs), cbsBlockTree(block));
}
/* cbsBlockAlloc -- allocate a new block and set its base and limit,
@ -401,7 +397,7 @@ static Res cbsBlockAlloc(CBSBlock *blockReturn, CBS cbs, Range range)
AVERT(CBS, cbs);
AVERT(Range, range);
res = PoolAlloc(&p, cbsBlockPool(cbs), sizeof(CBSBlockStruct),
res = PoolAlloc(&p, cbsBlockPool(cbs), cbs->blockStructSize,
/* withReservoirPermit */ FALSE);
if (res != ResOK)
goto failPoolAlloc;
@ -410,7 +406,8 @@ static Res cbsBlockAlloc(CBSBlock *blockReturn, CBS cbs, Range range)
TreeInit(cbsBlockTree(block));
block->base = RangeBase(range);
block->limit = RangeLimit(range);
block->maxSize = CBSBlockSize(block);
SplayNodeUpdate(cbsSplay(cbs), cbsBlockTree(block));
AVERT(CBSBlock, block);
*blockReturn = block;
@ -682,11 +679,9 @@ static Res cbsBlockDescribe(CBSBlock block, mps_lib_FILE *stream)
return ResFAIL;
res = WriteF(stream,
"[$P,$P) {$U, $B}",
"[$P,$P)",
(WriteFP)block->base,
(WriteFP)block->limit,
(WriteFU)block->maxSize,
(WriteFB)block->zones,
NULL);
return res;
}
@ -704,6 +699,65 @@ static Res cbsSplayNodeDescribe(Tree tree, mps_lib_FILE *stream)
return res;
}
static Res cbsFastBlockDescribe(CBSFastBlock block, mps_lib_FILE *stream)
{
Res res;
if (stream == NULL)
return ResFAIL;
res = WriteF(stream,
"[$P,$P) {$U}",
(WriteFP)block->cbsBlockStruct.base,
(WriteFP)block->cbsBlockStruct.limit,
(WriteFU)block->maxSize,
NULL);
return res;
}
static Res cbsFastSplayNodeDescribe(Tree tree, mps_lib_FILE *stream)
{
Res res;
if (tree == TreeEMPTY)
return ResFAIL;
if (stream == NULL)
return ResFAIL;
res = cbsFastBlockDescribe(cbsFastBlockOfTree(tree), stream);
return res;
}
static Res cbsZonedBlockDescribe(CBSZonedBlock block, mps_lib_FILE *stream)
{
Res res;
if (stream == NULL)
return ResFAIL;
res = WriteF(stream,
"[$P,$P) {$U, $B}",
(WriteFP)block->cbsFastBlockStruct.cbsBlockStruct.base,
(WriteFP)block->cbsFastBlockStruct.cbsBlockStruct.limit,
(WriteFU)block->cbsFastBlockStruct.maxSize,
(WriteFB)block->zones,
NULL);
return res;
}
static Res cbsZonedSplayNodeDescribe(Tree tree, mps_lib_FILE *stream)
{
Res res;
if (tree == TreeEMPTY)
return ResFAIL;
if (stream == NULL)
return ResFAIL;
res = cbsZonedBlockDescribe(cbsZonedBlockOfTree(tree), stream);
return res;
}
/* cbsIterate -- iterate over all blocks in CBS
*
@ -850,13 +904,13 @@ static Bool cbsFindFirst(Range rangeReturn, Range oldRangeReturn,
AVERT(Land, land);
cbs = cbsOfLand(land);
AVERT(CBS, cbs);
AVER(IsLandSubclass(cbsLand(cbs), CBSFastLandClass));
cbsEnter(cbs);
AVER(rangeReturn != NULL);
AVER(oldRangeReturn != NULL);
AVER(size > 0);
AVER(SizeIsAligned(size, LandAlignment(land)));
AVER(cbs->fastFind);
AVERT(FindDelete, findDelete);
METER_ACC(cbs->treeSearch, cbs->treeSize);
@ -912,15 +966,16 @@ static Bool cbsTestNodeInZones(SplayTree splay, Tree tree,
static Bool cbsTestTreeInZones(SplayTree splay, Tree tree,
void *closureP, Size closureSize)
{
CBSBlock block = cbsBlockOfTree(tree);
CBSFastBlock fastBlock = cbsFastBlockOfTree(tree);
CBSZonedBlock zonedBlock = cbsZonedBlockOfTree(tree);
cbsTestNodeInZonesClosure closure = closureP;
UNUSED(splay);
AVER(closureSize == sizeof(cbsTestNodeInZonesClosureStruct));
UNUSED(closureSize);
return block->maxSize >= closure->size &&
ZoneSetInter(block->zones, closure->zoneSet) != ZoneSetEMPTY;
return fastBlock->maxSize >= closure->size
&& ZoneSetInter(zonedBlock->zones, closure->zoneSet) != ZoneSetEMPTY;
}
@ -936,13 +991,13 @@ static Bool cbsFindLast(Range rangeReturn, Range oldRangeReturn,
AVERT(Land, land);
cbs = cbsOfLand(land);
AVERT(CBS, cbs);
AVER(IsLandSubclass(cbsLand(cbs), CBSFastLandClass));
cbsEnter(cbs);
AVER(rangeReturn != NULL);
AVER(oldRangeReturn != NULL);
AVER(size > 0);
AVER(SizeIsAligned(size, LandAlignment(land)));
AVER(cbs->fastFind);
AVERT(FindDelete, findDelete);
METER_ACC(cbs->treeSearch, cbs->treeSize);
@ -975,21 +1030,21 @@ static Bool cbsFindLargest(Range rangeReturn, Range oldRangeReturn,
AVERT(Land, land);
cbs = cbsOfLand(land);
AVERT(CBS, cbs);
AVER(IsLandSubclass(cbsLand(cbs), CBSFastLandClass));
cbsEnter(cbs);
AVER(rangeReturn != NULL);
AVER(oldRangeReturn != NULL);
AVER(cbs->fastFind);
AVERT(FindDelete, findDelete);
if (!SplayTreeIsEmpty(cbsSplay(cbs))) {
RangeStruct range;
CBSBlock block;
Tree tree = TreeEMPTY; /* suppress "may be used uninitialized" */
Size maxSize;
maxSize = cbsBlockOfTree(SplayTreeRoot(cbsSplay(cbs)))->maxSize;
maxSize = cbsFastBlockOfTree(SplayTreeRoot(cbsSplay(cbs)))->maxSize;
if (maxSize >= size) {
CBSBlock block;
METER_ACC(cbs->treeSearch, cbs->treeSize);
found = SplayFindFirst(&tree, cbsSplay(cbs), &cbsTestNode,
&cbsTestTree, NULL, maxSize);
@ -1024,6 +1079,7 @@ static Res cbsFindInZones(Range rangeReturn, Range oldRangeReturn,
AVERT(Land, land);
cbs = cbsOfLand(land);
AVERT(CBS, cbs);
AVER(IsLandSubclass(cbsLand(cbs), CBSZonedLandClass));
/* AVERT(ZoneSet, zoneSet); */
AVER(BoolCheck(high));
@ -1089,6 +1145,7 @@ static Res cbsDescribe(Land land, mps_lib_FILE *stream)
{
CBS cbs;
Res res;
Res (*describe)(Tree, mps_lib_FILE *);
if (!TESTT(Land, land))
return ResFAIL;
@ -1101,15 +1158,20 @@ static Res cbsDescribe(Land land, mps_lib_FILE *stream)
res = WriteF(stream,
"CBS $P {\n", (WriteFP)cbs,
" blockPool: $P\n", (WriteFP)cbsBlockPool(cbs),
" fastFind: $U\n", (WriteFU)cbs->fastFind,
" inCBS: $U\n", (WriteFU)cbs->inCBS,
" ownPool: $U\n", (WriteFU)cbs->ownPool,
" zoned: $U\n", (WriteFU)cbs->zoned,
" treeSize: $U\n", (WriteFU)cbs->treeSize,
NULL);
if (res != ResOK) return res;
res = SplayTreeDescribe(cbsSplay(cbs), stream, &cbsSplayNodeDescribe);
if (IsLandSubclass(land, CBSZonedLandClass))
describe = cbsZonedSplayNodeDescribe;
else if (IsLandSubclass(land, CBSFastLandClass))
describe = cbsFastSplayNodeDescribe;
else
describe = cbsSplayNodeDescribe;
res = SplayTreeDescribe(cbsSplay(cbs), stream, describe);
if (res != ResOK) return res;
res = METER_WRITE(cbs->treeSearch, stream);
@ -1137,6 +1199,22 @@ DEFINE_LAND_CLASS(CBSLandClass, class)
AVERT(LandClass, class);
}
DEFINE_LAND_CLASS(CBSFastLandClass, class)
{
INHERIT_CLASS(class, CBSLandClass);
class->name = "FASTCBS";
class->init = cbsInitFast;
AVERT(LandClass, class);
}
DEFINE_LAND_CLASS(CBSZonedLandClass, class)
{
INHERIT_CLASS(class, CBSFastLandClass);
class->name = "ZONEDCBS";
class->init = cbsInitZoned;
AVERT(LandClass, class);
}
/* C. COPYRIGHT AND LICENSE
*

View file

@ -15,36 +15,36 @@
#include "range.h"
#include "splay.h"
/* TODO: There ought to be different levels of CBS block with inheritance
so that CBSs without fastFind don't allocate the maxSize and zones fields,
and CBSs without zoned don't allocate the zones field. */
typedef struct CBSBlockStruct *CBSBlock;
typedef struct CBSBlockStruct {
TreeStruct treeStruct;
Addr base;
Addr limit;
Size maxSize; /* accurate maximum block size of sub-tree */
ZoneSet zones; /* union zone set of all ranges in sub-tree */
} CBSBlockStruct;
typedef struct CBSFastBlockStruct *CBSFastBlock;
typedef struct CBSFastBlockStruct {
struct CBSBlockStruct cbsBlockStruct;
Size maxSize; /* accurate maximum block size of sub-tree */
} CBSFastBlockStruct;
typedef struct CBSZonedBlockStruct *CBSZonedBlock;
typedef struct CBSZonedBlockStruct {
struct CBSFastBlockStruct cbsFastBlockStruct;
ZoneSet zones; /* union zone set of all ranges in sub-tree */
} CBSZonedBlockStruct;
typedef struct CBSStruct *CBS;
extern Bool CBSCheck(CBS cbs);
extern LandClass CBSLandClassGet(void);
extern LandClass CBSFastLandClassGet(void);
extern LandClass CBSZonedLandClassGet(void);
extern const struct mps_key_s _mps_key_cbs_block_pool;
#define CBSBlockPool (&_mps_key_cbs_block_pool)
#define CBSBlockPool_FIELD pool
extern const struct mps_key_s _mps_key_cbs_fast_find;
#define CBSFastFind (&_mps_key_cbs_fast_find)
#define CBSFastFind_FIELD b
extern const struct mps_key_s _mps_key_cbs_zoned;
#define CBSZoned (&_mps_key_cbs_zoned)
#define CBSZoned_FIELD b
/* TODO: Passing booleans to affect behaviour is ugly and error-prone. */
#endif /* cbs_h */

View file

@ -370,20 +370,23 @@ static void find(TestState state, Size size, Bool high, FindDelete findDelete)
remainderLimit = origLimit = addrOfIndex(state, expectedLimit);
switch(findDelete) {
case FindDeleteNONE: {
case FindDeleteNONE:
/* do nothing */
} break;
case FindDeleteENTIRE: {
break;
case FindDeleteENTIRE:
remainderBase = remainderLimit;
} break;
case FindDeleteLOW: {
break;
case FindDeleteLOW:
expectedLimit = expectedBase + size;
remainderBase = addrOfIndex(state, expectedLimit);
} break;
case FindDeleteHIGH: {
break;
case FindDeleteHIGH:
expectedBase = expectedLimit - size;
remainderLimit = addrOfIndex(state, expectedBase);
} break;
break;
default:
cdie(0, "invalid findDelete");
break;
}
if (findDelete != FindDeleteNONE) {
@ -455,9 +458,7 @@ static void test(TestState state, unsigned n) {
size = fbmRnd(ArraySize / 10) + 1;
high = fbmRnd(2) ? TRUE : FALSE;
switch(fbmRnd(6)) {
case 0:
case 1:
case 2: findDelete = FindDeleteNONE; break;
default: findDelete = FindDeleteNONE; break;
case 3: findDelete = FindDeleteLOW; break;
case 4: findDelete = FindDeleteHIGH; break;
case 5: findDelete = FindDeleteENTIRE; break;
@ -522,8 +523,7 @@ extern int main(int argc, char *argv[])
/* 1. Test CBS */
MPS_ARGS_BEGIN(args) {
MPS_ARGS_ADD(args, CBSFastFind, TRUE);
die((mps_res_t)LandInit(cbs, CBSLandClassGet(), arena, align, NULL, args),
die((mps_res_t)LandInit(cbs, CBSFastLandClassGet(), arena, align, NULL, args),
"failed to initialise CBS");
} MPS_ARGS_END(args);
state.align = align;
@ -549,7 +549,7 @@ extern int main(int argc, char *argv[])
for (i = 0; i < 2; ++i) {
MPS_ARGS_BEGIN(piArgs) {
MPS_ARGS_ADD(piArgs, MPS_KEY_MFS_UNIT_SIZE, sizeof(CBSBlockStruct));
MPS_ARGS_ADD(piArgs, MPS_KEY_MFS_UNIT_SIZE, sizeof(CBSFastBlockStruct));
MPS_ARGS_ADD(piArgs, MPS_KEY_EXTEND_BY, ArenaAlign(arena));
MPS_ARGS_ADD(piArgs, MFSExtendSelf, i);
MPS_ARGS_DONE(piArgs);
@ -557,9 +557,8 @@ extern int main(int argc, char *argv[])
} MPS_ARGS_END(piArgs);
MPS_ARGS_BEGIN(args) {
MPS_ARGS_ADD(args, CBSFastFind, TRUE);
MPS_ARGS_ADD(args, CBSBlockPool, mfs);
die((mps_res_t)LandInit(cbs, CBSLandClassGet(), arena, align, NULL,
die((mps_res_t)LandInit(cbs, CBSFastLandClassGet(), arena, align, NULL,
args),
"failed to initialise CBS");
} MPS_ARGS_END(args);

View file

@ -1020,6 +1020,8 @@ extern LandClass LandClassGet(void);
#define LAND_SUPERCLASS(className) ((LandClass)SUPERCLASS(className))
#define DEFINE_LAND_CLASS(className, var) \
DEFINE_ALIAS_CLASS(className, LandClass, var)
#define IsLandSubclass(land, className) \
IsSubclassPoly((land)->class, className ## Get())
/* Stack Probe */

View file

@ -659,8 +659,7 @@ typedef struct CBSStruct {
SplayTreeStruct splayTreeStruct;
STATISTIC_DECL(Count treeSize);
Pool blockPool; /* pool that manages blocks */
Bool fastFind; /* maintain and use size property? */
Bool zoned; /* maintain and use zone property? */
Size blockStructSize; /* size of block structure */
Bool inCBS; /* prevent reentrance */
Bool ownPool; /* did we create blockPool? */
/* meters for sizes of search structures at each op */

View file

@ -280,8 +280,7 @@ static Res MVTInit(Pool pool, ArgList args)
abqDepth = 3;
MPS_ARGS_BEGIN(liArgs) {
MPS_ARGS_ADD(liArgs, CBSFastFind, TRUE);
res = LandInit(MVTCBS(mvt), CBSLandClassGet(), arena, align, mvt, liArgs);
res = LandInit(MVTCBS(mvt), CBSFastLandClassGet(), arena, align, mvt, liArgs);
} MPS_ARGS_END(liArgs);
if (res != ResOK)
goto failCBS;

View file

@ -524,8 +524,7 @@ static Res MVFFInit(Pool pool, ArgList args)
goto failFreelistInit;
MPS_ARGS_BEGIN(liArgs) {
MPS_ARGS_ADD(liArgs, CBSFastFind, TRUE);
res = LandInit(CBSOfMVFF(mvff), CBSLandClassGet(), arena, align, mvff, liArgs);
res = LandInit(CBSOfMVFF(mvff), CBSFastLandClassGet(), arena, align, mvff, liArgs);
} MPS_ARGS_END(liArgs);
if (res != ResOK)
goto failCBSInit;

View file

@ -945,13 +945,12 @@ Bool SplayTreeNeighbours(Tree *leftReturn, Tree *rightReturn,
/* SplayTreeFirst, SplayTreeNext -- iterators
*
* SplayTreeFirst receives a key that must precede all
* nodes in the tree. It returns TreeEMPTY if the tree is empty.
* Otherwise, it splays the tree to the first node, and returns the
* new root.
* SplayTreeFirst returns TreeEMPTY if the tree is empty. Otherwise,
* it splays the tree to the first node, and returns the new root.
*
* SplayTreeNext takes a tree and splays it to the successor of a key
* and returns the new root. Returns TreeEMPTY is there are no successors.
* and returns the new root. Returns TreeEMPTY is there are no
* successors.
*
* SplayTreeFirst and SplayTreeNext do not require the tree to remain
* unmodified.
@ -1006,7 +1005,7 @@ Tree SplayTreeNext(SplayTree splay, TreeKey oldKey) {
*/
static Res SplayNodeDescribe(Tree node, mps_lib_FILE *stream,
SplayNodeDescribeMethod nodeDescribe) {
TreeDescribeMethod nodeDescribe) {
Res res;
#if defined(AVER_AND_CHECK)
@ -1318,13 +1317,26 @@ void SplayNodeRefresh(SplayTree splay, Tree node)
}
/* SplayNodeUpdate -- update the client property without splaying */
void SplayNodeUpdate(SplayTree splay, Tree node)
{
AVERT(SplayTree, splay);
AVERT(Tree, node);
AVER(SplayTreeIsEmpty(splay)); /* otherwise, call SplayNodeRefresh */
AVER(SplayHasUpdate(splay)); /* otherwise, why call? */
splay->updateNode(splay, node);
}
/* SplayTreeDescribe -- Describe a splay tree
*
* See <design/splay/#function.splay.tree.describe>.
*/
Res SplayTreeDescribe(SplayTree splay, mps_lib_FILE *stream,
SplayNodeDescribeMethod nodeDescribe) {
TreeDescribeMethod nodeDescribe) {
Res res;
#if defined(AVER_AND_CHECK)

View file

@ -19,7 +19,6 @@ typedef Bool (*SplayTestNodeMethod)(SplayTree splay, Tree node,
void *closureP, Size closureS);
typedef Bool (*SplayTestTreeMethod)(SplayTree splay, Tree node,
void *closureP, Size closureS);
typedef Res (*SplayNodeDescribeMethod)(Tree node, mps_lib_FILE *stream);
typedef void (*SplayUpdateNodeMethod)(SplayTree splay, Tree node);
extern void SplayTrivUpdate(SplayTree splay, Tree node);
@ -70,9 +69,10 @@ extern Bool SplayFindLast(Tree *nodeReturn, SplayTree splay,
void *closureP, Size closureS);
extern void SplayNodeRefresh(SplayTree splay, Tree node);
extern void SplayNodeUpdate(SplayTree splay, Tree node);
extern Res SplayTreeDescribe(SplayTree splay, mps_lib_FILE *stream,
SplayNodeDescribeMethod nodeDescribe);
TreeDescribeMethod nodeDescribe);
extern void SplayDebugUpdate(SplayTree splay, Tree tree);

View file

@ -25,6 +25,8 @@ typedef struct TreeStruct {
Tree left, right;
} TreeStruct;
typedef Res (*TreeDescribeMethod)(Tree tree, mps_lib_FILE *stream);
/* TreeKey and TreeCompare -- ordered binary trees
*

View file

@ -1,7 +1,7 @@
.. mode: -*- rst -*-
Coalescing block structure
==========================
Coalescing block structures
===========================
:Tag: design.mps.cbs
:Author: Gavin Matthews
@ -74,6 +74,21 @@ _`.function.class`: The function ``CBSLandClassGet()`` returns the CBS
class, a subclass of ``LandClass`` suitable for passing to
``LandCreate()`` or ``LandInit()``.
``LandClass CBSFastLandClassGet(void)``
_`.function.class`: Returns a subclass of ``CBSLandClass`` that
maintains, for each subtree, the size of the largest block in that
subtree. This enables the ``LandFindFirst()``, ``LandFindLast()``, and
``LandFindLargest()`` generic functions.
``LandClass CBSZonedLandClassGet(void)``
_`.function.class`: Returns a subclass of ``CBSFastLandClass`` that
maintains, for each subtree, the union of the zone sets of all ranges
in that subtree. This enables the ``LandFindInZones()`` generic
function.
Keyword arguments
.................
@ -97,27 +112,17 @@ following optional keyword arguments:
(This feature is used by the arena to bootstrap its own CBS of free
memory.)
* ``CBSFastFind`` (type ``Bool``; default ``FALSE``). If ``TRUE``,
causes the CBS to maintain, for each subtree, the size of the
largest block in that subtree. This enables the ``LandFindFirst()``,
``LandFindLast()``, and ``LandFindLargest()`` generic functions.
* ``CBSZoned`` (type ``Bool``; default ``FALSE``). If ``TRUE``, caused
the CBS to maintain, for each subtree, the union of the zone sets of
all ranges in that subtree. This enables the ``LandFindInZones()``
generic function.
Limitations
...........
_`.limit.find`: CBS does not support the ``LandFindFirst()``,
``LandFindLast()``, and ``LandFindLargest()`` generic functions unless
the ``CBSFastFind`` keyword argument was set to ``TRUE``.
_`.limit.find`: ``CBSLandClass`` does not support the
``LandFindFirst()``, ``LandFindLast()``, and ``LandFindLargest()``
generic functions (the subclasses do support these operations).
_`.limit.zones`: CBS does not support the ``LandFindInZones()``
generic function unless the ``CBSFastFind`` and ``CBSZoned`` keyword
arguments were both set to ``TRUE``.
_`.limit.zones`: ``CBSLandClass`` and ``CBSFastLandClass`` do not
support the ``LandFindInZones()`` generic function (the suclass
``CBSZonedLandClass`` does support this operation).
_`.limit.iterate`: CBS does not support visitors setting
``deleteReturn`` to ``TRUE`` when iterating over ranges with
@ -134,18 +139,18 @@ Splay tree
..........
_`.impl.splay`: The CBS is implemented using a splay tree (see
design.mps.splay_). Each splay tree node is embedded in a ``CBSBlock``
that represents a semi-open address range. The key passed for
comparison is the base of another range.
design.mps.splay_). Each splay tree node is embedded in a block
structure that represents a semi-open address range. The key passed
for comparison is the base of another range.
.. _design.mps.splay: splay
_`.impl.splay.fast-find`: ``cbsFindFirst()`` and ``cbsFindLast()`` use
the update/refresh facility of splay trees to store, in each
``CBSBlock``, an accurate summary of the maximum block size in the
tree rooted at the corresponding splay node. This allows rapid
location of the first or last suitable block, and very rapid failure
if there is no suitable block.
_`.impl.splay.fast-find`: In the ``CBSFastLandClass`` class,
``cbsFindFirst()`` and ``cbsFindLast()`` use the update/refresh
facility of splay trees to store, in each block, an accurate summary
of the maximum block size in the tree rooted at the corresponding
splay node. This allows rapid location of the first or last suitable
block, and very rapid failure if there is no suitable block.
_`.impl.find-largest`: ``cbsFindLargest()`` simply finds out the size
of the largest block in the CBS from the root of the tree, using
@ -154,10 +159,11 @@ size. This takes time proportional to the logarithm of the size of the
free list, so it's about the best you can do without maintaining a
separate priority queue, just to do ``cbsFindLargest()``.
_`.impl.splay.zones`: ``cbsFindInZones()`` uses the update/refresh
facility of splay trees to store, in each ``CBSBlock()``, the union of
the zones of the ranges in the tree rooted at the corresponding splay
node. This allows rapid location of a block in a set of zones.
_`.impl.splay.zones`: In the ``CBSZonedLandClass`` class,
``cbsFindInZones()`` uses the update/refresh facility of splay trees
to store, in each block, the union of the zones of the ranges in the
tree rooted at the corresponding splay node. This allows rapid
location of a block in a set of zones.
Low memory behaviour
@ -166,7 +172,7 @@ Low memory behaviour
_`.impl.low-mem`: When the CBS tries to allocate a new ``CBSBlock``
structure for a new isolated range as a result of either
``LandInsert()`` or ``LandDelete()``, and there is insufficient memory
to allocation the ``CBSBlock`` structure, then the range is not added
to allocation the block structure, then the range is not added
to the CBS or deleted from it, and the call to ``LandInsert()`` or
``LandDelete()`` returns ``ResMEMORY``.

View file

@ -0,0 +1,427 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="613.48077"
height="173.08984"
id="svg3079"
version="1.1"
inkscape:version="0.48.2 r9819"
sodipodi:docname="splay-assemble.svg">
<defs
id="defs3081">
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0"
refX="0"
id="Arrow1Mend"
style="overflow:visible">
<path
id="path3929"
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
transform="matrix(-0.4,0,0,-0.4,-4,0)"
inkscape:connector-curvature="0" />
</marker>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1"
inkscape:cx="468.97256"
inkscape:cy="37.753236"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:window-width="1204"
inkscape:window-height="920"
inkscape:window-x="139"
inkscape:window-y="0"
inkscape:window-maximized="0"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0">
<inkscape:grid
type="xygrid"
id="grid3087"
empspacing="5"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true" />
</sodipodi:namedview>
<metadata
id="metadata3084">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(20.211521,-49.088745)">
<path
inkscape:connector-curvature="0"
id="path3873"
d="m 45.528859,138.17859 40,-40 40.000001,40"
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
sodipodi:nodetypes="ccc" />
<path
sodipodi:type="star"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="path3859"
sodipodi:sides="3"
sodipodi:cx="95"
sodipodi:cy="182.36218"
sodipodi:r1="15"
sodipodi:r2="2.5"
sodipodi:arg1="-1.5707963"
sodipodi:arg2="-0.52359881"
inkscape:flatsided="true"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 95,167.36218 12.99038,22.5 -25.980761,0 z"
inkscape:transform-center-y="-1.25"
transform="translate(-49.471141,-29.183593)" />
<text
xml:space="preserve"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="44.134338"
y="182.17859"
id="text3861"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3863"
x="44.134338"
y="182.17859"
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana">A</tspan></text>
<path
transform="translate(30.528859,-29.183593)"
inkscape:transform-center-y="-1.25"
d="m 95,167.36218 12.99038,22.5 -25.980761,0 z"
inkscape:randomized="0"
inkscape:rounded="0"
inkscape:flatsided="true"
sodipodi:arg2="-0.52359881"
sodipodi:arg1="-1.5707963"
sodipodi:r2="2.5"
sodipodi:r1="15"
sodipodi:cy="182.36218"
sodipodi:cx="95"
sodipodi:sides="3"
id="path3865"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
sodipodi:type="star" />
<text
sodipodi:linespacing="125%"
id="text3867"
y="182.17859"
x="126.92338"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana"
y="182.17859"
x="126.92338"
id="tspan3869"
sodipodi:role="line">B</tspan></text>
<path
sodipodi:type="arc"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="path3089"
sodipodi:cx="115"
sodipodi:cy="157.36218"
sodipodi:rx="5"
sodipodi:ry="5"
d="m 120,157.36218 c 0,2.76143 -2.23858,5 -5,5 -2.76142,0 -5,-2.23857 -5,-5 0,-2.76142 2.23858,-5 5,-5 2.76142,0 5,2.23858 5,5 z"
transform="translate(-29.471141,-59.183594)" />
<path
sodipodi:type="star"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="path3877"
sodipodi:sides="3"
sodipodi:cx="95"
sodipodi:cy="182.36218"
sodipodi:r1="15"
sodipodi:r2="2.5"
sodipodi:arg1="-1.5707963"
sodipodi:arg2="-0.52359881"
inkscape:flatsided="true"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 95,167.36218 12.99038,22.5 -25.980761,0 z"
inkscape:transform-center-y="-1.25"
transform="translate(82.528859,-49.183594)" />
<text
xml:space="preserve"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="177.5992"
y="162.17859"
id="text3879"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3881"
x="177.5992"
y="162.17859"
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana">R</tspan></text>
<path
transform="translate(-69.471141,-19.183593)"
d="m 120,157.36218 c 0,2.76143 -2.23858,5 -5,5 -2.76142,0 -5,-2.23857 -5,-5 0,-2.76142 2.23858,-5 5,-5 2.76142,0 5,2.23858 5,5 z"
sodipodi:ry="5"
sodipodi:rx="5"
sodipodi:cy="157.36218"
sodipodi:cx="115"
id="path3875"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
sodipodi:type="arc" />
<text
sodipodi:linespacing="125%"
id="text3909"
y="102.36218"
x="281.88461"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana"
y="102.36218"
x="281.88461"
sodipodi:role="line"
id="tspan3913"></tspan><tspan
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana"
y="132.36218"
x="281.88461"
sodipodi:role="line"
id="tspan3561">assemble</tspan></text>
<path
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
d="m 242.25962,152.36218 80,0"
id="path3915"
inkscape:connector-curvature="0" />
<text
sodipodi:linespacing="125%"
id="text4361"
y="102.17859"
x="67.528877"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana"
y="102.17859"
x="67.528877"
id="tspan4363"
sodipodi:role="line">x</tspan></text>
<text
xml:space="preserve"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="29.528843"
y="142.17859"
id="text4365"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan4367"
x="29.528843"
y="142.17859"
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana">y</tspan></text>
<path
transform="translate(-101.47114,-49.183594)"
inkscape:transform-center-y="-1.25"
d="m 95,167.36218 12.99038,22.5 -25.980761,0 z"
inkscape:randomized="0"
inkscape:rounded="0"
inkscape:flatsided="true"
sodipodi:arg2="-0.52359881"
sodipodi:arg1="-1.5707963"
sodipodi:r2="2.5"
sodipodi:r1="15"
sodipodi:cy="182.36218"
sodipodi:cx="95"
sodipodi:sides="3"
id="path3050"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
sodipodi:type="star" />
<text
sodipodi:linespacing="125%"
id="text3052"
y="162.17859"
x="-6.5414691"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana"
y="162.17859"
x="-6.5414691"
id="tspan3054"
sodipodi:role="line">L</tspan></text>
<path
sodipodi:nodetypes="ccc"
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 395.52886,118.17859 92,-60.000001 92,60.000001"
id="path3601"
inkscape:connector-curvature="0" />
<path
transform="translate(352.52886,10.816406)"
inkscape:transform-center-y="-1.25"
d="m 95,167.36218 12.99038,22.5 -25.980761,0 z"
inkscape:randomized="0"
inkscape:rounded="0"
inkscape:flatsided="true"
sodipodi:arg2="-0.52359881"
sodipodi:arg1="-1.5707963"
sodipodi:r2="2.5"
sodipodi:r1="15"
sodipodi:cy="182.36218"
sodipodi:cx="95"
sodipodi:sides="3"
id="path3603"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
sodipodi:type="star" />
<text
sodipodi:linespacing="125%"
id="text3605"
y="222.17859"
x="446.13434"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana"
y="222.17859"
x="446.13434"
id="tspan3607"
sodipodi:role="line">A</tspan></text>
<path
sodipodi:type="star"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="path3609"
sodipodi:sides="3"
sodipodi:cx="95"
sodipodi:cy="182.36218"
sodipodi:r1="15"
sodipodi:r2="2.5"
sodipodi:arg1="-1.5707963"
sodipodi:arg2="-0.52359881"
inkscape:flatsided="true"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 95,167.36218 12.99038,22.5 -25.980761,0 z"
inkscape:transform-center-y="-1.25"
transform="translate(432.52886,10.816406)" />
<text
xml:space="preserve"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="528.92334"
y="222.17859"
id="text3611"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3613"
x="528.92334"
y="222.17859"
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana">B</tspan></text>
<path
transform="translate(372.52886,-99.183591)"
d="m 120,157.36218 c 0,2.76143 -2.23858,5 -5,5 -2.76142,0 -5,-2.23857 -5,-5 0,-2.76142 2.23858,-5 5,-5 2.76142,0 5,2.23858 5,5 z"
sodipodi:ry="5"
sodipodi:rx="5"
sodipodi:cy="157.36218"
sodipodi:cx="115"
id="path3615"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
sodipodi:type="arc" />
<path
transform="translate(484.52886,-49.183595)"
inkscape:transform-center-y="-1.25"
d="m 95,167.36218 12.99038,22.5 -25.980761,0 z"
inkscape:randomized="0"
inkscape:rounded="0"
inkscape:flatsided="true"
sodipodi:arg2="-0.52359881"
sodipodi:arg1="-1.5707963"
sodipodi:r2="2.5"
sodipodi:r1="15"
sodipodi:cy="182.36218"
sodipodi:cx="95"
sodipodi:sides="3"
id="path3617"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
sodipodi:type="star" />
<text
sodipodi:linespacing="125%"
id="text3619"
y="162.17859"
x="579.59918"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana"
y="162.17859"
x="579.59918"
id="tspan3621"
sodipodi:role="line">R</tspan></text>
<text
xml:space="preserve"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="469.52887"
y="62.178589"
id="text3625"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3627"
x="469.52887"
y="62.178589"
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana">x</tspan></text>
<path
sodipodi:type="star"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="path3633"
sodipodi:sides="3"
sodipodi:cx="95"
sodipodi:cy="182.36218"
sodipodi:r1="15"
sodipodi:r2="2.5"
sodipodi:arg1="-1.5707963"
sodipodi:arg2="-0.52359881"
inkscape:flatsided="true"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 95,167.36218 12.99038,22.5 -25.980761,0 z"
inkscape:transform-center-y="-1.25"
transform="translate(300.52886,-49.183595)" />
<text
xml:space="preserve"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="395.45853"
y="162.17859"
id="text3635"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3637"
x="395.45853"
y="162.17859"
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana">L</tspan></text>
<path
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 470,93.089844 -40,-40"
id="path3639"
inkscape:connector-curvature="0"
transform="translate(-22.471141,85.088745)" />
<path
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 550,93.089844 40,-40"
id="path3641"
inkscape:connector-curvature="0"
transform="translate(-22.471141,85.088745)" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 19 KiB

View file

@ -0,0 +1,437 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="529.48077"
height="173.08984"
id="svg3079"
version="1.1"
inkscape:version="0.48.2 r9819"
sodipodi:docname="splay-link-left.svg">
<defs
id="defs3081">
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0"
refX="0"
id="Arrow1Mend"
style="overflow:visible">
<path
id="path3929"
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
transform="matrix(-0.4,0,0,-0.4,-4,0)"
inkscape:connector-curvature="0" />
</marker>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1"
inkscape:cx="471.23218"
inkscape:cy="73.753236"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:window-width="1204"
inkscape:window-height="920"
inkscape:window-x="7"
inkscape:window-y="19"
inkscape:window-maximized="0"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0">
<inkscape:grid
type="xygrid"
id="grid3087"
empspacing="5"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true" />
</sodipodi:namedview>
<metadata
id="metadata3084">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(22.471141,-85.088745)">
<path
inkscape:connector-curvature="0"
id="path3873"
d="m 441.26924,134.17859 -40,-40 -40,40"
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
sodipodi:nodetypes="ccc" />
<path
sodipodi:type="star"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="path3859"
sodipodi:sides="3"
sodipodi:cx="95"
sodipodi:cy="182.36218"
sodipodi:r1="15"
sodipodi:r2="2.5"
sodipodi:arg1="-1.5707963"
sodipodi:arg2="-0.52359881"
inkscape:flatsided="true"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 95,167.36218 12.99038,22.5 -25.980761,0 z"
inkscape:transform-center-y="-1.25"
transform="matrix(-1,0,0,1,536.26924,-33.183593)" />
<text
xml:space="preserve"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="441.26923"
y="178.17859"
id="text3861"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3863"
x="441.26923"
y="178.17859"
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana">B</tspan></text>
<path
transform="matrix(-1,0,0,1,456.26924,-33.183593)"
inkscape:transform-center-y="-1.25"
d="m 95,167.36218 12.99038,22.5 -25.980761,0 z"
inkscape:randomized="0"
inkscape:rounded="0"
inkscape:flatsided="true"
sodipodi:arg2="-0.52359881"
sodipodi:arg1="-1.5707963"
sodipodi:r2="2.5"
sodipodi:r1="15"
sodipodi:cy="182.36218"
sodipodi:cx="95"
sodipodi:sides="3"
id="path3865"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
sodipodi:type="star" />
<text
sodipodi:linespacing="125%"
id="text3867"
y="178.17859"
x="359.87473"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana"
y="178.17859"
x="359.87473"
id="tspan3869"
sodipodi:role="line">A</tspan></text>
<path
sodipodi:type="arc"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="path3089"
sodipodi:cx="115"
sodipodi:cy="157.36218"
sodipodi:rx="5"
sodipodi:ry="5"
d="m 120,157.36218 c 0,2.76143 -2.23858,5 -5,5 -2.76142,0 -5,-2.23857 -5,-5 0,-2.76142 2.23858,-5 5,-5 2.76142,0 5,2.23858 5,5 z"
transform="matrix(-1,0,0,1,516.26924,-63.183594)" />
<path
sodipodi:type="star"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="path3877"
sodipodi:sides="3"
sodipodi:cx="95"
sodipodi:cy="182.36218"
sodipodi:r1="15"
sodipodi:r2="2.5"
sodipodi:arg1="-1.5707963"
sodipodi:arg2="-0.52359881"
inkscape:flatsided="true"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 95,167.36218 12.99038,22.5 -25.980761,0 z"
inkscape:transform-center-y="-1.25"
transform="matrix(-1,0,0,1,404.26924,-53.183594)" />
<text
xml:space="preserve"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="306.83173"
y="158.17859"
id="text3879"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3881"
x="306.83173"
y="158.17859"
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana">L</tspan></text>
<path
transform="matrix(-1,0,0,1,556.26924,-23.183593)"
d="m 120,157.36218 c 0,2.76143 -2.23858,5 -5,5 -2.76142,0 -5,-2.23857 -5,-5 0,-2.76142 2.23858,-5 5,-5 2.76142,0 5,2.23858 5,5 z"
sodipodi:ry="5"
sodipodi:rx="5"
sodipodi:cy="157.36218"
sodipodi:cx="115"
id="path3875"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
sodipodi:type="arc" />
<text
sodipodi:linespacing="125%"
id="text3909"
y="118.36218"
x="222.87442"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana"
y="118.36218"
x="222.87442"
id="tspan3911"
sodipodi:role="line">link</tspan><tspan
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana"
y="148.36218"
x="222.87442"
sodipodi:role="line"
id="tspan3913">left</tspan></text>
<path
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
d="m 264.53848,168.36218 -80,0"
id="path3915"
inkscape:connector-curvature="0" />
<text
sodipodi:linespacing="125%"
id="text4361"
y="98.178589"
x="419.26923"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana"
y="98.178589"
x="419.26923"
id="tspan4363"
sodipodi:role="line">x</tspan></text>
<text
xml:space="preserve"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="457.26926"
y="138.17859"
id="text4365"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan4367"
x="457.26926"
y="138.17859"
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana">y</tspan></text>
<path
transform="matrix(-1,0,0,1,588.26924,-53.183594)"
inkscape:transform-center-y="-1.25"
d="m 95,167.36218 12.99038,22.5 -25.980761,0 z"
inkscape:randomized="0"
inkscape:rounded="0"
inkscape:flatsided="true"
sodipodi:arg2="-0.52359881"
sodipodi:arg1="-1.5707963"
sodipodi:r2="2.5"
sodipodi:r1="15"
sodipodi:cy="182.36218"
sodipodi:cx="95"
sodipodi:sides="3"
id="path3050"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
sodipodi:type="star" />
<text
sodipodi:linespacing="125%"
id="text3052"
y="158.17859"
x="490.90207"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana"
y="158.17859"
x="490.90207"
id="tspan3054"
sodipodi:role="line">R</tspan></text>
<path
sodipodi:nodetypes="ccc"
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m -11.72114,126.67859 42.99038,47.5 -40.0000004,40"
id="path3094"
inkscape:connector-curvature="0" />
<path
transform="matrix(-1,0,0,1,176.26924,-53.183594)"
inkscape:transform-center-y="-1.25"
d="m 95,167.36218 12.99038,22.5 -25.980761,0 z"
inkscape:randomized="0"
inkscape:rounded="0"
inkscape:flatsided="true"
sodipodi:arg2="-0.52359881"
sodipodi:arg1="-1.5707963"
sodipodi:r2="2.5"
sodipodi:r1="15"
sodipodi:cy="182.36218"
sodipodi:cx="95"
sodipodi:sides="3"
id="path3096"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
sodipodi:type="star" />
<text
sodipodi:linespacing="125%"
id="text3098"
y="158.17859"
x="81.269226"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana"
y="158.17859"
x="81.269226"
id="tspan3100"
sodipodi:role="line">B</tspan></text>
<path
sodipodi:type="star"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="path3102"
sodipodi:sides="3"
sodipodi:cx="95"
sodipodi:cy="182.36218"
sodipodi:r1="15"
sodipodi:r2="2.5"
sodipodi:arg1="-1.5707963"
sodipodi:arg2="-0.52359881"
inkscape:flatsided="true"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 95,167.36218 12.99038,22.5 -25.980761,0 z"
inkscape:transform-center-y="-1.25"
transform="matrix(-1,0,0,1,86.26924,46.816406)" />
<text
xml:space="preserve"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="-10.125278"
y="258.17859"
id="text3104"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3106"
x="-10.125278"
y="258.17859"
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana">A</tspan></text>
<path
transform="matrix(-1,0,0,1,146.26924,16.816405)"
d="m 120,157.36218 c 0,2.76143 -2.23858,5 -5,5 -2.76142,0 -5,-2.23857 -5,-5 0,-2.76142 2.23858,-5 5,-5 2.76142,0 5,2.23858 5,5 z"
sodipodi:ry="5"
sodipodi:rx="5"
sodipodi:cy="157.36218"
sodipodi:cx="115"
id="path3108"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
sodipodi:type="arc" />
<path
transform="matrix(-1,0,0,1,86.26924,-53.183595)"
inkscape:transform-center-y="-1.25"
d="m 95,167.36218 12.99038,22.5 -25.980761,0 z"
inkscape:randomized="0"
inkscape:rounded="0"
inkscape:flatsided="true"
sodipodi:arg2="-0.52359881"
sodipodi:arg1="-1.5707963"
sodipodi:r2="2.5"
sodipodi:r1="15"
sodipodi:cy="182.36218"
sodipodi:cx="95"
sodipodi:sides="3"
id="path3110"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
sodipodi:type="star" />
<text
sodipodi:linespacing="125%"
id="text3112"
y="158.17859"
x="-11.168246"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana"
y="158.17859"
x="-11.168246"
id="tspan3114"
sodipodi:role="line">L</tspan></text>
<path
sodipodi:type="arc"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="path3116"
sodipodi:cx="115"
sodipodi:cy="157.36218"
sodipodi:rx="5"
sodipodi:ry="5"
d="m 120,157.36218 c 0,2.76143 -2.23858,5 -5,5 -2.76142,0 -5,-2.23857 -5,-5 0,-2.76142 2.23858,-5 5,-5 2.76142,0 5,2.23858 5,5 z"
transform="matrix(-1,0,0,1,196.26924,-43.183594)" />
<text
xml:space="preserve"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="49.269192"
y="178.17859"
id="text3118"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3120"
x="49.269192"
y="178.17859"
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana">x</tspan></text>
<text
sodipodi:linespacing="125%"
id="text3122"
y="118.17859"
x="97.269257"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana"
y="118.17859"
x="97.269257"
id="tspan3124"
sodipodi:role="line">y</tspan></text>
<path
sodipodi:type="star"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="path3126"
sodipodi:sides="3"
sodipodi:cx="95"
sodipodi:cy="182.36218"
sodipodi:r1="15"
sodipodi:r2="2.5"
sodipodi:arg1="-1.5707963"
sodipodi:arg2="-0.52359881"
inkscape:flatsided="true"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 95,167.36218 12.99038,22.5 -25.980761,0 z"
inkscape:transform-center-y="-1.25"
transform="matrix(-1,0,0,1,232.28848,-53.183593)" />
<text
xml:space="preserve"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="134.9213"
y="158.17859"
id="text3128"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3130"
x="134.9213"
y="158.17859"
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana">R</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 20 KiB

View file

@ -0,0 +1,437 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="529.48077"
height="173.08984"
id="svg3079"
version="1.1"
inkscape:version="0.48.2 r9819"
sodipodi:docname="splay-link-right.svg">
<defs
id="defs3081">
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0"
refX="0"
id="Arrow1Mend"
style="overflow:visible">
<path
id="path3929"
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
transform="matrix(-0.4,0,0,-0.4,-4,0)"
inkscape:connector-curvature="0" />
</marker>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1"
inkscape:cx="471.23218"
inkscape:cy="73.753236"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:window-width="1204"
inkscape:window-height="920"
inkscape:window-x="139"
inkscape:window-y="0"
inkscape:window-maximized="0"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0">
<inkscape:grid
type="xygrid"
id="grid3087"
empspacing="5"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true" />
</sodipodi:namedview>
<metadata
id="metadata3084">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(22.471141,-85.088745)">
<path
inkscape:connector-curvature="0"
id="path3873"
d="m 43.26924,134.17859 40,-40 40,40"
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
sodipodi:nodetypes="ccc" />
<path
sodipodi:type="star"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="path3859"
sodipodi:sides="3"
sodipodi:cx="95"
sodipodi:cy="182.36218"
sodipodi:r1="15"
sodipodi:r2="2.5"
sodipodi:arg1="-1.5707963"
sodipodi:arg2="-0.52359881"
inkscape:flatsided="true"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 95,167.36218 12.99038,22.5 -25.980761,0 z"
inkscape:transform-center-y="-1.25"
transform="translate(-51.73076,-33.183593)" />
<text
xml:space="preserve"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="41.874722"
y="178.17859"
id="text3861"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3863"
x="41.874722"
y="178.17859"
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana">A</tspan></text>
<path
transform="translate(28.26924,-33.183593)"
inkscape:transform-center-y="-1.25"
d="m 95,167.36218 12.99038,22.5 -25.980761,0 z"
inkscape:randomized="0"
inkscape:rounded="0"
inkscape:flatsided="true"
sodipodi:arg2="-0.52359881"
sodipodi:arg1="-1.5707963"
sodipodi:r2="2.5"
sodipodi:r1="15"
sodipodi:cy="182.36218"
sodipodi:cx="95"
sodipodi:sides="3"
id="path3865"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
sodipodi:type="star" />
<text
sodipodi:linespacing="125%"
id="text3867"
y="178.17859"
x="124.66376"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana"
y="178.17859"
x="124.66376"
id="tspan3869"
sodipodi:role="line">B</tspan></text>
<path
sodipodi:type="arc"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="path3089"
sodipodi:cx="115"
sodipodi:cy="157.36218"
sodipodi:rx="5"
sodipodi:ry="5"
d="m 120,157.36218 a 5,5 0 1 1 -10,0 5,5 0 1 1 10,0 z"
transform="translate(-31.73076,-63.183594)" />
<path
sodipodi:type="star"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="path3877"
sodipodi:sides="3"
sodipodi:cx="95"
sodipodi:cy="182.36218"
sodipodi:r1="15"
sodipodi:r2="2.5"
sodipodi:arg1="-1.5707963"
sodipodi:arg2="-0.52359881"
inkscape:flatsided="true"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 95,167.36218 12.99038,22.5 -25.980761,0 z"
inkscape:transform-center-y="-1.25"
transform="translate(80.26924,-53.183594)" />
<text
xml:space="preserve"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="175.33957"
y="158.17859"
id="text3879"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3881"
x="175.33957"
y="158.17859"
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana">R</tspan></text>
<path
transform="translate(-71.73076,-23.183593)"
d="m 120,157.36218 a 5,5 0 1 1 -10,0 5,5 0 1 1 10,0 z"
sodipodi:ry="5"
sodipodi:rx="5"
sodipodi:cy="157.36218"
sodipodi:cx="115"
id="path3875"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
sodipodi:type="arc" />
<text
sodipodi:linespacing="125%"
id="text3909"
y="118.36218"
x="259.625"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana"
y="118.36218"
x="259.625"
id="tspan3911"
sodipodi:role="line">link</tspan><tspan
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana"
y="148.36218"
x="259.625"
sodipodi:role="line"
id="tspan3913">right</tspan></text>
<path
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
d="m 220,168.36218 80,0"
id="path3915"
inkscape:connector-curvature="0" />
<text
sodipodi:linespacing="125%"
id="text4361"
y="98.178589"
x="65.269257"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana"
y="98.178589"
x="65.269257"
id="tspan4363"
sodipodi:role="line">x</tspan></text>
<text
xml:space="preserve"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="27.269224"
y="138.17859"
id="text4365"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan4367"
x="27.269224"
y="138.17859"
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana">y</tspan></text>
<path
transform="translate(-103.73076,-53.183594)"
inkscape:transform-center-y="-1.25"
d="m 95,167.36218 12.99038,22.5 -25.980761,0 z"
inkscape:randomized="0"
inkscape:rounded="0"
inkscape:flatsided="true"
sodipodi:arg2="-0.52359881"
sodipodi:arg1="-1.5707963"
sodipodi:r2="2.5"
sodipodi:r1="15"
sodipodi:cy="182.36218"
sodipodi:cx="95"
sodipodi:sides="3"
id="path3050"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
sodipodi:type="star" />
<text
sodipodi:linespacing="125%"
id="text3052"
y="158.17859"
x="-8.8010883"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana"
y="158.17859"
x="-8.8010883"
id="tspan3054"
sodipodi:role="line">L</tspan></text>
<path
sodipodi:nodetypes="ccc"
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 496.25962,126.67859 -42.99038,47.5 40,40"
id="path3094"
inkscape:connector-curvature="0" />
<path
transform="translate(308.26924,-53.183594)"
inkscape:transform-center-y="-1.25"
d="m 95,167.36218 12.99038,22.5 -25.980761,0 z"
inkscape:randomized="0"
inkscape:rounded="0"
inkscape:flatsided="true"
sodipodi:arg2="-0.52359881"
sodipodi:arg1="-1.5707963"
sodipodi:r2="2.5"
sodipodi:r1="15"
sodipodi:cy="182.36218"
sodipodi:cx="95"
sodipodi:sides="3"
id="path3096"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
sodipodi:type="star" />
<text
sodipodi:linespacing="125%"
id="text3098"
y="158.17859"
x="401.87473"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana"
y="158.17859"
x="401.87473"
id="tspan3100"
sodipodi:role="line">A</tspan></text>
<path
sodipodi:type="star"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="path3102"
sodipodi:sides="3"
sodipodi:cx="95"
sodipodi:cy="182.36218"
sodipodi:r1="15"
sodipodi:r2="2.5"
sodipodi:arg1="-1.5707963"
sodipodi:arg2="-0.52359881"
inkscape:flatsided="true"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 95,167.36218 12.99038,22.5 -25.980761,0 z"
inkscape:transform-center-y="-1.25"
transform="translate(398.26924,46.816406)" />
<text
xml:space="preserve"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="494.66376"
y="258.17859"
id="text3104"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3106"
x="494.66376"
y="258.17859"
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana">B</tspan></text>
<path
transform="translate(338.26924,16.816405)"
d="m 120,157.36218 a 5,5 0 1 1 -10,0 5,5 0 1 1 10,0 z"
sodipodi:ry="5"
sodipodi:rx="5"
sodipodi:cy="157.36218"
sodipodi:cx="115"
id="path3108"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
sodipodi:type="arc" />
<path
transform="translate(398.26924,-53.183595)"
inkscape:transform-center-y="-1.25"
d="m 95,167.36218 12.99038,22.5 -25.980761,0 z"
inkscape:randomized="0"
inkscape:rounded="0"
inkscape:flatsided="true"
sodipodi:arg2="-0.52359881"
sodipodi:arg1="-1.5707963"
sodipodi:r2="2.5"
sodipodi:r1="15"
sodipodi:cy="182.36218"
sodipodi:cx="95"
sodipodi:sides="3"
id="path3110"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
sodipodi:type="star" />
<text
sodipodi:linespacing="125%"
id="text3112"
y="158.17859"
x="493.33954"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana"
y="158.17859"
x="493.33954"
id="tspan3114"
sodipodi:role="line">R</tspan></text>
<path
sodipodi:type="arc"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="path3116"
sodipodi:cx="115"
sodipodi:cy="157.36218"
sodipodi:rx="5"
sodipodi:ry="5"
d="m 120,157.36218 a 5,5 0 1 1 -10,0 5,5 0 1 1 10,0 z"
transform="translate(288.26924,-43.183594)" />
<text
xml:space="preserve"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="435.26929"
y="178.17859"
id="text3118"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3120"
x="435.26929"
y="178.17859"
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana">x</tspan></text>
<text
sodipodi:linespacing="125%"
id="text3122"
y="118.17859"
x="387.26923"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana"
y="118.17859"
x="387.26923"
id="tspan3124"
sodipodi:role="line">y</tspan></text>
<path
sodipodi:type="star"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="path3126"
sodipodi:sides="3"
sodipodi:cx="95"
sodipodi:cy="182.36218"
sodipodi:r1="15"
sodipodi:r2="2.5"
sodipodi:arg1="-1.5707963"
sodipodi:arg2="-0.52359881"
inkscape:flatsided="true"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 95,167.36218 12.99038,22.5 -25.980761,0 z"
inkscape:transform-center-y="-1.25"
transform="translate(252.25,-53.183593)" />
<text
xml:space="preserve"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="347.17969"
y="158.17859"
id="text3128"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3130"
x="347.17969"
y="158.17859"
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana">L</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 19 KiB

View file

@ -0,0 +1,405 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="407.48077"
height="133.40625"
id="svg3079"
version="1.1"
inkscape:version="0.48.2 r9819"
sodipodi:docname="splay-rotate-right.svg">
<defs
id="defs3081">
<marker
inkscape:stockid="Arrow1Mstart"
orient="auto"
refY="0"
refX="0"
id="Arrow1Mstart"
style="overflow:visible">
<path
id="path3926"
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
transform="matrix(0.4,0,0,0.4,4,0)"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0"
refX="0"
id="Arrow1Mend"
style="overflow:visible">
<path
id="path3929"
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
transform="matrix(-0.4,0,0,-0.4,-4,0)"
inkscape:connector-curvature="0" />
</marker>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1"
inkscape:cx="180.49339"
inkscape:cy="51.253232"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:window-width="1204"
inkscape:window-height="920"
inkscape:window-x="179"
inkscape:window-y="20"
inkscape:window-maximized="0"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0">
<inkscape:grid
type="xygrid"
id="grid3087"
empspacing="5"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true" />
</sodipodi:namedview>
<metadata
id="metadata3084">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-56.259619,-83.272339)">
<path
inkscape:connector-curvature="0"
id="path3873"
d="m 110,132.36218 40,-39.999997 40,39.999997"
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
sodipodi:nodetypes="ccc" />
<path
sodipodi:type="star"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="path3859"
sodipodi:sides="3"
sodipodi:cx="95"
sodipodi:cy="182.36218"
sodipodi:r1="15"
sodipodi:r2="2.5"
sodipodi:arg1="-1.5707963"
sodipodi:arg2="-0.52359881"
inkscape:flatsided="true"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 95,167.36218 12.99038,22.5 -25.980761,0 z"
inkscape:transform-center-y="-1.25"
transform="translate(-25,5)" />
<text
xml:space="preserve"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="70"
y="216.36218"
id="text3861"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3863"
x="70"
y="216.36218"
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana">A</tspan></text>
<path
transform="translate(55,5)"
inkscape:transform-center-y="-1.25"
d="m 95,167.36218 12.99038,22.5 -25.980761,0 z"
inkscape:randomized="0"
inkscape:rounded="0"
inkscape:flatsided="true"
sodipodi:arg2="-0.52359881"
sodipodi:arg1="-1.5707963"
sodipodi:r2="2.5"
sodipodi:r1="15"
sodipodi:cy="182.36218"
sodipodi:cx="95"
sodipodi:sides="3"
id="path3865"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
sodipodi:type="star" />
<text
sodipodi:linespacing="125%"
id="text3867"
y="216.36218"
x="150"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana"
y="216.36218"
x="150"
id="tspan3869"
sodipodi:role="line">B</tspan></text>
<path
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 70,172.36218 40,-40 40,40"
id="path3871"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" />
<path
sodipodi:type="arc"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="path3089"
sodipodi:cx="115"
sodipodi:cy="157.36218"
sodipodi:rx="5"
sodipodi:ry="5"
d="m 120,157.36218 c 0,2.76143 -2.23858,5 -5,5 -2.76142,0 -5,-2.23857 -5,-5 0,-2.76142 2.23858,-5 5,-5 2.76142,0 5,2.23858 5,5 z"
transform="translate(35,-65)" />
<path
sodipodi:type="star"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="path3877"
sodipodi:sides="3"
sodipodi:cx="95"
sodipodi:cy="182.36218"
sodipodi:r1="15"
sodipodi:r2="2.5"
sodipodi:arg1="-1.5707963"
sodipodi:arg2="-0.52359881"
inkscape:flatsided="true"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 95,167.36218 12.99038,22.5 -25.980761,0 z"
inkscape:transform-center-y="-1.25"
transform="translate(95,-35)" />
<text
xml:space="preserve"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="190"
y="176.36218"
id="text3879"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3881"
x="190"
y="176.36218"
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana">C</tspan></text>
<path
transform="translate(-5,-25)"
d="m 120,157.36218 c 0,2.76143 -2.23858,5 -5,5 -2.76142,0 -5,-2.23857 -5,-5 0,-2.76142 2.23858,-5 5,-5 2.76142,0 5,2.23858 5,5 z"
sodipodi:ry="5"
sodipodi:rx="5"
sodipodi:cy="157.36218"
sodipodi:cx="115"
id="path3875"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
sodipodi:type="arc" />
<path
sodipodi:nodetypes="ccc"
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 410,132.36218 370,92.362183 330,132.36218"
id="path3883"
inkscape:connector-curvature="0" />
<path
transform="matrix(-1,0,0,1,545,5)"
inkscape:transform-center-y="-1.25"
d="m 95,167.36218 12.99038,22.5 -25.980761,0 z"
inkscape:randomized="0"
inkscape:rounded="0"
inkscape:flatsided="true"
sodipodi:arg2="-0.52359881"
sodipodi:arg1="-1.5707963"
sodipodi:r2="2.5"
sodipodi:r1="15"
sodipodi:cy="182.36218"
sodipodi:cx="95"
sodipodi:sides="3"
id="path3885"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
sodipodi:type="star" />
<text
sodipodi:linespacing="125%"
id="text3887"
y="216.36218"
x="450"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana"
y="216.36218"
x="450"
id="tspan3889"
sodipodi:role="line">C</tspan></text>
<path
sodipodi:type="star"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="path3891"
sodipodi:sides="3"
sodipodi:cx="95"
sodipodi:cy="182.36218"
sodipodi:r1="15"
sodipodi:r2="2.5"
sodipodi:arg1="-1.5707963"
sodipodi:arg2="-0.52359881"
inkscape:flatsided="true"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 95,167.36218 12.99038,22.5 -25.980761,0 z"
inkscape:transform-center-y="-1.25"
transform="matrix(-1,0,0,1,465,5)" />
<text
xml:space="preserve"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="368.60547"
y="216.36218"
id="text3893"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3895"
x="368.60547"
y="216.36218"
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana">B</tspan></text>
<path
sodipodi:nodetypes="ccc"
inkscape:connector-curvature="0"
id="path3897"
d="m 450,172.36218 -40,-40 -40,40"
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
transform="matrix(-1,0,0,1,485,-65)"
d="m 120,157.36218 c 0,2.76143 -2.23858,5 -5,5 -2.76142,0 -5,-2.23857 -5,-5 0,-2.76142 2.23858,-5 5,-5 2.76142,0 5,2.23858 5,5 z"
sodipodi:ry="5"
sodipodi:rx="5"
sodipodi:cy="157.36218"
sodipodi:cx="115"
id="path3899"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
sodipodi:type="arc" />
<path
transform="matrix(-1,0,0,1,425,-35)"
inkscape:transform-center-y="-1.25"
d="m 95,167.36218 12.99038,22.5 -25.980761,0 z"
inkscape:randomized="0"
inkscape:rounded="0"
inkscape:flatsided="true"
sodipodi:arg2="-0.52359881"
sodipodi:arg1="-1.5707963"
sodipodi:r2="2.5"
sodipodi:r1="15"
sodipodi:cy="182.36218"
sodipodi:cx="95"
sodipodi:sides="3"
id="path3901"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
sodipodi:type="star" />
<text
sodipodi:linespacing="125%"
id="text3903"
y="176.36218"
x="329.61328"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana"
y="176.36218"
x="329.61328"
id="tspan3905"
sodipodi:role="line">A</tspan></text>
<path
sodipodi:type="arc"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="path3907"
sodipodi:cx="115"
sodipodi:cy="157.36218"
sodipodi:rx="5"
sodipodi:ry="5"
d="m 120,157.36218 c 0,2.76143 -2.23858,5 -5,5 -2.76142,0 -5,-2.23857 -5,-5 0,-2.76142 2.23858,-5 5,-5 2.76142,0 5,2.23858 5,5 z"
transform="matrix(-1,0,0,1,525,-25)" />
<text
sodipodi:linespacing="125%"
id="text3909"
y="102.36218"
x="260"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana"
y="102.36218"
x="260"
id="tspan3911"
sodipodi:role="line">rotate</tspan><tspan
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana"
y="132.36218"
x="260"
sodipodi:role="line"
id="tspan3913">left</tspan></text>
<path
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow1Mstart);marker-end:none"
d="m 220,152.36218 80,0"
id="path3915"
inkscape:connector-curvature="0" />
<text
sodipodi:linespacing="125%"
id="text4361"
y="96.362183"
x="132"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana"
y="96.362183"
x="132"
id="tspan4363"
sodipodi:role="line">x</tspan></text>
<text
xml:space="preserve"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="94"
y="136.36218"
id="text4365"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan4367"
x="94"
y="136.36218"
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana">y</tspan></text>
<text
xml:space="preserve"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="388"
y="96.362183"
id="text4369"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan4371"
x="388"
y="96.362183"
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana">x</tspan></text>
<text
sodipodi:linespacing="125%"
id="text4373"
y="136.36218"
x="426"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana"
y="136.36218"
x="426"
id="tspan4375"
sodipodi:role="line">y</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 18 KiB

View file

@ -0,0 +1,391 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="407.48077"
height="133.40625"
id="svg3079"
version="1.1"
inkscape:version="0.48.2 r9819"
sodipodi:docname="splay-rotate-right.svg">
<defs
id="defs3081">
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0"
refX="0"
id="Arrow1Mend"
style="overflow:visible">
<path
id="path3929"
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
transform="matrix(-0.4,0,0,-0.4,-4,0)"
inkscape:connector-curvature="0" />
</marker>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1"
inkscape:cx="180.49339"
inkscape:cy="41.753236"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:window-width="1204"
inkscape:window-height="920"
inkscape:window-x="179"
inkscape:window-y="20"
inkscape:window-maximized="0"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0">
<inkscape:grid
type="xygrid"
id="grid3087"
empspacing="5"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true" />
</sodipodi:namedview>
<metadata
id="metadata3084">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-56.259619,-83.272339)">
<path
inkscape:connector-curvature="0"
id="path3873"
d="m 110,132.36218 40,-39.999997 40,39.999997"
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
sodipodi:nodetypes="ccc" />
<path
sodipodi:type="star"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="path3859"
sodipodi:sides="3"
sodipodi:cx="95"
sodipodi:cy="182.36218"
sodipodi:r1="15"
sodipodi:r2="2.5"
sodipodi:arg1="-1.5707963"
sodipodi:arg2="-0.52359881"
inkscape:flatsided="true"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 95,167.36218 12.99038,22.5 -25.980761,0 z"
inkscape:transform-center-y="-1.25"
transform="translate(-25,5)" />
<text
xml:space="preserve"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="70"
y="216.36218"
id="text3861"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3863"
x="70"
y="216.36218"
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana">A</tspan></text>
<path
transform="translate(55,5)"
inkscape:transform-center-y="-1.25"
d="m 95,167.36218 12.99038,22.5 -25.980761,0 z"
inkscape:randomized="0"
inkscape:rounded="0"
inkscape:flatsided="true"
sodipodi:arg2="-0.52359881"
sodipodi:arg1="-1.5707963"
sodipodi:r2="2.5"
sodipodi:r1="15"
sodipodi:cy="182.36218"
sodipodi:cx="95"
sodipodi:sides="3"
id="path3865"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
sodipodi:type="star" />
<text
sodipodi:linespacing="125%"
id="text3867"
y="216.36218"
x="150"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana"
y="216.36218"
x="150"
id="tspan3869"
sodipodi:role="line">B</tspan></text>
<path
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 70,172.36218 40,-40 40,40"
id="path3871"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccc" />
<path
sodipodi:type="arc"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="path3089"
sodipodi:cx="115"
sodipodi:cy="157.36218"
sodipodi:rx="5"
sodipodi:ry="5"
d="m 120,157.36218 c 0,2.76143 -2.23858,5 -5,5 -2.76142,0 -5,-2.23857 -5,-5 0,-2.76142 2.23858,-5 5,-5 2.76142,0 5,2.23858 5,5 z"
transform="translate(35,-65)" />
<path
sodipodi:type="star"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="path3877"
sodipodi:sides="3"
sodipodi:cx="95"
sodipodi:cy="182.36218"
sodipodi:r1="15"
sodipodi:r2="2.5"
sodipodi:arg1="-1.5707963"
sodipodi:arg2="-0.52359881"
inkscape:flatsided="true"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 95,167.36218 12.99038,22.5 -25.980761,0 z"
inkscape:transform-center-y="-1.25"
transform="translate(95,-35)" />
<text
xml:space="preserve"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="190"
y="176.36218"
id="text3879"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3881"
x="190"
y="176.36218"
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana">C</tspan></text>
<path
transform="translate(-5,-25)"
d="m 120,157.36218 c 0,2.76143 -2.23858,5 -5,5 -2.76142,0 -5,-2.23857 -5,-5 0,-2.76142 2.23858,-5 5,-5 2.76142,0 5,2.23858 5,5 z"
sodipodi:ry="5"
sodipodi:rx="5"
sodipodi:cy="157.36218"
sodipodi:cx="115"
id="path3875"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
sodipodi:type="arc" />
<path
sodipodi:nodetypes="ccc"
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 410,132.36218 370,92.362183 330,132.36218"
id="path3883"
inkscape:connector-curvature="0" />
<path
transform="matrix(-1,0,0,1,545,5)"
inkscape:transform-center-y="-1.25"
d="m 95,167.36218 12.99038,22.5 -25.980761,0 z"
inkscape:randomized="0"
inkscape:rounded="0"
inkscape:flatsided="true"
sodipodi:arg2="-0.52359881"
sodipodi:arg1="-1.5707963"
sodipodi:r2="2.5"
sodipodi:r1="15"
sodipodi:cy="182.36218"
sodipodi:cx="95"
sodipodi:sides="3"
id="path3885"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
sodipodi:type="star" />
<text
sodipodi:linespacing="125%"
id="text3887"
y="216.36218"
x="450"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana"
y="216.36218"
x="450"
id="tspan3889"
sodipodi:role="line">C</tspan></text>
<path
sodipodi:type="star"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="path3891"
sodipodi:sides="3"
sodipodi:cx="95"
sodipodi:cy="182.36218"
sodipodi:r1="15"
sodipodi:r2="2.5"
sodipodi:arg1="-1.5707963"
sodipodi:arg2="-0.52359881"
inkscape:flatsided="true"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 95,167.36218 12.99038,22.5 -25.980761,0 z"
inkscape:transform-center-y="-1.25"
transform="matrix(-1,0,0,1,465,5)" />
<text
xml:space="preserve"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="368.60547"
y="216.36218"
id="text3893"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3895"
x="368.60547"
y="216.36218"
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana">B</tspan></text>
<path
sodipodi:nodetypes="ccc"
inkscape:connector-curvature="0"
id="path3897"
d="m 450,172.36218 -40,-40 -40,40"
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
transform="matrix(-1,0,0,1,485,-65)"
d="m 120,157.36218 c 0,2.76143 -2.23858,5 -5,5 -2.76142,0 -5,-2.23857 -5,-5 0,-2.76142 2.23858,-5 5,-5 2.76142,0 5,2.23858 5,5 z"
sodipodi:ry="5"
sodipodi:rx="5"
sodipodi:cy="157.36218"
sodipodi:cx="115"
id="path3899"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
sodipodi:type="arc" />
<path
transform="matrix(-1,0,0,1,425,-35)"
inkscape:transform-center-y="-1.25"
d="m 95,167.36218 12.99038,22.5 -25.980761,0 z"
inkscape:randomized="0"
inkscape:rounded="0"
inkscape:flatsided="true"
sodipodi:arg2="-0.52359881"
sodipodi:arg1="-1.5707963"
sodipodi:r2="2.5"
sodipodi:r1="15"
sodipodi:cy="182.36218"
sodipodi:cx="95"
sodipodi:sides="3"
id="path3901"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
sodipodi:type="star" />
<text
sodipodi:linespacing="125%"
id="text3903"
y="176.36218"
x="329.61328"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana"
y="176.36218"
x="329.61328"
id="tspan3905"
sodipodi:role="line">A</tspan></text>
<path
sodipodi:type="arc"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="path3907"
sodipodi:cx="115"
sodipodi:cy="157.36218"
sodipodi:rx="5"
sodipodi:ry="5"
d="m 120,157.36218 c 0,2.76143 -2.23858,5 -5,5 -2.76142,0 -5,-2.23857 -5,-5 0,-2.76142 2.23858,-5 5,-5 2.76142,0 5,2.23858 5,5 z"
transform="matrix(-1,0,0,1,525,-25)" />
<text
sodipodi:linespacing="125%"
id="text3909"
y="102.36218"
x="260"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana"
y="102.36218"
x="260"
id="tspan3911"
sodipodi:role="line">rotate</tspan><tspan
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana"
y="132.36218"
x="260"
sodipodi:role="line"
id="tspan3913">right</tspan></text>
<path
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Mend)"
d="m 220,152.36218 80,0"
id="path3915"
inkscape:connector-curvature="0" />
<text
sodipodi:linespacing="125%"
id="text4361"
y="96.362183"
x="132"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana"
y="96.362183"
x="132"
id="tspan4363"
sodipodi:role="line">x</tspan></text>
<text
xml:space="preserve"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="94"
y="136.36218"
id="text4365"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan4367"
x="94"
y="136.36218"
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana">y</tspan></text>
<text
xml:space="preserve"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
x="388"
y="96.362183"
id="text4369"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan4371"
x="388"
y="96.362183"
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana">x</tspan></text>
<text
sodipodi:linespacing="125%"
id="text4373"
y="136.36218"
x="426"
style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
xml:space="preserve"><tspan
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Verdana;-inkscape-font-specification:Verdana"
y="136.36218"
x="426"
id="tspan4375"
sodipodi:role="line">y</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 17 KiB

View file

@ -6,7 +6,7 @@ Splay trees
:Tag: design.mps.splay
:Author: Gavin Matthews
:Date: 1998-05-01
:Status: draft document
:Status: complete design
:Revision: $Id$
:Copyright: See `Copyright and License`_.
:Index terms: pair: splay trees; design
@ -47,42 +47,46 @@ usage patterns. Unused nodes have essentially no time overhead.
Definitions
-----------
_`.def.splay-tree`: A "Splay Tree" is a self-adjusting binary tree as
described in paper.st85(0), paper.sleator96(0).
_`.def.splay-tree`: A *splay tree* is a self-adjusting binary tree as
described in [ST85]_ and [Sleator96]_.
_`.def.node`: A "node" is used in the typical datastructure sense to
_`.def.node`: A *node* is used in the typical data structure sense to
mean an element of a tree (see also `.type.splay.node`_).
_`.def.key`: A "key" is a value associated with each node; the keys
_`.def.key`: A *key* is a value associated with each node; the keys
are totally ordered by a client provided comparator.
_`.def.comparator`: A "comparator" is a function that compares keys to
determine their ordering (see also `.type.splay.compare.method`_).
_`.def.comparator`: A *comparator* is a function that compares keys to
determine their ordering (see also `.type.tree.compare.method`_).
_`.def.successor`: Node *N1* is the "successor" of node *N2* if *N1*
and *N2* are both in the same tree, and the key of *N1* immediately
follows the key of *N2* in the ordering of all keys for the tree.
_`.def.successor`: Node *N*\ :subscript:`2` is the *successor* of node
*N*\ :subscript:`1` if *N*\ :subscript:`1` and *N*\ :subscript:`2` are
both in the same tree, and the key of *N*\ :subscript:`2` immediately
follows the key of *N*\ :subscript:`1` in the ordering of all keys for
the tree.
_`.def.left-child`: Each node *N* contains a "left child", which is a
_`.def.left-child`: Each node *N* contains a *left child*, which is a
(possibly empty) sub-tree of nodes. The key of *N* is ordered after
the keys of all nodes in this sub-tree.
_`.def.right-child`: Each node *N* contains a "right child", which is
_`.def.right-child`: Each node *N* contains a *right child*, which is
a (possibly empty) sub-tree of nodes. The key of *N* is ordered before
the keys of all nodes in this sub-tree.
_`.def.neighbour`: A node *N* which has key *Kn* is a "neighbour" of a
key *K* if either *Kn* is the first key in the total order which
compares greater than *K* or if *Kn* is the last key in the total
order which compares less than *K*.
_`.def.neighbour`: The *left neighbour* of a key *K* is the node *N*
with the largest key that compares less than *K* in the total order.
The *right neighbour* of a key *K* is the node *N* with the smaller
key that compares greater than *K* in the total order. A node is a
*neighbour* of a key if it is either the left or right neighbour of
the key.
_`.def.first`: A node is the "first" node in a set of nodes if its key
_`.def.first`: A node is the *first* node in a set of nodes if its key
compares less than the keys of all other nodes in the set.
_`.def.last`: A node is the "last" node in a set of nodes if its key
_`.def.last`: A node is the *last* node in a set of nodes if its key
compares greater than the keys of all other nodes in the set.
_`.def.client-property`: A "client property" is a value that the
_`.def.client-property`: A *client property* is a value that the
client may associate with each node in addition to the key (a block
size, for example). This splay tree implementation provides support
for efficiently finding the first or last nodes with suitably large
@ -99,26 +103,21 @@ general inferred MPS requirements.
_`.req.order`: Must maintain a set of abstract keys which is totally
ordered for a comparator.
_`.req.tree`: The keys must be associated with nodes arranged in a
Splay Tree.
_`.req.splay`: Common operations must have low amortized cost.
_`.req.splay`: Common operations must balance the tree by splaying it,
to achieve low amortized cost (see paper.st85(0)).
_`.req.add`: Must be able to add new members. This is a common
_`.req.add`: Must be able to add new nodes. This is a common
operation.
_`.req.remove`: Must be able to remove members. This is a common
_`.req.remove`: Must be able to remove nodes. This is a common
operation.
_`.req.locate`: Must be able to locate a member, given a key. This is
_`.req.locate`: Must be able to locate a node, given a key. This is
a common operation.
_`.req.neighbours`: Must be able to locate the neighbouring members
(in order) of a non-member, given a key (see `.def.neighbour`_). This
is a common operation.
_`.req.neighbours`: Must be able to locate the neighbouring nodes of a
key (see `.def.neighbour`_). This is a common operation.
_`.req.iterate`: Must be able to iterate over all members in order
_`.req.iterate`: Must be able to iterate over all nodes in key order
with reasonable efficiency.
_`.req.protocol`: Must support detection of protocol violations.
@ -145,10 +144,73 @@ _`.req.root`: Must be able to find the root of a splay tree (if one
exists).
External types
--------------
Generic binary tree interface
-----------------------------
Types
.....
``typedef struct TreeStruct *Tree``
_`.type.tree`: ``Tree`` is the type of a node in a binary tree.
``Tree`` contains no fields to store the key associated with the node,
or the client property. Again, it is intended that the ``TreeStruct``
can be embedded in another structure, and that this is how the
association will be made (see `.usage.client-node`_ for an example).
No convenience functions are provided for allocation or deallocation.
``typedef void *TreeKey``
_`.type.treekey`: ``TreeKey`` is the type of a key associated with a
node in a binary tree. It is an alias for ``void *`` but expresses the
intention.
``typedef TreeKey (*TreeKeyMethod)(Tree tree)``
_`.type.tree.key.method`: A function of type ``TreeKey`` returns the
key associated with a node in a binary tree. (Since there is no space
in a ``TreeStruct`` to store a key, it is expected that the
``TreeStruct`` is embedded in another structure from which the key can
be extracted.)
``typedef Compare (*TreeCompare)(Tree tree, TreeKey key)``
_`.type.tree.compare.method`: A function of type ``TreeCompare`` is
required to compare ``key`` with the key the client associates with
that splay tree node ``tree``, and return the appropriate Compare
value (see `.usage.compare`_ for an example). The function compares a
key with a node, rather than a pair of keys or nodes as might seem
more obvious. This is because the details of the mapping between nodes
and keys is left to the client (see `.type.tree`_), and the splaying
operations compare keys with nodes (see `.impl.splay`_).
``typedef Res (*TreeDescribeMethod)(Tree tree, mps_lib_FILE *stream)``
_`.type.tree.describe.method`: A function of type
``TreeDescribeMethod`` is required to write (via ``WriteF()``) a
client-oriented representation of the splay node. The output should be
non-empty, short, and without newline characters. This is provided for
debugging purposes only.
Functions
.........
``Bool TreeCheck(Tree tree)``
_`.function.tree.check`: This is a check function for the
``Tree`` type (see guide.impl.c.adt.method.check and
design.mps.check_).
.. _design.mps.check: check
Splay tree interface
--------------------
Types
.....
``typedef struct SplayTreeStruct SplayTreeStruct``
``typedef struct SplayTreeStruct *SplayTree``
_`.type.splay.tree`: ``SplayTree`` is the type of the main object at
@ -157,39 +219,7 @@ the root of the splay tree. It is intended that the
`.usage.client-tree`_ for an example). No convenience functions are
provided for allocation or deallocation.
``typedef struct TreeStruct TreeStruct``
``typedef struct TreeStruct *Tree``
_`.type.splay.node`: ``Tree`` is the type of a binary tree, used as the
representation of the nodes of the splay tree.
``Tree`` contains no fields to store the key
associated with the node, or the client property. Again, it is
intended that the ``TreeStruct`` can be embedded in another
structure, and that this is how the association will be made (see
`.usage.client-node`_ for an example). No convenience functions are
provided for allocation or deallocation.
``typedef Compare (*TreeCompare)(Tree tree, TreeKey key)``
_`.type.splay.compare.method`: A function of type
``TreeCompare`` is required to compare ``key`` with the key the
client associates with that splay tree node ``tree``, and return the
appropriate Compare value (see `.usage.compare`_ for an example). The
function compares a key with a node, rather than a pair of keys or
nodes as might seem more obvious. This is because the details of the
mapping between nodes and keys is left to the client (see
`.type.splay.node`_), and the splaying operations compare keys with
nodes (see `.impl.splay`_).
``typedef Res (*SplayNodeDescribeMethod)(Tree tree, mps_lib_FILE *stream)``
_`.type.splay.node.describe.method`: A function of type
``SplayNodeDescribeMethod`` is required to write (via ``WriteF()``) a
client-oriented representation of the splay node. The output should be
non-empty, short, and without return characters. This is provided for
debugging purposes only.
``typedef Bool (*SplayTestNodeMethod)(SplayTree splay, Tree tree, void *closureP, unsigned long closureS)``
``typedef Bool (*SplayTestNodeMethod)(SplayTree splay, Tree tree, void *closureP, Size closureS)``
_`.type.splay.test.node.method`: A function of type
``SplayTestNodeMethod`` required to determine whether the node itself
@ -198,7 +228,7 @@ meets some client determined property (see `.prop`_ and
``closureS`` describe the environment for the function (see
`.function.splay.find.first`_ and `.function.splay.find.last`_).
``typedef Bool (*SplayTestTreeMethod)(SplayTree splay, Tree tree, void *closureP, unsigned long closureS)``
``typedef Bool (*SplayTestTreeMethod)(SplayTree splay, Tree tree, void *closureP, Size closureS)``
_`.type.splay.test.tree.method`: A function of type
``SplayTestTreeMethod`` is required to determine whether any of the
@ -214,46 +244,39 @@ environment for the function (see `.function.splay.find.first`_ and
``typedef void (*SplayUpdateNodeMethod)(SplayTree splay, Tree tree)``
_`.type.splay.update.node.method`: A function of type
``SplayUpdateNodeMethod`` is required to update any client
datastructures associated with a node to maintain some client
determined property (see `.prop`_) given that the children of the node
have changed. (See
`.usage.callback`_ for an example)
``SplayUpdateNodeMethod`` is required to update any client data
structures associated with a node to maintain some client determined
property (see `.prop`_) given that the children of the node have
changed. (See `.usage.callback`_ for an example)
External functions
------------------
Functions
.........
_`.function.no-thread`: The interface functions are not designed to be
either thread-safe or re-entrant. Clients of the interface are
responsible for synchronization, and for ensuring that client-provided
methods invoked by the splay module (`.type.splay.compare.method`_,
`.type.splay.test.node.method`_, `.type.splay.test.tree.method`_,
`.type.splay.update.node.method`_) do not call functions of the splay
module.
methods invoked by the splay module (`.type.tree.compare.method`_,
`.type.tree.key.method`_, `.type.splay.test.node.method`_,
`.type.splay.test.tree.method`_, `.type.splay.update.node.method`_) do
not call functions of the splay module.
``Bool SplayTreeCheck(SplayTree splay)``
_`.function.splay.tree.check`: This is a check function for the
SplayTree type (see guide.impl.c.adt.method.check &
design.mps.check(0)).
``SplayTree`` type (see guide.impl.c.adt.method.check and
design.mps.check_).
``Bool SplayNodeCheck(Tree tree)``
_`.function.splay.node.check`: This is a check function for the
``Tree`` type (see guide.impl.c.adt.method.check &
design.mps.check(0)).
``void SplayTreeInit(SplayTree splay, SplayCompareMethod compare, SplayUpdateNodeMethod updateNode)``
``void SplayTreeInit(SplayTree splay, TreeCompareMethod compare, TreeKeyMethod nodeKey, SplayUpdateNodeMethod updateNode)``
_`.function.splay.tree.init`: This function initialises a
``SplayTree`` (see guide.impl.c.adt.method.init). It requires a
``compare`` method that defines a total ordering on nodes (see
`.req.order`_); the effect of supplying a compare method that does not
implement a total ordering is undefined. It also requires an
``updateNode`` method, which will be used to keep client properties up
to date when the tree structure changes; the value
``SplayTrivUpdate`` may be used for this method if there is no
``SplayTree`` (see guide.impl.c.adt.method.init). The ``nodeKey``
function extracts a key from a tree node, and the ``compare`` function
defines a total ordering on keys of nodes (see `.req.order`_). The
effect of supplying a compare method that does not implement a total
ordering is undefined. The ``updateNode`` method is used to keep
client properties up to date when the tree structure changes; the
value ``SplayTrivUpdate`` may be used for this method if there is no
need to maintain client properties. (See `.usage.initialization`_ for
an example use).
@ -263,7 +286,7 @@ _`.function.splay.tree.finish`: This function clears the fields of a
``SplayTree`` (see guide.impl.c.adt.method.finish). Note that it does
not attempt to finish or deallocate any associated ``Tree``
objects; clients wishing to destroy a non-empty ``SplayTree`` must
first explicitly descend the tree and call ``SplayNodeFinish()`` on
first explicitly descend the tree and call ``TreeFinish()`` on
each node from the bottom up.
``Bool SplayTreeInsert(SplayTree splay, Tree tree, void *key)``
@ -285,84 +308,75 @@ given node does not compare ``CompareEQUAL`` with the given key, then
function first splays the tree at the given key. (See `.usage.delete`_
for an example use).
``Bool SplayTreeFind(Tree *nodeReturn, SplayTree splay, void *key)``
``Bool SplayTreeFind(Tree *nodeReturn, SplayTree splay, TreeKey key)``
_`.function.splay.tree.search`: This function searches the splay tree
for a node that compares ``CompareEQUAL`` to the given key (see
`.req.locate`_). It splays the tree at the key. It returns ``FALSE``
if there is no such node in the tree, otherwise ``*nodeReturn`` will
be set to the node.
_`.function.splay.tree.find`: Search the splay tree for a node that
compares ``CompareEQUAL`` to the given key (see `.req.locate`_), and
splay the tree at the key. Return ``FALSE`` if there is no such node
in the tree, otherwise set ``*nodeReturn`` to the node and return
``TRUE``.
``Bool SplayTreeNeighbours(Tree *leftReturn, Tree *rightReturn, SplayTree splay, void *key)``
``Bool SplayTreeNeighbours(Tree *leftReturn, Tree *rightReturn, SplayTree splay, TreeKey key)``
_`.function.splay.tree.neighbours`: This function searches a splay
tree for the two nodes that are the neighbours of the given key (see
`.req.neighbours`_). It splays the tree at the key. ``*leftReturn``
will be the neighbour which compares less than the key if such a
neighbour exists; otherwise it will be ``TreeEMPTY``. ``*rightReturn`` will
be the neighbour which compares greater than the key if such a
neighbour exists; otherwise it will be ``TreeEMPTY``. The function returns
``FALSE`` if any node in the tree compares ``CompareEQUAL`` with the
given key. (See `.usage.insert`_ for an example use).
_`.function.splay.tree.neighbours`: Search a splay tree for the two
nodes that are the neighbours of the given key (see
`.req.neighbours`_). Splay the tree at the key. If any node in the
tree compares ``CompareEQUAL`` with the given key, return ``FALSE``.
Otherwise return ``TRUE``, set ``*leftReturn`` to the left neighbour
of the key (or ``TreeEMPTY`` if the key has no left neighbour), and
set ``*rightReturn`` to the right neighbour of the key (or
``TreeEMPTY`` if the key has no right neighbour). See `.usage.insert`_
for an example of use.
``Tree SplayTreeFirst(SplayTree splay, void *zeroKey)``
``Tree SplayTreeFirst(SplayTree splay)``
_`.function.splay.tree.first`: This function splays the tree at the
first node, and returns that node (see `.req.iterate`_). The supplied
key should compare ``CompareLESS`` with all nodes in the tree. It will
return ``TreeEMPTY`` if the tree has no nodes.
_`.function.splay.tree.first`: If the tree has no nodes, return
``TreeEMPTY``. Otherwise, splay the tree at the first node, and return
that node (see `.req.iterate`_).
``Tree SplayTreeNext(SplayTree splay, Tree oldNode, void *oldKey)``
``Tree SplayTreeNext(SplayTree splay, TreeKey key)``
_`.function.splay.tree.next`: This function receives a node and key
and returns the successor node to that node (see `.req.iterate`_).
This function is intended for use in iteration when the received node
will be the current root of the tree, but is robust against being
interspersed with other splay operations (provided the old node still
exists). The supplied key must compare ``CompareEQUAL`` to the
supplied node. Note that use of this function rebalances the tree for
each node accessed. If many nodes are accessed as a result of multiple
uses, the resultant tree will be generally well balanced. But if the
tree was previously beneficially balanced for a small working set of
accesses, then this local optimization will be lost. (see
`.future.parent`_).
_`.function.splay.tree.next`: If the tree contains a right neighbour
for ``key``, splay the tree at that node and return it. Otherwise
return ``TreeEMPTY``. See `.req.iterate`_.
``Res SplayTreeDescribe(SplayTree splay, mps_lib_FILE *stream, SplayNodeDescribeMethod nodeDescribe)``
``Res SplayTreeDescribe(SplayTree splay, mps_lib_FILE *stream, TreeDescribeMethod nodeDescribe)``
_`.function.splay.tree.describe`: This function prints (using
``WriteF``) to the stream a textual representation of the given splay
tree, using ``nodeDescribe`` to print client-oriented representations
of the nodes (see `.req.debug`_).
_`.function.splay.tree.describe`: Print (using ``WriteF``) a textual
representation of the given splay tree to the stream, using
``nodeDescribe`` to print client-oriented representations of the nodes
(see `.req.debug`_).
``Bool SplayFindFirst(Tree *nodeReturn, SplayTree splay, SplayTestNodeMethod testNode, SplayTestTreeMethod testTree, void *closureP, unsigned long closureS)``
``Bool SplayFindFirst(Tree *nodeReturn, SplayTree splay, SplayTestNodeMethod testNode, SplayTestTreeMethod testTree, void *closureP, Size closureS)``
_`.function.splay.find.first`: ``SplayFindFirst()`` finds the first node
in the tree that satisfies some client property (as determined by the
``testNode`` and ``testTree`` methods) (see `.req.property.find`_).
``closureP`` and ``closureS`` are arbitrary values, and are passed to
the ``testNode`` and ``testTree`` methods which may use the values as
closure environments. If there is no satisfactory node, then ``FALSE``
is returned, otherwise ``*nodeReturn`` is set to the node. (See
`.usage.delete`_ for an example use).
_`.function.splay.find.first`: Find the first node in the tree that
satisfies some client property, as determined by the ``testNode`` and
``testTree`` methods (see `.req.property.find`_). ``closureP`` and
``closureS`` are arbitrary values, and are passed to the ``testNode``
and ``testTree`` methods which may use the values as closure
environments. If there is no satisfactory node, return ``FALSE``;
otherwise set ``*nodeReturn`` to the node and return ``TRUE``. See
`.usage.delete`_ for an example.
``Bool SplayFindFirst(Tree *nodeReturn, SplayTree splay, SplayTestNodeMethod testNode, SplayTestTreeMethod testTree, void *closureP, unsigned long closureS)``
``Bool SplayFindLast(Tree *nodeReturn, SplayTree splay, SplayTestNodeMethod testNode, SplayTestTreeMethod testTree, void *closureP, Size closureS)``
_`.function.splay.find.last`: ``SplayFindLast()`` finds the last node
in the tree that satisfies some client property (as determined by the
``testNode`` and ``testTree`` methods) (see `.req.property.find`_).
``closureP`` and ``closureS`` are arbitrary values, and are passed to
the ``testNode`` and ``testTree`` methods which may use the values as
closure environments. If there is no satisfactory node, then ``FALSE``
is returned, otherwise ``*nodeReturn`` is set to the node.
_`.function.splay.find.last`: As ``SplayFindFirst()``, but find the
last node in the tree that satisfies the client property.
``void SplayNodeRefresh(SplayTree splay, Tree tree, void *key)``
``void SplayNodeRefresh(SplayTree splay, Tree tree, TreeKey key)``
_`.function.splay.node.refresh`: ``SplayNodeRefresh()`` must be called
whenever the client property (see `.prop`_) at a node changes (see
`.req.property.change`_). It will call the ``updateNode`` method on
the given node, and any other nodes that may require update. The
_`.function.splay.node.refresh`: Call the ``updateNode`` method on the
given node, and on any other nodes that may require updating. The
client key for the node must also be supplied; the function splays the
tree at this key. (See `.usage.insert`_ for an example use).
tree at this key. (See `.usage.insert`_ for an example use). This
function must be called whenever the client property (see `.prop`_) at
a node changes (see `.req.property.change`_).
``void SplayNodeUpdate(SplayTree splay, Tree node)``
_`.function.splay.node.update`: Call the ``updateNode`` method on the
given node, but leave other nodes unchanged. This may be called when a
new node is created, to get the client property off the ground.
Client-determined properties
@ -390,7 +404,7 @@ tree at the specified node, which may provoke calls to the
``updateNode`` method will also be called whenever a new splay node is
inserted into the tree.
_`.prop.example`: For example, if implementing an address ordered tree
_`.prop.example`: For example, if implementing an address-ordered tree
of free blocks using a splay tree, a client might choose to use the
base address of each block as the key for each node, and the size of
each block as the client property. The client can then maintain as a
@ -400,7 +414,7 @@ last block of at least a given size. See `.usage.callback`_ for an
example ``updateNode`` method for such a client.
_`.prop.ops`: The splay operations must cause client properties for
nodes to be updated in the following circumstances:- (see `.impl`_ for
nodes to be updated in the following circumstances (see `.impl`_ for
details):
_`.prop.ops.rotate`: rotate left, rotate right -- We need to update
@ -447,16 +461,16 @@ _`.usage.client-tree`: Tree structure to embed a ``SplayTree`` (see
/* no obvious client fields for this simple example */
} FreeTreeStruct;
_`.usage.client-node`: Node structure to embed a Tree (see `.type.splay.node`_)::
_`.usage.client-node`: Node structure to embed a ``Tree`` (see `.type.tree`_)::
typedef struct FreeBlockStruct {
TreeStruct treeStruct; /* embedded splay node */
Addr base; /* base address of block is also the key */
Size size; /* size of block is also the client property */
Size maxSize; /* cached value for maximum size in subtree */
TreeStruct treeStruct; /* embedded splay node */
Addr base; /* base address of block is also the key */
Size size; /* size of block is also the client property */
Size maxSize; /* cached value for maximum size in subtree */
} FreeBlockStruct;
_`.usage.callback`: updateNode callback method (see
_`.usage.callback`: ``updateNode`` callback method (see
`.type.splay.update.node.method`_)::
void FreeBlockUpdateNode(SplayTree splay, Tree tree)
@ -466,18 +480,18 @@ _`.usage.callback`: updateNode callback method (see
/* the cached value for the left subtree (if any) and the cached */
/* value of the right subtree (if any) */
FreeBlock freeNode = FreeBlockOfSplayNode(tree);
FreeBlock freeNode = FreeBlockOfTree(tree);
Size maxSize = freeNode.size;
if (TreeHasLeft(tree)) {
FreeBlock leftNode = FreeBlockOfSplayNode(TreeLeft(tree));
FreeBlock leftNode = FreeBlockOfTree(TreeLeft(tree));
if(leftNode.maxSize > maxSize)
maxSize = leftNode->maxSize;
}
if (TreeHasRight(tree)) {
FreeBlock rightNode = FreeBlockOfSplayNode(TreeRight(tree));
FreeBlock rightNode = FreeBlockOfTree(TreeRight(tree));
if(rightNode.maxSize > maxSize)
maxSize = rightNode->maxSize;
}
@ -485,13 +499,13 @@ _`.usage.callback`: updateNode callback method (see
freeNode->maxSize = maxSize;
}
_`.usage.compare`: Comparison function (see `.type.splay.compare.method`_)::
_`.usage.compare`: Comparison function (see `.type.tree.compare.method`_)::
Compare FreeBlockCompare(Tree tree, TreeKey key) {
Addr base1, base2, limit2;
FreeBlock freeNode = FreeBlockOfSplayNode(tree);
FreeBlock freeNode = FreeBlockOfTree(tree);
base1 = (Addr *)key;
base1 = (Addr)key;
base2 = freeNode->base;
limit2 = AddrAdd(base2, freeNode->size);
@ -507,13 +521,13 @@ _`.usage.test.tree`: Test tree function (see
`.type.splay.test.tree.method`_)::
Bool FreeBlockTestTree(SplayTree splay, Tree tree
void *closureP, unsigned long closureS) {
void *closureP, Size closureS) {
/* Closure environment has wanted size as value of closureS. */
/* Look at the cached value for the node to see if any */
/* blocks in the subtree are big enough. */
Size size = (Size)closureS;
FreeBlock freeNode = FreeBlockOfSplayNode(tree);
Size size = closureS;
FreeBlock freeNode = FreeBlockOfTree(tree);
return freeNode->maxSize >= size;
}
@ -521,30 +535,30 @@ _`.usage.test.node`: Test node function (see
`.type.splay.test.node.method`_)::
Bool FreeBlockTestNode(SplayTree splay, Tree tree
void *closureP, unsigned long closureS) {
void *closureP, Size closureS) {
/* Closure environment has wanted size as value of closureS. */
/* Look at the size of the node to see if is big enough. */
Size size = (Size)closureS;
FreeBlock freeNode = FreeBlockOfSplayNode(tree);
Size size = closureS;
FreeBlock freeNode = FreeBlockOfTree(tree);
return freeNode->size >= size;
}
_`.usage.initialization`: Client's initialization function (see
`.function.splay.tree.init`_)::
void FreeTreeInit(FreeTree tree) {
void FreeTreeInit(FreeTree freeTree) {
/* Initialize the embedded splay tree. */
SplayTreeInit(&tree->splayTree, FreeBlockCompare, FreeBlockUpdateNode);
SplayTreeInit(&freeTree->splayTree, FreeBlockCompare, FreeBlockUpdateNode);
}
_`.usage.insert`: Client function to add a new free block into the
tree, merging it with an existing block if possible::
void FreeTreeInsert(FreeTree tree, Addr base, Addr limit) {
SplayTree splayTree = &tree->splayTree;
void FreeTreeInsert(FreeTree freeTree, Addr base, Addr limit) {
SplayTree splayTree = &freeTree->splayTree;
Tree leftNeighbour, rightNeighbour;
void *key = (void *)base; /* use the base of the block as the key */
TreeKey key = base; /* use the base of the block as the key */
Res res;
/* Look for any neighbouring blocks. (.function.splay.tree.neighbours) */
@ -560,7 +574,7 @@ tree, merging it with an existing block if possible::
/* The client housekeeping is left as an exercise to the reader. */
/* This changes the size of a block, which is the client */
/* property of the splay node. See `.function.splay.node.refresh`_ */
SplayNodeRefresh(tree, leftNeighbour, key);
SplayNodeRefresh(splayTree, leftNeighbour, key);
} else if (rightNeighbour != TreeEMPTY &&
FreeBlockBaseOfSplayNode(rightNeighbour) == limit) {
@ -568,18 +582,19 @@ tree, merging it with an existing block if possible::
/* The client housekeeping is left as an exercise to the reader. */
/* This changes the size of a block, which is the client */
/* property of the splay node. See `.function.splay.node.refresh`_ */
SplayNodeRefresh(tree, rightNeighbour, key);
SplayNodeRefresh(splayTree, rightNeighbour, key);
} else {
/* Not contiguous - so insert a new node */
FreeBlock newBlock = (FreeBlock)allocate(sizeof(FreeBlockStruct));
splayNode = &newBlock->splayNode;
Tree newTree = &newBlock->treeStruct;
newBlock->base = base;
newBlock->size = AddrOffset(base, limit);
SplayNodeInit(splayNode); /* `.function.splay.node.init`_ */
TreeInit(newTree); /* `.function.tree.init`_ */
SplayNodeUpdate(splayTree, newTree); /* `.function.splay.node.update`_ */
/* `.function.splay.tree.insert`_ */
res = SplayTreeInsert(splayTree, splayNode, key);
res = SplayTreeInsert(splayTree, newTree, key);
AVER(res == ResOK); /* this client doesn't duplicate free blocks */
}
}
@ -589,8 +604,8 @@ given size in address order. For simplicity, this allocates the entire
block::
Bool FreeTreeAllocate(Addr *baseReturn, Size *sizeReturn,
FreeTree tree, Size size) {
SplayTree splayTree = &tree->splayTree;
FreeTree freeTree, Size size) {
SplayTree splayTree = &freeTree->splayTree;
Tree splayNode;
Bool found;
@ -598,10 +613,10 @@ block::
/* closureP parameter is not used. See `.function.splay.find.first.`_ */
found = SplayFindFirst(&splayNode, splayTree,
FreeBlockTestNode, FreeBlockTestTree,
NULL, (unsigned long)size);
NULL, size);
if (found) {
FreeBlock freeNode = FreeBlockOfSplayNode(splayNode);
FreeBlock freeNode = FreeBlockOfTree(splayNode);
Void *key = (void *)freeNode->base; /* use base of block as the key */
Res res;
@ -609,7 +624,7 @@ block::
*baseReturn = freeNode->base;
*sizeReturn = freeNode->size;
/* remove the node from the splay tree - `.function.splay.tree.delete`_ */
/* `.function.splay.tree.delete`_ */
res = SplayTreeDelete(splayTree, splayNode, key);
AVER(res == ResOK); /* Must be possible to delete node */
@ -628,9 +643,9 @@ block::
Implementation
--------------
_`.impl`: For more details of how splay trees work, see paper.st85(0).
_`.impl`: For more details of how splay trees work, see [ST85]_.
For more details of how to implement operations on splay trees, see
paper.sleator96(0). Here we describe the operations involved.
[Sleator96]_. Here we describe the operations involved.
Top-down splaying
@ -638,22 +653,21 @@ Top-down splaying
_`.impl.top-down`: The method chosen to implement the splaying
operation is called "top-down splay". This is described as "procedure
top-down splay" in paper.st85(0) - although the implementation here
additionally permits attempts to access items which are not known to
be in the tree. Top-down splaying is particularly efficient for the
common case where the location of the node in a tree is not known at
the start of an operation. Tree restructuring happens as the tree is
descended, whilst looking for the node.
top-down splay" in [ST85]_, but the implementation here additionally
permits attempts to access items which are not known to be in the
tree. Top-down splaying is particularly efficient for the common case
where the location of the node in a tree is not known at the start of
an operation. Tree restructuring happens as the tree is descended,
whilst looking for the node.
_`.impl.splay`: The key to the operation of the splay tree is the
internal function ``SplaySplay()``. It searches the tree for a node
with a given key. In the process, it
brings the found node, or an arbitrary neighbour if not found, to the
root of the tree. This "bring-to-root" operation is performed top-down
during the search, and it is not the simplest possible bring-to-root
operation, but the resulting tree is well-balanced, and will give good
amortised cost for future calls to ``SplaySplay()``. (See
paper.st85(0))
with a given key. In the process, it brings the found node, or an
arbitrary neighbour if not found, to the root of the tree. This
"bring-to-root" operation is performed top-down during the search, and
it is not the simplest possible bring-to-root operation, but the
resulting tree is well-balanced, and will give good amortised cost for
future calls to ``SplaySplay()``. See [ST85]_.
_`.impl.splay.how`: To perform this top-down splay, the tree is broken
into three parts, a left tree, a middle tree and a right tree. We
@ -667,25 +681,28 @@ they form a partition with the ordering left, middle, right. The splay
is then performed by comparing the middle tree with the following six
cases, and performing the indicated operations, until none apply.
_`.impl.splay.cases`: Note that paper.st85(0)(Fig. 3) describes only 3
cases: zig, zig-zig and zig-zag. The additional cases described here
are the symmetric variants which are respectively called zag, zag-zag
and zag-zig. In the descriptions of these cases, ``root`` is the root
of the middle tree; ``node->left`` is the left child of ``node``;
``node->right`` is the right child of ``node``. The comparison
operators (``<``, ``>``, ``==``) are defined to compare a key and a
node in the obvious way by comparing the supplied key with the node's
associated key.
_`.impl.splay.cases`: Note that figure 3 of [ST85]_ describes only 3
cases: *zig*, *zig-zig* and *zig-zag*. The additional cases described
here are the symmetric variants which are respectively called *zag*,
*zag-zag* and *zag-zig*. In the descriptions of these cases, ``root``
is the root of the middle tree; ``node->left`` is the left child of
``node``; ``node->right`` is the right child of ``node``. The
comparison operators (``<``, ``>``, ``==``) are defined to compare a
key and a node in the obvious way by comparing the supplied key with
the node's associated key.
_`.impl.splay.zig`: The "zig" case is where ``key < root``, and either:
_`.impl.splay.zig`: The "zig" case is where ``key < root``, and
either:
- ``key == root->left``;
- ``key < root->left && root->left->left == NULL``; or
- ``key > root->left && root->left->right == NULL``.
The operation for the zig case is: link right (see `.impl.link.right`_).
The operation for the zig case is: link right (see
`.impl.link.right`_).
_`.impl.splay.zag`: The "zag" case is where ``key > root``, and either:
_`.impl.splay.zag`: The "zag" case is where ``key > root``, and
either:
- ``key == root->right``;
- ``key < root->right && root->right->left == NULL``; or
@ -744,48 +761,58 @@ _`.impl.splay.terminal.not-found`: The other typical terminal cases are:
- ``key < root && root->left == NULL``; and
- ``key > root && root->right == NULL``.
In these cases, the splay operation is complete, the three trees are assembled
(see `.impl.assemble`_), and "not found" is returned.
In these cases, the splay operation is complete, the three trees are
assembled (see `.impl.assemble`_), and "not found" is returned.
_`.impl.rotate.left`: The "rotate left" operation (see paper.st85(0)
Fig. 1) rearranges the middle tree as follows (where any of sub-trees
_`.impl.rotate.left`: The "rotate left" operation (see [ST85]_
figure 1) rearranges the middle tree as follows (where any of sub-trees
A, B and C may be empty):
[missing diagram]
.. figure:: splay-rotate-left.svg
:align: center
:alt: Diagram: the rotate left operation.
_`.impl.rotate.right`: The "rotate right" operation (see paper.st85(0)
Fig. 1) rearranges the middle tree as follows (where any of sub-trees
_`.impl.rotate.right`: The "rotate right" operation (see [ST85]_
figure 1) rearranges the middle tree as follows (where any of sub-trees
A, B and C may be empty):
[missing diagram]
.. figure:: splay-rotate-right.svg
:align: center
:alt: Diagram: the rotate right operation.
_`.impl.link.left`: The "link left" operation (see paper.st85(0) Fig.
_`.impl.link.left`: The "link left" operation (see [ST85]_ figure
11a for symmetric variant) rearranges the left and middle trees as
follows (where any of sub-trees A, B, L and R may be empty):
[missing diagram]
.. figure:: splay-link-left.svg
:align: center
:alt: Diagram: the link left operation.
The last node of the left tree is now x.
_`.impl.link.right`: The "link right" operation (see paper.st85(0)
Fig. 11a) rearranges the middle and right trees as follows (where any
of sub-trees A, B, L and R may be empty):
_`.impl.link.right`: The "link right" operation (see [ST85]_ figure
11a) rearranges the middle and right trees as follows (where any of
sub-trees A, B, L and R may be empty):
[missing diagram]
.. figure:: splay-link-right.svg
:align: center
:alt: Diagram: the link left operation.
The first node of the right tree is now x.
_`.impl.assemble`: The "assemble" operation (see paper.st85(0)
Fig. 12) merges the left and right trees with the middle tree as
follows (where any of sub-trees A, B, L and R may be empty):
_`.impl.assemble`: The "assemble" operation (see [ST85]_ figure 12)
merges the left and right trees with the middle tree as follows (where
any of sub-trees A, B, L and R may be empty):
[missing diagram]
.. figure:: splay-assemble.svg
:align: center
:alt: Diagram: the assemble operation.
Top-level operations
....................
_`.impl.insert`: ``SplayTreeInsert()``: (See paper.sleator96(0), chapter
_`.impl.insert`: ``SplayTreeInsert()``: (See [Sleator96]_, chapter
4, function insert). If the tree has no nodes, [how does it smell?]
add the inserted node and we're done; otherwise splay the tree around
the supplied key. If the splay successfully found a matching node,
@ -794,7 +821,7 @@ the old (newly splayed, but non-matching) root as its left or right
child as appropriate, and the opposite child of the old root as the
other child of the new root.
_`.impl.delete`: ``SplayTreeDelete()``: (See paper.sleator96(0), chapter
_`.impl.delete`: ``SplayTreeDelete()``: (See [Sleator96]_, chapter
4, function delete). Splay the tree around the supplied key. Check
that the newly splayed root is the same node as given by the caller,
and that it matches the key; return failure if not. If the given node
@ -881,8 +908,8 @@ _`.future.parent`: The iterator could be made more efficient (in an
amortized sense) if it didn't splay at each node. To implement this
(whilst meeting `.req.stack`_) we really need parent pointers from the
nodes. We could use the (first-child, right-sibling/parent) trick
described in paper.st85 to implement this, at a slight cost to all
other tree operations, and an increase in code complexity. paper.st85
described in [ST85]_ to implement this, at a slight cost to all
other tree operations, and an increase in code complexity. [ST85]_
doesn't describe how to distinguish the first-child between left-child
and right-child, and the right-sibling/parent between right-sibling
and parent. One could either use the comparator to make these

View file

@ -21,4 +21,5 @@ Design
range
ring
sig
splay
type

View file

@ -53,7 +53,6 @@ Old design
scan
seg
shield
splay
sso1al
strategy
telemetry