Matrix-exponentiation operator: Difference between revisions
Content added Content deleted
ReeceGoding (talk | contribs) m (→{{header|R}}) |
ReeceGoding (talk | contribs) m (→Infix operator: Improved syntax.) |
||
Line 2,869: | Line 2,869: | ||
===Infix operator=== |
===Infix operator=== |
||
The task wants the implementation to be "as an operator". Given that R lets us define new infix operators, it seems fitting to show how to do this. Ideally, for a matrix a and int n, we'd want to be able to use a^n. R actually has this already, but it's not what the task wants: |
The task wants the implementation to be "as an operator". Given that R lets us define new infix operators, it seems fitting to show how to do this. Ideally, for a matrix a and int n, we'd want to be able to use a^n. R actually has this already, but it's not what the task wants: |
||
<lang rsplus>a<-matrix(c(1,2,3,4),2,2) |
<lang rsplus>a <- matrix(c(1, 2, 3, 4), 2, 2) |
||
a^1 |
a^1 |
||
a^2</lang> |
a^2</lang> |
||
Line 2,882: | Line 2,882: | ||
[2,] 4 16</pre> |
[2,] 4 16</pre> |
||
As we can see, it instead returns the given matrix with its elements raised to the nth power. Overwriting the ^ operator would be dangerous and rude. However, R's base library suggests an alternative. %*% is already defined as matrix multiplication, so why not use %^% for exponentiation? |
As we can see, it instead returns the given matrix with its elements raised to the nth power. Overwriting the ^ operator would be dangerous and rude. However, R's base library suggests an alternative. %*% is already defined as matrix multiplication, so why not use %^% for exponentiation? |
||
<lang rsplus>`%^%`<-function(mat,n) |
<lang rsplus>`%^%` <- function(mat, n) |
||
{ |
{ |
||
is.wholenumber<-function(x,tol=.Machine$double.eps^0.5) |
is.wholenumber <- function(x, tol = .Machine$double.eps^0.5) abs(x - round(x)) < tol#See the docs for is.integer |
||
if(is.matrix(mat) && is.numeric(n) && is.wholenumber(n)) |
if(is.matrix(mat) && is.numeric(n) && is.wholenumber(n)) |
||
{ |
{ |
||
if(n==0) |
if(n==0) diag(nrow = nrow(mat))#Identity matrix of mat's dimensions |
||
else if(n==1) |
else if(n == 1) mat |
||
else if(n>1) |
else if(n > 1) mat %*% (mat%^%(n - 1)) |
||
else stop("Invalid n.") |
else stop("Invalid n.") |
||
} |
} |
||
Line 2,895: | Line 2,895: | ||
} |
} |
||
#For output: |
#For output: |
||
a%^%0 |
a %^% 0 |
||
a%^%1 |
a %^% 1 |
||
a%^%2 |
a %^% 2 |
||
a%*%a%*%a#Base R's equivalent of a%^%3 |
a %*% a %*% a#Base R's equivalent of a %^% 3 |
||
a%^%3 |
a %^% 3 |
||
nonSquareMatrix<-matrix(c(1,2,3,4,5,6),nrow=2,ncol=3) |
nonSquareMatrix <- matrix(c(1, 2, 3, 4, 5, 6), nrow = 2, ncol = 3) |
||
nonSquareMatrix%^%1 |
nonSquareMatrix %^% 1 |
||
nonSquareMatrix%^%2#R's %*% will throw the error for us</lang> |
nonSquareMatrix %^% 2#R's %*% will throw the error for us</lang> |
||
{{out}} |
{{out}} |
||
<pre>> a%^%0 |
<pre>> a %^% 0 |
||
[,1] [,2] |
[,1] [,2] |
||
[1,] 1 0 |
[1,] 1 0 |
||
[2,] 0 1 |
[2,] 0 1 |
||
> a%^%1 |
> a %^% 1 |
||
[,1] [,2] |
[,1] [,2] |
||
[1,] 1 3 |
[1,] 1 3 |
||
[2,] 2 4 |
[2,] 2 4 |
||
> a%^%2 |
> a %^% 2 |
||
[,1] [,2] |
[,1] [,2] |
||
[1,] 7 15 |
[1,] 7 15 |
||
[2,] 10 22 |
[2,] 10 22 |
||
> a%*%a%*%a#Base R's equivalent of a%^%3 |
> a %*% a %*% a#Base R's equivalent of a %^% 3 |
||
[,1] [,2] |
[,1] [,2] |
||
[1,] 37 81 |
[1,] 37 81 |
||
[2,] 54 118 |
[2,] 54 118 |
||
> a%^%3 |
> a %^% 3 |
||
[,1] [,2] |
[,1] [,2] |
||
[1,] 37 81 |
[1,] 37 81 |
||
[2,] 54 118 |
[2,] 54 118 |
||
> nonSquareMatrix<-matrix(c(1,2,3,4,5,6),nrow=2,ncol=3) |
> nonSquareMatrix <- matrix(c(1, 2, 3, 4, 5, 6), nrow = 2, ncol = 3) |
||
> nonSquareMatrix%^%1 |
> nonSquareMatrix %^% 1 |
||
[,1] [,2] [,3] |
[,1] [,2] [,3] |
||
[1,] 1 3 5 |
[1,] 1 3 5 |
||
[2,] 2 4 6 |
[2,] 2 4 6 |
||
> nonSquareMatrix%^%2#R's %*% will throw the error for us |
> nonSquareMatrix %^% 2#R's %*% will throw the error for us |
||
Error in mat %*% (mat %^% (n - 1)) : non-conformable arguments</pre> |
Error in mat %*% (mat %^% (n - 1)) : non-conformable arguments</pre> |
||
Our code is far from efficient and could do with more error-checking, but it demonstrates the principle. If we wanted to do this properly, we'd use a library - ideally one that calls C code. Following the previous submission's example, we can just do this: |
Our code is far from efficient and could do with more error-checking, but it demonstrates the principle. If we wanted to do this properly, we'd use a library - ideally one that calls C code. Following the previous submission's example, we can just do this: |
||
<lang rsplus>library(Biodem) |
<lang rsplus>library(Biodem) |
||
`%^%`<-function(mat,n) Biodem::mtx.exp(mat,n)</lang> |
`%^%` <- function(mat, n) Biodem::mtx.exp(mat, n)</lang> |
||
And it will work just the same, except for being much faster and throwing an error on nonSquareMatrix%^%1. |
And it will work just the same, except for being much faster and throwing an error on nonSquareMatrix %^% 1. |
||
=={{header|Racket}}== |
=={{header|Racket}}== |