home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Professional / OS2PRO194.ISO / os2 / prgramer / adaptor / dalib / pvm3 / cshift1.c < prev    next >
C/C++ Source or Header  |  1993-11-30  |  12KB  |  314 lines

  1. /**************************************************************************
  2. *                                                                         *
  3. *  Author      : Dr. Thomas Brandes, GMD, I1.HR                           *
  4. *  Copyright   : GMD St. Augustin, Germany                                *
  5. *  Date        : Feb 92                                                   *
  6. *  Last Update : Apr 93                                                   *
  7. *                                                                         *
  8. *  This Module is part of the DALIB                                       *
  9. *                                                                         *
  10. *  Module      : cshift1.c                                                *
  11. *                                                                         *
  12. *  Function    : circular shifting of full arrays                         *
  13. *                (distributed along one dimension)                        *
  14. *                                                                         *
  15. *  Export : FORTRAN Interface                                             *
  16. *                                                                         *
  17. *    void dalib_cshift1__ (dest, source, size, N1, dim, pos)              *
  18. *    void dalib_cshift2__ (dest, source, size, N1, N2, dim, pos)          *
  19. *    void dalib_cshift3__ (dest, source, size, N1, N2, N3, dim, pos)      *
  20. *    void dalib_cshift4__ (dest, source, size, N1, N2, N3, N4, dim, pos)  *
  21. *                                                                         *
  22. *    unsigned char *source, *dest;                                        *
  23. *    int *size, *dim, *pos, *N1, ..., *N4;                                *
  24. *                                                                         *
  25. *  final update needs no longer internal descriptors                      *
  26. *                                                                         *
  27. **************************************************************************/
  28.  
  29. #undef DEBUG
  30.  
  31. #include "system.h"
  32.  
  33. /*******************************************************************
  34. *                                                                  *
  35. *      NAME (j,i) = NAME (j,i-pos)                                 *
  36. *                                                                  *
  37. *      1    2    3    4    5    6 ...  NAME_size                   *
  38. *        <-   <-   <-   <-   <-                                    *
  39. *                                                                  *
  40. *       -----------------------------------------------------      *
  41. *       |+++      ---|+++      ---|+++      ---|+++      ---|      *
  42. *       -----------------------------------------------------      *
  43. *                                                                  *
  44. *    +++ : elements to send, --- : elements to recv                *
  45. *                                                                  *
  46. *        pos_size,  local_size + pos_size = full size of local s.  *
  47. *                                                                  *
  48. *******************************************************************/
  49.  
  50. void dalib_make_shift_left (dest, source, local_size, pos_size)
  51. unsigned char *dest, *source;
  52. int local_size, pos_size;
  53.  
  54. {  int from, to;
  55.  
  56.    /* send data to left neighbour */
  57.  
  58. #ifdef DEBUG
  59.    printf ("Proc %d calls shift left, local_size = %d, pos_size = %d\n",
  60.             pcb.i, local_size, pos_size);
  61. #endif
  62.  
  63.    from = pcb.i;
  64.    to   = from -1;
  65.    if (to == 0) to = pcb.p;
  66.  
  67.    asend (from, to, source, pos_size);
  68.  
  69.    /* dest(...,1:elems-pos) = source (...,pos+1:elems) */
  70.  
  71.    dalib_memcpy (dest, source+pos_size, local_size);
  72.  
  73.    /* receive data from right neighbour */
  74.  
  75.    to = pcb.i;
  76.    from = to + 1;
  77.    if (from > pcb.p) from = 1;
  78.  
  79.    areceive (to, from, dest+local_size, pos_size);
  80. }
  81.  
  82. /*******************************************************************
  83. *                                                                  *
  84. *      NAME (j,i) = NAME (j,i-pos)                                 *
  85. *                                                                  *
  86. *      1    2    3    4    5    6 ...  NAME_size                   *
  87. *        ->   ->   ->   ->   ->                                    *
  88. *                                                                  *
  89. *       -----------------------------------------------------      *
  90. *       |---      +++|---      +++|---      +++|---      +++|      *
  91. *       -----------------------------------------------------      *
  92. *                                                                  *
  93. *    +++ : elements to send, --- : elements to recv                *
  94. *                                                                  *
  95. *        pos_size,  local_size + pos_size = full size of local s.  *
  96. *                                                                  *
  97. *******************************************************************/
  98.  
  99. void dalib_make_shift_right (dest, source, local_size, pos_size)
  100. unsigned char *dest, *source;
  101. int local_size, pos_size;
  102.  
  103. {  int from, to;
  104.  
  105.    /* send data to right neighbour */
  106.  
  107. #ifdef DEBUG
  108.    printf ("Proc %d calls shift right, local_size = %d, pos_size = %d\n",
  109.             pcb.i, local_size, pos_size);
  110. #endif
  111.  
  112.    from = pcb.i;
  113.    to   = from +1;
  114.    if (to > pcb.p) to = 1;
  115.  
  116.    asend (from, to, source+local_size, pos_size);
  117.  
  118.    /* dest(...,pos+1:elems) = source (...,1:elems-pos) */
  119.  
  120.    dalib_rmemcpy (dest+pos_size, source, local_size);
  121.  
  122.    /* receive data from left neighbour */
  123.  
  124.    to = pcb.i;
  125.    from = to - 1;
  126.    if (from == 0) from = pcb.p;
  127.  
  128.    areceive (to, from, dest, pos_size);
  129. }
  130.  
  131. extern int dalib_local_size ();
  132.  
  133. /*******************************************************************
  134. *                                                                  *
  135. *  compute_shft_pos (shft_pos, real_pos, max_shift)                *
  136. *                                                                  *
  137. *   shft_pos  : number of positions that will be shifted           *
  138. *   real_pos  : number of positions that should be shifted (mod.)  *
  139. *                                                                  *
  140. *   max_shift : maximal number of positions that can be shifted    *
  141. *                                                                  *
  142. *******************************************************************/
  143.  
  144. void compute_shift_pos (shft_pos, real_pos, max_shift)
  145.  
  146. int *shft_pos, *real_pos, max_shift;
  147.  
  148. { if (*real_pos > max_shift)
  149.     { *shft_pos  = max_shift;
  150.       *real_pos -= max_shift;
  151.     }
  152.   else if (*real_pos > 0)
  153.     { *shft_pos  = *real_pos;
  154.       *real_pos  = 0;
  155.     }
  156.   else if (*real_pos < -max_shift)
  157.     { *shft_pos = -max_shift;
  158.       *real_pos += max_shift;
  159.     }
  160.   else
  161.     { *shft_pos = *real_pos;
  162.       *real_pos = 0;
  163.     };
  164. } /* compute_shift_pos */
  165.  
  166. /*******************************************************************
  167. *                                                                  *
  168. *   do_comm_cshift (dest, source, pos, N, col_size)                *
  169. *                                                                  *
  170. *   -  imagine dest, source as a two dimensional array             *
  171. *                                                                  *
  172. *   -  dest is pointer to target array                             *
  173. *   -  source is pointer to source array                           *
  174. *                                                                  *
  175. *   -  N is number of columns for the full array                   *
  176. *      (my_N will be the number of local columns)                  *
  177. *                                                                  *
  178. *   -  pos is number of positions that columns are shifted         *
  179. *                                                                  *
  180. *******************************************************************/
  181.  
  182. void do_comm_cshift (dest, source, pos, N, col_size)
  183.  
  184. unsigned char *dest, *source;
  185. int pos, N, col_size;
  186.  
  187. {  int max_shift;   /* maximal number of positions for shift */
  188.    int real_pos;    /* pos normed to N */
  189.    int shft_pos;    /* pos that will be shifted in on step   */
  190.    int move_size;   /* number of bytes for communication     */
  191.    int local_size;  /* nubmer of bytes for local move        */
  192.    int my_N;        /* my size of source, dest               */
  193.  
  194.    max_shift = N / pcb.p;
  195.  
  196.    real_pos = pos;
  197.    update_pos (&real_pos, N);    /* - N/2 <= pos <= N/2   */
  198.  
  199.    my_N = dalib_local_size (N);
  200.  
  201.    while (real_pos != 0)
  202.      { compute_shift_pos (&shft_pos, &real_pos, max_shift);
  203.        /* 1 <= shft_pos <= max_shift or -max_shift <= shft_pos <= -1 */
  204.        if (shft_pos > 0)
  205.          { move_size = col_size * shft_pos;
  206.            local_size = (my_N - shft_pos) * col_size;
  207.            dalib_make_shift_left (dest, source, local_size, move_size);
  208.          }
  209.        else
  210.          { move_size = col_size * (-shft_pos);
  211.            local_size = (my_N + shft_pos) * col_size;
  212.            dalib_make_shift_right (dest, source, local_size, move_size);
  213.          }
  214.      } /* while loop */
  215.  
  216. }  /* do_comm_cshift */
  217.  
  218. /*******************************************************************
  219. *                                                                  *
  220. *  ONE DIMENSIONAL ARRAYS                                          *
  221. *                                                                  *
  222. *******************************************************************/
  223.  
  224. void dalib_cshift1__ (dest, source, size, N1, dim, pos)
  225. unsigned char *dest, *source;
  226. int *size, *N1, *dim, *pos;
  227.  
  228. { int my_N;
  229.  
  230.   if (*dim == 1)
  231.  
  232.      do_comm_cshift (dest, source, *pos, *N1, *size);
  233.  
  234.   else
  235.  
  236.     { my_N = dalib_local_size (*N1);
  237.       dalib_lcshift1__ (dest, source, size, &my_N, dim, pos);
  238.     }
  239.  
  240. } /* dalib_cshift1 */
  241.  
  242. /*******************************************************************
  243. *                                                                  *
  244. *  TWO  DIMENSIONAL ARRAYS                                         *
  245. *                                                                  *
  246. *******************************************************************/
  247.  
  248. void dalib_cshift2__ (dest, source, size, N1, N2, dim, pos)
  249. unsigned char *dest, *source;
  250. int *size, *N1, *N2, *dim, *pos;
  251.  
  252. { int my_N;
  253.  
  254.   if (*dim == 2)
  255.  
  256.     do_comm_cshift (dest, source, *pos, *N2, *size * *N1);
  257.  
  258.   else
  259.  
  260.     { my_N = dalib_local_size (*N2);
  261.       dalib_lcshift2__ (dest, source, size, N1, &my_N, dim, pos);
  262.     }
  263.  
  264. } /* dalib_cshift2 */
  265.  
  266. /*******************************************************************
  267. *                                                                  *
  268. *  THREE DIMENSIONAL ARRAYS                                        *
  269. *                                                                  *
  270. *******************************************************************/
  271.  
  272. void dalib_cshift3__ (dest, source, size, N1, N2, N3, dim, pos)
  273. unsigned char *dest, *source;
  274. int *size, *N1, *N2, *N3, *dim, *pos;
  275.  
  276. { int my_N;
  277.  
  278.   if (*dim == 3)   /* is the distributed dimension */
  279.  
  280.     do_comm_cshift (dest, source, *pos, *N3, *size * *N1 * *N2);
  281.  
  282.   else
  283.  
  284.     { my_N = dalib_local_size (*N3);
  285.       dalib_lcshift3__ (dest, source, size, N1, N2, &my_N, dim, pos);
  286.     }
  287.  
  288. } /* dalib_cshift3 */
  289.  
  290. /*******************************************************************
  291. *                                                                  *
  292. *  FOUR  DIMENSIONAL ARRAYS                                        *
  293. *                                                                  *
  294. *******************************************************************/
  295.  
  296. void dalib_cshift4__ (dest, source, size, N1, N2, N3, N4, dim, pos)
  297. unsigned char *dest, *source;
  298. int *size, *N1, *N2, *N3, *N4, *dim, *pos;
  299.  
  300. { int my_N;
  301.  
  302.   if (*dim == 4)   /* is the distributed dimension */
  303.  
  304.     do_comm_cshift (dest, source, *pos, *N4, *size * *N1 * *N2 * *N3);
  305.  
  306.   else
  307.  
  308.     { my_N = dalib_local_size (*N4);
  309.       dalib_lcshift4__ (dest, source, size, N1, N2, N3, &my_N, dim, pos);
  310.     }
  311.  
  312. } /* dalib_cshift4 */
  313.  
  314.