334 changes: 334 additions & 0 deletions openmp/testsuite/README
Original file line number Diff line number Diff line change
@@ -0,0 +1,334 @@
============================================================================
| OpenMP Validation Suite V 3.0 |
| High Performance Computing Center, Stuttgart |
| High Performance Computing and Tools, University of Houston |
| Jan. 2012 |
============================================================================


TABLE OF CONTENTS

I INTRODUCTION
I.1. Aims and general function
I.2. Files and directories

II USAGE
II.1. First run with make
II.2 Where to search for results
II.3. Using the runtest script

III Adding and modifying tests
III.1. The template structure

IV Known Issues and Workaround

V Contact and Support

------------------------------------------------------------------------------

I. INTRODUCTION
==============================================================================

I.1. Aims and general function
--------------------------------

The OpenMP validation suite is designed to verify the correct implementation
of OpenMP in compilers. It is capable of checking Fortran as well as c
compiler.

Testing the implementation is based on statistics. Each directive is tested
by computing and verifying the result with the already known value. In most
cases a wrong implementation can result in the right values. So the tests are
run several times.

Additionally, the validation suite creates so called crosstests for each
directive. These are tests in which either the directive is missing or used
with different arguments. If this so called crosstest fails, this indicates
strongly that the previous test is capable of testing the directive.

Lastly, an orphaned test is also run to determine if the directive being
tested is able to correctly run when 'orphaned' from the main function.
Essentially, the directive's code is placed into its own function which is
called during execution of the main function and often inside a parallel
region.


I.2. Files and directories
----------------------------


d c directory containing the templates for the c tests
d fortran directory containing the templates for the Fortran
tests
Makefile Makefile containing options for compilation
common_utility.f
omp_my_sleep.h thread save sleep function
omp_testsuite.f Fortran header file
omp_testsuite.h autogenerated c-header file
ompts-c.conf configuration file for the c tests about how often
the tests shall be executed or how large the loop size
is
ompts_makeHeader.pl perl module for automatically generation of an up
to date header file
ompts_parserFunctions.pm perl module containing general functions for
the parser.pl script
ompts_parser.pl script for generating the source code out of the templates
ompts_standaloneProc.c framework for the c tests
ompts_standaloneProc.f framework for the Fortran tests
README the README file you've already found ;-)
LICENSE contains license information
runtest.pl the frame program of the test suite
testlist-f.txt test list containing the available tests for Fortran
testlist-c.txt test list containing the available tests for c


------------------------------------------------------------------------------

II. USAGE
==============================================================================


II.1. First run with make
--------------------------


You can do a first simple run of the testsuite only after one step of
configuration:

1) Modify the ompts.conf and ompts-c.conf file, change the number of threads
and number of repetitions of each test.

2) Modify the Makefile, uncommenting the CC/FC and CFLAGS/FFLAGS variables for
the compiler of your choice.

And now you can run the testsuite either for a C compiler with:

> make ctest

or for a Fortran compiler with:

> make ftest


II.2. Running custom tests
--------------------------


In order to run single tests or custom groups of tests, two make commmands
are defined: make stest and make fstest. These two command reference the file
customtest.txt when looking for a testlist to use. Simply edit customtest.txt
to include the desired test or tests. If customtest.txt contains c tests,

> make stest

or for fortran tests

> make fstest

In order to change the number of threads used in the tests, simply edit the
Makefile variables MINTHREADS and MAXTHREADS. By default, they are configured
to use 2 threads. To change the number of times each test is run, for c tests
edit the REPETITIONS variable in the file ompts-c.conf. The LOOPCOUNT and
SLEEPTIME variables can also be changed here. For fortran tests, edit the file
omp_testsuite.f to change both the LOOPCOUNT and the number of times each test
is run.



II.3. Understanding the results
---------------------------------


When running the testsuite the results will be shown on the screen.

If you need the results for further purpose you can use the results.txt, which
is a simple list containing the results for each directive
in a single line. Each line starts with the name of the directive. Then follows
the result of the test given in the percentage of the passed tests. If 100% of
the tests passed successfully, the second number gives the result of the
corresponding crosstest. Crosstests will only be run if the normal test passes
with 100% accuracy. If a crosstest was not run or a test does not exist, it is
denotated by a "-".
After the results of the normal tests, there follow a series of tests in the
orphaned mode. If there were no orphaned tests available this is shown by a "-".

If you run the testsuite with different numbers of threads (e.g. using the
runtest.pl script) the results are shown in blocks of 4 columns for each number
of threads.

If a test fails you can find more detailed information in the ompts.log,
bin/c/*.out and *.log files. While the ompts.log file contains all compiler
error messages for all tests, the *.out and *.log files contain detailed inforamtion
on the execution process of the single tests.
In the *.out files there are listed all the results of the single executions of
the tests. In the *.log files there are error messages of the tests itself.


II.4. Cleaning Up
-----------------


Because many files are generated for each tested directive, it is often necessary
to clean the main directory after a battery of tests. To clean all generated files
in the main directory including the results and log files,

> make clean


To clean only the logs and out files,

> make cleanlogs

To clean only the results,

> make cleanresults



II.4. Using the runtest script
-------------------------------


So for special purpose you can use the runtest.pl script, which allows a lot
more options for the execution process than the execution with make.

Using the runtest.pl script is rather easy. You can use the the test suite only
after two steps of modifications:

1.) Modify the Makefile to your wishes choosing your compiler and the necessary
compiler flags.
2.) If necessary edit one of the test lists (testlist-c.txt) and comment out the
tests you do not want to run using # at the beginning of a line. Testlists for Fortran end
with -f.txt while test lists for c with -c.txt.

And now you can run the test suite either for Fortran using
# > ./runtest.pl -lang=fortran -d=fortran testlist-f.txt
or for c
# > ./runtest.pl -lang=c -d=c testlist-c.txt

With the --help option you can show the complete list of options and their
explanations.

The test results are summarized in cresults or fresults.txt while *.log keep
details for individual tests. There is also a file (ompts.log) keeping
compilation information. (see section II.2 )

If you don't want to test the directives in orphaned mode you can use the
-norphan option. You also can use the runtest.pl script either to compile all
tests or run compiled tests e.g. for cross compilation on other platforms. For
this there are the options -norun and -nocompile.

Happy testing!


------------------------------------------------------------------------------

III. How to add new tests / The structure of test templates
==============================================================================

III.1 The template structure
------------------------------

The test suite is based on templates so that you only have one file for test,
crosstest and the orphaned versions of them.

A) Description of the template structure

The syntax of the templates is much like xml. So each test begins with
'<ompts:test>' and ends with '</ompts:test>'.

In between there are several other blocks holding information:

- <ompts:testdescription> </ompts:testdescription> In between this tag you can
give a description on what the test checks and how it works.

- <ompts:ompversion> </ompts:version> This tag is used to specify the
OpenMP-version which includes the tested directive.

- <ompts:directive> </ompts:directive> Used to specify the directive how it is
called in the programming language.

- <ompts:dependences> </ompts:dependences> With this tag you can specify other
omp directives which are necessary for the correct execution of your test.
The directives have to be listed by their directive names as it is called in
the programming language. Multiple directives are separated by ','.

- <ompts:testcode> </ompts:testcode> In this tag stands the whole source code
for the test / crosstest. Each test has to be written as a function. The
syntax of the functions differs between C and Fortran: In C it has to take a
file pointer 'FILE * logFile' and return an int. If the test has been passed
successful it has to return a value unequal to 0. The file pointer can be used
to write information into a log file. In Fortran the function takes no
argument and the function name must not exceed XX characters. The return value
has to be specified using the '<testfunctionname>' tags. It has to be 1 if the
test succeeded and 0 if the test failed. For details see the example.

To tell the test suite the name of your test function you have to enclose it
into the '<ompts:testcode:functionname> </ompts:testcode:functionname>' tag.

If there are differences between test and crosstest you can use the
<ompts:check> </ompts:check> and <ompts:crosscheck> </ompts:crosscheck> tag.
When generating the test the parser will use the code enclosed in
<ompts:check> tags and cut out the code written in <ompts:crosscheck> tags. So
you have two possibilities to write your template for test and crosstest: The
first way you can write the complete code is to write the test in one
<ompts:check> tag and later the crosstest in one <ompts:crosscheck> tag. The
second way is to write both tests only by enclosing differing parts in
corresponding tags.

The first method should be preferred if test and crosstest differ much from
each other. The second e.g. if you only want to change a few options like
replacing an omp singleprivate clause by an omp private clause or to cut out
a directive like omp flush. When you use the first way you have to take care
of the function name! You have to declare it twice with
<ompts:testcode:functionname>!

- <ompts:orphan> </ompts:orphan> This tag can be used if you want to enable
your test to check the directive in orphan regions, too. The code enclosed
in this part will be written to a separate function which will be called
instead. If you have variables which are used outside this region you have to
declare them as global variables enclosed in an <ompts:orphan:vars> tag. For
further information see the description of the <ompts:orphan:vars> tag.

- <ompts:orphan:vars> </ompts:orphan:vars> This tag is used to specify global
variables for an orphan region which allow the exchange of values between
the main program and the orphaned functions. The usage differs between C and
Fortran. In C you have to use a single declaration for each variable. You can
either declare all variables in one single or in several different regions. You
must not initialize the variables inside! In Fortran you have to put all
declarations in one single tag. Because there exist no global variables as in
C you have to use common blocks. For further information see the examples.

III.2. Adding tests to the test lists
--------------------------------------

After you have created a new test you have to add them to a testlist. Simply
add the function name in a new Line into a file.



------------------------------------------------------------------------------


IV. Known Issues and Workaround
==============================================================================

The Sun OS has a problem with the -maxdepth option on the 'make cleanall'
command. This prevents the tests from being removed from the working directory
and can cause problems with future tests. To remedy, edit the makefile line
under the clean command:

-rm [cf]test*.[cf] [cf]crosstest*.[cf] [cf]ctest*.[cf] [cf]orphan*.[cf]

Change to:

-rm [cf]test* [cf]crosstest* [cf]ctest* [cf]orphan*



------------------------------------------------------------------------------

V. Contact and Support
==============================================================================

Contact: http://www.cs.uh.edu/~hpctools
30 changes: 30 additions & 0 deletions openmp/testsuite/c/has_openmp.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<ompts:test>
<ompts:testdescription>Test which checks the OpenMp support.</ompts:testdescription>
<ompts:ompversion>2.0</ompts:ompversion>
<ompts:directive>_OPENMP</ompts:directive>
<ompts:testcode>
#include <stdio.h>

#include "omp_testsuite.h"

int <ompts:testcode:functionname>has_openmp</ompts:testcode:functionname>(FILE * logFile){
<ompts:orphan:vars>
int rvalue = 0;
</ompts:orphan:vars>

<ompts:orphan>
<ompts:check>
#ifdef _OPENMP
rvalue = 1;
#endif
</ompts:check>
<ompts:crosscheck>
#if 0
rvalue = 1;
#endif
</ompts:crosscheck>
</ompts:orphan>
return (rvalue);
}
</ompts:testcode>
</ompts:test>
434 changes: 434 additions & 0 deletions openmp/testsuite/c/omp_atomic.c

Large diffs are not rendered by default.

41 changes: 41 additions & 0 deletions openmp/testsuite/c/omp_barrier.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<ompts:test>
<ompts:testdescription>Test which checks the omp barrier directive. The test creates several threads and sends one of them sleeping before setting a flag. After the barrier the other ones do some littel work depending on the flag.</ompts:testdescription>
<ompts:ompversion>2.0</ompts:ompversion>
<ompts:directive>omp barrier</ompts:directive>
<ompts:testcode>
#include <stdio.h>
#include <unistd.h>

#include "omp_testsuite.h"
#include "omp_my_sleep.h"

int <ompts:testcode:functionname>omp_barrier</ompts:testcode:functionname> (FILE * logFile)
{
<ompts:orphan:vars>
int result1;
int result2;
</ompts:orphan:vars>

result1 = 0;
result2 = 0;

#pragma omp parallel
{
<ompts:orphan>
int rank;
rank = omp_get_thread_num ();
if (rank ==1) {
my_sleep(SLEEPTIME_LONG);
result2 = 3;
}
<ompts:check>#pragma omp barrier</ompts:check>
if (rank == 2) {
result1 = result2;
}
</ompts:orphan>
}
printf("result1=%d\n",result1);
return (result1 == 3);
}
</ompts:testcode>
</ompts:test>
42 changes: 42 additions & 0 deletions openmp/testsuite/c/omp_critical.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<ompts:test>
<ompts:testdescription>Test which checks the omp critical directive by counting up a variable in a parallelized loop within a critical section.</ompts:testdescription>
<ompts:ompversion>2.0</ompts:ompversion>
<ompts:directive>omp critical</ompts:directive>
<ompts:testcode>
#include <stdio.h>
#include <unistd.h>

#include "omp_testsuite.h"
#include "omp_my_sleep.h"

int <ompts:testcode:functionname>omp_critical</ompts:testcode:functionname> (FILE * logFile)
{
<ompts:orphan:vars>
int sum;
</ompts:orphan:vars>
sum=0;
int known_sum;

<ompts:orphan>
#pragma omp parallel
{
int mysum=0;
int i;

#pragma omp for
for (i = 0; i < 1000; i++)
mysum = mysum + i;

<ompts:check>#pragma omp critical</ompts:check>
sum = mysum +sum;

} /* end of parallel */
</ompts:orphan>

