1//
2//  KTMatrixImp
3//  KTMatrix
4//
5//  Implements an immutable KTMatrix 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 "KTMatrixImp.h"
16
17@implementation KTMatrixImp
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)initWithMatrix:(KTMatrix *)other
34{
35    if ((self = [super init]))
36        {
37        matrix = [[other matrixData] copyWithZone:[self zone]];
38        if ([[other locationHash] zone] == [self zone])
39            hash = [[other locationHash] retain];
40        else
41            hash = [[other locationHash] copyWithZone:[self zone]];
42        }
43    return self;
44}
45- (id)initWithMatrixData:(NSDictionary *)matrixData
46            locationHash:(id<KTLocationHash>)locationHash
47{
48    if ((self = [super init]))
49        {
50        matrix = [matrixData copyWithZone:[self zone]];
51        if ([locationHash zone] == [self zone])
52            hash = [locationHash retain];
53        else
54            hash = [locationHash copyWithZone:[self zone]];
55        }
56    return self;
57}
58- (id)initWithLocationHash:(id<KTLocationHash>)locationHash
59                   objects:(NSArray *)objects
60               atLocations:(NSArray *)loc1s
61               byLocations:(NSArray *)loc2s
62{
63    if ((self = [super init]))
64        {
65        NSMutableArray *indices = [[NSMutableArray alloc] initWithCapacity:
66            [loc1s count]];
67        int i;
68
69        if ([locationHash zone] == [self zone])
70            hash = [locationHash retain];
71        else
72            hash = [locationHash copyWithZone:[self zone]];
73
74        NSAssert([objects count] == [loc1s count],
75                 @"Objects and locations arrays not of equal length");
76        NSAssert([loc1s count] == [loc2s count],
77                 @"Locations arrays not of equal length");
78        for (i = 0; i < [loc1s count]; i++)
79            {
80            [indices addObject:[NSNumber numberWithInt:
81                [hash hashForLocation:[loc1s objectAtIndex:i]
82                           byLocation:[loc2s objectAtIndex:i]]]];
83            }
84        matrix = [[NSDictionary allocWithZone:[self zone]]
85            initWithObjects:objects
86                    forKeys:indices];
87
88        [indices release];
89        }
90    return self;
91}
92
93    // Accessor methods
94- (id)objectAtLocation:(NSDictionary *)loc
95            byLocation:(NSDictionary *)loc2;
96{
97    return [matrix objectForKey:[NSNumber numberWithInt:[hash
98        hashForLocation:loc byLocation:loc2]]];
99}
100
101- (id<KTLocationHash>)locationHash
102{ return hash; }
103- (NSDictionary *)matrixData
104{ return matrix; }
105
106- (NSEnumerator *)objectEnumerator
107{ return [matrix objectEnumerator]; }
108- (unsigned)count
109{ return [matrix count]; }
110
111- (void)dealloc
112{
113    [matrix release];
114    [hash release];
115}
116@end
117