This submission enables the following operations for the int64 and uint64 data types:
* Addition
* Subtraction
* Multiplication (element-wise and matrix)
* Division (element-wise only)
* mod, abs, bitshift
Hello! Tried to run the script, but there was an error:
int64 plus...
int64 minus...
int64 times...
int64 matrix multiplication...
Internal error 1028 line 163
incorrect char m
leal ( movl -40(%ebp),wildcard??? Error using ==> mex at 218
Unable to complete successfully.
Error in ==> compile_int64 at 10
mex int64matmul.c
Great functionality for those of us with pre-2011b versions. I had the same error as Vincent, and his solution worked for me too. Off the top of my head I couldn't figure out how to do the lshift and rshift, but I don't actually need them.
It didn't compile out of the box, however.
I tried to compile this on a Debian Stable machine, having gcc-4.3.2 installed.
The compilation of the first mex function aborts with the following error:
int64operation.c:38:1: error: pasting "OPERATOR" and "=" does not give a valid preprocessing token
I had to apply the following modifications:
Current situation:
One macro in each operator source files (#define OPERATOR +) and the OPERATOR_EQ defined as OPERATOR ## = in the (u)int64operation.c source files.
New situation:
Use two separate macro functions.
For example, the contens of int64plus.c is now:
---
#define UNARY_OPERATOR(a,b) ((a) += (b))
#define BINARY_OPERATOR(a,b) ((a) + (b))
#include "int64operation.c"
---
Where the OPERATOR and OPERATOR_EQ were used in int64operation.c:
---
c[i] OPERATOR_EQ b[i];
becomes
UNARY_OPERATOR(c[i], b[i]);
---
c[i] = a[0] OPERATOR b[i];
becomes
c[i] = BINARY_OPERATOR(a[0], b[i]);
---
I don't know if this works for every compiler around there, but for me, this works like a charm...
If you're interested, I can send you my modified version to the address specified in the README.txt file, so that you can more easily update your package.
Although INT64 values can be very large, you can still get an overflow. While Matlab uses saturated arithmetic for integer types, your tools do not. It is important to mention this in the documentation. Implementing a saturation (means: value is the max or min INT value if it exceeds the valid range) is not trivial, and omitting it is no reason to reduce the 5 star rating.
You mention precompiled in the ReadMe - where can I find them?
Following Loren's block about inplace operations, I suggest to replace e.g.:
function c = abs(a) c = a; end
by: function a = abs(a), end
Thanks a lot for this. Could you also add support for _colonobj so that one doesn't get a "Undefined function or method '_colonobj' for input arguments of type 'uint64'" when writing 1:n
1. The reason the check is made in an .m file is that otherwise the MEX files would have to be quite verbose with lots of conversions from various types to int64.
2. I'll implement this optimization
3. Same here
4. OK, I'll change that
5. OK, I guess I could follow Matlab here
6. long long works on GCC, MSVC++ and LCC and feels more standard
7. True, I'll change that
A really needed and useful submission!
The efficiency can be improved significantly:
1. checkinputs: "if length(size(a)) ~= length(size(b)) ... if ~all(size(a) == size(b))" can be combined to: "if isequal(size(a), size(b))". Performing the check in the Mex and omitting the intermediate call of the M-functions would reduce the overhead.
2. (u)int64abs: At first the input is duplicated to plhs[0]. Then it is not necessary to copy positive values from the input to the output. A faster approach:
void mexFunction(...) {
signed long long *c, *cf;
plhs[0] = mxDuplicateArray(prhs[0]);
if (!plhs[0]) ...
c = (signed long long *) mxGetData(plhs[0]); // not mxGetPr
cf = c + mxGetNumberOfElements(plhs[0]);
for ( ; c < cf; c++) {
if (*c < 0L) {*c = -*c; }
}
}
3. Similar improvements for plus, minus, times, rdived: If the 1st input is duplicated already, the operation does not need to access the values from the inputs again. So these lines in (u)int64operations.c:
c[i] = a[i] OPERATOR b[i]
can be changed to the faster:
c[i] OPERATOR b[i]
using e.g. "+=" as operator instead of "+".
4. TMW suggests to use mxGetData instead of mxGetPr to get a pointer to non-DOUBLE arrays. But at least both method works currently.
5. Matlab's MOD can handle 0 as second input, and a user might expect this for the (U)INT64 version also.
6. "long long" is supported by the LCC compiler shipped with Matlab. For (all) other compilers, you can use uint64_T and int64_T as defined in "tmwtypes.h".
7. The check for division by zero can be included in the same loop as the operation to save time.
I can't test this myself, so I cannot rate it. But if it now prevents A*B when A and B are both matrices, neither of which is a scalar, then this is good if it would otherwise have done the wrong thing. Better of course is to implement array multiplication too (perhaps in a future version.) Regardless, there have been a few times recently when I wanted to have int64 operations defined, so this is a good addition to MATLAB.
John, the reason the * operator is included at all is because it is desirable to support operations like
a = int64(2);
b = int64( [1 2; 3 4] );
c = a * b
That is the reason * was included. The next update will issue an error if both a and b are matrices. Thank you for your suggestions.
John -- Thanks for pointing out that Int64 matrix multiplication is element-wise. I should have been more careful, given that the description clearly states that "multiplication and division are element-wise only". This of course explains the O(n^2) behavior.
On a more general point, I wish there was a consistent standard for matrix multiplicaton. For example, in O-Matrix, C= A*B is the same as Matlab, but C=A^2 gives cij = (aij)^2. This is really confusing. In Fortran 90, C=A*B gives cij = aij*bij.
Derek - it points out that even though the function mtimes is provided, this package only claims to support ELEMENTWISE operations.
The quadratic behavior tells me that this code did not do a true matrix multiply. Did you check that A64*B64 was correct in your test? Element wise multiplication will take O(N^2) flops, whereas a matrix multiply (as * is supposed to generate) is O(N^3).
I would have preferred that an error be generated if you use * on a pair of matrices, when that operation will not return the proper result. This would normally make me downrate this code. Since I cannot test it without compiling it, I won't give any rating at all.
This seems to be an excellent package. I used it to test matrix multiplication
and obtained very surprising results : multiplying two 10^4x10^4 int64 matrices took about 2 secs while two doubles took about 35 secs. The double mat-mult used the Math Kernel and all 8 cores while the int64 did not use the Math Kernel.
Also, a 2-degree polyfit of the int64 mat-mult times was very good, i.e., t(n) is O(n^2)!
Can anyone enlighten me? Here is the test function:
function times = TimesInt64(v,degree);
% Test matrix multiplication using int64arithmetic
% int64arithmetic compiled with Microsoft Visual C++ 2008
% Dell Precision 690, 2xQuadcore Xeon 5345, 2.3GHz, 16GB
% Windows Vista 64
% Example : >> times = TimesInt64(1:15,2);
% Derek O'Connor Sept 2009
nvals = v'*10^3;
times = zeros(length(nvals),1);
c = intmax('int64');
for k = 1:length(nvals)
n = nvals(k);
A64=int64(floor(c*rand(n,n)));
B64=int64(floor(c*rand(n,n)));
I used Microsoft Visual C++ Express 2008 to compile the library. "long long" _is_ supported in later versions of Visual C++. Also, "long long" is more supported by other compilers and will probably end up in the next C++ standard as well.
After a quick look I have few comments that I wish the author could correct:
As stated, the C Mex can't be compiled by the popular MS VISUAL C (type LONG LONG must be replaced by __int64)
It is dangerous when no checking is performed after mxDuplicateArray that could returns NULL and results in a crash if there is not enough memory.
Updates
14 Jul 2009
Update according to suggestions from Bruno Luong: Out out memory check and requiring that the dimensions of the arrays matches exactly (not just number of elements).
12 Sep 2009
Added support for the bitshift function
18 Sep 2009
Description update
22 Sep 2009
*Added support for the uint64 datatype as well
*No longer accepts A*B is A and B are matrices
*Added binaries for Windows 64-bit
24 Oct 2009
Added matrix multiplication (not fast compared to double)
01 Jun 2010
Updating according to comments by Jan Simon. Thanks!
Nothing changes for the user except the behaviour of mod(i,0)