Files
2018-08-28 00:39:32 -04:00

357 lines
8.1 KiB
C

/*
C implementation of C$Id: adBuffer.f 3723 2011-02-24 13:34:42Z llh $
Replac the faulty PUSH/POPs by assignments to/from local arrays,
each of them being declared localized to its thread, make it
thread-safe for OPENMP.
If the OPENMP THREAD NUMBER IS GREATER THAN 256 on a single node,
the STACK_POOL_SEZE needs to be increased.
This portion just ported the necessary codes which used by WRFPLUS
from adBuffer.f, NOT THE WHOLE CODES.
Check it carefully before using for your own case.
2011-10-10 jliu@ucar.edu
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/*
#ifdef _OPENMP
*/
#include <omp.h>
#define STACK_POOL_SIZE 256
/*
#else
#define omp_get_thread_num() 0
#define STACK_POOL_SIZE 1
#endif
*/
#define BUFF_SIZE 512
#define bit_set(x,y) ((x) | ((unsigned long)0x00000001 << (y)))
#define bit_clear(x,y) ((x) & ~((unsigned long)0x00000001 << (y)))
#define bit_test(x,y) ((x) >> (y) & (unsigned long)0x00000001)
typedef int logical;
static int c__1 = 1;
static int c__512 = 512;
static int c_n512 = -512;
static int c__4 = 4;
static int c_n2048 = -2048;
static int c__8 = 8;
static int c_n4096 = -4096;
static int c__16 = 16;
static int c_n8192 = -8192;
static int c_b101 = 1000000;
static int c__9 = 9;
static int c__3 = 3;
static int adbitbuf[STACK_POOL_SIZE] = {0};
static int adbitibuf[STACK_POOL_SIZE] = {0};
static int *adi4buf[STACK_POOL_SIZE] = {NULL};
static int adi4ibuf[STACK_POOL_SIZE] = {0};
static double *adr8buf[STACK_POOL_SIZE] = {NULL};
static int adr8ibuf[STACK_POOL_SIZE] = {0};
static int i4arrnum = 0;
static int r8arrnum = 0;
static int i4num = 0;
static int r8num = 0;
void print_ulong_bin(const unsigned long * const var, int bits) {
int i;
#if defined(__LP64__) || defined(_LP64)
if( (bits > 64) || (bits <= 0) )
#else
if( (bits > 32) || (bits <= 0) )
#endif
return;
for(i = 0; i < bits; i++) {
printf("%lu", (*var >> (bits - 1 - i)) & 0x01);
}
printf("\n");
}
/* ========================= BITS ============================*/
int pushbit_( logical *bit )
{
int thread_id = omp_get_thread_num();
//printf("thread %i push %i bit %i\n", thread_id, *bit, adbitibuf[thread_id]);
if (*bit) {
adbitbuf[thread_id] = bit_set(adbitbuf[thread_id],
adbitibuf[thread_id]);
} else {
adbitbuf[thread_id] = bit_clear(adbitbuf[thread_id],
adbitibuf[thread_id]);
}
if (adbitibuf[thread_id] == 31) {
//printf("thread %02i : pushbit : pushinteger4 %03i : ",thread_id, i4num++);
//print_ulong_bin(&adbitbuf[thread_id],32);
pushinteger4_(&adbitbuf[thread_id]);
adbitbuf[thread_id]=0;
adbitibuf[thread_id]=0;
} else {
adbitibuf[thread_id]++;
}
return 0;
}
logical popbit_(void)
{
logical ret_val;
int thread_id = omp_get_thread_num();
if ( adbitibuf[thread_id] == 0 ) {
//printf("thread %02i : popbit : popinteger4 %03i : ",thread_id, --i4num);
//print_ulong_bin(&adbitbuf[thread_id],32);
popinteger4_(&adbitbuf[thread_id]);
adbitibuf[thread_id]=31;
} else {
adbitibuf[thread_id]--;
}
ret_val = bit_test(adbitbuf[thread_id], adbitibuf[thread_id]);
//printf("thread %i pop %i bit %i\n", thread_id, ret_val, adbitibuf[thread_id]);
return ret_val;
}
/* ========================= CONTROL ========================= */
int pushcontrol1b_(int *cc)
{
logical L;
L = *cc != 0;
pushbit_(&L);
return 0;
}
int popcontrol1b_(int *cc)
{
if (popbit_()) {
*cc = 1;
} else {
*cc = 0;
}
return 0;
}
int pushcontrol2b_(int *cc)
{
logical L;
L = bit_test(*cc,0);
pushbit_(&L);
L = bit_test(*cc,1);
pushbit_(&L);
return 0;
}
int popcontrol2b_(int *cc)
{
if (popbit_()) {
*cc = 2;
} else {
*cc = 0;
}
if (popbit_()) {
*cc = bit_set(*cc,0);
}
return 0;
}
int pushcontrol3b_(int *cc)
{
logical L;
L = bit_test(*cc,0);
pushbit_(&L);
L = bit_test(*cc,1);
pushbit_(&L);
L = bit_test(*cc,2);
pushbit_(&L);
return 0;
}
int popcontrol3b_(int *cc)
{
if (popbit_()) {
*cc = 4;
} else {
*cc = 0;
}
if (popbit_()) {
*cc = bit_set(*cc,1);
}
if (popbit_()) {
*cc = bit_set(*cc,0);
}
return 0;
}
int pushcontrol4b_(int *cc)
{
logical L;
L = bit_test(*cc,0);
pushbit_(&L);
L = bit_test(*cc,1);
pushbit_(&L);
L = bit_test(*cc,2);
pushbit_(&L);
L = bit_test(*cc,3);
pushbit_(&L);
return 0;
}
int popcontrol4b_(int *cc)
{
if (popbit_()) {
*cc = 8;
} else {
*cc = 0;
}
if (popbit_()) {
*cc = bit_set(*cc,2);
}
if (popbit_()) {
*cc = bit_set(*cc,1);
}
if (popbit_()) {
*cc = bit_set(*cc,0);
}
return 0;
}
int pushcontrol5b_(int *cc)
{
logical L;
L = bit_test(*cc,0);
pushbit_(&L);
L = bit_test(*cc,1);
pushbit_(&L);
L = bit_test(*cc,2);
pushbit_(&L);
L = bit_test(*cc,3);
pushbit_(&L);
L = bit_test(*cc,4);
pushbit_(&L);
return 0;
}
int popcontrol5b_(int *cc)
{
if (popbit_()) {
*cc = 16;
} else {
*cc = 0;
}
if (popbit_()) {
*cc = bit_set(*cc,3);
}
if (popbit_()) {
*cc = bit_set(*cc,2);
}
if (popbit_()) {
*cc = bit_set(*cc,1);
}
if (popbit_()) {
*cc = bit_set(*cc,0);
}
return 0;
}
/* ======================= INTEGER*4 =========================: */
int pushinteger4_(int *x)
{
int thread_id = omp_get_thread_num();
if ( adi4buf[thread_id] == NULL ) {
int *buf = (int*)calloc(BUFF_SIZE, sizeof(int));
if ( buf == NULL ) {
puts("Memory allocation failed.");
exit(0);
}
adi4buf[thread_id] = buf;
}
adi4buf[thread_id][adi4ibuf[thread_id]] = *x;
++adi4ibuf[thread_id];
if ( adi4ibuf[thread_id] == BUFF_SIZE) {
//printf("thread %02i : pushinteger4 : pushinteger4array : %04i : ", thread_id, ++i4arrnum);
//printf("[0]: %i [%i] : %i\n",adi4buf[thread_id][0], adi4ibuf[thread_id]-1, adi4buf[thread_id][adi4ibuf[thread_id]-1]);
pushinteger4array_(adi4buf[thread_id], &c__512);
adi4ibuf[thread_id] = 0 ;
}
//printf("thread %i pushinteger4 %i buff %i\n ", thread_id, *x, adi4ibuf[thread_id]);
return 0;
}
int popinteger4_(int *x)
{
int thread_id = omp_get_thread_num();
if ( adi4ibuf[thread_id] == 0 ) {
popinteger4array_(adi4buf[thread_id], &c__512);
adi4ibuf[thread_id] = BUFF_SIZE;
//printf("thread %02i : popinteger4 : popinteger4array : %04i : ", thread_id, i4arrnum--);
//printf("[0]: %i [%i] : %i\n",adi4buf[thread_id][0], adi4ibuf[thread_id]-1, adi4buf[thread_id][adi4ibuf[thread_id]-1]);
}
--adi4ibuf[thread_id];
*x = adi4buf[thread_id][adi4ibuf[thread_id]];
//printf("thread %i popinteger4 %i buff %i\n", thread_id, *x, adi4ibuf[thread_id]);
return 0;
}
/* ======================= REAL*8 ========================= */
int pushreal8_(double *x)
{
int thread_id = omp_get_thread_num();
if (adr8buf[thread_id] == NULL ) {
double *buf = (double*)calloc(BUFF_SIZE, sizeof(double));
if ( buf == NULL ) {
puts("Memory allocation failed.");
exit(0);
}
adr8buf[thread_id] = buf;
}
adr8buf[thread_id][adr8ibuf[thread_id]] = *x;
++adr8ibuf[thread_id];
if ( adr8ibuf[thread_id] == BUFF_SIZE) {
//printf("thread %02i : pushreal8 : pushreal8array : %04i : ", thread_id, ++r8arrnum);
//printf("[0]: %f [%i] : %f\n",adr8buf[thread_id][0], adr8ibuf[thread_id]-1, adr8buf[thread_id][adr8ibuf[thread_id]-1]);
pushreal8array_(adr8buf[thread_id], &c__512);
adr8ibuf[thread_id] = 0 ;
}
//printf("thread %i pushreal8 %f buff %i\n", thread_id, *x,adr8ibuf[thread_id] );
return 0;
}
int popreal8_(double *x)
{
int thread_id = omp_get_thread_num();
if ( adr8ibuf[thread_id] == 0 ) {
popreal8array_(adr8buf[thread_id], &c__512);
adr8ibuf[thread_id] = BUFF_SIZE;
//printf("thread %02i : popreal8 : popreal8array : %04i : ", thread_id, r8arrnum--);
//printf("[0]: %f [%i] : %f\n",adr8buf[thread_id][0], adr8ibuf[thread_id]-1, adr8buf[thread_id][adr8ibuf[thread_id]-1]);
}
--adr8ibuf[thread_id];
*x = adr8buf[thread_id][adr8ibuf[thread_id]];
//printf("thread %i popreal8 %f buff %i\n", thread_id, *x, adr8ibuf[thread_id]);
return 0;
}