printf("sum=%d\n",sum);
known_sum = 999 * 1000 / 2;
return (known_sum == sum);

}
</ompts:testcode>
</ompts:test>
50 changes: 50 additions & 0 deletions openmp/testsuite/c/omp_flush.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<ompts:test>
<ompts:testdescription>Test which checks the omp flush directive.</ompts:testdescription>
<ompts:ompversion>2.0</ompts:ompversion>
<ompts:directive>omp flush</ompts:directive>
<ompts:dependences>omp barrier</ompts:dependences>
<ompts:testcode>
#include <stdio.h>
#include <unistd.h>

#include "omp_testsuite.h"
#include "omp_my_sleep.h"

int <ompts:testcode:functionname>omp_flush</ompts:testcode:functionname> (FILE * logFile)
{
<ompts:orphan:vars>
int result1;
int result2;
int dummy;
</ompts:orphan:vars>

result1 = 0;
result2 = 0;

#pragma omp parallel
{
int rank;
rank = omp_get_thread_num ();

#pragma omp barrier
if (rank == 1) {
result2 = 3;
<ompts:orphan>
<ompts:check>#pragma omp flush (result2)</ompts:check>
dummy = result2;
</ompts:orphan>
}

if (rank == 0) {
<ompts:check>my_sleep(SLEEPTIME_LONG);</ompts:check>
<ompts:orphan>
<ompts:check>#pragma omp flush (result2)</ompts:check>
result1 = result2;
</ompts:orphan>
}
} /* end of parallel */

return ((result1 == result2) && (result2 == dummy) && (result2 == 3));
}
</ompts:testcode>
</ompts:test>
56 changes: 56 additions & 0 deletions openmp/testsuite/c/omp_for_collapse.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<ompts:test>
<ompts:testdescription>Test with omp for collapse clause. Bind with two loops. Without the collapse clause, the first loop will not be ordered</ompts:testdescription>
<ompts:ompversion>3.0</ompts:ompversion>
<ompts:directive>omp for collapse</ompts:directive>
<ompts:dependences>omp critical,omp for schedule</ompts:dependences>
<ompts:testcode>
#include <stdio.h>
#include <math.h>

#include "omp_testsuite.h"


/* Utility function to check that i is increasing monotonically
with each call */
static int check_i_islarger (int i)
{
static int last_i;
int islarger;
if (i==1)
last_i=0;
islarger = ((i >= last_i)&&(i - last_i<=1));
last_i = i;
return (islarger);
}

int <ompts:testcode:functionname>omp_for_collapse</ompts:testcode:functionname> (FILE * logFile)
{
<ompts:orphan:vars>
int is_larger = 1;
</ompts:orphan:vars>

#pragma omp parallel
{
<ompts:orphan>
int i,j;
int my_islarger = 1;
#pragma omp for private(i,j) schedule(static,1) <ompts:check>collapse(2)</ompts:check> ordered
for (i = 1; i < 100; i++){
<ompts:crosscheck>my_islarger = check_i_islarger(i)&& my_islarger;</ompts:crosscheck>
for (j =1; j <100; j++)
{
<ompts:check>
#pragma omp ordered
my_islarger = check_i_islarger(i)&&my_islarger;
</ompts:check>
} /* end of for */
}
#pragma omp critical
is_larger = is_larger && my_islarger;
</ompts:orphan>
}

return (is_larger);
}
</ompts:testcode>
</ompts:test>
55 changes: 55 additions & 0 deletions openmp/testsuite/c/omp_for_firstprivate.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<ompts:test>
<ompts:testdescription>Test which checks the omp for firstprivate clause by counting up a variable in a parallelized loop. Each thread has a firstprivate variable (1) and an variable (2) declared by for firstprivate. First it stores the result of its last iteration in variable (2). Then it stores the value of the variable (2) in its firstprivate variable (1). At the end all firstprivate variables (1) are added to a total sum in a critical section and compared with the correct result.</ompts:testdescription>
<ompts:ompversion>3.0</ompts:ompversion>
<ompts:directive>omp for firstprivate</ompts:directive>
<ompts:dependences>omp critical,omp parallel firstprivate</ompts:dependences>
<ompts:testcode>
#include <stdio.h>
#include <math.h>

#include "omp_testsuite.h"

int sum1;
#pragma omp threadprivate(sum1)

int <ompts:testcode:functionname>omp_for_firstprivate</ompts:testcode:functionname> (FILE * logFile)
{
int sum;
<ompts:orphan:vars>
int sum0;
</ompts:orphan:vars>

int known_sum;
int threadsnum;

sum = 0;
sum0 = 12345;
sum1 = 0;

#pragma omp parallel
{
#pragma omp single
{
threadsnum=omp_get_num_threads();
}
/* sum0 = 0; */
<ompts:orphan>
int i;
#pragma omp for <ompts:check>firstprivate(sum0)</ompts:check><ompts:crosscheck>private(sum0)</ompts:crosscheck>
for (i = 1; i <= LOOPCOUNT; i++)
{
sum0 = sum0 + i;
sum1 = sum0;
} /* end of for */
</ompts:orphan>
#pragma omp critical
{
sum = sum + sum1;
} /* end of critical */
} /* end of parallel */

known_sum = 12345* threadsnum+ (LOOPCOUNT * (LOOPCOUNT + 1)) / 2;
return (known_sum == sum);
}
</ompts:testcode>
</ompts:test>
52 changes: 52 additions & 0 deletions openmp/testsuite/c/omp_for_lastprivate.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<ompts:test>
<ompts:testdescription>Test which checks the omp for lastprivate clause by counting up a variable in a parallelized loop. Each thread saves the next summand in a lastprivate variable i0. At the end i0 is compared to the value of the expected last summand.</ompts:testdescription>
<ompts:ompversion>2.0</ompts:ompversion>
<ompts:directive>omp for lastprivate</ompts:directive>
<ompts:dependences>omp critical,omp parallel firstprivate,omp schedule</ompts:dependences>
<ompts:testcode>
#include <stdio.h>
#include <math.h>

#include "omp_testsuite.h"

int sum0;
#pragma omp threadprivate(sum0)

int <ompts:testcode:functionname>omp_for_lastprivate</ompts:testcode:functionname> (FILE * logFile)
{
int sum = 0;
int known_sum;
<ompts:orphan:vars>
int i0;
</ompts:orphan:vars>

i0 = -1;

#pragma omp parallel
{
sum0 = 0;
{ /* Begin of orphaned block */
<ompts:orphan>
int i;
#pragma omp for schedule(static,7) <ompts:check>lastprivate(i0)</ompts:check>
for (i = 1; i <= LOOPCOUNT; i++)
{
sum0 = sum0 + i;
i0 = i;
} /* end of for */
</ompts:orphan>
} /* end of orphaned block */

#pragma omp critical
{
sum = sum + sum0;
} /* end of critical */
} /* end of parallel */

known_sum = (LOOPCOUNT * (LOOPCOUNT + 1)) / 2;
fprintf(logFile," known_sum = %d , sum = %d \n",known_sum,sum);
fprintf(logFile," LOOPCOUNT = %d , i0 = %d \n",LOOPCOUNT,i0);
return ((known_sum == sum) && (i0 == LOOPCOUNT) );
}
</ompts:testcode>
</ompts:test>
57 changes: 57 additions & 0 deletions openmp/testsuite/c/omp_for_nowait.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<ompts:test>
<ompts:description>Test which checks the omp parallel for nowait directive. It fills an array with values and operates on these in the following.</ompts:description>
<ompts:directive>omp parallel for nowait</ompts:directive>
<ompts:version>1.0</ompts:version>
<ompts:dependences>omp parallel for, omp flush</ompts:dependences>
<ompts:testcode>
#include <stdio.h>

#include "omp_testsuite.h"
#include "omp_my_sleep.h"

