     print("default device = ", defaultDevice);
     
     let commandQueue = defaultDevice.newCommandQueue();
-    
     let commandBuffer = commandQueue.commandBuffer();
-    
     let commandEncoder = commandBuffer.computeCommandEncoder();
     
-    let library : MTLLibrary?;
+    let library: MTLLibrary = generateLibrary(defaultDevice)
     
-    do {
-        let source : String = try String(contentsOfFile: "./addFunction.metal" )
-        library = try defaultDevice.newLibraryWithSource(source, options: nil) // do we need compile options?
-    }
-    catch _ {
-        print("error creating library ...");
-        return;
-    }
-    let myAdditionFunction: MTLFunction = library!.newFunctionWithName("myAddFunction")!;
+    let myAdditionFunction: MTLFunction = library.newFunctionWithName("myAddFunction")!;
     
     let computePipelineState: MTLComputePipelineState?
     do {

    }
}

func computeSumMetal(array1 array1 : [Float], array2 : [Float], inout sumArray : [Float], N : Int) {
    
    let devices: [MTLDevice] = MTLCopyAllDevices();

    commandEncoder.setBuffer(sumBuffer, offset: 0, atIndex: 2);

    // 3. Call the dispatchThreadgroups(_:threadsPerThreadgroup:) method to encode the compute function with a specified number of threadgroups for the grid and the number of threads per threadgroup.
    let threadsPerThreadgroup: MTLSize = MTLSizeMake(256, 1, 1) // a decent guess
    let threadGroups: MTLSize = MTLSizeMake(N / threadsPerThreadgroup.width, 1, 1)
    commandEncoder.dispatchThreadgroups(threadGroups, threadsPerThreadgroup: threadsPerThreadgroup)
    
    // 4. Call endEncoding() to finish encoding the compute commands onto the command buffer.
    commandEncoder.endEncoding();
