How to change the rounding mode for floating point operations in MATLAB? - matlab

I want to change the rounding mode for floating point operations in MATLAB. According to IEEE 754-2008, there are 5 strategies for rounding:
round to nearest, ties to even
round to nearest, ties away from zero
round toward zero
round up (toward positive infinity)
round down (toward negative infinity)
Does MATLAB supports these 5 strategies? How to change the rounding mode for floating point operations in MATLAB?

Answer
Kind of. There is an undocumented feature('setround') function call that you can use to get or set the rounding mode used by Matlab.
So, it can be done, but you shouldn’t do it. :)
WARNING: This is an undocumented, unsupported feature! Use at your own peril!
This feature('setround') supports 4 of the 5 IEEE-754 rounding modes: there’s only one “nearest” mode, and I don't know if it’s “ties to even” or “ties away from zero”.
Supported modes:
feature('setround') – Get current rounding mode
feature('setround', 0.5) – Round toward nearest (don’t know if it’s ties to even or away from zero)
feature('setround', Inf) – Round up (towards +Inf)
feature('setround', 0) – Round toward zero
feature('setround', -Inf) – Round down (towards -Inf)
Note on testing: The IEEE-754 rounding mode does not affect round() and its relatives. Rather, it governs how arithmetic operations behave around the limits of floating-point precision.
Demonstration
%ROUNDINGEXAMPLE Demonstrates IEEE-754 Rounding Mode control
%
% This uses a completely undocumented and unsupported feature!
% Not for production use!
%% Setup
clear; clc
n = 2000;
X = ones(n)*1E-30; % matrix with n^2 elements
defaultRoundingMode = feature('setround'); % store default rounding mode
%%
feature('setround',0.5);
r1 = prettyPrint('Nearest', sum(X(:)));
%{
sign exponent mantissa
0 01110110001 0011010101111100001010011001101001110101010000011110
| \_________/ \__________________________________________________/
| | ______________________|___________________________
| | / \
(-1)^0 2^( 945 - 1023) 1.0011010101111100001010011001101001110101010000011110 = 4e-24
%}
%%
feature('setround',-Inf);
r2 = prettyPrint('To -Infinity', sum(X(:)));
%{
sign exponent mantissa
0 01110110001 0011010101111100001010011001101001011100000111000110
| \_________/ \__________________________________________________/
| | ______________________|___________________________
| | / \
(-1)^0 2^( 945 - 1023) 1.0011010101111100001010011001101001011100000111000110 = 4e-24
%}
%%
feature('setround',Inf);
r3 = prettyPrint('To Infinity', sum(X(:)));
%{
sign exponent mantissa
0 01110110001 0011010101111100001010011001101010100011101100100001
| \_________/ \__________________________________________________/
| | ______________________|___________________________
| | / \
(-1)^0 2^( 945 - 1023) 1.0011010101111100001010011001101010100011101100100001 = 4e-24
%}
%%
feature('setround',0);
r4 = prettyPrint('To zero', sum(X(:)));
%{
sign exponent mantissa
0 01110110001 0011010101111100001010011001101001011100000111000110
| \_________/ \__________________________________________________/
| | ______________________|___________________________
| | / \
(-1)^0 2^( 945 - 1023) 1.0011010101111100001010011001101001011100000111000110 = 4e-24
%}
%%
feature('setround',defaultRoundingMode);
r5 = prettyPrint('No accumulated roundoff error', 4e-24);
%{
sign exponent mantissa
0 01110110001 0011010101111100001010011001101010001000111010100111
| \_________/ \__________________________________________________/
| | ______________________|___________________________
| | / \
(-1)^0 2^( 945 - 1023) 1.0011010101111100001010011001101010001000111010100111 = 4e-24
%}
%% Helper function
function r = prettyPrint(s, r)
fprintf('%s:\n%65.60f\n\n', s, r);
end
I get:
Nearest:
0.000000000000000000000003999999999966490758963870373537264729
To -Infinity:
0.000000000000000000000003999999999789077070014108839608005726
To Infinity:
0.000000000000000000000004000000000118618095059505975310731249
To zero:
0.000000000000000000000003999999999789077070014108839608005726
No accumulated roundoff error:
0.000000000000000000000003999999999999999694801998206811298525
Acknowledgments
Thanks to Ryan Klots at MathWorks Technical Support for setting me straight on this and providing the nice demo code!

#HYF: I found that feature('setround', 0.5) leads to round to even.
I checked the following:
a=1+2^-52
This means that mantissa looks like so: 1.0...01 where the last 1 is still in the mantissa. The leading 1 is not stored in IIIE754 format.
( I checked that 1+2^-52 == 1 but not 1+2^-53 == 1)
Then I computed b = a + 2^-53.
Without rounding it is 1.0...01|1 where the last digit is to be rounded away.
I found the following true: b==1+2^-51
We have b == 1.0...010.
We have several rounding modes submodes of round to nearest:
This can be round to inf, round away from 0 or round to even.
Next we check -b==-1-2^-51 to be true which excludes round to inf
still allowing round away from 0 or round to even.
Then I checked 1.5==1.5+2^-53.
Of course 1.5 = 1.10...0 binary and
and 1.5+2^-53 = 1.10...0|1 without rounding, the last digit to be rounded away.
Rounding away from 0 would be 1.10...01
and rounding to even is 1.10...0.
So the latter is the case.