int <ompts:testcode:functionname>omp_for_nowait</ompts:testcode:functionname> (FILE * logFile)
{
<ompts:orphan:vars>
int result;
int count;
</ompts:orphan:vars>
int j;
int myarray[LOOPCOUNT];

result = 0;
count = 0;

#pragma omp parallel
{
<ompts:orphan>
int rank;
int i;

rank = omp_get_thread_num();

#pragma omp for <ompts:check>nowait</ompts:check>
for (i = 0; i < LOOPCOUNT; i++) {
if (i == 0) {
fprintf (logFile, "Thread nr %d entering for loop and going to sleep.\n", rank);
my_sleep(SLEEPTIME);
count = 1;
#pragma omp flush(count)
fprintf (logFile, "Thread nr %d woke up and set count = 1.\n", rank);
}
}

fprintf (logFile, "Thread nr %d exited first for loop and enters the second.\n", rank);
#pragma omp for
for (i = 0; i < LOOPCOUNT; i++)
{
#pragma omp flush(count)
if (count == 0)
result = 1;
}
</ompts:orphan>
}

return result;
}
</ompts:testcode>
</ompts:test>
60 changes: 60 additions & 0 deletions openmp/testsuite/c/omp_for_ordered.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<ompts:test>
<ompts:testdescription>Test which checks the omp ordered directive by counting up an variable in an parallelized loop and watching each iteration if the sumand is larger as the last one.</ompts:testdescription>
<ompts:ompversion>2.0</ompts:ompversion>
<ompts:directive>omp for ordered</ompts:directive>
<ompts:dependences>omp critical,omp for schedule</ompts:dependences>
<ompts:testcode>
#include <stdio.h>
#include <math.h>

#include "omp_testsuite.h"

static int last_i = 0;

/* Utility function to check that i is increasing monotonically
with each call */
static int check_i_islarger (int i)
{
int islarger;
islarger = (i > last_i);
last_i = i;
return (islarger);
}

int <ompts:testcode:functionname>omp_for_ordered</ompts:testcode:functionname> (FILE * logFile)
{
<ompts:orphan:vars>
int sum;
int is_larger = 1;
</ompts:orphan:vars>
int known_sum;

last_i = 0;
sum = 0;

#pragma omp parallel
{
<ompts:orphan>
int i;
int my_islarger = 1;
#pragma omp for schedule(static,1) ordered
for (i = 1; i < 100; i++)
{
<ompts:check>#pragma omp ordered</ompts:check>
{
my_islarger = check_i_islarger(i) && my_islarger;
sum = sum + i;
} /* end of ordered */
} /* end of for */
#pragma omp critical
{
is_larger = is_larger && my_islarger;
} /* end of critical */
</ompts:orphan>
}

known_sum=(99 * 100) / 2;
return ((known_sum == sum) && is_larger);
}
</ompts:testcode>
</ompts:test>
64 changes: 64 additions & 0 deletions openmp/testsuite/c/omp_for_private.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<ompts:test>
<ompts:testdescription>Test which checks the omp for private clause by counting up a variable in a parallelized loop. Each thread has a private variable (1) and a variable (2) declared by for private. First it stores the result of its last iteration in variable (2). Then this thread waits some time before it stores the value of the variable (2) in its private variable (1). At the beginning of the next iteration the value of (1) is assigned to (2). At the end all private variables (1) are added to a total sum in a critical section and compared with the correct result.</ompts:testdescription>
<ompts:ompversion>2.0</ompts:ompversion>
<ompts:directive>omp for private</ompts:directive>
<ompts:dependences>omp parallel,omp flush,omp critical,omp threadprivate</ompts:dependences>
<ompts:testcode>
#include <stdio.h>
#include <math.h>
#include "omp_testsuite.h"

/* Utility function do spend some time in a loop */
static void do_some_work (){
int i;
double sum = 0;
for(i = 0; i < 1000; i++){
sum += sqrt ((double) i);
}
}

int sum1;
#pragma omp threadprivate(sum1)

int <ompts:testcode:functionname>omp_for_private</ompts:testcode:functionname> (FILE * logFile)
{
int sum = 0;
<ompts:orphan:vars>
int sum0;
</ompts:orphan:vars>

int known_sum;

sum0 = 0; /* setting (global) sum0 = 0 */

#pragma omp parallel
{
sum1 = 0; /* setting sum1 in each thread to 0 */

{ /* begin of orphaned block */
<ompts:orphan>
int i;
#pragma omp for <ompts:check>private(sum0)</ompts:check> schedule(static,1)
for (i = 1; i <= LOOPCOUNT; i++)
{
sum0 = sum1;
#pragma omp flush
sum0 = sum0 + i;
do_some_work ();
#pragma omp flush
sum1 = sum0;
} /* end of for */
</ompts:orphan>
} /* end of orphaned block */

#pragma omp critical
{
sum = sum + sum1;
} /*end of critical*/
} /* end of parallel*/

known_sum = (LOOPCOUNT * (LOOPCOUNT + 1)) / 2;
return (known_sum == sum);
}
</ompts:testcode>
</ompts:test>
429 changes: 429 additions & 0 deletions openmp/testsuite/c/omp_for_reduction.c

Large diffs are not rendered by default.

55 changes: 55 additions & 0 deletions openmp/testsuite/c/omp_for_schedule_auto.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<ompts:test>
<ompts:testdescription>Test with omp for schedule auto</ompts:testdescription>
<ompts:ompversion>3.0</ompts:ompversion>
<ompts:directive>omp for auto</ompts:directive>
<ompts:dependences>omp critical,omp parallel firstprivate</ompts:dependences>
<ompts:testcode>
#include <stdio.h>
#include <math.h>

#include "omp_testsuite.h"

int sum1;
#pragma omp threadprivate(sum1)

int <ompts:testcode:functionname>omp_for_auto</ompts:testcode:functionname> (FILE * logFile)
{
int sum;
<ompts:orphan:vars>
int sum0;
</ompts:orphan:vars>

int known_sum;
int threadsnum;

sum = 0;
sum0 = 12345;
sum1 = 0;

#pragma omp parallel
{
#pragma omp single
{
threadsnum=omp_get_num_threads();
}
/* sum0 = 0; */
<ompts:orphan>
int i;
#pragma omp for <ompts:check>firstprivate(sum0) schedule(auto)</ompts:check><ompts:crosscheck>private(sum0)</ompts:crosscheck>
for (i = 1; i <= LOOPCOUNT; i++)
{
sum0 = sum0 + i;
sum1 = sum0;
} /* end of for */
</ompts:orphan>
#pragma omp critical
{
sum = sum + sum1;
} /* end of critical */
} /* end of parallel */

known_sum = 12345* threadsnum+ (LOOPCOUNT * (LOOPCOUNT + 1)) / 2;
return (known_sum == sum);
}
</ompts:testcode>
</ompts:test>
111 changes: 111 additions & 0 deletions openmp/testsuite/c/omp_for_schedule_dynamic.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
<ompts:test>
<ompts:testdescription>Test which checks the dynamic option of the omp for schedule directive</ompts:testdescription>
<ompts:ompversion>2.0</ompts:ompversion>
<ompts:directive>omp for schedule(dynamic)</ompts:directive>
<ompts:dependences>omp flush,omp for nowait,omp critical,omp single</ompts:dependences>
<ompts:testcode>

/*
* Test for dynamic scheduling with chunk size
* Method: caculate how many times the iteration space is dispatched
* and judge if each dispatch has the requested chunk size
* unless it is the last one.
* It is possible for two adjacent chunks are assigned to the same thread
* Modifyied by Chunhua Liao
*/
#include <stdio.h>
#include <omp.h>
#include <unistd.h>
#include <stdlib.h>

#include "omp_testsuite.h"
#include "omp_my_sleep.h"

#define CFDMAX_SIZE 100
const int chunk_size = 7;

int <ompts:testcode:functionname>omp_for_schedule_dynamic</ompts:testcode:functionname> (FILE * logFile)
{
int tid;
<ompts:orphan:vars>
int *tids;
int i;
</ompts:orphan:vars>

int tidsArray[CFDMAX_SIZE];
int count = 0;
int tmp_count = 0; /*dispatch times*/
int *tmp; /*store chunk size for each dispatch*/
int result = 0;

tids = tidsArray;

#pragma omp parallel private(tid) shared(tids)
{ /* begin of parallel */
<ompts:orphan>
int tid;

tid = omp_get_thread_num ();
#pragma omp for <ompts:check>schedule(dynamic,chunk_size)</ompts:check>
for (i = 0; i < CFDMAX_SIZE; i++)
{
tids[i] = tid;
}
</ompts:orphan>
} /* end of parallel */

for (i = 0; i < CFDMAX_SIZE - 1; ++i)
{
if (tids[i] != tids[i + 1])
{
count++;
}
}

tmp = (int *) malloc (sizeof (int) * (count + 1));
tmp[0] = 1;

for (i = 0; i < CFDMAX_SIZE - 1; ++i)
{
if (tmp_count > count)
{
printf ("--------------------\nTestinternal Error: List too small!!!\n--------------------\n"); /* Error handling */
break;
}
if (tids[i] != tids[i + 1])
{
tmp_count++;
tmp[tmp_count] = 1;
}
else
{
tmp[tmp_count]++;
}
}
/*
printf("debug----\n");
for (i = 0; i < CFDMAX_SIZE; ++i)
printf("%d ",tids[i]);
printf("debug----\n");
*/
/* is dynamic statement working? */
for (i = 0; i < count; i++)
{
if ((tmp[i]%chunk_size)!=0)
/*it is possible for 2 adjacent chunks assigned to a same thread*/
{
result++;
fprintf(logFile,"The intermediate dispatch has wrong chunksize.\n");
/*result += ((tmp[i] / chunk_size) - 1);*/
}
}
if ((tmp[count]%chunk_size)!=(CFDMAX_SIZE%chunk_size))
{
result++;
fprintf(logFile,"the last dispatch has wrong chunksize.\n");
}
/* for (int i=0;i<count+1;++i) printf("%d\t:=\t%d\n",i+1,tmp[i]); */
return (result==0);
}
</ompts:testcode>
</ompts:test>
225 changes: 225 additions & 0 deletions openmp/testsuite/c/omp_for_schedule_guided.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
<ompts:test>
<ompts:testdescription>Test which checks the guided option of the omp for schedule directive.</ompts:testdescription>
<ompts:ompversion>2.0</ompts:ompversion>
<ompts:directive>omp for schedule(guided)</ompts:directive>
<ompts:dependences>omp flush,omp for nowait,omp critical,omp single</ompts:dependences>
<ompts:testcode>
/* Test for guided scheduling
* Ensure threads get chunks interleavely first
* Then judge the chunk sizes are decreasing to a stable value
* Modified by Chunhua Liao
* For example, 100 iteration on 2 threads, chunksize 7
* one line for each dispatch, 0/1 means thread id
* 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 24
* 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 18
* 0 0 0 0 0 0 0 0 0 0 0 0 0 0 14
* 1 1 1 1 1 1 1 1 1 1 10
* 0 0 0 0 0 0 0 0 8
* 1 1 1 1 1 1 1 7
* 0 0 0 0 0 0 0 7
* 1 1 1 1 1 1 1 7
* 0 0 0 0 0 5
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

#include "omp_testsuite.h"
#include "omp_my_sleep.h"

#define NUMBER_OF_THREADS 10
#define CFSMAX_SIZE 1000
#define MAX_TIME 0.005

#ifdef SLEEPTIME
#undef SLEEPTIME
#define SLEEPTIME 0.0001
#endif

int <ompts:testcode:functionname>omp_for_schedule_guided</ompts:testcode:functionname> (FILE * logFile)
{
<ompts:orphan:vars>
int * tids;
int * chunksizes;
int notout;
int maxiter;
</ompts:orphan:vars>

int threads;
int i;
int result;

tids = (int *) malloc (sizeof (int) * (CFSMAX_SIZE + 1));
maxiter = 0;
result = 1;
notout = 1;

/* Testing if enought threads are available for this check. */
#pragma omp parallel
{
#pragma omp single
{
threads = omp_get_num_threads ();
} /* end of single */
} /* end of parallel */

