home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Professional
/
OS2PRO194.ISO
/
os2
/
prgramer
/
adaptor
/
dalib
/
pvm3
/
cshift1.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-11-30
|
12KB
|
314 lines
/**************************************************************************
* *
* Author : Dr. Thomas Brandes, GMD, I1.HR *
* Copyright : GMD St. Augustin, Germany *
* Date : Feb 92 *
* Last Update : Apr 93 *
* *
* This Module is part of the DALIB *
* *
* Module : cshift1.c *
* *
* Function : circular shifting of full arrays *
* (distributed along one dimension) *
* *
* Export : FORTRAN Interface *
* *
* void dalib_cshift1__ (dest, source, size, N1, dim, pos) *
* void dalib_cshift2__ (dest, source, size, N1, N2, dim, pos) *
* void dalib_cshift3__ (dest, source, size, N1, N2, N3, dim, pos) *
* void dalib_cshift4__ (dest, source, size, N1, N2, N3, N4, dim, pos) *
* *
* unsigned char *source, *dest; *
* int *size, *dim, *pos, *N1, ..., *N4; *
* *
* final update needs no longer internal descriptors *
* *
**************************************************************************/
#undef DEBUG
#include "system.h"
/*******************************************************************
* *
* NAME (j,i) = NAME (j,i-pos) *
* *
* 1 2 3 4 5 6 ... NAME_size *
* <- <- <- <- <- *
* *
* ----------------------------------------------------- *
* |+++ ---|+++ ---|+++ ---|+++ ---| *
* ----------------------------------------------------- *
* *
* +++ : elements to send, --- : elements to recv *
* *
* pos_size, local_size + pos_size = full size of local s. *
* *
*******************************************************************/
void dalib_make_shift_left (dest, source, local_size, pos_size)
unsigned char *dest, *source;
int local_size, pos_size;
{ int from, to;
/* send data to left neighbour */
#ifdef DEBUG
printf ("Proc %d calls shift left, local_size = %d, pos_size = %d\n",
pcb.i, local_size, pos_size);
#endif
from = pcb.i;
to = from -1;
if (to == 0) to = pcb.p;
asend (from, to, source, pos_size);
/* dest(...,1:elems-pos) = source (...,pos+1:elems) */
dalib_memcpy (dest, source+pos_size, local_size);
/* receive data from right neighbour */
to = pcb.i;
from = to + 1;
if (from > pcb.p) from = 1;
areceive (to, from, dest+local_size, pos_size);
}
/*******************************************************************
* *
* NAME (j,i) = NAME (j,i-pos) *
* *
* 1 2 3 4 5 6 ... NAME_size *
* -> -> -> -> -> *
* *
* ----------------------------------------------------- *
* |--- +++|--- +++|--- +++|--- +++| *
* ----------------------------------------------------- *
* *
* +++ : elements to send, --- : elements to recv *
* *
* pos_size, local_size + pos_size = full size of local s. *
* *
*******************************************************************/
void dalib_make_shift_right (dest, source, local_size, pos_size)
unsigned char *dest, *source;
int local_size, pos_size;
{ int from, to;
/* send data to right neighbour */
#ifdef DEBUG
printf ("Proc %d calls shift right, local_size = %d, pos_size = %d\n",
pcb.i, local_size, pos_size);
#endif
from = pcb.i;
to = from +1;
if (to > pcb.p) to = 1;
asend (from, to, source+local_size, pos_size);
/* dest(...,pos+1:elems) = source (...,1:elems-pos) */
dalib_rmemcpy (dest+pos_size, source, local_size);
/* receive data from left neighbour */
to = pcb.i;
from = to - 1;
if (from == 0) from = pcb.p;
areceive (to, from, dest, pos_size);
}
extern int dalib_local_size ();
/*******************************************************************
* *
* compute_shft_pos (shft_pos, real_pos, max_shift) *
* *
* shft_pos : number of positions that will be shifted *
* real_pos : number of positions that should be shifted (mod.) *
* *
* max_shift : maximal number of positions that can be shifted *
* *
*******************************************************************/
void compute_shift_pos (shft_pos, real_pos, max_shift)
int *shft_pos, *real_pos, max_shift;
{ if (*real_pos > max_shift)
{ *shft_pos = max_shift;
*real_pos -= max_shift;
}
else if (*real_pos > 0)
{ *shft_pos = *real_pos;
*real_pos = 0;
}
else if (*real_pos < -max_shift)
{ *shft_pos = -max_shift;
*real_pos += max_shift;
}
else
{ *shft_pos = *real_pos;
*real_pos = 0;
};
} /* compute_shift_pos */
/*******************************************************************
* *
* do_comm_cshift (dest, source, pos, N, col_size) *
* *
* - imagine dest, source as a two dimensional array *
* *
* - dest is pointer to target array *
* - source is pointer to source array *
* *
* - N is number of columns for the full array *
* (my_N will be the number of local columns) *
* *
* - pos is number of positions that columns are shifted *
* *
*******************************************************************/
void do_comm_cshift (dest, source, pos, N, col_size)
unsigned char *dest, *source;
int pos, N, col_size;
{ int max_shift; /* maximal number of positions for shift */
int real_pos; /* pos normed to N */
int shft_pos; /* pos that will be shifted in on step */
int move_size; /* number of bytes for communication */
int local_size; /* nubmer of bytes for local move */
int my_N; /* my size of source, dest */
max_shift = N / pcb.p;
real_pos = pos;
update_pos (&real_pos, N); /* - N/2 <= pos <= N/2 */
my_N = dalib_local_size (N);
while (real_pos != 0)
{ compute_shift_pos (&shft_pos, &real_pos, max_shift);
/* 1 <= shft_pos <= max_shift or -max_shift <= shft_pos <= -1 */
if (shft_pos > 0)
{ move_size = col_size * shft_pos;
local_size = (my_N - shft_pos) * col_size;
dalib_make_shift_left (dest, source, local_size, move_size);
}
else
{ move_size = col_size * (-shft_pos);
local_size = (my_N + shft_pos) * col_size;
dalib_make_shift_right (dest, source, local_size, move_size);
}
} /* while loop */
} /* do_comm_cshift */
/*******************************************************************
* *
* ONE DIMENSIONAL ARRAYS *
* *
*******************************************************************/
void dalib_cshift1__ (dest, source, size, N1, dim, pos)
unsigned char *dest, *source;
int *size, *N1, *dim, *pos;
{ int my_N;
if (*dim == 1)
do_comm_cshift (dest, source, *pos, *N1, *size);
else
{ my_N = dalib_local_size (*N1);
dalib_lcshift1__ (dest, source, size, &my_N, dim, pos);
}
} /* dalib_cshift1 */
/*******************************************************************
* *
* TWO DIMENSIONAL ARRAYS *
* *
*******************************************************************/
void dalib_cshift2__ (dest, source, size, N1, N2, dim, pos)
unsigned char *dest, *source;
int *size, *N1, *N2, *dim, *pos;
{ int my_N;
if (*dim == 2)
do_comm_cshift (dest, source, *pos, *N2, *size * *N1);
else
{ my_N = dalib_local_size (*N2);
dalib_lcshift2__ (dest, source, size, N1, &my_N, dim, pos);
}
} /* dalib_cshift2 */
/*******************************************************************
* *
* THREE DIMENSIONAL ARRAYS *
* *
*******************************************************************/
void dalib_cshift3__ (dest, source, size, N1, N2, N3, dim, pos)
unsigned char *dest, *source;
int *size, *N1, *N2, *N3, *dim, *pos;
{ int my_N;
if (*dim == 3) /* is the distributed dimension */
do_comm_cshift (dest, source, *pos, *N3, *size * *N1 * *N2);
else
{ my_N = dalib_local_size (*N3);
dalib_lcshift3__ (dest, source, size, N1, N2, &my_N, dim, pos);
}
} /* dalib_cshift3 */
/*******************************************************************
* *
* FOUR DIMENSIONAL ARRAYS *
* *
*******************************************************************/
void dalib_cshift4__ (dest, source, size, N1, N2, N3, N4, dim, pos)
unsigned char *dest, *source;
int *size, *N1, *N2, *N3, *N4, *dim, *pos;
{ int my_N;
if (*dim == 4) /* is the distributed dimension */
do_comm_cshift (dest, source, *pos, *N4, *size * *N1 * *N2 * *N3);
else
{ my_N = dalib_local_size (*N4);
dalib_lcshift4__ (dest, source, size, N1, N2, N3, &my_N, dim, pos);
}
} /* dalib_cshift4 */