home *** CD-ROM | disk | FTP | other *** search
- /**************************************************************************
- * *
- * 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 */
-
-