Friday, January 25, 2008

OpenGL In Java With JOGL

OpenGL itself is written for C/C++ programmers, and is in fact more efficiently implemented in that language. Serious games and animations are written that way. However, you can still do snazzy things with it from Java using the Java OpenGL (JOGL) library and the associated JNI/utilities library GLU. Perhaps an encouraging fact is that JOGL is the result of a joint effort between Sun Microsystems (makers of Java) and SGI (makers of OpenGL) to produce Java bindings and extensions for OpenGL. I also looked at Maya (the top GUI-oriented 3D package out there) and various incarnations of JOGL and Java 3D (native to the JDK), but decided that to learn the most about OpenGL, I should learn to code everything from scratch. Also considered was DirectX; I discourage this because it is targeted at Windows systems and thus not as portable as OpenGL is.

To get started, you need JOGL binaries (JARs) that you can download from java.net. Choose the apprpriate package for your OS and extract it to a location on your computer. For Windows, copy all DLLs into the %system32% directory, and the *.jar files into a location that your IDE can access to include in compile and build classpaths.
===
If you'll be using Eclipse, they claim to support OpenGL out-of-the-box (since Callisto, v3.2), but I couldn't get a simple application going until I added the JOGL libraries to the project. If you use NetBeans, there is a plugin for OpenGL available through the Update Center, but I couldn't get that going as well. So I decided to do things manually i.e. copy DLLs to appropriate location, then manually include JOGL libraries to the project path.

Here's the source code of a template you can use to start OpenGL projects. Included is a class (JoglTester) that tests whether your DLLs loaded correctly, and whether the core library is accessible. It'll also open a window (JoglApp) with dots of colors across the application, demonstrating how a canvas can be initialized for display. It is a good idea to have your own event handler that implements a GL listener (JoglGLEventListener). Most of your code changes will happen in the listener's overridden methods.
This work is based on Gene Davis' article at Java World. He does a good job of maintaining his code samples there (see comments/updates at bottom of article). When you set up your projects, create them as "Java Applications".

Tuesday, January 22, 2008

Delete, Create, Format Drive Partitions ...

At work, I sometimes have the need to create usable operating system partitions quickly on 20 or so hard drives, and it gets absolutely boring deleting existing partitions in Windows Disk Management, creating new partitions, and formatting each one. So I came up with this script that does it all for me.
It's basically a Perl script, but relies heavily on existing Windows features: diskpart - a disk management utility that comes with Windows XP/2003, and Windows Scripting Host - the default scripting engine that handles the VBScript I use. WSH uses OLE and the WMI framework. This is not the best implementation of the idea, but it absolutely works, so I don't care.
===
This script will attempt to determine what the system disk is and exclude it from all operations. Then it deletes all partitions on other hard drives, creates a 4GB partition, and formats it with the NTFS file system. It runs in under a minute, obviously depending on how many drives you have. I tested it with 23 (the most you can assign drive letters to in Windows). It doesn't work well on Windows 2000 because (1) it doesn't come standard with diskpart.exe, and (2) the WSH on it is ancient. On Windows 2000, it fails to format the partitions created.
Needless to say, don't be dumb and run it on a system with useful partitions. I don't give any warnings - I assume that in running the script, you really want to get rid of all partitions/volumes on your system except the system partition.
This script can be adapted many ways: split the main features into own module-friendly scripts or subroutines, or a mechanism to specify varying partition sizes and file systems, and whether to quick format or do a full format. You can even adapt it to operate on a remote machine (do you see how?).
===
Download the create-partitions-win.pl script.

Tuesday, January 15, 2008

Back To Language Basics

