“Many times I have been asked how one “invents” a programming language. One cannot really tell, but it certainly is a matter of experience with the subject of programming, and of careful deliberation. Sometimes I answered: “Like one designs an airplane. One must identify a number of necessary building blocks and materials, and then assemble and combine them properly to a functioning whole,” This answer may not be entirely satisfactory, but at least in both cases the result either flies or crashes.”
Niklaus Wirth, Pascal and its Successors in Software Pioneers (2002)
Month: March 2023
Generating a cylinder to represent HSB colour space
While we have generated the “top” of the HSB cylinder, generating the whole cylinder might be trickier. I mean we could create a cylinder just fine, but wrapping the colour space around it might be more challenging. But there is a slight-of-hand trick that can be used.
Basically, some ways of viewing a cylinder make the top of the cylinder appear as an ellipse. That shows the top surface as the 360 degrees of hue, and the saturation component, going from 100% along the edges to 0% in the centre. What we want to do is show the side of the cylinder, which represents the hue in combination with the brightness (100% at the top, 0% at the bottom). We don’t really care about the hidden portion of the cylinder.

So the easiest way of creating this is actually stacking 100 ellipses. The bottom ellipse will be generated using all the hues, the saturation going from 100% on the periphery to 0% in the middle, and a brightness value of 0%. Each ellipse stacked on top will have the brightness incremented by 1%, until we hit the topmost ellipse with a brightness of 100%.
The first thing to do is set up the environment, setting up an 800×800 sketch space, and setting up the colour space to HSB.
void setup() {
size(800, 800);
noStroke();
colorMode(HSB, 360, 100, 100);
background(255,0,100);
noLoop();
}
Next we create the draw()
procedure:
void draw() {
float y = 400;
int totalsteps = 100;
int stepcount = 0;
int z, b = 1;
strokeWeight(5);
y = 500;
while (stepcount < totalsteps){
drawellipse(200,50,400,y,100,b);
y = y - 2;
stepcount = stepcount + 1;
b = b + 1;
}
z = 100;
for (int i=200; i>=1; i=i-2){
drawellipse(i,i/4,400,y,z,100);
z = z - 1;
}
}
Lines 8-14 generates the 100 different ellipses, using the procedure drawellipse()
. The parameters of the procedure set the major-axis (200), and minor-axis (50) of the ellipse, and the x- (400), and y- coordinates, the latter of which is modified in each iteration of the loop. The last two values are the saturation (100), and brightness (b
). After the ellipse has been drawn, the position (y
) is modified, and the brightness (b
) is incremented. Lines 16-20 generates the top of the cylinder. It makes progressively smaller ellipses, and reduces the saturation (z
) of each ellipse while maintaining brightness.
Finally there is the drawellipse()
procedure. The procedure uses polar coordinates to draw the edge of the ellipse with the appropriate hue. Each of 360 degrees are processed, with each having a particular hue.
void drawellipse(float rx, float ry, float xc, float yc, int s, int b) {
float step = 1;
float dx, dy, r;
int hue = 0;
for (int theta=0; theta<=360; theta=theta+1){
r = radians(theta);
dx = xc + rx * cos(r);
dy = yc - ry * sin(r);
stroke(hue, s, b);
point(dx,dy);
hue = hue + 1;
}
}
where the parameters are:
rx = ellipse major-axis ry = ellipse minor-axis xc = x-coordinate yc = y-coordinate s = saturation (0-100) b = brightness (0-100)
How to deep dive for information
Most people think it’s easy to search with Google. The problem is most people can’t perform good searches. Why you ask? Because data takes many forms, and just performing a simple search will most often not get you exactly what you are looking for. People will then complain that they “can’t find it”, and my retort is that you didn’t actually look for it properly.
Let me provide a couple of examples. The first scenario is information that doesn’t exist on the net, and believe me there is a *lot* of it. First let’s search for information about Japanese woodworking saws, using the phrase “Japanese woodworking saws”. This actually produces a bunch of hits, a mix of places that sell saws, and blog posts about saws. But the problem here is that they are all in English. This is great if you want to buy a Japanese saw, but what about if you want to know more about them? For that you actually have to perform the search using the equivalent Japanese phrase. So “japanese woodworking saws” when translated using Google translate gives:
日本の木工のこぎり
Note, that Google translate always gives the English-based Japanese option as well, in this case “Nihon no mokkō nokogiri”, but it doesn’t work well in the search engine because most Japanese websites are in Japanese script. These days translating these websites is quite trivial. Of course if you are searching in Japanese, you really only need to specify “woodworking saw” in Japanese, and the mere fact that the search is being performed in Japanese means that it will find the most appropriate information. Of course information on the internet is somewhat deficient sometimes – real information can still only be found in books, and I’m not talking about digital books, I’m talking paper ones. It turns out that real information on the historical context of Japanese saws is found in historic books that aren’t digitized.
It is no different when trying to find something like vintage camera lenses from Germany. For example to search for vintage “Meyer Optik lenses”, you could search for the string as shown. However this will only find English results. It may be more beneficial to search using the equivalent German search string: “meyer optik objektive”. Even better is set the domain to “de”, to restrict searching to German domains. Because there is sometimes a lot of lens information on Japanese sites, it is also good to try searching using the Japanese phrase “マイヤーオプティックレンズ”.
The bottom line is that sometimes you have to use every possible trick in the book to find information online, knowing that in some cases, it doesn’t matter how you search, the information just does not exist in a digital form. We are of course very lucky that so much knowledge is available.
Problem solving and the human condition
In Star Trek TNG, in the episode “Attached”, Picard says “There is a way out of every box, a solution to every puzzle; it’s just a matter of finding it.” In many respects his comment is not at all far-fetched – even a problem that seems unsolvable will someday be solved by someone, somewhere. Five hundred years ago, it is unlikely anyone ever thought ships would be powered by anything but wind, or that humans would one day be able to fly in metal birds. Many things have been invented in the past 500 years. Some have been good, and others not so good, especially as far as the planet is concerned.
The problems we face in the world today are not trivial, but neither are they unsolvable. Our technology is evolving to the point where we may be able to rein in some of the effects of climate change, but there is no doubt we cannot stop it. We could use some of our technologies to clean up the planet of plastic, or indeed reduce the amount of CO2 we pump into the air, but we seem more inclined to worry about the next iPhone. Average humans have become detached from our planet, with little regard to maintaining any sort of environmental balance.
In some ways we have to wind back our lives. This means reducing the amount of things we buy, and manufacturing things that last, like we use to do in the days before the “throw-away” society. We need to advance technologies such as using enzymes to eat plastic. We have to learn to produce food locally again, with less reliance on food from far places. Humans can change the way we live, it’s a matter of whether or not we actually want to.
Recursion – The Sieve of Eratosthenes
We have looked at the “sieve” before, and realistically it is actually a good candidate for recursion.
Below is the main (calling) program in Fortran. The program uses a sieve which is stored as a dynamic array, by declaring the array primes
as allocatable
. This makes it more efficient from a storage perspective. The user can input a value for the upper bound to check for primes, and allocate()
is called to create the associated resources for prime
. After the recursive subroutine sieve()
is called, the remainder of the program deals with printing the primes to a file, primes.txt
, in an orderly, column-based manner.
program eratosthenes
integer :: i, j, N
integer, dimension(:), allocatable :: primes
open(unit=9,file='primes.txt',status='replace',action='write')
write (*,*) "Enter the boundary to check for primes: "
read (*,*) N
allocate(primes(N))
do i = 1, N
primes(i) = i
end do
call sieve(N,primes,2)
write (*,50) "Prime numbers from 1 to ", N, " written to file primes.txt"
50 format (A,I8,A)
j = 1
do i = 1, N
if (primes(i) /= 0) then
write (9,"(I5)",advance="no") primes(i)
j = j + 1
if (mod(j,10) == 0) then
write (9,*)
end if
end if
end do
close (9,status='keep')
end program eratosthenes
Now, on to the recursive subroutine sieve()
. The subroutine has three parameters: N
, the size of the sieve, p
, the sieve array holding the primes, and x
, the starting value, in this case 2.
recursive subroutine sieve(N, p, x)
integer, intent(in) :: N
integer, intent(inout), dimension(N) :: p
integer, intent(in) :: x
integer :: j, k
k = sqrt(real(N))
if (x == 2) then
do j = 4, N, 2
p(j) = 0
end do
call sieve(N,p,x+1)
elseif (mod(x,2) == 1 .and. x <= k) then
do j = x, N, x
!if (mod(p(j),x) == 0 .and. p(j) /= x) then
if (p(j) /= x) then
p(j) = 0
end if
end do
call sieve(N,p,x+2)
end if
end subroutine sieve
What is happening in this subroutine?
- On Line 10, if the value of
x
is 2, then all even numbers except 2 are set to 0. After this,sieve()
is called with thex+1
. This section of code is only actioned in the initial call tosieve()
. - On Line 15, the odd values are processed, until
x
is <=k
. All multiples ofj
are marked inp
by setting them to zero. For example ifx
= 3, then 6, 9, 12, etc. are set to 0. At the end of this section of code (Line 22),sieve()
is called withx+2
, making sure only odd numbers are processed.
Here is the output from the program:
1 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181 191 193 197 199 211 223 227 229 233 239 241 251 257 263 269 271 277 281 283 293 307 311 313 317 331 337 347 349 353 359 367 373 379 383 389 397 401 409 419 421 431 433 439 443 449 457 461 463 467 479 487 491 499 503 509 521 523 541 547 557 563 569 571 577 587 593 599 601 607 613 617 619 631 641 643 647 653 659 661 673 677 683 691 701 709 719 727 733 739 743 751 757 761 769 773 787 797 809 811 821 823 827 829 839 853 857 859 863 877 881 883 887 907 911 919 929 937 941 947 953 967 971 977 983 991 997
Generating a colour wheel in Processing
One of the annoying things about writing blogs is having access to figures that are hard to just generate without a program of sorts (its always easier to generate these things, than “borrow” them). A good example is a colour or hue wheel, or more specifically, a colour wheel associated with the HSV/HSB colour space. So things like this can be easily achieved in Processing, the programming language based on Java and designed for visual arts type applications.
Now the HSB Hue-Saturation-Brightness colour space is often represented as a cylinder, with three coordinates: the circumference of the circular end, representing hue from 0 to 360°, the radius from the centre of the cylinder to the end representing the saturation from o to 100%, and the length of the cylinder representing brightness from 0 to 100%.