if (threads < 2) {
printf ("This test only works with at least two threads .\n");
fprintf (logFile, "This test only works with at least two threads. Available were only %d thread(s).\n", threads);
return (0);
} /* end if */


/* Now the real parallel work:
*
* Each thread will start immediately with the first chunk.
*/
#pragma omp parallel shared(tids,maxiter)
{ /* begin of parallel */
<ompts:orphan>
double count;
int tid;
int j;

tid = omp_get_thread_num ();

#pragma omp for nowait <ompts:check>schedule(guided)</ompts:check>
for(j = 0; j < CFSMAX_SIZE; ++j)
{
count = 0.;
#pragma omp flush(maxiter)
if (j > maxiter)
{
#pragma omp critical
{
maxiter = j;
} /* end of critical */
}
/*printf ("thread %d sleeping\n", tid);*/
#pragma omp flush(maxiter,notout)
while (notout && (count < MAX_TIME) && (maxiter == j))
{
#pragma omp flush(maxiter,notout)
my_sleep (SLEEPTIME);
count += SLEEPTIME;
#ifdef VERBOSE
printf(".");
#endif
}
#ifdef VERBOSE
if (count > 0.) printf(" waited %lf s\n", count);
#endif
/*printf ("thread %d awake\n", tid);*/
tids[j] = tid;
#ifdef VERBOSE
printf("%d finished by %d\n",j,tid);
#endif
} /* end of for */

notout = 0;
#pragma omp flush(maxiter,notout)
</ompts:orphan>
} /* end of parallel */

/*******************************************************
* evaluation of the values *
*******************************************************/
{
int determined_chunksize = 1;
int last_threadnr = tids[0];
int global_chunknr = 0;
int local_chunknr[NUMBER_OF_THREADS];
int openwork = CFSMAX_SIZE;
int expected_chunk_size;
double c = 1;

for (i = 0; i < NUMBER_OF_THREADS; i++)
local_chunknr[i] = 0;

tids[CFSMAX_SIZE] = -1;

/*
* determine the number of global chunks
*/
/*fprintf(logFile,"# global_chunknr thread local_chunknr chunksize\n"); */
for(i = 1; i <= CFSMAX_SIZE; ++i)
{
if (last_threadnr==tids[i]) {
determined_chunksize++;
}
else
{
/* fprintf (logFile, "%d\t%d\t%d\t%d\n", global_chunknr,last_threadnr, local_chunknr[last_threadnr], m); */
global_chunknr++;
local_chunknr[last_threadnr]++;
last_threadnr = tids[i];
determined_chunksize = 1;
}
}
/* now allocate the memory for saving the sizes of the global chunks */
chunksizes = (int*)malloc(global_chunknr * sizeof(int));

/*
* Evaluate the sizes of the global chunks
*/
global_chunknr = 0;
determined_chunksize = 1;
last_threadnr = tids[0];
for (i = 1; i <= CFSMAX_SIZE; ++i)
{
/* If the threadnumber was the same as before increase the detected chunksize for this chunk
* otherwise set the detected chunksize again to one and save the number of the next thread in last_threadnr.
*/
if (last_threadnr == tids[i]) {
determined_chunksize++;
}
else {
chunksizes[global_chunknr] = determined_chunksize;
global_chunknr++;
local_chunknr[last_threadnr]++;
last_threadnr = tids[i];
determined_chunksize = 1;
}
}

#ifdef VERBOSE
fprintf (logFile, "found\texpected\tconstant\n");
#endif

/* identify the constant c for the exponential decrease of the chunksize */
expected_chunk_size = openwork / threads;
c = (double) chunksizes[0] / expected_chunk_size;

for (i = 0; i < global_chunknr; i++)
{
/* calculate the new expected chunksize */
if (expected_chunk_size > 1)
expected_chunk_size = c * openwork / threads;

#ifdef VERBOSE
fprintf (logFile, "%8d\t%8d\t%lf\n", chunksizes[i], expected_chunk_size, c * chunksizes[i]/expected_chunk_size);
#endif

/* check if chunksize is inside the rounding errors */
if (abs (chunksizes[i] - expected_chunk_size) >= 2) {
result = 0;
#ifndef VERBOSE
fprintf (logFile, "Chunksize differed from expected value: %d instead of %d\n", chunksizes[i], expected_chunk_size);
return 0;
#endif
} /* end if */

#ifndef VERBOSE
if (expected_chunk_size - chunksizes[i] < 0 )
fprintf (logFile, "Chunksize did not decrease: %d instead of %d\n", chunksizes[i],expected_chunk_size);
#endif

/* calculating the remaining ammount of work */
openwork -= chunksizes[i];
}
}
return result;
}
</ompts:testcode>
</ompts:test>

165 changes: 165 additions & 0 deletions openmp/testsuite/c/omp_for_schedule_static.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
<ompts:test>
<ompts:testdescription>Test which checks the static option of the omp for schedule directive.</ompts:testdescription>
<ompts:ompversion>2.0</ompts:ompversion>
<ompts:directive>omp for schedule(static)</ompts:directive>
<ompts:dependences>omp for nowait,omp flush,omp critical,omp single</ompts:dependences>
<ompts:testcode>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

#include "omp_testsuite.h"
#include "omp_my_sleep.h"

#define NUMBER_OF_THREADS 10
#define CFSMAX_SIZE 1000
#define MAX_TIME 0.01

#ifdef SLEEPTIME
#undef SLEEPTIME
#define SLEEPTIME 0.0005
#endif


int <ompts:testcode:functionname>omp_for_schedule_static</ompts:testcode:functionname> (FILE * logFile)
{
int threads;
int i,lasttid;
<ompts:orphan:vars>
int * tids;
int notout;
int maxiter;
int chunk_size;
</ompts:orphan:vars>
int counter = 0;
int tmp_count=1;
int lastthreadsstarttid = -1;
int result = 1;
chunk_size = 7;

tids = (int *) malloc (sizeof (int) * (CFSMAX_SIZE + 1));
notout = 1;
maxiter = 0;

#pragma omp parallel shared(tids,counter)
{ /* begin of parallel*/
#pragma omp single
{
threads = omp_get_num_threads ();
} /* end of single */
} /* end of parallel */

if (threads < 2)
{
printf ("This test only works with at least two threads");
fprintf (logFile,"This test only works with at least two threads");
return 0;
}
else
{
fprintf (logFile,"Using an internal count of %d\nUsing a specified chunksize of %d\n", CFSMAX_SIZE, chunk_size);
tids[CFSMAX_SIZE] = -1; /* setting endflag */
#pragma omp parallel shared(tids)
{ /* begin of parallel */
<ompts:orphan>
double count;
int tid;
int j;

tid = omp_get_thread_num ();

#pragma omp for nowait <ompts:check>schedule(static,chunk_size)</ompts:check>
for(j = 0; j < CFSMAX_SIZE; ++j)
{
count = 0.;
#pragma omp flush(maxiter)
if (j > maxiter)
{
#pragma omp critical
{
maxiter = j;
} /* end of critical */
}
/*printf ("thread %d sleeping\n", tid);*/
while (notout && (count < MAX_TIME) && (maxiter == j))
{
#pragma omp flush(maxiter,notout)
my_sleep (SLEEPTIME);
count += SLEEPTIME;
printf(".");
}
#ifdef VERBOSE
if (count > 0.) printf(" waited %lf s\n", count);
#endif
/*printf ("thread %d awake\n", tid);*/
tids[j] = tid;
#ifdef VERBOSE
printf("%d finished by %d\n",j,tid);
#endif
} /* end of for */

notout = 0;
#pragma omp flush(maxiter,notout)
</ompts:orphan>
} /* end of parallel */

/**** analysing the data in array tids ****/

lasttid = tids[0];
tmp_count = 0;

for (i = 0; i < CFSMAX_SIZE + 1; ++i)
{
/* If the work was done by the same thread increase tmp_count by one. */
if (tids[i] == lasttid) {
tmp_count++;
#ifdef VERBOSE
fprintf (logFile, "%d: %d \n", i, tids[i]);
#endif
continue;
}

/* Check if the next thread had has the right thread number. When finding
* threadnumber -1 the end should be reached.
*/
if (tids[i] == (lasttid + 1) % threads || tids[i] == -1) {
/* checking for the right chunk size */
if (tmp_count == chunk_size) {
tmp_count = 1;
lasttid = tids[i];
#ifdef VERBOSE
fprintf (logFile, "OK\n");
#endif
}
/* If the chunk size was wrong, check if the end was reached */
else {
if (tids[i] == -1) {
if (i == CFSMAX_SIZE) {
fprintf (logFile, "Last thread had chunk size %d\n", tmp_count);
break;
}
else {
fprintf (logFile, "ERROR: Last thread (thread with number -1) was found before the end.\n");
result = 0;
}
}
else {
fprintf (logFile, "ERROR: chunk size was %d. (assigned was %d)\n", tmp_count, chunk_size);
result = 0;
}
}
}
else {
fprintf(logFile, "ERROR: Found thread with number %d (should be inbetween 0 and %d).", tids[i], threads - 1);
result = 0;
}
#ifdef VERBOSE
fprintf (logFile, "%d: %d \n", i, tids[i]);
#endif
}
}

return result;
}
</ompts:testcode>
</ompts:test>
212 changes: 212 additions & 0 deletions openmp/testsuite/c/omp_for_schedule_static_3.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
<ompts:test>
<ompts:testdescription>Test which checks the static option of the omp for schedule directive considering the specifications for the chunk distribution of several loop regions is the same as specified in the Open MP standard version 3.0.</ompts:testdescription>
<ompts:ompversion>3.0</ompts:ompversion>
<ompts:directive>omp for schedule(static)</ompts:directive>
<ompts:dependences>omp for nowait,omp flush,omp critical,omp single</ompts:dependences>
<ompts:testcode>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

