🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: es.comp.os.linux.programacion
10 messages
10 total messages Started by CJR Sun, 05 Sep 1999 00:00
Una ayuda please :), piruleta por medio.
#18498
Author: CJR
Date: Sun, 05 Sep 1999 00:00
60 lines
2427 bytes
Los programadores me han preguntado que hace esta función.
Una especie de apuesta, piruleta por recompensa.

La cuestión está en ver quien es el primero que sabe que hace esta
función :


void send(int* to, int* from, int count)
{
        int n = (count+7)/8;
        switch(count%8) {
        case 0: do { *to++ = *from++;
       case 7:         *to++ = *from++;
       case 6:         *to++ = *from++;
       case 5:         *to++ = *from++;
       case 4:         *to++ = *from++;
       case 3:         *to++ = *from++;
       case 2:         *to++ = *from++;
       case 1:         *to++ = *from++;
                } while (--n>0);
        }
}

¿? con una explicación sencilla creo lo entenderé. (ojo que de
programación no tengo ni idea, solo trato de relacionarlo con lo poco
que se de basic y mis conocimientos de 4 primeras paginas de libro de C)
Supongo que los "case" son estructuras de tipo condicinal como las de
basic IF CASE. 
Int creo que define un numero entero, luego la linea int n =
(count+7)/8, define un número "n" que va en funcion de 
void send(int* to, int* from, int count)

Esto ya no tengo ni idea de que puede ser, supongo que se es una especie
de bucle, por la sintaxis... :?

to-from... ?

Lo del while (--n>0) creo que sera para que ocurra esto siempre y cuando
--n (que no se si sera como (-1)²), se a mayor que cero... 

El caso es que utilidad, utilidad no la encuentro nada...

Ojin que el pollo este ha estado en olimpiadas de programación, y no se
hasta donde podra llegar su calenturienta mente :)

Un saludo y gracias.

-- 

	   Carlos J. Ramos (CJR)
	  Us. Reg. Linux #102.291
____________________________________________
	 CCR Software & Marketing
     Primera empresa española en crear
    software de gestión para GNU/Linux.
Re: Una ayuda please :), piruleta por medio.
#18435
Author: Antonio Luque Estepa
Date: Mon, 06 Sep 1999 00:00
58 lines
2892 bytes
On Sun, 05 Sep 1999 20:17:15 +0200, CJR <cj.ramos@teleline.es> wrote:
> Los programadores me han preguntado que hace esta funci�n.
> Una especie de apuesta, piruleta por recompensa.
> 
> La cuesti�n est� en ver quien es el primero que sabe que hace esta
> funci�n :
> 
> 
> void send(int* to, int* from, int count)
> {
>         int n = (count+7)/8;
>         switch(count%8) {
>         case 0: do { *to++ = *from++;
>        case 7:         *to++ = *from++;
>        case 6:         *to++ = *from++;
>        case 5:         *to++ = *from++;
>        case 4:         *to++ = *from++;
>        case 3:         *to++ = *from++;
>        case 2:         *to++ = *from++;
>        case 1:         *to++ = *from++;
>                 } while (--n>0);
>         }
> }
> 
> �? con una explicaci�n sencilla creo lo entender�. (ojo que de
> programaci�n no tengo ni idea, solo trato de relacionarlo con lo poco
> que se de basic y mis conocimientos de 4 primeras paginas de libro de C)

Lo primero, recomendarte que aprendas algo de C, que siempre viene bien.

Lo segundo, aun cuando sepas programar en C, lo mas probable es que tampoco
entiendas del todo esta construccion.

Lo siguiente esta dirigido a la gente que sabe C:

