ONCE.23. OPERACIONES BINARIAS LÓGICAS

Bajo esta sección se agrupa una serie de funciones de AutoLISP que realizan operaciones a nivel binario. Esto quiere decir que, aunque admiten que se indiquen los números en decimal o en hexadecimal, los consideran como binarios (conjunto de unos y ceros). Su utilidad es por tanto muy específica.

NOTA: La explicación exhaustiva del sistema binario (funcionamiento, operaciones, conversiones...) o del álgebra de Boole (tablas de verdad, verdad y falsedad...) escapa a los objetivos de este curso. Aquí nos limitaremos única y exclusivamente a mostrar las funciones AutoLISP que manejan cifras binarias a nivel lógico.

(~ valor_numérico)

Esta función devuelve la negación lógica (NOT) de una cifra binaria, es decir el complemento a 1. El número indicado ha de ser entero. Veamos unos ejemplos:

(~ 5) devuelve –6
(~ -6)
devuelve 5
(~ 0)
devuelve –1
(~ 54)
devuelve –55

Recordemos que el carácter ~ (tilde) corresponde al código ASCII 126, por lo que se escribe con la combinación ALT+126.

(BOOLE operación [valor_entero1 valor_entero2...])

BOOLE realiza una operación booleana general a nivel binario. El argumento operación es un número entre 0 y 15 que representa una de las 16 operaciones booleanas posibles. Los valores enteros indicados se combinarán bit a bit de acuerdo con la función booleana especificada.

Esto significa que el primer bit del primer entero se combina con el primer bit del segundo entero y así sucesivamente. El resultado final será 0 ó 1 según la tabla de verdad de la función booleana indicada. Lo mismo con el resto de bits de los valores enteros especificados. La combinación final de todos los bits resultantes dará el número entero final que devuelve la función.

Algunos de los valores de operación se corresponden con las operaciones booleanas estándar. Estos valores, sus correspondencias y el resultado cierto (1) dependiendo de los números enteros se muestran en la tabla siguiente:

Valor de operación ------ Booleana estándar ------- Resultado es 1 si...

--------------------------------------------------------------------------------

1 ------------------------ AND (Y lógico) ------------- todos los bits de entrada
------------------------------------------------------ son
1 (A y B...).

6 ------------------------ XOR (O lógico exclusivo) ---- sólo uno de los bits de
------------------------------------------------------ entrada es
1 (o A o B...).

7 ------------------------ OR (O lógico) -------------- al menos 1 de los bits de
------------------------------------------------------ entrada es
1 (A o B...).

8 ------------------------ NOT (NO lógico) ------------ ninguno de los bits de
------------------------------------------------------ entrada es
1 (no A no B...).

Veamos un ejemplo. Supongamos que escribimos:

(BOOLE 6 8 12 7)

Esto equivale a un XOR de:

8 que en binario es 1000

12 que en binario es 1100

7 que en binario es 111

Por lo tanto, la operación XOR se realizará cuatro veces:

XOR de 1 1 0 devuelve 0

XOR de 0 1 1 devuelve 0

XOR de 0 0 1 devuelve 1

XOR de 0 0 1 devuelve 1

El resultado final es el número binario 0011 que equivale al 3 decimal. Por lo tanto:

(BOOLE 6 8 12 7) devuelve 3


(LOGAND [valor_entero1 valor_entero2...])

Esta función realiza un Y lógico (AND) a nivel binario de los valores indicados. Estos valores han de ser enteros; el resultado es también un entero.

En un caso particular de operación booleana con BOOLE, LOAGAND equivale a hacer BOOLE 1. Ejemplo:

(LOGAND 5 7 12 14) devuelve 4

(LOGIOR [valor_entero1 valor_entero2...])

Realiza un O lógico (OR) a nivel binario. Los valores serán enteros y el resultado también (equivale a BOOLE 7). Ejemplo:

(LOGIOR 1 4 9) devuelve 13


(LSH valor_entero número_bits)