#include "omp_testsuite.h"
#include "omp_my_sleep.h"

#define NUMBER_OF_THREADS 10
#define CFSMAX_SIZE 1000
#define MAX_TIME 0.01

#ifdef SLEEPTIME
#undef SLEEPTIME
#define SLEEPTIME 0.0005
#endif

#define VERBOSE 0


int <ompts:testcode:functionname>omp_for_schedule_static_3</ompts:testcode:functionname> (FILE * logFile)
{
int threads;
int i,lasttid;
<ompts:orphan:vars>
int * tids;
int * tids2;
int notout;
int maxiter;
int chunk_size;
</ompts:orphan:vars>
int counter = 0;
int tmp_count=1;
int lastthreadsstarttid = -1;
int result = 1;
chunk_size = 7;

tids = (int *) malloc (sizeof (int) * (CFSMAX_SIZE + 1));
notout = 1;
maxiter = 0;

#pragma omp parallel shared(tids,counter)
{ /* begin of parallel*/
#pragma omp single
{
threads = omp_get_num_threads ();
} /* end of single */
} /* end of parallel */

if (threads < 2)
{
printf ("This test only works with at least two threads");
fprintf (logFile,"This test only works with at least two threads");
return 0;
}
else
{
fprintf (logFile,"Using an internal count of %d\nUsing a specified chunksize of %d\n", CFSMAX_SIZE, chunk_size);
tids[CFSMAX_SIZE] = -1; /* setting endflag */
#pragma omp parallel shared(tids)
{ /* begin of parallel */
<ompts:orphan>
double count;
int tid;
int j;

tid = omp_get_thread_num ();

#pragma omp for nowait <ompts:check>schedule(static,chunk_size)</ompts:check>
for(j = 0; j < CFSMAX_SIZE; ++j)
{
count = 0.;
#pragma omp flush(maxiter)
if (j > maxiter)
{
#pragma omp critical
{
maxiter = j;
} /* end of critical */
}
/*printf ("thread %d sleeping\n", tid);*/
while (notout && (count < MAX_TIME) && (maxiter == j))
{
#pragma omp flush(maxiter,notout)
my_sleep (SLEEPTIME);
count += SLEEPTIME;
printf(".");
}
#ifdef VERBOSE
if (count > 0.) printf(" waited %lf s\n", count);
#endif
/*printf ("thread %d awake\n", tid);*/
tids[j] = tid;
#ifdef VERBOSE
printf("%d finished by %d\n",j,tid);
#endif
} /* end of for */

notout = 0;
#pragma omp flush(maxiter,notout)
</ompts:orphan>
} /* end of parallel */

/**** analysing the data in array tids ****/

lasttid = tids[0];
tmp_count = 0;

for (i = 0; i < CFSMAX_SIZE + 1; ++i)
{
/* If the work was done by the same thread increase tmp_count by one. */
if (tids[i] == lasttid) {
tmp_count++;
#ifdef VERBOSE
fprintf (logFile, "%d: %d \n", i, tids[i]);
#endif
continue;
}

/* Check if the next thread had has the right thread number. When finding
* threadnumber -1 the end should be reached.
*/
if (tids[i] == (lasttid + 1) % threads || tids[i] == -1) {
/* checking for the right chunk size */
if (tmp_count == chunk_size) {
tmp_count = 1;
lasttid = tids[i];
#ifdef VERBOSE
fprintf (logFile, "OK\n");
#endif
}
/* If the chunk size was wrong, check if the end was reached */
else {
if (tids[i] == -1) {
if (i == CFSMAX_SIZE) {
fprintf (logFile, "Last thread had chunk size %d\n", tmp_count);
break;
}
else {
fprintf (logFile, "ERROR: Last thread (thread with number -1) was found before the end.\n");
result = 0;
}
}
else {
fprintf (logFile, "ERROR: chunk size was %d. (assigned was %d)\n", tmp_count, chunk_size);
result = 0;
}
}
}
else {
fprintf(logFile, "ERROR: Found thread with number %d (should be inbetween 0 and %d).", tids[i], threads - 1);
result = 0;
}
#ifdef VERBOSE
fprintf (logFile, "%d: %d \n", i, tids[i]);
#endif
}
}

/* Now we check if several loop regions in one parallel region have the same
* logical assignement of chunks to threads.
* We use the nowait clause to increase the probability to get an error. */

/* First we allocate some more memmory */
free (tids);
tids = (int *) malloc (sizeof (int) * LOOPCOUNT);
tids2 = (int *) malloc (sizeof (int) * LOOPCOUNT);

#pragma omp parallel
{
<ompts:orphan>
{
int n;
#pragma omp for <ompts:check>schedule(static)</ompts:check> nowait
for (n = 0; n < LOOPCOUNT; n++)
{
if (LOOPCOUNT == n + 1 )
my_sleep(SLEEPTIME);

tids[n] = omp_get_thread_num();
}
}
</ompts:orphan>
<ompts:orphan>
{
int m;
#pragma omp for <ompts:check>schedule(static)</ompts:check> nowait
for (m = 1; m <= LOOPCOUNT; m++)
{
tids2[m-1] = omp_get_thread_num();
}
}
</ompts:orphan>
}

for (i = 0; i < LOOPCOUNT; i++)
if (tids[i] != tids2[i]) {
fprintf (logFile, "Chunk no. %d was assigned once to thread %d and later to thread %d.\n", i, tids[i],tids2[i]);
result = 0;
}

free (tids);
free (tids2);
return result;
}
</ompts:testcode>
</ompts:test>
39 changes: 39 additions & 0 deletions openmp/testsuite/c/omp_get_num_threads.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<ompts:test>
<ompts:testdescription>Test which checks that the omp_get_num_threads returns the correct number of threads. Therefor it counts up a variable in a parallelized section and compars this value with the result of the omp_get_num_threads function.</ompts:testdescription>
<ompts:ompversion>2.0</ompts:ompversion>
<ompts:directive>omp_get_num_threads</ompts:directive>
<ompts:testcode>
#include <stdio.h>

#include "omp_testsuite.h"

int <ompts:testcode:functionname>omp_get_num_threads</ompts:testcode:functionname> (FILE * logFile)
{
/* checks that omp_get_num_threads is equal to the number of
threads */
<ompts:orphan:vars>
int nthreads_lib;
</ompts:orphan:vars>
int nthreads = 0;

nthreads_lib = -1;

#pragma omp parallel
{
#pragma omp critical
{
nthreads++;
} /* end of critical */
#pragma omp single
{
<ompts:orphan>
<ompts:check>nthreads_lib = omp_get_num_threads ();</ompts:check>
</ompts:orphan>
} /* end of single */
} /* end of parallel */

fprintf (logFile, "Counted %d threads. get_num_threads returned %d.\n", nthreads, nthreads_lib);
return (nthreads == nthreads_lib);
}
</ompts:testcode>
</ompts:test>
24 changes: 24 additions & 0 deletions openmp/testsuite/c/omp_get_wtick.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<ompts:test>
<ompts:testdescription>Test which checks the omp_get_wtick function.</ompts:testdescription>
<ompts:ompversion>2.0</ompts:ompversion>
<ompts:directive>omp_get_wtick</ompts:directive>
<ompts:testcode>
#include<stdio.h>

#include "omp_testsuite.h"

int <ompts:testcode:functionname>omp_get_wtick</ompts:testcode:functionname>(FILE * logFile)
{
<ompts:orphan:vars>
double tick;
</ompts:orphan:vars>
tick = -1.;

<ompts:orphan>
<ompts:check>tick = omp_get_wtick ();</ompts:check>
</ompts:orphan>
fprintf (logFile, "Work took %lf sec. time.\n", tick);
return ((tick > 0.0) && (tick < 0.01));
}
</ompts:testcode>
</ompts:test>
38 changes: 38 additions & 0 deletions openmp/testsuite/c/omp_get_wtime.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<ompts:test>
<ompts:testdescription>Test which checks the omp_get_wtime function. It compares the time with which is called a sleep function with the time it took by messuring the difference between the call of the sleep function and its end.</ompts:testdescription>
<ompts:ompversion>2.0</ompts:ompversion>
<ompts:directive>omp_get_wtime</ompts:directive>
<ompts:testcode>
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>


#include "omp_testsuite.h"
#include "omp_my_sleep.h"

int <ompts:testcode:functionname>omp_get_wtime</ompts:testcode:functionname>(FILE * logFile)
{
<ompts:orphan:vars>
double start;
double end;
</ompts:orphan:vars>
double measured_time;
int wait_time = 1;

start = 0;
end = 0;

<ompts:orphan>
<ompts:check>start = omp_get_wtime ();</ompts:check>
</ompts:orphan>
my_sleep (wait_time);
<ompts:orphan>
<ompts:check>end = omp_get_wtime ();</ompts:check>
</ompts:orphan>
measured_time = end-start;
fprintf(logFile, "Work took %lf sec. time.\n", measured_time);
return ((measured_time > 0.99 * wait_time) && (measured_time < 1.01 * wait_time)) ;
}
</ompts:testcode>
</ompts:test>
51 changes: 51 additions & 0 deletions openmp/testsuite/c/omp_in_parallel.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<ompts:test>
<ompts:testdescription>Test which checks that omp_in_parallel returns false when called from a serial region and true when called within a parallel region.</ompts:testdescription>
<ompts:ompversion>2.0</ompts:ompversion>
<ompts:directive>omp_in_parallel</ompts:directive>
<ompts:testcode>
/*
* Checks that false is returned when called from serial region
* and true is returned when called within parallel region.
*/
#include <stdio.h>
#include "omp_testsuite.h"

int <ompts:testcode:functionname>omp_in_parallel</ompts:testcode:functionname>(FILE * logFile){
<ompts:orphan:vars>
int serial;
int isparallel;
</ompts:orphan:vars>

serial = 1;
isparallel = 0;

<ompts:check>
<ompts:orphan>
serial = omp_in_parallel ();
</ompts:orphan>

#pragma omp parallel
{
#pragma omp single
{
<ompts:orphan>
isparallel = omp_in_parallel ();
</ompts:orphan>
}
}
</ompts:check>

<ompts:crosscheck>
#pragma omp parallel
{
#pragma omp single
{

}
}
</ompts:crosscheck>

return (!(serial) && isparallel);
}
</ompts:testcode>
</ompts:test>
45 changes: 45 additions & 0 deletions openmp/testsuite/c/omp_lock.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<ompts:test>
<ompts:testdescription>Test which checks the omp_set_lock and the omp_unset_lock function by counting the threads entering and exiting a single region with locks.</ompts:testdescription>
<ompts:ompversion>2.0</ompts:ompversion>
<ompts:directive>omp_lock</ompts:directive>
<ompts:dependences>omp flush</ompts:dependences>
<ompts:testcode>
#include <stdio.h>
#include "omp_testsuite.h"