My friend Rachael can speak the language from Papua New Guinea as fluently as she does English, and that impressed me. For a while I hadn't been around people that spoke anything other than English and Spanish well, and I was getting bored, so this was something refreshing, and it inspired me to tap back into languages I used to know or learn some new ones. At one time, I spoke up to 6 languages well, but it's all eroded into a heavily accented English breeze. I tend to mumble much these days, have a very low voice volume (I swear it sounds really loud inside my head - that's why), and it affects how I communicate.

Some people like the accent (sounds more British than anything normally), but a majority others don't get it. People place me as being from the islands (Caribbean) and others wonder soon enough where I am from when I speak. Thing is: my accent is all languages I ever spoke rolled into one thick thing - the intonations, the phonetics, and expressiveness of my voice are heavily influenced by the African languages I learned as a child. Depending on what mood I am in (tired, stressed, happy, cheezy, etc), you might hear something different. Sometimes I can be really hard to understand ... and yet other times I'm as clear as day. My family doesn't notice anymore and for a long time I didn't care.

This year I'm doing something I enjoy much: learning languages. I started English (??) this week with my friend Jessica's mom coaching me (which I think she does professionally). On the side, I am also working through a French series using software by Topics Entertainment (Instant Immersion French Deluxe v2.0). The software has speech recognition features and some pretty good exercises to get you up to speed. If you have never spoken or learned French, even the beginner level is not for you - you need some background for this software to be useful at all. I sound ridiculous now repeating words and sentences many times over, but that's how I'll get back in the groove.
As I worked through the French series, I realized how much my experience as a musician helps me: I "sing"/sound the words and sentences I hear, and that's the only way I get them right. If I can't hear it, I can't say it - even if I can read it and understand it. I think I have an ability to imitate sounds quite well. Languages are my newest escape from the daily grind of computers, programming, music, and the social others.

After English and French, I'll be back to Swahili and Arabic (build on the little I knew), and then get caught up with other African languages. Some new languages I'd like to learn: Spanish or German. I'm not messing with Chinese and other Asian languages, like Ben and Megan have successfully done. For my friend Rochelle and the huge collection of Brazilian music I have, Portuguese would be an interesting language to pick up, I think.
The key to keeping in shape linguistically is practice, practice, practice. Any chance I have, I'll speak these languages. A while back, I switched to reading my news from French RSS news feeds ... and I haven't missed anything worthwhile on the world scene. That's just a start.

Thursday, January 10, 2008

Into Perl ...

I'm on a journey to master Perl by the end of this month. As it turns out, this powerful scripting language is being positioned at work as THE scripting language for the automation framework. All test tools will need to be written or re-written for compatibility with a new test/automation framework based on Perl.
So far, learning Perl is a walk in the park. I can certainly see a lot of relation to existing programming languages Java and C++, with a zing of more useful features. For being an interpreted language (you need to install an interpreter on Windows, Linux comes standard with one), it is efficiently fast. I like how it "has no limits but your system" and how "there's always more than one way to do things". It can get confusing sometimes, but if you just stick with a few ways, you will get by just fine. My methodology is formed from experience as a Java programmer, so I use syntax that resembles Java as much as I can.
My biggest hope for Perl is that I should be able to use it in my own testing - when I do development work for Strive, Ltd. I am developing a Javascript test framework for webapps I develop, but I can see now how Perl would greatly augment this package. It'll be interesting to learn to integrate it in my Java development and deployment policies.
The best part of it all: I can learn this language for free. There are so many good tutorials and even free ebooks online that I wonder if stores can still sell actual books at all!

Tuesday, January 08, 2008

Sieve of Eratosthenes (Perl)

Followup to a previous Java implementation (that blogger botched), here is the Perl scriptage:

print "\n=======================\n";
print "PRIME NUMBERS GENERATOR\n";
print "=======================\n";
# Get the range
print "Minimum value of primes: ";
my $min = <STDIN>;
chomp $min;
print "Maximum value of primes: ";
my $max = <STDIN>;
chomp $max;
# Create a max-sized array
my @primes = (1...$max);
# Initially assume all numbers are prime
for($i = 0; $i < $max; $i++) {
$primes[$i] = 1;
}
# The sieve
for ($i=2; $i*$i <= $max;$i+=1) {
if ($primes[$i]) {
for ($j=$i; $j*$i < $max; $j+=1) {
$primes[$i * $j] = 0;
}
}
}
# Show the results
my @p = ();
for ($i=$min; $i<=$max; $i++) {
if ($primes[$i]) {
push @p, $i;
}
}
$size = @p;
print qq(Found $size primes:\n@p\n);

Sunday, January 06, 2008

Alternative PDF Reader

If you are growing tired of Adobe Acrobat's bulky reader, there's hope in Foxit Software's free PDF reader. This app is fast, renders stuff much better, and is not a resource hog as Acrobat is. I had come across it 3 years ago, but at the time, I still has Acrobat 5, which was moderately good. Then came 6.x and 7.x and the angst grew, so I had been looking for an alternative to Acrobat Reader. The answer came in Foxit's extremely small application that does wonders! Consider this: Acrobat uses about 80MB working with a 9MB PDF file, takes forever to install and get started, causes Firefox to hang while closing, browses documents sluggishly, does a bad job rendering "weird" pages, and has a habit of calling home for updates; Foxit uses only 18MB for the same document, displays/renders fonts and images much crisper, and is a breeze to start and install. In fact, it is the fastest install I have ever seen! The installer itself is small - 2.5MB. I'm impressed by this program.
The guys at Adobe must be scratching their heads on this: how does a relatively unknown company do their idea better than them? Performance-wise, it's superior to Acrobat. I haven't used it long enough to know what other features and issues it has, but for my needs of reading (huge) PDF's, this is the clear choice.

Thursday, January 03, 2008

Notes On Hashing

  • Technique that promises near-ϑ(1) data lookup, compared with ϑ(n) for linked lists or ϑ(log n) for binary search trees.
  • Uses a hash function - a means of interpreting some object numerically (with an integer usually) to determine its position in some table (hashtable).
  • There's no order (e.g. sorting) to items stored in the hashtable - it all seems random and is the reason this process is sometimes called randomizing.
  • Implementations prone to inefficient storage usage and high rates of collisions when used slots are far-flung and many entries end up with the same hash code, respectively.
  • There's no such thing as a perfect hashing algorithm - there will always be some collisions and space will never always be utilized efficiently enough - a good trade-off is needed.
  • Prime numbers are king when calculating hashes.
  • The JDK's String class has the simplest and yet effective hashing algorithm I have ever seen!
  • When a hashing table fills up, you need to resize it dynamically.
  • Two techniques exist that help reduce the need to resize hashtables: (1) probing, and (2) bucketing.
  • Linear probing = if a collision occurs, look for the next available slot (including wrapping to the head of the table if necessary) to place the object in. At some point with more and more objects being added, performance degrades to linear/brute-force ϑ(n).
  • Bucketing = maintain a collection at each hashtable slot so that each hashcode can have more than one object.
  • One way to determine when to resize a hashtable is to keep track of a load factor = the ratio of stored values to available buckets (for bucketing).
  • A load factor of about 75% is a fairly good trade-off between space and time, and works well for most implementations.
  • Bucketing is the most efficient of the two techniques. Nor surprisingly, the JDK version implements bucketing with a default load factor if 0.75.
  • Modern hashing functions are based on serious mathematical analysis (beyond me). There are several websites I came across with some good hashing algorithms for everything from cryptography to applications in geometry: Arash Partow's site and Hash Algorithm Directory are just two of the many out there.
  • HowStuffWorks.com discusses hashing algorithms in their article about encryption.
  • Most everyday programmers don't deal with hashing (designing and implementing algorithms) beyond using data structures available in most APIs. I've never had to do anything like that beyond using the Hashtable and HashMap classes provided in the JDK. Always preferable to use any of the good GUID generators currently available (which probably use some sort of hashing internally). The advantage is that they guarantee you will have a unique identifier for every object in the proper context.

Tuesday, January 01, 2008

It's In The Sorting, Dude!

I just finished consulting on an interesting project: this client's inhouse web application had been working great until recently when it seemed to take longer and longer to respond to requests. Being it is an SOA application that uses AJAX all over, speed is of the essence for an overall satisfactory user experience. A couple of times, the IT guys had upgraded the servers running the webapp (hardware), but the problem lingered. So obviously the webapp itself was to blame - but where would the issue be in an application that's been relatively bug free since its inception?
Long story short, the sorting algorithms used were to blame. I couldn't identify which one was being used (proprietary or more advanced than I have learned?), but magic happened when I replaced the sorter with the well-known mergesort algorithm. In preliminary testing, the problem is pretty much gone for the size of live data the company typically works with. Amazing!

My real excitement though is in the fact that I got to use (so soon) knowledge from a previous school class I had taken (Design and Analysis of Algorthms, and Data Structures). I didn't expect to be using ideas from the class in a real-world environment yet, but I found myself doing real analysis of the client's code like we had done in assignments, and making a decision based solely on the results - and it worked. Sometimes class materials don't make complete sense until you have to use them practically.

Mergesort is a divide-and-conquer comparison-based algorithm that runs in ϑ(n log n) computational time. Its only drawback is that it requires significantly more memory to do its job than other algorithms. Here's the Java implementation of mergesort:


public class MergesortListSorter implements ListSorter {
private final Comparator comp;

public MergesortListSorter(Comparator comp) {
assert (comp!=null): "Comparator cannot be null.";
this.comp = comp;
}

public List sort(List list) {
assert (list!=null): "List cannot be null.";
return mergesort(list, 0, list.size()-1);
}

private List merge(List left, List right) {
List result = new LinkedList();
Iterator l = left.iterator();
Iterator r = right.iterator();
l.first();
r.first();
while(!(l.isDone() && r.isDone())) {
if(l.isDone()) {
result.add(r.current());
r.next();
} else if (r.isDone()) {
result.add(l.current());
l.next();
} else if (comp.compare(l.current(), r.current()) <= 0) {
result.add(l.current());
l.next();
} else {
result.add(r.current());
r.next();
}
}
return result;
}

private List mergesort(List list, int s, int e) {
if(s == e) {
List result = new LinkedList();
result.add(list.get(s));
return result;
}
int split = s + (e - s)/2;
List left = mergesort(list, s, split);
List right = mergesort(list, split+1, e);
return merge(left, right);
}
}


There's probably better implementations out there than this, but this variety worked well. The actual solution was a blend of mergesort and shellsort because both perform well in average and worst case scenarios. Java helps with the problem of memory because object references are used in collections (as opposed to objects themselves), so the overhead in memory is in the additional references that are created.