Let’s look at what the Processing program looks like. First the setup:
float sat, bright;
void setup() {
size(600, 600);
colorMode(HSB, 360, 100, 100);
background(255,0,100);
noStroke();
}
Set up the variables and environment. The size of the sketch area is set to 600×600, and the colour mode is set to HSB.
The background colour is set to white, based on HSB.
Then the draw()
procedure:
void draw() {
sat=100;
bright=100;
for (int i=100; i>=1; i=i-1){
drawColourWheel(width * (i/100.0));
sat = sat - 1;
}
}
The draw() procedure sets the brightness and saturation values to 100%, and then iterates through a loop 100 times. Each time the loop iterates, the procedure drawColourWheel()
is called. With each iteration the size of the circle is reduced, and the saturation is also reduced. Each smaller circle, overlaps the previous one.
The end result of the draw()
procedure is the top of the HSB cylinder, with 100% saturated colours around the rim, graduating towards 0% saturation colours in the centre. Here is the procedure drawColourwheel()
:
void drawColourWheel(float size) {
float angle=1;
float startDeg=0;
int nSeg = int(360.0/angle);
for (int i=0; i < nSeg; i++) {
float endDeg = startDeg + angle;
float hue = startDeg + ( angle / 2);
fill(360-hue, sat, bright);
arc(width/2, height/2, size, size, radians(startDeg), radians(endDeg));
startDeg = startDeg + angle;
}
}
What happens here?
- Line 2 : The variable sets the angle to 1°.
- Line 3: The variable is used for drawing the arc.
- Line 4: The variable is used to derives the number of segments.
- Lines 6-12: Loop to draw every segment of the circle.
- Line 7: Set the end degree for the arc.
- Line 8: Calculate the hue for the middle of the arc.
- Line 9: Set the fill colour.
- Line 10: Generate an arc.
- Line 11: Modify the starting degree.
Why Processing is so good for visual things
I don’t like heaping too much praise on a programming language, partially because I know that every language is built to do something well. I mean most languages can be used to do a lot of differing things, but while you can calculate Roman numerals in Cobol, it is designed to do financial calculations, as C is designed to do systems stuff, and C++… well I don’t really know what it was designed for (except perhaps to spread the doctrine of OO).
Processing was designed to do visual things. It is a programming language and environment built for the media arts communities.
“Processing’s programming constructs are consistent and well thoughtout—essentially simplified Java, although “simplified” is the wrong word; it might be better to say ‘elegantized’, because the authors of Processing have identified a target audience—geeky artists—and have created something out of Java’s baroque environment that geeky artists can learn quickly and explore immediately; they’ve whittled down Java’s carved-oak throne into a slick, Swiss sling-back chair on an aluminum frame.”
Paul Ford [3]
In some respects Processing may have been a poor choice for a name, because it does make it challenging to Google things. I use this language to do visual things. It’s not really good at user input, but it excels at creating visual output. Here are my “wins” for the language.
- It performs the task of visual processing admirably. It is easy to create visual things, modify them, and save copies of the visualization as images.
- The language includes a lot of visual primitives.
- Control structures are the same as you would find in Java.
- You don’t have to first learn class definitions or method declarations to visualize something.
- As Ben Fry, one of the creators put it “The IDE is designed to make Java-style programming less wretched.”
- It can be used for basic image processing.
So I was looking for a program to generate a colour spectrum image. This involves converting wavelengths to RGB. Now the hard work has already been done by Dan Bruton, who created a Fortran program for generating RGB values for visible wavelengths [5,6]. I translated the program to C, and generated a file of (comma separated) RGB values. Then I used Processing to read in this information and generate the colour spectrum. The thing is Processing doesn’t need to do grunt work like generating this data – if a program to generate the data already exists, use it. Below is what the generated colour spectrum looks like.

