// ~ Learning Goals ~ //
(1) Learn basics of creating and running threads.
(2) Understand further the nature and limits of inbuilt types.
// ~ Submitting Your Assignment ~ //
For this assignment you must only submit the solution file
"answer12.c". You can use the tester program to test your solution
before uploading it. Do not submit a zip file.
// ~ Introduction ~ //
So far we have only considered computer programs that try to do one
thing at a time. In this programming assignment we will learn about
computer programs that do muliple things at the same time. This is
referred to as "threading". For example, a sufficiently smart computer
program could optimize its time by watching important TV shows on HBO,
while simultaneously doing the ironing. This example is not entirely
glib. In this case we are talk about two different simultaneous tasks
(TV and ironing), and each executing task is referred to as a thread.
There are many reasons why threading is important. For this course we
will consider speed. Although computers are still getting faster,
today they are really only getting better at doing multiple things at
the same time. (The execution of single threaded programs is not
getting much faster.) To extend our analogy, if we have lots of
ironing to do, we cannot build a faster robot to do the ironing. The
speed of the robot is maxed out. But we can set up multiple robots on
multiple ironing boards to do the work simultaneously. Ten robots (ten
threads) would mean (roughly speaking) ten times as much ironing.
In general, you rarely get ten times the speed for using ten times as
many threads. The problem is that the threads will need to communicate
with each other, and that slows everything down. To extend our
analogy, imagine that our ironing robots are getting their tasks
(particularly wrinkly shirts) from a big bin full of fresh laundry. If
the robots do not communicate with each other, then we could imagine a
situation where two robots attempt to pick up the same shirt at the
same time -- probably tearing it in half. The chances of this
happening may be small, but non-zero. That means, firstly, that the
bug of a shirt being so-torn is very difficult to reproduce. If a bug
like this happens in your computer program, it can be almost
impossible to track down. Secondly, it means that all your robots need
to communicate with each other to get the job done.
In this assignment, we will create some threads (robots) to identify
whether or not a large number is prime (do the laundry). The threads
will each work on part of the task (break the laundry up into
piles). Normally you would need to consider how to make threads work
nicely together; however, this assignment has been carefully written
so that you do not need to do that. (If done straight-forwardly,
robots will never tear shirts in this assignment.) It is important to
keep in mind that threading is difficult to get right, and to do so,
you must learn how to synchronize the activities of your threads.
// ~ Determining if a Number is Prime ~ //
This is an ongoing area of research. For this assignment we will use a
very simple approach. Please read the following webpage on factorizing
prime numbers:
http://cartera.me/2012/01/10/primality-testing-and-factorization-in-c/
In this assignment, we will be using the
"primalityTestWithOnlyOddsAndSqrtLimit" function from the above
page. For your convenience, it is displayed below:
int primalityTestWithOnlyOddsAndSqrtLimit(long int n)
{
if (n % 2 == 0)
return 0;
long int max = floor(sqrt(n));
long int i;
for (i = 2; i < max; i++)
{
if (n % ((2 * i) + 1) == 0)
return 0;
}
return 1;
}
You will need to modify this function to make it
parallel. Furthermore, this function deals with puny "long int"
numbers. We'll want more juice than that. So you will also have to
modify this function to use 128 bit integers.
There are some other problems with this function too. (Lesson: do not
believe everything you read on the interwebs.) Can you see the
problems? For starters, this function says that 2 isn't a prime
number! Secondly, (and more perniciously), Carter Allen does not
handle the 'i' in the for loop correctly. For example, imagine that
you are testing if 83 is prime. In this case max = floor(sqrt(83)) ==
9, which is correct. Now you want to test every odd number between 3
and 9 inclusive, but that is not what Carter Allen has done! You will
need to fix this bug.
The webpage above (correctly) explains the very *very* simple
mathematics behind this function.
// ~ What you need to do :: Preliminaries ~ //
We will be testing LARGE prime numbers. These will be 128 bit
integers, which are far too large to fit in measly 32-bit or 64-bit
int variables. A 32-bit int variable can only contain values from 0 to
4,294,967,295, but with unsigned 128 bit numbers, you can go all the
way to 340,282,366,920,938,463,463,374,607,431,768,211,455.
GCC has a native 128-bit integer type called "__int128". In this
assignment we are interested in /unsigned/ integers, and so we will be
using the type "unsigned __int128". There is a typedef statement in
answer12.h that defines a shorthand notation "uint128"
typedef unsigned __int128 uint128;
There are no built in functions to print these integers, or to convert
strings into these integers. You will need to write and test such a
function yourself.
You must also write your own function for printing unsigned 128-bit
numbers.
You should be able to pass the following test-case.
// Example: writing out a Biiigggg number
int main(int argc, char * * argv)
{
const char * str = "340282366920938463463374607431768211455";
uint128 w = alphaTou128(str);
char * w_str = u128ToString(w);
printf("Biiigggg number: %s\n", w_str);
if(strcmp(str, w_str) != 0)
printf("ERROR!, expected %s\n", str);
free(w_str);
return EXIT_SUCCESS;
}
Before continuing with the assignment, you need to complete the
functions alphaTou128(str), and u128ToString(w).
// ~ What you need to do :: Testing primality ~ //
As Carter Allen notes on his webpage, the function
primalityTestWithOnlyOddsAndSqrtLimit lends itself to
parallelism. Simple put, if you want to test if a number is divisible
(exactly) by numbers in the range [0..n], then you can split this
range into chunks, and test each chunk in a separate thread. If /any/
chunk of the computation finds a factor, then the number is not prime.
For his threaded version, Carter Allen used "Grand Central Dispatch",
which is a relatively new Apple technology. For this assignment we
will use the trusty pthreads library instead of Grand Central
Dispatch. pthreads is the standard threading library available on all
flavors of unix (including OS X and Linux), and can also be used on
windows. One key reason for using pthreads is that, in my experience,
it is not worth learning a shiny simplified technology until you
understand a bit about the underlying machinery. So learning pthreads
is a very good idea, and the knowledge gained will transfer naturally
to other threading libraries.
Feel free to examine Carter Allen's code; however, you will not be
able to compile it on the ECE computers. Examining his code may help
you understand how to create a threaded version using pthreads;
however, many important details are missing.
// ~ How to Compile, Run and Test ~ //
For your convenience, the inputs folder contains two files. One file
contains 390 prime numbers. The other file contains 2116 non-prime
numbers. Your program should correctly detect all 390 primes as prime,
and all 2116 non-primes as non-prime. Don't forget that 2 is a prime
number.
// ~ Why Prime Numbers ~ //
You might know that modern cryptography relies on the fact that no-one
knows how to efficiently determine whether or not a number is
prime. If someone ever figures this out, then they may well be the
subject of a real-life spy novel. This was the theme of the 90s hit
film "Sneakers".
But as far as prime numbers go, cryptography is the tip of the
iceberg. If math has anything to do with the universe, then prime
numbers have a special place in how it ticks. These special numbers
have been the subject of extensive investigation by mathematicians for
all of recorded history, yet they still present many mysteries. Their
universality lead the great American scientist, Carl Sagan, to suggest
that if aliens were to communicate with humans, then they could use
prime numbers to capture our attention. This idea is the centre-piece
of Sagan's only work of fiction, the best selling novel, "Contact",
which has since been made into a film.
(http://www.youtube.com/watch?v=8qDjg8mdd8c)