Related

Why does Swift report CGFloat.pi.significand to be exactly pi/2?

Running Xcode 11.3
Why is the significant component of pi equal to pi/2?
print(CGFloat.pi.significand == CGFloat.pi/2). // true
I expected the significant to be equivalent to the mantissa.. Did I miss something?
We declare significand as follows.
let magnitude = x.significand * F.radix ** x.exponent
I assume pi = 3.14.
So pi = 1.57 * 2 1 where 1.57 is the significand.
If we divide both sides by 2 you will get pi/2 = 1.57.
In other words pi/2 = pi.significand. (this is kind of a special case).
According to the apple documentation,
The significand is frequently also called the mantissa, but significand is the preferred terminology in the IEEE 754 specification, to allay confusion with the use of mantissa for the fractional part of a logarithm.
Update
As mentioned by #Ptit all numbers between 2 and 4 satisfies the argument number/2 = number.significand.

Finding the essential prime implicants

Given the table:
I tried to find the prime implicants of the function F(w, x, y, z) = sum (0, 2, 5, 7, 8, 10, 12, 13, 14, 15). I got an essential prime implicant of xz. I was wondering if there were more essential prime implicants? I am having trouble understand how to find them.
Prime implicant is a logical term in minimal DNF (disjunctive normal form; SOP = sum of products) or minimal CNF (conjunctive normal form; POS = product of sums) form that after removal of any of it's part it would not be a prime implicant for the output function anymore.
Consider this easier example:
a\b 0 1
+---+---|
0 | 0 | 0 |
1 | 0 |(1)|
+---+---+
You could write the output function in the DNF form as a minterm on position of literals' values: a=1,b=1 ("circled" by the parenthesis in the K-map):
y = a*b
It is the prime implicant, because if you remove any of the literals (variable or the variable's negation) it wont be an implicant for the output function anymore!
Here you have only two variables, therefore you can remove from the right output function definition y = a*b either the a (a or its negaton) or the b (b or its negation).
Removing the b from the y = a*b you would either circle one zero on the position a=1, b=0:
a\b 0 1
+---+---|
0 | 0 | 0 |
1 |(0 1)|
+---+---+ wrong_output_function: y1 = a
or circle one unwanted zero on the position a=0, b=1 by removing the a (a or its negation):
a\b 0 1
+---+---|
0 | 0 |(0)|
1 | 0 |(1)|
+---+---+ wrong_output_function: y2 = b
In this example by choosing to express the output function in DNF you want to circle all ones and NO zero, that is why all those two boolean expressions y1 and y2 are wrong.
For your example:
For finding the minimal DNF form you would like to find the largest groups (terms) possible, those have the least possible number of variables in them, without threatening the validity of the output function in this case adding a zero in any of the groups (output function's implicants).
Here you can see, that some of the groups overlap, but that is ok, because the groups have the minimal form by the definition. This K-map is minimal, because you cannot make the chosen groups any bigger.
You could for example circle the red ones not captured by the green circle separately, but in that case they would not be prime implicants, because you can make their groups bigger as seen in the previous Karnaugh map. This K-map is therefore not minimal, because there are non-prime implicants.
Note: the indexes in your function does not match the indexes in my K-map, because of the different permutation of the variables. My K-maps match positions of the variables in your original K-map style. The output function is based on that.

matlab spectrum returns more FRAME than expected

I'm using the following code to get specgram2D from np array:
specgram2D, freq, time = mlab.specgram(samples, Fs=11025, NFFT=1024, window=mlab.window_hanning, noverlap=int(1024 * 0.5))
Then I print out specgram2D like
print len(specgram2D) # returns 513
I got 513 instead of expected 512 which is half the window size.
What am I doing wrong?
Can I just ignore specgram2D[512]?
I got 513 instead of expected 512 which is half the window size.
What am I doing wrong?
For a real-valued signal, the frequency spectrum obtained from the Discrete Fourier Transform (DFT) is symmetric and hence only half of the spectrum is necessary to describe the entire spectrum (since the other half can be obtained from symmetry). That is probably why you are expecting the size to be exactly half the input window size of 1024.
The problem is that with even sized inputs, the midpoint of the spectrum falls exactly on a frequency bin. As a result, that frequency bin is its own symmetry. To illustrate this, the symmetry can be seen from the following graph:
frequency: 0 fs/N ... fs/2 ... fs
bin number: 0 1 ... 511 512 513 ... 1023 1024
^ ^ ^ ^ ^ ^ ^ ^
| | | |-| | | |
| | | | | |
| | |--------| | |
| | | |
| |----------------------------| |
| |
|--------------------------------------|
Where N is the size of the FFT (as determined by the NFFT=1024 parameter) and fs is the sampling frequency. As you can see the spectrum is fully specified by taking bins 0 to 512, inclusive. Correspondingly you should be expecting the size to be floor(N/2)+1 (simply N/2 + 1 with integer division, but I included the floor to emphasis the round down operation), or 513 in your case.
Can I just ignore specgram2D[512]?
As previously shown it is an integral part of the spectrum, but many applications do not specifically require every single frequency bins (i.e. ignoring that bin depends on whether your application is mostly interested in other frequency components).

Simulation of custom probability distribution in Matlab

I'm trying to simulate the following distribution:
a | 0 | 1 | 7 | 11 | 13
-----------------------------------------
p(a) | 0.34 | 0.02 | 0.24 | 0.29 | 0.11
I already simulated a similar problem: four type of balls with chances of 0.3, 0.1, 0.4 and 0.2. I created a vector F = [0 0.3 0.4 0.8 1] and used repmat to grow it by 1000 rows. Then I compared it with a columnvector of 1000 random numbers grown with 5 columns using the same repmat approach. I compared those two, calculated the sumvector of the matrix, and calculated the difference to get the frequences (e.g. [301 117 386 196]). .
But with the current distribution I don't know how to create the initial matrix F and whether I can use the same approach I used before at all.
I need the answer to be "vectorised", so no (for, while or if) loops.
This question on math.stackexchange
What if you create the following arrays:
largeNumber = 1000000;
a=repmat( [0], 1, largeNumber*0.34 );
b=repmat( [1], 1, largeNumber*0.02 );
% ...
e=repmat( [13], 1, largeNumber*0.11 );
Then you concatenate all of these arrays (to get a single array where your entries are represented with their corresponding probabilities), shuffle them, and extract the first N elements to get an N-dimensional vector drawn from your distribution.
EDIT: of course this answer is the way to go.

Fast way for solving symbolic system of equations in Matlab

I have a system of equations with 100001 variables (x1 through x100000 and alpha) and exactly that many equations. Is there a computationally efficient way, in Matlab or otherwise, to solve this system of equations. I know of the solve() command, but I'm wondering if there is something that will run faster. The equations are of the form:
1.) -x1 + alpha * (x4 + x872 + x9932) = 0
.
.
.
100000.) -x100000 + alpha * (x38772 + x95) = 0
In other words, the i^th equation has variable xi with coefficient -1 added to alpha * (sum of some other variables) equals 0. The final equation is just that x1 + ... + x100000 = 1.
The Math Part
This system may be always brought to the eigen[value/vector] equation canonical form:
**A***x* = λx
where A is your system's matrix, and x = [x1; x2; ...; x100000]. Taking the example from this question, the system may be written down as:
/ \ / \ / \
| 0 1 0 0 0 | | x1 | | x1 |
| 0 0 1 0 1 | | x2 | | x2 |
| 1 0 0 0 0 | x | x3 | = (1/alpha) | x3 |
| 0 0 1 0 0 | | x4 | | x4 |
| 0 1 0 1 0 | | x5 | | x5 |
\ / \ / \ /
This means that your eigenvalues λ = 1/α. Of course, you should beware of complex eigenvalues (unless you really want to take them into account).
The Matlab part
Well this is much to your taste and skills. You can always find the eigenvalues of a matrix with eig(). Better to use sparse matrices (memory economy):
N = 100000;
A = sparse(N,N);
% Here's your code to set A's values
A_lambda = eig(A);
ieps= 0e-6; % below this threshold imaginary part is considered null
alpha = real(1 ./ (A_lambda(arrayfun(#(x) imag(x)<ieps, A_lambda)))); % Chose Real. Choose Life. Choose a job. Choose a career. Choose a family. Choose a f****** big television, choose washing machines, cars, compact disc players and electrical tin openers. Choose good health, low cholesterol, and dental insurance. Choose fixed interest mortgage repayments. Choose a starter home. Choose your friends. Choose leisurewear and matching luggage. Choose a three-piece suit on hire purchase in a range of f****** fabrics. Choose DIY and wondering who the f*** you are on a Sunday morning. Choose sitting on that couch watching mind-numbing, spirit-crushing game shows, stuffing f****** junk food into your mouth. Choose rotting away at the end of it all, pissing your last in a miserable home, nothing more than an embarrassment to the selfish, f***** up brats you spawned to replace yourself. Chose life.
% Now do your stuff with alpha here
But, mind this: numerically solving large eigenvalue equations might give you complex values where real are expected. Tweak your ieps to sensible values, if you don't find anything in the beginning.
To find the eigenvectors, just take one out of the system and solve for the rest by means of Cramer's rule. The norm them to one if you wish so.