Esta función devuelve el desplazamiento a nivel binario de un registro del número entero indicado en un valor del número de bits especificado como segundo argumento. Si éste es positivo, el entero se desplaza hacia la izquierda. Si el número de bits es negativo, el entero se desplaza a la derecha. Los dígitos que faltan entran como ceros, y se pierden los dígitos salientes.

En la siguiente tabla se muestran varios ejemplos donde se indica en primer lugar la función AutoLISP, después el número entero original indicado en la función; a continuación el binario equivalente a dicho entero; después el valor del desplazamiento especificado; a continuación el binario resultante una vez aplicado ese desplazamiento; por último el entero equivalente a ese binario, que es el resultado final que devuelve LSH:

Función ---- E ----- Binario ----- Desplazam. ------- Binario res. -- Entero res.

----------------------------------------------------------------------------------

(LSH 2 1) - 2 --- 10 --------- 1 -------------- 100 -------- 4

(LSH 2 -1)- 2 --- 10 --------- -1 ------------- 1 ---------- 1

(LSH 40 2)- 40 -- 101000 ----- 2 -------------- 10100000 --- 160

(LSH 11 -1)-11 -- 1011 ------- -1 ------------- 101 -------- 6

 

ONCE.24. GESTIÓN DE LA MEMORIA

Esta última sección contiene funciones de AutoLISP que gestionan la memoria disponible para almacenar las variables, definiciones de funciones y valores de los programas cargados. Resultan útiles cuando los requerimientos de memoria son grandes o la memoria disponible es reducida, lo que puede provocar problemas.

AutoCAD utiliza automáticamente la cantidad de memoria que necesita en cada caso. Pero en sistemas con una capacidad limitada puede hacerse necesario un ajuste de la misma. Hay que tener siempre presente que cuanto mayor es el número de variables y de funciones definidas, mayores son las necesidades de memoria. Al mismo tiempo, si sus nombres ocupan más de seis caracteres se consume más memoria. Todas estas circunstancias pueden forzar al usuario a liberar memoria o a activar la llamada paginación virtual de funciones, concepto que se explica a continuación.

Enfilemos pues la recta final de este MÓDULO.

(VMON)

Esta función activa la paginación virtual de funciones. Ésta no resulta necesaria hasta que se agotan todos los demás tipos de memoria virtual, lo que ocurre muy raramente en la mayoría de las plataformas. En algún caso, cuando se tiene cargado en memoria un programa extenso de AutoLISP o varios programas, puede ser insuficiente el espacio de memoria nodal disponible. La memoria nodal almacena todos los símbolos de funciones de usuario y de variables cargados en memoria. Estos símbolos son los también llamados nodos.

Si esto ocurre, se puede emplear VMON para activar la paginación virtual de funciones. Desde el momento en que se llame a VMON, esa paginación virtual afectará únicamente a las funciones de usuario cargadas a partir de ese momento. Cada vez que se carguen nuevas funciones de usuario y la memoria nodal sea insuficiente, AutoLISP irá evacuando las funciones poco utilizadas a un archivo temporal controlado por la paginación de archivos de AutoCAD. Si esas funciones evacuadas se volvieran a necesitar, AutoLISP volvería a cargarlas en memoria nodal. Estos intercambios son automáticos y transparentes de cara al usuario.

Si se dispone de suficiente memoria RAM ampliada o paginada, la utilización de esa memoria será lógicamente mucho más rápida que la paginación en disco.

Las funciones de usuario cargadas antes de la llamada a VMON no pueden ser evacuadas de la memoria nodal, por lo tanto seguirán ocupando espacio. De la misma manera, todos los símbolos de variables continúan en memoria nodal y no son afectados por VMON. Esto quiere decir que aunque se hayan ampliado mucho las posibilidades de cargar programas largos, sigue existiendo una limitación de memoria nodal disponible.

Con VMON activada, todas las nuevas DEFUN colocan un nuevo nodo llamado tabla de paginación como primer elemento añadido a la lista de AutoLISP que define la función. Este primer elemento no es visible a la hora de escribir (en pantalla o en un archivo) esa función. Pero se puede obtener con CAR. La función TYPE devuelve el tipo de elemento PAGETB para esas tablas de paginación (como se explicó en su momento).

(GC)