Now let’s go through the code. This first part of the code deals with setting up the environment.
public void setup() {
size(600,150);
background(255,255,255);
noStroke();
noLoop();
}
Next is the procedure that does all the work, draw()
:
void draw() {
float x=0, w=width/400.0;
int i;
colorMode(RGB,255,255,255);
String [] rgbinfo = loadStrings("sprgb.txt");
for (String s : rgbinfo){
String [] elements = s.split(",");
int rc = Integer.parseInt(elements[0]);
int gc = Integer.parseInt(elements[1]);
int bc = Integer.parseInt(elements[2]);
fill(rc, gc, bc);
rect(x, 0, w, height-30);
x = x + w;
}
fill(0, 0, 0);
stroke(0,0,0);
strokeWeight(2);
line(20*w,height-30,20*w,height-25);
text("400nm",20*w-20,height-5);
line(120*w,height-30,120*w,height-25);
text("500nm",120*w-20,height-5);
line(220*w,height-30,220*w,height-25);
text("600nm",220*w-20,height-5);
line(320*w,height-30,320*w,height-25);
text("700nm",320*w-20,height-5);
saveFrame("colourspectrum.png");
}
The for
loop on lines 8-16 reads the file data into a string, and then separates the R, G, B components (the data is separated by commas). It then sets the colour using fill()
, and a coloured bar representing the colour is generated using rect()
. Lines 18-28 just adds the text and lines at the bottom of the spectrum. The colour is set to black using fill()
, the values of the stokes are set, and then a combination of small lines and text is used to demarcate the various nanometres (nm).
I also wanted to create a couple of visuals to represent various aspects of the HSV/HSB colour space. As the colour space can be represented by a cylinder, I wanted to create: (i) the top of the cylinder representing hue and saturation, and (ii) a cylindrical representation of the HSB colour space. Neither of these things are easy to do in most languages, and even drawing apps struggle with getting the colours wrapped on the cylinder properly. I’ll be posting these two examples separately.
Further reading:
- Reas, C., Fry, B., “Processing: programming for the media arts”, AI & Soc 20, pp.526–538 (2006).
- Reas, C., Fry, B., “Working the art process by typing in computer code”, Visual Communication 5(2) pp.205-217 (2006)
- Ford, P., “Processing Processing”, in The Best Software Writing I, pp.79-93 (2005)
- Pearson, M., generative art: a practical guide using processing (2011)
- Bruton, D., “Approximate RGB values for Visible Wavelengths“, Fortran code, (1996)
- Bruton, D., Color Science, website
- Reas, C., Fry, B., Processing: a programming handbook for visual designers and artist, (2007)
The Sieve of Eratosthenes (iii) – Cobol
To get a little trickier, let’s now look at a Cobol version of the sieve program. Here’s the first part of the program:
identification division.
program-id. eratosthenes.
environment division.
input-output section.
file-control.
select efile assign to "primesC.txt"
organization is line sequential.
data division.
file section.
fd efile.
01 primes-record.
03 prime-num pic zzz999.
The first part of the program deals with all the same things found in normal Cobol programs. In file-control, an output file, primesC.txt
is associated with the file “pointer” efile
. Finally in the data division
, a record is associated with the file pointer – this specifies the form of the output to the file. The remainder of the data division deals with working storage. There are really just the variables used in the program.
working-storage section.
77 N pic 9(6).
77 i pic 9(6).
77 j pic 9(6).
77 k pic 9(6).
77 mm pic 9(6).
01 prime-numbers.
02 primes pic 9(6) occurs 10000 times depending on N.
Note the array primes
, which has a maximum size of 10000, is sized according to the value of N
.
procedure division.
open output efile.
display "Enter the boundary to check for primes: ".
accept N.
move 1 to i.
perform until i > N
move i to primes(i)
add 1 to i
end-perform.
perform sieve.
move 1 to i.
perform print-primes
until i is greater than N.
close efile.
stop run.
Here is what is happening in the first part of the procedure
division
:
- Lines 4-5: Obtain user input on the upper bound of values to check for primes.
- Lines 7-11: Populate the sieve with initial values.
- Line 13: Activate the paragraph
sieve
. - Lines 15-17: Print out the primes to file.
The paragraph sieve is shown below. Line 2 sets the upper bound. Lines 4-15 mark all multiples of a value by setting them to zero.
sieve.
compute k = function integer-part(function sqrt(N)).
move 2 to i.
perform until i > k
move 1 to j
perform until j > N
compute mm = function mod(primes(j), i)
if (mm is = 0) and (primes(j) is not = i) then
move 0 to primes(j)
end-if
add 1 to j
end-perform
add 1 to i
end-perform.
Finally, the paragraph print-primes
, output the prime values to file.
print-primes.
move primes(i) to prime-num.
if primes(i) is not = 0 then
write primes-record after advancing 1 line
end-if.
add 1 to i.
The Sieve of Eratosthenes (ii) – Fortran
With an understanding of the sieve, let’s look at a Fortran program to perform the calculation. There isn’t anything really magical about this program.
program primes
integer :: i, j, k, n=1000
integer, dimension(1000) :: sieve
do i = 1,1000
sieve(i) = i
end do
k = int(sqrt(real(n)))
do i = 2,k
do j = 1,n
if (mod(sieve(j),i) .eq. 0 .and. sieve(j) .ne. i) then
sieve(j) = 0
end if
end do
end do
write(*,"(a,i3)") "prime numbers from 1 to 1000"
do i = 1,n
if (sieve(i) .ne. 0) then
write(*,"(i5)",advance="no") sieve(i)
end if
end do
end
Here is what is happening in the program:
- Lines 5-7: Populate the sieve with the values 1 to 1000.
- Line 9: Sets the upper limits to check for primes.
- Lines 11-17: Mark all multiples of i by setting them to zero
- Lines 21-25: Print out the prime numbers, ignoring all the non-primes set to 0.
The Sieve of Eratosthenes (i) – Introduction
The Sieve of Eratosthenes is named after the Greek mathematician Eratosthenes (276-196 BC), from Alexandria, who invented it. He is also the man who first measured the circumference of the earth. This method, of listing primes, is called a “sieve” because it is like taking all of the numbers (up to some maximum) and running them through a sieve to separate out all of the primes.
A prime number (such as 2 or 3 or 5) is a natural number (positive whole number) which is only divisible by itself and one (and no other natural number). The other natural numbers (greater than one), are called composite numbers, and are the products of prime numbers. One is neither prime nor composite.
To determine if a number is prime or composite (and list its prime factors), we often have to experiment by dividing by primes from a list of primes. We divide by 2, 3, 5, etc. And if none of these divisions comes out even, then our number is a prime. Let’s try 91, which looks like it might be a prime. We try 2, 3, 5, and those don’t come out even. But, when we divide by 7, we get 13. So 91=7 x 13, and is composite. There is a fairly simple method for making a list of primes. We will start with a list of all of the numbers from 2 to 100:
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
We now make 2 bold (you can circle it), identifying it as prime (it is not divisible by lesser primes), and set to zero every second number after 2:
2 3 0 5 0 7 0 9 0 11 0 13 0 15 0 17 0 19 0 21 0 23 0 25 0 27 0 29 0 31 0 33 0 35 0 37 0 39 0 41 0 43 0 45 0 47 0 49 0 51 0 53 0 55 0 57 0 59 0 61 0 63 0 65 0 67 0 69 0 71 0 73 0 75 0 77 0 79 0 81 0 83 0 85 0 87 0 89 0 91 0 93 0 95 0 97 0 99 0
We have now identified 3 as a prime. It is not divisible by lesser primes. And we set to zero every third number after 3. Some of these are already set to zero. We will just skip over those:
2 3 0 5 0 7 0 0 0 11 0 13 0 0 0 17 0 19 0 0 0 23 0 25 0 0 0 29 0 31 0 0 0 35 0 37 0 0 0 41 0 43 0 0 0 47 0 49 0 0 0 53 0 55 0 0 0 59 0 61 0 0 0 65 0 67 0 0 0 71 0 73 0 0 0 77 0 79 0 0 0 83 0 85 0 0 0 89 0 91 0 0 0 95 0 97 0 0 0
We do the same thing with 5, and then 7:
2 3 0 5 0 7 0 0 0 11 0 13 0 0 0 17 0 19 0 0 0 23 0 0 0 0 0 29 0 31 0 0 0 0 0 37 0 0 0 41 0 43 0 0 0 47 0 0 0 0 0 53 0 0 0 0 0 59 0 61 0 0 0 0 0 67 0 0 0 71 0 73 0 0 0 0 0 79 0 0 0 83 0 0 0 0 0 89 0 0 0 0 0 0 0 97 0 0 0
And now, we can stop! You may want to go on and try 11. But that is unnecessary. No more numbers will be crossed out, between 2 and 100. Do you see why?
We can stop at the square root of 100, which is 10. The reason for this is that any number less than 100 (91, for example), which is divisible by a number greater than the square root of 100 (13, in this e0ample), is also divisible by a number less than the square root of 100 (7, in this example). So, we have already crossed out all such numbers. Removing the 0’s, we have this list of primes:
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97