├── .gitignore
├── .travis.yml
├── AppledocSettings.plist
├── LICENSE
├── README.md
├── YCMatrix.xcodeproj
├── project.pbxproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcuserdata
│ │ └── yanconst.xcuserdatad
│ │ └── WorkspaceSettings.xcsettings
├── xcshareddata
│ └── xcschemes
│ │ └── YCMatrix.xcscheme
└── xcuserdata
│ ├── oo.xcuserdatad
│ └── xcschemes
│ │ ├── YCMatrix.xcscheme
│ │ └── xcschememanagement.plist
│ └── yanconst.xcuserdatad
│ ├── xcdebugger
│ └── Breakpoints_v2.xcbkptlist
│ └── xcschemes
│ └── xcschememanagement.plist
├── YCMatrix
├── Constants.h
├── HaltonInterface.h
├── HaltonInterface.mm
├── Matrix+Advanced.h
├── Matrix+Advanced.m
├── Matrix+Manipulate.h
├── Matrix+Manipulate.m
├── Matrix+Map.h
├── Matrix+Map.m
├── Matrix.h
├── Matrix.m
├── NSArray+Matrix.h
├── NSArray+Matrix.m
├── YCMatrix-Info.plist
├── YCMatrix.h
├── en.lproj
│ └── InfoPlist.strings
├── halton_sampler.h
└── soboldata.h
├── YCMatrixTests
├── YCMatrixAdvancedTests.m
├── YCMatrixManipulateTests.m
├── YCMatrixMapTests.m
├── YCMatrixNSArrayTests.m
├── YCMatrixPerformanceTests.m
├── YCMatrixTests-Info.plist
├── YCMatrixTests.m
└── en.lproj
│ └── InfoPlist.strings
└── ycmatrix.png
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 |
4 | ## Build generated
5 | build/
6 | DerivedData/
7 |
8 | ## Various settings
9 | *.pbxuser
10 | !default.pbxuser
11 | *.mode1v3
12 | !default.mode1v3
13 | *.mode2v3
14 | !default.mode2v3
15 | *.perspectivev3
16 | !default.perspectivev3
17 | xcuserdata/
18 |
19 | ## Other
20 | *.moved-aside
21 | *.xccheckout
22 | *.xcscmblueprint
23 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: objective-c
2 | xcode_project: YCMatrix.xcodeproj
3 | osx_image: xcode7
4 | xcode_scheme: YCMatrix
5 |
6 | branches:
7 | only:
8 | - master
9 |
--------------------------------------------------------------------------------
/AppledocSettings.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | --project-name
6 | YCMatrix
7 | --project-version
8 | 0.6.16
9 | --project-company
10 | Ioannis Chatzikonstantinou / yconst.com
11 | --create-html
12 |
13 | --create-docset
14 |
15 | --output
16 | ./YCMatrix
17 |
18 |
19 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | YCMatrix
2 |
3 | Copyright (c) 2013 - 2016 Ioannis (Yannis) Chatzikonstantinou. All rights reserved.
4 | http://yconst.com
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in
14 | all copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | THE SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | # YCMatrix
5 |
6 | [](https://travis-ci.org/yconst/YCMatrix)
7 | [](https://zenodo.org/badge/latestdoi/20003/yconst/YCMatrix)
8 | [](https://github.com/Carthage/Carthage)
9 |
10 | A flexible Matrix library for Objective-C and Swift, that interfaces
11 | BLAS, LAPACK and vDSP functions via the Accelerate Framework.
12 |
13 | YCMatrix is available for MacOS (10.7+), as well as iOS (8.0+).
14 |
15 | ## Getting started
16 |
17 | ### Adding the framework to your project
18 |
19 | Import the project in your workspace, or open the framework project in XCode, build and import the product.
20 |
21 | .. or alternatively, just drag+drop the files (.h and .m) that you want to your project, presto.
22 |
23 | ### Importing
24 |
25 | YCMatrix defines a module so in newer versions of XCode,
26 | you can simply import the framework with:
27 |
28 | @include YCMatrix;
29 |
30 | Alternatively, you can do:
31 |
32 | #import "YCMatrix/YCMatrix.h"
33 |
34 | ### Dependencies
35 |
36 | YCMatrix has no dependencies other than system
37 | frameworks (namely Foundation.framework and Accelerate.framework).
38 |
39 | ### Importing/Using with CocoaPods (no longer supported)
40 |
41 | Unfortunately Cocoapods is no longer supported as of 0.6.8. The decision to end Cocoapods support is related to the increasing time needed for debugging related to Cocoapods support (e.g. Xcode/OS updates, addition of C++ etc.). Dropping Cocoapods support will allow for more time spent to developing the project. We recommend Carthage for managing your project's dependencies. You may easily include YCMatrix in your cartfile as follows:
42 |
43 | github "yconst/YCMatrix"
44 |
45 | In addition, YCMatrix can be easily included manually into an Xcode project, by copying header and implementation files (and optionally creating a new target).
46 |
47 | ## Usage
48 |
49 | ### Naming Conventions
50 |
51 | Methods that result in a new Matrix instance are usually prefixed with "matrixFrom",
52 | e.g. -matrixFromSubtraction: . Methods that change the receiver in-place
53 | do not have the prefix. In some cases, such as matrix-matrix multiplication,
54 | the prefix is not included in the method name, even though it is obvious that
55 | the result of the operation is a new Matrix instance.
56 |
57 | ### Example
58 |
59 | The snippet below is a basic example of matrix multiplication.
60 | It also shows how you can easily create matrices with predefined
61 | values.
62 |
63 | @include YCMatrix;
64 |
65 | Matrix *I = [Matrix identityOfRows:3 columns:3]; // 3x3 Identity
66 | Matrix *C = [Matrix matrixOfRows:3 columns:3 value:2]; // 3x3 filled with 2s
67 | Matrix *S = [I matrixByAddition:C]; // Outputs a new matrix
68 | NSLog(@"Result:\n%@", S);
69 |
70 | // Result:
71 | // 3.0 2.0 2.0
72 | // 2.0 3.0 2.0
73 | // 2.0 2.0 3.0
74 |
75 | ## What's in there?
76 |
77 | The Framework functionality is split into four files: The base class
78 | definition, and three categories:
79 |
80 | - Matrix.h : YCMatrix class definition and basic operations.
81 | - Matrix+Advanced.h : Interface to more advanced LAPACK functions.
82 | - Matrix+Manipulate.h : Functions for manipulating rows/columns etc.
83 | - Matrix+Map.h : Functions for linearly mapping matrices.
84 |
85 | In addition, there is a file that implements functionality related to NSArrays containing Matrices.
86 |
87 | Please refer to the [docs](http://cocoadocs.org/docsets/YCMatrix/) for a complete overview of the functionality
88 | contained in each of the categories.
89 |
90 | In addition, YCMatrix comes with many unit tests included. Tests are divided in six files:
91 |
92 | - YCMatrixTests : General Matrix-related tests.
93 | - YCMatrixAdvancedTests : Tests related to higher-level operations (decompositions, inverses etc.).
94 | - YCMatrixManipulateTests : Tests related to matrix manipulation operations.
95 | - YCMatrixMapTests : Tests related to linear mapping operations.
96 | - YCMatrixNSArrayTests : Tests related to NSArray categories.
97 | - YCMatrixPerformanceTests: Tests for measuring performance of various operations.
98 |
99 | ## Performance
100 |
101 | YCMatrix has been built from the ground up with performance in mind. vDSP, BLAS and LAPACK are being used extensively throughout the framework. In addition, care has been given in memory allocation during initialization and copying.
102 |
103 | The test file YCMatrixPerformanceTests.m contains some benchmarks using different addition/subtraction implementations (vDSP, BLAS, and pure C).
104 |
105 | ## License
106 |
107 | __YCMatrix__
108 |
109 | Copyright (c) 2013 - 2016 Ioannis (Yannis) Chatzikonstantinou. All rights reserved.
110 | http://yconst.com
111 |
112 | Permission is hereby granted, free of charge, to any person obtaining a copy
113 | of this software and associated documentation files (the "Software"), to deal
114 | in the Software without restriction, including without limitation the rights
115 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
116 | copies of the Software, and to permit persons to whom the Software is
117 | furnished to do so, subject to the following conditions:
118 |
119 | The above copyright notice and this permission notice shall be included in
120 | all copies or substantial portions of the Software.
121 |
122 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
123 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
124 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
125 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
126 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
127 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
128 | THE SOFTWARE.
129 |
130 | ## Acknowledgments
131 |
132 | This software relies on the following copyrighted material, the use of which is hereby acknowledged.
133 |
134 | ----
135 |
136 | soboldata.h and sobolseq.c
137 | Part of the NLOpt Software
138 |
139 | Copyright (c) 2007 Massachusetts Institute of Technology
140 |
141 | Permission is hereby granted, free of charge, to any person obtaining
142 | a copy of this software and associated documentation files (the
143 | "Software"), to deal in the Software without restriction, including
144 | without limitation the rights to use, copy, modify, merge, publish,
145 | distribute, sublicense, and/or sell copies of the Software, and to
146 | permit persons to whom the Software is furnished to do so, subject to
147 | the following conditions:
148 |
149 | The above copyright notice and this permission notice shall be
150 | included in all copies or substantial portions of the Software.
151 |
152 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
153 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
154 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
155 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
156 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
157 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
158 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
159 |
160 | ----
161 |
162 | haltondata.cpp
163 |
164 | Copyright (c) 2012 Leonhard Gruenschloss (leonhard@gruenschloss.org)
165 |
166 | Permission is hereby granted, free of charge, to any person obtaining a copy
167 | of this software and associated documentation files (the "Software"), to deal
168 | in the Software without restriction, including without limitation the rights to
169 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
170 | of the Software, and to permit persons to whom the Software is furnished to do
171 | so, subject to the following conditions:
172 |
173 | The above copyright notice and this permission notice shall be included in
174 | all copies or substantial portions of the Software.
175 |
176 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
177 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
178 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
179 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
180 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
181 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
182 | SOFTWARE.
183 |
184 | ----
185 |
186 | Routine for computing the Singular Value Decomposition
187 | of *column-major* matrix A using LAPACK
188 |
189 | Author: Luke Lonergan
190 | Date: 5/31/08
191 | License: Use pfreely
192 |
193 |
--------------------------------------------------------------------------------
/YCMatrix.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | CB02F7B51AAF446400EF1E02 /* YCMatrix.h in Headers */ = {isa = PBXBuildFile; fileRef = CB02F7B41AAF446400EF1E02 /* YCMatrix.h */; settings = {ATTRIBUTES = (Public, ); }; };
11 | CB0B6D391C5A5B05002A76E2 /* YCMatrixPerformanceTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CB0B6D381C5A5B05002A76E2 /* YCMatrixPerformanceTests.m */; };
12 | CB26DAA21A856232007F73E2 /* NSArray+Matrix.h in Headers */ = {isa = PBXBuildFile; fileRef = CB26DAA01A856232007F73E2 /* NSArray+Matrix.h */; settings = {ATTRIBUTES = (Public, ); }; };
13 | CB26DAA31A856232007F73E2 /* NSArray+Matrix.m in Sources */ = {isa = PBXBuildFile; fileRef = CB26DAA11A856232007F73E2 /* NSArray+Matrix.m */; };
14 | CB4388EA1C2887BE00C6D330 /* halton_sampler.h in Headers */ = {isa = PBXBuildFile; fileRef = CB4388E91C2887BE00C6D330 /* halton_sampler.h */; };
15 | CB4D3CA81C10F092009CAE8B /* soboldata.h in Headers */ = {isa = PBXBuildFile; fileRef = CB4D3CA71C10F092009CAE8B /* soboldata.h */; };
16 | CB723AFC1C47C37600600043 /* YCMatrixNSArrayTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CB723AFB1C47C37600600043 /* YCMatrixNSArrayTests.m */; };
17 | CBBE02BA178F215000744F77 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = CBBE02B8178F215000744F77 /* InfoPlist.strings */; };
18 | CBBE02BE178F215000744F77 /* Matrix.m in Sources */ = {isa = PBXBuildFile; fileRef = CBBE02BD178F215000744F77 /* Matrix.m */; };
19 | CBBE02CA178F215100744F77 /* YCMatrix.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CBBE02AC178F215000744F77 /* YCMatrix.framework */; };
20 | CBBE02D0178F215100744F77 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = CBBE02CE178F215100744F77 /* InfoPlist.strings */; };
21 | CBBE02D3178F215100744F77 /* YCMatrixTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CBBE02D2178F215100744F77 /* YCMatrixTests.m */; };
22 | CBBE02E0178F216800744F77 /* Matrix+Advanced.h in Headers */ = {isa = PBXBuildFile; fileRef = CBBE02DC178F216800744F77 /* Matrix+Advanced.h */; settings = {ATTRIBUTES = (Public, ); }; };
23 | CBBE02E1178F216800744F77 /* Matrix+Advanced.m in Sources */ = {isa = PBXBuildFile; fileRef = CBBE02DD178F216800744F77 /* Matrix+Advanced.m */; };
24 | CBBE02E2178F216800744F77 /* Matrix+Manipulate.h in Headers */ = {isa = PBXBuildFile; fileRef = CBBE02DE178F216800744F77 /* Matrix+Manipulate.h */; settings = {ATTRIBUTES = (Public, ); }; };
25 | CBBE02E3178F216800744F77 /* Matrix+Manipulate.m in Sources */ = {isa = PBXBuildFile; fileRef = CBBE02DF178F216800744F77 /* Matrix+Manipulate.m */; };
26 | CBBE02E9178F218600744F77 /* YCMatrixManipulateTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CBBE02E7178F218600744F77 /* YCMatrixManipulateTests.m */; };
27 | CBBE0301178F258B00744F77 /* Matrix.h in Headers */ = {isa = PBXBuildFile; fileRef = CBBE02BC178F215000744F77 /* Matrix.h */; settings = {ATTRIBUTES = (Public, ); }; };
28 | CBCF36241C28383D009D89D7 /* HaltonInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = CBCF36221C28383D009D89D7 /* HaltonInterface.h */; };
29 | CBCF36251C28383D009D89D7 /* HaltonInterface.mm in Sources */ = {isa = PBXBuildFile; fileRef = CBCF36231C28383D009D89D7 /* HaltonInterface.mm */; };
30 | CBD5120719D37764004DD8D3 /* Constants.h in Headers */ = {isa = PBXBuildFile; fileRef = CBD5120619D37764004DD8D3 /* Constants.h */; };
31 | CBD7D3D218A4DD10006A04C0 /* Matrix+Map.h in Headers */ = {isa = PBXBuildFile; fileRef = CBD7D3D018A4DD10006A04C0 /* Matrix+Map.h */; settings = {ATTRIBUTES = (Public, ); }; };
32 | CBD7D3D318A4DD10006A04C0 /* Matrix+Map.m in Sources */ = {isa = PBXBuildFile; fileRef = CBD7D3D118A4DD10006A04C0 /* Matrix+Map.m */; };
33 | CBE66B9A1A6BB0A000E2EF2C /* YCMatrixMapTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CBE66B991A6BB0A000E2EF2C /* YCMatrixMapTests.m */; };
34 | CBE9E7AD19D0D79600460953 /* YCMatrixAdvancedTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CBE9E7AC19D0D79600460953 /* YCMatrixAdvancedTests.m */; };
35 | /* End PBXBuildFile section */
36 |
37 | /* Begin PBXContainerItemProxy section */
38 | CBBE02C8178F215100744F77 /* PBXContainerItemProxy */ = {
39 | isa = PBXContainerItemProxy;
40 | containerPortal = CBBE02A3178F215000744F77 /* Project object */;
41 | proxyType = 1;
42 | remoteGlobalIDString = CBBE02AB178F215000744F77;
43 | remoteInfo = YCMatrix;
44 | };
45 | /* End PBXContainerItemProxy section */
46 |
47 | /* Begin PBXFileReference section */
48 | CB02F7B41AAF446400EF1E02 /* YCMatrix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = YCMatrix.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
49 | CB0B6D381C5A5B05002A76E2 /* YCMatrixPerformanceTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YCMatrixPerformanceTests.m; sourceTree = ""; };
50 | CB2242AF19D413C0005B3F7E /* AppledocSettings.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = AppledocSettings.plist; sourceTree = ""; };
51 | CB265CCD1B24BB55004BE740 /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.3.sdk/System/Library/Frameworks/Accelerate.framework; sourceTree = DEVELOPER_DIR; };
52 | CB26DAA01A856232007F73E2 /* NSArray+Matrix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = "NSArray+Matrix.h"; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
53 | CB26DAA11A856232007F73E2 /* NSArray+Matrix.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = "NSArray+Matrix.m"; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
54 | CB4388E91C2887BE00C6D330 /* halton_sampler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = halton_sampler.h; sourceTree = ""; };
55 | CB4BAA9919D2CE3D001E7A7A /* .gitignore */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitignore; sourceTree = ""; };
56 | CB4D3CA71C10F092009CAE8B /* soboldata.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = soboldata.h; sourceTree = ""; };
57 | CB58B99D19D1ED310097EEB1 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = text; path = README.md; sourceTree = ""; };
58 | CB723AFB1C47C37600600043 /* YCMatrixNSArrayTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YCMatrixNSArrayTests.m; sourceTree = ""; };
59 | CB84DE0319D4BD32009EED7E /* LICENSE */ = {isa = PBXFileReference; lastKnownFileType = text; lineEnding = 0; path = LICENSE; sourceTree = ""; xcLanguageSpecificationIdentifier = ""; };
60 | CB9F9CFC19DAE83E00B6A1E4 /* ycmatrix.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ycmatrix.png; sourceTree = ""; };
61 | CBBE02AC178F215000744F77 /* YCMatrix.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = YCMatrix.framework; sourceTree = BUILT_PRODUCTS_DIR; };
62 | CBBE02B4178F215000744F77 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
63 | CBBE02B7178F215000744F77 /* YCMatrix-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "YCMatrix-Info.plist"; sourceTree = ""; };
64 | CBBE02B9178F215000744F77 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; };
65 | CBBE02BC178F215000744F77 /* Matrix.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = Matrix.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
66 | CBBE02BD178F215000744F77 /* Matrix.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = Matrix.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
67 | CBBE02C4178F215100744F77 /* YCMatrixTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = YCMatrixTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
68 | CBBE02CD178F215100744F77 /* YCMatrixTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "YCMatrixTests-Info.plist"; sourceTree = ""; };
69 | CBBE02CF178F215100744F77 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; };
70 | CBBE02D2178F215100744F77 /* YCMatrixTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = YCMatrixTests.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
71 | CBBE02DC178F216800744F77 /* Matrix+Advanced.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = "Matrix+Advanced.h"; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
72 | CBBE02DD178F216800744F77 /* Matrix+Advanced.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = "Matrix+Advanced.m"; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
73 | CBBE02DE178F216800744F77 /* Matrix+Manipulate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = "Matrix+Manipulate.h"; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
74 | CBBE02DF178F216800744F77 /* Matrix+Manipulate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = "Matrix+Manipulate.m"; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
75 | CBBE02E7178F218600744F77 /* YCMatrixManipulateTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = YCMatrixManipulateTests.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
76 | CBCF36221C28383D009D89D7 /* HaltonInterface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HaltonInterface.h; sourceTree = ""; };
77 | CBCF36231C28383D009D89D7 /* HaltonInterface.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = HaltonInterface.mm; sourceTree = ""; };
78 | CBD5120519D2D720004DD8D3 /* .travis.yml */ = {isa = PBXFileReference; lastKnownFileType = text; path = .travis.yml; sourceTree = ""; };
79 | CBD5120619D37764004DD8D3 /* Constants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Constants.h; sourceTree = ""; };
80 | CBD7D3D018A4DD10006A04C0 /* Matrix+Map.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = "Matrix+Map.h"; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
81 | CBD7D3D118A4DD10006A04C0 /* Matrix+Map.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = "Matrix+Map.m"; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
82 | CBE66B991A6BB0A000E2EF2C /* YCMatrixMapTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = YCMatrixMapTests.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
83 | CBE9E7AC19D0D79600460953 /* YCMatrixAdvancedTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = YCMatrixAdvancedTests.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
84 | /* End PBXFileReference section */
85 |
86 | /* Begin PBXFrameworksBuildPhase section */
87 | CBBE02A8178F215000744F77 /* Frameworks */ = {
88 | isa = PBXFrameworksBuildPhase;
89 | buildActionMask = 2147483647;
90 | files = (
91 | );
92 | runOnlyForDeploymentPostprocessing = 0;
93 | };
94 | CBBE02C0178F215100744F77 /* Frameworks */ = {
95 | isa = PBXFrameworksBuildPhase;
96 | buildActionMask = 2147483647;
97 | files = (
98 | CBBE02CA178F215100744F77 /* YCMatrix.framework in Frameworks */,
99 | );
100 | runOnlyForDeploymentPostprocessing = 0;
101 | };
102 | /* End PBXFrameworksBuildPhase section */
103 |
104 | /* Begin PBXGroup section */
105 | CB26DA9F1A856219007F73E2 /* Categories */ = {
106 | isa = PBXGroup;
107 | children = (
108 | CB26DAA01A856232007F73E2 /* NSArray+Matrix.h */,
109 | CB26DAA11A856232007F73E2 /* NSArray+Matrix.m */,
110 | );
111 | name = Categories;
112 | sourceTree = "";
113 | };
114 | CBBE02A2178F215000744F77 = {
115 | isa = PBXGroup;
116 | children = (
117 | CBBE02B5178F215000744F77 /* YCMatrix */,
118 | CBBE02CB178F215100744F77 /* YCMatrixTests */,
119 | CBBE02AE178F215000744F77 /* Frameworks */,
120 | CBBE02AD178F215000744F77 /* Products */,
121 | CB58B99D19D1ED310097EEB1 /* README.md */,
122 | CB84DE0319D4BD32009EED7E /* LICENSE */,
123 | CB4BAA9919D2CE3D001E7A7A /* .gitignore */,
124 | CBD5120519D2D720004DD8D3 /* .travis.yml */,
125 | CB2242AF19D413C0005B3F7E /* AppledocSettings.plist */,
126 | CB9F9CFC19DAE83E00B6A1E4 /* ycmatrix.png */,
127 | );
128 | sourceTree = "";
129 | };
130 | CBBE02AD178F215000744F77 /* Products */ = {
131 | isa = PBXGroup;
132 | children = (
133 | CBBE02AC178F215000744F77 /* YCMatrix.framework */,
134 | CBBE02C4178F215100744F77 /* YCMatrixTests.xctest */,
135 | );
136 | name = Products;
137 | sourceTree = "";
138 | };
139 | CBBE02AE178F215000744F77 /* Frameworks */ = {
140 | isa = PBXGroup;
141 | children = (
142 | CB265CCD1B24BB55004BE740 /* Accelerate.framework */,
143 | CBBE02B4178F215000744F77 /* Foundation.framework */,
144 | );
145 | name = Frameworks;
146 | sourceTree = "";
147 | };
148 | CBBE02B5178F215000744F77 /* YCMatrix */ = {
149 | isa = PBXGroup;
150 | children = (
151 | CB02F7B41AAF446400EF1E02 /* YCMatrix.h */,
152 | CBBE02BC178F215000744F77 /* Matrix.h */,
153 | CBBE02BD178F215000744F77 /* Matrix.m */,
154 | CBBE02DC178F216800744F77 /* Matrix+Advanced.h */,
155 | CBBE02DD178F216800744F77 /* Matrix+Advanced.m */,
156 | CBBE02DE178F216800744F77 /* Matrix+Manipulate.h */,
157 | CBBE02DF178F216800744F77 /* Matrix+Manipulate.m */,
158 | CBD7D3D018A4DD10006A04C0 /* Matrix+Map.h */,
159 | CBD7D3D118A4DD10006A04C0 /* Matrix+Map.m */,
160 | CB26DA9F1A856219007F73E2 /* Categories */,
161 | CBBE02B6178F215000744F77 /* Supporting Files */,
162 | );
163 | path = YCMatrix;
164 | sourceTree = "";
165 | };
166 | CBBE02B6178F215000744F77 /* Supporting Files */ = {
167 | isa = PBXGroup;
168 | children = (
169 | CBCF36221C28383D009D89D7 /* HaltonInterface.h */,
170 | CBCF36231C28383D009D89D7 /* HaltonInterface.mm */,
171 | CB4388E91C2887BE00C6D330 /* halton_sampler.h */,
172 | CB4D3CA71C10F092009CAE8B /* soboldata.h */,
173 | CBBE02B7178F215000744F77 /* YCMatrix-Info.plist */,
174 | CBBE02B8178F215000744F77 /* InfoPlist.strings */,
175 | CBD5120619D37764004DD8D3 /* Constants.h */,
176 | );
177 | name = "Supporting Files";
178 | sourceTree = "";
179 | };
180 | CBBE02CB178F215100744F77 /* YCMatrixTests */ = {
181 | isa = PBXGroup;
182 | children = (
183 | CBBE02D2178F215100744F77 /* YCMatrixTests.m */,
184 | CBE9E7AC19D0D79600460953 /* YCMatrixAdvancedTests.m */,
185 | CBBE02E7178F218600744F77 /* YCMatrixManipulateTests.m */,
186 | CBE66B991A6BB0A000E2EF2C /* YCMatrixMapTests.m */,
187 | CB723AFB1C47C37600600043 /* YCMatrixNSArrayTests.m */,
188 | CB0B6D381C5A5B05002A76E2 /* YCMatrixPerformanceTests.m */,
189 | CBBE02CC178F215100744F77 /* Supporting Files */,
190 | );
191 | path = YCMatrixTests;
192 | sourceTree = "";
193 | };
194 | CBBE02CC178F215100744F77 /* Supporting Files */ = {
195 | isa = PBXGroup;
196 | children = (
197 | CBBE02CD178F215100744F77 /* YCMatrixTests-Info.plist */,
198 | CBBE02CE178F215100744F77 /* InfoPlist.strings */,
199 | );
200 | name = "Supporting Files";
201 | sourceTree = "";
202 | };
203 | /* End PBXGroup section */
204 |
205 | /* Begin PBXHeadersBuildPhase section */
206 | CBBE02A9178F215000744F77 /* Headers */ = {
207 | isa = PBXHeadersBuildPhase;
208 | buildActionMask = 2147483647;
209 | files = (
210 | CBD5120719D37764004DD8D3 /* Constants.h in Headers */,
211 | CBCF36241C28383D009D89D7 /* HaltonInterface.h in Headers */,
212 | CB02F7B51AAF446400EF1E02 /* YCMatrix.h in Headers */,
213 | CB4D3CA81C10F092009CAE8B /* soboldata.h in Headers */,
214 | CBBE02E0178F216800744F77 /* Matrix+Advanced.h in Headers */,
215 | CB4388EA1C2887BE00C6D330 /* halton_sampler.h in Headers */,
216 | CB26DAA21A856232007F73E2 /* NSArray+Matrix.h in Headers */,
217 | CBBE02E2178F216800744F77 /* Matrix+Manipulate.h in Headers */,
218 | CBBE0301178F258B00744F77 /* Matrix.h in Headers */,
219 | CBD7D3D218A4DD10006A04C0 /* Matrix+Map.h in Headers */,
220 | );
221 | runOnlyForDeploymentPostprocessing = 0;
222 | };
223 | /* End PBXHeadersBuildPhase section */
224 |
225 | /* Begin PBXNativeTarget section */
226 | CBBE02AB178F215000744F77 /* YCMatrix */ = {
227 | isa = PBXNativeTarget;
228 | buildConfigurationList = CBBE02D6178F215100744F77 /* Build configuration list for PBXNativeTarget "YCMatrix" */;
229 | buildPhases = (
230 | CBBE02A7178F215000744F77 /* Sources */,
231 | CBBE02A8178F215000744F77 /* Frameworks */,
232 | CBBE02A9178F215000744F77 /* Headers */,
233 | CBBE02AA178F215000744F77 /* Resources */,
234 | );
235 | buildRules = (
236 | );
237 | dependencies = (
238 | );
239 | name = YCMatrix;
240 | productName = YCMatrix;
241 | productReference = CBBE02AC178F215000744F77 /* YCMatrix.framework */;
242 | productType = "com.apple.product-type.framework";
243 | };
244 | CBBE02C3178F215100744F77 /* YCMatrixTests */ = {
245 | isa = PBXNativeTarget;
246 | buildConfigurationList = CBBE02D9178F215100744F77 /* Build configuration list for PBXNativeTarget "YCMatrixTests" */;
247 | buildPhases = (
248 | CBBE02BF178F215100744F77 /* Sources */,
249 | CBBE02C0178F215100744F77 /* Frameworks */,
250 | CBBE02C1178F215100744F77 /* Resources */,
251 | );
252 | buildRules = (
253 | );
254 | dependencies = (
255 | CBBE02C9178F215100744F77 /* PBXTargetDependency */,
256 | );
257 | name = YCMatrixTests;
258 | productName = YCMatrixTests;
259 | productReference = CBBE02C4178F215100744F77 /* YCMatrixTests.xctest */;
260 | productType = "com.apple.product-type.bundle.unit-test";
261 | };
262 | /* End PBXNativeTarget section */
263 |
264 | /* Begin PBXProject section */
265 | CBBE02A3178F215000744F77 /* Project object */ = {
266 | isa = PBXProject;
267 | attributes = {
268 | LastUpgradeCheck = 0800;
269 | ORGANIZATIONNAME = "Ioannis Chatzikonstantinou";
270 | };
271 | buildConfigurationList = CBBE02A6178F215000744F77 /* Build configuration list for PBXProject "YCMatrix" */;
272 | compatibilityVersion = "Xcode 3.2";
273 | developmentRegion = English;
274 | hasScannedForEncodings = 0;
275 | knownRegions = (
276 | en,
277 | );
278 | mainGroup = CBBE02A2178F215000744F77;
279 | productRefGroup = CBBE02AD178F215000744F77 /* Products */;
280 | projectDirPath = "";
281 | projectRoot = "";
282 | targets = (
283 | CBBE02AB178F215000744F77 /* YCMatrix */,
284 | CBBE02C3178F215100744F77 /* YCMatrixTests */,
285 | );
286 | };
287 | /* End PBXProject section */
288 |
289 | /* Begin PBXResourcesBuildPhase section */
290 | CBBE02AA178F215000744F77 /* Resources */ = {
291 | isa = PBXResourcesBuildPhase;
292 | buildActionMask = 2147483647;
293 | files = (
294 | CBBE02BA178F215000744F77 /* InfoPlist.strings in Resources */,
295 | );
296 | runOnlyForDeploymentPostprocessing = 0;
297 | };
298 | CBBE02C1178F215100744F77 /* Resources */ = {
299 | isa = PBXResourcesBuildPhase;
300 | buildActionMask = 2147483647;
301 | files = (
302 | CBBE02D0178F215100744F77 /* InfoPlist.strings in Resources */,
303 | );
304 | runOnlyForDeploymentPostprocessing = 0;
305 | };
306 | /* End PBXResourcesBuildPhase section */
307 |
308 | /* Begin PBXSourcesBuildPhase section */
309 | CBBE02A7178F215000744F77 /* Sources */ = {
310 | isa = PBXSourcesBuildPhase;
311 | buildActionMask = 2147483647;
312 | files = (
313 | CB26DAA31A856232007F73E2 /* NSArray+Matrix.m in Sources */,
314 | CBD7D3D318A4DD10006A04C0 /* Matrix+Map.m in Sources */,
315 | CBBE02BE178F215000744F77 /* Matrix.m in Sources */,
316 | CBCF36251C28383D009D89D7 /* HaltonInterface.mm in Sources */,
317 | CBBE02E1178F216800744F77 /* Matrix+Advanced.m in Sources */,
318 | CBBE02E3178F216800744F77 /* Matrix+Manipulate.m in Sources */,
319 | );
320 | runOnlyForDeploymentPostprocessing = 0;
321 | };
322 | CBBE02BF178F215100744F77 /* Sources */ = {
323 | isa = PBXSourcesBuildPhase;
324 | buildActionMask = 2147483647;
325 | files = (
326 | CBE9E7AD19D0D79600460953 /* YCMatrixAdvancedTests.m in Sources */,
327 | CB0B6D391C5A5B05002A76E2 /* YCMatrixPerformanceTests.m in Sources */,
328 | CB723AFC1C47C37600600043 /* YCMatrixNSArrayTests.m in Sources */,
329 | CBBE02D3178F215100744F77 /* YCMatrixTests.m in Sources */,
330 | CBBE02E9178F218600744F77 /* YCMatrixManipulateTests.m in Sources */,
331 | CBE66B9A1A6BB0A000E2EF2C /* YCMatrixMapTests.m in Sources */,
332 | );
333 | runOnlyForDeploymentPostprocessing = 0;
334 | };
335 | /* End PBXSourcesBuildPhase section */
336 |
337 | /* Begin PBXTargetDependency section */
338 | CBBE02C9178F215100744F77 /* PBXTargetDependency */ = {
339 | isa = PBXTargetDependency;
340 | target = CBBE02AB178F215000744F77 /* YCMatrix */;
341 | targetProxy = CBBE02C8178F215100744F77 /* PBXContainerItemProxy */;
342 | };
343 | /* End PBXTargetDependency section */
344 |
345 | /* Begin PBXVariantGroup section */
346 | CBBE02B8178F215000744F77 /* InfoPlist.strings */ = {
347 | isa = PBXVariantGroup;
348 | children = (
349 | CBBE02B9178F215000744F77 /* en */,
350 | );
351 | name = InfoPlist.strings;
352 | sourceTree = "";
353 | };
354 | CBBE02CE178F215100744F77 /* InfoPlist.strings */ = {
355 | isa = PBXVariantGroup;
356 | children = (
357 | CBBE02CF178F215100744F77 /* en */,
358 | );
359 | name = InfoPlist.strings;
360 | sourceTree = "";
361 | };
362 | /* End PBXVariantGroup section */
363 |
364 | /* Begin XCBuildConfiguration section */
365 | CBBE02D4178F215100744F77 /* Debug */ = {
366 | isa = XCBuildConfiguration;
367 | buildSettings = {
368 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO;
369 | ALWAYS_SEARCH_USER_PATHS = NO;
370 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
371 | CLANG_CXX_LIBRARY = "libc++";
372 | CLANG_ENABLE_OBJC_ARC = YES;
373 | CLANG_WARN_BOOL_CONVERSION = YES;
374 | CLANG_WARN_CONSTANT_CONVERSION = YES;
375 | CLANG_WARN_EMPTY_BODY = YES;
376 | CLANG_WARN_ENUM_CONVERSION = YES;
377 | CLANG_WARN_INFINITE_RECURSION = YES;
378 | CLANG_WARN_INT_CONVERSION = YES;
379 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
380 | CLANG_WARN_UNREACHABLE_CODE = YES;
381 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
382 | COPY_PHASE_STRIP = NO;
383 | ENABLE_STRICT_OBJC_MSGSEND = YES;
384 | ENABLE_TESTABILITY = YES;
385 | GCC_C_LANGUAGE_STANDARD = gnu99;
386 | GCC_DYNAMIC_NO_PIC = NO;
387 | GCC_ENABLE_OBJC_EXCEPTIONS = YES;
388 | GCC_NO_COMMON_BLOCKS = YES;
389 | GCC_OPTIMIZATION_LEVEL = 0;
390 | GCC_PREPROCESSOR_DEFINITIONS = (
391 | "DEBUG=1",
392 | "$(inherited)",
393 | );
394 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
395 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
396 | GCC_WARN_ABOUT_RETURN_TYPE = YES;
397 | GCC_WARN_UNDECLARED_SELECTOR = YES;
398 | GCC_WARN_UNINITIALIZED_AUTOS = YES;
399 | GCC_WARN_UNUSED_FUNCTION = YES;
400 | GCC_WARN_UNUSED_VARIABLE = YES;
401 | MACOSX_DEPLOYMENT_TARGET = 10.7;
402 | ONLY_ACTIVE_ARCH = YES;
403 | SDKROOT = macosx;
404 | SUPPORTED_PLATFORMS = "macosx iphonesimulator iphoneos";
405 | VALID_ARCHS = "arm64 armv7 armv7s i386 x86_64";
406 | };
407 | name = Debug;
408 | };
409 | CBBE02D5178F215100744F77 /* Release */ = {
410 | isa = XCBuildConfiguration;
411 | buildSettings = {
412 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO;
413 | ALWAYS_SEARCH_USER_PATHS = NO;
414 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
415 | CLANG_CXX_LIBRARY = "libc++";
416 | CLANG_ENABLE_OBJC_ARC = YES;
417 | CLANG_WARN_BOOL_CONVERSION = YES;
418 | CLANG_WARN_CONSTANT_CONVERSION = YES;
419 | CLANG_WARN_EMPTY_BODY = YES;
420 | CLANG_WARN_ENUM_CONVERSION = YES;
421 | CLANG_WARN_INFINITE_RECURSION = YES;
422 | CLANG_WARN_INT_CONVERSION = YES;
423 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
424 | CLANG_WARN_UNREACHABLE_CODE = YES;
425 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
426 | COPY_PHASE_STRIP = YES;
427 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
428 | ENABLE_STRICT_OBJC_MSGSEND = YES;
429 | GCC_C_LANGUAGE_STANDARD = gnu99;
430 | GCC_ENABLE_OBJC_EXCEPTIONS = YES;
431 | GCC_NO_COMMON_BLOCKS = YES;
432 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
433 | GCC_WARN_ABOUT_RETURN_TYPE = YES;
434 | GCC_WARN_UNDECLARED_SELECTOR = YES;
435 | GCC_WARN_UNINITIALIZED_AUTOS = YES;
436 | GCC_WARN_UNUSED_FUNCTION = YES;
437 | GCC_WARN_UNUSED_VARIABLE = YES;
438 | MACOSX_DEPLOYMENT_TARGET = 10.7;
439 | SDKROOT = macosx;
440 | SUPPORTED_PLATFORMS = "macosx iphonesimulator iphoneos";
441 | VALID_ARCHS = "arm64 armv7 armv7s i386 x86_64";
442 | };
443 | name = Release;
444 | };
445 | CBBE02D7178F215100744F77 /* Debug */ = {
446 | isa = XCBuildConfiguration;
447 | buildSettings = {
448 | CLANG_ENABLE_MODULES = YES;
449 | COMBINE_HIDPI_IMAGES = YES;
450 | DEFINES_MODULE = YES;
451 | DYLIB_COMPATIBILITY_VERSION = 1;
452 | DYLIB_CURRENT_VERSION = 1;
453 | FRAMEWORK_SEARCH_PATHS = "";
454 | FRAMEWORK_VERSION = A;
455 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
456 | INFOPLIST_FILE = "YCMatrix/YCMatrix-Info.plist";
457 | INSTALL_PATH = "@rpath";
458 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
459 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
460 | PRODUCT_BUNDLE_IDENTIFIER = "yconst.$(PRODUCT_NAME:rfc1034identifier)";
461 | PRODUCT_NAME = "$(TARGET_NAME)";
462 | SKIP_INSTALL = YES;
463 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
464 | VALID_ARCHS = "arm64 armv7 armv7s i386 x86_64";
465 | WATCHOS_DEPLOYMENT_TARGET = 2.0;
466 | WRAPPER_EXTENSION = framework;
467 | };
468 | name = Debug;
469 | };
470 | CBBE02D8178F215100744F77 /* Release */ = {
471 | isa = XCBuildConfiguration;
472 | buildSettings = {
473 | CLANG_ENABLE_MODULES = YES;
474 | COMBINE_HIDPI_IMAGES = YES;
475 | DEFINES_MODULE = YES;
476 | DYLIB_COMPATIBILITY_VERSION = 1;
477 | DYLIB_CURRENT_VERSION = 1;
478 | FRAMEWORK_SEARCH_PATHS = "";
479 | FRAMEWORK_VERSION = A;
480 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
481 | INFOPLIST_FILE = "YCMatrix/YCMatrix-Info.plist";
482 | INSTALL_PATH = "@rpath";
483 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
484 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
485 | PRODUCT_BUNDLE_IDENTIFIER = "yconst.$(PRODUCT_NAME:rfc1034identifier)";
486 | PRODUCT_NAME = "$(TARGET_NAME)";
487 | SKIP_INSTALL = YES;
488 | VALID_ARCHS = "arm64 armv7 armv7s i386 x86_64";
489 | WATCHOS_DEPLOYMENT_TARGET = 2.0;
490 | WRAPPER_EXTENSION = framework;
491 | };
492 | name = Release;
493 | };
494 | CBBE02DA178F215100744F77 /* Debug */ = {
495 | isa = XCBuildConfiguration;
496 | buildSettings = {
497 | CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = NO;
498 | CLANG_ENABLE_MODULES = YES;
499 | CODE_SIGN_IDENTITY = "";
500 | COMBINE_HIDPI_IMAGES = YES;
501 | FRAMEWORK_SEARCH_PATHS = (
502 | "$(SDKROOT)",
503 | "$(inherited)",
504 | "$(DEVELOPER_FRAMEWORKS_DIR)",
505 | );
506 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
507 | INFOPLIST_FILE = "YCMatrixTests/YCMatrixTests-Info.plist";
508 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks @executable_path/../Frameworks @loader_path/../Frameworks";
509 | PRODUCT_BUNDLE_IDENTIFIER = "yconst.${PRODUCT_NAME:rfc1034identifier}";
510 | PRODUCT_NAME = "$(TARGET_NAME)";
511 | };
512 | name = Debug;
513 | };
514 | CBBE02DB178F215100744F77 /* Release */ = {
515 | isa = XCBuildConfiguration;
516 | buildSettings = {
517 | CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = NO;
518 | CLANG_ENABLE_MODULES = YES;
519 | CODE_SIGN_IDENTITY = "";
520 | COMBINE_HIDPI_IMAGES = YES;
521 | FRAMEWORK_SEARCH_PATHS = (
522 | "$(SDKROOT)",
523 | "$(inherited)",
524 | "$(DEVELOPER_FRAMEWORKS_DIR)",
525 | );
526 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
527 | INFOPLIST_FILE = "YCMatrixTests/YCMatrixTests-Info.plist";
528 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks @executable_path/../Frameworks @loader_path/../Frameworks";
529 | PRODUCT_BUNDLE_IDENTIFIER = "yconst.${PRODUCT_NAME:rfc1034identifier}";
530 | PRODUCT_NAME = "$(TARGET_NAME)";
531 | };
532 | name = Release;
533 | };
534 | /* End XCBuildConfiguration section */
535 |
536 | /* Begin XCConfigurationList section */
537 | CBBE02A6178F215000744F77 /* Build configuration list for PBXProject "YCMatrix" */ = {
538 | isa = XCConfigurationList;
539 | buildConfigurations = (
540 | CBBE02D4178F215100744F77 /* Debug */,
541 | CBBE02D5178F215100744F77 /* Release */,
542 | );
543 | defaultConfigurationIsVisible = 0;
544 | defaultConfigurationName = Release;
545 | };
546 | CBBE02D6178F215100744F77 /* Build configuration list for PBXNativeTarget "YCMatrix" */ = {
547 | isa = XCConfigurationList;
548 | buildConfigurations = (
549 | CBBE02D7178F215100744F77 /* Debug */,
550 | CBBE02D8178F215100744F77 /* Release */,
551 | );
552 | defaultConfigurationIsVisible = 0;
553 | defaultConfigurationName = Release;
554 | };
555 | CBBE02D9178F215100744F77 /* Build configuration list for PBXNativeTarget "YCMatrixTests" */ = {
556 | isa = XCConfigurationList;
557 | buildConfigurations = (
558 | CBBE02DA178F215100744F77 /* Debug */,
559 | CBBE02DB178F215100744F77 /* Release */,
560 | );
561 | defaultConfigurationIsVisible = 0;
562 | defaultConfigurationName = Release;
563 | };
564 | /* End XCConfigurationList section */
565 | };
566 | rootObject = CBBE02A3178F215000744F77 /* Project object */;
567 | }
568 |
--------------------------------------------------------------------------------
/YCMatrix.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/YCMatrix.xcodeproj/project.xcworkspace/xcuserdata/yanconst.xcuserdatad/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges
6 |
7 | SnapshotAutomaticallyBeforeSignificantChanges
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/YCMatrix.xcodeproj/xcshareddata/xcschemes/YCMatrix.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
43 |
44 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
63 |
64 |
70 |
71 |
72 |
73 |
74 |
75 |
81 |
82 |
84 |
85 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/YCMatrix.xcodeproj/xcuserdata/oo.xcuserdatad/xcschemes/YCMatrix.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
42 |
43 |
52 |
53 |
54 |
55 |
61 |
62 |
64 |
65 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/YCMatrix.xcodeproj/xcuserdata/oo.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | YCMatrix.xcscheme
8 |
9 | orderHint
10 | 4
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | CBBE02AB178F215000744F77
16 |
17 | primary
18 |
19 |
20 | CBBE02C3178F215100744F77
21 |
22 | primary
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/YCMatrix.xcodeproj/xcuserdata/yanconst.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
8 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/YCMatrix.xcodeproj/xcuserdata/yanconst.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | YCMatrix.xcscheme_^#shared#^_
8 |
9 | orderHint
10 | 0
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | CB265CB31B24BB30004BE740
16 |
17 | primary
18 |
19 |
20 | CB265CBD1B24BB30004BE740
21 |
22 | primary
23 |
24 |
25 | CB265CE01B24BD24004BE740
26 |
27 | primary
28 |
29 |
30 | CB265CEA1B24BD24004BE740
31 |
32 | primary
33 |
34 |
35 | CB265D0E1B24C309004BE740
36 |
37 | primary
38 |
39 |
40 | CB265D281B24C478004BE740
41 |
42 | primary
43 |
44 |
45 | CBBE02AB178F215000744F77
46 |
47 | primary
48 |
49 |
50 | CBBE02C3178F215100744F77
51 |
52 | primary
53 |
54 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/YCMatrix/Constants.h:
--------------------------------------------------------------------------------
1 | //
2 | // Constants.h
3 | // YCMatrix
4 | //
5 | // Created by Ioannis Chatzikonstantinou on 25/9/14.
6 | // Copyright (c) 2014 Ioannis Chatzikonstantinou. All rights reserved.
7 | //
8 |
9 | #ifndef YCMatrix_Constants_h
10 | #define YCMatrix_Constants_h
11 |
12 | #define ARC4RANDOM_MAX 0x100000000
13 |
14 | #endif
15 |
--------------------------------------------------------------------------------
/YCMatrix/HaltonInterface.h:
--------------------------------------------------------------------------------
1 | //
2 | // HaltonInterface.h
3 | // YCMatrix
4 | //
5 | // Created by Ioannis Chatzikonstantinou on 21/12/15.
6 | // Copyright © 2015 Ioannis Chatzikonstantinou. All rights reserved.
7 | //
8 |
9 | #import
10 | @class Matrix;
11 |
12 | @interface HaltonInterface : NSObject
13 |
14 | + (Matrix *)sampleWithDimension:(int)dimension count:(int)count;
15 |
16 | @end
17 |
--------------------------------------------------------------------------------
/YCMatrix/HaltonInterface.mm:
--------------------------------------------------------------------------------
1 | //
2 | // HaltonInterface.m
3 | // YCMatrix
4 | //
5 | // Created by Ioannis Chatzikonstantinou on 21/12/15.
6 | // Copyright © 2015 Ioannis Chatzikonstantinou. All rights reserved.
7 | //
8 |
9 | #import "HaltonInterface.h"
10 | #import "Matrix.h"
11 | #import "halton_sampler.h"
12 |
13 | @implementation HaltonInterface
14 |
15 | + (Matrix *)sampleWithDimension:(int)dimension count:(int)count
16 | {
17 | Halton_sampler halton_sampler;
18 | halton_sampler.init_faure();
19 |
20 | Matrix *result = [Matrix matrixOfRows:dimension columns:count];
21 |
22 | for (unsigned i = 0; i < dimension; ++i) // Iterate over rows.
23 | {
24 | for (unsigned j = 0; j < count; ++j) // Iterate over columns.
25 | {
26 | [result i:i j:j set:halton_sampler.sample(i, j)];
27 | }
28 | }
29 | return result;
30 | }
31 |
32 | @end
33 |
--------------------------------------------------------------------------------
/YCMatrix/Matrix+Advanced.h:
--------------------------------------------------------------------------------
1 | //
2 | // Matrix+Advanced.h
3 | //
4 | // YCMatrix
5 | //
6 | // Copyright (c) 2013 - 2016 Ioannis (Yannis) Chatzikonstantinou. All rights reserved.
7 | // http://yconst.com
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | #import
28 | #import "Matrix.h"
29 | #import "Matrix+Manipulate.h"
30 | #import "Matrix+Map.h"
31 | #import
32 |
33 | /**
34 | Advanced is a category to the Matrix class, that exposes some
35 | more complex behavior.
36 | */
37 | @interface Matrix (Advanced)
38 |
39 | /**
40 | Returns a matrix containing random values uniformly distributed between |lower| and |upper|.
41 | The parameter matrices should have the same dimensions, and the resulting
42 | matrix will also be of the same dimensions as the parameters.
43 |
44 | @param lower Matrix containing values for the lower bounds.
45 | @param upper Matrix containing values for the upper bounds.
46 |
47 | @return A matrix of random values between lower and upper, and of the same size.
48 | */
49 | + (instancetype)uniformRandomLowerBound:(Matrix *)lower upperBound:(Matrix *)upper;
50 |
51 | /**
52 | Returns a matrix of random values uniformly distributed within the specified domain.
53 |
54 | @param rows The number of rows of the matrix.
55 | @param columns The number of columns of the matrix.
56 | @param domain The domain to generate uniform random number within.
57 |
58 | @return A matrix of random values.
59 | */
60 | + (instancetype)uniformRandomRows:(int)rows columns:(int)columns domain:(YCDomain)domain;
61 |
62 | /**
63 | Returns a matrix containing random values uniformly distributed between |lower| and |upper|.
64 | The lower and upper matrices should be either row or column matrices. The method will
65 | generate |count| random row or column matrices, and return them in a single matrix.
66 | As an example, if the sizes of |lower| and |upper| are mx1 and the value of the count parameter
67 | is n, the return matrix will be mxn. Conversely, if |lower| and |upper| are 1xm and count is
68 | n, the return matrix will be nxm.
69 |
70 | @param lower The matrix containing the lower bounds for the uniform random numbers.
71 | @param upper The matrix containing the upper bounds for the uniform random numbers.
72 | @param count The number of examples to generate.
73 |
74 | @return The matrix containing the uniform random numbers.
75 |
76 | @warning The lower and upper matrices should be either row or column matrices.
77 | */
78 | + (instancetype)uniformRandomLowerBound:(Matrix *)lower
79 | upperBound:(Matrix *)upper
80 | count:(int)count;
81 |
82 | /**
83 | Returns a matrix containing random values normally distributed
84 | with specified mean and variance. The parameter matrices should have
85 | the same dimensions, and the resulting matrix will also be of the same
86 | dimensions as the parameters.
87 |
88 | @param mean Matrix containing values for the means.
89 | @param variance Matrix containing values for the variances.
90 |
91 | @return A matrix of random values between lower and upper, and of the same size.
92 | */
93 | + (instancetype)normalRandomMean:(Matrix *)mean variance:(Matrix *)variance;
94 |
95 | /**
96 | Returns a matrix of random values uniformly distributed with specified mean and variance.
97 |
98 | @param rows The number of rows of the matrix.
99 | @param columns The number of columns of the matrix.
100 | @param mean The mean of the normal distribution.
101 | @param variance The variance of the normal distribution.
102 |
103 | @return A matrix of random values.
104 | */
105 | + (instancetype)normalRandomRows:(int)rows
106 | columns:(int)columns
107 | mean:(double)mean
108 | variance:(double)variance;
109 |
110 | /**
111 | Returns a matrix containing random values normally distributed with specified mean and variance.
112 | The mean and variance matrices should be either row or column matrices. The method will
113 | generate |count| random row or column matrices, and return them in a single matrix.
114 | As an example, if the sizes of |mean| and |variance| are mx1 and the value of the count parameter
115 | is n, the return matrix will be mxn. Conversely, if |mean| and |variance| are 1xm and count is
116 | n, the return matrix will be nxm.
117 |
118 | @param mean The matrix containing the means of the normally distributed random numbers.
119 | @param variance The matrix containing the variances of the normally distributed random numbers.
120 | @param count The number of examples to generate.
121 |
122 | @return The matrix containing the normally distributed random numbers.
123 |
124 | @warning The mean and variance matrices should be either row or column matrices.
125 | */
126 | + (instancetype)normalRandomMean:(Matrix *)mean
127 | variance:(Matrix *)variance
128 | count:(int)count;
129 |
130 | /**
131 | Returns a matrix of quasi-random values according to the Sobol sequence.
132 | The parameter matrices should have the same dimensions, and the resulting
133 | matrix will also be of the same dimensions as the parameters.
134 |
135 | @param lower Matrix containing values for the lower bounds.
136 | @param upper Matrix containing values for the upper bounds.
137 | @param count The number of points to sample.
138 |
139 | @return A matrix of the values corresponding to the Sobol sequence.
140 | */
141 | + (instancetype)sobolSequenceLowerBound:(Matrix *)lower
142 | upperBound:(Matrix *)upper
143 | count:(int)count;
144 |
145 | /**
146 | Returns a matrix of quasi-random values according to the Halton sequence.
147 | The parameter matrices should have the same dimensions, and the resulting
148 | matrix will also be of the same dimensions as the parameters.
149 |
150 | @param lower Matrix containing values for the lower bounds.
151 | @param upper Matrix containing values for the upper bounds.
152 | @param count The number of points to sample.
153 |
154 | @return A matrix of the values corresponding to the Halton sequence.
155 | */
156 | + (instancetype)haltonSequenceWithLowerBound:(Matrix *)lower
157 | upperBound:(Matrix *)upper
158 | count:(int)count;
159 |
160 | /**
161 | Returns the pseudo-inverse of the receiver.
162 | The calculation is performed using Singular Value Decomposition.
163 |
164 | @return The pseudo-inverse of the receiver.
165 | */
166 | - (Matrix *)pseudoInverse;
167 |
168 | /**
169 | Performs Singular Value Decomposition on the receiver.
170 |
171 | @return An NSDictionary containing the "U", "S", "V" components of the SVD of the receiver.
172 |
173 | @warning As a matter of efficiency, and because the corresponding LAPACK function requires
174 | column-major matrices, the output dictionary will contain the "V" matrix, and not
175 | it's transpose.
176 | */
177 | - (NSDictionary *)SVD;
178 |
179 | /**
180 | Returns the X vector that is the solution to the linear system A * X = B, with the receiver being A.
181 |
182 | @param B The matrix B.
183 |
184 | @return The solution vector X.
185 | */
186 | - (Matrix *)solve:(Matrix *)B;
187 |
188 | /**
189 | Performs an in-place Cholesky decomposition on the receiver.
190 | Makes lower triangular R such that R * R' = self. Modifies self.
191 | */
192 | - (void)cholesky;
193 |
194 | /**
195 | Returns a new matrix by performing Cholesky decomposition on the receiver.
196 | Makes lower triangular R such that R * R' = self.
197 |
198 | @return The matrix resulting from the Cholesky decomposition of the receiver.
199 | */
200 | - (Matrix *)matrixByCholesky;
201 |
202 | /**
203 | Returns a row matrix containing the real Eigenvalues of the receiver.
204 |
205 | @return The resulting row matrix.
206 | */
207 | - (Matrix *)realEigenvalues;
208 |
209 | /**
210 | Returns an NSDictionary with the results of performing an Eigenvalue decomposition on the receiver.
211 |
212 | @return A dictionary with the following key/value assignments:
213 | "Real Eigenvalues" : nx1 vector containing the matrix real eigenvalues.
214 | "Imaginary Eigenvalues" : nx1 vector containing the matrix imaginary eigenvalues.
215 | "Left Eigenvectors" : nxn matrix containing the matrix left eigenvectors, one per row.
216 | "Right Eigenvectors" : nxn matrix containing the matrix right eigenvectors, one per row.
217 |
218 | @warning The eigenvectors appear per ROW in the result. If you wish to obtain per column
219 | results, yuo need to transpose the resulting eigenvector matrix.
220 | */
221 | - (NSDictionary *)eigenvectorsAndEigenvalues;
222 |
223 | /**
224 | Returns the determinant of the receiver.
225 |
226 | @return A double value corresponsing to the determinant of the receiver.
227 |
228 | @warning This method has not been extensively tested and may contain serious flaws.
229 | */
230 | - (double)determinant;
231 |
232 | /**
233 | Returns a column matrix containing the sums of the rows of the receiver.
234 |
235 | @return The column matrix containing the sums of rows.
236 | */
237 | - (Matrix *)sumsOfRows;
238 |
239 | /**
240 | Returns a row matrix containing the sums of the columns of the receiver.
241 |
242 | @return The row matrix containing the sums of columns.
243 | */
244 | - (Matrix *)sumsOfColumns;
245 |
246 | /**
247 | Returns a column matrix containing the means of the rows of the receiver.
248 |
249 | @return The column matrix containing the means of rows.
250 | */
251 | - (Matrix *)meansOfRows;
252 |
253 | /**
254 | Returns a row matrix containing the means of the columns of the receiver.
255 |
256 | @return The row matrix containing the means of columns.
257 | */
258 | - (Matrix *)meansOfColumns;
259 |
260 | /**
261 | Returns a column matrix containing the population variances of the rows of the receiver.
262 |
263 | @return The column matrix containing the variances of rows.
264 |
265 | @warning This calculates the population variance.
266 | */
267 | - (Matrix *)variancesOfRows;
268 |
269 | /**
270 | Returns a row matrix containing the population variances of the columns of the receiver.
271 |
272 | @return The row matrix containing the variances of columns.
273 |
274 | @warning This calculates the population variance.
275 | */
276 | - (Matrix *)variancesOfColumns;
277 |
278 | /**
279 | Returns a column matrix containing the sample variances of the rows of the receiver.
280 |
281 | @return The column matrix containing the variances of rows.
282 |
283 | @warning This calculates the sample variance.
284 | */
285 | - (Matrix *)sampleVariancesOfRows;
286 |
287 | /**
288 | Returns a row matrix containing the sample variances of the columns of the receiver.
289 |
290 | @return The row matrix containing the variances of columns.
291 |
292 | @warning This calculates the sample variance.
293 | */
294 | - (Matrix *)sampleVariancesOfColumns;
295 |
296 | /**
297 | Returns a column matrix containing the minimum values of each row of the receiver.
298 |
299 | @return The column matrix containing the minimum values of each row.
300 | */
301 | - (Matrix *)minimumsOfRows;
302 |
303 | /**
304 | Returns a column matrix containing the maximum values of each row of the receiver.
305 |
306 | @return The column matrix containing the maximum values of each row.
307 | */
308 | - (Matrix *)maximumsOfRows;
309 |
310 | /**
311 | Returns a row matrix containing the minimum values of each column of the receiver.
312 |
313 | @return The row matrix containing the minimum values of each column.
314 | */
315 | - (Matrix *)minimumsOfColumns;
316 |
317 | /**
318 | Returns a row matrix containing the maximum values of each column of the receiver.
319 |
320 | @return The row matrix containing the maximum values of each column.
321 | */
322 | - (Matrix *)maximumsOfColumns;
323 |
324 | /**
325 | Returns a new matrix with each cell being the result of applying a function to
326 | the corresponding cell of the receiver.
327 |
328 | @param function The function to apply.
329 |
330 | @return The matrix of transformed values.
331 | */
332 | - (Matrix *)matrixByApplyingFunction:(double (^)(double value))function;
333 |
334 | /**
335 | Applies a function to each cell of the receiver.
336 |
337 | @param function The function to apply.
338 | */
339 | - (void)applyFunction:(double (^)(double value))function;
340 |
341 | /**
342 | Returns the multidimensional Euclidean distance of the receiver to another matrix.
343 |
344 | @param other The matrix to claculate the distance to.
345 |
346 | @return The calculated distance.
347 |
348 | @warning This method will accept any kind of matrix as parameter, as long as the
349 | dimensions are equal.
350 |
351 | */
352 | - (double)euclideanDistanceTo:(Matrix *)other;
353 |
354 | /**
355 | Returns the multidimensional Quadrance (square of Euclidean distance of the receiver to another matrix.
356 |
357 | @param other The matrix to claculate the quadrance to.
358 |
359 | @return The calculated quadrance.
360 |
361 | @warning This method will accept any kind of matrix as parameter, as long as the
362 | dimensions are equal.
363 |
364 | */
365 | - (double)quadranceTo:(Matrix *)other;
366 |
367 | /**
368 | Replaces values of the receiver with zeroes or ones, depending on the probability expressed by
369 | the existing values in the receiver.
370 | */
371 | - (void)bernoulli;
372 |
373 | @end
374 |
--------------------------------------------------------------------------------
/YCMatrix/Matrix+Manipulate.h:
--------------------------------------------------------------------------------
1 | //
2 | // Matrix+Manipulate.h
3 | //
4 | // YCMatrix
5 | //
6 | // Copyright (c) 2013 - 2016 Ioannis (Yannis) Chatzikonstantinou. All rights reserved.
7 | // http://yconst.com
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | #import
28 | #import "Matrix.h"
29 |
30 | /**
31 | Manipulate is a category to the Matrix class that extends it
32 | by exposing functionality related to manipulating rows and columns,
33 | splitting and joining, sampling, shuffling, and a few others.
34 | */
35 | @interface Matrix (Manipulate)
36 |
37 | /**
38 | Initializes and returns a new matrix from an NSArray of row matrices.
39 |
40 | @param rows The NSArray containing row matrix objects.
41 |
42 | @return A new matrix resulting from merging the rows.
43 | */
44 | + (Matrix *)matrixFromRows:(NSArray *)rows;
45 |
46 | /**
47 | Initializes and returns a new matrix from an NSArray of column matrices.
48 |
49 | @param rows The NSArray containing column matrix objects.
50 |
51 | @return A new matrix resulting from merging the column.
52 | */
53 | + (Matrix *)matrixFromColumns:(NSArray *)columns;
54 |
55 | /**
56 | Copy all the values of the matrix passed as the argument, to the receiver.
57 |
58 | @param matrix The matrix to copy the values from.
59 | */
60 | - (void)copyValuesFrom:(Matrix *)aMatrix;
61 |
62 | /**
63 | Returns a row matrix with the contents of row |rowNumber|.
64 |
65 | @param rowNumber The index of the row to copy.
66 |
67 | @return The row matrix.
68 | */
69 | - (Matrix *)row:(int)rowIndex;
70 |
71 | /**
72 | Returns a row matrix by referencing the contents of row |rowNumber|.
73 |
74 | @param rowIndex The index of the row to copy
75 |
76 | @return The row referencing matrix.
77 |
78 | @warning The returned matrix does not retain it's data.
79 | */
80 | - (Matrix *)rowReference:(int)rowIndex;
81 |
82 | /**
83 | Returns a column (vector) matrix by referencing the contents of row |rowNumber|.
84 |
85 | @param rowIndex The index of the row to copy
86 |
87 | @return The referencing vector.
88 |
89 | @warning The returned matrix does not retain it's data.
90 | */
91 | - (Matrix *)rowReferenceVector:(int)rowIndex;
92 |
93 | /**
94 | Returns a new matrix with the contents of the rows at the specified indexes.
95 |
96 | @param indexes The indexes of the rows.
97 |
98 | @return The matrix containing the specified rows.
99 | */
100 | - (Matrix *)rows:(NSIndexSet *)indexes;
101 |
102 | /**
103 | Replaces the values of row |rowIndex| with those of row matrix |rowValue|
104 |
105 | @param rowIndex The index of the row to replace.
106 | @param rowValue The values to replace with.
107 | */
108 | - (void)setRow:(int)rowIndex value:(Matrix *)rowValue;
109 |
110 | /**
111 | Returns an NSArray of row matrices, each representing one row of the receiver.
112 |
113 | @return The NSArray of row matrices.
114 | */
115 | - (NSArray *)rowsAsNSArray;
116 |
117 | /**
118 | Row-wise splits the receiver at the specified indexes.
119 |
120 | @param indexes The splitting indexes.
121 |
122 | @return An NSArray containing the split segments.
123 | */
124 | - (NSArray *)rowWiseSplitAtIndexes:(NSIndexSet *)indexes;
125 |
126 | /**
127 | Partitions the receiver into row chunks of size s.
128 |
129 | @param s The size of each row chunk.
130 |
131 | @return The NSArray of matrices resulting from the partitioning.
132 | */
133 | - (NSArray *)rowWisePartition:(int)size;
134 |
135 | /**
136 | Returns the values of column |colIndex| as a column matrix.
137 |
138 | @param colIndex The index of the column
139 |
140 | @return The column matrix with the values of the column |colIndex|.
141 | */
142 | - (Matrix *)column:(int)colIndex;
143 |
144 | /**
145 | Returns a new matrix with the contents of the columns at the specified indexes.
146 |
147 | @param indexes The indexes of the columns.
148 |
149 | @return The matrix containing the specified columns.
150 | */
151 | - (Matrix *)columns:(NSIndexSet *)indexes;
152 |
153 | /**
154 | Replaces values of column |colIndex| with those of column matrix |columnValue|
155 |
156 | @param colNumber The index of the column to replace.
157 | @param columnValue The values to replace with.
158 | */
159 | - (void)setColumn:(int)colNumber value:(Matrix *)columnValue;
160 |
161 | /**
162 | Creates column matrices from the columns of the matrix and returns them as an NSArray.
163 |
164 | @return The NSArray containing the columns of the receiver.
165 | */
166 | - (NSArray *)columnsAsNSArray;
167 |
168 | /**
169 | Column-wise splits the receiver at the specified indexes.
170 |
171 | @param indexes The splitting indexes.
172 |
173 | @return An NSArray containing the split segments.
174 | */
175 | - (NSArray *)columnWiseSplitAtIndexes:(NSIndexSet *)indexes;
176 |
177 | /**
178 | Partitions the receiver into column chunks of size s.
179 |
180 | @param s The size of each column chunk.
181 |
182 | @return The NSArray of matrices resulting from the partitioning.
183 | */
184 | - (NSArray *)columnWisePartition:(int)size;
185 |
186 | /**
187 | Returns a matrix resulting from adding the values in the
188 | row matrix |row| to every row.
189 |
190 | @param row The row matrix whose values to add.
191 |
192 | @return The matrix after the addition.
193 | */
194 | - (Matrix *)matrixByAddingRow:(Matrix *)row;
195 |
196 | /**
197 | Returns a matrix resulting from subtracting the values in
198 | row matrix |row| from every row.
199 |
200 | @param row The row matrix whose values to subtract.
201 |
202 | @return The matrix after the subtraction.
203 | */
204 | - (Matrix *)matrixBySubtractingRow:(Matrix *)row;
205 |
206 | /**
207 | Returns a matrix resulting from multiplying the values in
208 | row matrix |row| with every row.
209 |
210 | @param row The row matrix whose values to multiply with.
211 |
212 | @return The matrix after the multiplication
213 | */
214 | - (Matrix *)matrixByMultiplyingWithRow:(Matrix *)row;
215 |
216 | /**
217 | Returns a matrix resulting from adding the values in the
218 | column matrix |column| to every column.
219 |
220 | @param column The column matrix whose values to add.
221 |
222 | @return The matrix after the addition.
223 | */
224 | - (Matrix *)matrixByAddingColumn:(Matrix *)column;
225 |
226 | /**
227 | Returns a matrix resulting from subtracting the values in
228 | column matrix |column| from every column.
229 |
230 | @param column The rocolumnw matrix whose values to subtract.
231 |
232 | @return The matrix after the subtraction.
233 | */
234 | - (Matrix *)matrixBySubtractingColumn:(Matrix *)column;
235 |
236 | /**
237 | Returns a matrix resulting from multiplying the values in
238 | column matrix |column| with every column.
239 |
240 | @param column The column matrix whose values to multiply with.
241 |
242 | @return The matrix after the multiplication
243 | */
244 | - (Matrix *)matrixByMultiplyingWithColumn:(Matrix *)column;
245 |
246 | /**
247 | Returns a new matrix with the values of the columns
248 | whose indices are in |range|.
249 |
250 | @param range The range of indices of columns to include.
251 |
252 | @return The matrix of columns in |range|.
253 | */
254 | - (Matrix *)matrixWithColumnsInRange:(NSRange)range;
255 |
256 | /**
257 | Returns a new matrix with the values of the rows
258 | whose indices are in |range|.
259 |
260 | @param range The range of indices of rows to include.
261 |
262 | @return The matrix of rows in |range|.
263 | */
264 | - (Matrix *)matrixWithRowsInRange:(NSRange)range;
265 |
266 | /**
267 | Adds row matrix |row| to every row of the receiver.
268 |
269 | @param row The row matrix to add
270 | */
271 | - (void)addRow:(Matrix *)row;
272 |
273 | /**
274 | Subtracts row matrix |row| from every row of the receiver.
275 |
276 | @param row The row matrix to subtract
277 | */
278 | - (void)subtractRow:(Matrix *)row;
279 |
280 | /**
281 | Multiplies row matrix |row| with every row of the receiver.
282 |
283 | @param row The row matrix to multiply
284 | */
285 | - (void)multiplyRow:(Matrix *)row;
286 |
287 | /**
288 | Divides every row of the receiver with row matrix |row|.
289 |
290 | @param row The row matrix to multiply
291 | */
292 | - (void)divideRow:(Matrix *)row;
293 |
294 | /**
295 | Adds column matrix |column| to every column of the receiver.
296 |
297 | @param column The column matrix to add
298 | */
299 | - (void)addColumn:(Matrix *)column;
300 |
301 | /**
302 | Subtracts column matrix |column| from every column of the receiver.
303 |
304 | @param column The column matrix to subtract
305 | */
306 | - (void)subtractColumn:(Matrix *)column;
307 |
308 | /**
309 | Multiplies column matrix |column| with every column of the receiver.
310 |
311 | @param column The column matrix to multiply
312 | */
313 | - (void)multiplyColumn:(Matrix *)column;
314 |
315 | /**
316 | Divides every column of the receiver with column matrix |column|.
317 |
318 | @param column The column matrix to multiply
319 | */
320 | - (void)divideColumn:(Matrix *)column;
321 |
322 | /**
323 | Returns a new matrix by appending row matrix |row|.
324 |
325 | @param row The row matrix to append.
326 |
327 | @return The result of appending.
328 | */
329 | - (Matrix *)appendRow:(Matrix *)row;
330 |
331 | /**
332 | Returns a new matrix by appending column matrix |column|.
333 |
334 | @param column The column matrix to append.
335 |
336 | @return The result of appending.
337 | */
338 | - (Matrix *)appendColumn:(Matrix *)column;
339 |
340 | /**
341 | Returns a new matrix that is the result of removing
342 | the row at |rowIndex|.
343 |
344 | @param rowIndex The index of the row to remove.
345 |
346 | @return The matrix missing the removed row.
347 | */
348 | - (Matrix *)removeRow:(int)rowIndex;
349 |
350 | /**
351 | Returns a new matrix that is the result of removing
352 | the column at |columnIndex|.
353 |
354 | @param columnIndex The index of the column to remove.
355 |
356 | @return The matrix missing the removed column.
357 | */
358 | - (Matrix *)removeColumn:(int)columnIndex;
359 |
360 | /**
361 | Returns a matrix resulting from appending a row with values |value|
362 |
363 | @param value The value of the row matrix to append.
364 |
365 | @return The matrix after appending.
366 | */
367 | - (Matrix *)appendValueAsRow:(double)value;
368 |
369 |
370 | - (void)applyMatrix:(Matrix *)other i:(int)i j:(int)j;
371 |
372 | /**
373 | Returns a matrix with shuffled rows
374 |
375 | @return The matrix after shuffling rows.
376 | */
377 | - (Matrix *)matrixByShufflingRows;
378 |
379 | /**
380 | Shuffles the rows of the receiver.
381 | */
382 | - (void)shuffleRows;
383 |
384 | /**
385 | Returns a matrix with shuffled columns.
386 |
387 | @return The matrix after shuffling columns.
388 | */
389 | - (Matrix *)matrixByShufflingColumns;
390 |
391 | /**
392 | Shuffles the columns of the receiver.
393 | */
394 | - (void)shuffleColumns;
395 |
396 | /**
397 | Returns a matrix resulting from uniform random sampling of |sampleCount|
398 | rows, optionally with |replacement|.
399 |
400 | @param sampleCount The number of rows to sample.
401 | @param replacement Whether to use replacement in sampling.
402 |
403 | @return The matrix resulting from the sampling.
404 | */
405 | - (Matrix *)matrixBySamplingRows:(NSUInteger)sampleCount replacement:(BOOL)replacement;
406 |
407 | /**
408 | Returns a matrix resulting from uniform random sampling of |sampleCount|
409 | columns, optionally with |replacement|.
410 |
411 | @param sampleCount The number of columns to sample.
412 | @param replacement Whether to use replacement in sampling.
413 |
414 | @return The matrix resulting from the sampling.
415 | */
416 | - (Matrix *)matrixBySamplingColumns:(NSUInteger)sampleCount replacement:(BOOL)replacement;
417 |
418 | @end
419 |
--------------------------------------------------------------------------------
/YCMatrix/Matrix+Manipulate.m:
--------------------------------------------------------------------------------
1 | //
2 | // Matrix+Manipulate.m
3 | //
4 | // YCMatrix
5 | //
6 | // Copyright (c) 2013 - 2016 Ioannis (Yannis) Chatzikonstantinou. All rights reserved.
7 | // http://yconst.com
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | #import "Matrix+Manipulate.h"
28 | #import "Constants.h"
29 |
30 | #define ARC4RANDOM_MAX 0x100000000
31 |
32 | @implementation Matrix (Manipulate)
33 |
34 | + (Matrix *)matrixFromRows:(NSArray *)rows
35 | {
36 | NSUInteger rowCount = [rows count];
37 | if (rowCount == 0) return [Matrix matrixOfRows:0 columns:0];
38 | Matrix *firstRow = rows[0];
39 | int columnCount = firstRow->columns;
40 | Matrix *ret = [Matrix matrixOfRows:(int)rowCount columns:(int)columnCount];
41 | for (int i=0; imatrix[j] row:i column:j];
47 | }
48 | }
49 | return ret;
50 | }
51 |
52 | + (Matrix *)matrixFromColumns:(NSArray *)columns
53 | {
54 | NSUInteger columnCount = [columns count];
55 | if (columnCount == 0) return [Matrix matrixOfRows:0 columns:0];
56 | Matrix *firstCol = columns[0];
57 | int rowCount = firstCol->rows;
58 | Matrix *ret = [Matrix matrixOfRows:(int)rowCount columns:(int)columnCount];
59 | for (int i=0; imatrix[j] row:j column:i];
65 | }
66 | }
67 | return ret;
68 | }
69 |
70 | - (void)copyValuesFrom:(Matrix *)aMatrix
71 | {
72 | NSAssert(aMatrix.rows == self.rows && aMatrix.columns == self.columns, @"Incorrect matrix size");
73 | memcpy(self->matrix, aMatrix->matrix, self.rows * self.columns * sizeof(double));
74 | }
75 |
76 | - (Matrix *)row:(int) rowIndex
77 | {
78 | NSAssert(rowIndex < self->rows, @"Index out of bounds");
79 | // http://stackoverflow.com/questions/5850000/how-to-split-array-into-two-arrays-in-c
80 | int startIndex = rowIndex * self->columns;
81 | Matrix *rowmatrix = [Matrix matrixOfRows:1 columns:self->columns];
82 | double *row = rowmatrix->matrix;
83 | memcpy(row, self->matrix + startIndex, self->columns * sizeof(double));
84 | return rowmatrix;
85 | }
86 |
87 | - (Matrix *)rowReference:(int)rowIndex
88 | {
89 | NSAssert(rowIndex < self->rows, @"Index out of bounds");
90 | int startIndex = rowIndex * self->columns;
91 | return [Matrix matrixFromArray:self->matrix+startIndex rows:1
92 | columns:self->columns mode:YCMWeak];
93 | }
94 |
95 | - (Matrix *)rowReferenceVector:(int)rowIndex
96 | {
97 | NSAssert(rowIndex < self->rows, @"Index out of bounds");
98 | int startIndex = rowIndex * self->columns;
99 | return [Matrix matrixFromArray:self->matrix+startIndex rows:self->columns
100 | columns:1 mode:YCMWeak];
101 | }
102 |
103 | - (Matrix *)rows:(NSIndexSet *)indexes
104 | {
105 | NSAssert([indexes lastIndex] < self->rows, @"Index out of bounds");
106 | __block int count = 0;
107 | Matrix *result = [Matrix matrixOfRows:(int)[indexes count] columns:self.columns];
108 | [indexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) {
109 | [result setRow:count++ value:[self row:(int)idx]];
110 | }];
111 | return result;
112 | }
113 |
114 | - (void)setRow:(int)rowIndex value:(Matrix *)rowValue
115 | {
116 | NSAssert(rowIndex < self->rows, @"Index out of bounds");
117 | NSAssert(rowValue->rows == 1 && rowValue->columns == columns, @"Matrix size mismatch");
118 | memcpy(self->matrix + columns * rowIndex, rowValue->matrix, columns * sizeof(double));
119 | }
120 |
121 | - (NSArray *)rowsAsNSArray
122 | {
123 | NSMutableArray *rowsArray = [NSMutableArray arrayWithCapacity:rows];
124 | for (int i=0; i 0)
155 | {
156 | partitions++;
157 | }
158 | NSMutableArray *result = [NSMutableArray array];
159 | for (int i=0; i 0)
163 | {
164 | sLim = remainder;
165 | }
166 | NSRange partitionRange = NSMakeRange(i * size, sLim);
167 | Matrix *partition = [self rows:[NSIndexSet indexSetWithIndexesInRange:partitionRange]];
168 | [result addObject:partition];
169 | }
170 | return result;
171 | }
172 |
173 | - (Matrix *)column:(int) colIndex
174 | {
175 | NSAssert(colIndex < self->columns, @"Index out of bounds");
176 | Matrix *columnmatrix = [Matrix matrixOfRows:self->rows columns:1];
177 | double *column = columnmatrix->matrix;
178 | for (int i=0; irows; i++)
179 | {
180 | column[i] = self->matrix[i*self->columns + colIndex];
181 | }
182 | return columnmatrix;
183 | }
184 |
185 | - (Matrix *)columns:(NSIndexSet *)indexes
186 | {
187 | NSAssert([indexes lastIndex] < self->columns, @"Index out of bounds");
188 | __block int count = 0;
189 | Matrix *result = [Matrix matrixOfRows:self.rows columns:(int)[indexes count]];
190 | [indexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) {
191 | [result setColumn:count++ value:[self column:(int)idx]];
192 | }];
193 | return result;
194 | }
195 |
196 | - (void)setColumn:(int)colIndex value:(Matrix *)columnValue
197 | {
198 | NSAssert(colIndex < self->columns, @"Index out of bounds");
199 | NSAssert(columnValue->columns == 1 && columnValue->rows == rows, @"Matrix size mismatch");
200 | for (int i=0; imatrix[columns*i + colIndex] = columnValue->matrix[i];
203 | }
204 | }
205 |
206 | - (NSArray *)columnsAsNSArray // needs some speed improvement
207 | {
208 | NSMutableArray *columnsArray = [NSMutableArray arrayWithCapacity:columns];
209 | for (int i=0; i 0)
240 | {
241 | partitions++;
242 | }
243 | NSMutableArray *result = [NSMutableArray array];
244 | for (int i=0; i 0)
248 | {
249 | sLim = remainder;
250 | }
251 | NSRange partitionRange = NSMakeRange(i * size, sLim);
252 | Matrix *partition = [self columns:[NSIndexSet indexSetWithIndexesInRange:partitionRange]];
253 | [result addObject:partition];
254 | }
255 | return result;
256 | }
257 |
258 | - (Matrix *)matrixByAddingRow:(Matrix *)row
259 | {
260 | Matrix *result = [self copy];
261 | [result addRow:row];
262 | return result;
263 | }
264 |
265 | - (Matrix *)matrixBySubtractingRow:(Matrix *)row
266 | {
267 | Matrix *result = [self copy];
268 | [result subtractRow:row];
269 | return result;
270 | }
271 |
272 | - (Matrix *)matrixByMultiplyingWithRow:(Matrix *)row
273 | {
274 | Matrix *result = [self copy];
275 | [result multiplyRow:row];
276 | return result;
277 | }
278 |
279 | - (Matrix *)matrixByAddingColumn:(Matrix *)column
280 | {
281 | Matrix *result = [self copy];
282 | [result addColumn:column];
283 | return result;
284 | }
285 |
286 | - (Matrix *)matrixBySubtractingColumn:(Matrix *)column
287 | {
288 | Matrix *result = [self copy];
289 | [result subtractColumn:column];
290 | return result;
291 | }
292 |
293 | - (Matrix *)matrixByMultiplyingWithColumn:(Matrix *)column
294 | {
295 | Matrix *result = [self copy];
296 | [result multiplyColumn:column];
297 | return result;
298 | }
299 |
300 | - (Matrix *)matrixWithRowsInRange:(NSRange)range
301 | {
302 | NSAssert(range.location + range.length <= self->rows, @"Input out of bounds");
303 | int valueOffset = (int)range.location * self->columns;
304 | int valueCount = (int)range.length * self->columns;
305 |
306 | Matrix *newMatrix = [Matrix matrixOfRows:(int)range.length columns:self->columns];
307 | memcpy(newMatrix->matrix, self->matrix+valueOffset, valueCount * sizeof(double));
308 |
309 | return newMatrix;
310 | }
311 |
312 | - (Matrix *)matrixWithColumnsInRange:(NSRange)range
313 | {
314 | NSAssert(range.location + range.length <= self->columns, @"Input out of bounds");
315 | int rowOffset = (int)range.location;
316 | int rowLength = (int)range.length;
317 |
318 | Matrix *newMatrix = [Matrix matrixOfRows:self->rows columns:rowLength];
319 |
320 | for (int i=0; irows; i++)
321 | {
322 | memcpy(newMatrix->matrix + i*rowLength,
323 | self->matrix + rowOffset + i*self->columns,
324 | rowLength * sizeof(double));
325 | }
326 | return newMatrix;
327 | }
328 |
329 | - (void)addRow:(Matrix *)row
330 | {
331 | NSAssert(row->rows == 1 && row->columns == self->columns, @"Matrix size mismatch");
332 | double *sumarray = self->matrix;
333 | double *addendarray = row->matrix;
334 | int cols = self->columns;
335 | int rws = self->rows;
336 | for (int i=0; irows == 1 && row->columns == self->columns, @"Matrix size mismatch");
348 | double *subtractedarray = self->matrix;
349 | double *subtrahendarray = row->matrix;
350 | int cols = self->columns;
351 | int rws = self->rows;
352 | for (int i=0; irows == 1 && row->columns == self->columns, @"Matrix size mismatch");
364 | double *productarray = self->matrix;
365 | double *factorarray = row->matrix;
366 | int cols = self->columns;
367 | int rws = self->rows;
368 | for (int i=0; irows == 1 && row->columns == self->columns, @"Matrix size mismatch");
380 | double *productarray = self->matrix;
381 | double *factorarray = row->matrix;
382 | int cols = self->columns;
383 | int rws = self->rows;
384 | for (int i=0; icolumns == 1 && column->rows == self->rows, @"Matrix size mismatch");
397 | double *sumarray = self->matrix;
398 | double *addendarray = column->matrix;
399 | int cols = self->columns;
400 | int rws = self->rows;
401 | for (int i=0; icolumns == 1 && column->rows == self->rows, @"Matrix size mismatch");
413 | double *subtractedarray = self->matrix;
414 | double *subtrahendarray = column->matrix;
415 | int cols = self->columns;
416 | int rws = self->rows;
417 | for (int i=0; icolumns == 1 && column->rows == self->rows, @"Matrix size mismatch");
429 | double *productarray = self->matrix;
430 | double *factorarray = column->matrix;
431 | int cols = self->columns;
432 | int rws = self->rows;
433 | for (int i=0; icolumns == 1 && column->rows == self->rows, @"Matrix size mismatch");
445 | double *productarray = self->matrix;
446 | double *factorarray = column->matrix;
447 | int cols = self->columns;
448 | int rws = self->rows;
449 | for (int i=0; irows == 1 && row->columns == self->columns, @"Matrix size mismatch");
461 | double *newMatrix = malloc(columns * (rows + 1) * sizeof(double));
462 | memcpy(newMatrix, self->matrix, columns * rows * sizeof(double));
463 | memcpy(newMatrix + columns*rows, row->matrix, columns * sizeof(double));
464 | return [Matrix matrixFromArray:newMatrix rows:rows + 1 columns:columns mode:YCMStrong];
465 | }
466 |
467 | - (Matrix *)appendColumn:(Matrix *)column
468 | {
469 | NSAssert(column->columns == 1 && column->rows == self->rows, @"Matrix size mismatch");
470 | double *newMatrix = malloc((columns + 1) * rows * sizeof(double));
471 | int newCols = columns + 1;
472 | for (int i=0; i < rows; i++)
473 | {
474 | memcpy(newMatrix + newCols * i, self->matrix + columns * i, columns * sizeof(double));
475 | newMatrix[newCols * i + columns] = column->matrix[i];
476 | }
477 | return [Matrix matrixFromArray:newMatrix rows:rows columns:columns + 1 mode:YCMStrong];
478 | }
479 |
480 | - (Matrix *)removeRow:(int)rowIndex
481 | {
482 |
483 | NSAssert(rowIndex < self->rows, @"Index out of bounds");
484 | double newRows = rows - 1;
485 | double *newMatrix = malloc(columns * newRows * sizeof(double));
486 | for (int i=0; i < newRows; i++) // should count to one-less than rows, so newRows
487 | {
488 | int idx = i >= rowIndex ? i+1 : i;
489 | memcpy(newMatrix + columns * i, self->matrix + columns * idx, columns * sizeof(double));
490 | }
491 | return [Matrix matrixFromArray:newMatrix rows:newRows columns:columns];
492 | }
493 |
494 | - (Matrix *)removeColumn:(int)columnIndex
495 | {
496 | NSAssert(columnIndex < self->columns, @"Index out of bounds");
497 | int newCols = columns - 1;
498 | double *newMatrix = malloc(newCols * rows * sizeof(double));
499 | for (int i=0; i < rows; i++)
500 | {
501 | memcpy(newMatrix + i*newCols,
502 | self->matrix + i*self->columns,
503 | columnIndex * sizeof(double));
504 | memcpy(newMatrix + columnIndex + i*newCols,
505 | self->matrix + columnIndex + 1 + i*self->columns,
506 | (newCols - columnIndex) * sizeof(double));
507 | }
508 | return [Matrix matrixFromArray:newMatrix rows:rows columns:newCols];
509 | }
510 |
511 | - (Matrix *)appendValueAsRow:(double)value
512 | {
513 | NSAssert(columns == 1, @"Matrix size mismatch – Input needs to be a vector");
514 | int newRows = rows + 1;
515 | double *newArray = malloc(columns * newRows * sizeof(double));
516 | memcpy(newArray, matrix, columns * rows * sizeof(double));
517 | newArray[columns * newRows - 1] = value;
518 | return [Matrix matrixFromArray:newArray rows:newRows columns:columns];
519 | }
520 |
521 | - (void)applyMatrix:(Matrix *)other i:(int)i j:(int)j
522 | {
523 | NSAssert(other.rows + 1 <= self.rows && other.columns + j <= self.columns,
524 | @"Matrix out of bounds");
525 | int ma = self.rows;
526 | int na = self.columns;
527 | int mo = other.rows;
528 | int no = other.columns;
529 | for (int io = 0; iomatrix[(io + i) * na + (jo + j)] = other->matrix[io * no + jo];
534 | }
535 | }
536 | }
537 |
538 | // Fisher-Yates Inside-out Shuffle
539 | - (Matrix *)matrixByShufflingRows
540 | {
541 | Matrix *ret = [Matrix matrixFromMatrix:self];
542 | int rowCount = self->rows;
543 | int colCount = self->columns;
544 | for (int i=0; imatrix[i*colCount + j] = ret->matrix[o*colCount + j];
552 | ret->matrix[o*colCount + j] = self->matrix[i*colCount + j];
553 | }
554 | }
555 | return ret;
556 | }
557 |
558 | // Fisher-Yates Shuffle
559 | - (void)shuffleRows
560 | {
561 | int rowCount = self->rows;
562 | int colCount = self->columns;
563 | double tmp;
564 | for (int i = rowCount - 1; i>=0; --i)
565 | {
566 | int o = arc4random_uniform((int)i);
567 | for (int j=0; jmatrix[i*colCount + j];
571 | self->matrix[i*colCount + j] = self->matrix[o*colCount + j];
572 | self->matrix[o*colCount + j] = tmp;
573 | }
574 | }
575 | }
576 |
577 | // Fisher-Yates Inside-out Shuffle (UNTESTED!)
578 | - (Matrix *)matrixByShufflingColumns
579 | {
580 | Matrix *ret = [Matrix matrixFromMatrix:self];
581 | int rowCount = self->rows;
582 | int colCount = self->columns;
583 | for (int i=0; imatrix[j*colCount + i] = ret->matrix[j*colCount + o];
589 | ret->matrix[j*colCount + o] = self->matrix[j*colCount + i];
590 | }
591 | }
592 | return ret;
593 | }
594 |
595 | // Fisher-Yates Shuffle
596 | - (void)shuffleColumns
597 | {
598 | int rowCount = self->rows;
599 | int colCount = self->columns;
600 | double tmp;
601 | for (int i = colCount - 1; i>=0; --i)
602 | {
603 | int o = arc4random_uniform((int)i);
604 | for (int j=0; jmatrix[j*colCount + i];
607 | self->matrix[j*colCount + i] = self->matrix[j*colCount + o];
608 | self->matrix[j*colCount + o] = tmp;
609 | }
610 | }
611 | }
612 |
613 | - (Matrix *)matrixBySamplingRows:(NSUInteger)sampleCount replacement:(BOOL)replacement
614 | {
615 | int rowSize = self->rows;
616 | int colSize = self->columns;
617 | int colMemory = colSize * sizeof(double);
618 | Matrix *new = [Matrix matrixOfRows:(int)sampleCount columns:colSize];
619 | if (replacement)
620 | {
621 | for (int i=0; irows);
624 | memcpy(new->matrix + i * colMemory, self->matrix + rnd * colMemory, colSize);
625 | }
626 | }
627 | else
628 | {
629 | // Knuth's S algorithm
630 | int i = 0;
631 | int n = (int)sampleCount;
632 | int samples = n;
633 | NSUInteger N = rowSize;
634 | while (n > 0)
635 | {
636 | if (N * (double)arc4random() / ARC4RANDOM_MAX <= n)
637 | {
638 | memcpy(new->matrix + (samples - n) * colMemory, self->matrix + i * colMemory, colSize);
639 | n--;
640 | }
641 | i++;
642 | N--;
643 | }
644 | }
645 | return new;
646 | }
647 |
648 | - (Matrix *)matrixBySamplingColumns:(NSUInteger)sampleCount replacement:(BOOL)replacement
649 | {
650 | int rowSize = self->rows;
651 | int colSize = self->columns;
652 | Matrix *new = [Matrix matrixOfRows:rowSize columns:(int)sampleCount];
653 | if (replacement)
654 | {
655 | for (int i=0; irows);
658 | [new setColumn:i value:[self column:rnd]];
659 | }
660 | }
661 | else
662 | {
663 | // Knuth's S algorithm
664 | int i = 0;
665 | int n = (int)sampleCount;
666 | int samples = n;
667 | NSUInteger N = colSize;
668 | while (n > 0)
669 | {
670 | if (N * (double)arc4random() / ARC4RANDOM_MAX <= n)
671 | {
672 | [new setColumn:samples - n value:[self column:i]];
673 | n--;
674 | }
675 | i++;
676 | N--;
677 | }
678 | }
679 | return new;
680 | }
681 |
682 | @end
683 |
--------------------------------------------------------------------------------
/YCMatrix/Matrix+Map.h:
--------------------------------------------------------------------------------
1 | //
2 | // Matrix+Map.h
3 | //
4 | // YCMatrix
5 | //
6 | // Copyright (c) 2013 - 2016 Ioannis (Yannis) Chatzikonstantinou. All rights reserved.
7 | // http://yconst.com
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | #import
28 | #import "Matrix.h"
29 |
30 | typedef enum _MapBasis : int16_t
31 | {
32 | StDev = 1,
33 | MinMax = 0
34 | } MapBasis;
35 |
36 | typedef struct _YCDomain
37 | {
38 | double location;
39 | double length;
40 | } YCDomain;
41 |
42 | static inline YCDomain YCMakeDomain(double loc, double len)
43 | {
44 | YCDomain d;
45 | d.location = loc;
46 | d.length = len;
47 | return d;
48 | }
49 |
50 | static inline NSUInteger YCMaxDomain(YCDomain domain)
51 | {
52 | return (domain.location + domain.length);
53 | }
54 |
55 | static inline BOOL YCNumberInDomain(double num, YCDomain domain)
56 | {
57 | return (!(num < domain.location) && (num - domain.location) < domain.length) ? YES : NO;
58 | }
59 |
60 | static inline BOOL YCEqualDomains(YCDomain domain1, YCDomain domain2)
61 | {
62 | return (domain1.location == domain2.location && domain1.length == domain2.length);
63 | }
64 |
65 | @interface Matrix (Map)
66 |
67 | /**
68 | Returns the result of a row-wise linear mapping of the receiver using the
69 | supplied mapping matrix.
70 |
71 | @param transform A two-column matrix describing the linear row-wise mapping.
72 |
73 | @return A matrix containing the mapped values.
74 | */
75 | - (Matrix *)matrixByRowWiseMapUsing:(Matrix *)transform;
76 |
77 | /**
78 | Returns a two-column matrix that describes a linear row-wise mapping of the receiver
79 | to a supplied domain.
80 |
81 | @param domain The domain to map the rows to
82 | @param basis Whether to use min and max values for deriving the source domain, or the
83 | row values' standard deviation.
84 |
85 | @return A two-column descriptor matrix with the linear row-wise map coefficients
86 | */
87 | - (Matrix *)rowWiseMapToDomain:(YCDomain)domain basis:(MapBasis)basis;
88 |
89 | /**
90 | Returns a two-column matrix that describes an inverse linear row-wise mapping of
91 | the receiver from a supplied domain.
92 |
93 | @param domain The domain to map the rows from.
94 | @param basis Whether to use min and max values for deriving the target domain, or the
95 | row values' standard deviation.
96 |
97 | @return A two-column descriptor matrix with the inverse linear row-wise map coefficients
98 | */
99 | - (Matrix *)rowWiseInverseMapFromDomain:(YCDomain)domain basis:(MapBasis)basis;
100 |
101 | /**
102 | Returns the result of a column-wise linear mapping of the receiver using the
103 | supplied mapping matrix.
104 |
105 | @param transform A two-column matrix describing the linear column-wise mapping.
106 |
107 | @return A matrix containing the mapped values.
108 | */
109 | - (Matrix *)matrixByColumnWiseMapUsing:(Matrix *)transform;
110 |
111 | /**
112 | Returns a two-column matrix that describes a linear column-wise mapping of the receiver
113 | to a supplied domain.
114 |
115 | @param domain The domain to map the column to.
116 | @param basis Whether to use min and max values for deriving the source domain, or the
117 | column values' standard deviation.
118 |
119 | @return A two-column descriptor matrix with the linear column-wise map coefficients
120 | */
121 | - (Matrix *)columnWiseMapToDomain:(YCDomain)domain basis:(MapBasis)basis;
122 |
123 | /**
124 | Returns a two-column matrix that describes an inverse linear column-wise mapping of
125 | the receiver from a supplied domain.
126 |
127 | @param domain The domain to map the column from.
128 | @param basis Whether to use min and max values for deriving the target domain, or the
129 | column values' standard deviation.
130 |
131 | @return A two-column descriptor matrix with the inverse linear column-wise map coefficients
132 | */
133 | - (Matrix *)columnWiseInverseMapFromDomain:(YCDomain)domain basis:(MapBasis)basis;
134 |
135 | @end
136 |
--------------------------------------------------------------------------------
/YCMatrix/Matrix+Map.m:
--------------------------------------------------------------------------------
1 | //
2 | // Matrix+Map.m
3 | //
4 | // YCMatrix
5 | //
6 | // Copyright (c) 2013 - 2016 Ioannis (Yannis) Chatzikonstantinou. All rights reserved.
7 | // http://yconst.com
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | #import "Matrix+Map.h"
28 | #import "Matrix+Manipulate.h"
29 |
30 | @implementation Matrix (Map)
31 |
32 | - (Matrix *)matrixByRowWiseMapUsing:(Matrix *)transform
33 | {
34 | double *mtxArray = self->matrix;
35 | double *transformArray = transform->matrix;
36 | Matrix *transformed = [Matrix matrixOfRows:rows columns:columns];
37 | double *transformedArray = transformed->matrix;
38 | dispatch_apply(rows, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(size_t i)
39 | {
40 | double a = transformArray[2*i];
41 | double b = transformArray[2*i + 1];
42 | for (int j=0; jrows;
53 | int numColumns = self->columns;
54 | NSArray *matrixRows = [self rowsAsNSArray];
55 | Matrix *transform = [Matrix matrixOfRows:numRows columns:2];
56 | int i=0;
57 | double tmean = domain.location + domain.length * 0.5;
58 | double trange = domain.length;
59 | for (Matrix *m in matrixRows)
60 | {
61 | double a, b;
62 | double fmean = 0, frange = 0;
63 | for (int j=0; jmatrix[j];
66 | }
67 | fmean /= numColumns;
68 | if (basis == StDev)
69 | {
70 | double fstdev = 0;
71 | for (int j=0; jmatrix[j] - fmean, 2);
74 | }
75 | fstdev = sqrt(fstdev/numColumns);
76 | frange = 2*fstdev;
77 | }
78 | else
79 | {
80 | double min = DBL_MAX;
81 | double max = -DBL_MAX;
82 | for (int j=0; jmatrix[j]);
85 | max = MAX(max, m->matrix[j]);
86 | }
87 | frange = max - min;
88 | }
89 | a = trange / frange;
90 | b = tmean - fmean * (trange / frange);
91 | [transform setValue:a row:i column:0];
92 | [transform setValue:b row:i++ column:1];
93 | }
94 | return transform;
95 | }
96 |
97 | - (Matrix *)rowWiseInverseMapFromDomain:(YCDomain)domain basis:(MapBasis)basis
98 | {
99 | int numRows = self->rows;
100 | int numColumns = self->columns;
101 | NSArray *matrixRows = [self rowsAsNSArray];
102 | Matrix *transform = [Matrix matrixOfRows:numRows columns:2];
103 | int i=0;
104 | double fmean = domain.location + domain.length * 0.5;
105 | double frange = domain.length;
106 | for (Matrix *m in matrixRows)
107 | {
108 | double a, b;
109 | double tmean = 0, trange = 0;
110 | for (int j=0; jmatrix[j];
113 | }
114 | tmean /= numColumns;
115 | if (basis == StDev)
116 | {
117 | double tstdev = 0;
118 | for (int j=0; jmatrix[j] - tmean, 2);
121 | }
122 | tstdev = sqrt(tstdev/numColumns);
123 | trange = 2*tstdev;
124 | }
125 | else
126 | {
127 | double min = DBL_MAX;
128 | double max = -DBL_MAX;
129 | for (int j=0; jmatrix[j]);
132 | max = MAX(max, m->matrix[j]);
133 | }
134 | trange = max - min;
135 | }
136 | a = trange / frange;
137 | b = tmean - fmean * (trange / frange);
138 | [transform setValue:a row:i column:0];
139 | [transform setValue:b row:i++ column:1];
140 | }
141 | return transform;
142 | }
143 |
144 |
145 | - (Matrix *)matrixByColumnWiseMapUsing:(Matrix *)transform
146 | {
147 | // TODO: Reimplement to improve performance (remove extra transposition)
148 | return [[self matrixByTransposing] matrixByRowWiseMapUsing:transform];
149 | }
150 |
151 | - (Matrix *)columnWiseMapToDomain:(YCDomain)domain basis:(MapBasis)basis
152 | {
153 | // TODO: Reimplement to improve performance (remove extra transposition)
154 | return [[self matrixByTransposing] rowWiseMapToDomain:domain basis:basis];
155 | }
156 |
157 | - (Matrix *)columnWiseInverseMapFromDomain:(YCDomain)domain basis:(MapBasis)basis
158 | {
159 | // TODO: Reimplement to improve performance (remove extra transposition)
160 | return [[self matrixByTransposing] rowWiseInverseMapFromDomain:domain basis:basis];
161 | }
162 |
163 | @end
164 |
--------------------------------------------------------------------------------
/YCMatrix/Matrix.h:
--------------------------------------------------------------------------------
1 | //
2 | // Matrix.h
3 | //
4 | // YCMatrix
5 | //
6 | // Copyright (c) 2013 - 2016 Ioannis (Yannis) Chatzikonstantinou. All rights reserved.
7 | // http://yconst.com
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | typedef enum refMode { YCMWeak, YCMStrong, YCMCopy } refMode;
28 |
29 | #import
30 | #import
31 |
32 | /**
33 | The Matrix class is the main class in the YCMatrix framework,
34 | which represents a single mxn matrix.
35 | */
36 | @interface Matrix : NSObject
37 | {
38 | @public double *matrix;
39 | @public int rows;
40 | @public int columns;
41 | @private BOOL freeData;
42 | }
43 |
44 | /// @name Initialization
45 |
46 | /**
47 | Initializes and returns a new matrix of |m| rows and |n| columns.
48 |
49 | @param m Number of rows.
50 | @param n Number of columns.
51 |
52 | @return A new matrix of |m| rows and |n| columns.
53 | */
54 | + (instancetype)matrixOfRows:(int)m columns:(int)n;
55 |
56 | /**
57 | Initializes and returns a new matrix with the same number of rows and columns as |other|.
58 |
59 | @param other The matrix whose number of rows and columns to clone.
60 |
61 | @return A new matrix with the same number of rows and columns as |other|.
62 | */
63 | + (instancetype)matrixLike:(Matrix *)other;
64 |
65 | /**
66 | Initializes and returns a new matrix of ones with the same number of rows and columns as |other|.
67 |
68 | @param other The matrix whose number of rows and columns to clone.
69 |
70 | @return A new matrix of ones with the same number of rows and columns as |other|.
71 | */
72 | + (instancetype)onesLike:(Matrix *)other;
73 |
74 | /**
75 | Initializes and returns a new matrix of |m| rows and |n| columns, each containing value |val|.
76 |
77 | @param m The number of rows.
78 | @param n The number of columns.
79 | @param val Cell value.
80 |
81 | @return A new matrix of |m| rows and |n| columns.
82 | */
83 | + (instancetype)matrixOfRows:(int)m columns:(int)n value:(double)val;
84 |
85 | /**
86 | Initializes and returns a new matrix of |m| rows and |n| columns, with value |diagonal|
87 | representing values in the matrix diagonal, and each other cell containing value |val|.
88 |
89 | @param m The number of rows.
90 | @param n The number of columns.
91 | @param diagonal The value to insert to the diagonal.
92 | @param val The value to insert to the rest of the matrix.
93 |
94 | @return A new matrix of |m| rows and |n| columns.
95 | */
96 | + (instancetype)matrixOfRows:(int)m
97 | columns:(int)n
98 | valueInDiagonal:(double)diagonal
99 | value:(double)val;
100 |
101 | /**
102 | Initializes and returns a new matrix of |m| rows and |n| columns, with values in array |diagonal|
103 | representing values in the matrix diagonal, and each other cell containing value |val|.
104 |
105 | @param m The number of rows.
106 | @param n The number of columns.
107 | @param diagonal The values to insert to the diagonal.
108 | @param val The value to insert to the rest of the matrix.
109 |
110 | @return A new matrix of |m| rows and |n| columns.
111 | */
112 | + (instancetype)matrixOfRows:(int)m
113 | columns:(int)n
114 | valuesInDiagonal:(double *)diagonal
115 | value:(double)val;
116 |
117 | /**
118 | Initializes and returns a new matrix of |m| rows and |n| columns,
119 | by copying array |arr|.
120 |
121 | @param arr The array of values.
122 | @param m The number of rows.
123 | @param n The number of columns.
124 |
125 | @return A new matrix of |m| rows and |n| columns.
126 | */
127 | + (instancetype)matrixFromArray:(double *)arr rows:(int)m columns:(int)n;
128 |
129 | /**
130 | Initializes and returns a new matrix of |m| rows and |n| columns,
131 | by either weakly or strongly referencing, or copying array |arr|.
132 |
133 | @param arr The array of values.
134 | @param m The number of rows.
135 | @param n The number of columns.
136 | @param mode The reference mode.
137 |
138 | @return A new matrix of |m| rows and |n| columns.
139 | */
140 | + (instancetype)matrixFromArray:(double *)arr rows:(int)m columns:(int)n mode:(refMode)mode;
141 |
142 | /**
143 | Initializes and returns a new matrix of |m| rows and |n| columns,
144 | by copying values in NSArray |arr|
145 |
146 | @param arr The NSArray containing values to be copied.
147 | @param m The number of rows.
148 | @param n The number of columns.
149 |
150 | @return A new matrix of |m| rows and |n| columns.
151 | */
152 | + (instancetype)matrixFromNSArray:(NSArray *)arr rows:(int)m columns:(int)n;
153 |
154 | /**
155 | Initializes and returns a new matrix by copying matrix |other|.
156 |
157 | @param other The matrix to copy.
158 |
159 | @return A new matrix of equal dimensions to |other|.
160 | */
161 | + (instancetype)matrixFromMatrix:(Matrix *)other;
162 |
163 | /**
164 | Initializes and returns a new Identity matrix of |m| rows and |n| columns
165 |
166 | @param m The number of rows.
167 | @param n The number of columns.
168 |
169 | @return A new matrix of |m| rows and |n| columns.
170 | */
171 | + (instancetype)identityOfRows:(int)m columns:(int)n;
172 |
173 |
174 | /// @name Accessing and setting data
175 |
176 | /**
177 | Returns the value at position |row|, |column| of the receiver.
178 |
179 | @param row The row.
180 | @param column The column.
181 |
182 | @return A double corresponding to the value at position |row|, |column|.
183 | */
184 | - (double)valueAtRow:(int)row column:(int)column;
185 |
186 | /**
187 | Returns the value at position |i|, |j| of the receiver.
188 |
189 | @param i The row.
190 | @param j The column.
191 |
192 | @return A double corresponding to the value at position |i|, |j|.
193 | */
194 | - (double)i:(int)i j:(int)j;
195 |
196 | /**
197 | Sets value |value| at |row|, |column| of the receiver.
198 |
199 | @param value The value to set.
200 | @param row The row.
201 | @param column The column.
202 | */
203 | - (void)setValue:(double)value row:(int)row column:(int)column;
204 |
205 | /**
206 | Sets value |value| at |i|, |j| of the receiver.
207 |
208 | @param i The row.
209 | @param j The column.
210 | @param value The value to set.
211 | */
212 | - (void)i:(int)i j:(int)j set:(double)value;
213 |
214 | /**
215 | Increments value at |i|, |j| of the receiver, by |value|.
216 |
217 | @param i The row.
218 | @param j The column.
219 | @param value The value to set.
220 | */
221 | - (void)i:(int)i j:(int)j increment:(double)value;
222 |
223 | /**
224 | Increments all values in the matrix by |value|.
225 |
226 | @param value The value to increment by.
227 | */
228 | - (void)incrementAll:(double)value;
229 |
230 | /// @name Matrix Operations
231 |
232 | /**
233 | Returns the result of adding the matrix to |addend|.
234 |
235 | @param addend The matrix to add to.
236 |
237 | @return The result of the addition.
238 | */
239 | - (Matrix *)matrixByAdding:(Matrix *)addend;
240 |
241 | /**
242 | Returns the result of subtracting |subtrahend| from the receiver.
243 |
244 | @param subtrahend The matrix to subtract from this.
245 |
246 | @return The result of the subtraction.
247 | */
248 | - (Matrix *)matrixBySubtracting:(Matrix *)subtrahend;
249 |
250 | /**
251 | Returns the result of multiplying the receiver with right matrix |mt|.
252 |
253 | @param mt The matrix to multiply with.
254 |
255 | @return The result of the multiplication.
256 | */
257 | - (Matrix *)matrixByMultiplyingWithRight:(Matrix *)mt;
258 |
259 | /**
260 | Returns the result of multiplying the receiver with right matrix |mt| and optionally transposing
261 | the result.
262 |
263 | @param mt The matrix to multiply with.
264 | @param trans Whether to transpose the result.
265 |
266 | @return The result of the operation.
267 | */
268 | - (Matrix *)matrixByMultiplyingWithRight:(Matrix *)mt AndTransposing:(bool)trans;
269 |
270 | /**
271 | Returns the result of multiplying the receiver with right matrix |mt| and adding
272 | YCMatrix |ma| to the result.
273 |
274 | @param mt The matrix to multiply with.
275 | @param ma The matrix to add to the multiplication result.
276 |
277 | @return The result of the operation.
278 | */
279 | - (Matrix *)matrixByMultiplyingWithRight:(Matrix *)mt AndAdding:(Matrix *)ma;
280 |
281 | /**
282 | Returns the result of multiplying the receiver with right matrix |mt| and then with scalar |factor|.
283 |
284 | @param mt The matrix to multiply with.
285 | @param sf The scalar factor to multiply with.
286 |
287 | @return The result of the multiplication.
288 | */
289 | - (Matrix *)matrixByMultiplyingWithRight:(Matrix *)mt AndFactor:(double)sf;
290 |
291 | /**
292 | Returns the result of transposing the receiver and multiplying with right matrix |mt|.
293 |
294 | @param mt The matrix to multiply with.
295 |
296 | @return The result of the operation.
297 | */
298 | - (Matrix *)matrixByTransposingAndMultiplyingWithRight:(Matrix *)mt;
299 |
300 | /**
301 | Returns the result of transposing the receiver and multiplying with left matrix |mt|.
302 |
303 | @param mt The matrix to multiply with.
304 |
305 | @return The result of the operation.
306 | */
307 | - (Matrix *)matrixByTransposingAndMultiplyingWithLeft:(Matrix *)mt;
308 |
309 | /**
310 | Returns the result of multiplying the receiver with scalar |ms|.
311 |
312 | @param ms The scalar to multiply with.
313 |
314 | @return The result of the multiplication.
315 | */
316 | - (Matrix *)matrixByMultiplyingWithScalar:(double)ms;
317 |
318 | /**
319 | Returns the result of multiplying the receiver with scalar |ms| and adding matrix |addend|.
320 |
321 | @param ms The scalar to multiply with
322 | @param addend The matrix to add.
323 |
324 | @return The result of the operation.
325 | */
326 | - (Matrix *)matrixByMultiplyingWithScalar:(double)ms AndAdding:(Matrix *)addend;
327 |
328 | /**
329 | Negates the receiver.
330 |
331 | @return The result of the negation.
332 | */
333 | - (Matrix *)matrixByNegating;
334 |
335 | /**
336 | Returns a matrix by squaring the elements of the receiver.
337 |
338 | @return The matrix with squared elements.
339 | */
340 | - (Matrix *)matrixBySquaring;
341 |
342 | /**
343 | Returns a matrix by absolute values of the receiver.
344 |
345 | @return The matrix with the absolute values of the elements.
346 | */
347 | - (Matrix *)matrixByAbsolute;
348 |
349 | /**
350 | Returns the transpose of the receiver.
351 |
352 | @return The result of the transposition.
353 | */
354 | - (Matrix *)matrixByTransposing;
355 |
356 | /**
357 | Returns the result of elementwise multiplication of the receiver with matrix |mt|.
358 |
359 | @param mt The matrix to elementwise multiply with.
360 |
361 | @return The result of the elementwise multiplication.
362 | */
363 | - (Matrix *)matrixByElementWiseMultiplyWith:(Matrix *)mt;
364 |
365 | /**
366 | Returns the result of elementwise division of the receiver by matrix |mt|.
367 |
368 | @param mt The matrix to elementwise divide by.
369 |
370 | @return The result of the elementwise division.
371 | */
372 | - (Matrix *)matrixByElementWisDivideBy:(Matrix *)mt;
373 |
374 | /// @name In-place Matrix Operations
375 |
376 | /**
377 | Performs an in-place addition of |addend|.
378 |
379 | @param addend The matrix to add.
380 | */
381 | - (void)add:(Matrix *)addend;
382 |
383 | /**
384 | Performs an in-place subtraction of |subtrahend|.
385 |
386 | @param subtrahend The matrix to subtract.
387 | */
388 | - (void)subtract:(Matrix *)subtrahend;
389 |
390 | /**
391 | Performs an in-place scalar multiplication of the receiver.
392 |
393 | @param ms The scalar to multiply with.
394 | */
395 | - (void)multiplyWithScalar:(double)ms;
396 |
397 | /**
398 | Performs an in-place negation of the receiver's elements.
399 | */
400 | - (void)negate;
401 |
402 | /**
403 | Performs an in-place squaring of the receiver's elements.
404 | */
405 | - (void)square;
406 |
407 | /**
408 | Performs an in-place absolute of the receiver's elements.
409 | */
410 | - (void)absolute;
411 |
412 | /**
413 | Returns the result of an elementwise multiplication with matrix |mt|.
414 |
415 | @param mt The result of the elementwise multiplication.
416 | */
417 | - (void)elementWiseMultiply:(Matrix *)mt;
418 |
419 | /**
420 | Returns the result of an elementwise division by matrix |mt|.
421 |
422 | @param mt The result of the elementwise division.
423 | */
424 | - (void)elementWiseDivide:(Matrix *)mt;
425 |
426 | /**
427 | Sets all values of the matrix on its diagonal to the specified value
428 |
429 | @param value The value to set the values on the diagonal to.
430 | */
431 | - (void)setDiagonalTo:(double)value;
432 |
433 | /**
434 | Returns the trace of this matrix.
435 |
436 | @return A double corresponding to the calculated trace of the receiver.
437 | */
438 | - (double)trace;
439 |
440 | /**
441 | Returns a double resulting from the summation of an elementwise multiplication of the receiver with |other|
442 |
443 | @param other The matrix to perform the elementwise multiplication with.
444 |
445 | @return A double corresponding to the result of the operation.
446 | */
447 | - (double)dotWith:(Matrix *)other;
448 |
449 | /**
450 | Returns a copy that is normalized to the range [0,1].
451 |
452 | @return The matrix copy.
453 | @warning This method is applicable only to vectors.
454 | */
455 | - (Matrix *)matrixByUnitizing;
456 |
457 | /**
458 | Compares the receiver with a matrix, using the specified numerical tolerance
459 |
460 | @param aMatrix The other matrix
461 | @param precision The numerical tolerance used for comparison
462 |
463 | @return Boolean showing whether the matrix objects are equal or not.
464 | */
465 | - (BOOL)isEqualToMatrix:(Matrix *)aMatrix tolerance:(double)tolerance;
466 |
467 | /**
468 | Returns the data array of the receiver.
469 | */
470 | @property (readonly) double *array;
471 |
472 | /**
473 | Returns a copy of the data array of thereceiver.
474 | */
475 | @property (readonly) double *arrayCopy;
476 |
477 | /**
478 | Returns an NSArray with the content of the data array of the receiver.
479 | */
480 | @property (readonly) NSArray *numberArray;
481 |
482 | /**
483 | Returns a column matrix (vector) containing the elements of the diagonal of the receiver.
484 |
485 | @warning Calling this method repeatedly will incur a performance penalty,
486 | since the elements need to be extracted every time. Better store
487 | the result and reuse.
488 | */
489 | @property (readonly) Matrix *diagonal;
490 |
491 | /**
492 | Returns the number of rows of the receiver.
493 | */
494 | @property (readonly) int rows;
495 |
496 | /**
497 | Returns the number of columns of the receiver.
498 | */
499 | @property (readonly) int columns;
500 |
501 | /**
502 | Returns the length of the data array of the receiver.
503 | */
504 | @property (readonly) NSUInteger count;
505 |
506 | /**
507 | Returns the sum of all the elements of the receiver.
508 | */
509 | @property (readonly) double sum;
510 |
511 | /**
512 | Returns the product of all the elements of the receiver.
513 | */
514 | @property (readonly) double product;
515 |
516 | /**
517 | Returns the smallest value among the elements of the receiver.
518 | */
519 | @property (readonly) double min;
520 |
521 | /**
522 | Returns the largest value among the elements of the receiver.
523 | */
524 | @property (readonly) double max;
525 |
526 | /**
527 | Returns YES if the receiver is a square matrix.
528 | */
529 | @property (readonly) BOOL isSquareMatrix;
530 |
531 | @end
532 |
--------------------------------------------------------------------------------
/YCMatrix/Matrix.m:
--------------------------------------------------------------------------------
1 | //
2 | // Matrix.m
3 | //
4 | // YCMatrix
5 | //
6 | // Copyright (c) 2013 - 2016 Ioannis (Yannis) Chatzikonstantinou. All rights reserved.
7 | // http://yconst.com
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | #import "Matrix.h"
28 | #import "Constants.h"
29 |
30 | @implementation Matrix
31 |
32 | #pragma mark Factory Methods
33 |
34 | + (instancetype)matrixOfRows:(int)m columns:(int)n
35 | {
36 | return [self matrixOfRows:m columns:n valuesInDiagonal:nil value:0];
37 | }
38 |
39 | + (instancetype)matrixLike:(Matrix *)other
40 | {
41 | return [self matrixOfRows:other->rows columns:other->columns];
42 | }
43 |
44 | + (instancetype)onesLike:(Matrix *)other
45 | {
46 | return [self matrixOfRows:other->rows columns:other->columns value:1.0];
47 | }
48 |
49 | + (instancetype)dirtyMatrixOfRows:(int)m columns:(int)n
50 | {
51 | double *new_m = malloc(m*n * sizeof(double));
52 | Matrix *mt = [self matrixFromArray:new_m rows:m columns:n mode:YCMWeak];
53 | mt->freeData = YES;
54 | return mt;
55 | }
56 |
57 | + (instancetype)matrixOfRows:(int)m columns:(int)n value:(double)val
58 | {
59 | return [self matrixOfRows:m columns:n valuesInDiagonal:nil value:val];
60 | }
61 |
62 | + (instancetype)matrixOfRows:(int)m
63 | columns:(int)n
64 | valueInDiagonal:(double)diagonal
65 | value:(double)val
66 | {
67 | double *new_m = malloc(m*n*sizeof(double));
68 | Matrix *mt = [self matrixFromArray:new_m rows:m columns:n mode:YCMWeak];
69 | mt->freeData = YES;
70 | int len = m*n;
71 |
72 | vDSP_vfillD(&val, mt->matrix, 1, len);
73 |
74 | int mind = MIN(m, n);
75 | for (int i=0; imatrix[i*(n+1)] = diagonal;
78 | }
79 | return mt;
80 | }
81 |
82 | + (instancetype)matrixOfRows:(int)m
83 | columns:(int)n
84 | valuesInDiagonal:(double *)diagonal
85 | value:(double)val
86 | {
87 | double *new_m = malloc(m*n*sizeof(double));
88 | Matrix *mt = [self matrixFromArray:new_m rows:m columns:n mode:YCMWeak];
89 | mt->freeData = YES;
90 | int len = m*n;
91 | for (int i=0; imatrix[i] = val;
94 | }
95 | if (diagonal)
96 | {
97 | int mind = MIN(m, n);
98 | for (int i=0; imatrix[i*(n+1)] = diagonal[i];
101 | }
102 | }
103 | return mt;
104 | }
105 |
106 | + (instancetype)matrixFromArray:(double *)arr rows:(int)m columns:(int)n
107 | {
108 | return [self matrixFromArray:arr rows:m columns:n mode:YCMCopy];
109 | }
110 |
111 | + (instancetype)matrixFromArray:(double *)arr rows:(int)m columns:(int)n mode:(refMode)mode
112 | {
113 | Matrix *mt = [[Matrix alloc] init];
114 | if (mode == YCMCopy)
115 | {
116 | double *new_m = malloc(m*n*sizeof(double));
117 | memcpy(new_m, arr, m*n*sizeof(double));
118 | mt->matrix = new_m;
119 | mt->freeData = YES;
120 | }
121 | else
122 | {
123 | mt->matrix = arr;
124 | mt->freeData = NO;
125 | }
126 | if (mode != YCMWeak) mt->freeData = YES;
127 | mt->rows = m;
128 | mt->columns = n;
129 | return mt;
130 | }
131 |
132 | + (instancetype)matrixFromNSArray:(NSArray *)arr rows:(int)m columns:(int)n
133 | {
134 | if([arr count] != m*n)
135 | @throw [NSException exceptionWithName:@"MatrixSizeException"
136 | reason:@"Matrix size does not match that of the input array."
137 | userInfo:nil];
138 | Matrix *newMatrix = [Matrix matrixOfRows:m columns:n];
139 | double *cArray = newMatrix->matrix;
140 | NSUInteger j=[arr count];
141 | for (int i=0; imatrix rows:other->rows columns:other->columns];
151 | return mt;
152 | }
153 |
154 | + (instancetype)identityOfRows:(int)m columns:(int)n
155 | {
156 | double *new_m = calloc(m*n, sizeof(double));
157 | int minsize = m;
158 | if (n < m) minsize = n;
159 | for(int i=0; imatrix, 1, addend->matrix, 1, result->matrix, 1, self.count);
209 | return result;
210 | }
211 |
212 | - (Matrix *)matrixBySubtracting:(Matrix *)subtrahend
213 | {
214 | Matrix *result = [Matrix dirtyMatrixOfRows:self.rows columns:self.columns];
215 | vDSP_vsubD(subtrahend->matrix, 1, self->matrix, 1, result->matrix, 1, self.count);
216 | return result;
217 | }
218 |
219 | - (Matrix *)matrixByMultiplyingWithRight:(Matrix *)mt
220 | {
221 | return [self matrixByTransposing:NO
222 | TransposingRight:NO
223 | MultiplyWithRight:mt
224 | Factor:1
225 | Adding:nil];
226 | }
227 |
228 | - (Matrix *)matrixByMultiplyingWithRight:(Matrix *)mt AndTransposing:(bool)trans
229 | {
230 | Matrix *M1 = trans ? mt : self;
231 | Matrix *M2 = trans ? self : mt;
232 | return [M1 matrixByTransposing:trans
233 | TransposingRight:trans
234 | MultiplyWithRight:M2
235 | Factor:1
236 | Adding:nil];
237 | }
238 |
239 | - (Matrix *)matrixByMultiplyingWithRight:(Matrix *)mt AndAdding:(Matrix *)ma
240 | {
241 | return [self matrixByTransposing:NO
242 | TransposingRight:NO
243 | MultiplyWithRight:mt
244 | Factor:1
245 | Adding:ma];
246 | }
247 |
248 | - (Matrix *)matrixByMultiplyingWithRight:(Matrix *)mt AndFactor:(double)sf
249 | {
250 | return [self matrixByTransposing:NO
251 | TransposingRight:NO
252 | MultiplyWithRight:mt
253 | Factor:sf
254 | Adding:nil];
255 | }
256 |
257 | - (Matrix *)matrixByTransposingAndMultiplyingWithRight:(Matrix *)mt
258 | {
259 | return [self matrixByTransposing:YES
260 | TransposingRight:NO
261 | MultiplyWithRight:mt
262 | Factor:1
263 | Adding:nil];
264 | }
265 |
266 | - (Matrix *)matrixByTransposingAndMultiplyingWithLeft:(Matrix *)mt
267 | {
268 | return [mt matrixByTransposing:NO
269 | TransposingRight:YES
270 | MultiplyWithRight:self
271 | Factor:1
272 | Adding:nil];
273 | }
274 |
275 | //
276 | // Actual calls to BLAS
277 |
278 | - (Matrix *)matrixByTransposing:(BOOL)transposeLeft
279 | TransposingRight:(BOOL)transposeRight
280 | MultiplyWithRight:(Matrix *)mt
281 | Factor:(double)factor
282 | Adding:(Matrix *)addend
283 | {
284 | int M = transposeLeft ? columns : rows;
285 | int N = transposeRight ? mt->rows : mt->columns;
286 | int K = transposeLeft ? rows : columns;
287 | int lda = columns;
288 | int ldb = mt->columns;
289 | int ldc = N;
290 |
291 | if ((transposeLeft ? rows : columns) != (transposeRight ? mt->columns : mt->rows))
292 | {
293 | @throw [NSException exceptionWithName:@"MatrixSizeException"
294 | reason:@"Matrix size unsuitable for multiplication."
295 | userInfo:nil];
296 | }
297 | if (addend && (addend->rows != M && addend->columns != N)) // FIX!!!
298 | {
299 | @throw [NSException exceptionWithName:@"MatrixSizeException"
300 | reason:@"Matrix size unsuitable for addition."
301 | userInfo:nil];
302 | }
303 | enum CBLAS_TRANSPOSE lT = transposeLeft ? CblasTrans : CblasNoTrans;
304 | enum CBLAS_TRANSPOSE rT = transposeRight ? CblasTrans : CblasNoTrans;
305 |
306 | Matrix *result = addend ?[Matrix matrixFromMatrix:addend] :[Matrix matrixOfRows:M
307 | columns:N];
308 | cblas_dgemm(CblasRowMajor, lT, rT, M,
309 | N, K, factor, matrix,
310 | lda, mt->matrix, ldb, 1,
311 | result->matrix, ldc);
312 | return result;
313 | }
314 |
315 | - (Matrix *)matrixByMultiplyingWithScalar:(double)ms
316 | {
317 | Matrix *product = [Matrix matrixFromMatrix:self];
318 | cblas_dscal(rows*columns, ms, product->matrix, 1);
319 | return product;
320 | }
321 |
322 | - (Matrix *)matrixByMultiplyingWithScalar:(double)ms AndAdding:(Matrix *)addend
323 | {
324 | if(columns != addend->columns || rows != addend->rows || sizeof(matrix) != sizeof(addend->matrix))
325 | @throw [NSException exceptionWithName:@"MatrixSizeException"
326 | reason:@"Matrix size mismatch."
327 | userInfo:nil];
328 | Matrix *sum = [Matrix matrixFromMatrix:addend];
329 | cblas_daxpy(rows*columns, ms, self->matrix, 1, sum->matrix, 1);
330 | return sum;
331 | }
332 |
333 | // End of actual calls to BLAS
334 | //
335 |
336 | - (Matrix *)matrixByNegating
337 | {
338 | Matrix *result = [Matrix dirtyMatrixOfRows:self->rows columns:self->columns];
339 | vDSP_vnegD(self->matrix, 1, result->matrix, 1, self.count);
340 | return result;
341 | }
342 |
343 | - (Matrix *)matrixBySquaring
344 | {
345 | Matrix *result = [Matrix dirtyMatrixOfRows:self->rows columns:self->columns];
346 | vDSP_vsqD(self->matrix, 1, result->matrix, 1, self.count);
347 | return result;
348 | }
349 |
350 | - (Matrix *)matrixByAbsolute
351 | {
352 | Matrix *result = [Matrix dirtyMatrixOfRows:self->rows columns:self->columns];
353 | vDSP_vabsD(self->matrix, 1, result->matrix, 1, self.count);
354 | return result;
355 | }
356 |
357 | - (Matrix *)matrixByTransposing
358 | {
359 | Matrix *trans = [Matrix dirtyMatrixOfRows:columns columns:rows];
360 | vDSP_mtransD(self->matrix, 1, trans->matrix, 1, trans->rows, trans->columns);
361 | return trans;
362 | }
363 |
364 | - (Matrix *)matrixByElementWiseMultiplyWith:(Matrix *)mt
365 | {
366 | Matrix *result = [self copy];
367 | [result elementWiseMultiply:mt];
368 | return result;
369 | }
370 |
371 | - (Matrix *)matrixByElementWisDivideBy:(Matrix *)mt
372 | {
373 | Matrix *result = [self copy];
374 | [result elementWiseDivide:mt];
375 | return result;
376 | }
377 |
378 | - (void)add:(Matrix *)addend
379 | {
380 | NSAssert(columns == addend->columns && rows == addend->rows, @"Matrix size error");
381 | vDSP_vaddD(self->matrix, 1, addend->matrix, 1, self->matrix, 1, self.count);
382 | }
383 |
384 | - (void)subtract:(Matrix *)subtrahend
385 | {
386 | NSAssert(columns == subtrahend->columns && rows == subtrahend->rows, @"Matrix size error");
387 | vDSP_vsubD(subtrahend->matrix, 1, self->matrix, 1, self->matrix, 1, self.count);
388 | }
389 |
390 | - (void)multiplyWithScalar:(double)ms
391 | {
392 | //cblas_dscal(rows*columns, ms, matrix, 1);
393 | vDSP_vsmulD(self->matrix, 1, &ms, self->matrix, 1, self.count);
394 | }
395 |
396 | - (void)negate
397 | {
398 | vDSP_vnegD(self->matrix, 1, self->matrix, 1, self.count);
399 | }
400 |
401 | - (void)square
402 | {
403 | vDSP_vsqD(self->matrix, 1, self->matrix, 1, self.count);
404 | }
405 |
406 | - (void)absolute
407 | {
408 | vDSP_vabsD(self->matrix, 1, self->matrix, 1, self.count);
409 | }
410 |
411 | - (void)elementWiseMultiply:(Matrix *)mt
412 | {
413 | NSAssert(columns == mt->columns && rows == mt->rows, @"Matrix size error");
414 | for (int i=0, j=self->rows * self->columns; imatrix[i] *= mt->matrix[i];
417 | }
418 | }
419 |
420 | - (void)elementWiseDivide:(Matrix *)mt
421 | {
422 | NSAssert(columns == mt->columns && rows == mt->rows, @"Matrix size error");
423 | for (int i=0, j=self->rows * self->columns; imatrix[i] /= mt->matrix[i];
426 | }
427 | }
428 |
429 | - (void)setDiagonalTo:(double)value
430 | {
431 | for (int i=0, j=MIN(rows, columns); imatrix[i * (columns + 1)] = value;
434 | }
435 | }
436 |
437 | - (double)trace
438 | {
439 | NSAssert(columns == rows, @"Matrix not square");
440 | double trace = 0;
441 | for (int i=0; irows * self->columns, self->matrix, 1, other->matrix, 1);
453 | }
454 |
455 | - (Matrix *)matrixByUnitizing
456 | {
457 | if(columns != 1 && rows != 1)
458 | @throw [NSException exceptionWithName:@"MatrixSizeException"
459 | reason:@"Unit can only be performed on vectors."
460 | userInfo:nil];
461 | int len = rows * columns;
462 | double sqsum = 0;
463 | for (int i=0; imatrix;
471 | for (int i=0; irows*self->columns, sizeof(double));
486 | memcpy(resArr, matrix, self->rows*self->columns*sizeof(double));
487 | return resArr;
488 | }
489 |
490 | - (NSArray *)numberArray
491 | {
492 | int length = self->rows * self->columns;
493 | NSMutableArray *result = [NSMutableArray arrayWithCapacity:length];
494 | for (int i=0; imatrix[i])];
497 | }
498 | return result;
499 | }
500 |
501 | - (Matrix *)diagonal
502 | {
503 | int minDim = MIN(rows, columns);
504 | Matrix *result = [Matrix matrixOfRows:minDim columns:1];
505 | for (int i=0; irows;
515 | }
516 |
517 | - (int)columns
518 | {
519 | return self->columns;
520 | }
521 |
522 | - (NSUInteger)count
523 | {
524 | return self->rows * self->columns;
525 | }
526 |
527 | - (double)sum
528 | {
529 | double sum = 0;
530 | NSUInteger j= [self count];
531 | for (int i=0; imatrix[i];
534 | }
535 | return sum;
536 | }
537 |
538 | - (double)product
539 | {
540 | double product = 1;
541 | NSUInteger j= [self count];
542 | for (int i=0; imatrix[i];
545 | }
546 | return product;
547 | }
548 |
549 | - (double)min
550 | {
551 | double min = DBL_MAX;
552 | NSUInteger j= [self count];
553 | for (int i=0; imatrix[i] < min) min = self->matrix[i];
556 | }
557 | return min;
558 | }
559 |
560 | - (double)max
561 | {
562 | double max = -DBL_MAX;
563 | NSUInteger j= [self count];
564 | for (int i=0; imatrix[i] > max) max = self->matrix[i];
567 | }
568 | return max;
569 | }
570 |
571 | - (BOOL)isSquareMatrix
572 | {
573 | return self->rows == self->columns;
574 | }
575 |
576 | - (BOOL)isEqual:(id)anObject {
577 | if (![anObject isKindOfClass:[self class]]) return NO;
578 | Matrix *other = (Matrix *)anObject;
579 | if (rows != other->rows || columns != other->columns) return NO;
580 | int arr_length = self->rows * self->columns;
581 | for (int i=0; imatrix[i]) return NO;
583 | }
584 | return YES;
585 | }
586 |
587 | - (NSUInteger)hash
588 | {
589 | // An implementation of
590 | // http://www.cse.yorku.ca/~oz/hash.html
591 | unsigned long hash = 5381;
592 | int c;
593 | char ch[10];
594 |
595 | for (int i=0, k=(int)self.count; imatrix[i];
598 | sprintf(ch , "%lf" , d);
599 | c = 0;
600 |
601 | for (int j=0; j<8; j++)
602 | {
603 | c = ch[j] - '0';
604 | hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
605 | }
606 | }
607 | hash = ((hash << 5) + hash) + self.rows;
608 | hash = ((hash << 5) + hash) + self.columns;
609 |
610 | return hash;
611 | }
612 |
613 | - (BOOL)isEqualToMatrix:(Matrix *)aMatrix tolerance:(double)tolerance
614 | {
615 | if (self->rows != aMatrix->rows || self->columns != aMatrix->columns) return NO;
616 | int arr_length = self->rows * self->columns;
617 | for (int i=0; imatrix[i]);
620 | if ( diff > tolerance ) return NO;
621 | }
622 | return YES;
623 | }
624 |
625 | - (NSString *)description {
626 | NSString *s = @"\n";
627 | for ( int i=0; ifreeData) free(self->matrix);
638 | }
639 |
640 | #pragma mark NSCoding Implementation
641 |
642 | - (void)encodeWithCoder:(NSCoder *)encoder
643 | {
644 | [encoder encodeBytes:(const uint8_t *)self->matrix
645 | length:self.count * sizeof(double)
646 | forKey:@"matrix"];
647 | [encoder encodeInt:self->rows forKey:@"rows"];
648 | [encoder encodeInt:self->columns forKey:@"columns"];
649 | }
650 |
651 | - (instancetype)initWithCoder:(NSCoder *)decoder
652 | {
653 | if (self = [super init])
654 | {
655 | self->freeData = YES;
656 | self->rows = [decoder decodeIntForKey:@"rows"];
657 | self->columns = [decoder decodeIntForKey:@"columns"];
658 | if ([decoder containsValueForKey:@"matrix"])
659 | {
660 | NSUInteger length;
661 | double *tempMatrix = (double *)[decoder decodeBytesForKey:@"matrix" returnedLength:&length];
662 | NSAssert(length == self.count * sizeof(double), @"Decoded matrix length differs");
663 | self->matrix = malloc(length);
664 | memcpy(self->matrix, tempMatrix, length);
665 | }
666 | else
667 | {
668 | // legacy decoding
669 | NSArray *matrixContent = [decoder decodeObjectForKey:@"matrixContent"];
670 | int len = self->rows*self->columns;
671 | self->matrix = malloc(len*sizeof(double));
672 | for (int i=0; imatrix[i] = [matrixContent[i] doubleValue];
675 | }
676 | }
677 | }
678 | return self;
679 | }
680 |
681 | - (instancetype)copyWithZone:(NSZone *)zone
682 | {
683 | Matrix *newMatrix = [Matrix matrixFromArray:self->matrix
684 | rows:self->rows
685 | columns:self->columns];
686 | return newMatrix;
687 | }
688 |
689 | @end
690 |
--------------------------------------------------------------------------------
/YCMatrix/NSArray+Matrix.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSArray+Matrix.h
3 | //
4 | // YCMatrix
5 | //
6 | // Copyright (c) 2013 - 2016 Ioannis (Yannis) Chatzikonstantinou. All rights reserved.
7 | // http://yconst.com
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | #import
28 | #import "Matrix.h"
29 |
30 | @interface NSArray (Matrix)
31 |
32 | /**
33 | Returns a matrix that contains the sum of all matrices
34 | contained in the receiver.
35 | */
36 | @property (readonly) Matrix *matrixSum;
37 |
38 | /**
39 | Returna a matrix that contains the element-wise product of
40 | all matrices contained in the receiver.
41 | */
42 | @property (readonly) Matrix *matrixProduct;
43 |
44 | /**
45 | Returns a matrix that contains the element-wise mean values of
46 | all matrices contained in the receiver.
47 | */
48 | @property (readonly) Matrix *matrixMean;
49 |
50 | /**
51 | Returns a matrix that contains the element-wise maximum values of
52 | all matrices contained in the receiver.
53 | */
54 | @property (readonly) Matrix *matrixMax;
55 |
56 | /**
57 | Returns a matrix that contains the element-wise minimum values of
58 | all matrices contained in the receiver.
59 | */
60 | @property (readonly) Matrix *matrixMin;
61 |
62 | @end
63 |
--------------------------------------------------------------------------------
/YCMatrix/NSArray+Matrix.m:
--------------------------------------------------------------------------------
1 | //
2 | // NSArray+Matrix.m
3 | //
4 | // YCMatrix
5 | //
6 | // Copyright (c) 2013 - 2016 Ioannis (Yannis) Chatzikonstantinou. All rights reserved.
7 | // http://yconst.com
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | #import "NSArray+Matrix.h"
28 |
29 | @implementation NSArray (Matrix)
30 |
31 | - (Matrix *)matrixSum
32 | {
33 | Matrix *result;
34 | for (Matrix *m in self)
35 | {
36 | NSAssert([m isKindOfClass:[Matrix class]], @"Array element is not a matrix");
37 | if (!result)
38 | {
39 | result = [m copy];
40 | }
41 | else
42 | {
43 | [result add:m];
44 | }
45 | }
46 | return result;
47 | }
48 |
49 | - (Matrix *)matrixMean
50 | {
51 | Matrix *result = [self matrixSum];
52 | [result multiplyWithScalar:1.0 / (double)self.count];
53 | return result;
54 | }
55 |
56 | - (Matrix *)matrixProduct
57 | {
58 | Matrix *result;
59 | for (Matrix *m in self)
60 | {
61 | NSAssert([m isKindOfClass:[Matrix class]], @"Array element is not a matrix");
62 | if (!result)
63 | {
64 | result = [m copy];
65 | }
66 | else
67 | {
68 | [result elementWiseMultiply:m];
69 | }
70 | }
71 | return result;
72 | }
73 |
74 | - (Matrix *)matrixMax
75 | {
76 | Matrix *result;
77 | for (Matrix *m in self)
78 | {
79 | NSAssert([m isKindOfClass:[Matrix class]], @"Array element is not a matrix");
80 | if (!result)
81 | {
82 | result = [m copy];
83 | }
84 | else
85 | {
86 | for (int i=0, n=(int)result.count; i
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | English
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIconFile
10 |
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | ${PRODUCT_NAME}
17 | CFBundlePackageType
18 | FMWK
19 | CFBundleShortVersionString
20 | 0.6.16
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1
25 | NSHumanReadableCopyright
26 | Copyright © 2013 - 2016 Ioannis Chatzikonstantinou. All rights reserved.
27 | NSPrincipalClass
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/YCMatrix/YCMatrix.h:
--------------------------------------------------------------------------------
1 | //
2 | // YCMatrix.h
3 | //
4 | // YCMatrix
5 | //
6 | // Copyright (c) 2013 - 2016 Ioannis (Yannis) Chatzikonstantinou. All rights reserved.
7 | // http://yconst.com
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | #import
28 |
29 | #import "Matrix+Advanced.h"
30 | #import "Matrix+Manipulate.h"
31 | #import "Matrix+Map.h"
32 | #import "NSArray+Matrix.h"
--------------------------------------------------------------------------------
/YCMatrix/en.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /* Localized versions of Info.plist keys */
2 |
3 |
--------------------------------------------------------------------------------
/YCMatrixTests/YCMatrixAdvancedTests.m:
--------------------------------------------------------------------------------
1 | //
2 | // YCMatrixAdvancedTests.m
3 | //
4 | // YCMatrix
5 | //
6 | // Copyright (c) 2013 - 2016 Ioannis (Yannis) Chatzikonstantinou. All rights reserved.
7 | // http://yconst.com
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | @import XCTest;
28 | @import YCMatrix;
29 | #import
30 |
31 | #define ARC4RANDOM_MAX 0x100000000
32 |
33 | // Definitions for convenience logging functions (without date/object and title logging).
34 | #define CleanNSLog(FORMAT, ...) fprintf(stderr,"%s\n", [[NSString stringWithFormat:FORMAT, ##__VA_ARGS__] UTF8String]);
35 | #define TitleNSLog(FORMAT, ...) fprintf(stderr,"\n%s\n_____________________________________\n\n", [[NSString stringWithFormat:FORMAT, ##__VA_ARGS__] UTF8String]);
36 |
37 | @interface YCMatrixAdvancedTests : XCTestCase
38 |
39 | @end
40 |
41 | @implementation YCMatrixAdvancedTests
42 |
43 | - (void)testUniformRandom
44 | {
45 | Matrix *lower = [Matrix matrixFromNSArray:@[@10, @5, @5, @10] rows:1 columns:4];
46 | Matrix *upper = [Matrix matrixFromNSArray:@[@20, @6, @10, @30] rows:1 columns:4];
47 | Matrix *random = [Matrix uniformRandomLowerBound:lower upperBound:upper];
48 | CleanNSLog(@"%@", random);
49 | XCTAssert([random i:0 j:0]>10);
50 | XCTAssert([random i:0 j:0]<20);
51 | XCTAssert([random i:0 j:1]>5);
52 | XCTAssert([random i:0 j:1]<6);
53 | XCTAssert([random i:0 j:2]>5);
54 | XCTAssert([random i:0 j:2]<10);
55 | XCTAssert([random i:0 j:3]>10);
56 | XCTAssert([random i:0 j:3]<30);
57 | }
58 |
59 | - (void)testNormalRandomColumns
60 | {
61 | Matrix *mean = [Matrix matrixFromNSArray:@[@10, @5, @5, @10] rows:1 columns:4];
62 | Matrix *variance = [Matrix matrixFromNSArray:@[@1, @2, @3, @4] rows:1 columns:4];
63 | Matrix *random = [Matrix normalRandomMean:mean variance:variance count:20000];
64 | Matrix *actualMean = [random meansOfColumns];
65 | Matrix *actualVariance = [random variancesOfColumns];
66 |
67 | XCTAssert([mean isEqualToMatrix:actualMean tolerance:0.1]);
68 | XCTAssert([variance isEqualToMatrix:actualVariance tolerance:0.1]);
69 | }
70 |
71 | - (void)testNormalRandomRows
72 | {
73 | Matrix *mean = [Matrix matrixFromNSArray:@[@10, @5, @5, @10] rows:4 columns:1];
74 | Matrix *variance = [Matrix matrixFromNSArray:@[@1, @2, @3, @4] rows:4 columns:1];
75 | Matrix *random = [Matrix normalRandomMean:mean variance:variance count:20000];
76 | Matrix *actualMean = [random meansOfRows];
77 | Matrix *actualVariance = [random variancesOfRows];
78 |
79 | XCTAssert([mean isEqualToMatrix:actualMean tolerance:0.1]);
80 | XCTAssert([variance isEqualToMatrix:actualVariance tolerance:0.1]);
81 | }
82 |
83 | - (void)testSVD
84 | {
85 | TitleNSLog(@"Singular Value Decomposition");
86 | int m = 10;
87 | int n = 6;
88 | double *orig_array = _mm_malloc(m*n*sizeof(double), 64);
89 | for (int i=0, j=m*n; irows, po->columns);
110 | CleanNSLog(@"%@",po);
111 | CleanNSLog(@"PseudoInverse: %ix%i",poi->rows, poi->columns);
112 | CleanNSLog(@"%@",poi);
113 |
114 | double pinv_orig_array2[6] = { 1.0, 2.0,
115 | 3.0, 4.0, 5.0, 6.0};
116 | Matrix *po2 = [Matrix matrixFromArray:pinv_orig_array2 rows:3 columns:2];
117 | Matrix *poi2 = [po2 pseudoInverse];
118 | CleanNSLog(@"Original: %ix%i",po2->rows, po2->columns);
119 | CleanNSLog(@"%@",po2);
120 | CleanNSLog(@"PseudoInverse: %ix%i",poi2->rows, poi2->columns);
121 | CleanNSLog(@"%@",poi2);
122 | }
123 |
124 | - (void)testCholesky
125 | {
126 | TitleNSLog(@"Cholesky Decomposition Test (A: 3x3)");
127 | double simple_array[9] = { 4, 12, -16,
128 | 12, 37, -43,
129 | -16, -43, 98}; // Test from Wikipedia
130 | Matrix *A = [Matrix matrixFromArray:simple_array rows:3 columns:3];
131 | CleanNSLog(@"Original Matrix A: %@",A);
132 | Matrix *ch = [A matrixByCholesky];
133 | CleanNSLog(@"Cholesky Decomposition of A: %@",ch);
134 | XCTAssertEqualObjects([ch matrixByTransposingAndMultiplyingWithLeft:ch], A,
135 | @"Error with Cholesky decomposition");
136 |
137 | TitleNSLog(@"Cholesky Decomposition Test (Correlation Matrix: 4x4)");
138 |
139 | double correlation_array[16] = { 1, 0.5, 0.5, 0.5,
140 | 0.5, 1, 0.5, 0.5,
141 | 0.5, 0.5, 1, 0.5,
142 | 0.5, 0.5, 0.5, 1 };
143 | Matrix *correlationMatrix = [Matrix matrixFromArray:correlation_array rows:4 columns:4];
144 |
145 | CleanNSLog(@"Correlation Matrix: %@",correlationMatrix);
146 | Matrix *correlationCholesky = [correlationMatrix matrixByCholesky];
147 | CleanNSLog(@"Cholesky Decomposition of Correlation Matrix: %@",correlationCholesky);
148 | Matrix *response = [correlationCholesky matrixByTransposingAndMultiplyingWithLeft:correlationCholesky];
149 | XCTAssert([response isEqualToMatrix:correlationMatrix tolerance:1E-9],
150 | @"Error with Cholesky decomposition");
151 | }
152 |
153 | - (void)testSobol
154 | {
155 | // test integrand from Joe and Kuo paper ... integrates to 1
156 |
157 | int count = 1000;
158 |
159 | TitleNSLog(@"Sobol Sequence Test");
160 |
161 | Matrix *lower = [Matrix matrixOfRows:10 columns:1 value:0.0];
162 | Matrix *upper = [Matrix matrixOfRows:10 columns:1 value:1.0];
163 |
164 | Matrix *sequence = [Matrix sobolSequenceLowerBound:lower upperBound:upper count:count];
165 |
166 | NSArray *columns = [sequence columnsAsNSArray];
167 |
168 | double acc = 0;
169 |
170 | for (Matrix *column in columns)
171 | {
172 | double f = 1;
173 | for (int j = 1; j <= column.count; ++j) {
174 | double cj = pow((double) j, 0.3333333333333333333);
175 | f *= (fabs(4*column->matrix[j-1] - 2) + cj) / (1 + cj);
176 | }
177 | acc += f;
178 | }
179 | acc /= count;
180 |
181 | XCTAssertEqualWithAccuracy(acc, 1.0, 0.01);
182 | CleanNSLog(@"%f", acc);
183 | }
184 |
185 | - (void)testHalton
186 | {
187 | // test integrand from Joe and Kuo paper ... integrates to 1
188 |
189 | int count = 1000;
190 |
191 | TitleNSLog(@"Halton Sequence Test");
192 |
193 | Matrix *lower = [Matrix matrixOfRows:10 columns:1 value:0.0];
194 | Matrix *upper = [Matrix matrixOfRows:10 columns:1 value:1.0];
195 |
196 | Matrix *sequence = [Matrix haltonSequenceWithLowerBound:lower upperBound:upper count:count];
197 |
198 | NSArray *columns = [sequence columnsAsNSArray];
199 |
200 | double acc = 0;
201 |
202 | for (Matrix *column in columns)
203 | {
204 | double f = 1;
205 | for (int j = 1; j <= column.count; ++j) {
206 | double cj = pow((double) j, 0.3333333333333333333);
207 | f *= (fabs(4*column->matrix[j-1] - 2) + cj) / (1 + cj);
208 | }
209 | acc += f;
210 | }
211 | acc /= count;
212 |
213 | XCTAssertEqualWithAccuracy(acc, 1.0, 0.01);
214 | CleanNSLog(@"%f", acc);
215 | }
216 |
217 | - (void)testMeans
218 | {
219 | TitleNSLog(@"Mean Test");
220 | double mean_array[12] = { 1.0, 1.0, 1.0,
221 | 4.0, -4.0, 2.0,
222 | -153.0, 614.0, 33.0,
223 | -100.0, 100.0, 0.0};
224 | double columnMeanTargetArray[3] = { -62.0, 177.75, 9.0 };
225 | double rowMeantargetArray[4] = { 1.0, 2.0/3.0, 494.0/3.0, 0.0 };
226 | Matrix *columnMeanTargetMatrix = [Matrix matrixFromArray:columnMeanTargetArray rows:1 columns:3];
227 | Matrix *rowMeanTargetMatrix = [Matrix matrixFromArray:rowMeantargetArray rows:4 columns:1];
228 | Matrix *meanMatrix = [Matrix matrixFromArray:mean_array rows:4 columns:3];
229 | Matrix *rowMeans = [meanMatrix meansOfRows];
230 | Matrix *columnMeans = [meanMatrix meansOfColumns];
231 | XCTAssertEqualObjects(rowMeans, rowMeanTargetMatrix,
232 | @"Error in calculating Row Means.");
233 | XCTAssertEqualObjects(columnMeans, columnMeanTargetMatrix,
234 | @"Error in calculating Column Means.");
235 | CleanNSLog(@"%@", rowMeans);
236 | CleanNSLog(@"%@", columnMeans);
237 | }
238 |
239 | - (void)testVariances
240 | {
241 | TitleNSLog(@"Variances Test");
242 | double var_array[12] = { 1.0, 10.0, 1.0,
243 | 2.0, -6.0, -5.0,
244 | -153.0, 34.0, 15.67,
245 | -110.1, 1900.0, 0.0};
246 | double columnVarTargetArray[3] = { 6207.66917, 890777.00000, 79.16722 };
247 | double rowVartargetArray[4] = { 27.00, 19.00, 10625.76, 1277104.00 };
248 | Matrix *columnVarTargetMatrix = [Matrix matrixFromArray:columnVarTargetArray rows:1 columns:3];
249 | Matrix *rowVarTargetMatrix = [Matrix matrixFromArray:rowVartargetArray rows:4 columns:1];
250 | Matrix *varMatrix = [Matrix matrixFromArray:var_array rows:4 columns:3];
251 | Matrix *rowVars = [varMatrix sampleVariancesOfRows];
252 | Matrix *columnVars = [varMatrix sampleVariancesOfColumns];
253 | XCTAssert([rowVars isEqualToMatrix:rowVarTargetMatrix tolerance:0.01],
254 | @"Error in calculating Row Variances.");
255 | XCTAssert([columnVars isEqualToMatrix:columnVarTargetMatrix tolerance:0.01],
256 | @"Error in calculating Column Variances.");
257 | CleanNSLog(@"%@", rowVarTargetMatrix);
258 | CleanNSLog(@"%@", columnVarTargetMatrix);
259 | CleanNSLog(@"%@", rowVars);
260 | CleanNSLog(@"%@", columnVars);
261 | }
262 |
263 | - (void)testMins
264 | {
265 | TitleNSLog(@"Minimums Test");
266 | double var_array[12] = { 1.0, 10.0, 1.0,
267 | 2.0, -6.0, -5.0,
268 | -153.0, 34.0, 15.67,
269 | -110.1, 1900.0, 0.0};
270 | double columnMinTargetArray[3] = { -153.0, -6.0, -5.0 };
271 | double rowMintargetArray[4] = { 1.0, -6.0, -153.0, -110.1 };
272 | Matrix *columnMinTargetMatrix = [Matrix matrixFromArray:columnMinTargetArray rows:1 columns:3];
273 | Matrix *rowMinTargetMatrix = [Matrix matrixFromArray:rowMintargetArray rows:4 columns:1];
274 | Matrix *minMatrix = [Matrix matrixFromArray:var_array rows:4 columns:3];
275 | Matrix *rowMins = [minMatrix minimumsOfRows];
276 | Matrix *columnMins = [minMatrix minimumsOfColumns];
277 | XCTAssert([rowMins isEqualToMatrix:rowMinTargetMatrix tolerance:0.01],
278 | @"Error in calculating Row Minimums.");
279 | XCTAssert([columnMins isEqualToMatrix:columnMinTargetMatrix tolerance:0.01],
280 | @"Error in calculating Column Minimums.");
281 | CleanNSLog(@"%@", rowMinTargetMatrix);
282 | CleanNSLog(@"%@", columnMinTargetMatrix);
283 | CleanNSLog(@"%@", rowMins);
284 | CleanNSLog(@"%@", columnMins);
285 | }
286 |
287 |
288 | - (void)testMaxs
289 | {
290 | TitleNSLog(@"Maximums Test");
291 | double var_array[12] = { 1.0, 10.0, -1.0,
292 | 2.0, -6.0, -5.0,
293 | -153.0, 34.0, -15.67,
294 | -110.1, 1900.0, -0.1};
295 | double columnMaxTargetArray[3] = { 2.0, 1900.0, -0.1 };
296 | double rowMaxTargetArray[4] = { 10.0, 2.00, 34.0, 1900.00 };
297 | Matrix *columnMaxTargetMatrix = [Matrix matrixFromArray:columnMaxTargetArray rows:1 columns:3];
298 | Matrix *rowMaxTargetMatrix = [Matrix matrixFromArray:rowMaxTargetArray rows:4 columns:1];
299 | Matrix *maxMatrix = [Matrix matrixFromArray:var_array rows:4 columns:3];
300 | Matrix *rowMaxs = [maxMatrix maximumsOfRows];
301 | Matrix *columnMaxs = [maxMatrix maximumsOfColumns];
302 | XCTAssert([rowMaxs isEqualToMatrix:rowMaxTargetMatrix tolerance:0.01],
303 | @"Error in calculating Row Maximums.");
304 | XCTAssert([columnMaxs isEqualToMatrix:columnMaxTargetMatrix tolerance:0.01],
305 | @"Error in calculating Column Maximums.");
306 | CleanNSLog(@"%@", rowMaxTargetMatrix);
307 | CleanNSLog(@"%@", columnMaxTargetMatrix);
308 | CleanNSLog(@"%@", rowMaxs);
309 | CleanNSLog(@"%@", columnMaxs);
310 | }
311 |
312 | - (void)testEigenvalues
313 | {
314 | TitleNSLog(@"Eigenvalues Test");
315 | double simple_array[9] = { 1.000, 2.000, 3.000,
316 | 5.000, 10.000, 15.000,
317 | 0.100, 0.200, 0.300 };
318 | double ref_array[3] = {11.3, 0.0, 0.0};
319 | Matrix *original = [Matrix matrixFromArray:simple_array rows:3 columns:3];
320 | Matrix *ev = [original realEigenvalues];
321 | Matrix *evRef = [Matrix matrixFromArray:ref_array rows:1 columns:3];
322 | CleanNSLog(@"%@", ev);
323 | XCTAssert([ev isEqualToMatrix:evRef tolerance:1E-4], @"Error with Eigenvalue calculation");
324 | }
325 |
326 | - (void)testEigenValuesandVectors
327 | {
328 | TitleNSLog(@"Eigenvectors Test");
329 | double simple_array[9] = { 35.000, 100.000, 42.000,
330 | 87.000, 72.000, 97.000,
331 | 28.000, 21.000, 55.000 };
332 | double left_result[9] = {-0.6062, -0.8280, -0.6705,
333 | -0.7489, 0.5461, -0.2132,
334 | -0.2678, 0.1268, 0.7106};
335 | Matrix *original = [Matrix matrixFromArray:simple_array rows:3 columns:3];
336 | Matrix *rightTarget = [Matrix matrixFromArray:left_result rows:3 columns:3];
337 | NSDictionary *e = [original eigenvectorsAndEigenvalues];
338 | XCTAssert([e[@"Right Eigenvectors"]
339 | isEqualToMatrix:rightTarget tolerance:1E-3]);
340 | }
341 |
342 | - (void)testDeterminant
343 | {
344 | TitleNSLog(@"Determinant Test");
345 | double simple_array[16] = { 1.0, 2.0, 3.0, 4.0,
346 | 5.0, 6.0, 7.0, 8.0,
347 | 2.0, 6.0, 4.0, 8.0,
348 | 3.0, 1.0, 1.0, 2.0 };
349 | Matrix *original = [Matrix matrixFromArray:simple_array rows:4 columns:4];
350 | double det = [original determinant];
351 | double detRef = 72;
352 | CleanNSLog(@"%f", det);
353 | XCTAssertEqual(det, detRef, @"Error with Determinant calculation");
354 | }
355 |
356 | - (void)testBernoulli
357 | {
358 | TitleNSLog(@"Bernoulli Distribution Test");
359 |
360 | Matrix *ones = [Matrix matrixOfRows:20 columns:20 value:1];
361 | Matrix *onesWithProbability = [ones copy];
362 | [onesWithProbability bernoulli];
363 | XCTAssertEqualObjects(ones, onesWithProbability);
364 |
365 | Matrix *zeroes = [Matrix matrixOfRows:20 columns:20 value:0];
366 | Matrix *zeroesWithProbability = [zeroes copy];
367 | [zeroesWithProbability bernoulli];
368 | XCTAssertEqualObjects(zeroes, zeroesWithProbability);
369 | }
370 |
371 |
372 | @end
373 |
--------------------------------------------------------------------------------
/YCMatrixTests/YCMatrixManipulateTests.m:
--------------------------------------------------------------------------------
1 | //
2 | // ManipulateTests.m
3 | //
4 | // YCMatrix
5 | //
6 | // Copyright (c) 2013 - 2016 Ioannis (Yannis) Chatzikonstantinou. All rights reserved.
7 | // http://yconst.com
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | @import XCTest;
28 | @import YCMatrix;
29 |
30 | #define ARC4RANDOM_MAX 0x100000000
31 |
32 | // Definitions for convenience logging functions (without date/object and title logging).
33 | #define CleanNSLog(FORMAT, ...) fprintf(stderr,"%s\n", [[NSString stringWithFormat:FORMAT, ##__VA_ARGS__] UTF8String]);
34 | #define TitleNSLog(FORMAT, ...) fprintf(stderr,"\n%s\n_____________________________________\n\n", [[NSString stringWithFormat:FORMAT, ##__VA_ARGS__] UTF8String]);
35 |
36 | @interface YCMatrixManipulateTests : XCTestCase
37 |
38 | @end
39 |
40 | @implementation YCMatrixManipulateTests
41 |
42 | - (void)testRowRetrieval
43 | {
44 | TitleNSLog(@"Matrix row retrieval");
45 | double testmrarr[6] = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 };
46 | Matrix *testmr = [Matrix matrixFromArray:testmrarr rows:2 columns:3];
47 | Matrix *rowm = [testmr row:1]; // This is being tested.
48 | CleanNSLog(@"%@", rowm);
49 | double templatermatrixarr[3] = { 4.0, 5.0, 6.0 };
50 | Matrix *templatemr = [Matrix matrixFromArray:templatermatrixarr rows:1 columns:3];
51 | XCTAssertTrue([rowm isEqual:templatemr], @"Matrix row retrieval error.");
52 | }
53 |
54 | - (void)testRowReference
55 | {
56 | TitleNSLog(@"Matrix row referencing");
57 | double testmrarr[6] = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 };
58 | Matrix *testmr = [Matrix matrixFromArray:testmrarr rows:2 columns:3];
59 | Matrix *rowm = [testmr rowReference:1]; // This is being tested.
60 | CleanNSLog(@"%@", rowm);
61 | double templatermatrixarr[3] = { 4.0, 5.0, 6.0 };
62 | Matrix *templatemr = [Matrix matrixFromArray:templatermatrixarr rows:1 columns:3];
63 | XCTAssertTrue([rowm isEqual:templatemr], @"Matrix row retrieval error.");
64 | }
65 |
66 | - (void)testRowVectorReference
67 | {
68 | TitleNSLog(@"Matrix row referencing vector");
69 | double testmrarr[6] = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 };
70 | Matrix *testmr = [Matrix matrixFromArray:testmrarr rows:2 columns:3];
71 | Matrix *rowm = [testmr rowReferenceVector:1]; // This is being tested.
72 | CleanNSLog(@"%@", rowm);
73 | double templatermatrixarr[3] = { 4.0, 5.0, 6.0 };
74 | Matrix *templatemr = [Matrix matrixFromArray:templatermatrixarr rows:3 columns:1];
75 | XCTAssertTrue([rowm isEqual:templatemr], @"Matrix row retrieval error.");
76 | }
77 |
78 | - (void)testMultiplyRowReference
79 | {
80 | Matrix *source = [Matrix matrixFromNSArray:@[@21.600,
81 | @15.000,
82 | @1.700,
83 | @3.000,
84 | @44.000,
85 | @12.000,
86 | @69.000] rows:1 columns:7];
87 | Matrix *row = [source rowReference:0];
88 | row->rows = row->columns;
89 | row->columns = 1;
90 |
91 | Matrix *result = [row matrixByTransposingAndMultiplyingWithRight:row];
92 | XCTAssertEqual(result.rows, 1);
93 | XCTAssertEqual(result.columns, 1);
94 | double val = [result i:0 j:0];
95 | XCTAssertEqual(val, 7544.450);
96 | }
97 |
98 | - (void)testMultipleRowRetrieval
99 | {
100 | TitleNSLog(@"Multiple matrix row retrieval");
101 | double testmrarr[9] = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0 };
102 | Matrix *testmr = [Matrix matrixFromArray:testmrarr rows:3 columns:3];
103 | NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1, 2)];
104 | Matrix *rowm = [testmr rows:indexSet]; // This is being tested.
105 | CleanNSLog(@"%@", rowm);
106 | double templatermatrixarr[6] = { 4.0, 5.0, 6.0, 7.0, 8.0, 9.0 };
107 | Matrix *templatemr = [Matrix matrixFromArray:templatermatrixarr rows:2 columns:3];
108 | XCTAssertTrue([rowm isEqual:templatemr], @"Multiple matrix row retrieval error.");
109 | }
110 |
111 | - (void)testColumnRetrieval
112 | {
113 | TitleNSLog(@"Matrix column retrieval");
114 | double testmcarr[6] = { 1.0, 4.0, 2.0, 5.0, 3.0, 6.0 };
115 | Matrix *testmc = [Matrix matrixFromArray:testmcarr rows:3 columns:2];
116 | Matrix *columnm = [testmc column:1]; // This is being tested.
117 | CleanNSLog(@"%@", columnm);
118 | double templatecmatrixarr[3] = { 4.0, 5.0, 6.0 };
119 | Matrix *templatemc = [Matrix matrixFromArray:templatecmatrixarr rows:3 columns:1];
120 | XCTAssertTrue([columnm isEqual:templatemc], @"Matrix column retrieval error.");
121 | }
122 |
123 | - (void)testMultipleColumnRetrieval
124 | {
125 | TitleNSLog(@"Multiple matrix column retrieval");
126 | double testmcarr[9] = { 1.0, 4.0, 7.0, 2.0, 5.0, 8.0, 3.0, 6.0, 9.0 };
127 | Matrix *testmc = [Matrix matrixFromArray:testmcarr rows:3 columns:3];
128 | NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1, 2)];
129 | Matrix *columnm = [testmc columns:indexSet]; // This is being tested.
130 | CleanNSLog(@"%@", columnm);
131 | double templatecmatrixarr[6] = { 4.0, 7.0, 5.0, 8.0, 6.0, 9.0 };
132 | Matrix *templatemc = [Matrix matrixFromArray:templatecmatrixarr rows:3 columns:2];
133 | XCTAssertTrue([columnm isEqual:templatemc], @"Multiple matrix column retrieval error.");
134 | }
135 |
136 | - (void)testRowsToNSArray
137 | {
138 | TitleNSLog(@"Rows as NSArray");
139 | double rowsColumnsArrayTest[12] = { 1.0, 2.0, 3.0, 4.0,
140 | 5.0, 6.0, 7.0, 8.0,
141 | 9.0, 10.0, 11.0, 12.0};
142 | double firstRow[4] = { 1.0, 2.0, 3.0, 4.0 };
143 | Matrix *firstRowMatrix = [Matrix matrixFromArray:firstRow rows:1 columns:4];
144 | double secondRow[4] = { 5.0, 6.0, 7.0, 8.0 };
145 | Matrix *secondRowMatrix = [Matrix matrixFromArray:secondRow rows:1 columns:4];
146 | double thirdRow[4] = { 9.0, 10.0, 11.0, 12.0 };
147 | Matrix *thirdRowMatrix = [Matrix matrixFromArray:thirdRow rows:1 columns:4];
148 |
149 | Matrix *rowsColumnsTestMatrix = [Matrix matrixFromArray:rowsColumnsArrayTest rows:3 columns:4];
150 | NSArray *rowsTestRows = [rowsColumnsTestMatrix rowsAsNSArray];
151 | XCTAssertEqualObjects([rowsTestRows objectAtIndex:0], firstRowMatrix, @"Error in conversion to rows array(1).");
152 | XCTAssertEqualObjects([rowsTestRows objectAtIndex:1], secondRowMatrix, @"Error in conversion to rows array(2).");
153 | XCTAssertEqualObjects([rowsTestRows objectAtIndex:2], thirdRowMatrix, @"Error in conversion to rows array(3).");
154 | }
155 |
156 | // All code under test must be linked into the Unit Test bundle
157 | - (void)testColumnsToNSArray
158 | {
159 | TitleNSLog(@"Columns as NSArray");
160 | double rowsColumnsArrayTest[12] = { 1.0, 2.0, 3.0, 4.0,
161 | 5.0, 6.0, 7.0, 8.0,
162 | 9.0, 10.0, 11.0, 12.0};
163 | double firstColumn[3] = { 1.0, 5.0, 9.0 };
164 | Matrix *firstColumnMatrix = [Matrix matrixFromArray:firstColumn rows:3 columns:1];
165 | double secondColumn[3] = { 2.0, 6.0, 10.0 };
166 | Matrix *secondColumnMatrix = [Matrix matrixFromArray:secondColumn rows:3 columns:1];
167 | double thirdColumn[3] = { 3.0, 7.0, 11.0 };
168 | Matrix *thirdColumnMatrix = [Matrix matrixFromArray:thirdColumn rows:3 columns:1];
169 | double fourthColumn[3] = { 4.0, 8.0, 12.0 };
170 | Matrix *fourthColumnMatrix = [Matrix matrixFromArray:fourthColumn rows:3 columns:1];
171 |
172 | Matrix *rowsColumnsTestMatrix = [Matrix matrixFromArray:rowsColumnsArrayTest rows:3 columns:4];
173 | NSArray *columnsTestColumns = [rowsColumnsTestMatrix columnsAsNSArray];
174 | XCTAssertEqualObjects([columnsTestColumns objectAtIndex:0], firstColumnMatrix,
175 | @"Error in conversion to columns array(1).");
176 | XCTAssertEqualObjects([columnsTestColumns objectAtIndex:1], secondColumnMatrix,
177 | @"Error in conversion to columns array(2).");
178 | XCTAssertEqualObjects([columnsTestColumns objectAtIndex:2], thirdColumnMatrix,
179 | @"Error in conversion to columns array(3).");
180 | XCTAssertEqualObjects([columnsTestColumns objectAtIndex:3], fourthColumnMatrix,
181 | @"Error in conversion to columns array(4).");
182 | }
183 |
184 | - (void)testSubMatrices
185 | {
186 | TitleNSLog(@"Sub-Matrix Extraction Test");
187 | double simple_array[16] = { 1.0, 2.0, 3.0, 4.0,
188 | 5.0, 6.0, 7.0, 8.0,
189 | 9.0, 10.0, 11.0, 12.0,
190 | 13.0, 14.0, 15.0, 16.0 };
191 | Matrix *original = [Matrix matrixFromArray:simple_array rows:4 columns:4];
192 |
193 | double expected_rows[8] = { 5.0, 6.0, 7.0, 8.0,
194 | 9.0, 10.0, 11.0, 12.0 };
195 | Matrix *expectedRows = [Matrix matrixFromArray:expected_rows rows:2 columns:4];
196 | Matrix *resultRows = [original matrixWithRowsInRange:NSMakeRange(1, 2)];
197 | CleanNSLog(@"%@", resultRows);
198 | XCTAssertEqualObjects(expectedRows, resultRows, @"Error while extracting rows to sub-matrix");
199 |
200 | double expected_columns[8] = { 2.0, 3.0,
201 | 6.0, 7.0,
202 | 10.0, 11.0,
203 | 14.0, 15.0 };
204 | Matrix *expectedColumns = [Matrix matrixFromArray:expected_columns rows:4 columns:2];
205 | Matrix *resultColumns = [original matrixWithColumnsInRange:NSMakeRange(1, 2)];
206 | CleanNSLog(@"%@", resultColumns);
207 | XCTAssertEqualObjects(expectedColumns, resultColumns, @"Error while extracting columns to sub-matrix");
208 | }
209 |
210 | - (void)testRowAndColumnAdditionsSubtractions
211 | {
212 | TitleNSLog(@"Row / Column Additions / Subtractions");
213 | double simple_array[16] = { 1.0, 2.0, 3.0, 4.0,
214 | 5.0, 6.0, 7.0, 8.0,
215 | 9.0, 10.0, 11.0, 12.0,
216 | 13.0, 14.0, 15.0, 16.0 };
217 | Matrix *original = [Matrix matrixFromArray:simple_array rows:4 columns:4];
218 | double element[4] = { 4.0, 1.0, -40.0, -22.5 };
219 | Matrix *column = [Matrix matrixFromArray:element rows:4 columns:1];
220 | Matrix *row = [Matrix matrixFromArray:element rows:1 columns:4];
221 | Matrix *step1 = [original matrixByAddingRow:row];
222 | Matrix *step2 = [step1 matrixByAddingColumn:column];
223 | Matrix *step3 = [step2 matrixBySubtractingColumn:column];
224 | Matrix *step4 = [step3 matrixBySubtractingRow:row];
225 |
226 | XCTAssertEqualObjects(original, step4, @"Error while Adding / Subtracting Rows / Columns");
227 | }
228 |
229 | - (void)testRowRemoval
230 | {
231 | double original[16] = {
232 | 16.0, 2.0, 3.0, 13.0,
233 | 5.0, 11.0, 10.0, 8.0,
234 | 9.0, 7.0, 6.0, 12.0,
235 | 4.0, 14.0, 15.0, 0.05
236 | };
237 |
238 | double test[12] = {
239 | 16.0, 2.0, 3.0, 13.0,
240 | 9.0, 7.0, 6.0, 12.0,
241 | 4.0, 14.0, 15.0, 0.05
242 | };
243 |
244 | Matrix *originalMatrix = [Matrix matrixFromArray:original rows:4 columns:4];
245 | Matrix *resultMatrix = [originalMatrix removeRow:1];
246 | Matrix *testMatrix = [Matrix matrixFromArray:test rows:3 columns:4];
247 | XCTAssertEqualObjects(testMatrix, resultMatrix);
248 | CleanNSLog(@"Original:\n%@", originalMatrix);
249 | CleanNSLog(@"Test:\n%@", testMatrix);
250 | CleanNSLog(@"-removeRow: Result:\n%@", resultMatrix);
251 | }
252 |
253 | - (void)testColumnRemoval
254 | {
255 | double original[16] = {
256 | 16.0, 2.0, 3.0, 13.0,
257 | 5.0, 11.0, 10.0, 8.0,
258 | 9.0, 7.0, 6.0, 12.0,
259 | 4.0, 14.0, 15.0, 0.05
260 | };
261 |
262 | double test[12] = {
263 | 16.0, 3.0, 13.0,
264 | 5.0, 10.0, 8.0,
265 | 9.0, 6.0, 12.0,
266 | 4.0, 15.0, 0.05
267 | };
268 |
269 | Matrix *originalMatrix = [Matrix matrixFromArray:original rows:4 columns:4];
270 | Matrix *resultMatrix = [originalMatrix removeColumn:1];
271 | Matrix *testMatrix = [Matrix matrixFromArray:test rows:4 columns:3];
272 | XCTAssertEqualObjects(testMatrix, resultMatrix);
273 | CleanNSLog(@"Original:\n%@", originalMatrix);
274 | CleanNSLog(@"Test:\n%@", testMatrix);
275 | CleanNSLog(@"-removeColumn: Result:\n%@", resultMatrix);
276 | }
277 |
278 | - (void)testRowShuffling
279 | {
280 | double original[20] = {
281 | 1.0, 10.0, 100.0, 1000.0, 10000.0,
282 | 2.0, 20.0, 200.0, 2000.0, 20000.0,
283 | 3.0, 30.0, 300.0, 3000.0, 30000.0,
284 | 4.0, 40.0, 400.0, 4000.0, 40000.0
285 | };
286 |
287 | Matrix *originalMatrix = [Matrix matrixFromArray:original rows:4 columns:5];
288 | CleanNSLog(@"%@", originalMatrix);
289 | Matrix *shuffledMatrix = [originalMatrix copy];
290 | [shuffledMatrix shuffleRows];
291 | CleanNSLog(@"%@", shuffledMatrix);
292 | // Sums of columns should remain the same
293 | XCTAssertEqualObjects([originalMatrix sumsOfColumns], [shuffledMatrix sumsOfColumns]);
294 |
295 | shuffledMatrix = [originalMatrix matrixByShufflingRows];
296 | CleanNSLog(@"%@", shuffledMatrix);
297 | // Sums of columns should remain the same
298 | XCTAssertEqualObjects([originalMatrix sumsOfColumns], [shuffledMatrix sumsOfColumns]);
299 | }
300 |
301 | - (void)testColumnShuffling
302 | {
303 | double original[20] = {
304 | 1.0, 10.0, 100.0, 1000.0, 10000.0,
305 | 2.0, 20.0, 200.0, 2000.0, 20000.0,
306 | 3.0, 30.0, 300.0, 3000.0, 30000.0,
307 | 4.0, 40.0, 400.0, 4000.0, 40000.0
308 | };
309 |
310 | Matrix *originalMatrix = [Matrix matrixFromArray:original rows:4 columns:5];
311 | CleanNSLog(@"%@", originalMatrix);
312 | Matrix *shuffledMatrix = [originalMatrix copy];
313 | [shuffledMatrix shuffleColumns];
314 | CleanNSLog(@"%@", shuffledMatrix);
315 | // Sums of rows should remain the same
316 | XCTAssertEqualObjects([originalMatrix sumsOfRows], [shuffledMatrix sumsOfRows]);
317 |
318 | shuffledMatrix = [originalMatrix matrixByShufflingColumns];
319 | CleanNSLog(@"%@", shuffledMatrix);
320 | // Sums of columns should remain the same
321 | XCTAssertEqualObjects([originalMatrix sumsOfRows], [shuffledMatrix sumsOfRows]);
322 | }
323 |
324 | - (void)testRowSplit
325 | {
326 | double original[35] = {
327 | 1.0, 10.0, 100.0, 1000.0, 10000.0,
328 | 2.0, 20.0, 200.0, 2000.0, 20000.0,
329 | 3.0, 30.0, 300.0, 3000.0, 30000.0,
330 | 4.0, 40.0, 400.0, 4000.0, 40000.0,
331 | 5.0, 50.0, 500.0, 5000.0, 50000.0,
332 | 6.0, 60.0, 600.0, 6000.0, 60000.0,
333 | 7.0, 70.0, 700.0, 7000.0, 70000.0
334 | };
335 | Matrix *originalMatrix = [Matrix matrixFromArray:original rows:7 columns:5];
336 |
337 | double res0[15] = {
338 | 1.0, 10.0, 100.0, 1000.0, 10000.0,
339 | 2.0, 20.0, 200.0, 2000.0, 20000.0,
340 | 3.0, 30.0, 300.0, 3000.0, 30000.0
341 | };
342 | Matrix *res0Matrix = [Matrix matrixFromArray:res0 rows:3 columns:5];
343 |
344 | double res1[10] = {
345 | 4.0, 40.0, 400.0, 4000.0, 40000.0,
346 | 5.0, 50.0, 500.0, 5000.0, 50000.0
347 | };
348 | Matrix *res1Matrix = [Matrix matrixFromArray:res1 rows:2 columns:5];
349 |
350 | double res2[10] = {
351 | 6.0, 60.0, 600.0, 6000.0, 60000.0,
352 | 7.0, 70.0, 700.0, 7000.0, 70000.0
353 | };
354 | Matrix *res2Matrix = [Matrix matrixFromArray:res2 rows:2 columns:5];
355 |
356 | NSMutableIndexSet *indexes = [NSMutableIndexSet indexSet];
357 | [indexes addIndex:3];
358 | [indexes addIndex:5];
359 | NSArray *segments = [originalMatrix rowWiseSplitAtIndexes:indexes];
360 |
361 | XCTAssertEqualObjects(segments[0], res0Matrix, @"Segments not equal");
362 | XCTAssertEqualObjects(segments[1], res1Matrix, @"Segments not equal");
363 | XCTAssertEqualObjects(segments[2], res2Matrix, @"Segments not equal");
364 | }
365 |
366 | - (void)testColumnSplit
367 | {
368 | double original[28] = {
369 | 1.0, 10.0, 100.0, 1000.0, 10000.0, 10001.0, 10002.0,
370 | 2.0, 20.0, 200.0, 2000.0, 20000.0, 20001.0, 20002.0,
371 | 3.0, 30.0, 300.0, 3000.0, 30000.0, 30001.0, 30002.0,
372 | 4.0, 40.0, 400.0, 4000.0, 40000.0, 40001.0, 40002.0
373 | };
374 | Matrix *originalMatrix = [Matrix matrixFromArray:original rows:4 columns:7];
375 |
376 | double res0[12] = {
377 | 1.0, 10.0, 100.0,
378 | 2.0, 20.0, 200.0,
379 | 3.0, 30.0, 300.0,
380 | 4.0, 40.0, 400.0
381 | };
382 | Matrix *res0Matrix = [Matrix matrixFromArray:res0 rows:4 columns:3];
383 |
384 | double res1[8] = {
385 | 1000.0, 10000.0,
386 | 2000.0, 20000.0,
387 | 3000.0, 30000.0,
388 | 4000.0, 40000.0
389 | };
390 | Matrix *res1Matrix = [Matrix matrixFromArray:res1 rows:4 columns:2];
391 |
392 | double res2[8] = {
393 | 10001.0, 10002.0,
394 | 20001.0, 20002.0,
395 | 30001.0, 30002.0,
396 | 40001.0, 40002.0
397 | };
398 | Matrix *res2Matrix = [Matrix matrixFromArray:res2 rows:4 columns:2];
399 |
400 | NSMutableIndexSet *indexes = [NSMutableIndexSet indexSet];
401 | [indexes addIndex:3];
402 | [indexes addIndex:5];
403 | NSArray *segments = [originalMatrix columnWiseSplitAtIndexes:indexes];
404 |
405 | XCTAssertEqualObjects(segments[0], res0Matrix, @"Segments not equal");
406 | XCTAssertEqualObjects(segments[1], res1Matrix, @"Segments not equal");
407 | XCTAssertEqualObjects(segments[2], res2Matrix, @"Segments not equal");
408 | }
409 |
410 | - (void)testRowPartitioningExact
411 | {
412 | double original[20] = {
413 | 1.0, 10.0, 100.0, 1000.0, 10000.0,
414 | 2.0, 20.0, 200.0, 2000.0, 20000.0,
415 | 3.0, 30.0, 300.0, 3000.0, 30000.0,
416 | 4.0, 40.0, 400.0, 4000.0, 40000.0
417 | };
418 | Matrix *originalMatrix = [Matrix matrixFromArray:original rows:4 columns:5];
419 |
420 | double partition0[10] = {
421 | 1.0, 10.0, 100.0, 1000.0, 10000.0,
422 | 2.0, 20.0, 200.0, 2000.0, 20000.0
423 | };
424 | Matrix *partition0Matrix = [Matrix matrixFromArray:partition0 rows:2 columns:5];
425 |
426 | double partition1[10] = {
427 | 3.0, 30.0, 300.0, 3000.0, 30000.0,
428 | 4.0, 40.0, 400.0, 4000.0, 40000.0
429 | };
430 | Matrix *partition1Matrix = [Matrix matrixFromArray:partition1 rows:2 columns:5];
431 |
432 | NSArray *partitions = [originalMatrix rowWisePartition:2];
433 | XCTAssertEqualObjects(partitions[0], partition0Matrix, @"Partitions not equal");
434 | XCTAssertEqualObjects(partitions[1], partition1Matrix, @"Partitions not equal");
435 | }
436 |
437 | - (void)testRowPartitioningRemainder
438 | {
439 | double original[25] = {
440 | 1.0, 10.0, 100.0, 1000.0, 10000.0,
441 | 2.0, 20.0, 200.0, 2000.0, 20000.0,
442 | 3.0, 30.0, 300.0, 3000.0, 30000.0,
443 | 4.0, 40.0, 400.0, 4000.0, 40000.0,
444 | 5.0, 50.0, 500.0, 5000.0, 50000.0
445 | };
446 | Matrix *originalMatrix = [Matrix matrixFromArray:original rows:5 columns:5];
447 |
448 | double partition0[10] = {
449 | 1.0, 10.0, 100.0, 1000.0, 10000.0,
450 | 2.0, 20.0, 200.0, 2000.0, 20000.0
451 | };
452 | Matrix *partition0Matrix = [Matrix matrixFromArray:partition0 rows:2 columns:5];
453 |
454 | double partition1[10] = {
455 | 3.0, 30.0, 300.0, 3000.0, 30000.0,
456 | 4.0, 40.0, 400.0, 4000.0, 40000.0
457 | };
458 | Matrix *partition1Matrix = [Matrix matrixFromArray:partition1 rows:2 columns:5];
459 |
460 | double partition2[5] = {
461 | 5.0, 50.0, 500.0, 5000.0, 50000.0
462 | };
463 | Matrix *partition2Matrix = [Matrix matrixFromArray:partition2 rows:1 columns:5];
464 |
465 | NSArray *partitions = [originalMatrix rowWisePartition:2];
466 | XCTAssertEqualObjects(partitions[0], partition0Matrix, @"Partitions not equal");
467 | XCTAssertEqualObjects(partitions[1], partition1Matrix, @"Partitions not equal");
468 | XCTAssertEqualObjects(partitions[2], partition2Matrix, @"Partitions not equal");
469 | }
470 |
471 | - (void)testColumnPartitioningExact
472 | {
473 | double original[20] = {
474 | 1.0, 10.0, 100.0, 1000.0,
475 | 2.0, 20.0, 200.0, 2000.0,
476 | 3.0, 30.0, 300.0, 3000.0,
477 | 4.0, 40.0, 400.0, 4000.0,
478 | 5.0, 50.0, 500.0, 5000.0
479 | };
480 | Matrix *originalMatrix = [Matrix matrixFromArray:original rows:5 columns:4];
481 |
482 | double partition0[10] = {
483 | 1.0, 10.0,
484 | 2.0, 20.0,
485 | 3.0, 30.0,
486 | 4.0, 40.0,
487 | 5.0, 50.0
488 | };
489 | Matrix *partition0Matrix = [Matrix matrixFromArray:partition0 rows:5 columns:2];
490 |
491 | double partition1[10] = {
492 | 100.0, 1000.0,
493 | 200.0, 2000.0,
494 | 300.0, 3000.0,
495 | 400.0, 4000.0,
496 | 500.0, 5000.0
497 | };
498 | Matrix *partition1Matrix = [Matrix matrixFromArray:partition1 rows:5 columns:2];
499 |
500 | NSArray *partitions = [originalMatrix columnWisePartition:2];
501 | XCTAssertEqualObjects(partitions[0], partition0Matrix, @"Partitions not equal");
502 | XCTAssertEqualObjects(partitions[1], partition1Matrix, @"Partitions not equal");
503 | }
504 |
505 | - (void)testColumnPartitioningRemainder
506 | {
507 | double original[25] = {
508 | 1.0, 10.0, 100.0, 1000.0, 10000.0,
509 | 2.0, 20.0, 200.0, 2000.0, 20000.0,
510 | 3.0, 30.0, 300.0, 3000.0, 30000.0,
511 | 4.0, 40.0, 400.0, 4000.0, 40000.0,
512 | 5.0, 50.0, 500.0, 5000.0, 50000.0
513 | };
514 | Matrix *originalMatrix = [Matrix matrixFromArray:original rows:5 columns:5];
515 |
516 | double partition0[10] = {
517 | 1.0, 10.0,
518 | 2.0, 20.0,
519 | 3.0, 30.0,
520 | 4.0, 40.0,
521 | 5.0, 50.0
522 | };
523 | Matrix *partition0Matrix = [Matrix matrixFromArray:partition0 rows:5 columns:2];
524 |
525 | double partition1[10] = {
526 | 100.0, 1000.0,
527 | 200.0, 2000.0,
528 | 300.0, 3000.0,
529 | 400.0, 4000.0,
530 | 500.0, 5000.0
531 | };
532 | Matrix *partition1Matrix = [Matrix matrixFromArray:partition1 rows:5 columns:2];
533 |
534 | double partition2[5] = {
535 | 10000.0,
536 | 20000.0,
537 | 30000.0,
538 | 40000.0,
539 | 50000.0
540 | };
541 | Matrix *partition2Matrix = [Matrix matrixFromArray:partition2 rows:5 columns:1];
542 |
543 | NSArray *partitions = [originalMatrix columnWisePartition:2];
544 | XCTAssertEqualObjects(partitions[0], partition0Matrix, @"Partitions not equal");
545 | XCTAssertEqualObjects(partitions[1], partition1Matrix, @"Partitions not equal");
546 | XCTAssertEqualObjects(partitions[2], partition2Matrix, @"Partitions not equal");
547 | }
548 |
549 | - (void)testApplyMatrix
550 | {
551 | // Test by applying matrices of different values and checking the sum
552 | Matrix *large = [Matrix matrixOfRows:100 columns:100 value:1];
553 | Matrix *small = [Matrix matrixOfRows:10 columns:10 value:0];
554 | XCTAssert(large.sum == 10000, @"Sum incorrect");
555 | [large applyMatrix:small i:50 j:50];
556 | XCTAssert(large.sum == 9900, @"Sum incorrect");
557 | [large applyMatrix:small i:10 j:10];
558 | XCTAssert(large.sum == 9800, @"Sum incorrect");
559 | [large applyMatrix:small i:15 j:15];
560 | XCTAssert(large.sum == 9725, @"Sum incorrect");
561 | [large applyMatrix:small i:55 j:55];
562 | XCTAssert(large.sum == 9650, @"Sum incorrect");
563 | [large applyMatrix:small i:55 j:55];
564 | XCTAssert(large.sum == 9650, @"Sum incorrect");
565 | [large applyMatrix:small i:50 j:55];
566 | XCTAssert(large.sum == 9625, @"Sum incorrect");
567 | }
568 |
569 | @end
570 |
--------------------------------------------------------------------------------
/YCMatrixTests/YCMatrixMapTests.m:
--------------------------------------------------------------------------------
1 | //
2 | // YCMatrixMapTests.m
3 | //
4 | // YCMatrix
5 | //
6 | // Copyright (c) 2013 - 2016 Ioannis (Yannis) Chatzikonstantinou. All rights reserved.
7 | // http://yconst.com
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | @import XCTest;
28 | @import YCMatrix;
29 |
30 | #define ARC4RANDOM_MAX 0x100000000
31 |
32 | // Definitions for convenience logging functions (without date/object and title logging).
33 | #define CleanNSLog(FORMAT, ...) fprintf(stderr,"%s\n", [[NSString stringWithFormat:FORMAT, ##__VA_ARGS__] UTF8String]);
34 | #define TitleNSLog(FORMAT, ...) fprintf(stderr,"\n%s\n_____________________________________\n\n", [[NSString stringWithFormat:FORMAT, ##__VA_ARGS__] UTF8String]);
35 |
36 | @interface YCMatrixMapTests : XCTestCase
37 |
38 | @end
39 |
40 | @implementation YCMatrixMapTests
41 |
42 | - (void)testMinMaxMapping
43 | {
44 | Matrix *low = [Matrix matrixOfRows:4 columns:5 value:3];
45 | Matrix *high = [Matrix matrixOfRows:4 columns:5 value:8];
46 | Matrix *original = [Matrix uniformRandomLowerBound:low upperBound:high];
47 | Matrix *mapping = [original rowWiseMapToDomain:YCMakeDomain(0, 1) basis:MinMax];
48 | Matrix *inverse = [original rowWiseInverseMapFromDomain:YCMakeDomain(0, 1) basis:MinMax];
49 | Matrix *mapped = [original matrixByRowWiseMapUsing:mapping];
50 | Matrix *copy = [mapped matrixByRowWiseMapUsing:inverse];
51 | XCTAssert([copy isEqualToMatrix:original tolerance:1E-9], @"Mapping failed");
52 | }
53 |
54 | - (void)testStDevMapping
55 | {
56 | Matrix *low = [Matrix matrixOfRows:4 columns:5 value:3];
57 | Matrix *high = [Matrix matrixOfRows:4 columns:5 value:8];
58 | Matrix *original = [Matrix uniformRandomLowerBound:low upperBound:high];
59 | Matrix *mapping = [original rowWiseMapToDomain:YCMakeDomain(-1, 2) basis:StDev];
60 | Matrix *inverse = [original rowWiseInverseMapFromDomain:YCMakeDomain(-1, 2) basis:StDev];
61 | Matrix *mapped = [original matrixByRowWiseMapUsing:mapping];
62 | Matrix *copy = [mapped matrixByRowWiseMapUsing:inverse];
63 | XCTAssert([copy isEqualToMatrix:original tolerance:1E-9], @"Mapping failed");
64 | }
65 |
66 | @end
67 |
--------------------------------------------------------------------------------
/YCMatrixTests/YCMatrixNSArrayTests.m:
--------------------------------------------------------------------------------
1 | //
2 | // YCMatrixNSArrayTests.m
3 | // YCMatrix
4 | //
5 | // Created by Ioannis Chatzikonstantinou on 14/1/16.
6 | // Copyright © 2016 Ioannis Chatzikonstantinou. All rights reserved.
7 | //
8 |
9 | @import XCTest;
10 | @import YCMatrix;
11 |
12 | @interface YCMatrixNSArrayTests : XCTestCase
13 |
14 | @end
15 |
16 | @implementation YCMatrixNSArrayTests
17 |
18 | - (void)testArrayMin
19 | {
20 | double v1[10] = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19};
21 | double v2[10] = {19, 18, 17, 16, 15, 14, 13, 12, 11, 10};
22 | double v3[10] = {20, 20, 20, 10, 10, 10, 10, 20, 20, 20};
23 | double vt[10] = {10, 11, 12, 10, 10, 10, 10, 12, 11, 10};
24 |
25 | Matrix *m1 = [Matrix matrixFromArray:v1 rows:10 columns:1];
26 | Matrix *m2 = [Matrix matrixFromArray:v2 rows:10 columns:1];
27 | Matrix *m3 = [Matrix matrixFromArray:v3 rows:10 columns:1];
28 | Matrix *mt = [Matrix matrixFromArray:vt rows:10 columns:1];
29 |
30 | NSArray *matrixArray = @[m1, m2, m3];
31 |
32 | Matrix *mins = [matrixArray matrixMin];
33 |
34 | XCTAssert([mins isEqualTo:mt], @"Error in computing min matrix of array");
35 | }
36 |
37 | - (void)testArrayMax
38 | {
39 | double v1[10] = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19};
40 | double v2[10] = {19, 18, 17, 16, 15, 14, 13, 12, 11, 10};
41 | double v3[10] = {20, 20, 20, 10, 10, 10, 10, 20, 20, 20};
42 | double vt[10] = {20, 20, 20, 16, 15, 15, 16, 20, 20, 20};
43 |
44 | Matrix *m1 = [Matrix matrixFromArray:v1 rows:10 columns:1];
45 | Matrix *m2 = [Matrix matrixFromArray:v2 rows:10 columns:1];
46 | Matrix *m3 = [Matrix matrixFromArray:v3 rows:10 columns:1];
47 | Matrix *mt = [Matrix matrixFromArray:vt rows:10 columns:1];
48 |
49 | NSArray *matrixArray = @[m1, m2, m3];
50 |
51 | Matrix *maxs = [matrixArray matrixMax];
52 |
53 | XCTAssert([maxs isEqualTo:mt], @"Error in computing max matrix of array");
54 | }
55 |
56 | @end
57 |
--------------------------------------------------------------------------------
/YCMatrixTests/YCMatrixPerformanceTests.m:
--------------------------------------------------------------------------------
1 | //
2 | // YCMatrixPerformanceTests.m
3 | // YCMatrix
4 | //
5 | // Created by Ioannis Chatzikonstantinou on 28/1/16.
6 | // Copyright © 2016 Ioannis Chatzikonstantinou. All rights reserved.
7 | //
8 |
9 | #import
10 | @import YCMatrix;
11 |
12 | @interface YCMatrixPerformanceTests : XCTestCase
13 |
14 | @end
15 |
16 | @implementation YCMatrixPerformanceTests
17 |
18 | - (void)testVDSPAddPerformance {
19 |
20 | Matrix *lower = [Matrix matrixOfRows:10000 columns:2000 value:0];
21 | Matrix *upper = [Matrix matrixOfRows:10000 columns:2000 value:1];
22 |
23 | Matrix *A = [Matrix uniformRandomLowerBound:lower upperBound:upper];
24 | Matrix *B = [Matrix uniformRandomLowerBound:lower upperBound:upper];
25 |
26 | [self measureBlock:^{
27 | [A matrixByAdding:B];
28 | }];
29 | }
30 |
31 | - (void)testBLASMultiplyScalarAndAddPerformance {
32 |
33 | Matrix *lower = [Matrix matrixOfRows:10000 columns:2000 value:0];
34 | Matrix *upper = [Matrix matrixOfRows:10000 columns:2000 value:1];
35 |
36 | Matrix *A = [Matrix uniformRandomLowerBound:lower upperBound:upper];
37 | Matrix *B = [Matrix uniformRandomLowerBound:lower upperBound:upper];
38 |
39 | [self measureBlock:^{
40 | [A matrixByMultiplyingWithScalar:1 AndAdding:B];
41 | }];
42 | }
43 |
44 | - (void)testCAddPerformance {
45 |
46 | Matrix *lower = [Matrix matrixOfRows:10000 columns:2000 value:0];
47 | Matrix *upper = [Matrix matrixOfRows:10000 columns:2000 value:1];
48 |
49 | Matrix *A = [Matrix uniformRandomLowerBound:lower upperBound:upper];
50 | Matrix *B = [Matrix uniformRandomLowerBound:lower upperBound:upper];
51 |
52 | double *ma = A->matrix;
53 | double *mb = B->matrix;
54 |
55 | [self measureBlock:^{
56 |
57 | // Need to include memory allocation as well here
58 | Matrix *C = [Matrix matrixLike:A];
59 | double *mc = C->matrix;
60 |
61 | #pragma vector always
62 | for (int i=0, j=(int)A.count; imatrix;
105 | double *mb = B->matrix;
106 |
107 | [self measureBlock:^{
108 |
109 | // Need to include memory allocation as well here
110 | Matrix *C = [Matrix matrixLike:A];
111 | double *mc = C->matrix;
112 |
113 | #pragma vector always
114 | for (int i=0, j=(int)A.count; irows*A->columns, 10, A->matrix, 1);
131 | }];
132 | }
133 |
134 | - (void)testVDSPMultiplyScalarPerformance
135 | {
136 | Matrix *lower = [Matrix matrixOfRows:10000 columns:2000 value:0];
137 | Matrix *upper = [Matrix matrixOfRows:10000 columns:2000 value:1];
138 |
139 | Matrix *A = [Matrix uniformRandomLowerBound:lower upperBound:upper];
140 |
141 | [self measureBlock:^{
142 | [A multiplyWithScalar:10];
143 | }];
144 | }
145 |
146 | @end
147 |
--------------------------------------------------------------------------------
/YCMatrixTests/YCMatrixTests-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundlePackageType
14 | BNDL
15 | CFBundleShortVersionString
16 | 1.0
17 | CFBundleSignature
18 | ????
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/YCMatrixTests/YCMatrixTests.m:
--------------------------------------------------------------------------------
1 | //
2 | // YCMatrixTests.m
3 | //
4 | // YCMatrix
5 | //
6 | // Copyright (c) 2013 - 2016 Ioannis (Yannis) Chatzikonstantinou. All rights reserved.
7 | // http://yconst.com
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 |
27 | //References for this Document:
28 | // http://en.wikipedia.org/wiki/Cholesky_decomposition
29 |
30 | @import XCTest;
31 | @import YCMatrix;
32 |
33 | #define ARC4RANDOM_MAX 0x100000000
34 |
35 | // Definitions for convenience logging functions (without date/object and title logging).
36 | #define CleanNSLog(FORMAT, ...) fprintf(stderr,"%s\n", [[NSString stringWithFormat:FORMAT, ##__VA_ARGS__] UTF8String]);
37 | #define TitleNSLog(FORMAT, ...) fprintf(stderr,"\n%s\n_____________________________________\n\n", [[NSString stringWithFormat:FORMAT, ##__VA_ARGS__] UTF8String]);
38 |
39 | @interface YCMatrixTests : XCTestCase
40 |
41 | @end
42 |
43 | @implementation YCMatrixTests
44 |
45 | - (void)testIdentity
46 | {
47 | TitleNSLog(@"Identity Matrix Test");
48 | double idm_ref_array[15] = { 1.0, 0.0, 0.0,
49 | 0.0, 1.0, 0.0,
50 | 0.0, 0.0, 1.0,
51 | 0.0, 0.0, 0.0,
52 | 0.0, 0.0, 0.0 };
53 | Matrix *idmRef = [Matrix matrixFromArray:idm_ref_array rows:5 columns:3];
54 | Matrix *idm = [Matrix identityOfRows:5 columns:3];
55 | CleanNSLog(@"%@",idm);
56 | XCTAssertEqualObjects(idm, idmRef, @"Error in creating Identity Matrix");
57 | }
58 |
59 | - (void)testOnes
60 | {
61 | Matrix *template = [Matrix matrixOfRows:5 columns:5 value:1];
62 | Matrix *match = [Matrix onesLike:template];
63 | XCTAssertEqualObjects(template, match, @"Error in creating matrix of ones.");
64 | }
65 |
66 | - (void)testAbsolute
67 | {
68 | Matrix *absoluteMatrix = [Matrix uniformRandomRows:10 columns:10 domain:YCMakeDomain(-1.0, 1.0)];
69 | [absoluteMatrix absolute];
70 | for (int i=0, k=absoluteMatrix.rows; i= 0, @"Negative value in absolute matrix");
75 | }
76 | }
77 | }
78 |
79 | - (void)testRetrieval
80 | {
81 | TitleNSLog(@"Simple Array Test");
82 | double simple_array[9] = { 1.0, 2.0, 3.0,
83 | 4.0, 5.0, 6.0,
84 | 7.0, 8.0, 9.0 };
85 | Matrix *simple_matrix = [Matrix matrixFromArray:simple_array rows:3 columns:3];
86 | CleanNSLog(@"%@",simple_matrix);
87 |
88 | // Perform various get item tests
89 | TitleNSLog(@"Get Items Test");
90 | CleanNSLog(@"Value at 0,0: %f",[simple_matrix valueAtRow:0 column:0]);
91 | CleanNSLog(@"Value at 1,1: %f",[simple_matrix valueAtRow:1 column:1]);
92 | CleanNSLog(@"Value at 2,1: %f",[simple_matrix valueAtRow:2 column:1]);
93 | CleanNSLog(@"Value at 1,2: %f",[simple_matrix valueAtRow:1 column:2]);
94 | CleanNSLog(@"Value at 2,2: %f",[simple_matrix valueAtRow:2 column:2]);
95 | XCTAssertTrue([simple_matrix valueAtRow:0 column:0] == 1.0, @"GetValue error!");
96 | XCTAssertTrue([simple_matrix valueAtRow:1 column:0] == 4.0, @"GetValue error!");
97 | XCTAssertTrue([simple_matrix valueAtRow:2 column:0] == 7.0, @"GetValue error!");
98 | XCTAssertTrue([simple_matrix valueAtRow:0 column:1] == 2.0, @"GetValue error!");
99 | XCTAssertTrue([simple_matrix valueAtRow:0 column:2] == 3.0, @"GetValue error!");
100 | XCTAssertTrue([simple_matrix valueAtRow:2 column:1] == 8.0, @"GetValue error!");
101 | XCTAssertTrue([simple_matrix i:0 j:1] == 2.0, @"GetValue error!");
102 | XCTAssertTrue([simple_matrix i:0 j:2] == 3.0, @"GetValue error!");
103 | XCTAssertTrue([simple_matrix i:2 j:1] == 8.0, @"GetValue error!");
104 | }
105 |
106 | - (void)testDiagonal
107 | {
108 | double source_array[12] = { 1.0, 2.0, 3.0,
109 | 4.0, 5.0, 6.0,
110 | 7.0, 8.0, 9.0,
111 | 1.0, 2.0, 6.0};
112 | Matrix *sourceMatrix = [Matrix matrixFromArray:source_array rows:4 columns:3];
113 | double target_array[3] = { 1.0, 5.0, 9.0 };
114 | Matrix *targetMatrix = [Matrix matrixFromArray:target_array rows:3 columns:1];
115 | Matrix *diagonal = [sourceMatrix diagonal];
116 | XCTAssertEqualObjects(diagonal, targetMatrix, @"Error in deriving diagonal.");
117 | }
118 |
119 | - (void)testTransposition
120 | {
121 | TitleNSLog(@"Transposition");
122 | double matrix_orig_arr[6] = { 1.0, 2.0, 3.0,
123 | 4.0, 5.0, 6.0 };
124 | double matrix_trans_arr[6] = { 1.0, 4.0,
125 | 2.0, 5.0,
126 | 3.0, 6.0 };
127 | Matrix *orig = [Matrix matrixFromArray:matrix_orig_arr rows:2 columns:3];
128 | Matrix *trans = [Matrix matrixFromArray:matrix_trans_arr rows:3 columns:2];
129 | Matrix *trans2 = [orig matrixByTransposing];
130 | CleanNSLog(@"%@",orig);
131 | CleanNSLog(@"%@",trans);
132 | CleanNSLog(@"%@",trans2);
133 | XCTAssertEqualObjects(trans, trans2, @"M^T != Mt");
134 | XCTAssertEqualObjects(orig, [[orig matrixByTransposing] matrixByTransposing], @"M^T^T != M");
135 | }
136 |
137 | - (void)testDot
138 | {
139 | TitleNSLog(@"Dot Product");
140 | double vectorarray[3] = { 1.0, 2.0, 3.0 };
141 | Matrix *Vector = [Matrix matrixFromArray:vectorarray rows:3 columns:1];
142 | double dotp = [Vector dotWith:Vector];
143 | CleanNSLog(@"Dot Product: %f",dotp);
144 | XCTAssertEqual(dotp, 14.0, @"Error in calculating dot product");
145 | }
146 |
147 | - (void)testTrace
148 | {
149 | TitleNSLog(@"Trace");
150 | double matrix_array[9] = { 1.0, 2.0, 3.0,
151 | 4.0, 5.0, 6.0,
152 | 7.0, 8.0, 9.0 };
153 | Matrix *tracetestm = [Matrix matrixFromArray:matrix_array rows:3 columns:3];
154 | double trace = [[tracetestm matrixByMultiplyingWithRight:tracetestm] trace];
155 | CleanNSLog(@"%f",trace);
156 | XCTAssertEqual(trace, 261.000, @"Trace is not correct!");
157 | }
158 |
159 | - (void)testAdditionScalarMultiplication
160 | {
161 | TitleNSLog(@"Addition and Scalar Multiplication");
162 | double matrix_array[9] = { 1.0, 2.0, 3.0,
163 | 4.0, 5.0, 6.0,
164 | 7.0, 8.0, 9.0 };
165 | Matrix *testm1 = [Matrix matrixFromArray:matrix_array rows:3 columns:3];
166 | Matrix *testm2 = [Matrix matrixFromMatrix:testm1];
167 | Matrix *testm_add = [testm1 matrixByAdding:testm2];
168 | Matrix *testm_ms = [testm1 matrixByMultiplyingWithScalar:2];
169 | XCTAssertEqualObjects(testm_ms, testm_add, @"M+M != 2*M");
170 |
171 | TitleNSLog(@"Matrix Multiplication");
172 | CleanNSLog(@"Test Matrix 1: %ix%i",testm1->rows, testm1->columns);
173 | CleanNSLog(@"Test Matrix 2: %ix%i",testm2->rows, testm2->columns);
174 | Matrix *multResult = [testm1 matrixByMultiplyingWithRight:testm2];
175 | CleanNSLog(@"Resulting Matrix: %ix%i",multResult->rows, multResult->columns);
176 | CleanNSLog(@"%@",multResult);
177 | }
178 |
179 | - (void)testVDSPAdd
180 | {
181 | Matrix *A = [Matrix matrixOfRows:10 columns:1 value:1];
182 | Matrix *B = [Matrix matrixOfRows:10 columns:1 value:1];
183 |
184 | Matrix *C = [A matrixByAdding:B];
185 | Matrix *T = [Matrix matrixOfRows:10 columns:1 value:2];
186 | XCTAssertEqualObjects(C, T, @"Matrix subtraction failed");
187 | [A add:B];
188 | XCTAssertEqualObjects(A, T, @"Matrix subtraction failed");
189 | }
190 |
191 | - (void)testVDSPSubtract
192 | {
193 | Matrix *A = [Matrix matrixOfRows:10 columns:1 value:0];
194 | Matrix *B = [Matrix matrixOfRows:10 columns:1 value:1];
195 |
196 | Matrix *C = [A matrixBySubtracting:B];
197 | Matrix *T = [Matrix matrixOfRows:10 columns:1 value:-1];
198 | XCTAssertEqualObjects(C, T, @"Matrix subtraction failed");
199 | [A subtract:B];
200 | XCTAssertEqualObjects(A, T, @"Matrix subtraction failed");
201 | }
202 |
203 | - (void)testTransposedMultiply
204 | {
205 | double simple_array[6] = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 };
206 | Matrix *A = [Matrix matrixFromArray:simple_array rows:2 columns:3];
207 | CleanNSLog(@"%@",A);
208 |
209 | double simple_array_2[6] = { 2.0, 3.0, 1.0, 4.0, 0.0, 5.0 };
210 | Matrix *B = [Matrix matrixFromArray:simple_array_2 rows:3 columns:2];
211 | CleanNSLog(@"%@",B);
212 |
213 | Matrix *C = [A matrixByMultiplyingWithRight:B AndTransposing:YES];
214 | CleanNSLog(@"%@",C);
215 | }
216 |
217 | - (void)testGEMMPerformance
218 | {
219 | Matrix *A = [Matrix uniformRandomRows:1000 columns:1000 domain:YCMakeDomain(0, 10)];
220 | Matrix *B = [Matrix uniformRandomRows:1000 columns:1000 domain:YCMakeDomain(0, 10)];
221 |
222 | [self measureBlock:^{
223 | [A matrixByMultiplyingWithRight:B];
224 | }];
225 | }
226 |
227 | - (void)testGEMM
228 | {
229 | Matrix *A = [Matrix uniformRandomRows:10 columns:10 domain:YCMakeDomain(0, 10)];
230 | Matrix *B = [Matrix uniformRandomRows:10 columns:10 domain:YCMakeDomain(0, 10)];
231 |
232 | Matrix *ACopy = [A copy];
233 | Matrix *BCopy = [B copy];
234 | NSLog(@"%@", [A matrixByMultiplyingWithRight:B]);
235 | XCTAssertEqualObjects(A, ACopy);
236 | XCTAssertEqualObjects(B, BCopy);
237 | }
238 |
239 | - (void)testDictionaryContainsKey
240 | {
241 | NSMutableDictionary *dict = [NSMutableDictionary dictionary];
242 | Matrix *m1 = [Matrix uniformRandomRows:1 columns:5 domain:YCMakeDomain(0, 1)];
243 | [dict setObject:@1 forKey:[m1 copy]];
244 | XCTAssert([dict[m1] isEqual:@1], @"Matrix dictionary key lookup unsuccessful");
245 | XCTAssertNil(dict[[m1 matrixByTransposing]], @"Value of transpose not nil");
246 | }
247 |
248 | - (void)testHash
249 | {
250 | Matrix *m1 = [Matrix uniformRandomRows:50 columns:50 domain:YCMakeDomain(0, 1)];
251 | NSLog(@"%lu", m1.hash);
252 | }
253 |
254 | - (void)testSerialization
255 | {
256 | Matrix *testm1 = [Matrix uniformRandomRows:10 columns:10 domain:YCMakeDomain(0, 10)];
257 | NSData *serialized = [NSKeyedArchiver archivedDataWithRootObject:testm1];
258 | Matrix *recovered = [NSKeyedUnarchiver unarchiveObjectWithData:serialized];
259 | XCTAssertEqualObjects(testm1, recovered, @"Error in deserialization");
260 | }
261 |
262 | @end
263 |
--------------------------------------------------------------------------------
/YCMatrixTests/en.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /* Localized versions of Info.plist keys */
2 |
3 |
--------------------------------------------------------------------------------
/ycmatrix.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yconst/YCMatrix/c169e2e3fbe40e80b38ac272462b0f731815e174/ycmatrix.png
--------------------------------------------------------------------------------