コード例 #1
0
ファイル: TOMS_transpose.c プロジェクト: Pinkii-/PCA
/*
 * "a" is a 1D array of length ny*nx which constains the nx x ny matrix to be
 * transposed.  "a" is stored in C order (last index varies fastest).  move
 * is a 1D array of length move_size used to store information to speed up
 * the process.  The value move_size=(ny+nx)/2 is recommended.
 * 
 * Here, instead of each element of "a" being a single value of type
 * TOMS_el_type, each element is el_size values of type TOMS_el_type.
 * 
 * The return value indicates the success or failure of the routine. Returns 0
 * if okay, -1 if ny or nx < 0, and -2 if move_size < 1. Also, returns -3 if
 * it ran out of memory.  The return value should never be positive, but it
 * it is, it is set to the final position in a when the search is completed
 * but some elements have not been moved.
 * 
 * Note: move[i] will stay zero for fixed points.
 */
short TOMS_transpose_2d_arbitrary(TOMS_el_type * a,
				  int nx, int ny,
				  int el_size,
				  char *move,
				  int move_size)
{
	int             i, j, im, mn;
	TOMS_el_type   *b, *c, *d;
	int             ncount;
	int             k;

	/* check arguments and initialize: */
	if (ny < 0 || nx < 0)
		return -1;
	if (ny < 2 || nx < 2 || el_size < 1)
		return 0;
	if (move_size < 1)
		return -2;

	b = (TOMS_el_type *) malloc(sizeof(TOMS_el_type) * el_size);
	if (!b)
		return -3;

	if (ny == nx) {
		/*
		 * if matrix is square, exchange elements a(i,j) and a(j,i):
		 */
		for (i = 0; i < nx; ++i)
			for (j = i + 1; j < nx; ++j) {
				memcpy(b, &a[el_size * (i + j * nx)], el_size * sizeof(TOMS_el_type));
				memcpy(&a[el_size * (i + j * nx)], &a[el_size * (j + i * nx)], el_size * sizeof(TOMS_el_type));
				memcpy(&a[el_size * (j + i * nx)], b, el_size * sizeof(TOMS_el_type));
			}
		free(b);
		return 0;
	}
	c = (TOMS_el_type *) malloc(sizeof(TOMS_el_type) * el_size);
	if (!c) {
		free(b);
		return -3;
	}
	ncount = 2;		/* always at least 2 fixed points */
	k = (mn = ny * nx) - 1;

	for (i = 0; i < move_size; ++i)
		move[i] = 0;

	if (ny >= 3 && nx >= 3)
		ncount += TOMS_gcd(ny - 1, nx - 1) - 1;	/* # fixed points */

	i = 1;
	im = ny;

	while (1) {
		int             i1, i2, i1c, i2c;
		int             kmi;

		/** Rearrange the elements of a loop
	              and its companion loop: **/

		i1 = i;
		kmi = k - i;
		memcpy(b, &a[el_size * i1], el_size * sizeof(TOMS_el_type));
		i1c = kmi;
		memcpy(c, &a[el_size * i1c], el_size * sizeof(TOMS_el_type));

		while (1) {
			i2 = ny * i1 - k * (i1 / nx);
			i2c = k - i2;
			if (i1 < move_size)
				move[i1] = 1;
			if (i1c < move_size)
				move[i1c] = 1;
			ncount += 2;
			if (i2 == i)
				break;
			if (i2 == kmi) {
				d = b;
				b = c;
				c = d;
				break;
			}
			memcpy(&a[el_size * i1], &a[el_size * i2], 
			       el_size * sizeof(TOMS_el_type));
			memcpy(&a[el_size * i1c], &a[el_size * i2c], 
			       el_size * sizeof(TOMS_el_type));
			i1 = i2;
			i1c = i2c;
		}
		memcpy(&a[el_size * i1], b, el_size * sizeof(TOMS_el_type));
		memcpy(&a[el_size * i1c], c, el_size * sizeof(TOMS_el_type));

		if (ncount >= mn)
			break;	/* we've moved all elements */

		/** Search for loops to rearrange: **/

		while (1) {
			int             max;

			max = k - i;
			++i;
			if (i > max) {
				free(b);
				free(c);
				return i;
			}
			im += ny;
			if (im > k)
				im -= k;
			i2 = im;
			if (i == i2)
				continue;
			if (i >= move_size) {
				while (i2 > i && i2 < max) {
					i1 = i2;
					i2 = ny * i1 - k * (i1 / nx);
				}
				if (i2 == i)
					break;
			} else if (!move[i])
				break;
		}
	}

	free(b);
	free(c);
	return 0;
}
コード例 #2
0
ファイル: TOMS_transpose.c プロジェクト: Pinkii-/PCA
short TOMS_transpose_2d(TOMS_el_type * a,
			int nx, int ny,
			char *move,
			int move_size)
{
	int             i, j, im, mn;
	TOMS_el_type    b, c, d;
	int             ncount;
	int             k;

	/* check arguments and initialize: */
	if (ny < 0 || nx < 0)
		return -1;
	if (ny < 2 || nx < 2)
		return 0;
	if (move_size < 1)
		return -2;

	if (ny == nx) {
		/*
		 * if matrix is square, exchange elements a(i,j) and a(j,i):
		 */
		for (i = 0; i < nx; ++i)
			for (j = i + 1; j < nx; ++j) {
				b = a[i + j * nx];
				a[i + j * nx] = a[j + i * nx];
				a[j + i * nx] = b;
			}
		return 0;
	}
	ncount = 2;		/* always at least 2 fixed points */
	k = (mn = ny * nx) - 1;

	for (i = 0; i < move_size; ++i)
		move[i] = 0;

	if (ny >= 3 && nx >= 3)
		ncount += TOMS_gcd(ny - 1, nx - 1) - 1;	/* # fixed points */

	i = 1;
	im = ny;

	while (1) {
		int             i1, i2, i1c, i2c;
		int             kmi;

		/** Rearrange the elements of a loop
	              and its companion loop: **/

		i1 = i;
		kmi = k - i;
		b = a[i1];
		i1c = kmi;
		c = a[i1c];

		while (1) {
			i2 = ny * i1 - k * (i1 / nx);
			i2c = k - i2;
			if (i1 < move_size)
				move[i1] = 1;
			if (i1c < move_size)
				move[i1c] = 1;
			ncount += 2;
			if (i2 == i)
				break;
			if (i2 == kmi) {
				d = b;
				b = c;
				c = d;
				break;
			}
			a[i1] = a[i2];
			a[i1c] = a[i2c];
			i1 = i2;
			i1c = i2c;
		}
		a[i1] = b;
		a[i1c] = c;

		if (ncount >= mn)
			break;	/* we've moved all elements */

		/** Search for loops to rearrange: **/

		while (1) {
			int             max;

			max = k - i;
			++i;
			if (i > max)
				return i;
			im += ny;
			if (im > k)
				im -= k;
			i2 = im;
			if (i == i2)
				continue;
			if (i >= move_size) {
				while (i2 > i && i2 < max) {
					i1 = i2;
					i2 = ny * i1 - k * (i1 / nx);
				}
				if (i2 == i)
					break;
			} else if (!move[i])
				break;
		}
	}

	return 0;
}
コード例 #3
0
ファイル: misc_utils.c プロジェクト: gdesvignes/psrfits_utils
short transpose_bytes_inplace(unsigned char *a, int nx, int ny, unsigned char *move,
                      int move_size)
/*
 * TOMS Transpose.  Revised version of algorithm 380.
 *
 * These routines do in-place transposes of arrays.
 *
 * [ Cate, E.G. and Twigg, D.W., ACM Transactions on Mathematical Software,
 *   vol. 3, no. 1, 104-110 (1977) ]
 *
 * C version by Steven G. Johnson. February 1997.
 *
 * "a" is a 1D array of length ny*nx which contains the nx x ny matrix to be
 * transposed.  "a" is stored in C order (last index varies fastest).  move
 * is a 1D array of length move_size used to store information to speed up
 * the process.  The value move_size=(ny+nx)/2 is recommended.
 *
 * The return value indicates the success or failure of the routine. Returns 0
 * if okay, -1 if ny or nx < 0, and -2 if move_size < 1. The return value
 * should never be positive, but it it is, it is set to the final position in
 * a when the search is completed but some elements have not been moved.
 *
 * Note: move[i] will stay zero for fixed points.
 */
{
   int i, j, im, mn;
   unsigned char b, c, d;
   int ncount;
   int k;

   /* check arguments and initialize: */
   if (ny < 0 || nx < 0)
      return -1;
   if (ny < 2 || nx < 2)
      return 0;
   if (move_size < 1)
      return -2;

   if (ny == nx) {
      /*
       * if matrix is square, exchange elements a(i,j) and a(j,i):
       */
      for (i = 0; i < nx; ++i)
         for (j = i + 1; j < nx; ++j) {
            b = a[i + j * nx];
            a[i + j * nx] = a[j + i * nx];
            a[j + i * nx] = b;
         }
      return 0;
   }
   ncount = 2;                  /* always at least 2 fixed points */
   k = (mn = ny * nx) - 1;

   for (i = 0; i < move_size; ++i)
      move[i] = 0;

   if (ny >= 3 && nx >= 3)
      ncount += TOMS_gcd(ny - 1, nx - 1) - 1;   /* # fixed points */

   i = 1;
   im = ny;

   while (1) {
      int i1, i2, i1c, i2c;
      int kmi;

    /** Rearrange the elements of a loop
        and its companion loop: **/

      i1 = i;
      kmi = k - i;
      b = a[i1];
      i1c = kmi;
      c = a[i1c];

      while (1) {
         i2 = ny * i1 - k * (i1 / nx);
         i2c = k - i2;
         if (i1 < move_size)
            move[i1] = 1;
         if (i1c < move_size)
            move[i1c] = 1;
         ncount += 2;
         if (i2 == i)
            break;
         if (i2 == kmi) {
            d = b;
            b = c;
            c = d;
            break;
         }
         a[i1] = a[i2];
         a[i1c] = a[i2c];
         i1 = i2;
         i1c = i2c;
      }
      a[i1] = b;
      a[i1c] = c;

      if (ncount >= mn)
         break;                 /* we've moved all elements */

    /** Search for loops to rearrange: **/

      while (1) {
         int max;

         max = k - i;
         ++i;
         if (i > max)
            return i;
         im += ny;
         if (im > k)
            im -= k;
         i2 = im;
         if (i == i2)
            continue;
         if (i >= move_size) {
            while (i2 > i && i2 < max) {
               i1 = i2;
               i2 = ny * i1 - k * (i1 / nx);
            }
            if (i2 == i)
               break;
         } else if (!move[i])
            break;
      }
   }

   return 0;
}