Newsgroup: it.comp.lang.delphi
Titolo: Int64 e ciclo for

D2005 non permette di compilare la seguente affermendo che nel for e' 
necessario un "ordinal", in sostanza non accetta la n: Int64???
function TUdpCmd.CheckSum: Int64;
var n: Int64; Point: PByte;
begin
Result:=0;
Point:=DataBuff.Memory;
for n:=0 to DataBuff.Size-1 do
  begin
  Result:=Result+Point^;
  Inc(Point);
  end;
end;
Giorgio Padoan 

 necessario un "ordinal", in sostanza non accetta la n: Int64???
Non accetta l'intero a 64 bit come indice del for e questa costituisce una
delle tante incongruenze di Delphi.
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

for n:=0 to DataBuff.Size-1 do
Proprio perché è a 32 bit un buffer di memoria - anche in un 
TMemoryStream - non può essere più grande di max(longint), anzi, 
difficile superare i 2/3GB. Quindi perché usare un Int64?
Ci sono anche funzioni di checksum migliori...
--- posted by geoForum on 
http://www.delphiedintorni.it

 [...]Quindi perché usare un Int64?
A Delphi purtroppo manca la caratteristica di fornire un tipo per la
"size" a seconda della classe usata e la possibilità di "iterare" sugli
elementi usando degli iteratori (ce l'ha persino Java, sic!). Si è portati
a pensare di usare un Int64 perché la proprietà Size di un TStream è,
appunto, Int64.


 elementi usando degli iteratori (ce l'ha persino Java, sic!). [...]
Con "iteratori" ti riferisci a ciò che è possibile sfruttare con il
costrutto *for...in*? O si tratta di qualcos'altro?
Ciao (e buon Ferragosto!) :-)
   Marco.
-- 
MARCO BREVEGLIERI
  (
http://www.marco.breveglieri.name
)

costrutto *for...in*? O si tratta di qualcos'altro?
Mi riferisco a questo (C++):
std::vector<T> v;
for (std::vector<T>::iterator it = v.begin();
     it != v.end();
     it++) {
  //...
  //... *it č l'elemento corrente...
  //... 
}
oppure (Java):
ArrayList list;
Iterator it=list.iterator();
while (it.hasNext()) {
  // ...
  // it.next() č l'elemento corrente...
  // ...
}

> Ci sono anche funzioni di checksum migliori...
Me ne indicheresti qualcuna, purche' non troppo lenta ripetto la consueta?
Grazie, Giorgio 

>std::vector<T> v;
Non avendo ancora i template devi accontentarti del for..in. Che non so 
se funzioni con gli stream :)


 Non avendo ancora i template[...]
La programmazione generica non c'entra. Java possiede gli iteratori da
molto prima che venissero introdotti i "generics" (presenti da pochissimo,
peraltro). In ogni caso, il discorso degli iteratori sottolineava solo la
possibilità di scorrere qualsiasi "container" in maniera uniforme (senza
far riferimento ad alcun indice e quindi alcun tipo per l'indice). Per gli
stream, invece, vale il discorso del tipo dell'indice. In Delphi si è
indecisi se usare Integer o Int64 (si dovrebbe usare Int64 perché la
proprietà Size del TStream è di questo tipo) mentre in altri linguaggi è
stato definito un tipo apposta per le dimensioni (vedi il size_t di C) e
in altri addirittura si distingue il tipo in base alla classe, vedi in C++:
    std::vector<T> v;
    ...
    for (std::vector<T>::size_type i = 0;
         i < v.size();
         i++)


>stream, invece, vale il discorso del tipo dell'indice. In Delphi si è
Per gli stream l'interfaccia è generica (solo nella gerarchia degli 
stream, ovviamente) - basta usare read finchè restituisce che non ci 
sono più byte da leggere. Se avesse scritto:
Point: byte;
while DataBuff.Read(Point, 1) > 0 do
begin
  Result := Result + Point;
