<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>#AltDevBlogADay &#187; Jasper Bekkers</title>
	<atom:link href="http://www.altdevblogaday.com/author/jasper-bekkers/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.altdevblogaday.com</link>
	<description>Each day a little more #gamedev love</description>
	<lastBuildDate>Mon, 17 Jun 2013 14:45:09 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<item>
		<title>IEEE 754 multiplication and addition</title>
		<link>http://www.altdevblogaday.com/2011/12/01/ieee-754-multiplication-and-addition/</link>
		<comments>http://www.altdevblogaday.com/2011/12/01/ieee-754-multiplication-and-addition/#comments</comments>
		<pubDate>Thu, 01 Dec 2011 10:52:11 +0000</pubDate>
		<dc:creator>Jasper Bekkers</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[addition]]></category>
		<category><![CDATA[float]]></category>
		<category><![CDATA[floating point]]></category>
		<category><![CDATA[floating point numbers]]></category>
		<category><![CDATA[fused-multiply-add]]></category>
		<category><![CDATA[IEEE 754]]></category>
		<category><![CDATA[magic numbers]]></category>
		<category><![CDATA[mantissa]]></category>
		<category><![CDATA[math]]></category>
		<category><![CDATA[Mathematics]]></category>
		<category><![CDATA[maths]]></category>
		<category><![CDATA[multiplication]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://altdevblogaday.com/?p=12437</guid>
		<description><![CDATA[<p>To me, programming has always been an exercise in understanding blackboxes. About taking systems apart and figuring out their internal workings. And although this teaches you about how other programmers think and work it does take away some of the amazement you have when seeing a cleverly written piece of code.</p>
<p><a href="http://www.altdevblogaday.com/2011/12/01/ieee-754-multiplication-and-addition/" class="more-link">Read more on IEEE 754 multiplication and addition&#8230;</a></p>
]]></description>
				<content:encoded><![CDATA[<p>To me, programming has always been an exercise in understanding blackboxes. About taking systems apart and figuring out their internal workings. And although this teaches you about how other programmers think and work it does take away some of the amazement you have when seeing a cleverly written piece of code.</p>
<p>For me, and for a lot of other programmers, floating point numbers have for the longest time been one of these blackboxes. There is a lot of (good and bad) information on the web about floating points, most of it describes the data format, how the bits are interpreted, what epsilon values you should use or how to deal with accuracy issues in floats. Hardly any article talks about where all of this actually comes from or how fundamental floating point operations are implemented.</p>
<p>So in this article I will talk about how some of these operations are implemented, specifically multiplication, addition and fused-multiply-add. I won&#8217;t talk about decimal-to-float conversions, float-to-double or float-to-int casts, division, comparisons or trigonometry functions. If you&#8217;re interested in these I suggest taking a look at John Hauser&#8217;s excellent SoftFloat library listed below. It&#8217;s the same library I&#8217;ve used to borrow the code samples in this article from.</p>
<p>For convenience sake I&#8217;ll also show an image of the floating point data layout taken from wikipedia because this might help explain some of the magic numbers and masks used in the code below. The hardware diagrams are taken from the &#8220;Floating-Point Fused Multiply-Add Architectures&#8221; paper linked below and are diagrams for <strong>double precision</strong> implementations (this due to me being unable to produce these pretty pictures myself). Keep that in mind when reading them.</p>
<p><a href="http://altdevblogaday.com/wp-content/uploads/2011/11/ieee754_32bit_float_format.png"><img class="aligncenter size-full wp-image-19685" src="http://altdevblogaday.com/wp-content/uploads/2011/11/ieee754_32bit_float_format.png" alt="1 Sign bit, 8 exponent bits, 23 mantissa bits" width="590" height="75" /></a></p>
<h2>Multiplication</h2>
<p>The way IEEE 754 multiplication works is identical to how it works for regular scientific notation. Simply multiply the coefficients and add the exponents. However, because this is done in hardware we have some extra constraints, such as overflow and rounding, to take into account. These extra constraints are what make floats appear so &#8216;fuzzy&#8217; to some.</p>
<ol>
<li>Check if either of the operands (A and B) are zero (early out)</li>
<li>Check for potential exponent overflow and throw corresponding overflow errors</li>
<li>Compute sign as C<sub>sign</sub> = A<sub>sign</sub> XOR B<sub>sign</sub></li>
<li>Compute the exponent C<sub>exponent</sub> = A<sub>exponent</sub> + B<sub>exponent</sub> – 127</li>
<li>Compute mantissa C<sub>mantissa </sub>= A<sub>mantissa</sub> * B<sub>mantissa</sub> (23-bit integer multiply) and round the result according to the currently set rounding mode.</li>
<li>­­If C<sub>mantissa</sub> has overflown, normalize results (C<sub>mantissa</sub> &lt;&lt;= 1, C<sub>exponent</sub> -= 1)</li>
</ol>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
</pre></td><td class="code"><pre class="c" style="font-family:monospace;">f32 float32_mul<span style="color: #009900;">&#40;</span>f32 a<span style="color: #339933;">,</span> f32 b<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
	<span style="color: #666666; font-style: italic;">// extract mantissa, exponent and sign</span>
	u32 aFrac <span style="color: #339933;">=</span> a <span style="color: #339933;">&amp;</span> <span style="color: #208080;">0x007FFFFF</span><span style="color: #339933;">;</span>
	u32 bFrac <span style="color: #339933;">=</span> b <span style="color: #339933;">&amp;</span> <span style="color: #208080;">0x007FFFFF</span><span style="color: #339933;">;</span>
&nbsp;
	u32 aExp <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>a <span style="color: #339933;">&gt;&gt;</span> <span style="color: #0000dd;">23</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;</span> <span style="color: #208080;">0xFF</span><span style="color: #339933;">;</span>
	u32 bExp <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>b <span style="color: #339933;">&gt;&gt;</span> <span style="color: #0000dd;">23</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;</span> <span style="color: #208080;">0xFF</span><span style="color: #339933;">;</span>
&nbsp;
	u32 aSign <span style="color: #339933;">=</span> a <span style="color: #339933;">&gt;&gt;</span> <span style="color: #0000dd;">31</span><span style="color: #339933;">;</span>
	u32 bSign <span style="color: #339933;">=</span> b <span style="color: #339933;">&gt;&gt;</span> <span style="color: #0000dd;">31</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">// compute sign bit</span>
	u32 zSign <span style="color: #339933;">=</span> aSign <span style="color: #339933;">^</span> bSign<span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">// removed: handle edge conditions where the exponent is about to overflow</span>
	<span style="color: #666666; font-style: italic;">//  see the SoftFloat library for more information</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">// compute exponent</span>
	u32 zExp <span style="color: #339933;">=</span> aExp <span style="color: #339933;">+</span> bExp <span style="color: #339933;">-</span> <span style="color: #208080;">0x7F</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">// add implicit `1' bit</span>
	aFrac <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>aFrac <span style="color: #339933;">|</span> <span style="color: #208080;">0x00800000</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&lt;&lt;</span> <span style="color: #0000dd;">7</span><span style="color: #339933;">;</span>
	bFrac <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>bFrac <span style="color: #339933;">|</span> <span style="color: #208080;">0x00800000</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&lt;&lt;</span> <span style="color: #0000dd;">8</span><span style="color: #339933;">;</span>
&nbsp;
	u64 zFrac <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>u64<span style="color: #009900;">&#41;</span>aFrac <span style="color: #339933;">*</span> <span style="color: #009900;">&#40;</span>u64<span style="color: #009900;">&#41;</span>bFrac<span style="color: #339933;">;</span>
&nbsp;
	u32 zFrac0 <span style="color: #339933;">=</span> zFrac <span style="color: #339933;">&gt;&gt;</span> <span style="color: #0000dd;">32</span><span style="color: #339933;">;</span>
	u32 zFrac1 <span style="color: #339933;">=</span> zFrac <span style="color: #339933;">&amp;</span> <span style="color: #208080;">0xFFFFFFFF</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">// check if we overflowed into more than 23-bits and handle accordingly</span>
	zFrac0 <span style="color: #339933;">|=</span> <span style="color: #009900;">&#40;</span>zFrac1 <span style="color: #339933;">!=</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #0000dd;">0</span> <span style="color: #339933;">&lt;=</span> <span style="color: #009900;">&#40;</span>i32<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#40;</span>zFrac0 <span style="color: #339933;">&lt;&lt;</span> <span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		zFrac0 <span style="color: #339933;">&lt;&lt;=</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">;</span>
		zExp<span style="color: #339933;">--;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">// reconstruct the float; I've removed the rounding code and just truncate</span>
	<span style="color: #b1b100;">return</span> <span style="color: #009900;">&#40;</span>zSign <span style="color: #339933;">&lt;&lt;</span> <span style="color: #0000dd;">31</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">|</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>zExp <span style="color: #339933;">&lt;&lt;</span> <span style="color: #0000dd;">23</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #009900;">&#40;</span>zFrac <span style="color: #339933;">&gt;&gt;</span> <span style="color: #0000dd;">7</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p><a href="http://altdevblogaday.com/wp-content/uploads/2011/11/muldiagram.png"><img class="aligncenter size-full wp-image-19694" src="http://altdevblogaday.com/wp-content/uploads/2011/11/muldiagram.png" alt="" width="509" height="389" /></a></p>
<h2>Addition</h2>
<p>Again, the steps for floating point addition are based on calculating with scientific notation. First you align the exponents, then you add the mantissas. The alignment step is the reason for the big inaccuracies with adding small and large numbers together.</p>
<ol>
<li>Align binary point
<ol>
<li>If A<sub>exponent </sub>&gt; B<sub>exponent</sub><em> </em>Then do B<sub>mantissa </sub>&gt;&gt;= 1 until B<sub>mantissa</sub> * 2 <sup>Bexponent – Aexponent</sup></li>
<li>If B<sub>exponent </sub>&gt; A<sub>exponent</sub><em> </em>Then do A<sub>mantissa </sub>&gt;&gt;= 1 until A<sub>mantissa</sub> * 2 <sup>Aexponent – Bexponent</sup></li>
<li>Compute sum of aligned mantissas
<ol>
<li>A<sub>mantissa</sub> * 2<sup> Aexponent – Bexponent </sup>+B<sub>mantissa</sub></li>
<li>Or B<sub>mantissa</sub> * 2<sup> Bexponent – Aexponent </sup>+A<sub>mantissa</sub></li>
<li>Normalized and round results</li>
<li>Check for exponent overflow and throw corresponding overflow errors</li>
<li>If C<sub>mantissa</sub> is zero set the entire float to zero to return a ‘correct’ 0 float.</li>
</ol>
</li>
</ol>
</li>
</ol>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// implementation only works with a and b of equal sign</span>
<span style="color: #666666; font-style: italic;">// if a and b are of different sign, we call float32_sub instead</span>
<span style="color: #666666; font-style: italic;">// look at the SoftFloat source-code for specifics.</span>
<span style="color: #993333;">static</span> f32 float32_add<span style="color: #009900;">&#40;</span>f32 a<span style="color: #339933;">,</span> f32 b<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
	<span style="color: #993333;">int</span> zExp<span style="color: #339933;">;</span>
	u32 zFrac<span style="color: #339933;">;</span>
&nbsp;
	u32 aFrac <span style="color: #339933;">=</span> a <span style="color: #339933;">&amp;</span> <span style="color: #208080;">0x007FFFFF</span><span style="color: #339933;">;</span>
	u32 bFrac <span style="color: #339933;">=</span> b <span style="color: #339933;">&amp;</span> <span style="color: #208080;">0x007FFFFF</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #993333;">int</span> aExp <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>a <span style="color: #339933;">&gt;&gt;</span> <span style="color: #0000dd;">23</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;</span> <span style="color: #208080;">0xFF</span><span style="color: #339933;">;</span>
	<span style="color: #993333;">int</span> bExp <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>b <span style="color: #339933;">&gt;&gt;</span> <span style="color: #0000dd;">23</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;</span> <span style="color: #208080;">0xFF</span><span style="color: #339933;">;</span>
&nbsp;
	u32 aSign <span style="color: #339933;">=</span> a <span style="color: #339933;">&gt;&gt;</span> <span style="color: #0000dd;">31</span><span style="color: #339933;">;</span>
	u32 bSign <span style="color: #339933;">=</span> b <span style="color: #339933;">&gt;&gt;</span> <span style="color: #0000dd;">31</span><span style="color: #339933;">;</span>
&nbsp;
	u32 zSign <span style="color: #339933;">=</span> aSign<span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #993333;">int</span> expDiff <span style="color: #339933;">=</span> aExp <span style="color: #339933;">-</span> bExp<span style="color: #339933;">;</span>
	aFrac <span style="color: #339933;">&lt;&lt;=</span> <span style="color: #0000dd;">6</span><span style="color: #339933;">;</span>
	bFrac <span style="color: #339933;">&lt;&lt;=</span> <span style="color: #0000dd;">6</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">// align exponents if needed</span>
	<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>expDiff <span style="color: #339933;">&gt;</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>bExp <span style="color: #339933;">==</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">--</span>expDiff<span style="color: #339933;">;</span>
		<span style="color: #b1b100;">else</span> bFrac <span style="color: #339933;">|=</span> <span style="color: #208080;">0x20000000</span><span style="color: #339933;">;</span>
&nbsp;
		bFrac <span style="color: #339933;">=</span> shift32RightJamming<span style="color: #009900;">&#40;</span>bFrac<span style="color: #339933;">,</span> expDiff<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		zExp  <span style="color: #339933;">=</span> aExp<span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
	<span style="color: #b1b100;">else</span> <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>expDiff <span style="color: #339933;">&lt;</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>aExp <span style="color: #339933;">==</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">++</span>expDiff<span style="color: #339933;">;</span>
		<span style="color: #b1b100;">else</span> aFrac <span style="color: #339933;">|=</span> <span style="color: #208080;">0x20000000</span><span style="color: #339933;">;</span>
&nbsp;
		aFrac <span style="color: #339933;">=</span> shift32RightJamming<span style="color: #009900;">&#40;</span>aFrac<span style="color: #339933;">,</span> <span style="color: #339933;">-</span>expDiff<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		zExp  <span style="color: #339933;">=</span> bExp<span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
	<span style="color: #b1b100;">else</span> <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>expDiff <span style="color: #339933;">==</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>aExp <span style="color: #339933;">==</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">return</span> <span style="color: #009900;">&#40;</span>zSign <span style="color: #339933;">&lt;&lt;</span> <span style="color: #0000dd;">31</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">|</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>aFrac <span style="color: #339933;">+</span> bFrac<span style="color: #009900;">&#41;</span> <span style="color: #339933;">&gt;&gt;</span> <span style="color: #0000dd;">6</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
		zFrac <span style="color: #339933;">=</span> <span style="color: #208080;">0x40000000</span> <span style="color: #339933;">+</span> aFrac <span style="color: #339933;">+</span> bFrac<span style="color: #339933;">;</span>
		zExp <span style="color: #339933;">=</span> aExp<span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #b1b100;">return</span> <span style="color: #009900;">&#40;</span>zSign <span style="color: #339933;">&lt;&lt;</span> <span style="color: #0000dd;">31</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">|</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>zExp <span style="color: #339933;">&lt;&lt;</span> <span style="color: #0000dd;">23</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #009900;">&#40;</span>zFrac <span style="color: #339933;">&gt;&gt;</span> <span style="color: #0000dd;">7</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	aFrac <span style="color: #339933;">|=</span> <span style="color: #208080;">0x20000000</span><span style="color: #339933;">;</span>
	zFrac <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>aFrac <span style="color: #339933;">+</span> bFrac<span style="color: #009900;">&#41;</span> <span style="color: #339933;">&lt;&lt;</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">;</span>
	<span style="color: #339933;">--</span>zExp<span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>i32<span style="color: #009900;">&#41;</span>zFrac <span style="color: #339933;">&lt;</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		zFrac <span style="color: #339933;">=</span> aFrac <span style="color: #339933;">+</span> bFrac<span style="color: #339933;">;</span>
		<span style="color: #339933;">++</span>zExp<span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">// reconstruct the float; I've removed the rounding code and just truncate</span>
	<span style="color: #b1b100;">return</span> <span style="color: #009900;">&#40;</span>zSign <span style="color: #339933;">&lt;&lt;</span> <span style="color: #0000dd;">31</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">|</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>zExp <span style="color: #339933;">&lt;&lt;</span> <span style="color: #0000dd;">23</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #009900;">&#40;</span>zFrac <span style="color: #339933;">&gt;&gt;</span> <span style="color: #0000dd;">7</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// for reference</span>
<span style="color: #993333;">static</span> u32 shift32RightJamming<span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span> a<span style="color: #339933;">,</span> <span style="color: #993333;">int</span> count<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>count <span style="color: #339933;">==</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span>              <span style="color: #b1b100;">return</span> a<span style="color: #339933;">;</span>
    <span style="color: #b1b100;">else</span> <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>count <span style="color: #339933;">&lt;</span> <span style="color: #0000dd;">32</span><span style="color: #009900;">&#41;</span>         <span style="color: #b1b100;">return</span> <span style="color: #009900;">&#40;</span>a <span style="color: #339933;">&gt;&gt;</span> count<span style="color: #009900;">&#41;</span> <span style="color: #339933;">|</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>a <span style="color: #339933;">&lt;&lt;</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">-</span>count<span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;</span> <span style="color: #0000dd;">31</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">else</span>                        <span style="color: #b1b100;">return</span> a <span style="color: #339933;">!=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>An overview of floating point addition hardware. The implementation will make a distinction between adding numbers where the exponent differs (the far path) and numbers where the exponent is the same (the close path), much like the implementation above.</p>
<p><a href="http://altdevblogaday.com/wp-content/uploads/2011/11/adddiagram1.png"><img class="aligncenter size-full wp-image-20848" src="http://altdevblogaday.com/wp-content/uploads/2011/11/adddiagram1.png" alt="" width="531" height="521" /></a></p>
<h2>Fused-multiply-add</h2>
<p>The multiply-add operation is basically a combination of both of these operations that is as efficient or more efficient to implement in hardware as both operations separately. The primary difference in operation is (as long as it’s not a <em>pseudo-fma</em>) is the fact that there is only one rounding operation done at the end of the result, instead of one in the multiply <em>and</em> the add circuits (steps 3 and 4 respectively).</p>
<p>Some, if not most, SIMD architectures on current-gen platforms are actually built around just the fused-multiply-add and don&#8217;t have regular multiply or addition hardware (they&#8217;ll just insert identity constants into one of the three operands) a simple give-away for this is usually that the cycle count for these operations is identical in each case.</p>
<p><a href="http://altdevblogaday.com/wp-content/uploads/2011/11/fmadiagram.png"><img class="aligncenter size-full wp-image-19690" src="http://altdevblogaday.com/wp-content/uploads/2011/11/fmadiagram.png" alt="" width="584" height="619" /></a></p>
<h1>Further reading and citations</h1>
<p><em>Single precision floating-point format</em>. (2011, June 19).<br />
Retrieved Juli 2011, from Wikipedia: http://en.wikipedia.org/wiki/Single_precision_floating-point_format</p>
<p>Quinnell, E. C. (2007, May). <em>Floating-Point Fused Multiply-Add Architectures.</em> Retrieved June 2011, from http://repositories.lib.utexas.edu/bitstream/handle/2152/3082/quinnelle60861.pdf</p>
<p>Shaadan, D. M. (2000, Januari). <em>Floating Point Arithmetic Using The IEEE 754 Standard Revisited.</em> Retrieved June 2011, from http://meseec.ce.rit.edu/eecc250-winter99/250-1-27-2000.pdf</p>
<p>Hauser, J. (2010, June). <em>SoftFloat</em> Retrieved June 2011, from http://www.jhauser.us/arithmetic/SoftFloat.html</p>
<p>Giesen, F. (2011, July). <em>Int-multiply-using-floats trickery</em> Retrieved July 2011, from http://pastebin.com/jyT0gTSS</p>
]]></content:encoded>
			<wfw:commentRss>http://www.altdevblogaday.com/2011/12/01/ieee-754-multiplication-and-addition/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Practical MLAA on the GPU &#8211; My take</title>
		<link>http://www.altdevblogaday.com/2011/08/03/practical-mlaa-on-the-gpu-my-take-2/</link>
		<comments>http://www.altdevblogaday.com/2011/08/03/practical-mlaa-on-the-gpu-my-take-2/#comments</comments>
		<pubDate>Wed, 03 Aug 2011 08:29:33 +0000</pubDate>
		<dc:creator>Jasper Bekkers</dc:creator>
				<category><![CDATA[#gamedev]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[gpu]]></category>
		<category><![CDATA[mlaa]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[shaders]]></category>

		<guid isPermaLink="false">http://altdevblogaday.com/?p=13285</guid>
		<description><![CDATA[<p>
In days where FXAA seems to be the anti-aliasing method of choice, due to it being easy to implement and fast to execute. I&#8217;m going to take a look at how the &#8220;French MLAA paper&#8221; (<a href="http://igm.univ-mlv.fr/~biri/mlaa-gpu/">Morphological Antialiasing on GPU</a>) approached anti-aliasing. This has two reasons: first and foremost it&#8217;s because the paper uses a <em><a href="http://en.wikipedia.org/wiki/Double_recursion">Recursive Doubling</a></em> approach to implement an iterative gather algorithm in shaders (as &#8216;popularized&#8217; by <a href="http://developer.amd.com/media/gpu_assets/Hensley-Schuermann-SAT-Sketch-SIG05.pdf">Interactive Summed-Area Table Generation for Glossy Environmental Reﬂections</a>). And second, because the code is quite hard to understand if you don&#8217;t know any French (I don&#8217;t, and because of this I might have made some mistakes; bear with me).
</p>
<p><a href="http://www.altdevblogaday.com/2011/08/03/practical-mlaa-on-the-gpu-my-take-2/" class="more-link">Read more on Practical MLAA on the GPU &#8211; My take&#8230;</a></p>
]]></description>
				<content:encoded><![CDATA[<p>
In days where FXAA seems to be the anti-aliasing method of choice, due to it being easy to implement and fast to execute. I&#8217;m going to take a look at how the &#8220;French MLAA paper&#8221; (<a href="http://igm.univ-mlv.fr/~biri/mlaa-gpu/">Morphological Antialiasing on GPU</a>) approached anti-aliasing. This has two reasons: first and foremost it&#8217;s because the paper uses a <em><a href="http://en.wikipedia.org/wiki/Double_recursion">Recursive Doubling</a></em> approach to implement an iterative gather algorithm in shaders (as &#8216;popularized&#8217; by <a href="http://developer.amd.com/media/gpu_assets/Hensley-Schuermann-SAT-Sketch-SIG05.pdf">Interactive Summed-Area Table Generation for Glossy Environmental Reﬂections</a>). And second, because the code is quite hard to understand if you don&#8217;t know any French (I don&#8217;t, and because of this I might have made some mistakes; bear with me).
</p>
<h1>Overview</h1>
<p>
The algorithm consists of 4 different steps implemented in 5 different shaders to accomplish what Crytek calls a <em>fancy edge blur</em>. I&#8217;ll outline the steps first and then go into detail about what each part does.
</p>
<ol>
<li>Edge detection</li>
<li>Count line lengths of log<sub>4</sub>(maxLineLength) passes</li>
<li>Determine blend weights</li>
<li>Blur (I won&#8217;t go into this here because it&#8217;s a simple blur filter based on the previously calculated weights)</li>
</ol>
<h1>1. Edge detection</h1>
<p>
Although there are many ways to do edge detection in a pixel shader, the paper decided to implement this using a difference based on color, it makes sense to do this because blurring edges based on normal/depth. And as it turns the most recent version at the time of writing also supports color + depth edge detection. Currently the shader is implemented by converting colors to <a href="http://en.wikipedia.org/wiki/Lab_color_space">LAB color space</a> and calculating a Euclidian distance between two colors and optionally do a depth compare; when this distance exceeds a certain threshold you have your edge.
</p>
<p>The paper uses and outputs to two textures, a mask and the texture used to count line lengths and they are laid out like this:</p>
<ul>
<li>The mask consists of 2 channels:
<ul>
<li>R gets a 1 if there is a <strong>horizontal</strong> edge (zero otherwise)</li>
<li>G gets a 1 if there is a <strong>vertical</strong> edge (zero otherwise)</li>
<li>The line length texture consists of 4 channels:
<ul>
<li>B and A get a value of 1/255 if there is a <strong>horizontal</strong> discrepancy (zero otherwise)</li>
<li>R and G get a value of 1/255 if there is a <strong>vertical</strong> discrepancy (zero otherwise)
<ul>
<li>If there is a horizontal discrepancy, this means that there is a vertical line and vice versa! Keep this in mind for the Count line lengths shader.</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>
For my implementation I dropped the mask because the line length texture can serve the exact same purpose, except that it&#8217;s data is in different channels and checks of equals 1 should be converted to doesn&#8217;t equal 0. This made the flow of the algorithm a lot easier and saved some memory.
</p>
<h1>2. Count line lengths</h1>
<p>
The process of determining the line lengths uses a technique called <em>recursive doubling</em> which is the reason this part of the process gets it&#8217;s logarithmic runtime performance of O(log<sub>4</sub>(maxLineLength)) this basically comes down to doing 4 passes for a maximum length of 256 pixels. To see how this works we should first see exactly how the line-length buffer is structured.
</p>
<p>
Basically, the R channel stores how many pixels a certain line has to the left of it and the G channel stores how many there are to the right; this means that for each pixel you can look up the length of the edge by summing up either the R and G channels for horizontal length and the R and G channels for vertical length.
</p>
<p align="center"><img src="http://altdevblogaday.com/wp-content/uploads/2011/07/tbl.png" alt="	" /></p>
<p align="center">Orange represents the alpha channel. This is the content of the buffer when the algorithm is done processing.</p>
<p>
The gist of the algorithm is pretty simple and I&#8217;ll go over it briefly. Just keep in mind that the following loop is done per channel (eg. 4 times).
</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
</pre></td><td class="code"><pre class="c" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// PreviousLengths is initialized to 1.f/255.f for edges and 0 for non-edges</span>
float4 currentLengths <span style="color: #339933;">=</span> tex2D<span style="color: #009900;">&#40;</span>PreviousLengths<span style="color: #339933;">,</span> Tex<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
float4 currentDelta <span style="color: #339933;">=</span> currentLengths <span style="color: #339933;">*</span> PixelSize.<span style="color: #202020;">zzww</span><span style="color: #339933;">;</span>
<span style="color: #993333;">const</span> <span style="color: #993333;">float</span> Threshold <span style="color: #339933;">=</span> Level <span style="color: #339933;">/</span> <span style="color: #0000dd;">255</span>.<span style="color: #202020;">f</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>currentLengths.<span style="color: #202020;">r</span> <span style="color: #339933;">&gt;=</span> Threshold<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    float2 newTex <span style="color: #339933;">=</span> Tex <span style="color: #339933;">-</span> float2<span style="color: #009900;">&#40;</span>currentDelta.<span style="color: #202020;">r</span><span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">for</span><span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span> k <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span> k <span style="color: #339933;">&lt;</span> <span style="color: #0000dd;">3</span><span style="color: #339933;">;</span> k<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #993333;">float</span> oneDelta <span style="color: #339933;">=</span> tex2D<span style="color: #009900;">&#40;</span>PreviousLengths<span style="color: #339933;">,</span> newTex<span style="color: #009900;">&#41;</span>.<span style="color: #202020;">r</span><span style="color: #339933;">;</span>
        currentLengths.<span style="color: #202020;">r</span> <span style="color: #339933;">+=</span> oneDelta<span style="color: #339933;">;</span>
        newTex.<span style="color: #202020;">x</span> <span style="color: #339933;">-=</span> oneDelta <span style="color: #339933;">*</span> PixelSize.<span style="color: #202020;">z</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>
For the first pass Level is initialized to 1 (then to 4, 16 and 64) so this check only does the length count only if it thinks it should still be counting the lengths of the edges. PixelSize is initialized to (1/width, 1/height, 255/width, 255/height) so when multiplying by zzww we convert between increments in 1/255th to increments in 1/width and 1/height.
</p>
<p>
The interesting part, however, is inside the loop as it moves more pixels to the side depending on the value in the R channel it retrieves. This has a effect that if the value at that pixel is 0, nothing changes and currentLengths doesn&#8217;t get incremented.
</p>
<p align="center"><img src="http://altdevblogaday.com/wp-content/uploads/2011/07/line.png" alt="" /></p>
<p align="center">The different colors do not indicate different channels, they are merely different lines.</p>
<p>
When doing normal point-sampling when you reach 0 you&#8217;ll know the line has ended and the loop makes sure you stop there. Hower; as shown by Nicolas Vizerie in <a href="http://www.vizerie3d.net/">MLAA (MorphoLogical AntiAliasing) on the GPU using Direct3D9.0</a> using bilinear filtering can reduce the amount of texture fetches by testing two lines at a time.
</p>
<h1>3. Determine blend weights</h1>
<p>
The blend weights are calculated from a pre-generated lookup table (look for tabAires in the source-code, I didn&#8217;t bother to re-implement it). However, the basic gist of the table is that on the vertical axis is the size (eg. the sum of two channels in the LineLength texture) of the line and on the horizontal is the size in one direction (eg. one of the two channels in the LineLength texture). The content of the table are the areas below the triangles that the edges form and they are almost all handled by the formula  <code>0.5 * (1. - (2 * j + 1) / (float)S)</code> the other formulas in the lookup table are there to help in edge cases where the equation tails off.  Each pixel in the lookup table has a range of 0.25 ≤ pixelvalue ≤ 0.5 because the blending of a certain pixel has a maximum contribution of four other pixels.
</p>
<p>
The shader, although lengthy has quite a straightforward implementation that basically checks the endpoints of the lines to see if there is exists an edge orthogonal to it. If that&#8217;s the case, it uses the shortest of the two line-segments and the total size of the original line to determine the weights in the lookup table. This process is done four times:
</p>
<ul>
<li>Horizontal for current pixel</li>
<li>Vertical for current pixel</li>
<li>Horizontal for one pixel to the left</li>
<li>Vertical for one pixel above</li>
</ul>
<h1>Further references</h1>
<ul>
<li><a href="http://divergentcoder.com/rendering/mlaa-demo-2/">MLAA Demo 2 by @synulation</a> Optimized DX10 version of the previous version of the shader.</li>
<li><a href="http://www.iryoku.com/mlaa/">Practical Morphological Anti-Aliasing</a> Other MLAA on the GPU technique.</li>
<li><a href="http://www.vizerie3d.net/"> MLAA (MorphoLogical AntiAliasing) on the GPU using Direct3D9.0</a> Another MLAA implementation (also uses the old version of the paper).</li>
<li><a href="http://igm.univ-mlv.fr/~biri/mlaa-gpu/">Morphological Antialiasing on GPU<br />
</a></li>
<li><a href="http://developer.amd.com/media/gpu_assets/Hensley-Schuermann-SAT-Sketch-SIG05.pdf">Interactive Summed-Area Table Generation for Glossy Environmental Reﬂections</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.altdevblogaday.com/2011/08/03/practical-mlaa-on-the-gpu-my-take-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic page generated in 1.167 seconds. -->
<!-- Cached page generated by WP-Super-Cache on 2013-06-17 15:19:37 -->
<!-- Compression = gzip -->