1//
2//  KTMutableMatrixImp
3//  KTMatrix
4//
5//  Implements a mutable KTMutableMatrix 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 "KTMutableMatrixImp.h"
16
17@implementation KTMutableMatrixImp
18
19+ (id)matrixWithMatrix:(KTMatrix *)other
20{
21    return [[[self alloc] initWithMatrix:other] autorelease];
22}
23+ (id)matrixWithLocationHash:(id<KTLocationHash>)locationHash
24                     objects:(NSArray *)objects
25                 atLocations:(NSArray *)loc1s
26                 byLocations:(NSArray *)loc2s
27{
28    return [[[self alloc] initWithLocationHash:locationHash
29                                       objects:objects
30                                   atLocations:loc1s
31                                   byLocations:loc2s] autorelease];
32}
33+ (id)matrixWithCapacity:(unsigned)numItems
34            locationHash:(id<KTLocationHash>)_hs
35{
36    return [[KTMutableMatrixImp alloc] initWithCapacity:numItems
37                                           locationHash:_hs];
38}
39- (id)initWithMatrix:(KTMatrix *)other
40{
41    if ((self = [super init]))
42        {
43        matrix = [[other matrixData] mutableCopyWithZone:[self zone]];
44        if ([[other locationHash] zone] == [self zone])
45            hash = [[other locationHash] retain];
46        else
47            hash = [[other locationHash] copyWithZone:[self zone]];
48        }
49    return self;
50}
51- (id)initWithMatrixData:(NSDictionary *)matrixData
52            locationHash:(id<KTLocationHash>)locationHash
53{
54    if ((self = [super init]))
55        {
56        matrix = [matrixData mutableCopyWithZone:[self zone]];
57        if ([locationHash zone] == [self zone])
58            hash = [locationHash retain];
59        else
60            hash = [locationHash copyWithZone:[self zone]];
61        }
62    return self;
63}
64- (id)initWithLocationHash:(id<KTLocationHash>)locationHash
65{
66    if ((self = [super init]))
67        {
68        matrix = [[NSMutableDictionary allocWithZone:[self zone]] init];
69        if ([locationHash zone] == [self zone])
70            hash = [locationHash retain];
71        else
72            hash = [locationHash copyWithZone:[self zone]];
73        }
74    return self;
75}
76- (id)initWithLocationHash:(id<KTLocationHash>)locationHash
77                   objects:(NSArray *)objects
78               atLocations:(NSArray *)loc1s
79               byLocations:(NSArray *)loc2s
80{
81    if ((self = [super init]))
82        {
83        NSMutableArray *indices = [[NSMutableArray alloc] initWithCapacity:
84            [loc1s count]];
85        unsigned i;
86
87        if ([locationHash zone] == [self zone])
88            hash = [locationHash retain];
89        else
90            hash = [locationHash copyWithZone:[self zone]];
91
92        NSAssert([objects count] == [loc1s count],
93                 @"Objects and locations arrays not of equal length");
94        NSAssert([loc1s count] == [loc2s count],
95                 @"Locations arrays not of equal length");
96        for (i = 0; i < [loc1s count]; i++)
97            {
98            [indices addObject:[NSNumber numberWithInt:
99                [hash hashForLocation:[loc1s objectAtIndex:i]
100                           byLocation:[loc2s objectAtIndex:i]]]];
101            }
102        matrix = [[NSMutableDictionary allocWithZone:[self zone]]
103            initWithObjects:objects
104                    forKeys:indices];
105
106        [indices release];
107        }
108    return self;
109}
110- (id)initWithCapacity:(unsigned)numItems
111          locationHash:(id<KTLocationHash>)locationHash
112{
113    if ((self = [super init]))
114        {
115        matrix = [[NSMutableDictionary allocWithZone:[self zone]]
116                                  initWithCapacity:numItems];
117        if ([locationHash zone] == [self zone])
118            hash = [locationHash retain];
119        else
120            hash = [locationHash copyWithZone:[self zone]];
121        }
122    return self;
123}
124
125
126// Accessor methods
127- (id)objectAtLocation:(NSDictionary *)loc
128            byLocation:(NSDictionary *)loc2;
129{
130    return [matrix objectForKey:[NSNumber numberWithInt:[hash
131        hashForLocation:loc byLocation:loc2]]];
132}
133
134- (id<KTLocationHash>)locationHash
135{ return hash; }
136- (NSDictionary *)matrixData
137{ return matrix; }
138
139- (NSEnumerator *)objectEnumerator
140{ return [matrix objectEnumerator]; }
141- (unsigned)count
142{ return [matrix count]; }
143
144
145//// Mutator methods
146- (void)setMatrix:(KTMatrix *)other
147{
148    [matrix release];
149    [hash release];
150    matrix = [[other matrixData] mutableCopyWithZone:[self zone]];
151    if ([[other locationHash] zone] == [self zone])
152        hash = [[other locationHash] retain];
153    else
154        hash = [[other locationHash] copyWithZone:[self zone]];
155}
156- (void)setObject:(id)object
157       atLocation:(NSDictionary *)loc1
158       byLocation:(NSDictionary *)loc2
159{
160    [matrix setObject:object
161               forKey:[NSNumber numberWithInt:[hash
162                                       hashForLocation:loc1
163                                            byLocation:loc2]]];
164}
165- (void)removeObjectAtLocation:(NSDictionary *)loc1
166                    byLocation:(NSDictionary *)loc2;
167{
168    [matrix removeObjectForKey:[NSNumber numberWithInt:[hash
169                                       hashForLocation:loc1
170                                            byLocation:loc2]]];
171}
172- (void)removeAllObjects
173{
174    [matrix removeAllObjects];
175}
176
177- (void)dealloc
178{
179    [matrix release];
180    [hash release];
181}
182@end
183