makeCacheMatrix()

Calculating the inverse as well as performing other operations can be a very expensive task. It may be useful or more memory efficient to save(cache) the inverse if this operation will be repeated. Lexical scoping in R makes this possible. In lexical scoping R looks up the value of a variable in the environment where the function was defined, not where it was called.

makeCacheMatrix is a function to:
- set the value of the matrix
- get the value of the matrix
- set the inverse of the matrix
- retrieve the inverse of the matrix

The super assignment operator (<<-) is utilized in the function below. “Super assignment, <<-, never creates a variable in the current environment, but instead modifies an existing variable found in a parent environment.”

makeCacheMatrix <- function(x = matrix()) {
  inv <- NULL
  
  set <- function(m){
    x <<- m
    inv <<- NULL
  }
  
  get <- function() x
  
  setInv <- function(a){inv <<- a}
  
  getInv <- function() inv
  
  list(set = set, 
       get = get,
       setInv = setInv, 
       getInv = getInv)

}

cacheSolve()

cacheSolve() takes a makeCacheMatrix object and returns the inverse of the associated matrix. cacheSolve() assumes that the matrix set by makeCacheMatrix is invertible.

If the inverse is cached, cacheSolve retrieves and returns it; otherwise, it calculates the inverse, caches it before returning the inverse to the user.

cacheSolve <- function(x, ...) {
  ## Return a matrix that is the inverse of 'x'
  inv <- x$getInv()
  
  if(!is.null(inv)){
    message('Getting Cached inverse...')
    return(inv)
  }else{
    message('Inverse is not cached! Calculating inverse...')
    
    mat <- x$get()
    inv <- solve(mat, ...)
    x$setInv(inv)
    inv
  }
  
  
}

TESTING

set.seed(1)
m <- matrix(sample(0:10, 9), nrow = 3, ncol = 3)
m
     [,1] [,2] [,3]
[1,]    8    0    2
[2,]    3    1   10
[3,]    6    4    9
Instantiate an instance of makeCacheMatrix
M <- makeCacheMatrix(m)
M$get()
     [,1] [,2] [,3]
[1,]    8    0    2
[2,]    3    1   10
[3,]    6    4    9
M$getInv()
NULL

Get Inverse of M(an object of makeCacheMatrix)

Since this is the first time cacheSolve is called for object M, the inverse is not stored (i.e. M$getInv() yields NULL). cacheSolve(M) calculates and returns the inverse.

cacheSolve(M) # (1)
Inverse is not cached! Calculating inverse...
            [,1]        [,2]         [,3]
[1,]  0.13135593 -0.03389831  0.008474576
[2,] -0.13983051 -0.25423729  0.313559322
[3,] -0.02542373  0.13559322 -0.033898305

Running cachSolve(M) a second time yields:

cacheSolve(M)
Getting Cached inverse...
            [,1]        [,2]         [,3]
[1,]  0.13135593 -0.03389831  0.008474576
[2,] -0.13983051 -0.25423729  0.313559322
[3,] -0.02542373  0.13559322 -0.033898305

The cached inverse was retrieved since inverse was already calculated in (1) above.

Source:
- https://adv-r.hadley.nz/index.html
- https://www.coursera.org/learn/r-programming/home/info

