1// 2// KTPlaceholderMatrix 3// KTMatrix collection class cluster 4// 5// KTMatrix class cluster initialisation subclass 6// 7// Copyright (c) 2002 Chris Purcell. All rights reserved. 8// 9// You may use this code for whatever purposes you wish. 10// This code comes with no warranties, implied or otherwise. 11// Using it may damage your data. It shouldn't, but save a copy first. 12// That's a good idea anyway, actually. 13// 14 15#import "KTPlaceholderMatrix.h" 16#import "KTCuboidHash.h" 17#import "KTMatrixSparseImp.h" 18#import "KTMatrixDenseImp.h" 19#import "KTMutableMatrixSparseImp.h" 20 21@implementation KTPlaceholderMatrix 22 23//// Primitive methods 24- (id)init 25{ 26 NSZone *zone = [self zone]; 27 KTCuboidHash *hash = [[KTCuboidHash alloc] init]; 28 [self release]; 29 self = [[KTMatrixSparseImp allocWithZone:zone] 30 initWithLocationHash:hash]; 31 [hash release]; 32 return self; 33} 34- (id)initWithMatrix:(KTMatrix *)matrix 35{ 36 NSZone *zone = [self zone]; 37 [self release]; 38 if (([[matrix locationHash] hashBound] == 0) || 39 ([matrix count] < [[matrix locationHash] hashBound]/3)) 40 self = [KTMatrixSparseImp allocWithZone:zone]; 41 else 42 self = [KTMatrixDenseImp allocWithZone:zone]; 43 self = [self initWithMatrix:matrix]; 44 return self; 45} 46- (id)initWithLocationHash:(id<KTLocationHash>)hash 47{ 48 NSZone *zone = [self zone]; 49 [self release]; 50 return [[KTMatrixSparseImp allocWithZone:zone] initWithLocationHash:hash]; 51} 52- (id)initWithLocationHash:(id<KTLocationHash>)hash 53 objects:(NSArray *)objects 54 atLocations:(NSArray *)loc1s 55 byLocations:(NSArray *)loc2s 56{ 57 NSZone *zone = [self zone]; 58 [self release]; 59 if (([hash hashBound] == 0) || ([objects count] < [hash hashBound]/3)) 60 self = [KTMatrixSparseImp allocWithZone:zone]; 61 else 62 self = [KTMatrixDenseImp allocWithZone:zone]; 63 self = [self initWithLocationHash:hash 64 objects:objects 65 atLocations:loc1s 66 byLocations:loc2s]; 67 return self; 68} 69 70//// Efficient implementations of other methods 71- (id)initWithCuboidBoundsObjectAtCoordinates:(unsigned)bound1,... 72{ 73 NSZone *zone = [self zone]; 74 KTCuboidHash *hash; 75 id object = nil; 76 va_list args; 77 78 [self release]; 79 80 va_start(args, bound1); 81 hash = [[KTCuboidHash allocWithZone:zone] 82 initWithBoundsList:bound1 :&args]; 83 84 object = va_arg(args, id); 85 86 if (([hash hashBound] != 0) && ([hash hashBound] <= 3)) 87 self = [KTMatrixDenseImp alloc]; 88 else 89 self = [KTMatrixSparseImp alloc]; 90 self = [(id)self initWithLocationHash:hash 91 object:object 92 atHashedLocation:[hash hashForCoordinatesList:&args]]; 93 94 va_end(args); 95 [hash release]; 96 return self; 97} 98- (id)initWithCuboidBoundsObjectsAtCoordinates:(unsigned)bound1,... 99{ // Can optimize away some inefficiencies 100 NSZone *zone = [self zone]; 101 KTCuboidHash *hash; // The hashing object to use 102 va_list args; // To trawl through the arguments 103 id object; // Used to store the objects in the arguments 104 105 // Need a mutable temporary to store all the objects 106 KTMutableMatrixSparseImp *temp; 107 // SELs/IMPs to speed up repeated method calls 108 SEL hashListSEL = @selector(hashForCoordinatesList:); 109 SEL setObjSEL = @selector(setObject:atHashedLocation:); 110 unsigned (*hashListIMP)(id, SEL, ...); 111 void (*setObjIMP)(id, SEL, ...); 112 113 [self release]; 114 115 // Read in data for the cuboid hash 116 va_start(args, bound1); 117 hash = [[KTCuboidHash allocWithZone:zone] 118 initWithBoundsList:bound1 :&args]; 119 120 // Allocate the temporary mutable matrix 121 temp = [[KTMutableMatrixSparseImp allocWithZone:zone] 122 initWithCapacity:0 123 locationHash:hash]; 124 125 // Read in objects and coordinates 126 hashListIMP = (unsigned (*)(id, SEL, ...)) 127 [hash methodForSelector:hashListSEL]; 128 setObjIMP = (void (*)(id, SEL, ...)) 129 [temp methodForSelector:setObjSEL]; 130 while (object = va_arg(args, id)) 131 setObjIMP(temp, setObjSEL, object, 132 hashListIMP(hash,hashListSEL,&args)); 133 134 // Make an immutable copy of the object 135 self = [temp copyWithZone:zone]; 136 [temp release]; 137 138 [hash release]; 139 va_end(args); 140 return self; 141} 142@end 143