end;
non avrebbe avuto problemi di tipo di size o di tipo dello stream, al di 
là dell'efficienza del codice. Sì può anche creare una classe stream che 
supporti in, non credo l'abbiano fatto già. Chi è che parlava di "non 
finito borlandesco"?


 sono piů byte da leggere.
Come fare a leggere uno stream in maniera alternativa credo sia noto.
La questione era sul tipo dell'indice.


 
Ho trovato questo 
algoritmo di checksum (Fletcher's checksum) ma non mi tornano le due righe 
sotto: len non dovrebbe diventare negativo, invece se len > 360 -> tle=360 
-> len=tlen-len diventa negativo? 
Giorgio
unsigned tlen = 
len > 360 ? 360 : len;
len -= tlen;
const uint16_t *data;  
/* Pointer to the data to be summed */
       
size_t len;      /* Length in 16-bit words 
*/
       uint32_t sum1 = 0xffff, sum2 = 
0xffff;
       while (len) 
{
               
unsigned tlen = len > 360 ? 360 : 
len;
               
len -= 
tlen;
               
do 
{
                       
sum1 += 
*data++;
                       
sum2 += 
sum1;
               
} while 
(--tlen);
               
sum1 = (sum1 & 0xffff) + (sum1 >> 
16);
               
sum2 = (sum2 & 0xffff) + (sum2 >> 
16);
       
}
       /* Second reduction step to reduce 
sums to 16 bits */
       sum1 = (sum1 & 
0xffff) + (sum1 >> 16);
       sum2 = 
(sum2 & 0xffff) + (sum2 >> 
16);
       return sum2 << 16 | 
sum1;



 len -= tlen;
x-=y significa x=x-y non x=y-x quindi, se len>360, si ha che tlen=360,
quindi len = len-tlen > 0


"Andrea Laforgia" <x...@xx.xx> ha scritto nel messaggio 
news:fa1obj$538$1...@news.newsland.it...

Hai ragione.
Le forme abbraviate mi sono del tutto antipatiche... Giorgio 

 end;
Prova a confrontare la differenza di tempo impiegato tra le istruzioni 
DataBuff.Read(B,1) e quella con l'uso dei puntatori, naturalmente iterata 
per la dimensioni del buffer, vedrai che il .Read in certi casi e' del tutto 
improponibile.
Giorgio 

improponibile.
Il codice della Read di TMemoryStream è già piuttosto ottimizzato, 
utilizzando Move() e Inc(). L'overhead è dato dai controlli che fa 
poiché non legge un solo byte per volta e quindi deve evitare di leggere 
oltre la fine dello stream, e dal fatto che chiami un metodo e la CALL 
ha un overhead - purtroppo non sembra dichiarata inline cosa che 
migliorerebbe le prestazioni.
Comunque se è per questo la tua routine è ulteriormente ottimizzabile:
for i := 0 to DataBuff.Size -1 do
  Inc(Result, PByteArray(DataBuff.Memory)^[i]);
(PByteArray e TByteArray li trovi definiti in System o SysUtils, non mi 
ricordo di preciso). Eliminando un'assegnazione e un incremento di 
puntatore è probabilmente più veloce.
Si può incrementare ulteriormente utilizzando un cast con valori più 
grandi di un byte, ma c'è da tenere presente cosa succede con gli ultimi 
byte.
Utilizzando la Read() scriverei:
BufSize = 2048
Buf: Pointer;
BytesRead: Integer;
GetMem(Buf, BufSize);
try
  BytesRead := DataBuff.Read(Buf^, BufSize); 
  while BytesRead > 0 do
  begin
    for i := 0 to BytesRead -1 do
      Inc(Result, PByteArray(Buf)^[i];
   BytesRead := DataBuff.Read(Buf^, BufSize); 
  end;
finally
  FreeMem(Buf, BufSize);
end;
Con la giusta dimensione del buffer probabilmente non è molto più lenta 
e funziona con qualsiasi stream, non solo un memorystream.
