├── README.md ├── extract_sample.lua ├── iOSClient ├── iOSClient.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata │ │ │ ├── kurtjacobs.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ │ │ └── woffle_laptop.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ ├── kurtjacobs.xcuserdatad │ │ ├── xcdebugger │ │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ │ ├── iOSClient.xcscheme │ │ │ └── xcschememanagement.plist │ │ └── woffle_laptop.xcuserdatad │ │ └── xcschemes │ │ ├── iOSClient.xcscheme │ │ └── xcschememanagement.plist ├── iOSClient │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── Info.plist │ ├── THESDiskFile.h │ ├── THESDiskFile.m │ ├── THESLayer.h │ ├── THESLayer.m │ ├── ViewController.h │ ├── ViewController.m │ └── main.m ├── iOSClientTests │ ├── Info.plist │ └── iOSClientTests.m └── iOSClientUITests │ ├── Info.plist │ └── iOSClientUITests.m ├── ios_xor.t7ios ├── mnist.lua ├── mnist_ios.t7ios ├── mnist_samples.t7iosb ├── torch2ios.lua ├── torch2ios_reader.c ├── torch2ios_utils.lua └── xor.lua /README.md: -------------------------------------------------------------------------------- 1 | # torch2ios 2 | 3 | Small lib to serialise Torch7 Networks for iOS. Supported Layers include Fully Connected, Pooling and Convolution Layers at present. The library stores the weights & biases (if any) for each layer necesarry for inference on iOS devices. 4 | 5 | Usage is simple: just require 'torch2ios' in your lua script and call saveForiOS(_yourmodel, _destfilename) and a new .t7ios file will be created for use with the KSJNeuralNetwork [https://github.com/woffle/KSJNeuralNetwork] iOS library on the iOS client. 6 | 7 | Included is a simple demo of the usage, see xor.lua. 8 | 9 | Also added are API to access the binary file format on iOS and C. See iOSClient for iOS example and torch2ios_read.c for C example. Namespace for the iOS to Torch7 support will follow THES (Torch Embedded Systems)tag. 10 | 11 | ![alt tag](https://s31.postimg.org/p0o25qy8b/Torch_ES_File.png) 12 | ![alt tag](https://s32.postimg.org/xu32b5x5x/pool_arch.png) 13 | ![alt tag](https://s32.postimg.org/qpl924pwl/fc_arch.png) 14 | ![alt tag](https://s32.postimg.org/sg4a3m7fp/conv_arch.png) 15 | -------------------------------------------------------------------------------- /extract_sample.lua: -------------------------------------------------------------------------------- 1 | require 'torch2ios_utils' 2 | 3 | local test_set = torch.load("test_32x32.t7", 'ascii') 4 | local data = test_set.data:type(torch.getdefaulttensortype()) 5 | local labels = test_set.labels 6 | 7 | -- Normalise Data 8 | local std = std_ or data:std() 9 | local mean = mean_ or data:mean() 10 | data:add(-mean) 11 | data:mul(1/std) 12 | 13 | local file = torch.DiskFile("mnist_samples"..".t7iosb", 'w') 14 | file:binary() 15 | 16 | -- Extract an arbitrary number of samples [say 5 maybe?] 17 | file:writeInt(5) 18 | for i=1,5,1 do 19 | d_sample = torch2ios_utils.flatten(data[i]) 20 | d_sample_len = d_sample:size(1) 21 | l_sample = labels[i] 22 | 23 | file:writeInt(d_sample_len) 24 | for j=1,d_sample_len,1 do 25 | file:writeFloat(d_sample[j]) 26 | end 27 | file:writeInt(l_sample) 28 | end -------------------------------------------------------------------------------- /iOSClient/iOSClient.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 3C935C421D43FB70004B1351 /* mnist_ios.t7ios in Resources */ = {isa = PBXBuildFile; fileRef = 3C935C411D43FB70004B1351 /* mnist_ios.t7ios */; }; 11 | 3C935C441D43FBE6004B1351 /* ios_xor.t7ios in Resources */ = {isa = PBXBuildFile; fileRef = 3C935C431D43FBE6004B1351 /* ios_xor.t7ios */; }; 12 | 3CBC19961D351C75005CB3C7 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 3CBC19951D351C75005CB3C7 /* main.m */; }; 13 | 3CBC19991D351C75005CB3C7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 3CBC19981D351C75005CB3C7 /* AppDelegate.m */; }; 14 | 3CBC199C1D351C75005CB3C7 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3CBC199B1D351C75005CB3C7 /* ViewController.m */; }; 15 | 3CBC199F1D351C75005CB3C7 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 3CBC199D1D351C75005CB3C7 /* Main.storyboard */; }; 16 | 3CBC19A11D351C75005CB3C7 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3CBC19A01D351C75005CB3C7 /* Assets.xcassets */; }; 17 | 3CBC19A41D351C75005CB3C7 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 3CBC19A21D351C75005CB3C7 /* LaunchScreen.storyboard */; }; 18 | 3CBC19AF1D351C76005CB3C7 /* iOSClientTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3CBC19AE1D351C76005CB3C7 /* iOSClientTests.m */; }; 19 | 3CBC19BA1D351C76005CB3C7 /* iOSClientUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3CBC19B91D351C76005CB3C7 /* iOSClientUITests.m */; }; 20 | 3CBC19CD1D35477E005CB3C7 /* THESDiskFile.m in Sources */ = {isa = PBXBuildFile; fileRef = 3CBC19CC1D35477E005CB3C7 /* THESDiskFile.m */; }; 21 | 3CBC19D01D3548C9005CB3C7 /* THESLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 3CBC19CF1D3548C9005CB3C7 /* THESLayer.m */; }; 22 | /* End PBXBuildFile section */ 23 | 24 | /* Begin PBXContainerItemProxy section */ 25 | 3CBC19AB1D351C76005CB3C7 /* PBXContainerItemProxy */ = { 26 | isa = PBXContainerItemProxy; 27 | containerPortal = 3CBC19891D351C75005CB3C7 /* Project object */; 28 | proxyType = 1; 29 | remoteGlobalIDString = 3CBC19901D351C75005CB3C7; 30 | remoteInfo = iOSClient; 31 | }; 32 | 3CBC19B61D351C76005CB3C7 /* PBXContainerItemProxy */ = { 33 | isa = PBXContainerItemProxy; 34 | containerPortal = 3CBC19891D351C75005CB3C7 /* Project object */; 35 | proxyType = 1; 36 | remoteGlobalIDString = 3CBC19901D351C75005CB3C7; 37 | remoteInfo = iOSClient; 38 | }; 39 | /* End PBXContainerItemProxy section */ 40 | 41 | /* Begin PBXFileReference section */ 42 | 3C935C411D43FB70004B1351 /* mnist_ios.t7ios */ = {isa = PBXFileReference; lastKnownFileType = file; name = mnist_ios.t7ios; path = ../../mnist_ios.t7ios; sourceTree = ""; }; 43 | 3C935C431D43FBE6004B1351 /* ios_xor.t7ios */ = {isa = PBXFileReference; lastKnownFileType = file; name = ios_xor.t7ios; path = ../../ios_xor.t7ios; sourceTree = ""; }; 44 | 3CBC19911D351C75005CB3C7 /* iOSClient.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = iOSClient.app; sourceTree = BUILT_PRODUCTS_DIR; }; 45 | 3CBC19951D351C75005CB3C7 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 46 | 3CBC19971D351C75005CB3C7 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 47 | 3CBC19981D351C75005CB3C7 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 48 | 3CBC199A1D351C75005CB3C7 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 49 | 3CBC199B1D351C75005CB3C7 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 50 | 3CBC199E1D351C75005CB3C7 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 51 | 3CBC19A01D351C75005CB3C7 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 52 | 3CBC19A31D351C75005CB3C7 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 53 | 3CBC19A51D351C75005CB3C7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 54 | 3CBC19AA1D351C76005CB3C7 /* iOSClientTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = iOSClientTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 55 | 3CBC19AE1D351C76005CB3C7 /* iOSClientTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = iOSClientTests.m; sourceTree = ""; }; 56 | 3CBC19B01D351C76005CB3C7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 57 | 3CBC19B51D351C76005CB3C7 /* iOSClientUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = iOSClientUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 58 | 3CBC19B91D351C76005CB3C7 /* iOSClientUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = iOSClientUITests.m; sourceTree = ""; }; 59 | 3CBC19BB1D351C76005CB3C7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 60 | 3CBC19CB1D35477E005CB3C7 /* THESDiskFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = THESDiskFile.h; sourceTree = ""; }; 61 | 3CBC19CC1D35477E005CB3C7 /* THESDiskFile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = THESDiskFile.m; sourceTree = ""; }; 62 | 3CBC19CE1D3548C9005CB3C7 /* THESLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = THESLayer.h; sourceTree = ""; }; 63 | 3CBC19CF1D3548C9005CB3C7 /* THESLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = THESLayer.m; sourceTree = ""; }; 64 | /* End PBXFileReference section */ 65 | 66 | /* Begin PBXFrameworksBuildPhase section */ 67 | 3CBC198E1D351C75005CB3C7 /* Frameworks */ = { 68 | isa = PBXFrameworksBuildPhase; 69 | buildActionMask = 2147483647; 70 | files = ( 71 | ); 72 | runOnlyForDeploymentPostprocessing = 0; 73 | }; 74 | 3CBC19A71D351C76005CB3C7 /* Frameworks */ = { 75 | isa = PBXFrameworksBuildPhase; 76 | buildActionMask = 2147483647; 77 | files = ( 78 | ); 79 | runOnlyForDeploymentPostprocessing = 0; 80 | }; 81 | 3CBC19B21D351C76005CB3C7 /* Frameworks */ = { 82 | isa = PBXFrameworksBuildPhase; 83 | buildActionMask = 2147483647; 84 | files = ( 85 | ); 86 | runOnlyForDeploymentPostprocessing = 0; 87 | }; 88 | /* End PBXFrameworksBuildPhase section */ 89 | 90 | /* Begin PBXGroup section */ 91 | 3CBC19881D351C75005CB3C7 = { 92 | isa = PBXGroup; 93 | children = ( 94 | 3CBC19931D351C75005CB3C7 /* iOSClient */, 95 | 3CBC19AD1D351C76005CB3C7 /* iOSClientTests */, 96 | 3CBC19B81D351C76005CB3C7 /* iOSClientUITests */, 97 | 3CBC19921D351C75005CB3C7 /* Products */, 98 | ); 99 | sourceTree = ""; 100 | }; 101 | 3CBC19921D351C75005CB3C7 /* Products */ = { 102 | isa = PBXGroup; 103 | children = ( 104 | 3CBC19911D351C75005CB3C7 /* iOSClient.app */, 105 | 3CBC19AA1D351C76005CB3C7 /* iOSClientTests.xctest */, 106 | 3CBC19B51D351C76005CB3C7 /* iOSClientUITests.xctest */, 107 | ); 108 | name = Products; 109 | sourceTree = ""; 110 | }; 111 | 3CBC19931D351C75005CB3C7 /* iOSClient */ = { 112 | isa = PBXGroup; 113 | children = ( 114 | 3CBC19971D351C75005CB3C7 /* AppDelegate.h */, 115 | 3CBC19981D351C75005CB3C7 /* AppDelegate.m */, 116 | 3CBC199A1D351C75005CB3C7 /* ViewController.h */, 117 | 3CBC199B1D351C75005CB3C7 /* ViewController.m */, 118 | 3CBC19CE1D3548C9005CB3C7 /* THESLayer.h */, 119 | 3CBC19CF1D3548C9005CB3C7 /* THESLayer.m */, 120 | 3CBC19CB1D35477E005CB3C7 /* THESDiskFile.h */, 121 | 3CBC19CC1D35477E005CB3C7 /* THESDiskFile.m */, 122 | 3C935C431D43FBE6004B1351 /* ios_xor.t7ios */, 123 | 3C935C411D43FB70004B1351 /* mnist_ios.t7ios */, 124 | 3CBC199D1D351C75005CB3C7 /* Main.storyboard */, 125 | 3CBC19A01D351C75005CB3C7 /* Assets.xcassets */, 126 | 3CBC19A21D351C75005CB3C7 /* LaunchScreen.storyboard */, 127 | 3CBC19A51D351C75005CB3C7 /* Info.plist */, 128 | 3CBC19941D351C75005CB3C7 /* Supporting Files */, 129 | ); 130 | path = iOSClient; 131 | sourceTree = ""; 132 | }; 133 | 3CBC19941D351C75005CB3C7 /* Supporting Files */ = { 134 | isa = PBXGroup; 135 | children = ( 136 | 3CBC19951D351C75005CB3C7 /* main.m */, 137 | ); 138 | name = "Supporting Files"; 139 | sourceTree = ""; 140 | }; 141 | 3CBC19AD1D351C76005CB3C7 /* iOSClientTests */ = { 142 | isa = PBXGroup; 143 | children = ( 144 | 3CBC19AE1D351C76005CB3C7 /* iOSClientTests.m */, 145 | 3CBC19B01D351C76005CB3C7 /* Info.plist */, 146 | ); 147 | path = iOSClientTests; 148 | sourceTree = ""; 149 | }; 150 | 3CBC19B81D351C76005CB3C7 /* iOSClientUITests */ = { 151 | isa = PBXGroup; 152 | children = ( 153 | 3CBC19B91D351C76005CB3C7 /* iOSClientUITests.m */, 154 | 3CBC19BB1D351C76005CB3C7 /* Info.plist */, 155 | ); 156 | path = iOSClientUITests; 157 | sourceTree = ""; 158 | }; 159 | /* End PBXGroup section */ 160 | 161 | /* Begin PBXNativeTarget section */ 162 | 3CBC19901D351C75005CB3C7 /* iOSClient */ = { 163 | isa = PBXNativeTarget; 164 | buildConfigurationList = 3CBC19BE1D351C76005CB3C7 /* Build configuration list for PBXNativeTarget "iOSClient" */; 165 | buildPhases = ( 166 | 3CBC198D1D351C75005CB3C7 /* Sources */, 167 | 3CBC198E1D351C75005CB3C7 /* Frameworks */, 168 | 3CBC198F1D351C75005CB3C7 /* Resources */, 169 | ); 170 | buildRules = ( 171 | ); 172 | dependencies = ( 173 | ); 174 | name = iOSClient; 175 | productName = iOSClient; 176 | productReference = 3CBC19911D351C75005CB3C7 /* iOSClient.app */; 177 | productType = "com.apple.product-type.application"; 178 | }; 179 | 3CBC19A91D351C76005CB3C7 /* iOSClientTests */ = { 180 | isa = PBXNativeTarget; 181 | buildConfigurationList = 3CBC19C11D351C76005CB3C7 /* Build configuration list for PBXNativeTarget "iOSClientTests" */; 182 | buildPhases = ( 183 | 3CBC19A61D351C76005CB3C7 /* Sources */, 184 | 3CBC19A71D351C76005CB3C7 /* Frameworks */, 185 | 3CBC19A81D351C76005CB3C7 /* Resources */, 186 | ); 187 | buildRules = ( 188 | ); 189 | dependencies = ( 190 | 3CBC19AC1D351C76005CB3C7 /* PBXTargetDependency */, 191 | ); 192 | name = iOSClientTests; 193 | productName = iOSClientTests; 194 | productReference = 3CBC19AA1D351C76005CB3C7 /* iOSClientTests.xctest */; 195 | productType = "com.apple.product-type.bundle.unit-test"; 196 | }; 197 | 3CBC19B41D351C76005CB3C7 /* iOSClientUITests */ = { 198 | isa = PBXNativeTarget; 199 | buildConfigurationList = 3CBC19C41D351C76005CB3C7 /* Build configuration list for PBXNativeTarget "iOSClientUITests" */; 200 | buildPhases = ( 201 | 3CBC19B11D351C76005CB3C7 /* Sources */, 202 | 3CBC19B21D351C76005CB3C7 /* Frameworks */, 203 | 3CBC19B31D351C76005CB3C7 /* Resources */, 204 | ); 205 | buildRules = ( 206 | ); 207 | dependencies = ( 208 | 3CBC19B71D351C76005CB3C7 /* PBXTargetDependency */, 209 | ); 210 | name = iOSClientUITests; 211 | productName = iOSClientUITests; 212 | productReference = 3CBC19B51D351C76005CB3C7 /* iOSClientUITests.xctest */; 213 | productType = "com.apple.product-type.bundle.ui-testing"; 214 | }; 215 | /* End PBXNativeTarget section */ 216 | 217 | /* Begin PBXProject section */ 218 | 3CBC19891D351C75005CB3C7 /* Project object */ = { 219 | isa = PBXProject; 220 | attributes = { 221 | LastUpgradeCheck = 0730; 222 | ORGANIZATIONNAME = RandomDudes; 223 | TargetAttributes = { 224 | 3CBC19901D351C75005CB3C7 = { 225 | CreatedOnToolsVersion = 7.3; 226 | }; 227 | 3CBC19A91D351C76005CB3C7 = { 228 | CreatedOnToolsVersion = 7.3; 229 | TestTargetID = 3CBC19901D351C75005CB3C7; 230 | }; 231 | 3CBC19B41D351C76005CB3C7 = { 232 | CreatedOnToolsVersion = 7.3; 233 | TestTargetID = 3CBC19901D351C75005CB3C7; 234 | }; 235 | }; 236 | }; 237 | buildConfigurationList = 3CBC198C1D351C75005CB3C7 /* Build configuration list for PBXProject "iOSClient" */; 238 | compatibilityVersion = "Xcode 3.2"; 239 | developmentRegion = English; 240 | hasScannedForEncodings = 0; 241 | knownRegions = ( 242 | en, 243 | Base, 244 | ); 245 | mainGroup = 3CBC19881D351C75005CB3C7; 246 | productRefGroup = 3CBC19921D351C75005CB3C7 /* Products */; 247 | projectDirPath = ""; 248 | projectRoot = ""; 249 | targets = ( 250 | 3CBC19901D351C75005CB3C7 /* iOSClient */, 251 | 3CBC19A91D351C76005CB3C7 /* iOSClientTests */, 252 | 3CBC19B41D351C76005CB3C7 /* iOSClientUITests */, 253 | ); 254 | }; 255 | /* End PBXProject section */ 256 | 257 | /* Begin PBXResourcesBuildPhase section */ 258 | 3CBC198F1D351C75005CB3C7 /* Resources */ = { 259 | isa = PBXResourcesBuildPhase; 260 | buildActionMask = 2147483647; 261 | files = ( 262 | 3CBC19A41D351C75005CB3C7 /* LaunchScreen.storyboard in Resources */, 263 | 3CBC19A11D351C75005CB3C7 /* Assets.xcassets in Resources */, 264 | 3CBC199F1D351C75005CB3C7 /* Main.storyboard in Resources */, 265 | 3C935C441D43FBE6004B1351 /* ios_xor.t7ios in Resources */, 266 | 3C935C421D43FB70004B1351 /* mnist_ios.t7ios in Resources */, 267 | ); 268 | runOnlyForDeploymentPostprocessing = 0; 269 | }; 270 | 3CBC19A81D351C76005CB3C7 /* Resources */ = { 271 | isa = PBXResourcesBuildPhase; 272 | buildActionMask = 2147483647; 273 | files = ( 274 | ); 275 | runOnlyForDeploymentPostprocessing = 0; 276 | }; 277 | 3CBC19B31D351C76005CB3C7 /* Resources */ = { 278 | isa = PBXResourcesBuildPhase; 279 | buildActionMask = 2147483647; 280 | files = ( 281 | ); 282 | runOnlyForDeploymentPostprocessing = 0; 283 | }; 284 | /* End PBXResourcesBuildPhase section */ 285 | 286 | /* Begin PBXSourcesBuildPhase section */ 287 | 3CBC198D1D351C75005CB3C7 /* Sources */ = { 288 | isa = PBXSourcesBuildPhase; 289 | buildActionMask = 2147483647; 290 | files = ( 291 | 3CBC199C1D351C75005CB3C7 /* ViewController.m in Sources */, 292 | 3CBC19991D351C75005CB3C7 /* AppDelegate.m in Sources */, 293 | 3CBC19961D351C75005CB3C7 /* main.m in Sources */, 294 | 3CBC19CD1D35477E005CB3C7 /* THESDiskFile.m in Sources */, 295 | 3CBC19D01D3548C9005CB3C7 /* THESLayer.m in Sources */, 296 | ); 297 | runOnlyForDeploymentPostprocessing = 0; 298 | }; 299 | 3CBC19A61D351C76005CB3C7 /* Sources */ = { 300 | isa = PBXSourcesBuildPhase; 301 | buildActionMask = 2147483647; 302 | files = ( 303 | 3CBC19AF1D351C76005CB3C7 /* iOSClientTests.m in Sources */, 304 | ); 305 | runOnlyForDeploymentPostprocessing = 0; 306 | }; 307 | 3CBC19B11D351C76005CB3C7 /* Sources */ = { 308 | isa = PBXSourcesBuildPhase; 309 | buildActionMask = 2147483647; 310 | files = ( 311 | 3CBC19BA1D351C76005CB3C7 /* iOSClientUITests.m in Sources */, 312 | ); 313 | runOnlyForDeploymentPostprocessing = 0; 314 | }; 315 | /* End PBXSourcesBuildPhase section */ 316 | 317 | /* Begin PBXTargetDependency section */ 318 | 3CBC19AC1D351C76005CB3C7 /* PBXTargetDependency */ = { 319 | isa = PBXTargetDependency; 320 | target = 3CBC19901D351C75005CB3C7 /* iOSClient */; 321 | targetProxy = 3CBC19AB1D351C76005CB3C7 /* PBXContainerItemProxy */; 322 | }; 323 | 3CBC19B71D351C76005CB3C7 /* PBXTargetDependency */ = { 324 | isa = PBXTargetDependency; 325 | target = 3CBC19901D351C75005CB3C7 /* iOSClient */; 326 | targetProxy = 3CBC19B61D351C76005CB3C7 /* PBXContainerItemProxy */; 327 | }; 328 | /* End PBXTargetDependency section */ 329 | 330 | /* Begin PBXVariantGroup section */ 331 | 3CBC199D1D351C75005CB3C7 /* Main.storyboard */ = { 332 | isa = PBXVariantGroup; 333 | children = ( 334 | 3CBC199E1D351C75005CB3C7 /* Base */, 335 | ); 336 | name = Main.storyboard; 337 | sourceTree = ""; 338 | }; 339 | 3CBC19A21D351C75005CB3C7 /* LaunchScreen.storyboard */ = { 340 | isa = PBXVariantGroup; 341 | children = ( 342 | 3CBC19A31D351C75005CB3C7 /* Base */, 343 | ); 344 | name = LaunchScreen.storyboard; 345 | sourceTree = ""; 346 | }; 347 | /* End PBXVariantGroup section */ 348 | 349 | /* Begin XCBuildConfiguration section */ 350 | 3CBC19BC1D351C76005CB3C7 /* Debug */ = { 351 | isa = XCBuildConfiguration; 352 | buildSettings = { 353 | ALWAYS_SEARCH_USER_PATHS = NO; 354 | CLANG_ANALYZER_NONNULL = YES; 355 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 356 | CLANG_CXX_LIBRARY = "libc++"; 357 | CLANG_ENABLE_MODULES = YES; 358 | CLANG_ENABLE_OBJC_ARC = YES; 359 | CLANG_WARN_BOOL_CONVERSION = YES; 360 | CLANG_WARN_CONSTANT_CONVERSION = YES; 361 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 362 | CLANG_WARN_EMPTY_BODY = YES; 363 | CLANG_WARN_ENUM_CONVERSION = YES; 364 | CLANG_WARN_INT_CONVERSION = YES; 365 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 366 | CLANG_WARN_UNREACHABLE_CODE = YES; 367 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 368 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 369 | COPY_PHASE_STRIP = NO; 370 | DEBUG_INFORMATION_FORMAT = dwarf; 371 | ENABLE_STRICT_OBJC_MSGSEND = YES; 372 | ENABLE_TESTABILITY = YES; 373 | GCC_C_LANGUAGE_STANDARD = gnu99; 374 | GCC_DYNAMIC_NO_PIC = NO; 375 | GCC_NO_COMMON_BLOCKS = YES; 376 | GCC_OPTIMIZATION_LEVEL = 0; 377 | GCC_PREPROCESSOR_DEFINITIONS = ( 378 | "DEBUG=1", 379 | "$(inherited)", 380 | ); 381 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 382 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 383 | GCC_WARN_UNDECLARED_SELECTOR = YES; 384 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 385 | GCC_WARN_UNUSED_FUNCTION = YES; 386 | GCC_WARN_UNUSED_VARIABLE = YES; 387 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 388 | MTL_ENABLE_DEBUG_INFO = YES; 389 | ONLY_ACTIVE_ARCH = YES; 390 | SDKROOT = iphoneos; 391 | TARGETED_DEVICE_FAMILY = "1,2"; 392 | }; 393 | name = Debug; 394 | }; 395 | 3CBC19BD1D351C76005CB3C7 /* Release */ = { 396 | isa = XCBuildConfiguration; 397 | buildSettings = { 398 | ALWAYS_SEARCH_USER_PATHS = NO; 399 | CLANG_ANALYZER_NONNULL = YES; 400 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 401 | CLANG_CXX_LIBRARY = "libc++"; 402 | CLANG_ENABLE_MODULES = YES; 403 | CLANG_ENABLE_OBJC_ARC = YES; 404 | CLANG_WARN_BOOL_CONVERSION = YES; 405 | CLANG_WARN_CONSTANT_CONVERSION = YES; 406 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 407 | CLANG_WARN_EMPTY_BODY = YES; 408 | CLANG_WARN_ENUM_CONVERSION = YES; 409 | CLANG_WARN_INT_CONVERSION = YES; 410 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 411 | CLANG_WARN_UNREACHABLE_CODE = YES; 412 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 413 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 414 | COPY_PHASE_STRIP = NO; 415 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 416 | ENABLE_NS_ASSERTIONS = NO; 417 | ENABLE_STRICT_OBJC_MSGSEND = YES; 418 | GCC_C_LANGUAGE_STANDARD = gnu99; 419 | GCC_NO_COMMON_BLOCKS = YES; 420 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 421 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 422 | GCC_WARN_UNDECLARED_SELECTOR = YES; 423 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 424 | GCC_WARN_UNUSED_FUNCTION = YES; 425 | GCC_WARN_UNUSED_VARIABLE = YES; 426 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 427 | MTL_ENABLE_DEBUG_INFO = NO; 428 | SDKROOT = iphoneos; 429 | TARGETED_DEVICE_FAMILY = "1,2"; 430 | VALIDATE_PRODUCT = YES; 431 | }; 432 | name = Release; 433 | }; 434 | 3CBC19BF1D351C76005CB3C7 /* Debug */ = { 435 | isa = XCBuildConfiguration; 436 | buildSettings = { 437 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 438 | INFOPLIST_FILE = iOSClient/Info.plist; 439 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 440 | PRODUCT_BUNDLE_IDENTIFIER = com.randomdudes.iOSClient; 441 | PRODUCT_NAME = "$(TARGET_NAME)"; 442 | }; 443 | name = Debug; 444 | }; 445 | 3CBC19C01D351C76005CB3C7 /* Release */ = { 446 | isa = XCBuildConfiguration; 447 | buildSettings = { 448 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 449 | INFOPLIST_FILE = iOSClient/Info.plist; 450 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 451 | PRODUCT_BUNDLE_IDENTIFIER = com.randomdudes.iOSClient; 452 | PRODUCT_NAME = "$(TARGET_NAME)"; 453 | }; 454 | name = Release; 455 | }; 456 | 3CBC19C21D351C76005CB3C7 /* Debug */ = { 457 | isa = XCBuildConfiguration; 458 | buildSettings = { 459 | BUNDLE_LOADER = "$(TEST_HOST)"; 460 | INFOPLIST_FILE = iOSClientTests/Info.plist; 461 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 462 | PRODUCT_BUNDLE_IDENTIFIER = com.randomdudes.iOSClientTests; 463 | PRODUCT_NAME = "$(TARGET_NAME)"; 464 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/iOSClient.app/iOSClient"; 465 | }; 466 | name = Debug; 467 | }; 468 | 3CBC19C31D351C76005CB3C7 /* Release */ = { 469 | isa = XCBuildConfiguration; 470 | buildSettings = { 471 | BUNDLE_LOADER = "$(TEST_HOST)"; 472 | INFOPLIST_FILE = iOSClientTests/Info.plist; 473 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 474 | PRODUCT_BUNDLE_IDENTIFIER = com.randomdudes.iOSClientTests; 475 | PRODUCT_NAME = "$(TARGET_NAME)"; 476 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/iOSClient.app/iOSClient"; 477 | }; 478 | name = Release; 479 | }; 480 | 3CBC19C51D351C76005CB3C7 /* Debug */ = { 481 | isa = XCBuildConfiguration; 482 | buildSettings = { 483 | INFOPLIST_FILE = iOSClientUITests/Info.plist; 484 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 485 | PRODUCT_BUNDLE_IDENTIFIER = com.randomdudes.iOSClientUITests; 486 | PRODUCT_NAME = "$(TARGET_NAME)"; 487 | TEST_TARGET_NAME = iOSClient; 488 | }; 489 | name = Debug; 490 | }; 491 | 3CBC19C61D351C76005CB3C7 /* Release */ = { 492 | isa = XCBuildConfiguration; 493 | buildSettings = { 494 | INFOPLIST_FILE = iOSClientUITests/Info.plist; 495 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 496 | PRODUCT_BUNDLE_IDENTIFIER = com.randomdudes.iOSClientUITests; 497 | PRODUCT_NAME = "$(TARGET_NAME)"; 498 | TEST_TARGET_NAME = iOSClient; 499 | }; 500 | name = Release; 501 | }; 502 | /* End XCBuildConfiguration section */ 503 | 504 | /* Begin XCConfigurationList section */ 505 | 3CBC198C1D351C75005CB3C7 /* Build configuration list for PBXProject "iOSClient" */ = { 506 | isa = XCConfigurationList; 507 | buildConfigurations = ( 508 | 3CBC19BC1D351C76005CB3C7 /* Debug */, 509 | 3CBC19BD1D351C76005CB3C7 /* Release */, 510 | ); 511 | defaultConfigurationIsVisible = 0; 512 | defaultConfigurationName = Release; 513 | }; 514 | 3CBC19BE1D351C76005CB3C7 /* Build configuration list for PBXNativeTarget "iOSClient" */ = { 515 | isa = XCConfigurationList; 516 | buildConfigurations = ( 517 | 3CBC19BF1D351C76005CB3C7 /* Debug */, 518 | 3CBC19C01D351C76005CB3C7 /* Release */, 519 | ); 520 | defaultConfigurationIsVisible = 0; 521 | defaultConfigurationName = Release; 522 | }; 523 | 3CBC19C11D351C76005CB3C7 /* Build configuration list for PBXNativeTarget "iOSClientTests" */ = { 524 | isa = XCConfigurationList; 525 | buildConfigurations = ( 526 | 3CBC19C21D351C76005CB3C7 /* Debug */, 527 | 3CBC19C31D351C76005CB3C7 /* Release */, 528 | ); 529 | defaultConfigurationIsVisible = 0; 530 | defaultConfigurationName = Release; 531 | }; 532 | 3CBC19C41D351C76005CB3C7 /* Build configuration list for PBXNativeTarget "iOSClientUITests" */ = { 533 | isa = XCConfigurationList; 534 | buildConfigurations = ( 535 | 3CBC19C51D351C76005CB3C7 /* Debug */, 536 | 3CBC19C61D351C76005CB3C7 /* Release */, 537 | ); 538 | defaultConfigurationIsVisible = 0; 539 | defaultConfigurationName = Release; 540 | }; 541 | /* End XCConfigurationList section */ 542 | }; 543 | rootObject = 3CBC19891D351C75005CB3C7 /* Project object */; 544 | } 545 | -------------------------------------------------------------------------------- /iOSClient/iOSClient.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /iOSClient/iOSClient.xcodeproj/project.xcworkspace/xcuserdata/kurtjacobs.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kurtjacobsdev/torch2ios/1edb18d5ac7f2426e9c682a7d25ae38d71c81491/iOSClient/iOSClient.xcodeproj/project.xcworkspace/xcuserdata/kurtjacobs.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /iOSClient/iOSClient.xcodeproj/project.xcworkspace/xcuserdata/woffle_laptop.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kurtjacobsdev/torch2ios/1edb18d5ac7f2426e9c682a7d25ae38d71c81491/iOSClient/iOSClient.xcodeproj/project.xcworkspace/xcuserdata/woffle_laptop.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /iOSClient/iOSClient.xcodeproj/xcuserdata/kurtjacobs.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /iOSClient/iOSClient.xcodeproj/xcuserdata/kurtjacobs.xcuserdatad/xcschemes/iOSClient.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 43 | 49 | 50 | 51 | 52 | 53 | 59 | 60 | 61 | 62 | 63 | 64 | 74 | 76 | 82 | 83 | 84 | 85 | 86 | 87 | 93 | 95 | 101 | 102 | 103 | 104 | 106 | 107 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /iOSClient/iOSClient.xcodeproj/xcuserdata/kurtjacobs.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | iOSClient.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 3CBC19901D351C75005CB3C7 16 | 17 | primary 18 | 19 | 20 | 3CBC19A91D351C76005CB3C7 21 | 22 | primary 23 | 24 | 25 | 3CBC19B41D351C76005CB3C7 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /iOSClient/iOSClient.xcodeproj/xcuserdata/woffle_laptop.xcuserdatad/xcschemes/iOSClient.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 43 | 49 | 50 | 51 | 52 | 53 | 59 | 60 | 61 | 62 | 63 | 64 | 74 | 76 | 82 | 83 | 84 | 85 | 86 | 87 | 93 | 95 | 101 | 102 | 103 | 104 | 106 | 107 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /iOSClient/iOSClient.xcodeproj/xcuserdata/woffle_laptop.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | iOSClient.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 3CBC19901D351C75005CB3C7 16 | 17 | primary 18 | 19 | 20 | 3CBC19A91D351C76005CB3C7 21 | 22 | primary 23 | 24 | 25 | 3CBC19B41D351C76005CB3C7 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /iOSClient/iOSClient/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // Created by Kurt Jacobs 4 | // Copyright © 2016 RandomDudes. All rights reserved. 5 | // 6 | // 7 | 8 | #import 9 | 10 | @interface AppDelegate : UIResponder 11 | 12 | @property (strong, nonatomic) UIWindow *window; 13 | 14 | 15 | @end 16 | 17 | -------------------------------------------------------------------------------- /iOSClient/iOSClient/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // Created by Kurt Jacobs 4 | // Copyright © 2016 RandomDudes. All rights reserved. 5 | // 6 | // 7 | 8 | #import "AppDelegate.h" 9 | 10 | @interface AppDelegate () 11 | 12 | @end 13 | 14 | @implementation AppDelegate 15 | 16 | 17 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 18 | // Override point for customization after application launch. 19 | return YES; 20 | } 21 | 22 | - (void)applicationWillResignActive:(UIApplication *)application { 23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 24 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 25 | } 26 | 27 | - (void)applicationDidEnterBackground:(UIApplication *)application { 28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | - (void)applicationWillEnterForeground:(UIApplication *)application { 33 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | - (void)applicationDidBecomeActive:(UIApplication *)application { 37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 38 | } 39 | 40 | - (void)applicationWillTerminate:(UIApplication *)application { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /iOSClient/iOSClient/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /iOSClient/iOSClient/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /iOSClient/iOSClient/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /iOSClient/iOSClient/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 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /iOSClient/iOSClient/THESDiskFile.h: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // Created by Kurt Jacobs 4 | // Copyright © 2016 RandomDudes. All rights reserved. 5 | // 6 | // 7 | 8 | #import 9 | #import "THESLayer.h" 10 | 11 | @interface THESDiskFile : NSObject 12 | 13 | /*! @brief Reads a .t7ios file on disk and returns an array of THESLayer objects. 14 | * @param path The path to the .t7ios file on disk. 15 | */ 16 | + (NSArray *)readLayersBinary:(NSString *)path; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /iOSClient/iOSClient/THESDiskFile.m: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // Created by Kurt Jacobs 4 | // Copyright © 2016 RandomDudes. All rights reserved. 5 | // 6 | // 7 | 8 | #import "THESDiskFile.h" 9 | #import 10 | 11 | #define CONV_LAYER_STRUCTURE_COUNT 8 12 | #define LINEAR_LAYER_STRUCTURE_COUNT 2 13 | #define POOLING_LAYER_STRUCTURE_COUNT 6 14 | 15 | typedef NS_ENUM(NSUInteger, THESDiskFileDataType) 16 | { 17 | THESDiskFileDataTypeFloat = 1, 18 | THESDiskFileDataTypeDouble = 2, 19 | THESDiskFileDataTypeInt = 3 20 | }; 21 | 22 | @implementation THESDiskFile 23 | 24 | + (NSArray *)readLayersBinary:(NSString *)path 25 | { 26 | NSMutableArray *layers = [NSMutableArray array]; 27 | 28 | NSFileHandle *f = [NSFileHandle fileHandleForReadingAtPath:path]; 29 | int layer_count = 0; 30 | [[f readDataOfLength:sizeof(int)] getBytes:&layer_count length:sizeof(int)]; 31 | int layer_type = 0; 32 | int datatype_w = 0; 33 | int weights_len = 0; 34 | void *weight_buffer; 35 | int datatype_b = 0; 36 | int bias_len = 0; 37 | void *bias_buffer; 38 | int *structure_buffer; 39 | 40 | for (int i = 0; i < layer_count ; i ++) 41 | { 42 | layer_type = 0; 43 | datatype_w = 0; 44 | weights_len = 0; 45 | weight_buffer = NULL; 46 | datatype_b = 0; 47 | bias_len = 0; 48 | bias_buffer = NULL; 49 | [[f readDataOfLength:sizeof(int)] getBytes:&layer_type length:sizeof(int)]; 50 | 51 | if (layer_type == 1) 52 | { 53 | structure_buffer = (int *)calloc(LINEAR_LAYER_STRUCTURE_COUNT,sizeof(int)); 54 | for (int j = 0; j < LINEAR_LAYER_STRUCTURE_COUNT; j++) 55 | { 56 | [[f readDataOfLength:sizeof(int)] getBytes:&structure_buffer[j] length:sizeof(int)]; 57 | } 58 | } 59 | else if (layer_type == 2) 60 | { 61 | structure_buffer = (int *)calloc(CONV_LAYER_STRUCTURE_COUNT,sizeof(int)); 62 | for (int j = 0; j < CONV_LAYER_STRUCTURE_COUNT; j++) 63 | { 64 | [[f readDataOfLength:sizeof(int)] getBytes:&structure_buffer[j] length:sizeof(int)]; 65 | } 66 | } 67 | else if (layer_type == 3 || layer_type == 4) 68 | { 69 | structure_buffer = (int *)calloc(POOLING_LAYER_STRUCTURE_COUNT,sizeof(int)); 70 | for (int j = 0; j < POOLING_LAYER_STRUCTURE_COUNT; j++) 71 | { 72 | [[f readDataOfLength:sizeof(int)] getBytes:&structure_buffer[j] length:sizeof(int)]; 73 | } 74 | } 75 | else 76 | { 77 | structure_buffer = (int *)calloc(LINEAR_LAYER_STRUCTURE_COUNT,sizeof(int)); 78 | for (int j = 0; j < LINEAR_LAYER_STRUCTURE_COUNT; j++) 79 | { 80 | [[f readDataOfLength:sizeof(int)] getBytes:&structure_buffer[j] length:sizeof(int)]; 81 | } 82 | } 83 | 84 | if (layer_type <= 2) 85 | { 86 | [[f readDataOfLength:sizeof(int)] getBytes:&datatype_w length:sizeof(int)]; 87 | [[f readDataOfLength:sizeof(int)] getBytes:&weights_len length:sizeof(int)]; 88 | if (datatype_w == THESDiskFileDataTypeFloat) 89 | { 90 | weight_buffer = (float *)calloc(weights_len,sizeof(float)); 91 | } 92 | else if (datatype_w == THESDiskFileDataTypeDouble) 93 | { 94 | weight_buffer = (double *)calloc(weights_len,sizeof(double)); 95 | } 96 | else if (datatype_w == THESDiskFileDataTypeInt) 97 | { 98 | weight_buffer = (int *)calloc(weights_len,sizeof(int)); 99 | } 100 | for (int j = 0; j < weights_len; j++) 101 | { 102 | if (datatype_w == THESDiskFileDataTypeFloat) 103 | { 104 | float readValue; 105 | [[f readDataOfLength:sizeof(float)] getBytes:&readValue length:sizeof(float)]; 106 | float *castBuffer = weight_buffer; 107 | castBuffer[j] = readValue; 108 | } 109 | else if (datatype_w == THESDiskFileDataTypeDouble) 110 | { 111 | double readValue; 112 | [[f readDataOfLength:sizeof(double)] getBytes:&readValue length:sizeof(double)]; 113 | double *castBuffer = weight_buffer; 114 | castBuffer[j] = readValue; 115 | } 116 | else if(datatype_w == THESDiskFileDataTypeInt) 117 | { 118 | int readValue; 119 | [[f readDataOfLength:sizeof(int)] getBytes:&readValue length:sizeof(int)]; 120 | int *castBuffer = weight_buffer; 121 | castBuffer[j] = readValue; 122 | } 123 | } 124 | [[f readDataOfLength:sizeof(int)] getBytes:&datatype_b length:sizeof(int)]; 125 | [[f readDataOfLength:sizeof(int)] getBytes:&bias_len length:sizeof(int)]; 126 | 127 | if (datatype_b == THESDiskFileDataTypeFloat) 128 | { 129 | bias_buffer = (float *)calloc(bias_len,sizeof(float)); 130 | } 131 | else if (datatype_b == THESDiskFileDataTypeDouble) 132 | { 133 | bias_buffer = (double *)calloc(bias_len,sizeof(double)); 134 | } 135 | else if (datatype_b == THESDiskFileDataTypeInt) 136 | { 137 | bias_buffer = (int *)calloc(bias_len,sizeof(int)); 138 | } 139 | for (int j = 0; j < bias_len; j++) 140 | { 141 | if (datatype_b == THESDiskFileDataTypeFloat) 142 | { 143 | float readValue; 144 | [[f readDataOfLength:sizeof(float)] getBytes:&readValue length:sizeof(float)]; 145 | float *castBuffer = bias_buffer; 146 | castBuffer[j] = readValue; 147 | } 148 | else if (datatype_b == THESDiskFileDataTypeDouble) 149 | { 150 | double readValue; 151 | [[f readDataOfLength:sizeof(double)] getBytes:&readValue length:sizeof(double)]; 152 | double *castBuffer = bias_buffer; 153 | castBuffer[j] = readValue; 154 | } 155 | else if(datatype_b == THESDiskFileDataTypeInt) 156 | { 157 | int readValue; 158 | [[f readDataOfLength:sizeof(int)] getBytes:&readValue length:sizeof(int)]; 159 | int *castBuffer = bias_buffer; 160 | castBuffer[j] = readValue; 161 | } 162 | } 163 | } 164 | 165 | THESLayer *layer = [[THESLayer alloc] initWithLayerType:@(layer_type) weightBuffer:[NSValue valueWithPointer:weight_buffer] weightBufferSize:weights_len biasBuffer:[NSValue valueWithPointer:bias_buffer] weightBufferSize:bias_len andStructureBuffer:[NSValue valueWithPointer:structure_buffer]]; 166 | [layers addObject:layer]; 167 | } 168 | 169 | [f closeFile]; 170 | return layers; 171 | } 172 | 173 | @end 174 | -------------------------------------------------------------------------------- /iOSClient/iOSClient/THESLayer.h: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // Created by Kurt Jacobs 4 | // Copyright © 2016 RandomDudes. All rights reserved. 5 | // 6 | // 7 | 8 | #import 9 | 10 | extern NSString * const THES_layer_activations[]; 11 | extern NSString * const THES_tensor_types[]; 12 | 13 | @interface THESLayer : NSObject 14 | 15 | @property (nonatomic) NSNumber *layerType; 16 | @property (nonatomic) NSValue *weightsBuffer; 17 | @property (nonatomic) NSUInteger weightsBufferSize; 18 | @property (nonatomic) NSValue *biasBuffer; 19 | @property (nonatomic) NSUInteger biasBufferSize; 20 | @property (nonatomic) NSValue *structureBuffer; 21 | 22 | /*! @brief Accepts an array of THESLayers and clears the bias and weight buffers for each instance. 23 | * @param layers An array of THESLayers. 24 | */ 25 | + (void)freeLayerBuffers:(NSArray *)layers; 26 | 27 | 28 | - (instancetype)initWithLayerType:(NSNumber *)layerType weightBuffer:(NSValue *)wBuffer weightBufferSize:(NSUInteger)wBufferSize biasBuffer:(NSValue *)bBuffer weightBufferSize:(NSUInteger)bBufferSize andStructureBuffer:(NSValue *)structureBuffer; 29 | 30 | /*! @brief Clears the bias and weight buffers. 31 | */ 32 | - (void)freeBuffers; 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /iOSClient/iOSClient/THESLayer.m: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // Created by Kurt Jacobs 4 | // Copyright © 2016 RandomDudes. All rights reserved. 5 | // 6 | // 7 | 8 | #import "THESLayer.h" 9 | 10 | NSString * const THES_layer_activations[] = { 11 | @"",@"nn.Linear",@"nn.SpatialConvolution",@"nn.SpatialMaxPooling",@"nn.SpatialAveragePooling",@"nn.Tanh",@"nn.HardTanh",@"nn.LogSigmoid",@"nn.LogSoftMax",@"nn.Sigmoid",@"nn.ReLU",@"nn.Reshape" 12 | }; 13 | 14 | NSString * const THES_tensor_types[] = { 15 | @"",@"torch.FloatTensor",@"torch.DoubleTensor",@"torch.IntTensor" 16 | }; 17 | 18 | @implementation THESLayer 19 | 20 | - (instancetype)initWithLayerType:(NSNumber *)layerType weightBuffer:(NSValue *)wBuffer weightBufferSize:(NSUInteger)wBufferSize biasBuffer:(NSValue *)bBuffer weightBufferSize:(NSUInteger)bBufferSize andStructureBuffer:(NSValue *)structureBuffer 21 | { 22 | self = [super init]; 23 | if (self) 24 | { 25 | self.weightsBuffer = wBuffer; 26 | self.biasBuffer = bBuffer; 27 | self.weightsBufferSize = wBufferSize; 28 | self.biasBufferSize = bBufferSize; 29 | self.layerType = layerType; 30 | self.structureBuffer = structureBuffer; 31 | } 32 | return self; 33 | } 34 | 35 | - (void)freeBuffers 36 | { 37 | free([self.weightsBuffer pointerValue]); 38 | free([self.biasBuffer pointerValue]); 39 | free([self.structureBuffer pointerValue]); 40 | } 41 | 42 | + (void)freeLayerBuffers:(NSArray *)layers 43 | { 44 | [layers enumerateObjectsUsingBlock:^(THESLayer *layer, NSUInteger idx, BOOL * _Nonnull stop) 45 | { 46 | [layer freeBuffers]; 47 | }]; 48 | } 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /iOSClient/iOSClient/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // Created by Kurt Jacobs 4 | // Copyright © 2016 RandomDudes. All rights reserved. 5 | // 6 | // 7 | 8 | #import 9 | 10 | @interface ViewController : UIViewController 11 | 12 | @end 13 | 14 | -------------------------------------------------------------------------------- /iOSClient/iOSClient/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // Created by Kurt Jacobs 4 | // Copyright © 2016 RandomDudes. All rights reserved. 5 | // 6 | // 7 | 8 | #import "ViewController.h" 9 | #import "THESDiskFile.h" 10 | #import "THESLayer.h" 11 | 12 | @interface ViewController () 13 | 14 | @end 15 | 16 | @implementation ViewController 17 | 18 | - (void)viewDidLoad 19 | { 20 | [super viewDidLoad]; 21 | 22 | NSArray *layers = [THESDiskFile readLayersBinary:[[NSBundle mainBundle] pathForResource:@"ios_xor" ofType:@"t7ios"]]; 23 | // NSArray *layers = [THESDiskFile readLayersBinary:[[NSBundle mainBundle] pathForResource:@"mnist_ios" ofType:@"t7ios"]]; 24 | [layers enumerateObjectsUsingBlock:^(THESLayer *layer, NSUInteger idx, BOOL * _Nonnull stop) 25 | { 26 | NSLog(@"%@",THES_layer_activations[[layer.layerType integerValue]]); 27 | NSLog(@"%lu",layer.weightsBufferSize); 28 | NSLog(@"%lu",layer.biasBufferSize); 29 | NSLog(@"first value structure buffer: %i",((int*)[layer.structureBuffer pointerValue])[0]); 30 | }]; 31 | 32 | [THESLayer freeLayerBuffers:layers]; 33 | } 34 | 35 | - (void)didReceiveMemoryWarning 36 | { 37 | [super didReceiveMemoryWarning]; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /iOSClient/iOSClient/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // iOSClient 4 | // 5 | // Created by Kurt Jacobs on 2016/07/12. 6 | // Copyright © 2016 RandomDudes. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /iOSClient/iOSClientTests/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 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /iOSClient/iOSClientTests/iOSClientTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // iOSClientTests.m 3 | // iOSClientTests 4 | // 5 | // Created by Kurt Jacobs on 2016/07/12. 6 | // Copyright © 2016 RandomDudes. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface iOSClientTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation iOSClientTests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | // Put setup code here. This method is called before the invocation of each test method in the class. 20 | } 21 | 22 | - (void)tearDown { 23 | // Put teardown code here. This method is called after the invocation of each test method in the class. 24 | [super tearDown]; 25 | } 26 | 27 | - (void)testExample { 28 | // This is an example of a functional test case. 29 | // Use XCTAssert and related functions to verify your tests produce the correct results. 30 | } 31 | 32 | - (void)testPerformanceExample { 33 | // This is an example of a performance test case. 34 | [self measureBlock:^{ 35 | // Put the code you want to measure the time of here. 36 | }]; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /iOSClient/iOSClientUITests/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 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /iOSClient/iOSClientUITests/iOSClientUITests.m: -------------------------------------------------------------------------------- 1 | // 2 | // iOSClientUITests.m 3 | // iOSClientUITests 4 | // 5 | // Created by Kurt Jacobs on 2016/07/12. 6 | // Copyright © 2016 RandomDudes. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface iOSClientUITests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation iOSClientUITests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | 22 | // In UI tests it is usually best to stop immediately when a failure occurs. 23 | self.continueAfterFailure = NO; 24 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 25 | [[[XCUIApplication alloc] init] launch]; 26 | 27 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 28 | } 29 | 30 | - (void)tearDown { 31 | // Put teardown code here. This method is called after the invocation of each test method in the class. 32 | [super tearDown]; 33 | } 34 | 35 | - (void)testExample { 36 | // Use recording to get started writing UI tests. 37 | // Use XCTAssert and related functions to verify your tests produce the correct results. 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /ios_xor.t7ios: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kurtjacobsdev/torch2ios/1edb18d5ac7f2426e9c682a7d25ae38d71c81491/ios_xor.t7ios -------------------------------------------------------------------------------- /mnist.lua: -------------------------------------------------------------------------------- 1 | -- Kurt Jacobs 2 | -- RandomDudes 3 | -- 2016 4 | 5 | require 'torch' 6 | require 'nn' 7 | require 'nnx' 8 | require 'torch2ios' 9 | 10 | torch.setdefaulttensortype('torch.FloatTensor') 11 | mnist_model = torch.load("trainedmnist.net") 12 | 13 | saveForiOS(mnist_model, "mnist_ios") -------------------------------------------------------------------------------- /mnist_ios.t7ios: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kurtjacobsdev/torch2ios/1edb18d5ac7f2426e9c682a7d25ae38d71c81491/mnist_ios.t7ios -------------------------------------------------------------------------------- /mnist_samples.t7iosb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kurtjacobsdev/torch2ios/1edb18d5ac7f2426e9c682a7d25ae38d71c81491/mnist_samples.t7iosb -------------------------------------------------------------------------------- /torch2ios.lua: -------------------------------------------------------------------------------- 1 | -- Kurt Jacobs 2 | -- RandomDudes 3 | -- 2016 4 | 5 | require 'torch2ios_utils' 6 | require 'torch' 7 | 8 | local linear = 1 9 | local spatial_conv = 2 10 | local pooling_max = 3 11 | local pooling_average = 4 12 | 13 | local tanh_activation = 5 14 | local hard_tanh_activation = 6 15 | local log_sigmoid_activation = 7 16 | local log_soft_max_activation = 8 17 | local sigmoid_activation = 9 18 | local relu_activation = 10 19 | 20 | local reshape = 11 21 | 22 | local torchFloatT = 1 23 | local torchDoubleT = 2 24 | local torchIntT = 3 25 | 26 | function saveForiOS(container, filename) 27 | local file = torch.DiskFile(filename..".t7ios", 'w') 28 | file:binary() 29 | local modulesCount = container:listModules() 30 | --Layer Count 31 | file:writeInt(#modulesCount-1) 32 | for idx, value in pairs (modulesCount) do 33 | -- --Network Type Sequential, Parrallel, etc 34 | if idx == 1 then 35 | -- --Network Layers 36 | else 37 | local supported, n, w, b, wc, bc, wlt, blt, linear_v, conv_v, pool_v = processLayer(value) 38 | if supported then 39 | appendBinary(file,n,w,b,wc,bc,wlt,blt,linear_v,conv_v,pool_v) 40 | else 41 | print ("unsupported layer with name: "..n.." encountered.") 42 | file:close() 43 | os.remove(filename..".t7ios") 44 | os.exit(-1) 45 | end 46 | end 47 | end 48 | file:close() 49 | end 50 | 51 | function resolveLayerName(name) 52 | local id = 0 53 | if name == "nn.Linear" then 54 | id = linear 55 | elseif name == "nn.SpatialMaxPooling" then 56 | id = pooling_max 57 | elseif name == "nn.SpatialAveragePooling" then 58 | id = pooling_average 59 | elseif name == "nn.SpatialConvolution" or name == "nn.SpatialConvolutionMM" then 60 | id = spatial_conv 61 | elseif name == "nn.Tanh" then 62 | id = tanh_activation 63 | elseif name == "nn.ReLU" then 64 | id = relu_activation 65 | elseif name == "nn.Sigmoid" then 66 | id = sigmoid_activation 67 | elseif name == "nn.HardTanh" then 68 | id = hard_tanh_activation 69 | elseif name == "nn.LogSigmoid" then 70 | id = log_sigmoid_activation 71 | elseif name == "nn.LogSoftMax" then 72 | id = log_soft_max_activation 73 | elseif name == "nn.Reshape" then 74 | id = reshape 75 | else 76 | id = -1 77 | end 78 | return id 79 | end 80 | 81 | function resolveTensorType(tensorType) 82 | local id = 0 83 | if tensorType == "torch.FloatTensor" then 84 | id = torchFloatT 85 | elseif tensorType == "torch.DoubleTensor" then 86 | id = torchDoubleT 87 | elseif tensorType == "torch.IntTensor" then 88 | id = torchIntT 89 | end 90 | return id; 91 | end 92 | 93 | function appendBinary(file, name, weight, bias, weight_c, bias_c, weight_layer_type, bias_layer_type, linear_values, conv_values, pool_values) 94 | --Write Layer Type ID 95 | local layerid = resolveLayerName(name) 96 | file:writeInt(layerid) 97 | 98 | if name == "nn.Linear" then 99 | for i=1,#linear_values do 100 | file:writeInt(linear_values[i]) 101 | end 102 | elseif name == "nn.SpatialConvolutionMM" or name == "nn.SpatialConvolution" then 103 | for i=1,#conv_values do 104 | file:writeInt(conv_values[i]) 105 | end 106 | elseif name == "nn.SpatialMaxPooling" or name == "nn.SpatialAveragePooling" then 107 | for i=1,#pool_values do 108 | file:writeInt(pool_values[i]) 109 | end 110 | else 111 | for i=1,#linear_values do 112 | file:writeInt(linear_values[i]) 113 | end 114 | end 115 | 116 | --Write Weights 117 | if weight:nDimension() > 0 then 118 | local weightTensorTypeID = resolveTensorType(weight_layer_type) 119 | file:writeInt(weightTensorTypeID) 120 | file:writeInt(weight_c) 121 | local t_data = torch.data(weight) 122 | if weightTensorTypeID == torchFloatT then 123 | for i = 0,weight:nElement()-1 do file:writeFloat(t_data[i]) end 124 | elseif weightTensorTypeID == torchIntT then 125 | for i = 0,weight:nElement()-1 do file:writeInt(t_data[i]) end 126 | elseif weightTensorTypeID == torchDoubleT then 127 | for i = 0,weight:nElement()-1 do file:writeDouble(t_data[i]) end 128 | end 129 | end 130 | 131 | -- Write Biases 132 | if bias:nDimension() > 0 then 133 | local biasTensorTypeID = resolveTensorType(bias_layer_type) 134 | file:writeInt(biasTensorTypeID) 135 | file:writeInt(bias_c) 136 | local t_data = torch.data(bias) 137 | if biasTensorTypeID == torchFloatT then 138 | for i = 0,bias:nElement()-1 do file:writeFloat(t_data[i]) end 139 | elseif weightTensorTypeID == torchIntT then 140 | for i = 0,bias:nElement()-1 do file:writeInt(t_data[i]) end 141 | elseif weightTensorTypeID == torchDoubleT then 142 | for i = 0,bias:nElement()-1 do file:writeDouble(t_data[i]) end 143 | end 144 | end 145 | end 146 | 147 | function isSupportedLayer(layerName) 148 | if resolveLayerName(layerName) > 0 then 149 | return true 150 | end 151 | return false 152 | end 153 | 154 | function processLayer(layerData) 155 | --Layer Name 156 | local name = torch.type(layerData) 157 | if isSupportedLayer(name) == false then 158 | return false, name 159 | end 160 | --Layer Weights & Biases 161 | local weight_c = 0 162 | local weight = torch.Tensor() 163 | local bias_c = 0 164 | local bias = torch.Tensor() 165 | 166 | --Layer Data Type 167 | local wltype = nil 168 | local bltype = nil 169 | 170 | local linear_input_size = nil 171 | local linear_output_size = nil 172 | 173 | local conv_input_plane = nil 174 | local conv_output_plane = nil 175 | local conv_kernel_width = nil 176 | local conv_kernel_height = nil 177 | local conv_shift_width = nil 178 | local conv_shift_height = nil 179 | local conv_pad_width = nil 180 | local conv_pad_height = nil 181 | 182 | local pool_kernel_width = nil 183 | local pool_kernel_height = nil 184 | local pool_shift_width = nil 185 | local pool_shift_height = nil 186 | local pool_pad_width = nil 187 | local pool_pad_height = nil 188 | 189 | if name == "nn.Linear" then 190 | linear_input_size = layerData.gradInput:size(layerData.gradInput:dim()) 191 | linear_output_size = layerData.output:size(layerData.output:dim()) 192 | elseif name == "nn.SpatialConvolutionMM" or name == "nn.SpatialConvolution" then 193 | conv_input_plane = layerData.nInputPlane 194 | conv_output_plane = layerData.nOutputPlane 195 | conv_kernel_width = layerData.kW 196 | conv_kernel_height = layerData.kH 197 | conv_shift_width = layerData.dW 198 | conv_shift_height = layerData.dH 199 | conv_pad_width = layerData.padW 200 | conv_pad_height = layerData.padH 201 | elseif name == "nn.SpatialMaxPooling" or name == "nn.SpatialAveragePooling" then 202 | pool_kernel_width = layerData.kW 203 | pool_kernel_height = layerData.kH 204 | pool_shift_width = layerData.dW 205 | pool_shift_height = layerData.dH 206 | pool_pad_width = layerData.padW 207 | pool_pad_height = layerData.padH 208 | else 209 | -- Other Layer Such as Activation or Reshape.. 210 | linear_input_size = layerData.gradInput:size(layerData.gradInput:dim()) 211 | linear_output_size = layerData.output:size(layerData.output:dim()) 212 | end 213 | 214 | if layerData.weight ~= nil then 215 | weight = torch2ios_utils.flatten(layerData.weight) 216 | weight_c = weight:size(1) 217 | wltype = weight:type() 218 | end 219 | if layerData.bias ~= nil then 220 | bias = torch2ios_utils.flatten(layerData.bias) 221 | bias_c = bias:size(1) 222 | bltype = bias:type() 223 | end 224 | 225 | return true, name, weight, bias, weight_c, bias_c, wltype, bltype, {linear_input_size,linear_output_size}, {conv_input_plane,conv_output_plane,conv_kernel_width,conv_kernel_height,conv_shift_width,conv_shift_height,conv_pad_width,conv_pad_height},{pool_kernel_width,pool_kernel_height,pool_shift_width,pool_shift_height,pool_pad_width,pool_pad_height} 226 | end -------------------------------------------------------------------------------- /torch2ios_reader.c: -------------------------------------------------------------------------------- 1 | // Kurt Jacobs 2 | // RandomDudes 3 | // 2016 4 | 5 | #include 6 | #include 7 | 8 | #define CONV_LAYER_STRUCTURE_COUNT 8 9 | #define LINEAR_LAYER_STRUCTURE_COUNT 2 10 | #define POOLING_LAYER_STRUCTURE_COUNT 6 11 | 12 | typedef struct layer_entry 13 | { 14 | int layertype; 15 | int *structure_buffer; 16 | int datatype_w; 17 | int datatype_b; 18 | union 19 | { 20 | float *weights_buff_f; 21 | int *weights_buff_i; 22 | double *weights_buff_d; 23 | }weight_buffers; 24 | union 25 | { 26 | float *bias_buff_f; 27 | int *bias_buff_i; 28 | double *bias_buff_d; 29 | }bias_buffers; 30 | int weight_buffer_size; 31 | int bias_buffer_size; 32 | } TORCH_LAYER; 33 | 34 | const char* layers_and_activations[] = {"","nn.Linear","nn.SpatialConvolution","nn.SpatialMaxPooling","nn.SpatialAveragePooling","nn.Tanh","nn.HardTanh","nn.LogSigmoid","nn.LogSoftMax","nn.Sigmoid","nn.ReLU","nn.Reshape"}; 35 | const char* tensor_types[] = {"","torch.FloatTensor","torch.DoubleTensor","torch.IntTensor"}; 36 | 37 | void read_bin(char filename [], TORCH_LAYER **layers_pp, int *layers_count) 38 | { 39 | FILE *file_reader; 40 | file_reader=fopen(filename,"rb"); 41 | if (!file_reader) 42 | { 43 | printf("Unable to open file!"); 44 | return; 45 | } 46 | 47 | fread(layers_count,sizeof(int),1,file_reader); 48 | 49 | if (*layers_count <= 0) 50 | { 51 | return; 52 | } 53 | 54 | TORCH_LAYER *layers_array = (TORCH_LAYER *) calloc(*layers_count,sizeof(TORCH_LAYER)); 55 | 56 | int lcc = *layers_count; 57 | for (int i = 0; i < lcc; i++) 58 | { 59 | int wc = 0; 60 | int bc = 0; 61 | int layertype = 0; 62 | int in_size = 0; 63 | int out_size = 0; 64 | int datatype_w = 0; 65 | int datatype_b = 0; 66 | void *weights = NULL; 67 | void *bias = NULL; 68 | int *structure_buffer; 69 | 70 | fread(&layertype,sizeof(int),1,file_reader); 71 | if (layertype == 1) 72 | { 73 | structure_buffer = (int *)calloc(LINEAR_LAYER_STRUCTURE_COUNT,sizeof(int)); 74 | fread(structure_buffer,sizeof(int),LINEAR_LAYER_STRUCTURE_COUNT,file_reader); 75 | } 76 | else if (layertype == 2) 77 | { 78 | structure_buffer = (int *)calloc(CONV_LAYER_STRUCTURE_COUNT,sizeof(int)); 79 | fread(structure_buffer,sizeof(int),CONV_LAYER_STRUCTURE_COUNT,file_reader); 80 | } 81 | else if (layertype == 3 || layertype == 4) 82 | { 83 | structure_buffer = (int *)calloc(POOLING_LAYER_STRUCTURE_COUNT,sizeof(int)); 84 | fread(structure_buffer,sizeof(int),POOLING_LAYER_STRUCTURE_COUNT,file_reader); 85 | } 86 | else 87 | { 88 | structure_buffer = (int *)calloc(LINEAR_LAYER_STRUCTURE_COUNT,sizeof(int)); 89 | fread(structure_buffer,sizeof(int),LINEAR_LAYER_STRUCTURE_COUNT,file_reader); 90 | } 91 | 92 | if (layertype <= 2) 93 | { 94 | fread(&datatype_w,sizeof(int),1,file_reader); 95 | fread(&wc,sizeof(int),1,file_reader); 96 | if (datatype_w == 1) 97 | { 98 | weights = (float *)calloc(wc,sizeof(float)); 99 | fread(weights,sizeof(float),wc,file_reader); 100 | } 101 | else if (datatype_w == 2) 102 | { 103 | weights = (double *)calloc(wc,sizeof(double)); 104 | fread(weights,sizeof(double),wc,file_reader); 105 | } 106 | else if (datatype_w == 3) 107 | { 108 | weights = (int *)calloc(wc,sizeof(int)); 109 | fread(weights,sizeof(int),wc,file_reader); 110 | } 111 | fread(&datatype_b,sizeof(int),1,file_reader); 112 | fread(&bc,sizeof(int),1,file_reader); 113 | if (datatype_w == 1) 114 | { 115 | bias = (float *)calloc(bc,sizeof(float)); 116 | fread(bias,sizeof(float),bc,file_reader); 117 | } 118 | else if (datatype_w == 2) 119 | { 120 | bias = (double *)calloc(bc,sizeof(double)); 121 | fread(bias,sizeof(double),bc,file_reader); 122 | } 123 | else if (datatype_w == 3) 124 | { 125 | bias = (int *)calloc(bc,sizeof(int)); 126 | fread(bias,sizeof(int),bc,file_reader); 127 | } 128 | } 129 | 130 | layers_array[i].layertype = layertype; 131 | layers_array[i].structure_buffer = structure_buffer; 132 | layers_array[i].datatype_w = datatype_w; 133 | layers_array[i].datatype_b = datatype_b; 134 | //floatTensor 135 | if (datatype_w == 1 && datatype_b == 1) 136 | { 137 | layers_array[i].weight_buffers.weights_buff_f = (float*)weights; 138 | layers_array[i].bias_buffers.bias_buff_f = (float*)bias; 139 | } 140 | //doubleTensor 141 | else if (datatype_w == 2 && datatype_b == 2) 142 | { 143 | layers_array[i].weight_buffers.weights_buff_d = (double*)weights; 144 | layers_array[i].bias_buffers.bias_buff_d = (double*)bias; 145 | } 146 | //intTensor 147 | else if (datatype_w == 3 && datatype_b == 3) 148 | { 149 | layers_array[i].weight_buffers.weights_buff_i = (int*)weights; 150 | layers_array[i].bias_buffers.bias_buff_i = (int*)bias; 151 | } 152 | layers_array[i].weight_buffer_size = wc; 153 | layers_array[i].bias_buffer_size = bc; 154 | layers_count++; 155 | } 156 | *layers_pp = layers_array; 157 | 158 | fclose(file_reader); 159 | } 160 | 161 | int main() 162 | { 163 | TORCH_LAYER ** layers_pp; 164 | int lc = 0; 165 | read_bin("ios_xor.t7ios",layers_pp,&lc); 166 | TORCH_LAYER *layers_p = *layers_pp; 167 | 168 | printf("\n"); 169 | for (int i = 0; i < lc; i ++) 170 | { 171 | printf("Layer Type: %s\n", layers_and_activations[layers_p[i].layertype]); 172 | if (layers_p[i].datatype_w > 0) 173 | { 174 | printf("DataType W: %s\n", tensor_types[layers_p[i].datatype_w]); 175 | } 176 | if (layers_p[i].datatype_b > 0) 177 | { 178 | printf("DataType B: %s\n", tensor_types[layers_p[i].datatype_b]); 179 | } 180 | if (layers_p[i].weight_buffers.weights_buff_f != NULL || layers_p[i].weight_buffers.weights_buff_i != NULL || layers_p[i].weight_buffers.weights_buff_d != NULL) 181 | { 182 | printf("Weight Buffer Size:%i\n",layers_p[i].weight_buffer_size); 183 | if (layers_p[i].datatype_w == 1) 184 | { 185 | printf("First Value In Weight Buffer:%f\n",layers_p[i].weight_buffers.weights_buff_f[0]); 186 | } 187 | else if (layers_p[i].datatype_w == 2) 188 | { 189 | printf("First Value In Weight Buffer:%lf\n",layers_p[i].weight_buffers.weights_buff_d[0]); 190 | } 191 | else if (layers_p[i].datatype_w == 3) 192 | { 193 | printf("First Value In Weight Buffer:%i\n",layers_p[i].weight_buffers.weights_buff_i[0]); 194 | } 195 | } 196 | if (layers_p[i].bias_buffers.bias_buff_f != NULL || layers_p[i].bias_buffers.bias_buff_i != NULL || layers_p[i].bias_buffers.bias_buff_d != NULL) 197 | { 198 | printf("Bias Buffer Size:%i\n",layers_p[i].bias_buffer_size); 199 | if (layers_p[i].datatype_b == 1) 200 | { 201 | printf("First Value In Bias Buffer:%f\n",layers_p[i].bias_buffers.bias_buff_f[0]); 202 | } 203 | else if (layers_p[i].datatype_b == 2) 204 | { 205 | printf("First Value In Bias Buffer:%lf\n",layers_p[i].bias_buffers.bias_buff_d[0]); 206 | } 207 | else if (layers_p[i].datatype_b == 3) 208 | { 209 | printf("First Value In Bias Buffer:%i\n",layers_p[i].bias_buffers.bias_buff_i[0]); 210 | } 211 | } 212 | printf("First Value In Structure Buffer:%i\n",layers_p[i].structure_buffer[0]); 213 | printf("\n"); 214 | } 215 | free (layers_p); 216 | 217 | return 0; 218 | } -------------------------------------------------------------------------------- /torch2ios_utils.lua: -------------------------------------------------------------------------------- 1 | -- Kurt Jacobs 2 | -- RandomDudes 3 | -- 2016 4 | 5 | torch2ios_utils = {} 6 | 7 | function torch2ios_utils.flatten(tensor) 8 | local dimensions = tensor:nDimension() 9 | if dimensions == 1 then 10 | return tensor 11 | end 12 | 13 | local tensorSize = 0 14 | tensorSize = tensor:size(1) * tensor:size(2) 15 | if dimensions > 2 then 16 | for i=3,dimensions,1 do 17 | tensorSize = tensorSize * tensor:size(i) 18 | end 19 | end 20 | 21 | t = tensor:clone() 22 | t:resizeAs(torch.Tensor(tensorSize)) 23 | return t 24 | end -------------------------------------------------------------------------------- /xor.lua: -------------------------------------------------------------------------------- 1 | require 'torch' 2 | require 'nn' 3 | require 'torch2ios' 4 | 5 | torch.setdefaulttensortype('torch.FloatTensor') 6 | 7 | mlp = nn.Sequential(); 8 | inputs = 2; outputs = 1; HUs = 20; 9 | mlp:add(nn.Linear(inputs, HUs)) 10 | mlp:add(nn.Tanh()) 11 | mlp:add(nn.Linear(HUs, outputs)) 12 | 13 | criterion = nn.MSECriterion() 14 | 15 | for i = 1,2500 do 16 | local input= torch.randn(2); 17 | local output= torch.Tensor(1); 18 | if input[1]*input[2] > 0 then 19 | output[1] = -1 20 | else 21 | output[1] = 1 22 | end 23 | 24 | criterion:forward(mlp:forward(input), output) 25 | mlp:zeroGradParameters() 26 | mlp:backward(input, criterion:backward(mlp.output, output)) 27 | mlp:updateParameters(0.01) 28 | end 29 | 30 | saveForiOS(mlp,"ios_xor") --------------------------------------------------------------------------------