LS0tDQp0aXRsZTogIkxleGljYWwgU2NvcGluZzogQ2FjaGluZyBEYXRhIg0KYXV0aG9yOiAiU0sgTWlsbGVyIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KIyMjIyAqKm1ha2VDYWNoZU1hdHJpeCgpKioNCg0KQ2FsY3VsYXRpbmcgdGhlIGludmVyc2UgYXMgd2VsbCBhcyBwZXJmb3JtaW5nIG90aGVyIG9wZXJhdGlvbnMgY2FuIGJlIGEgdmVyeSANCmV4cGVuc2l2ZSB0YXNrLiBJdCBtYXkgYmUgdXNlZnVsIG9yIG1vcmUgbWVtb3J5IGVmZmljaWVudCB0byBzYXZlKGNhY2hlKSB0aGUgDQppbnZlcnNlIGlmIHRoaXMgb3BlcmF0aW9uIHdpbGwgYmUgcmVwZWF0ZWQuIFtMZXhpY2FsIHNjb3BpbmddKGh0dHBzOi8vYWR2LXIuaGFkbGV5Lm56L2Z1bmN0aW9ucy5odG1sI2xleGljYWwtc2NvcGluZykgaW4gUiBtYWtlcyB0aGlzIHBvc3NpYmxlLiBJbiBbbGV4aWNhbCBzY29waW5nXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9TY29wZV8oY29tcHV0ZXJfc2NpZW5jZSkjTGV4aWNhbF9zY29wZV92cy5fZHluYW1pY19zY29wZSkgUiBsb29rcyB1cCB0aGUgdmFsdWUgb2YgYSB2YXJpYWJsZSBpbiB0aGUgZW52aXJvbm1lbnQNCndoZXJlIHRoZSBmdW5jdGlvbiB3YXMgZGVmaW5lZCwgbm90IHdoZXJlIGl0IHdhcyBjYWxsZWQuDQoNCm1ha2VDYWNoZU1hdHJpeCBpcyBhIGZ1bmN0aW9uIHRvOiAgDQotIHNldCB0aGUgdmFsdWUgb2YgdGhlIG1hdHJpeCAgDQotIGdldCB0aGUgdmFsdWUgb2YgdGhlIG1hdHJpeCAgDQotIHNldCB0aGUgaW52ZXJzZSBvZiB0aGUgbWF0cml4ICAgDQotIHJldHJpZXZlIHRoZSBpbnZlcnNlIG9mIHRoZSBtYXRyaXggIA0KDQpUaGUgW3N1cGVyIGFzc2lnbm1lbnQgb3BlcmF0b3IgKDw8LSldKGh0dHBzOi8vYWR2LXIuaGFkbGV5Lm56L2Vudmlyb25tZW50cy5odG1sKSBpcyB1dGlsaXplZCBpbiB0aGUgZnVuY3Rpb24gYmVsb3cuICJbU3VwZXIgYXNzaWdubWVudF0oaHR0cHM6Ly9hZHYtci5oYWRsZXkubnovZW52aXJvbm1lbnRzLmh0bWwpLCA8PC0sIG5ldmVyIGNyZWF0ZXMgYSB2YXJpYWJsZSBpbiB0aGUgY3VycmVudCBlbnZpcm9ubWVudCwgYnV0IGluc3RlYWQgbW9kaWZpZXMgYW4gZXhpc3RpbmcgdmFyaWFibGUgZm91bmQgaW4gYSBwYXJlbnQgZW52aXJvbm1lbnQuIg0KDQpgYGB7cn0NCm1ha2VDYWNoZU1hdHJpeCA8LSBmdW5jdGlvbih4ID0gbWF0cml4KCkpIHsNCiAgaW52IDwtIE5VTEwNCiAgDQogIHNldCA8LSBmdW5jdGlvbihtKXsNCiAgICB4IDw8LSBtDQogICAgaW52IDw8LSBOVUxMDQogIH0NCiAgDQogIGdldCA8LSBmdW5jdGlvbigpIHgNCiAgDQogIHNldEludiA8LSBmdW5jdGlvbihhKXtpbnYgPDwtIGF9DQogIA0KICBnZXRJbnYgPC0gZnVuY3Rpb24oKSBpbnYNCiAgDQogIGxpc3Qoc2V0ID0gc2V0LCANCiAgICAgICBnZXQgPSBnZXQsDQogICAgICAgc2V0SW52ID0gc2V0SW52LCANCiAgICAgICBnZXRJbnYgPSBnZXRJbnYpDQoNCn0NCmBgYA0KDQoNCg0KIyMjIyAqKmNhY2hlU29sdmUoKSoqDQoNCmNhY2hlU29sdmUoKSB0YWtlcyBhIG1ha2VDYWNoZU1hdHJpeCBvYmplY3QgYW5kIHJldHVybnMgdGhlIGludmVyc2Ugb2YgdGhlIA0KYXNzb2NpYXRlZCBtYXRyaXguIGNhY2hlU29sdmUoKSAqYXNzdW1lcyogdGhhdCB0aGUgbWF0cml4IHNldCBieSBtYWtlQ2FjaGVNYXRyaXggaXMNCioqaW52ZXJ0aWJsZSoqLg0KDQpJZiB0aGUgaW52ZXJzZSBpcyBjYWNoZWQsIGNhY2hlU29sdmUgcmV0cmlldmVzIGFuZCByZXR1cm5zIGl0OyBvdGhlcndpc2UsIGl0IA0KY2FsY3VsYXRlcyB0aGUgaW52ZXJzZSwgY2FjaGVzIGl0IGJlZm9yZSByZXR1cm5pbmcgdGhlIGludmVyc2UgdG8gdGhlIHVzZXIuDQoNCmBgYHtyfQ0KY2FjaGVTb2x2ZSA8LSBmdW5jdGlvbih4LCAuLi4pIHsNCiAgIyMgUmV0dXJuIGEgbWF0cml4IHRoYXQgaXMgdGhlIGludmVyc2Ugb2YgJ3gnDQogIGludiA8LSB4JGdldEludigpDQogIA0KICBpZighaXMubnVsbChpbnYpKXsNCiAgICBtZXNzYWdlKCdHZXR0aW5nIENhY2hlZCBpbnZlcnNlLi4uJykNCiAgICByZXR1cm4oaW52KQ0KICB9ZWxzZXsNCiAgICBtZXNzYWdlKCdJbnZlcnNlIGlzIG5vdCBjYWNoZWQhIENhbGN1bGF0aW5nIGludmVyc2UuLi4nKQ0KICAgIA0KICAgIG1hdCA8LSB4JGdldCgpDQogICAgaW52IDwtIHNvbHZlKG1hdCwgLi4uKQ0KICAgIHgkc2V0SW52KGludikNCiAgICBpbnYNCiAgfQ0KICANCiAgDQp9DQpgYGANCg0KDQoNCg0KDQojIyMjICoqVEVTVElORyoqDQpgYGB7cn0NCnNldC5zZWVkKDEpDQptIDwtIG1hdHJpeChzYW1wbGUoMDoxMCwgOSksIG5yb3cgPSAzLCBuY29sID0gMykNCm0NCmBgYA0KDQoNCg0KIyMjIyMgSW5zdGFudGlhdGUgYW4gaW5zdGFuY2Ugb2YgbWFrZUNhY2hlTWF0cml4DQpgYGB7cn0NCk0gPC0gbWFrZUNhY2hlTWF0cml4KG0pDQpgYGANCg0KYGBge3J9DQpNJGdldCgpDQpgYGANCmBgYHtyfQ0KTSRnZXRJbnYoKQ0KYGBgDQoNCg0KDQojIyMjICoqR2V0IEludmVyc2Ugb2YgTShhbiBvYmplY3Qgb2YgbWFrZUNhY2hlTWF0cml4KSoqDQpTaW5jZSB0aGlzIGlzIHRoZSBmaXJzdCB0aW1lIGNhY2hlU29sdmUgaXMgY2FsbGVkIGZvciBvYmplY3QgTSwgdGhlIGludmVyc2UNCmlzIG5vdCBzdG9yZWQgKGkuZS4gTSRnZXRJbnYoKSB5aWVsZHMgTlVMTCkuIGNhY2hlU29sdmUoTSkgY2FsY3VsYXRlcyBhbmQgDQpyZXR1cm5zIHRoZSBpbnZlcnNlLg0KDQpgYGB7cn0NCmNhY2hlU29sdmUoTSkgIyAoMSkNCmBgYA0KDQoNCg0KUnVubmluZyBgY2FjaFNvbHZlKE0pYCBhIHNlY29uZCB0aW1lIHlpZWxkczoNCmBgYHtyfQ0KY2FjaGVTb2x2ZShNKQ0KYGBgDQoNCg0KVGhlIGNhY2hlZCBpbnZlcnNlIHdhcyByZXRyaWV2ZWQgc2luY2UgaW52ZXJzZSB3YXMgYWxyZWFkeSBjYWxjdWxhdGVkIGluICgxKSBhYm92ZS4NCg0KU291cmNlOiAgDQotIGh0dHBzOi8vYWR2LXIuaGFkbGV5Lm56L2luZGV4Lmh0bWwgIA0KLSBodHRwczovL3d3dy5jb3Vyc2VyYS5vcmcvbGVhcm4vci1wcm9ncmFtbWluZy9ob21lL2luZm8NCg==