omp_lock_t lck;

int <ompts:testcode:functionname>omp_lock</ompts:testcode:functionname>(FILE * logFile)
{
int nr_threads_in_single = 0;
int result = 0;
int nr_iterations = 0;
int i;
omp_init_lock (&lck);

#pragma omp parallel shared(lck)
{
#pragma omp for
for(i = 0; i < LOOPCOUNT; i++)
{
<ompts:orphan>
<ompts:check>omp_set_lock (&lck);</ompts:check>
</ompts:orphan>
#pragma omp flush
nr_threads_in_single++;
#pragma omp flush
nr_iterations++;
nr_threads_in_single--;
result = result + nr_threads_in_single;
<ompts:orphan>
<ompts:check>omp_unset_lock(&lck);</ompts:check>
</ompts:orphan>
}
}
omp_destroy_lock (&lck);

return ((result == 0) && (nr_iterations == LOOPCOUNT));

}
</ompts:testcode>
</ompts:test>
37 changes: 37 additions & 0 deletions openmp/testsuite/c/omp_master.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<ompts:test>
<ompts:testdescription>Test which checks the omp master directive by counting up a variable in a omp master section.</ompts:testdescription>
<ompts:ompversion>2.0</ompts:ompversion>
<ompts:directive>omp master</ompts:directive>
<ompts:dependences>omp critical</ompts:dependences>
<ompts:testcode>
#include <stdio.h>
#include "omp_testsuite.h"

int <ompts:testcode:functionname>omp_master</ompts:testcode:functionname>(FILE * logFile)
{
<ompts:orphan:vars>
int nthreads;
int executing_thread;
</ompts:orphan:vars>

nthreads = 0;
executing_thread = -1;

#pragma omp parallel
{
<ompts:orphan>
<ompts:check>#pragma omp master </ompts:check>
{
#pragma omp critical
{
nthreads++;
}
executing_thread = omp_get_thread_num ();

} /* end of master*/
</ompts:orphan>
} /* end of parallel*/
return ((nthreads == 1) && (executing_thread == 0));
}
</ompts:testcode>
</ompts:test>
44 changes: 44 additions & 0 deletions openmp/testsuite/c/omp_master_3.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<ompts:test>
<ompts:testdescription>Test which checks the omp master directive by counting up a variable in a omp master section. It also checks that the master thread has the thread number 0 as specified in the Open MP standard version 3.0.</ompts:testdescription>
<ompts:ompversion>3.0</ompts:ompversion>
<ompts:directive>omp master</ompts:directive>
<ompts:dependences>omp critical</ompts:dependences>
<ompts:testcode>
#include <stdio.h>
#include "omp_testsuite.h"

int <ompts:testcode:functionname>omp_master_3</ompts:testcode:functionname>(FILE * logFile)
{
<ompts:orphan:vars>
int nthreads;
int executing_thread;
int tid_result = 0; /* counts up the number of wrong thread no. for
the master thread. (Must be 0) */
</ompts:orphan:vars>

nthreads = 0;
executing_thread = -1;

#pragma omp parallel
{
<ompts:orphan>
<ompts:check>#pragma omp master </ompts:check>
{
int tid = omp_get_thread_num();
if (tid != 0) {
#pragma omp critical
{ tid_result++; }
}
#pragma omp critical
{
nthreads++;
}
executing_thread = omp_get_thread_num ();

} /* end of master*/
</ompts:orphan>
} /* end of parallel*/
return ((nthreads == 1) && (executing_thread == 0) && (tid_result == 0));
}
</ompts:testcode>
</ompts:test>
45 changes: 45 additions & 0 deletions openmp/testsuite/c/omp_nest_lock.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<ompts:test>
<ompts:testdescription>Test which checks the omp_set_nest_lock and the omp_unset_nest_lock function.</ompts:testdescription>
<ompts:ompversion>2.0</ompts:ompversion>
<ompts:directive>omp_nest_lock</ompts:directive>
<ompts:dependences>omp flush</ompts:dependences>
<ompts:testcode>
#include <stdio.h>
#include "omp_testsuite.h"

omp_nest_lock_t lck;

int <ompts:testcode:functionname>omp_nest_lock</ompts:testcode:functionname>(FILE * logFile)
{
int nr_threads_in_single = 0;
int result = 0;
int nr_iterations = 0;
int i;

omp_init_nest_lock (&lck);

#pragma omp parallel shared(lck)
{
#pragma omp for
for(i = 0; i < LOOPCOUNT; i++)
{
<ompts:orphan>
<ompts:check>omp_set_nest_lock (&lck);</ompts:check>
</ompts:orphan>
#pragma omp flush
nr_threads_in_single++;
#pragma omp flush
nr_iterations++;
nr_threads_in_single--;
result = result + nr_threads_in_single;
<ompts:orphan>
<ompts:check>omp_unset_nest_lock (&lck);</ompts:check>
</ompts:orphan>
}
}
omp_destroy_nest_lock (&lck);

return ((result == 0) && (nr_iterations == LOOPCOUNT));
}
</ompts:testcode>
</ompts:test>
42 changes: 42 additions & 0 deletions openmp/testsuite/c/omp_nested.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<ompts:test>
<ompts:testdescription>Test which checks the omp_nested function.</ompts:testdescription>
<ompts:ompversion>2.0</ompts:ompversion>
<ompts:directive>omp_nested</ompts:directive>
<ompts:dependences>omp critical</ompts:dependences>
<ompts:testcode>
/*
* Test if the compiler supports nested parallelism
* By Chunhua Liao, University of Houston
* Oct. 2005
*/
#include <stdio.h>
#include "omp_testsuite.h"

int <ompts:testcode:functionname>omp_nested</ompts:testcode:functionname>(FILE * logFile)
{

<ompts:orphan:vars>
int counter = 0;
</ompts:orphan:vars>

#ifdef _OPENMP
<ompts:check>omp_set_nested(1);</ompts:check>
<ompts:crosscheck>omp_set_nested(0);</ompts:crosscheck>
#endif

#pragma omp parallel shared(counter)
{
<ompts:orphan>
#pragma omp critical
counter ++;
#pragma omp parallel
{
#pragma omp critical
counter --;
}
</ompts:orphan>
}
return (counter != 0);
}
</ompts:testcode>
</ompts:test>
47 changes: 47 additions & 0 deletions openmp/testsuite/c/omp_parallel_copyin.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<ompts:test>
<ompts:testdescription>Test which checks the omp parallel copyin directive.</ompts:testdescription>
<ompts:ompversion>3.0</ompts:ompversion>
<ompts:directive>omp parallel copyin</ompts:directive>
<ompts:dependences>omp critical,omp threadprivate</ompts:dependences>
<ompts:testcode>
#include <stdio.h>
#include <stdlib.h>
#include "omp_testsuite.h"

static int sum1 = 789;
#pragma omp threadprivate(sum1)

int <ompts:testcode:functionname>omp_parallel_copyin</ompts:testcode:functionname>(FILE * logFile)
{
<ompts:orphan:vars>
int sum, num_threads;
</ompts:orphan:vars>
int known_sum;

sum = 0;
sum1 = 7;
num_threads = 0;

#pragma omp parallel <ompts:check>copyin(sum1)</ompts:check>
{
/*printf("sum1=%d\n",sum1);*/
<ompts:orphan>
int i;
#pragma omp for
for (i = 1; i < 1000; i++)
{
sum1 = sum1 + i;
} /*end of for*/
#pragma omp critical
{
sum = sum + sum1;
num_threads++;
} /*end of critical*/
</ompts:orphan>
} /* end of parallel*/
known_sum = (999 * 1000) / 2 + 7 * num_threads;
return (known_sum == sum);

}
</ompts:testcode>
</ompts:test>
44 changes: 44 additions & 0 deletions openmp/testsuite/c/omp_parallel_default.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<ompts:test>
<ompts:testdescription>Test which checks the default option of the parallel construct.</ompts:testdescription>
<ompts:ompversion>3.0</ompts:ompversion>
<ompts:directive>omp parallel default</ompts:directive>
<ompts:testcode>
#include <stdio.h>
#include <unistd.h>

#include "omp_testsuite.h"

int <ompts:testcode:functionname>omp_parallel_default</ompts:testcode:functionname> (FILE * logFile)
{
<ompts:orphan:vars>
int i;
int sum;
int mysum;
</ompts:orphan:vars>

int known_sum;
sum =0;
known_sum = (LOOPCOUNT * (LOOPCOUNT + 1)) / 2 ;

<ompts:orphan>
#pragma omp parallel <ompts:check>default(shared)</ompts:check> private(i) private(mysum<ompts:crosscheck>,sum</ompts:crosscheck>)
{
mysum = 0;
#pragma omp for
for (i = 1; i <= LOOPCOUNT; i++)
{
mysum = mysum + i;
}
#pragma omp critical
{
sum = sum + mysum;
} /* end of critical */
} /* end of parallel */
</ompts:orphan>
if (known_sum != sum) {
fprintf(logFile, "KNOWN_SUM = %d; SUM = %d\n", known_sum, sum);
}
return (known_sum == sum);
}
</ompts:testcode>
</ompts:test>
48 changes: 48 additions & 0 deletions openmp/testsuite/c/omp_parallel_firstprivate.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<ompts:test>
<ompts:testdescription>Test which checks the omp parallel firstprivate directive.</ompts:testdescription>
<ompts:ompversion>3.0</ompts:ompversion>
<ompts:directive>omp parallel firstprivate</ompts:directive>
<ompts:dependences>omp for omp critical</ompts:dependences>
<ompts:testcode>
#include <stdio.h>
#include <stdlib.h>
#include "omp_testsuite.h"

//static int sum1 = 789;

