Newsgroup: it.comp.lang.c
Titolo: shift circolare

Re,
qualcuno conosce un modo piu' veloce del seguente per implementare
uno shift circolare? Io ho fatto cosi':
#define CSH_L(x, y) (x = (x << y) | (x >> 32-y))
#define CSH_R(x, y) (x = (x >> y) | (x << 32-y))
(32 si deve sostituire con sizeof(x)*8 per essere semi-portabile)
Ma e' davvero un peccato perche' sul pentium ci sono delle istruzioni
apposite per ottenere uno shift circolare. Sapete come mai il C
non possiede qualcosa tipo gli operatori ">>>" e "<<<"?
A parte l'assembler inlined conoscete un metodo piu' veloce per
eseguire la stessa operazione?
grazie in anticipo,
antirez

 eseguire la stessa operazione?
Una macro che, inclusa in un header che poi devi ricordarti di includere,
usi l'assembler inline, oppure una procedura che faccia lo stesso.
Se ti sembra banale, pensa che molte delle funzioni delle librerie standard
che usi probabilmente sono fatte cosě.
--
Alessandro Monti

 uno shift circolare?
Questo č ciň che ho trovato su Thinking in C++ di Bruce Eckel:
//: C03:Rotation.cpp {O}
// Perform left and right rotations
unsigned char rol(unsigned char val) {
  int highbit;
  if(val & 0x80) // 0x80 is the high bit only
    highbit = 1;
  else
    highbit = 0;
  // Left shift (bottom bit becomes 0):
  val <<= 1;
  // Rotate the high bit onto the bottom:
  val |= highbit;
  return val;
}
unsigned char ror(unsigned char val) {
  int lowbit;
  if(val & 1) // Check the low bit
    lowbit = 1;
  else
    lowbit = 0;
  val >>= 1; // Right shift by one position
  // Rotate the low bit onto the top:
  val |= (lowbit << 7);
  return val;
} ///:~
EMG

 Questo č ciň che ho trovato su Thinking in C++ di Bruce Eckel:
Beh, Eckel assume che un char abia 8 bits - il che e' sbagliato.  Io
avrei usato al posto di << 7 (nella seconda procedura) << (CHAR_BIT-1);
ed al posto di 0x80 (nella prima) un #define HIGH_BIT (1 << (CHAR_BIT-1)).
Un compilatore appena appena decente dovrebbe risolvere le costanti a
compile time.  (CHAR_BIT e' definito in <limits.h> appositamente per
questo genere di cose).
-- 
Maurizio Loreti                         
http://www.pd.infn.it/~loreti/mlo.html
Univ. of Padova, Dept. of Physics - Padova, Italy            
lor...@pd.infn.it

 Beh, Eckel assume che un char abia 8 bits - il che e' sbagliato.
Ehm, scusate ma avevo appunto dimenticato di aggiungere che andava fatta
questa modifica. In effetti l'esempio di codice č riportato in uno dei
primissimi capitoli per cui tante sottigliezze non erano ancora state
trattate.
EMG

 wrote:
:> A parte l'assembler inlined conoscete un metodo piu' veloce per
:> eseguire la stessa operazione?
: Una macro che, inclusa in un header che poi devi ricordarti di includere,
: usi l'assembler inline, oppure una procedura che faccia lo stesso.
Sure, puo' essere una buona soluzione se si vuole utilizzare l'assembler.
A dire il vero mi viene voglia di fare una patch al GCC per fargli
supportare <<< e >>>
Comunque secondo me sarebbe davvero il caso di proporlo come
standard C, anche se qualche tempo fa aveva meno senso ora
lo shift circolare e' molto usato (perche' e' molto piu'
usata la crittografia), e Intel ha una istruzione apposita,
e Intel e' il processore piu' usato e... ;))
<SEMIOT> Sapete se esiste una istruzione per eseguire lo shift circolare
su Motorola, PowerPC, Alpha eccetera. E' una cosa che si trova
solo nel CISC? </SEMIOT>
Ho visto la soluzione proposta da Think in C++ (o del genere) grazie
ad EMG, purtroppo e' estremamente lenta, ma conferma che la macro
che ho scritto e' una discreta soluzione, anche perche' ho
trovato questo dentro sha1.c di Steve Reid:
#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
che e' praticamente identico.
Anche se si rischia che alcuni compilatori vadano piu' veloci
invertendo le parti che sono separate da '|'.
ciao,
antirez

 #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
Sul Motorola 68000 (15 anni fa!) c'erano, per cui suppongo anche nei successivi.
O chiedevi Motorola RISC? (Nin zo!)
Ciao
        gpb