Foros - Stratos

Programadores => General Programadores => Mensaje iniciado por: Omaddon en 30 de Julio de 2003, 10:58:55 PM

Título: Empaquetar
Publicado por: Omaddon en 30 de Julio de 2003, 10:58:55 PM
Necesito empaquetar 3 valores de 10 bits(0..1023 codificados como int o short) en una palabra de 4 bytes(int). Como deben ser las operaciones a nivel de bits para solo elegir los 10 bits menos significativos de cada componente y situarlos en el lugar de la palabra de 4 bytes correcto y despues poder leer los valores de la componente desde dicha palabra. Muchas gracias.
Título: Empaquetar
Publicado por: tywok en 31 de Julio de 2003, 12:56:20 AM
 Hola
a ver.. no es muy dificil... tienes el int a 0, para guardar el primer dato simplemente se lo sumas al int, para guardar el segundo dato y le suma al int (y<<10) y para guardar el tercero le sumas al int (z<<20). para sacarlos es muy facil, lo unico q haces es valor=(valorguardado>>(10*i))%1024; (i = 0..2).
como ves no es muy dificil, un saludo!
Título: Empaquetar
Publicado por: ethernet en 31 de Julio de 2003, 07:15:48 AM
 Y los acarreos? no sería mejor hacer un or ?
por otra parte no tendría que ser:

valor=(valorguardado>>(10*i))%1024;  --- > valor=(valorguardado>>(10*i))%0x03ff; ?

saludos
Título: Empaquetar
Publicado por: Omaddon en 31 de Julio de 2003, 01:47:44 PM
 Funciona bien si solo introduzco datos una vez. Si una vez empaquetado, necesito sobreescribir el valor de uno de los componente, da un resultado incorrecto.
Título: Empaquetar
Publicado por: tywok en 31 de Julio de 2003, 03:10:53 PM
 a ver... para introducir otro dato despues de haber guardado uno antes lo q tienes q hacer es sacarlo, es decir, restar y dejar los 10 bits a 0 para q cuando añadas otro valor se te guarde correctamente....

void ponvalor(int indice, int valor){
int antiguovalor=(valorguardado>>(10*i))%1024;
valorguardado-=antiguovalor<<(10*i);
valorguardado+=valor<<(10*i);
}
eso deberia funcionar, corregirme si me equivoco...

PD: ethernet, pq haces modulo 1023??un valor de 10 bits va de 0 a 1023, pero un modulo de 1023 va solamente hasta el 1022, asiq daria fallo en el caso de q el valor fuese 1023, x lo q el 1024 esta bien

un saludo y omaddon, dime si funciona cuando lo leas
tywok
Título: Empaquetar
Publicado por: Mars Attacks en 31 de Julio de 2003, 03:30:55 PM
 En vez de los desplazamientos yo usaría máscaras y ors para la escritura y ands para poner a 0 la parte que luego quieras reescribir con un or, tal como dice ethy.
Título: Empaquetar
Publicado por: tywok en 31 de Julio de 2003, 04:27:44 PM
 pero bueno, hacerlo con mascaras es lo mismo q hago yo, pero desde otro punto de vista... no creo q vaya mas rapido ni nada, aunque bueno, vosotros sabreis, ya q sabeis mas q yo...
un saludo
Título: Empaquetar
Publicado por: Mars Attacks en 31 de Julio de 2003, 07:28:51 PM
 Creo que los desplazamientos están al mismo nivel de velocidad que un or o un and, son funciones básicas. Y si no, en cualquier caso tendrán tiempos parecidísimos, no notarías las diferencia.

La máscara para los 10 bits más significativos sería un & 0x000003FF si no me he equivocado.
Título: Empaquetar
Publicado por: Juan Mellado en 31 de Julio de 2003, 07:30:29 PM
 
int Get(int v, int i)   //i = [0, 1, 2]
{
   return( (v >> (10 * i) ) & 0x3FF);
}

