From 5a1abd62224c25ff308af040522bf97a2036845f Mon Sep 17 00:00:00 2001 From: Kenneth Dombrowski Date: Mon, 20 Oct 2014 20:49:32 -0400 Subject: [PATCH 1/4] implement makeCacheMatrix & cacheSolve --- cachematrix.R | 76 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 69 insertions(+), 7 deletions(-) diff --git a/cachematrix.R b/cachematrix.R index a50be65aa44..177aa4be3c2 100644 --- a/cachematrix.R +++ b/cachematrix.R @@ -1,15 +1,77 @@ -## Put comments here that give an overall description of what your -## functions do +## makeCacheMatrix accepts x, an invertible square matrix, and returns a list +## of four named functions bound to the input data in the environment of the +## function body (an object constructor). Regarding "invertible square matrices", +## Wikipedia says this... +## +## "In linear algebra, an n-by-n square matrix A is called invertible (also +## nonsingular or nondegenerate) if there exists an n-by-n square matrix B such +## that AB == BA == In where In denotes the n-by-n identity matrix and the +## multiplication used is ordinary matrix multiplication. If this is the case, +## then the matrix B is uniquely determined by A and is called the inverse of A, +## denoted by A−1. +## +## A square matrix that is not invertible is called singular or degenerate. A +## square matrix is singular if and only if its determinant is 0. Singular +## matrices are rare in the sense that a square matrix randomly selected from a +## continuous uniform distribution on its entries will almost never be singular. +## +## Non-square matrices (m-by-n matrices for which m ≠ n) do not have an inverse. +## +## and an "identity matrix" is: +## +## "In linear algebra, the identity matrix or unit matrix of size n is the +## n × n square matrix with ones on the main diagonal and zeros elsewhere. +## +## cacheSolve accepts as an argument the vector/list object already bound to the +## functions added by makeCacheMatrix, and returns the inverse of the matrix x +## originally passed to makeCacheMatrix(), from cache in object's env if exists, +## or after calculating it & storing it in the cache if requested for the first time -## Write a short comment describing this function +## bind invertible square matrix "x" to functions: +## * get() to retrieve data matrix x +## * set(x) to update data matrix x +## * getinverse() returns current value of inverse variable within object's env +## * setinverse(inv) set value of inverse variable within object's env makeCacheMatrix <- function(x = matrix()) { - + inv <- NULL + set <- function(y = matrix()) { + x <<- y # update value of x in outer scope of makeCacheMatrix body + inv <<- NULL # unset value of inv in outer scope in case prev set + } + message("set is created") + get <- function() x + message("get is created") + setinverse <- function(inverse) { + inv <<- inverse # set in outer scope of function body + } + message("setinverse is created") + getinverse <- function() inv + message("getinverse is created") + list(set = set, get = get, setinverse = setinverse, getinverse = getinverse) } -## Write a short comment describing this function - +## return the inverse of the original matrix for object x, which is the object +## returned from makeCacheMatrix. +## +## This uses a pattern called "memoize" in other languages, where the result of +## the operation is cached after the first time it is requested, and subsequent +## requests for the value are returned from the cache. +## +## The inverse itself is calculated by calling solve() with parameter x, any +## optional parameters will also be passed along to solve() (but note, this +## function does not take those into account when reading the cache... if you +## choose to call this with optional parameters to solve(), be sure to +## invalidate the cache before doing so, e.g. x$setinverse(NULL)) cacheSolve <- function(x, ...) { - ## Return a matrix that is the inverse of 'x' + inv <- x$getinverse() + if (! is.null(inv)) { + message("returning inverse from cache") + return(inv) + } + orig_x <- x$get() + inv <- solve(orig_x, ...) + x$setinverse(inv) + inv } From 23455f6933bf9cd0372b7e8e1f7d3aa9f320bd5b Mon Sep 17 00:00:00 2001 From: Kenneth Dombrowski Date: Mon, 20 Oct 2014 20:52:58 -0400 Subject: [PATCH 2/4] rm debug msgs --- cachematrix.R | 4 ---- 1 file changed, 4 deletions(-) diff --git a/cachematrix.R b/cachematrix.R index 177aa4be3c2..1c53f6916c7 100644 --- a/cachematrix.R +++ b/cachematrix.R @@ -39,15 +39,11 @@ makeCacheMatrix <- function(x = matrix()) { x <<- y # update value of x in outer scope of makeCacheMatrix body inv <<- NULL # unset value of inv in outer scope in case prev set } - message("set is created") get <- function() x - message("get is created") setinverse <- function(inverse) { inv <<- inverse # set in outer scope of function body } - message("setinverse is created") getinverse <- function() inv - message("getinverse is created") list(set = set, get = get, setinverse = setinverse, getinverse = getinverse) } From 2e0d615504534af683a0c585e9f890b423bd5741 Mon Sep 17 00:00:00 2001 From: Kenneth Dombrowski Date: Mon, 20 Oct 2014 22:12:37 -0400 Subject: [PATCH 3/4] clearer comment about passing the original matrix to solve(), not the objectified one --- cachematrix.R | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/cachematrix.R b/cachematrix.R index 1c53f6916c7..f0804f91333 100644 --- a/cachematrix.R +++ b/cachematrix.R @@ -55,11 +55,12 @@ makeCacheMatrix <- function(x = matrix()) { ## the operation is cached after the first time it is requested, and subsequent ## requests for the value are returned from the cache. ## -## The inverse itself is calculated by calling solve() with parameter x, any -## optional parameters will also be passed along to solve() (but note, this -## function does not take those into account when reading the cache... if you -## choose to call this with optional parameters to solve(), be sure to -## invalidate the cache before doing so, e.g. x$setinverse(NULL)) +## The inverse itself is calculated by calling solve() with the original matrix +## passed to makeCacheMatrix as parameter, any optional parameters will also be +## passed along to solve() (but note, this function does not take those into +## account when reading the cache... if you choose to call this with optional +## parameters to solve(), be sure to invalidate the cache before doing so, +## e.g. x$setinverse(NULL)) cacheSolve <- function(x, ...) { inv <- x$getinverse() if (! is.null(inv)) { From 6247ab539bc7552cd997cc60e6a19bf620cf50fb Mon Sep 17 00:00:00 2001 From: Kenneth Dombrowski Date: Tue, 21 Oct 2014 13:35:46 -0400 Subject: [PATCH 4/4] be clearer about when you might need to invalidate the cache --- .gitignore | 1 + cachematrix.R | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000000..dc528e536ff --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.Rhistory diff --git a/cachematrix.R b/cachematrix.R index f0804f91333..0216cdb705d 100644 --- a/cachematrix.R +++ b/cachematrix.R @@ -59,8 +59,8 @@ makeCacheMatrix <- function(x = matrix()) { ## passed to makeCacheMatrix as parameter, any optional parameters will also be ## passed along to solve() (but note, this function does not take those into ## account when reading the cache... if you choose to call this with optional -## parameters to solve(), be sure to invalidate the cache before doing so, -## e.g. x$setinverse(NULL)) +## parameters to solve(), and those parameters change, be sure to invalidate the +## cache before doing so, e.g. x$setinverse(NULL)) cacheSolve <- function(x, ...) { inv <- x$getinverse() if (! is.null(inv)) {