Getting max possible value of integer data type in Octave - range

I use GNU Octave, version 6.4.0. Is there any command for getting size of usual data classes, at least for integral data types? Really I want to get max possible value for data type of a matrix which is related to an image. For example for an uint8 image such I it must return 256 for argument class(I). I am looking for a builtin command and do not want to write a switch myself.

The intmax() function does what you want for integer types. Either intmax("uint8") or intmax(a) where a is of type uint8 (or any other integer type).
https://octave.sourceforge.io/octave/function/intmax.html
A similar function realmax() exists for floating point types.

Related

Accuracy error in binomials using MATLAB?

The value is absolute integer, not a floating point to be doubted, also, it is not about an overflow since a double value can hold until 2^1024.
fprintf('%f',realmax)
179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
The problem I am facing in nchoosek function that it doesn't produce exact values
fprintf('%f\n',nchoosek(55,24));
2488589544741302.000000
While it is a percentage error of 2 regarding that binomian(n,m)=binomial(n-1,m)+binomial(n-1,m-1) as follows
fprintf('%f',nchoosek(55-1,24)+nchoosek(55-1,24-1))
2488589544741301.000000
Ps: The exact value is 2488589544741300
this demo shows
What is wrong with MATLAB?
Your understanding of the realmax function is wrong. It's the maximum value which can be stored, but with such large numbers you have a floating point precision error far above 1. The first integer which can not be stored in a double value is 2^53+1, try 2^53==2^53+1 for a simple example.
If the symbolic toolbox is available, the easiest to implement solution is using it:
>> nchoosek(sym(55),sym(24))
ans =
2488589544741300
There is a difference between something that looks like an integer (55) and something that's actually an integer (in terms of variable type).
The way you're calculating it, your values are stored as floating point (which is what realmax is pointing you to - the largest positive floating point number - check intmax('int64') for the largest possible integer value), so you can get floating point errors. An absolute difference of 2 in a large value is not that unexpected - the actual percentage error is tiny.
Plus, you're using %f in your format string - e.g. asking it to display as floating point.
For nchoosek specifically, from the docs, the output is returned as a nonnegative scalar value, of the same type as inputs n and k, or, if they are different types, of the non-double type (you can only have different input types if one is a double).
In Matlab, when you type a number directly into a function input, it generally defaults to a float. You have to force it to be an integer.
Try instead:
fprintf('%d\n',nchoosek(int64(55),int64(24)));
Note: %d not %f, converting both inputs to specifically integer. The output of nchoosek here should be of type int64.
I don't have access to MATLAB, but since you're obviously okay working with Octave I'll post my observations based on that.
If you look at the Octave source code using edit nchoosek or here you'll see that the equation for calculating the binomial coefficient is quite simple:
A = round (prod ((v-k+1:v)./(1:k)));
As you can see, there are k divisions, each with the possibility of introducing some small error. The next line attempts to be helpful and warn you of the possibility of loss of precision:
if (A*2*k*eps >= 0.5)
warning ("nchoosek", "nchoosek: possible loss of precision");
So, if I may slightly modify your final question, what is wrong with Octave? I would say nothing is wrong. The authors obviously knew of the possibility of imprecision and included a check to warn users when that possibility arises. So the function is working as intended. If you require greater precision for your application than the built-in function provides, it looks as though you'll need to code (or find) something that calculates the intermediate results with greater precision.

Make Matlab issue a warning when converting a double to a uint8 and vice versa?

