1// 2// KTPlaceholderMutableMatrix 3// KTMatrix collection class cluster 4// 5// KTMutableMatrix 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 "KTPlaceholderMutableMatrix.h" 16#import "KTCuboidHash.h" 17#import "KTMutableMatrixSparseImp.h" 18#import "KTMutableMatrixDenseImp.h" 19 20@implementation KTPlaceholderMutableMatrix 21 22- (id)init 23{ 24 NSZone *zone = [self zone]; 25 id<KTLocationHash> hash = [[KTCuboidHash allocWithZone:zone] init]; 26 [self release]; 27 self = [[KTMutableMatrixSparseImp allocWithZone:zone] 28 initWithCapacity:0 locationHash:hash]; 29 [hash release]; 30 return self; 31} 32- (id)initWithMatrix:(KTMatrix *)matrix 33{ 34 NSZone *zone = [self zone]; 35 [self release]; 36 if (([[matrix locationHash] hashBound] == 0) || 37 ([matrix count] < [[matrix locationHash] hashBound]/3)) 38 self = [KTMutableMatrixSparseImp allocWithZone:zone]; 39 else 40 self = [KTMutableMatrixDenseImp allocWithZone:zone]; 41 [self initWithMatrix:matrix]; 42 return self; 43} 44- (id)initWithLocationHash:(id<KTLocationHash>)hash 45 objects:(NSArray *)objects 46 atLocations:(NSArray *)loc1s 47 byLocations:(NSArray *)loc2s 48{ 49 NSZone *zone = [self zone]; 50 [self release]; 51 if (([hash hashBound] == 0) || 52 ([objects count] < [hash hashBound]/3)) 53 self = [KTMutableMatrixSparseImp allocWithZone:zone]; 54 else 55 self = [KTMutableMatrixDenseImp allocWithZone:zone]; 56 self = [self initWithLocationHash:hash 57 objects:objects 58 atLocations:loc1s 59 byLocations:loc2s]; 60 return self; 61} 62- (id)initWithCapacity:(unsigned)numItems 63 locationHash:(id<KTLocationHash>)hash 64{ 65 NSZone *zone = [self zone]; 66 [self release]; 67 if (([hash hashBound] == 0) || (numItems < [hash hashBound]/3)) 68 self = [KTMutableMatrixSparseImp allocWithZone:zone]; 69 else 70 self = [KTMutableMatrixDenseImp allocWithZone:zone]; 71 [self initWithCapacity:numItems 72 locationHash:hash]; 73 return self; 74} 75 76//// Efficient implementations of other methods 77- (id)initWithCuboidBoundsObjectAtCoordinates:(unsigned)bound1,... 78{ 79 NSZone *zone = [self zone]; 80 KTCuboidHash *hash; 81 id object = nil; 82 va_list args; 83 84 [self release]; 85 86 va_start(args, bound1); 87 hash = [[KTCuboidHash allocWithZone:zone] 88 initWithBoundsList:bound1 :&args]; 89 90 object = va_arg(args, id); 91 92 if (([hash hashBound] != 0) && ([hash hashBound] <= 3)) 93 self = [KTMutableMatrixDenseImp alloc]; 94 else 95 self = [KTMutableMatrixSparseImp alloc]; 96 self = [(id)self initWithLocationHash:hash 97 object:object 98 atHashedLocation:[hash hashForCoordinatesList:&args]]; 99 100 va_end(args); 101 [hash release]; 102 return self; 103} 104- (id)initWithCuboidBoundsObjectsAtCoordinates:(unsigned)bound1,... 105{ // Can optimize away some inefficiencies 106 NSZone *zone = [self zone]; 107 KTCuboidHash *hash; // The hashing object to use 108 va_list args; // To trawl through the arguments 109 id object; // Used to store the objects in the arguments 110 111 // Need a mutable temporary to store all the objects 112 KTMutableMatrixSparseImp *temp; 113 // SELs/IMPs to speed up repeated method calls 114 SEL hashListSEL = @selector(hashForCoordinatesList:); 115 SEL setObjSEL = @selector(setObject:atHashedLocation:); 116 unsigned (*hashListIMP)(id, SEL, ...); 117 void (*setObjIMP)(id, SEL, ...); 118 119 [self release]; 120 121 // Read in data for the cuboid hash 122 va_start(args, bound1); 123 hash = [[KTCuboidHash allocWithZone:zone] 124 initWithBoundsList:bound1 :&args]; 125 126 // Allocate the temporary mutable matrix 127 temp = [[KTMutableMatrixSparseImp allocWithZone:zone] 128 initWithCapacity:0 129 locationHash:hash]; 130 131 // Read in objects and coordinates 132 hashListIMP = (unsigned (*)(id, SEL, ...)) 133 [hash methodForSelector:hashListSEL]; 134 setObjIMP = (void (*)(id, SEL, ...)) 135 [temp methodForSelector:setObjSEL]; 136 while (object = va_arg(args, id)) 137 setObjIMP(temp, setObjSEL, object, 138 hashListIMP(hash,hashListSEL,&args)); 139 140 // Make a mutable copy of the object if necessary 141 if (([hash hashBound] == 0) || 142 ([temp count] < [hash hashBound]/3)) 143 self = [temp retain]; 144 else 145 self = [temp mutableCopyWithZone:zone]; 146 [temp release]; 147 148 [hash release]; 149 va_end(args); 150 return self; 151} 152 153@end 154