David Bishop said:
Jonathan said:
assert natural(2.50) = 3 report "cast rounding error"; [...]
I can remove lots of math_real.round functions
from my rtl and testbench code.
Yes; real and integer are "closely related types" and
can be mutually type-converted as you showed.
I *think* (too much Christmas idleness to check the LRM)
that the rounding of exact halves from REAL to INTEGER
is indeterminate (might go up or down), whereas
math_real.trunc() and math_real.round() have precisely
defined behaviour. For the overwhelming majority of
applications that doesn't matter, of course.
The rule (according to IEEE 754) rounding has to do with the bottom bit of
the integer portion.
If the remainder is greater than 0.5, round up
If the remainder is less than 0.5, round down
If the remainder IS 0.5, then look at the bottom bit of the integer
portion. If it is a "1" (odd) round up, if it is a "0" (even) round down.
This is the functionality of "round nearest", which should be the default
rounding style for all floating point numbers.
I think that math_real function is "floor" though.
Per Modelsim (too lazy for LRM also).... 'round' does the same thing as a
simple cast but it doesn't appear that the decision to round 'up' or 'down'
depends on the least significant bit of the integer. Instead it depends on
the sign of the integer and pushes it 'away' from 0 towards the next largest
(in absolute value) integer.
KJ
begin
assert FALSE
report "i=" & integer'image(i) & LF &
"integer'image(integer(real(i)+ 0.5))=" &
integer'image(integer(real(i)+ 0.5)) & LF &
"real'image(ieee.math_real.round(real(i)+0.5))" &
real'image(ieee.math_real.round(real(i)+0.5)) & LF &
"real'image(ieee.math_real.ceil(real(i) + 0.5))" &
real'image(ieee.math_real.ceil(real(i) + 0.5)) & LF &
"real'image(ieee.math_real.floor(real(i) + 0.5))" &
real'image(ieee.math_real.floor(real(i) + 0.5)) & LF
severity NOTE;
end generate G_TEST;
# ** Note: i=3
# integer'image(integer(real(i)+ 0.5))=4
# real'image(ieee.math_real.round(real(i)+0.5))4.000000e+000
# real'image(ieee.math_real.ceil(real(i) + 0.5))4.000000e+000
# real'image(ieee.math_real.floor(real(i) + 0.5))3.000000e+000
#
# Time: 0 ns Iteration: 0 Instance: /tiff_test_area/g_test__3
# ** Note: i=2
# integer'image(integer(real(i)+ 0.5))=3
# real'image(ieee.math_real.round(real(i)+0.5))3.000000e+000
# real'image(ieee.math_real.ceil(real(i) + 0.5))3.000000e+000
# real'image(ieee.math_real.floor(real(i) + 0.5))2.000000e+000
#
# Time: 0 ns Iteration: 0 Instance: /tiff_test_area/g_test__2
# ** Note: i=1
# integer'image(integer(real(i)+ 0.5))=2
# real'image(ieee.math_real.round(real(i)+0.5))2.000000e+000
# real'image(ieee.math_real.ceil(real(i) + 0.5))2.000000e+000
# real'image(ieee.math_real.floor(real(i) + 0.5))1.000000e+000
#
# Time: 0 ns Iteration: 0 Instance: /tiff_test_area/g_test__1
# ** Note: i=0
# integer'image(integer(real(i)+ 0.5))=1
# real'image(ieee.math_real.round(real(i)+0.5))1.000000e+000
# real'image(ieee.math_real.ceil(real(i) + 0.5))1.000000e+000
# real'image(ieee.math_real.floor(real(i) + 0.5))0.000000e+000
#
# Time: 0 ns Iteration: 0 Instance: /tiff_test_area/g_test__0
# ** Note: i=-1
# integer'image(integer(real(i)+ 0.5))=-1
# real'image(ieee.math_real.round(real(i)+0.5))-1.000000e+000
# real'image(ieee.math_real.ceil(real(i) + 0.5))0.000000e+000
# real'image(ieee.math_real.floor(real(i) + 0.5))-1.000000e+000
#
# Time: 0 ns Iteration: 0 Instance: /tiff_test_area/g_test__-1
# ** Note: i=-2
# integer'image(integer(real(i)+ 0.5))=-2
# real'image(ieee.math_real.round(real(i)+0.5))-2.000000e+000
# real'image(ieee.math_real.ceil(real(i) + 0.5))-1.000000e+000
# real'image(ieee.math_real.floor(real(i) + 0.5))-2.000000e+000
#
# Time: 0 ns Iteration: 0 Instance: /tiff_test_area/g_test__-2
# ** Note: i=-3
# integer'image(integer(real(i)+ 0.5))=-3
# real'image(ieee.math_real.round(real(i)+0.5))-3.000000e+000
# real'image(ieee.math_real.ceil(real(i) + 0.5))-2.000000e+000
# real'image(ieee.math_real.floor(real(i) + 0.5))-3.000000e+000
#
# Time: 0 ns Iteration: 0 Instance: /tiff_test_area/g_test__-3
# ** Note: i=-4
# integer'image(integer(real(i)+ 0.5))=-4
# real'image(ieee.math_real.round(real(i)+0.5))-4.000000e+000
# real'image(ieee.math_real.ceil(real(i) + 0.5))-3.000000e+000
# real'image(ieee.math_real.floor(real(i) + 0.5))-4.000000e+000
#
# Time: 0 ns Iteration: 0 Instance: /tiff_test_area/g_test__-4