int <ompts:testcode:functionname>omp_parallel_firstprivate</ompts:testcode:functionname>(FILE * logFile)
{
<ompts:orphan:vars>
int sum, num_threads,sum1;
</ompts:orphan:vars>
int known_sum;

sum = 0;
sum1=7;
num_threads = 0;


#pragma omp parallel <ompts:check>firstprivate(sum1)</ompts:check><ompts:crosscheck>private(sum1)</ompts:crosscheck>
{

/*printf("sum1=%d\n",sum1);*/
<ompts:orphan>
int i;
#pragma omp for
for (i = 1; i < 1000; i++)
{
sum1 = sum1 + i;
} /*end of for*/
#pragma omp critical
{
sum = sum + sum1;
num_threads++;
} /*end of critical*/
</ompts:orphan>
} /* end of parallel*/
known_sum = (999 * 1000) / 2 + 7 * num_threads;
return (known_sum == sum);

}
</ompts:testcode>
</ompts:test>
36 changes: 36 additions & 0 deletions openmp/testsuite/c/omp_parallel_for_firstprivate.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<ompts:test>
<ompts:testdescription>Test which checks the omp parallel for firstprivate directive.</ompts:testdescription>
<ompts:ompversion>2.0</ompts:ompversion>
<ompts:directive>omp parallel for firstprivate</ompts:directive>
<ompts:dependences>omp parallel for reduction,omp parallel for private</ompts:dependences>
<ompts:testcode>
#include <stdio.h>
#include "omp_testsuite.h"

int <ompts:testcode:functionname>omp_parallel_for_firstprivate</ompts:testcode:functionname>(FILE * logFile)
{
<ompts:orphan:vars>
int sum ;
int i2;
int i;
</ompts:orphan:vars>

sum=0;
i2=3;
int known_sum;

#pragma omp parallel for reduction(+:sum) private(i) <ompts:check>firstprivate(i2)</ompts:check><ompts:crosscheck>private(i2)</ompts:crosscheck>
<ompts:orphan>
for (i = 1; i <= LOOPCOUNT; i++)
{
sum = sum + (i + i2);
} /*end of for*/
</ompts:orphan>

known_sum = (LOOPCOUNT * (LOOPCOUNT + 1)) / 2 + i2 * LOOPCOUNT;

return (known_sum == sum);

} /* end of check_parallel_for_fistprivate */
</ompts:testcode>
</ompts:test>
38 changes: 38 additions & 0 deletions openmp/testsuite/c/omp_parallel_for_if.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<ompts:test>
<ompts:testdescription>Test which checks the omp parallel for if directive. Needs at least two threads.</ompts:testdescription>
<ompts:ompversion>2.0</ompts:ompversion>
<ompts:directive>omp parallel for if</ompts:directive>
<ompts:dependences></ompts:dependences>
<ompts:testcode>
#include <stdio.h>
#include <math.h>
#include "omp_testsuite.h"

int <ompts:testcode:functionname>omp_parallel_for_if</ompts:testcode:functionname>(FILE * logFile){
int known_sum;
<ompts:orphan:vars>
int num_threads;
int sum, sum2;
int i;
int control;
</ompts:orphan:vars>
control = 0;
num_threads=0;
sum = 0;
sum2 = 0;

#pragma omp parallel for private(i) <ompts:check>if (control==1)</ompts:check>
<ompts:orphan>
for (i=0; i <= LOOPCOUNT; i++)
{
num_threads = omp_get_num_threads();
sum = sum + i;
} /*end of for*/

</ompts:orphan>
known_sum = (LOOPCOUNT * (LOOPCOUNT + 1)) / 2;
fprintf (logFile, "Number of threads determined by omp_get_num_threads: %d\n", num_threads);
return (known_sum == sum && num_threads == 1);
} /* end of check_paralel_for_private */
</ompts:testcode>
</ompts:test>
34 changes: 34 additions & 0 deletions openmp/testsuite/c/omp_parallel_for_lastprivate.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<ompts:test>
<ompts:testdescription>Test which checks the omp parallel for lastprivate directive.</ompts:testdescription>
<ompts:ompversion>2.0</ompts:ompversion>
<ompts:directive>omp parallel for lastprivate</ompts:directive>
<ompts:dependences>omp parallel for reduction,omp parallel for private</ompts:dependences>
<ompts:testcode>
#include <stdio.h>
#include "omp_testsuite.h"

int <ompts:testcode:functionname>omp_parallel_for_lastprivate</ompts:testcode:functionname>(FILE * logFile){
<ompts:orphan:vars>
int sum;
int i;
int i0;
</ompts:orphan:vars>

sum =0;
i0 = -1;
int known_sum;

#pragma omp parallel for reduction(+:sum) schedule(static,7) private(i) <ompts:check>lastprivate(i0)</ompts:check><ompts:crosscheck>private(i0)</ompts:crosscheck>
<ompts:orphan>
for (i = 1; i <= LOOPCOUNT; i++)
{
sum = sum + i;
i0 = i;
} /*end of for*/
/* end of parallel*/
</ompts:orphan>
known_sum = (LOOPCOUNT * (LOOPCOUNT + 1)) / 2;
return ((known_sum == sum) && (i0 == LOOPCOUNT));
} /* end of check_parallel_for_lastprivate */
</ompts:testcode>
</ompts:test>
62 changes: 62 additions & 0 deletions openmp/testsuite/c/omp_parallel_for_ordered.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<ompts:test>
<ompts:testdescription>Test which checks the omp parallel for ordered directive</ompts:testdescription>
<ompts:ompversion>2.0</ompts:ompversion>
<ompts:directive>omp parallel for ordered</ompts:directive>
<ompts:dependences>omp parallel schedule(static)</ompts:dependences>
<ompts:testcode>
#include <stdio.h>
#include "omp_testsuite.h"

static int last_i = 0;
int i;

#pragma omp threadprivate(i)

/* Variable ii is used to avoid problems with a threadprivate variable used as a loop
* index. See test omp_threadprivate_for.
*/
static int ii;
#pragma omp threadprivate(ii)

/*!
Utility function: returns true if the passed argument is larger than
the argument of the last call of this function.
*/
static int check_i_islarger2 (int i){
int islarger;
islarger = (i > last_i);
last_i = i;
return (islarger);
}

int <ompts:testcode:functionname>omp_parallel_for_ordered</ompts:testcode:functionname>(FILE * logFile){
<ompts:orphan:vars>
int sum;
int is_larger;
</ompts:orphan:vars>

int known_sum;
int i;

sum = 0;
is_larger = 1;
last_i = 0;
#pragma omp parallel for schedule(static,1) private(i) <ompts:check>ordered</ompts:check>
for (i = 1; i < 100; i++)
{
ii = i;
<ompts:orphan>
<ompts:check>#pragma omp ordered</ompts:check><ompts:crosscheck></ompts:crosscheck>
{
is_larger = check_i_islarger2 (ii) && is_larger;
sum = sum + ii;
}
</ompts:orphan>
}
known_sum = (99 * 100) / 2;
fprintf (logFile," known_sum = %d , sum = %d \n", known_sum, sum);
fprintf (logFile," is_larger = %d\n", is_larger);
return (known_sum == sum) && is_larger;
}
</ompts:testcode>
</ompts:test>
48 changes: 48 additions & 0 deletions openmp/testsuite/c/omp_parallel_for_private.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<ompts:test>
<ompts:testdescription>Test which checks the omp parallel for private directive.</ompts:testdescription>
<ompts:ompversion>2.0</ompts:ompversion>
<ompts:directive>omp parallel for private</ompts:directive>
<ompts:dependences>omp parallel for reduction,omp flush</ompts:dependences>
<ompts:testcode>
#include <stdio.h>
#include <math.h>
#include "omp_testsuite.h"

/*! Utility function to spend some time in a loop */
static void do_some_work (void){
int i;
double sum = 0;
for(i = 0; i < 1000; i++){
sum += sqrt (i);
}
}

int <ompts:testcode:functionname>omp_parallel_for_private</ompts:testcode:functionname>(FILE * logFile){
<ompts:orphan:vars>
int sum;
int i;
int i2;
</ompts:orphan:vars>

sum =0;
i2=0;
int known_sum;

#pragma omp parallel for reduction(+:sum) schedule(static,1) private(i) <ompts:check>private(i2)</ompts:check>
<ompts:orphan>

for (i=1;i<=LOOPCOUNT;i++)
{
i2 = i;
#pragma omp flush
do_some_work ();
#pragma omp flush
sum = sum + i2;
} /*end of for*/
</ompts:orphan>

known_sum = (LOOPCOUNT * (LOOPCOUNT + 1)) / 2;
return (known_sum == sum);
} /* end of check_paralel_for_private */
</ompts:testcode>
</ompts:test>
280 changes: 280 additions & 0 deletions openmp/testsuite/c/omp_parallel_for_reduction.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,280 @@
<ompts:test>
<ompts:testdescription>Test which checks the omp parallel for reduction directive with all its options.</ompts:testdescription>
<ompts:ompversion>2.0</ompts:ompversion>
<ompts:directive>omp parallel for reduction</ompts:directive>
<ompts:testcode>
#include <stdio.h>
#include <math.h>
#include "omp_testsuite.h"


