Dr. Dobb's Journal December 1999
The Small Language
Dear DDJ,
In reviewing the excellent article, "The Small Scripting Language" by Thiadmer Riemersma (DDJ, October 1999), I discovered what I believe is an error in the program for computing the day of the week utilizing Zeller's Congruence (Listing Three). Specifically, the last line of the weekday procedure is given as return (day (month+1)*26/10+j+j/4+e/4-2*e)%7. This form of the equation unfortunately allows the left-hand operator of the modulo operation to be negative for some dates (March 1, 2000, being a good example). For most commercially available processors, the modulo operation is defined only for the domain of real positive integers. If a negative number is encountered, they will behave in "undefined" fashions. Substituting an equivalent variation of the algorithm (+5*e%7 and -2*e%7 are equivalent values): return (day+(month+1)*26/10+j+j/4 +e/4+5*e)%7 yields an expression that is always valid, but is computationally more difficult as it will optimize the second e term to an integer multiplication by an odd integer, instead of the binary shift generated by the original algorithm. I doubt that this is a major concern with modern processors, but if computational speed is of the essence, a constant, even multiple of 7, can be added to the equation, keeping it valid for a defined range of dates.
The algorithm originally given breaks down on March 1, 300, and for various date ranges following (always starting in March of even centuries). Adding a constant of 35 yields an algorithm valid until 2300, a value of 70 would be good until 4300 as shown in the following algorithm that I have seen cited in various places. return(day+(month+1)*26/10 +j+j/4+e/4-2*e+70)%7. How long do you want your software to last? Other than this small quibbling, I was very glad to see that some folks still realize that smaller can be better.
John Neal
nlabs@ij.net
Thiadmer responds: John, I am glad you enjoyed the article on the Small language. As you correctly put forward, many microprocessors return a negative value for the modulus if either of the operands is negative and most programming languages map their "modulus" or "remainder" to the related microprocessor instruction. Small, however, defines the modulus operation to always return positive values, regardless of the sign of the operands. This is in accordance with how mathematicians interpret the modulus operation. The Small manual documents the behavior of the modulus and division operators, but the article indeed did not mention it. By the way, Java and Ada also define the modulus operator to behave in a specific way for negative operands, without regard to the microprocessor on which the virtual machine or the compiler runs. (Small's definition of the modulus differs from the ones in Ada and Java.)
Java 2 Graphics
Dear DDJ,
I enjoyed Torpum Jannak's article, "Java 2 Graphics Rendering" (DDJ, September 1999), which involved pooling graphics objects. We looked at his pool object and wanted to use it in some code we are implementing Connection Pools in a Java Servlet. However, there are some flaws with the ObjectPool. We found this out while debugging some of our code. Torpum synchronized the getObject and releaseObject, which in the getObject [requires] a wait. This wait is useless because this method is synchronized, so no other threads can release an object. Second, we found a bug in the getObject code. Torpum has a for loop in which you reset the i variable to do a search to the left of the array. Note what happens when the m_currentFreeIndex=2 and all the objects are checked out. You get into an endless loop. You need to place a Boolean variable that tells the for loop to break and that the search has been exhausted. Other than that, it's a very cool object.
Jeff Genender
Jeff.Genender@qwest.com
Torpum responds: Jeff, thanks again for alerting me to the problem with the code. I've updated the code (available electronically; see "Resource Center," page 5) for the infinite loop problem when the producer thread outperforms the consumer thread in utilizing the ObjectPool. The loop basically wants to start at a given index (m_currentFreeIndex) and pass through the entire array once, looping back to index zero as necessary. A much more efficient looping mechanism (which I use frequently but missed it in the published code) is to start from a point K, go to (K+maxSize-1), and use "modulo maxSize" to loop back to zero as necessary.
Regarding the wait() inside a synchronized method -- this is not a problem. A wait() inside a synchronized method causes the object's monitor to be temporarily released, allowing other threads access to the object containing the method. For example, another thread can call the releaseObject() along with a notify() to wake up the other blocked threads. The inappropriate behavior you noticed may have stemmed from the infinite loop problem mentioned, where the synchronized method controlling the object's monitor never got to the wait() call, thus preventing other threads from accessing the object and calling the releaseObject() method.
Our initial tests failed to hit on this problem as our consumer threads were very slim and fast compared to the producer threads. Again, I personally apologize if this caused you longer debugging cycles than you might otherwise have expected.
Cross-Platform Independence
Dear DDJ,
In his October 1999 column on shareware, Al Stevens writes "We agreed that an application which is cross-platform independent at the source-code level would probably use only the lowest common denominator of the GUI features of all the platforms." This may be unduly pessimistic. See http://www.halcyon.com/ www3/jesjones/Whisper/Home.html.
Richard A. Clarke
RichardAClarke@compuserve.com
Version Control
Dear DDJ,
Aspi Havewala's article on version control ("The Version Control Process," DDJ, May 1999) and the follow-up letters on it have been really interesting.
Having been in software development for the past 15 years, the last 10 of which having been on large projects using C++, I feel I must comment on using certain features found in SCM systems. In particular, parallel development and three-way merge. It has been our experience, and evidently Aspi's also, that these features are loaded with opportunities to "break the build." Manual intervention of an automated merge guarantees that, at some point, a junior programmer is going to be responsible for merging their code with that of a senior programmer. And, while one of your readers pointed out that refresh merging on the local hard drive can solve the parallel update interlace problem, it still requires that the programmer actually elects to refresh his checked out files. In my opinion, there is only one way to guarantee that the build does not get broken, and that is serialized edits, and a rigorous build process. Our process demands that each developer build his changes into the current view path before submitting their changes to the source database. This guarantees that the overnight build will not fail. Overnight failures of builds on small projects may be acceptable, but break the nightly build on a project that takes 6 to 10 hours to complete and you have literally thrown away the next day's productivity. Thanks for a great publication.
William C. Brown
corey@ga.prestige.net
Median Filters
Dear DDJ,
I enjoyed "Algorithm Alley" by Wesley Bylsma (DDJ, October 1999) and would like to make one suggestion regarding the MATLAB code shown for the median filter. The code x=[x(1)*ones(1,L),x',x(l)*ones(1,L)]'; will generate the following error if x is a row vector instead of a column vector:
??? All matrices on a row in the bracketed expression must have the same number of rows.
This error occurs when x is passed in as row vector and the x' transposes x into a column vector, which does not fit into the row vector formulation of the bracketed expression. I suggest as the easiest fix to change the line to read x=[x(1) *ones(1,L),x(:)',x(l)*ones(1,L)]';. The x(:) forces the vector x to be treated in the expression as a column vector regardless of how the calling routine passes it in. I consider this a good idea especially because the comments do not address the form of x (column or row vector).
Jeffrey Simmers
Jeff.Simmers@dynetics.com
Open Source in Turkey
Dear DDJ,
I've been reading Al Stevens' "C Programming" column in DDJ for three years and have benefited from his C/C++ programming CD-ROM. I enjoyed his comments about open source and would like to share our experiences in Turkey. (I should mention that we had an Open Source Conference about six months here as well.)
In Turkey, almost 80-90 percent of commercial programs are pirated copies, and people make their living (if you can call this a living!) only on services such as installation, tutoring, customizing, and the like. In short, it is not much different than an open source or free software movement.
While it's true that "free software cannot survive without revenue," revenue is somehow raised either through donations to foundations, or through services rendered.
What is more important is the attitude of those who write code and share it freely with others. In Turkey we have talented young people who, while studying or working for a company, devote a lot of their personal times to contributing to the free software "spirit." Thus, we now have Turkuaz (the Turkish version of RedHat Linux distribution), a lot of GUI tools translated into Turkish, documentation, and all the technical support that people make money on.
After all, "sharing" is very much the "Turkish spirit" and making money on services is never considered a "mouse trap" here in Turkey.
Kemal Gencay
kemalg@superonline.com
DDJ