Cada vez que se pretende cargar en memoria un nuevo símbolo de función o de variable, AutoLISP busca en la memoria nodal nodos libres donde almacenarlo. La simple operación de crear una variable y atribuirle un valor, por ejemplo:

(SETQ Var 27.53)

requiere dos nodos: uno para almacenar en memoria el nombre del símbolo (en este caso Var) y otro para almacenar su valor (aquí 27.53).

Si el nombre del símbolo tiene seis caracteres o menos, se almacena directamente en el nodo. Si tiene más, se toma espacio adicional de la memoria nodal o montón. De ahí la importancia de utilizar nombres de símbolos (funciones de usuario o variables) con menos de seis caracteres.

Si no existen nodos libres para almacenar ese símbolo, AutoLISP recupera automáticamente el espacio inutilizado (nodos que se han liberado porque ya no tienen ningún símbolo asociado). Si esto resulta insuficiente, solicita memoria adicional del montón para crear nuevos nodos. En el momento en que se agote esta memoria, tendría que recurrir a la paginación virtual de funciones si se encuentra activada (si se ha empleado VMON).

El espacio de memoria tomada del montón para crear nuevos nodos ya no puede ser devuelta al montón hasta salir de AutoCAD. Sin embargo existe la posibilidad de forzar la recuperación de esa memoria mediante GC. Esta recuperación de memoria lleva bastante tiempo y su utilidad es limitada. Es preferible dejar que AutoLISP vaya recuperando automáticamente los nodos liberados en memoria sin necesidad de llamar a esta función.

(ALLOC valor_entero)

Los nodos en AutoLISP tienen un tamaño de 12 octetos. Para evitar un fraccionamiento excesivo de la memoria nodal, los nodos se agrupan en segmentos. Cada segmento tiene un tamaño implícito de 514 nodos, es decir, 6168 octetos.

Si se desea especificar un número de nodos diferente a 514 como tamaño del segmento, se puede hacer con ALLOC:

(ALLOC 1024)

Este ejemplo asignará a cada segmento un tamaño de 1024 nodos, lo que representará 10240 octetos.

Asignando un tamaño adecuado a los segmentos se pueden reducir las operaciones de recuperación de memoria inutilizada, ganando en velocidad de ejecución del programa. De todas formas, es preferible dejar la tarea de gestión de memoria al mecanismo automático de atribución de nodos de AutoLISP.

(EXPAND valor_entero)

El espacio de memoria para almacenar valores de cadenas se toma de la misma memoria montón que los segmentos de nodos. Estos valores de cadenas son de todo tipo: nombres de símbolos de más de seis caracteres, valores concretos de variables de texto, textos de mensajes, textos de opciones de menú, etcétera.

Por lo tanto en la memoria de montón, además de la utilizada para los segmentos de nodos, se requiere una parte para cadenas de texto. La función EXPAND reserva explícitamente para nodos, un número determinado de segmentos de la memoria montón. Ejemplo:

(EXPAND 10)

Este ejemplo reservará 10 segmentos que, si son de 514 nodos cada uno, representarán un espacio de 51400 octetos. No es posible reservar toda la memoria montón disponible para segmentos de nodos. AutoLISP necesita que exista una parte libre para la memoria de cadenas.

(MEM)

Esta función visualiza el estado actual de la memoria en AutoLISP, y devuelve nil. Por ejemplo la función podría visualizar:

Nodos: 20224
Nodos libres: 40
Segmentos: 76
Asignado: 256
Colecciones: 5
nil


En versiones idiomáticas inglesas de AutoCAD 14 la lista sería así:


Nodes: 20224
Free nodes: 40
Segments: 76
Allocate: 256
Collections: 5
nil


Cada término indica lo siguiente:

— Nodos: el número total de nodos atribuidos hasta ese momento.

— Nodos libres: es el número de nodos que se encuentran libres como consecuencia
de la recuperación de memoria no utilizada.

— Segmentos: es el número de segmentos atribuidos.

— Asignado: indica el tamaño en nodos del segmento actual.

— Colecciones: es el total de recuperaciones de memoria no utilizada, que han sido

efectuadas (ya sea automática o manualmente).