int <ompts:testcode:functionname>omp_parallel_for_reduction</ompts:testcode:functionname>(FILE * logFile){
<ompts:orphan:vars>
int sum;
int known_sum;
double dsum;
double dknown_sum;
double dt=0.5; /* base of geometric row for + and - test*/
double rounding_error= 1.E-9;
#define DOUBLE_DIGITS 20 /* dt^DOUBLE_DIGITS */
int diff;
double ddiff;
int product;
int known_product;
#define MAX_FACTOR 10
#define KNOWN_PRODUCT 3628800 /* 10! */
int logic_and;
int logic_or;
int bit_and;
int bit_or;
int exclusiv_bit_or;
int logics[LOOPCOUNT];
int i;
double dpt;
int result;
</ompts:orphan:vars>

sum =0;
dsum=0;
dt = 1./3.;
result = 0;
product = 1;
logic_and=1;
logic_or=0;
bit_and=1;
bit_or=0;
exclusiv_bit_or=0;

known_sum = (LOOPCOUNT*(LOOPCOUNT+1))/2;
<ompts:orphan>
#pragma omp parallel for schedule(dynamic,1) private(i) <ompts:check>reduction(+:sum)</ompts:check><ompts:crosscheck></ompts:crosscheck>
for (i=1;i<=LOOPCOUNT;i++)
{
sum=sum+i;
}

if(known_sum!=sum)
{
result++;
fprintf(logFile,"Error in sum with integers: Result was %d instead of %d\n",sum,known_sum);
}

diff = (LOOPCOUNT*(LOOPCOUNT+1))/2;
#pragma omp parallel for schedule(dynamic,1) private(i) <ompts:check>reduction(-:diff)</ompts:check><ompts:crosscheck></ompts:crosscheck>
for (i=1;i<=LOOPCOUNT;++i)
{
diff=diff-i;
}

if(diff != 0)
{
result++;
fprintf(logFile,"Error in difference with integers: Result was %d instead of 0.\n",diff);
}

/* Tests for doubles */
dsum=0;
dpt=1;
for (i=0;i<DOUBLE_DIGITS;++i)
{
dpt*=dt;
}
dknown_sum = (1-dpt)/(1-dt);
#pragma omp parallel for schedule(dynamic,1) private(i) <ompts:check>reduction(+:dsum)</ompts:check><ompts:crosscheck></ompts:crosscheck>
for (i=0;i<DOUBLE_DIGITS;++i)
{
dsum += pow(dt,i);
}

if( fabs(dsum-dknown_sum) > rounding_error )
{
result++;
fprintf(logFile,"Error in sum with doubles: Result was %f instead of %f (Difference: %E)\n",dsum,dknown_sum, dsum-dknown_sum);
}

dpt=1;

for (i=0;i<DOUBLE_DIGITS;++i)
{
dpt*=dt;
}
fprintf(logFile,"\n");
ddiff = (1-dpt)/(1-dt);
#pragma omp parallel for schedule(dynamic,1) private(i) <ompts:check>reduction(-:ddiff)</ompts:check><ompts:crosscheck></ompts:crosscheck>
for (i=0;i<DOUBLE_DIGITS;++i)
{
ddiff -= pow(dt,i);
}
if( fabs(ddiff) > rounding_error)
{
result++;
fprintf(logFile,"Error in Difference with doubles: Result was %E instead of 0.0\n",ddiff);
}

#pragma omp parallel for schedule(dynamic,1) private(i) <ompts:check>reduction(*:product)</ompts:check><ompts:crosscheck></ompts:crosscheck>
for(i=1;i<=MAX_FACTOR;i++)
{
product *= i;
}

known_product = KNOWN_PRODUCT;
if(known_product != product)
{
result++;
fprintf(logFile,"Error in Product with integers: Result was %d instead of %d\n\n",product,known_product);
}

for(i=0;i<LOOPCOUNT;i++)
{
logics[i]=1;
}

#pragma omp parallel for schedule(dynamic,1) private(i) <ompts:check>reduction(&&:logic_and)</ompts:check><ompts:crosscheck></ompts:crosscheck>
for(i=0;i<LOOPCOUNT;++i)
{
logic_and = (logic_and && logics[i]);
}
if(!logic_and)
{
result++;
fprintf(logFile,"Error in logic AND part 1.\n");
}

logic_and = 1;
logics[LOOPCOUNT/2]=0;

#pragma omp parallel for schedule(dynamic,1) private(i) <ompts:check>reduction(&&:logic_and)</ompts:check><ompts:crosscheck></ompts:crosscheck>
for(i=0;i<LOOPCOUNT;++i)
{
logic_and = logic_and && logics[i];
}
if(logic_and)
{
result++;
fprintf(logFile,"Error in logic AND part 2.\n");
}

for(i=0;i<LOOPCOUNT;i++)
{
logics[i]=0;
}

#pragma omp parallel for schedule(dynamic,1) private(i) <ompts:check>reduction(||:logic_or)</ompts:check><ompts:crosscheck></ompts:crosscheck>
for(i=0;i<LOOPCOUNT;++i)
{
logic_or = logic_or || logics[i];
}
if(logic_or)
{
result++;
fprintf(logFile,"Error in logic OR part 1.\n");
}
logic_or = 0;
logics[LOOPCOUNT/2]=1;

#pragma omp parallel for schedule(dynamic,1) private(i) <ompts:check>reduction(||:logic_or)</ompts:check><ompts:crosscheck></ompts:crosscheck>
for(i=0;i<LOOPCOUNT;++i)
{
logic_or = logic_or || logics[i];
}
if(!logic_or)
{
result++;
fprintf(logFile,"Error in logic OR part 2.\n");
}


for(i=0;i<LOOPCOUNT;++i)
{
logics[i]=1;
}

#pragma omp parallel for schedule(dynamic,1) private(i) <ompts:check>reduction(&:bit_and)</ompts:check><ompts:crosscheck></ompts:crosscheck>
for(i=0;i<LOOPCOUNT;++i)
{
bit_and = (bit_and & logics[i]);
}
if(!bit_and)
{
result++;
fprintf(logFile,"Error in BIT AND part 1.\n");
}

bit_and = 1;
logics[LOOPCOUNT/2]=0;

#pragma omp parallel for schedule(dynamic,1) private(i) <ompts:check>reduction(&:bit_and)</ompts:check><ompts:crosscheck></ompts:crosscheck>
for(i=0;i<LOOPCOUNT;++i)
{
bit_and = bit_and & logics[i];
}
if(bit_and)
{
result++;
fprintf(logFile,"Error in BIT AND part 2.\n");
}

for(i=0;i<LOOPCOUNT;i++)
{
logics[i]=0;
}

#pragma omp parallel for schedule(dynamic,1) private(i) <ompts:check>reduction(|:bit_or)</ompts:check><ompts:crosscheck></ompts:crosscheck>
for(i=0;i<LOOPCOUNT;++i)
{
bit_or = bit_or | logics[i];
}
if(bit_or)
{
result++;
fprintf(logFile,"Error in BIT OR part 1\n");
}
bit_or = 0;
logics[LOOPCOUNT/2]=1;

#pragma omp parallel for schedule(dynamic,1) private(i) <ompts:check>reduction(|:bit_or)</ompts:check><ompts:crosscheck></ompts:crosscheck>
for(i=0;i<LOOPCOUNT;++i)
{
bit_or = bit_or | logics[i];
}
if(!bit_or)
{
result++;
fprintf(logFile,"Error in BIT OR part 2\n");
}

for(i=0;i<LOOPCOUNT;i++)
{
logics[i]=0;
}

#pragma omp parallel for schedule(dynamic,1) private(i) <ompts:check>reduction(^:exclusiv_bit_or)</ompts:check><ompts:crosscheck></ompts:crosscheck>
for(i=0;i<LOOPCOUNT;++i)
{
exclusiv_bit_or = exclusiv_bit_or ^ logics[i];
}
if(exclusiv_bit_or)
{
result++;
fprintf(logFile,"Error in EXCLUSIV BIT OR part 1\n");
}

exclusiv_bit_or = 0;
logics[LOOPCOUNT/2]=1;

#pragma omp parallel for schedule(dynamic,1) private(i) <ompts:check>reduction(^:exclusiv_bit_or)</ompts:check><ompts:crosscheck></ompts:crosscheck>
for(i=0;i<LOOPCOUNT;++i)
{
exclusiv_bit_or = exclusiv_bit_or ^ logics[i];
}
if(!exclusiv_bit_or)
{
result++;
fprintf(logFile,"Error in EXCLUSIV BIT OR part 2\n");
}
</ompts:orphan>
/*printf("\nResult:%d\n",result);*/
return (result==0);
}
</ompts:testcode>
</ompts:test>
40 changes: 40 additions & 0 deletions openmp/testsuite/c/omp_parallel_if.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<ompts:test>
<ompts:testdescription>Test which checks the if option of the parallel construct.</ompts:testdescription>
<ompts:ompversion>3.0</ompts:ompversion>
<ompts:directive>omp parallel if</ompts:directive>
<ompts:testcode>
#include <stdio.h>
#include <unistd.h>

#include "omp_testsuite.h"

int <ompts:testcode:functionname>omp_parallel_if</ompts:testcode:functionname> (FILE * logFile)
{
<ompts:orphan:vars>
int i;
int sum;
int known_sum;
int mysum;
int control=1;
</ompts:orphan:vars>
sum =0;
known_sum = (LOOPCOUNT * (LOOPCOUNT + 1)) / 2 ;
#pragma omp parallel private(i) <ompts:check>if(control==0)</ompts:check>
{
<ompts:orphan>
mysum = 0;
for (i = 1; i <= LOOPCOUNT; i++)
{
mysum = mysum + i;
}
#pragma omp critical
{
sum = sum + mysum;
} /* end of critical */
</ompts:orphan>
} /* end of parallel */

return (known_sum == sum);
}
</ompts:testcode>
</ompts:test>
46 changes: 46 additions & 0 deletions openmp/testsuite/c/omp_parallel_num_threads.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<ompts:test>
<ompts:testdescription>Test which checks the omp_parallel_num_threads directive by counting the threads in a parallel region which was started with an explicitly stated number of threads.</ompts:testdescription>
<ompts:ompversion>3.0</ompts:ompversion>
<ompts:directive>omp parellel num_threads</ompts:directive>
<ompts:dependences>omp master,omp parallel reduction,omp atomic</ompts:dependences>
<ompts:testcode>
#include <stdio.h>
#include "omp_testsuite.h"

int <ompts:testcode:functionname>omp_parallel_num_threads</ompts:testcode:functionname>(FILE * logFile){
<ompts:orphan:vars>
int failed;
int threads;
int nthreads;
</ompts:orphan:vars>

int max_threads = 0;

failed = 0;

/* first we check how many threads are available */
#pragma omp parallel
{
#pragma omp master
max_threads = omp_get_num_threads ();
}

/* we increase the number of threads from one to maximum:*/
for (threads = 1; threads <= max_threads; threads++)
{
nthreads = 0;

<ompts:orphan>
#pragma omp parallel reduction(+:failed) <ompts:check>num_threads(threads)</ompts:check>
{
failed = failed + !(threads == omp_get_num_threads ());
#pragma omp atomic
nthreads += 1;
}
</ompts:orphan>
failed = failed + !(nthreads == threads);
}
return (!failed);
}
</ompts:testcode>
</ompts:test>
50 changes: 50 additions & 0 deletions openmp/testsuite/c/omp_parallel_private.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<ompts:test>
<ompts:testdescription>Test which checks the omp parallel private directive.</ompts:testdescription>
<ompts:ompversion>3.0</ompts:ompversion>
<ompts:directive>omp parallel private</ompts:directive>
<ompts:dependences>omp for omp critical</ompts:dependences>
<ompts:testcode>
#include <stdio.h>
#include <stdlib.h>
#include "omp_testsuite.h"

//static int sum1 = 789;

int <ompts:testcode:functionname>omp_parallel_private</ompts:testcode:functionname>(FILE * logFile)
{
<ompts:orphan:vars>
int sum, num_threads,sum1;
</ompts:orphan:vars>
int known_sum;

sum = 0;
<ompts:crosscheck> sum1=0; </ompts:crosscheck>
num_threads = 0;


#pragma omp parallel <ompts:check>private(sum1)</ompts:check>
{
<ompts:check>
sum1 = 7;
</ompts:check>
/*printf("sum1=%d\n",sum1);*/
<ompts:orphan>
int i;
#pragma omp for
for (i = 1; i < 1000; i++)
{
sum1 = sum1 + i;
} /*end of for*/
#pragma omp critical
{
sum = sum + sum1;
num_threads++;
} /*end of critical*/
</ompts:orphan>
} /* end of parallel*/
known_sum = (999 * 1000) / 2 + 7 * num_threads;
return (known_sum == sum);

}
</ompts:testcode>
</ompts:test>
Loading