Typically in Matlab colours are represented by three element vectors of RGB intensity values, with precision uint8 (range 0 - 255) or double (range 0 - 1). Matlabs functions such as imshow work with either representation making both easy to use in a program.
It is equally easy however to introduce a bug when assigning colour values from a matrix of one type, to that of another (because the value is converted silently, but not re-scaled to the new range). Having just spent a number of hours finding such a bug, I would like to make sure it is never introduced again.
How do I make Matlab display a warning when type conversion takes place?
Ideally it would only be when the conversion is between double and uint8. It should also be difficult to deactivate (i.e. the option is not reset when loading a workspace, or when matlab crashes).
A possible solution is to define your own uint8 function that casts to uint8 and issues a warning if some value has been truncated.
You should place this function in a folder where it shadows the builtin uint8 funciton. For example, your user folder is a good choice, as it usually appears the first in path.
Or, as noted by Sam Roberts, if you want this function to be called only when converting from double into uint8 (not when converting from any other type into uint8), put it in a folder named #double within your path.
function y = uint8(x)
y = builtin('uint8', x);
if any(x(:)>255) || any(x(:)<0)
warning('MATLAB:castTruncation', 'Values truncated during conversion to uint8')
end
The warning is on by default. You can switch it on or off with the commands warning('on','MATLAB:castTruncation') and warning('off','MATLAB:castTruncation') (thanks to CitizenInsane for the suggestion).

Bitget working with large inputs?

The default type is uint64 but the below apparently requires larger support where you can see that the number 536870915 (100000000000000000000000000011 in binary, 30 bits' length) is not supported by the above bitget command. So
How to get bitget command working with large inputs like the below?
Input
hhhh=sparse([],[],[],2^40+1,1);
hhhh(536870915)=1;
bitget(str2num(dec2bin(find(hhhh)-1)),2,'uint64')
Output
Error using bitget
Double inputs must have integer values in the range of ASSUMEDTYPE.
You pass the output of dec2bin(find(hhhh)-1) to str2num. This directly converts the string of ones and zeros into a double: 9.999999999999999e+28. I'm guessing that's not what you want.
If you're just trying to get the second bit of 536870915, why not use:
bitget(find(hhhh)-1,2,'uint64')
On the other hand, I think that you could also use this (probably slower, but maybe it'll work with the rest of your code if you're already converting to string representation):
b = dec2bin(find(hhhh)-1);
str2double(b(end-1))
It seems like you're trying to combine two approaches.

Why is find in matlab returning double values

The find function within matlab returns indices where the given locigal argument evaluates true.
Thus I'm wondering, why the return values (for the indices) are of type double and not uint32 or uint64 like the biggest index into a matrix could be.
Another strange thing which might be connected to that here is, that running
[~,max_num_of_elem]=computer
returns the maximal number of elements allowed for a matrix in the variable max_num_of_elem which is also of type double.
I can only guess, but probably because a wide range of functions only support double. Run
setdiff(methods('double'), methods('uint32'))
to see what functions are defined for double and not for uint32 on your version of MATLAB.
Also there is the overflow issue with integer data types in MATLAB that can introduce some hard to detect bugs.

Type casting a vector in Matlab

version: Matlab 2009a
I am generating a vector of size <1x116286> using randsrc() function. Since I am again adding it to the matrix of same size but of uint8 type, I am doing as follows -
l=typecast(randsrc(1,v(2)),'uint8');
Now, Matlab has changed the returned a vector of elements - [240,63,0] instead of [-1,1], with the size of <1x930288 uint8>. This is expected as double and uint8 has different size, but I want a vector of same size and values after type casting.
PS: I want to subtract or add '1' from all trhe values on a matrix of size <1x116286>. Is there any other neat way to do this?
As I understand the problem, there are a couple of issues with the above:
uint8 is an unsigned type so will not support a negative offset;
the "typecast" function is used to reinterpret existing data, not to convert it: here you are interpreting each byte of the floating-point output of randsrc(...) as an integer.
Unfortunately I don't have Matlab handy to test, but the following should provide something closer to what you are after:
l = int8( randsrc(1,v(2)) );
well instead of forming a vector (-1,1...) and adding it to some vector 'z' , I did something like this.
l =randsrc(1,v(2));
z(l==-1)=z(l==-1)-1;
z(l==1)=z(l==1)+1;
So, I now, don't need to change types.