From 7c1220ed52b5f4a2da18c54e1c8a96170a6363af Mon Sep 17 00:00:00 2001 From: Bob McDonald Date: Tue, 22 Jul 2014 21:39:54 +0900 Subject: [PATCH 1/3] first pass at making a working version of the homework assignment, likely to be modified after more testing, out fo time for now --- cachematrix.R | 44 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/cachematrix.R b/cachematrix.R index a50be65aa44..213b989d8f2 100644 --- a/cachematrix.R +++ b/cachematrix.R @@ -1,15 +1,47 @@ -## Put comments here that give an overall description of what your -## functions do +## These functions take the sometimes time-consuming task of +## calculating the inverse of a matrix, and ensure that while +## the underlying matrix remains unchanged, the calculation +## of the inverse need only happen once. -## Write a short comment describing this function +## This function takes a matrix as an argument, and contains +## getters and setters for both the matrix itself, and the +## inverse of the matrix. makeCacheMatrix <- function(x = matrix()) { - + inverse <- NULL + set <- function(y) { + x <<- y + inverse <<- NULL + } + get <- function() { + x + } + setInverse <- function(invertedMatrix) { + inverse <<- invertedMatrix + } + getInverse <- function() { + inverse + } + list(set = set, get = get, + setInverse = setInverse, + getInverse = getInverse) } -## Write a short comment describing this function +## This function takes an object created with makeCacheMatrix +## as an argument and returns the inverse of its matrix, from +## cache if it exists, and via calculation that is then cached +## if not. cacheSolve <- function(x, ...) { - ## Return a matrix that is the inverse of 'x' + ## Return a matrix that is the inverse of 'x' + invertedMatrix <- x$getInverse() + if(!is.null(invertedMatrix)) { + message("getting cached data") + return(invertedMatrix) + } + data <- x$get() + invertedMatrix <- solve(data) + x$setInverse(invertedMatrix) + invertedMatrix } From 33ab759d8e860e8cedb387902c15ce363fcc5ba3 Mon Sep 17 00:00:00 2001 From: Bob McDonald Date: Wed, 23 Jul 2014 15:06:15 +0900 Subject: [PATCH 2/3] added some unit tests to check that the functions seem to be doing what they are supposed to --- run_tests.R | 11 +++++++++++ tests/1.R | 23 +++++++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 run_tests.R create mode 100644 tests/1.R diff --git a/run_tests.R b/run_tests.R new file mode 100644 index 00000000000..7f909b46da3 --- /dev/null +++ b/run_tests.R @@ -0,0 +1,11 @@ +library("RUnit") + +source('cachematrix.R') + +test.suite <- defineTestSuite("testTesting", + dirs = file.path("tests"), + testFileRegexp = '^\\d+\\.R') + +test.result <- runTestSuite(test.suite) + +printTextProtocol(test.result) \ No newline at end of file diff --git a/tests/1.R b/tests/1.R new file mode 100644 index 00000000000..4de97086404 --- /dev/null +++ b/tests/1.R @@ -0,0 +1,23 @@ +test.testTesting <- function() { + checkTrue(TRUE) +} + +test.MCM <- function() { + testMatrix <- matrix(c(4,2,7,6),2,2) + newmat <- matrix(c(1,2,3,4),2,2) + testMCM <- makeCacheMatrix(testMatrix) + checkEquals(testMatrix, testMCM$get()) + checkEquals(NULL,testMCM$getInverse()) + testMCM$set(newmat) + checkEquals(newmat, testMCM$get()) + checkEquals(NULL, testMCM$getInverse()) + newSol <- cacheSolve(testMCM) + checkEquals(matrix(c(-2,1,1.5,-0.5),2,2),newSol) + checkEquals(newSol, testMCM$getInverse()) + testMCM$set(testMatrix) + checkEquals(NULL,testMCM$getInverse()) + testSol <- cacheSolve(testMCM) + checkEquals(matrix(c(0.6,-0.2,-0.7,0.4),2,2),testSol) + checkTrue(!is.null(testMCM$getInverse())) + checkEquals(testMCM$getInverse(),testSol) +} \ No newline at end of file From 82d9038440242ef247a4b71140a6b8a14737a183 Mon Sep 17 00:00:00 2001 From: Bob McDonald Date: Thu, 24 Jul 2014 10:13:26 +0900 Subject: [PATCH 3/3] added some more unit tests and comments explaining the parts of the function that had been confusing to me --- cachematrix.R | 13 ++++++++++++- tests/1.R | 49 +++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 51 insertions(+), 11 deletions(-) diff --git a/cachematrix.R b/cachematrix.R index 213b989d8f2..5f9d4158ebf 100644 --- a/cachematrix.R +++ b/cachematrix.R @@ -5,9 +5,15 @@ ## This function takes a matrix as an argument, and contains ## getters and setters for both the matrix itself, and the -## inverse of the matrix. +## inverse of the matrix. When the matrix is changed the +## cache of the inverse matrix is cleared makeCacheMatrix <- function(x = matrix()) { + # I'll confess some minor scoping confusion. I don't + # really understand what environment inverse is being + # created in and why it doesn't end up being shared + # by all instances of makeCacheMatrix, but I tested + # and it doesn't inverse <- NULL set <- function(y) { x <<- y @@ -22,6 +28,11 @@ makeCacheMatrix <- function(x = matrix()) { getInverse <- function() { inverse } + # this list below was confusing to me before so I'm commenting + # to explain it to future me. The last call in a function + # is the one that gets returned, so by returning this list, + # we are providing all the functions to the new object + # being created. list(set = set, get = get, setInverse = setInverse, getInverse = getInverse) diff --git a/tests/1.R b/tests/1.R index 4de97086404..22a39702c98 100644 --- a/tests/1.R +++ b/tests/1.R @@ -6,18 +6,47 @@ test.MCM <- function() { testMatrix <- matrix(c(4,2,7,6),2,2) newmat <- matrix(c(1,2,3,4),2,2) testMCM <- makeCacheMatrix(testMatrix) - checkEquals(testMatrix, testMCM$get()) - checkEquals(NULL,testMCM$getInverse()) + #check that matrix is being set properly + checkEquals(testMatrix, testMCM$get()) #1 + # check that inverse variable properly initialized to NULL + checkEquals(NULL,testMCM$getInverse()) #2 testMCM$set(newmat) - checkEquals(newmat, testMCM$get()) - checkEquals(NULL, testMCM$getInverse()) + # check that setter is working properly + checkEquals(newmat, testMCM$get()) #3 + # check that inverse stays null after set + checkEquals(NULL, testMCM$getInverse()) #4 newSol <- cacheSolve(testMCM) - checkEquals(matrix(c(-2,1,1.5,-0.5),2,2),newSol) - checkEquals(newSol, testMCM$getInverse()) + #check that cacheSolve gives the correct answer (matrix newmat) + checkEquals(matrix(c(-2,1,1.5,-0.5),2,2),newSol) #5 + # check that there is now a value for inverse and that + # getInverse works properly + checkEquals(newSol, testMCM$getInverse()) #6 testMCM$set(testMatrix) - checkEquals(NULL,testMCM$getInverse()) + # check that setting the matrix resets inverse to NULL + checkEquals(NULL,testMCM$getInverse()) #7 testSol <- cacheSolve(testMCM) - checkEquals(matrix(c(0.6,-0.2,-0.7,0.4),2,2),testSol) - checkTrue(!is.null(testMCM$getInverse())) - checkEquals(testMCM$getInverse(),testSol) + # check for the correct answer with another matrix (testMatrix) + checkEquals(matrix(c(0.6,-0.2,-0.7,0.4),2,2),testSol) #8 + # check that the inverse cache is now set + checkTrue(!is.null(testMCM$getInverse())) #9 + # check that the cached value is correct + checkEquals(testMCM$getInverse(),testSol) #10 + # this set of checks creates two makeCacheMatrix objects and + # checks to make sure their caches don't interfere + testMCM$set(testMatrix) + newMCM <- makeCacheMatrix(newmat) + checkTrue(is.null(testMCM$getInverse())) #11 + checkTrue(is.null(newMCM$getInverse())) #12 + checkTrue(is.null(newMCM$inverse)) #13 + checkTrue(is.null(testMCM$inverse)) #14 + cacheSolve(testMCM) + checkTrue(!is.null(testMCM$getInverse())) #15 + checkTrue(is.null(newMCM$getInverse())) #16 + # now we've confirmed that testMCM has a cached inverse + # and newMCM doesn't, and that the value of xxxMCM$inverse + # was null before, now we'll check that they were null + # because you can't pull the data out that way, not + # because the cache hadn't been set yet + checkTrue(is.null(testMCM$inverse)) #17 + checkTrue(is.null(newMCM$inverse)) #18 } \ No newline at end of file