void Set(int & v, int i, int s)   //s = valor a poner
{
   int m[] = {0x3FFFFC00, 0x3FF003FF, 0x000FFFFF};

   v = (v & m[i]) | (s << (10 * i) );
}
Título: Empaquetar
Publicado por: Mars Attacks en 31 de Julio de 2003, 07:33:52 PM
 Juer, qué friki  :blink:  
Título: Empaquetar
Publicado por: Omaddon en 31 de Julio de 2003, 10:05:42 PM
 Ya funciona. Gracias a todos por vuestras respuestas.
Título: Empaquetar
Publicado por: tywok en 31 de Julio de 2003, 11:36:53 PM
 
CitarLa máscara para los 10 bits más significativos sería un & 0x000003FF si no me he equivocado.

bueno, pues para la mascara si, pq en binario es diez unos seguidos, pero si lo haces en modulo, tienes q poner el siguiente, osea, el 1024. las dos cosas estan bien (ole)

PD: omaddon, al final como lo hiciste, x simple curiosidad??

un saludo
Título: Empaquetar
Publicado por: ethernet en 01 de Agosto de 2003, 07:13:47 AM
Cita de: "tywok"
PD: ethernet, pq haces modulo 1023??un valor de 10 bits va de 0 a 1023, pero un modulo de 1023 va solamente hasta el 1022, asiq daria fallo en el caso de q el valor fuese 1023, x lo q el 1024 esta bien
Perdon, me confundí, quise poner un &  ;).  
Título: Empaquetar
Publicado por: Omaddon en 01 de Agosto de 2003, 01:15:32 PM
 El código de Juan Mellado funciona bien.

int Get(int v, int i)   //i = [0, 1, 2]
{
  return( (v >> (10 * i) ) & 0x3FF);
}


void Set(int & v, int i, int s)   //s = valor a poner
{
  int m[] = {0x3FFFFC00, 0x3FF003FF, 0x000FFFFF};

  v = (v & m) | (s << (10 * i) );
}


Lo único, es que he añadido una comprobación para evitar que en la función Set, introduzcan un valor suparior a 10bits, porque si lo hacen modificarias también la componente superior.
Título: Empaquetar
Publicado por: Mars Attacks en 01 de Agosto de 2003, 04:01:33 PM
 Juan Mellado rocks  (ole)  (ole)  (ole)  
Título: Empaquetar
Publicado por: ethernet en 01 de Agosto de 2003, 04:40:33 PM
 Cuando hacemos algo deberiamos hacerlo bien no? y si dejamos un poco de lado el orgullo coder podemos usar código de otras personas y ya que estamos hablando de videojuegos podemos recurrir a uno de los códigos de juegos que tenemos a nuestra disposición, en este caso unreal (tim sweney rocks)



*-----------------------------------------------------------------------------
FBitWriter.
-----------------------------------------------------------------------------*/

//
// Writes bitstreams.
//
struct CORE_API FBitWriter : public FArchive
{
friend struct FBitWriterMark;
public:
FBitWriter( INT InMaxBits )
: Num   ( 0 )
, Max   ( InMaxBits )
, Buffer  ( (InMaxBits+7)/8 )
, Overflowed ( 0 )
{
 guard(FBitWriter::FBitWriter);
 ArIsNet = ArIsPersistent = ArIsSaving = 1;
 unguard;
}
void SerializeBits( void* Src, INT LengthBits )
{
 guard(FBitWriter::SerializeBits);
 if( Num+LengthBits<=Max )
 {
  for( INT i=0; i<LengthBits; i++,Num++ )
   if( ((BYTE*)Src)[i/8]&(1<<(i&7)) )
    Buffer(Num/8) |= (1<<(Num&7));
   else
    Buffer(Num/8) &= ~(1<<(Num&7));
 }
 else Overflowed = 1;
 unguard;
}
void WriteInt( DWORD Result, DWORD Max )
{
 Result = INTEL_ORDER(Result);
 SerializeBits( &Result, appCeilLogTwo(Max) );
}
void WriteBit( BYTE In )
{
 guard(FBitWriter::WriteBit);
 SerializeBits( &In, 1 );
 unguard;
}
void Serialize( void* Src, INT LengthBytes )
{
 guard(FBitWriter::Serialize);
 SerializeBits( Src, LengthBytes*8 );
 unguard;
}
INT GetNumBytes()
{
 return (Num+7)/8;
}
INT GetNumBits()
{
 return Num;
}
UBOOL GetOverflowed()
{
 return Overflowed;
}
void SetOverflowed()
{
 Overflowed = 1;
}
BYTE* GetData()
{
 return &Buffer(0);
}
private:
TArray<BYTE> Buffer;
INT   Num;
INT   Max;
UBOOL Overflowed;
};