Esto es un bucle que sirve unicamente para copiar una serie de bytes desde
'from' hasta 'to'. Es conocido como el Dispositivo de Duff (Duff's device),
y fue dise�ado por Tom Duff cuando trabajaba en Lucasfilm.

Aunque parezca increible, es legal intercalar los 'case' dentro del bucle
'do'.

Cuando Duff hizo publico este codigo, afirmo que la sintaxis del 'switch' en
C habia sido polemica durante mucho tiempo, en particular la caracteristica
del paso (fall through) a otro 'case' si no hay 'break'. Duff dijo que "este
codigo es un argumento en ese debate, pero no estoy seguro de si es a favor
o en contra".

En cualquier caso, es una de la construcciones mas rebuscadas que se han
hecho hasta ahora en C.

Saludos,

-- 
                    Antonio Luque Estepa 
	   Escuela Superior de Ingenieros de Sevilla
	              aluque@esi.us.es
		http://www.esi.us.es/~aluque
Re: Una ayuda please :), piruleta por medio.
#18437
Author: *puntero_loco
Date: Mon, 06 Sep 1999 00:00
65 lines
3165 bytes
El Sun, 05 Sep 1999 20:17:15 +0200, CJR <cj.ramos@teleline.es> escribi�:
|Los programadores me han preguntado que hace esta funci�n.
|Una especie de apuesta, piruleta por recompensa.
|
|La cuesti�n est� en ver quien es el primero que sabe que hace esta
|funci�n :
|

|void send(int* to, int* from, int count)
|{
|        int n = (count+7)/8; // 1
|        switch(count%8) {    // 1
|        case 0: do { *to++ = *from++; // 2
|       case 7:         *to++ = *from++; 
|       case 6:         *to++ = *from++;
|       case 5:         *to++ = *from++;
|       case 4:         *to++ = *from++;
|       case 3:         *to++ = *from++;
|       case 2:         *to++ = *from++;
|       case 1:         *to++ = *from++;
|                } while (--n>0);
|        }
|}
|

1) Tomamos el resto de dividir count entre 8. Con este resto: Salga lo que
salga copiamos el contenido de la posici�n de memoria from en la direcci�n to.
Y esto lo hacemos mientras (while) n sea mayor que cero decrement�ndolo cada
vez. Por lo tanto solo copiamos aproximadamente 1/8 parte de count. 

2) Sin embargo lo del ^Z creo que es una vacilada, que el sabr� lo que hace
(con el editor que utilize), pero que no es parte del C, al menos que yo sepa.
Sin embargo, por la estructura del programa creo que lo que ese ^Z hace es que
salte a la siguiente linea y antes de interpretar lo que queda, con lo que el
programa sin chorraditas quedar�a:

void send(int* to, int* from, int count)
{
        int n = (count+7)/8; 
        switch(count%8) {    
        case 0: do { 
		*to++ = *from++; 
		} while (--n>0);
       case 7:         *to++ = *from++;
       case 6:         *to++ = *from++;
       case 5:         *to++ = *from++;
       case 4:         *to++ = *from++;
       case 3:         *to++ = *from++;
       case 2:         *to++ = *from++;
       case 1:         *to++ = *from++;              
        }
}

As� esta mas claro: Si el resto de count/8 es igual a cero entonces copia el
valor de (count+7)/8 posiciones de memoria con el tama�o de un entero de from
a to. Sino, s�lo copia una posici�n de memoria.

Me debes una piruleta.
-- 
 /-----------------------------\
|      *puntero_loco            |  
|     Debian 2.1 Slink          |
|  jajsNOSPAM@retemail.es       |
| http://personal5.iddeo.es/jajs|
 \-----------------------------/
Re: Una ayuda please :), piruleta por medio.
#18438
Author: Ignacio Arenaza
Date: Mon, 06 Sep 1999 00:00
41 lines
1817 bytes
>>>>> "CJR" == CJR  <cj.ramos@teleline.es> writes:

Reformateando ligeramente, queda asi:

    CJR> void send(int* to, int* from, int count)
    CJR> {
    CJR>         int n = (count+7)/8;
    CJR>         switch(count%8) {
    CJR>         case 0:
    CJR>                 do { *to++ = *from++;
    CJR>              case 7:         *to++ = *from++;
    CJR>              case 6:         *to++ = *from++;
    CJR>              case 5:         *to++ = *from++;
    CJR>              case 4:         *to++ = *from++;
    CJR>              case 3:         *to++ = *from++;
    CJR>              case 2:         *to++ = *from++;
    CJR>              case 1:         *to++ = *from++;
    CJR>              } while (--n>0);
    CJR>         }
    CJR> }

Si 'count' no es multiplo de 8, no hace absolutamente nada. Si es
multiplo de 8, entonces copia de la direccion 'from' a la direccion
'to' tantos enteros como indique 'count'. Es una forma muy rara de
hacerlo, pero cada uno programa como quiere. De hecho, quitando toda
la parafernalia para despistar, es lo mismo que:

	void send(int* to, int* from, int count)
	{
		if (count%8)
			while ((count--) > 0)
				*to++ = *from++;
	}

Bastante mas corto, no?

Saludos. I�aki.

-- 
  PGP Key available at http://personales.jet.es/inaki.arenaza/pgpkey.html
  Linux Registered User #44369
Re: Una ayuda please :), piruleta por medio.
#18439
Author: quasimodo_TEM
Date: Tue, 07 Sep 1999 00:00
11 lines
839 bytes
quasimodo_TEM wrote:

> void send(int* to, int* from, int count)
> {
>         int n = (count+7)/8;
>         do {  <<<< ----------------- OOPS!!!  se me ha escapado esta
> linea
>         switch(count%8) {
>         case 0:  do

> ... etc.
Re: Una ayuda please :), piruleta por medio.
#18440
Author: quasimodo_TEM
Date: Tue, 07 Sep 1999 00:00
92 lines
3266 bytes
*puntero_loco wrote:

>  el programa sin chorraditas quedar�a:
>
> void send(int* to, int* from, int count)
> {
>         int n = (count+7)/8;
>         switch(count%8) {
>         case 0: do {
>                 *to++ = *from++;
>                 } while (--n>0);
>        case 7:         *to++ = *from++;
>        case 6:         *to++ = *from++;
>        case 5:         *to++ = *from++;
>        case 4:         *to++ = *from++;
>        case 3:         *to++ = *from++;
>        case 2:         *to++ = *from++;
>        case 1:         *to++ = *from++;
>         }
> }

Discrepo: empleando una sintaxis m�s ortodoxa, su
equivalente ser�a esto:

void send(int* to, int* from, int count)
{
        int n = (count+7)/8;
        do {
        switch(count%8) {
        case 0:  do {
                  *to++ = *from++;
                  *to++ = *from++;
                  *to++ = *from++;
                  *to++ = *from++;
                  *to++ = *from++;
                  *to++ = *from++;
                  *to++ = *from++;
                  *to++ = *from++;
             } while (--n>0);
             break;
        case 1:  do {
                  *to++ = *from++;
                  *to++ = *from++;
                  *to++ = *from++;
                  *to++ = *from++;
                  *to++ = *from++;
                  *to++ = *from++;
                  *to++ = *from++;
             } while (--n>0);
             break;
         case 2: do {
                  *to++ = *from++;
                  *to++ = *from++;
                  *to++ = *from++;
                  *to++ = *from++;
                  *to++ = *from++;
                  *to++ = *from++;
             } while (--n>0);
             break;
         case 3: do {
                  *to++ = *from++;
                  *to++ = *from++;
                  *to++ = *from++;
                  *to++ = *from++;
                  *to++ = *from++;
             } while (--n>0);
             break;
         case 4: do {
                  *to++ = *from++;
                  *to++ = *from++;
                  *to++ = *from++;
                  *to++ = *from++;
             } while (--n>0);
             break;
         case 5: do {
                  *to++ = *from++;
                  *to++ = *from++;
                  *to++ = *from++;
             } while (--n>0);
             break;
         case 6: do {
                  *to++ = *from++;
                  *to++ = *from++;
             } while (--n>0);
             break;
         case 7: do {
                  *to++ = *from++;
             } while (--n>0);
         }
 }

... que SI es inteligible.
Re: Una ayuda please :), piruleta por medio.
#18441
Author: quasimodo_TEM
Date: Tue, 07 Sep 1999 00:00
4 lines
772 bytes
y adem�s he puesto mal la secuencia de n�meros de los cases:
en lugar de 0,1,2,...7 es 0,7,6,...,1.

Es que no son horas para hacer estas cosas...
Re: Una ayuda please :), piruleta por medio.
#18442
Author: Manolo Soft
Date: Tue, 07 Sep 1999 00:00
93 lines
4315 bytes
CJR wrote:
> void send(int* to, int* from, int count)
> {
>         int n = (count+7)/8;
>         switch(count%8) {
>         case 0: do { *to++ = *from++;
>        case 7:         *to++ = *from++;
>        case 6:         *to++ = *from++;
>        case 5:         *to++ = *from++;
>        case 4:         *to++ = *from++;
>        case 3:         *to++ = *from++;
>        case 2:         *to++ = *from++;
>        case 1:         *to++ = *from++;
>                 } while (--n>0);
>         }
> }

Esto parece ser un programa que copia "count" enteros desde
el vector "from" al vector "to". Solo que complicandose la
vida y con el caso particular de que si se ejecuta con count=0, 
copia 8 enteros.

La forma de interpretarla es teniendo en cuenta que no existe
"break"s en el switch-case. Eso significa que si count%8 es
0, se ejecutaran los ocho *to++ = *from++ que son los que
hacen la copia. Si es 7, se ejecutara 7 veces, si 6 ,6 veces,etc.

El int n = (count+7)/8 lo he visto muchas veces en ensamblador
del DOS. Se usaba para calcular la memoria que debías reservar
en segmentos (bloques de 16 bytes) para una cantidad de elementos
variable. Se hacía segmentos=(bytes+15)/16 pues tiene la bonita
propiedad de que si vas a reservar 0 bytes, te salen 0 segmentos.
En cuanto necesitabas un byte, ya te salía un segmento, igual
para 2 bytes, 3.... hasta 16. Cuando eran 17 ya te salían dos
segmentos (como debía ser). Es una forma de calcular ((n-1)/8)+1
y es el número más uno de copias de bloques de 8 bytes que se 
realizarán.

El operador % sirve para hallar el resto de la division y el / 
es para la división entera. 

Así, si count es 1, n es 1 y al llegar al switch salta al case 1
copia un byte,y al llegar al bucle que cierra, la condición no se 
cumple por lo que termina y acaba la rutina.

Si es count es 2, igual solo que saltará al case 2 y copiará dos
bytes.

Así, igual hasta count = 7. Cuando vale 8, el resto de la división
entre 8 es cero, pero n sigue valiendo 1, por lo que salta al 
case 0, hace las 8 copias y acaba la rutina.

Cuando count=9, n ya vale 2 y el resto de la división 1. Por tanto
salta al case 1 haciendo una copia con lo que llega al final del
bucle. La condición --n>0 se cumple por tanto el programa se va
a despues del do, que es donde comienza el bucle. En el bucle hará
8 copias más por lo que en total habrá copiado nueve bytes, como
debe ser. Así sucesivamente.

El caso particular count=0, hace que el resto salga 0, por lo que
se ejecuta el do y las 8 copias. Y al no cumplirse la condición del
while acaba la rutina.

Así, el programa hace primero tantas copias como el resto de count
entre 8 (salvo en caso de resto cero en el que hace 8 copias).
Despues hace (count/8) veces 8 copias de bytes, salvo en caso de
que count sea multiplo de 8, en la que hace una vez menos.
Así si count no es multiplo de 8 copia este número de elementos:

resto(count/8)+8*cociente(count/8)

Que facilmente se demuestra que es igual a count. Si count es
multiplo de 8 copia esta cantidad de numeros:

8+(cociente(count/8)-1)*8

Que se demuestra es igual a count. Salvo en el caso particular
del count=0 en el que se copian 8 enteros ya que que el do
siempre se ejecuta independientemente de que la condición del
while no se cumpla de salida.

Saludos...

-- 
Manuel Constantino - MANOLO SOFT
Email: manolo@manolosoft.dhis.org
Re: Una ayuda please :), piruleta por medio.
#18457
Author: *puntero_loco
Date: Wed, 08 Sep 1999 00:00
18 lines
1289 bytes
El Tue, 07 Sep 1999 00:36:38 +0200, quasimodo_TEM <kuskiSKIPTHIS@euskalnet.net> escribi�:
|y adem�s he puesto mal la secuencia de n�meros de los cases:
|en lugar de 0,1,2,...7 es 0,7,6,...,1.
|
|Es que no son horas para hacer estas cosas...

