2012-02-09 13 views
6

¿Es posible generar una permutación específica de una matriz con una macro en C?permutaciones de matriz C con macros

es decir, Si tengo una matriz X de elementos:

 0 1 2 3 4 5 
x = ["0","1","1","0","1","0"] 

estaba pensando puede haber algo de foo macro para algo como esto:

#define S_2Permute(x) = [x[5], x[3], x[4], x[2], x[1]] 

donde redefinir el orden de la matriz , entonces el elemento en la posición original 5 ahora está en la posición 0.

¿Alguna idea?

Ejemplo de

estoy empezando a crear una implementación del algoritmo de cifrado DES. DES requiere varias permutaciones/expansiones en las que tendría que volver a ordenar todos los elementos en la matriz, a veces reduciendo la matriz y, a veces, expandiéndola. Esperaba poder definir una macro para permutar las matrices por mí.

Edit2

bien en DES el primer paso es algo que se llama la permutación inicial. Así que al principio tengo algo de clave de 64 bits, lo que para este ejemplo puede ser hexagonal 0-15:

ABCDEF 

que se expande a:

0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111 

El IP (permutación inicial) iba a permutar esta cadena por lo que cada elemento de la matriz estaría en una nueva posición:

IP = 
      58 50 42 34 26 18 10 2 
      60 52 44 36 28 20 12 4 
      62 54 46 38 30 22 14 6 
      64 56 48 40 32 24 16 8 
      57 49 41 33 25 17  9 1 
      59 51 43 35 27 19 11 3 
      61 53 45 37 29 21 13 5 
      63 55 47 39 31 23 15 7 

Así que la nueva primera elemento de la cadena de bits sería el elemento 58a (bits) de la cadena de bits originales.

por lo que tendría todos estos bits almacenados en una matriz de caracteres:

x = [0,0,0,0,0,0,0,1,0,0,1,0,0,0,1,1,0,1,0,0,0,1,0,1,0,1,1,0,0, 
    1,1,1,1,0,0,0,1,0,0,1,1,0,1,0,1,0,1,1,1,1,0,0,1,1,0,1,1,1,1,0,1,1,1,1] 

y luego a llamarlo

IP_PERMUTE(x); 

Y macro magia se habrá movido todos los bits en el nuevo posiciones correctas.

+0

No estoy seguro de obtenerlo. ¿Podría darnos un ejemplo de cómo le gustaría usar esto? –

+0

@GregHewgill seguro, agregué lo que con suerte usaré para esto. –

+0

Estaba pensando más en un ejemplo de código. ¿Cómo * exactamente * se vería su código, y qué parte reemplazaría la macro? –

Respuesta

4

Absolutamente - ya casi está allí con su ejemplo. Prueba esto:

#define S_2Permute(x) {x[5], x[3], x[4], x[2], x[1]} 

Luego, más tarde:

int x[] = {1,2,3,4,5,6}; 
int y[] = S_2Permute(x); // y is now {6,4,5,3,2} 

Dos cosas para recordar:

1) en C, las matrices están numeradas del 0, por lo que es posible que significaba:

#define S_2Permute(x) {x[4], x[2], x[3], x[1], x[0]} 

2) Si está utilizando gcc, puede compilar con -E para ver la salida del preprocesador (muy bueno para debu expansiones de macros gging).


Sin embargo, no creo que realmente lo haría de esta manera - Yo diría que el código será más fácil de leer (y potencialmente menos propenso a errores) si se generan las permutaciones programación - y yo duda de que sea un gran golpe de rendimiento.


Dado que usted dice que tiene problemas para compilar esto, aquí hay un programa de prueba que funciona para mí en gcc 4.6.1:

#include <stdio.h> 
#define S_2Permute(x) {x[5], x[3], x[4], x[2], x[1]} 

int main(void) { 
    int x[] = {1,2,3,4,5,6}; 
    int y[] = S_2Permute(x); 

    for(int i = 0; i < 5; i++) { 
    printf("%d,",y[i]); 
    } 
    printf("\n"); 
} 

compilé con gcc test.c -std=c99 -Wall

+0

Aparece un error de compilación cuando pruebo esto: 'MACRO_TEST.c: 4: 1: error: expected '=', ',', ';', 'asm' o '__attribute__' antes '{' token' –

+0

Realmente ? ¿Puedes publicar tu macro y la línea en la que la usas? Funciona para mí en GCC 4.6.1 –

+0

Aquí está la macro: '#define S2_PERMUTE (x) {x [4], x [2], x [3], x [1], x [0]}' Y Llamo a la macro tal como lo hiciste en tu ejemplo. Estoy usando gcc 4.5.2. Cuando ejecuto gcc -E, sin embargo, veo que el preprocesador amplió la matriz correctamente. Publicaré el programa completo arriba. –

2

estoy nuevo así que le pido disculpas si no está bien ofrecer un medio diferente de solución, pero ¿ha considerado utilizar una función en línea en lugar de una macro?

Me encanta líneas individuales de código que pueden hacer mucho más que el tipo de al lado, pero tiene más sentido para mí para hacerlo de esta manera:

//I would have an array that defined how I wanted to swap the positions, I'll assume 5 elements 
short reordering[5] = {4,1,3,2,0}; 

inline void permuteArray(char array[]) { 
    char swap = array[reordering[0]]; 
    array[reordering[0]] = array[reordinger[1]]; 
    array[reordering[1]] = array[reordinger[2]]; 
    array[reordering[2]] = array[reordinger[3]]; 
    array[reordering[3]] = array[reordinger[4]]; 
    array[reordering[4]] = swap; 
} 

esto puede no ser tan bonita o más eficiente una macro, pero podría ahorrarte algunos dolores de cabeza administrando y manteniendo tu código (y siempre podría ser cambiado por la versión macro que sugiere Timothy.

+2

Está perfectamente bien sugerir una solución diferente (¡y mejor!) A cualquier pregunta, siempre y cuando resuelva el problema en cuestión. Debe mejorar su respuesta elaborando lo que quiere decir con "usar una función en línea", preferiblemente con ejemplos de código compilables. –

+0

Gracias por la respuesta, servirá. –

+0

Gracias por la sugerencia @RobotRocker. –

0

Estoy haciendo algo similar. Este es mi código. La variable que entra es un ulong, entonces lo convierto en una matriz de bits y luego reorganizo todos los bits y luego lo vuelvo a convertir en un ulong.

public override ulong Permutation(ulong input, int[] permuation) 
     { 
      byte[] test = BitConverter.GetBytes(input); 
      BitArray test2 = new BitArray(test); 
      BitArray final = new BitArray(test); 
      ulong x = 0; 
      ulong y = 1; 
      for (int i = 0; i < permuation.Length; i++) 
      { 
       final[i] = test2[(permuation[i]-1)]; 
      } 
      for (int i = 0; i < final.Length; i++) 
      { 

       if (final[i] == true) 
       { 
        x += (1 * y); 
       } 
       else 
       { 
        x += (0 * y); 
       } 
       y = y * 2; 
      } 
      return x; 
     }