/*-----------------------------------------------------------------------------
FBitReader.
-----------------------------------------------------------------------------*/

//
// Reads bitstreams.
//
struct CORE_API FBitReader : public FArchive
{
public:
FBitReader( BYTE* Src=NULL, INT CountBits=0 )
: Num   ( CountBits )
, Buffer  ( (CountBits+7)/8 )
, Pos   ( 0 )
, Overflowed ( 0 )
{
 guard(FBitReader::FBitReader);
 ArIsNet = ArIsPersistent = ArIsLoading = 1;
 if( Src )
  appMemcpy( &Buffer(0), Src, (CountBits+7)/8 );
 unguard;
}
void SetData( FBitReader& Src, INT CountBits )
{
 guard(FBitReader::SetData);
 Num        = CountBits;
 Pos        = 0;
 Overflowed = 0;
 Buffer.Empty();
 Buffer.Add( (CountBits+7)/8 );
 Src.SerializeBits( &Buffer(0), CountBits );
 unguard;
}
void SerializeBits( void* Dest, INT LengthBits )
{
 guard(FBitReader::SerializeBits);
 if( Pos+LengthBits<=Num )
 {
  for( INT i=0; i<LengthBits; i++,Pos++ )
   if( Buffer(Pos/8)&(1<<(Pos&7)) )
    ((BYTE*)Dest)[i/8] |= (1<<(i&7));
   else
    ((BYTE*)Dest)[i/8] &= ~(1<<(i&7));
 }
 else SetOverflowed();
 unguard;
}
DWORD ReadInt( DWORD Max )
{
 INT Result=0;
 SerializeBits( &Result, appCeilLogTwo(Max) );
 return INTEL_ORDER(Result);
}
BYTE ReadBit()
{
 BYTE Bit=0;
 SerializeBits( &Bit, 1 );
 return Bit;
}
void Serialize( void* Dest, INT LengthBytes )
{
 guard(FBitReader::Serialize);
 SerializeBits( Dest, LengthBytes*8 );
 unguard;
}
UBOOL AtEnd()
{
 return Overflowed || Pos==Num;
}
UBOOL GetOverflowed()
{
 return Overflowed;
}
void SetOverflowed()
{
 Overflowed = 1;
}
BYTE* GetData()
{
 return &Buffer(0);
}
INT GetNumBytes()
{
 return (Num+7)/8;
}
INT GetNumBits()
{
 return Num;
}
INT GetPosBits()
{
 return Pos;
}
private:
TArray<BYTE> Buffer;
INT   Num;
INT   Pos;
UBOOL Overflowed;
};


ROCKS, ROCKS UNREAL ROCKS !
Título: Empaquetar
Publicado por: Juan Mellado en 01 de Agosto de 2003, 06:59:27 PM
 Mars :P  
Título: Empaquetar
Publicado por: Mars Attacks en 01 de Agosto de 2003, 09:18:19 PM
 Esto demuestra una de las Leyes de Murphy que reza que cualquier cosa sencilla puede explicarse de manera que resulte incomprensible  :ph34r:  
Título: Empaquetar
Publicado por: ethernet en 01 de Agosto de 2003, 10:22:34 PM
 A mi me resulta sencillo leer ese codigo. Lo mejor es enemigo de lo bueno