Si, programar y leer las news a estas horas deber�a estar prohibido... y
encima hacemos las dos cosas a la vez en este thread.


-- 
 /-----------------------------\
|      *puntero_loco            |  
|     Debian 2.1 Slink          |
|  jajsNOSPAM@retemail.es       |
| http://personal5.iddeo.es/jajs|
 \-----------------------------/
.
Solución [era lo de la piruleta ;]
#18465
Author: CJR
Date: Thu, 09 Sep 1999 00:00
81 lines
3371 bytes
*puntero_loco escribió:
> 
> El Tue, 07 Sep 1999 00:36:38 +0200, quasimodo_TEM <kuskiSKIPTHIS@euskalnet.net> escribió:
> |y además he puesto mal la secuencia de números de los cases:
> |en lugar de 0,1,2,...7 es 0,7,6,...,1.
> |
> |Es que no son horas para hacer estas cosas...
> 
> Si, programar y leer las news a estas horas debería estar prohibido... y
> encima hacemos las dos cosas a la vez en este thread.
> 
> --
>  /-----------------------------\
> |      *puntero_loco            |
> |     Debian 2.1 Slink          |
> |  jajsNOSPAM@retemail.es       |
> | http://personal5.iddeo.es/jajs|
>  \-----------------------------/
> ..

Esta es la respuesta correcta :

**************************************************************
La verdadera utilidad de la función esta es la optimización.

El único objetivo del programa es la copia
de "count" enteros, pero dividiendo la copia en grupos de 8.
Cada grupo de 8 enteros tiene asociadas 8 operaciones de copia
consecutivas. El compilador traducirá estas operaciones a 
código máquina del procesador y el resultado serán varias 
instrucciones seguidas. Además, si la arquitectura interna
del procesador está "segmentada" o dividida en unidades 
funcionales paralelas es posible que varias de las operaciones
anteriores (y tras una reordenación) se realicen simultaneamente.

La utilización de un bucle lleva implícita una variable contador
de las pasadas del bucle. La copia de un array de enteror necesitaría
"count" operaciones (suma o resta de 1) del contador. La susodicha 
función hace que sólo se necesiten "count" / 8 operaciones de suma
para la gestión del bucle. Por ejemplo, supongamos la copia de
128 Kb enteros. Entonces nos ahorraríamos 128 Kb - 128 Kb / 8 =
(7 * 128 Kb) / 8 = 7 * 16 Kb = 113 Kb operaciones de suma o resta.

¿ A que merece la pena ?

La función la encontré en un libro y aparentemente se usaba en
un controlador de dispositivo.

-- 
            _                |\ 
           / \   __  /\_    /  \ _
         _/   \ /  \/   \__/    V \_
        /      V                    \_
Luis Paul Tomillo       luispaul@bbvnet.com
***************************************************************


Bueno, pues aqui nos quedamos :)

Muchas gracias a todos los que habeis contestado al mensaje :)

-- 

	   Carlos J. Ramos (CJR)
	  Us. Reg. Linux #102.291
____________________________________________
	 CCR Software & Marketing
     Primera empresa española en crear
    software de gestión para GNU/Linux.
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads