jueves, agosto 12, 2010

Multiplicación de cantidades decimales: una cuestión de representación, escala y transformación


I like to think of mathematics as a vast musical instrument on which one can play a great variety of beautiful melodies. Many generations of mathematitians have provided us with rich tonal resources that offer limitless possibilities for harmonious combination.
Knuth, Donald - Algorithmic Themes, AMS History of Mathematics, Volume 1: A Century of Mathematics in America, AMS, Providence, RI, 1988.


¿Por qué la multiplicación de dos cantidades decimales x e y, tal que {1 > x > 0 ; 1 > y > 0}, nos da como resultado una cantidad menor que los multiplicandos, a diferencia de la multiplicación de cantidades iguales o mayores que la unidad?

Aquí está la respuesta expresada gráficamente. Es una cuestión de escala. La parte superior del gráfico muestra la multiplicación de una cantidad mayor que la unidad por otra cantidad menor que la unidad: el resultado (esperado por la regla de la multiplicación) es otra cantidad mayor que la unidad. La parte inferior muestra el ejemplo clásico de multiplicación en la cual el resultado es una cantidad que es misteriosamente mucho menor que los multiplicandos. Un resultado no tan obvio, sobre todo si se trabaja la multiplicación de forma mecánica manualmente (multiplicación trae la idea a la mente de magnificar una cantidad N veces ella misma):



Es una paradoja. La misma paradoja que enfrenta todo niño en la escuela cuando, despues de tanto machacar de memoria las tablas de multiplicar (en la cual el resultado de la multiplicación de dos cantidades siempre muestra una cantidad mayor que los multiplicandos), de pronto aparece una operación de multiplicación que desafía esta regla de caletre. El niño(a) curioso y protestón descubre que ha sido engañado y que realmente no sabe qué es realmente la operación aritmética de multiplicación. Un escenario que ocurre con mucha frecuencia y que es producto de un alumnado que no quiere esforzarce en comprender y por otro lado un profesorado que no le gusta que le pregunten para no tener que explicar y desarrollar didacticas que realmente "lleguen al punto" (el punto en este caso es que el alumno comprenda perfectamente bien una idea).

Esta paradoja de las operaciones aritméticas "al ojo" es una de las razones que motivaron el uso de la notación estándar o notación científica: se establece una posición fija para la coma "," decimal en cualquier cifra numérica, lo cual facilita su lectura y por consiguiente su uso en operaciones aritméticas. Es así como una cifra numérica se expresa como una expresión potencia de base N (en nuestro sistema decimal se usa como base el 10):

"cifra-decimal * 10^n" , siendo n la posición de la verdadera coma "," decimal.

Por ejemplo, nos presentan la siguiente multiplicación:

5.267,4232 * 0,0000012967 = ? (1)

Usando la notación estándar podemos transformar las cifras originales en la siguiente forma:

0,526x10^4 * 0,129x10^-5 (2)

Y resolviendo terminos semejantes en (2) obtenemos:

0,526 * 0,129 * 10^-1 (3)

La expresión (3) es más adecuada tanto a la vista del calculador que hace el trabajo de forma manual como al calculador que hace uso de una regla de cálculo o de tablas. En nuestro ejemplo, sin embargo, hicimos una simplificación al truncar varios dígitos en las cifras originales y por consiguiente cargamos con un margen de error en la precisión del resultado desde el puno de vista de los operandos originales. En este caso el error sería de 0,0000448676634399988, pero es un buen ejemplo de la forma de operar y los errores que pudieramos esperar en aritmética manual de precisión.

Para el caso de una regla de calculo, en la cual la escala comienza en la unidad ("1"), podemos expresar el problema simplificado (3) así:

5,26x10^3 * 1,29x10^-6 (4)

Luego, simplificando (4) obtenemos:

5,26 * 1,29 * 10^-3 (5)

La sub-expresión 5,26 * 1,29 de (5) la trasladamos al desplazamiento de escalas en una regla de calculo y obtenemos el resultado (de 6,78) de forma analógica como se muestra en la siguiente imagen en las escalas A y B (parte superior de la regla de calculo - para ver detalle presionar el mouse sobre la imagen):


Finalmente operamos este sub-resultado ajustando la escala al factor 10^-3 de la expresión (5) para obtener el total.

La notación estándar es utilizada en programas de hoja de calculo y frecuentemente se expresan las cifras con el formato "f.ffff...E+e", siendo "f.ffff..." la parte decimal, "+" el signo del exponente y "e" el exponente de base 10.

El modelo de programación de un procesador (microprocesador) diseñado para almacenar y operar con cifras decimales aproximadas, debe permitir registrar en una misma palabra de dato las distintas partes que conforman la notación estándar o científica que mostramos antes. Esta notación, aplicada a los procesadores digitales se le llama de punto flotante (Floating Point notation) y pudieramos representarla en su forma básica de la siguiente manera:

+/- e fffff...

Siendo +/- el signo de la cifra representada, "e" el exponente en base 10 o base 2, y "fffff..." la cifra decimal o Mantisa.


Sobre el uso de la regla de cálculo y los logaritmos:

La regla de cálculo como instrumento, hoy día olvidado (incluso como herramienta educativa), es el típico ejemplo de un computador analógico (transformación de cantidades numéricas en cantidades físicas: desplazamientos, voltages). Dada una operación aritmética a resolver, las cantidades involucradas son transformadas en desplazamientos entre una regla deslizante y otra regla estática. A través de los mismos desplazamientos y escalas logaritmicas impresas físicamente en las superficies de las reglas se hacen los calculos y el resultado (como en el ejemplo dado en esta entrada) es leido en las escalas como números. Las escalas impresas en la superficie de la regla son logaritmicas y están basadas en la siguiente identidad de los logaritmos:

LOG(A x B) = LOG(A) + LOG(B) (6)

Asumiendo que usamos nuevas variables para representar los logaritmos de cada número original, tenemos

LOG(A) = X

LOG(B) = Y

Entonces

LOG(A x B) = X + Y

Es decir, "X + Y" es el exponente al cual debemos elevar la base (10 en nuestros ejemplos) para obtener "A x B":

10^(X + Y) = A x B

Esto mismo es lo que hace la regla de cálculo, los números u operandos originales son transformados en nuevos operandos que representan desplazamientos en las escalas de la regla. Si observamos las escalas veremos una numeración del 1 al 10 (en algunos casos como la regla Faber Castell 2/82, la numeración comienza en 0,9). Sin embargo la distancia entre los números no es uniforme: las distancias son exponenciales.

Vamos a revisar un ejemplo de este enunciado. Imaginemos que deseamos resolver la multiplicación de las cantidades:

1,78 x 5.011,87

Usando la escala L de una regla de cálculo ó usando una tabla de logaritmos, encontramos que:

LOG(1,78) = 0,25 y LOG(5.011,87) = 3,7 (6.1)

Luego sustituyendo (6.1) en (6) tenemos:

LOG(1,78) + LOG(5.011,87) = LOG(1,78 x 5.011,87) (6.2)

Resolviendo cada lado de la ecuación (6.2) :

0,25 + 3,7 = 3,95

Por lo tanto, obtener el producto A x B es equivalente a obtener la suma de sus logaritmos (cantidades a las cuales debe "elevarse" una base 10 para obtener cada valor A y B):

10^0,25 = 1,78 y 10^3,7 = 5.011,87

El proceso de transformación que referimos antes ocurre cuando trasladamos nuestro calculo original (multiplicación en este caso) a el "mundo" de escalas logaritmicas y desplazamientos físicos entre superficies: la multiplicación de cantidades se transforma en suma de cantidades y esta a su vez se transforma en suma de desplazamientos físicos. La ecuación (6) muestra cómo desplazando una escala logaritmica sobre otra estática (suma) obtenemos el producto entre cantidades.


Esta imagen presenta un ejemplo de multiplicación utilizando la suma de logaritmos. La hoja (parte superior) desglosa las operaciones involucradas tal y como fueron descritas en la ecuación (6). Para el caso de la regla de cálculo (parte inferior) se muestra el desplazamiento cuya distancia es proporcional al logaritmo.


Anterior a las tablas logaritmicas y a las reglas de cálculo, uno de los métodos usados fue el llamado Prosthaphaeresis o método Prosthaphaeretico a través del cual operaciones de multiplicación eran transformadas en multiplicaciones de funciones seno/coseno de ángulos y estas a su vez resueltas por identidades trigonométricas que las igualaban con operaciones de resta y suma de senos/cosenos (ver "On Tycho Brae's Manual of Trigonometry" - 1916 ; en ese trabajo se hace referencia al esfuerzo de un tal Johannes Wener de Nurnberg, a parte del trabajo que el mismo Tycho describe haber realizado en 1580 junto a Paul Wittich de Breslau). La palabra Prosthaphaeresis es la conjunción de las palabras adición y sustracción en griego y una de las identidades usadas para hacer la transformación era la siguiente:

2 x Sen(alpha) x Cos(betha) = cos(alpha - betha) - Cos(alpha + betha) (6.1)

La formulación (6.1) requiere el resolver nuestras cantidades originales A y B a sus correspondientes ángulos alpha y betha mediante una búsqueda en tablas, tal que:

Seno(alpha) = A

y

Coseno(betha) = B

Como se ve era un método más complicado que el uso de tablas logaritmicas posteriores, además de sus limitaciones.

Este mismo proceso de transformación (llamado Isomorfísmo por el Prof. Martin Cohen) conforma el principio de los instrumentos de medición como el Sextante. En el Sextante, la elevación del sol respecto al horizonte aparente es transformada en una medida angular utilizando espejos, tornillo micrométrico y brazo mecánico montados de forma relacional en un cuadrante de metal o madera.

El capitán Nemo usando un Sextante para transformar la elevación del sol, respecto al horizonte aparente, en una medida angular para el calculo de la latitud (de un grabado de Alphonse de Neuville)

Las tablas de logaritmos han sido usadas desde mediados del siglo XVII hasta muy entrada la década de los años 1970 para "mecanizar" las operaciones aritméticas de multiplicación, división realizadas por ingenieros, astrónomos y matemáticos. Por otro lado, las escalas logaritmicas (como las impresas en la regla de cálculo) proliferaron en Europa especialmente en Francia durante los años medios del siglo XIX (como necesidad de herramientas de cálculo durante las labores de ingeniería en la construcción de las vías de ferrocarriles) en forma de Nomogramas. Uno de los Nomogramas más interesantes de esa época es el Abaque ou Compteur Universel creado por Léon Lalanne (ofrecía la posibilidad de hacer operaciones básica de multiplicación "z = xy" de números enteros, división de números enteros y otros cálculos más laboriosos como el cálculo de medidas en la circunferencia). En una próxima entrada en este Blog trataré este interesante téma de las tablas logaritmicas, la Nomografía y su utilización práctica. Aquí es importante afirmar que la idea de estos instrumentos y artificios (tablas logaritmicas, reglas de cálculo y la representación de cantidades por notación científica) es la de "mecanizar" las operaciones aritméticas y por ende acelerar el procedimiento de resolución. De esta "mecanización" (secuencia de pasos como búsqueda al "ojo" en una tabla logarítmica o el desplazamiento de escalas en las reglas de cáculo) se pasó luego a la automatización (de estas mecanizaciones) a través del uso de calculadoras y computadoras programables.

Esta gráfica muestra la creación de una escala logarítmica (parte superior) similar a las escalas C y D de la regla de cálculo básica Manheimm

Una de las ventajas de las reglas de cálculo y el uso de tablas es que son herramientas de un "proceso conciente". Utilizar una calculadora programable (con solo pulsar un par de botones) representa un proceso hasta cierto punto "inconciente". El "usuario" de una calculadora programable pudiera no ser conciente de la formulación matemática y procedimiento para obtener un resultado. La regla de cálculo por otra parte exige un llevar cuenta de las posiciones decimales de cada operando y para cada resultado obtenido. La regla de cálculo rebasa la frontera que separa el "usuario" del "calculista" (este último termino era dado a los ingenieros que se dedicaban a hacer los cálculos para trabajos de ingeniería). En el pasado (años 1970 hacia atrás) las organizaciones y compañías de ingeniería tenían un equipo de "calculistas" o "computadores" quienes realizaban los calculos para los proyectos.


Esta imagen muestra el proceso de Transformación que ocurre con el uso de las reglas de cálculo: a la izquierda de la imagen se muestra la operación de multiplicación tal y como se dá en un (1) solo paso, contrastando con los tres (3) pasos requeridos por la Transformación. Presionar sobre la imagen para verla ampliada


Veamos otro ejemplo esta vez un poco más abultado:

1.590 x 3,64 x 0,763 (7)
---------------------
4,39 x 930

Usando una calculadora escribiríamos las operaciones de forma jerárquica RPN (Reverse Polish Notation - ver entrada sobre computación en los años 1950 en este mismo Blog). En una calculadora programable es posible almacenar esta secuencia como un programa titulado "A" y ejecutarlo presionando unas pocas teclas:

1.590
ENTER
3,64
x
0,763
x
STO 10
4,39
ENTER
930
x
STO 11
RCL 10
ENTER
RCL 11
/

La calculadora nos muestra entonces, luego de ejecutar esta secuencia de pasos, el resultado 1,0816.

Ahora vamos a hacerlo con nuestro método manual y mucho más instructivo e interesante combinando la notación estándar o científica y una regla de cálculo.

Primero normalizamos todas las cantidades involucradas a través de la notación estándar:

- 1.590 se convierte en 1,6 x 10^3

- 3,64 se convierte en 3,64 x 10^0

- 0,763 se convierte en 7,63 x 10^-1

- 4,39 se convierte en 4,39 x 10^0

- 930 se convierte en 9,30 x 10^2

Nuestra expresión original se convierte en:

(1,6 x 10^3) x (3,64 x 10^0) x (7,63 x 10^-1) [8]
----------------------------------------------
(4,39 x 10^0) x (9,30 x 10^2)

La expresión aritmética [8] es nuestra expresión original en la cual los operandos se expresan de forma estándar o científica.

En este punto debemos recordar la precedencia de operadores aritméticos. Esto es, la operación de multiplicación tiene una precedencia mayor que la operación de división. Por tanto resolveremos las multiplicaciones y al final resolveremos la división. Este método no es el recomendado por los calculistas de antaño. El método que ellos recomendaban (para minimizar la cantidad de desplazamientos de la regla) es el de "zig-zag" (vease la nota al final de esta entrada). También es importante indicar que al utilizar una regla de cálculo, es posible resolver operaciones de multiplicación continuada del tipo aa x bb x cc. Para esto deslizamos la unidad de la escala C sobre el primer multiplicando. Seguidamente deslizamos el apuntador sobre el próximo multiplicando en la escala C. Observamos el resultado intermedio en la escala D (en el mismo punto indicado por el apuntador en este instante). Luego deslizando la unidad de la escala C sobre la posición del indicador, deslizamos el indicador sobre el siguiente operando en la escala D. Observamos el resultado final en la escala C en la nueva posición del indicador. No mostraremos aquí imágenes de la regla de calculo. La imágen anterior puede servir como guía. Luego publicaré un enlace para descargar reglas de calculo en forma de applets de java para practicar en el navegador de Internet. Yo utilizo una Faber-Castell 2/82 y una Aristo 0968 (ambas muy buenas para el cálculo de sobre-mesa por su buen tamaño de más de 25cm). Lo importante de tener varias reglas de cálculo es que permite la práctica constante. En su libro sobre la Regla de Cálculo, el doctor Porcel nos dice que el oficio de calculista es similar a la taquigrafía: como el caso de la taquigrafía, se debe practicar frecuentemente.

Procedemos entonces a reducir las expresiones del numerador y denominador de la división:

1,6 x 3,64 x 7,63 x 10^2 (9)
------------------------
4,39 x 9,30 x 10^2

NOTA IMPORTANTE: La multiplicación en el denominador dará como resultado 4 x 9 = 36. Igualmente para el caso del numerador 3 x 7 = 21. Es decir, el resultado será una cifra con un orden superior al de las cifras multiplicando. Por otra parte, la regla de cálculo nos da el resultado con, máximo, tres cifras significativas pero sin indicación de dónde puede estar localizada la coma decimal. Entonces, debemos tomar en cuenta en nuestro calculo mental o en nuestras anotaciones este orden superior del resultado (10^1). Con lo cual, la expresión del denominador en (9) quedaría: 4,39 x 9,30 x 10^2 x 10^1. Continuamos nuestras operaciones sin tomar en cuenta esto, suponiendo que las cuentas las hacemos mentalmente. Pero ya sabemos que para el calculo con regla debemos tomar en cuenta estos cambios de orden en las operaciones parciales.

Resolviendo las multiplicaciones en (9) nos queda:

4,44 x 10^2 (10)
------------
4,07 x 10^2

Para finalizar resolviendo la división en (10):

1,09 x 10^0 = 1,09 x 1 = 1,090

El resultado del programa RPN en la calculadora fué 1,0816.

Dejo el siguiente ejercicio al lector:

0,028 * 0,0031 * 0,4
---------------------
0,315 * 0,22 * 0,5


Lo interesante del uso de tablas logaritmicas o regla de cálculo es que la acción de resolución se hace mentalmente con ayuda de la herramienta (tablas o regla). Es decir, llevamos mentalmente la cuenta de los exponentes de diez (10).

Otro punto importante, sobre la resolución de operaciones como las anteriores y a través de la regla de cálculo, es que se sigue un esquema de "zig-zag" para aprovechar el posicionamiento de la regla en cada sub-desplazamiento. Por ejemplo:

A x B x C
---------
D x E

La secuencia de operaciones sería: (((A / D) x B) / E) x C

El siguiente ejemplo (e imagen) muestra cómo se opera con tabla de logarítmos y por otra parte con regla de cálculo. Supongamos que nos plantean la siguiente división:

0,0272 x 27,1 x 12,6
---------------------
2,371 x 0,007

Usando tabla de logarítmos tenemos,

log(0,0272) = (-) 2,43457
log(27,1) = 1,43297
log(12,6) = 1,10037
- log(2,371) = (-) 1,62507
- log(0,007) = 2,15491 +
-------------
2,74789

Aplicando Antilog(2,74789) = 559,6

El cálculo con tabla de logarítmos (incluidas las operaciones de sustracción de 1,00000 para cada valor negativo de logarítmo más la sumatoria total final) tomó 6 minutos aproximadamente.

Luego, haciendo el cálculo con la regla (utilicé una regla Hemmi SUN 259D con escalas D, C, DF, CF),

Paso 1. utilizo las escalas DF-CF y D-C siguiendo la estrategia "center-drift" con los valores 12,6 y 0,007 localizados en las escalas superiores DF-CF y el resto de los valores localizados en las escalas inferiores D-C. Obtenemos el valor "562".

Paso 2. Aproximación de la coma decimal por medio de la notación Estándar -1 -(-3) = 2, obtenemos el valor definitivo "562,0".

El cálculo con regla tomó 1 minuto aproximadamente.

La diferencia entre los valores "559,6" del cálculo con tabla de logarítmos y el "562,0" se explica dado que la tabla de logarítmos contempla valores resultantes de hasta 4 dígitos, mientras que la regla (que en este caso es de 25cm.) contempla hasta 3 dígitos. Sin embargo, el uso de la regla acelera los cálculos. Sobre todo en operaciones múltiples que incluyen productos, cocientes e incluso funciones trigonométricas y/o exponenciales, la regla es como la taquigrafía!

Aquí se muestra la hoja en la cual se realizó el cálculo final y el valor marcado en la escala de la regla (escala D, es decir primera escala de abajo hacia arriba)

lunes, junio 14, 2010

Intérpretes y el arte de la programación, 2da Parte


It is no exaggeration to regard this as
the most fundamental idea in programming:
"The evaluator, which determines
the meaning of expressions in a
programming language,
is just another program"

Structure and Interpretation of Computer Programs
Abelson & Sussman, 1996



Continuación del tema sobre programación de computadoras, Intérpretes y el arte de estructurar. Esta entrada junto con la anterior (1ra parte) conforman un breve resumen y crónica sobre la idea fundamental de la programación de computadoras.

Revisaremos las estructuras: Analizador Sintáctico, Intérprete. Además de la programación funcional como herramienta habilitadora en la construcción de Analizadores Sintácticos (Parsers en inglés) que "navegan" a traves de gramáticas de lenguajes para descubrir la estructura inmersa en un texto cualquiera. La estructura del texto está definida por una Gramática. Una Gramática se utiliza para definir un Lenguaje y sobre-poner una estructura en cada Sentencia del Lenguaje (la gramática en si misma es una programa, ejecutado por un autómata que recorre las producciones gramaticales y también el texto del listado fuente siendo traducido). La función de "navegar" de un Analizador Sintáctico verifica que el texto obedece las convenciones sintácticas de la Gramática. Revisar estas estructuras virtuales es un paso necesario para continuar nuestro recorrido sobre Intérpretes y Virtual Machines partiendo ahora de los años 1970s. Uno de los ejemplos que utilizaremos se conecta directamente con la referencia que hicimos de FORTRAN en la 1ra Parte. Este tema es muy extenso y en la Internet y en las bibliotecas existe mucha literatura sobre él. Recomiendo entonces tomar estos escritos como punto inicial en una labor de investigación en la cual el lector descubrirá el gran espectro de aplicaciones que tienen hoy día y que tendrán en el futuro estas ideas fundamentales. También, al igual que en la 1ra parte, haremos referencia a varios textos de estudio.


Sección del listado fuente de EULER, la cual representa al Intérprete para la ejecución del P-Code generado por compilador [1]. Wirth nunca más abandonó este método de escribir a cerca de un lenguaje X incluyendo dentro del mismo texto/documento el listado fuente de un Compilador e Intérprete para la traducción del lenguaje X. Documentos como este de Wirth, escritos durante la década de 1960, sembraron la semilla para la portabilidad y método de distribución de lenguajes de 3ra generación que proliferaron durante la década de 1970 (Tiny Basic, SmallTalk y otros).

Muestra del clásico ejemplo las Torres de Hanoi escrito en el lenguaje Pascal. La siguiente figura muestra la traducción hecha por el compilador Pascal-F. El traductor o Compilador Pascal-F recibía de entrada un listado fuente en lenguaje Pascal y producía en su salida un listado fuente en F-Code. Este listado fuente en F-Code es Fortran puro y podía ser traducido a su vez por cualquier compilador Fortran de la época [2] . Este método (de utilizar un lenguaje de alto nivel como lenguaje Assembler, aprovechando la difusión de tal lenguaje para asegurar la portabilidad) continuó apareciendo en las siguientes décadas a 1970s. La primera referencia bibliográfica de este método la encontré en el libro "Compiler Design in C" por Allen I. Holub (1990). Posterior a esta publicación existe el trabajo titulado "C--: A portable Assembly Language" por Peyton Jones, Nordin, Oliva (1997). Este último trabajo es en parte una crítica a la utilización del lenguaje C como Assembler.


Un punto muy importante a tomar en cuenta: el Compilador diseñado por Manning estaba escrito en lenguaje Pascal, de tal manera que su listado fuente pudiera ser compilado por otra instancia del mismo compilador ya existente en la instalación destino (un Compilador Pascal traduciendo el listado fuente del mismo Compilador). Aquí aparece nuevamente la idea fundamental expresada por los profesores Abelson y Sussman en su libro: “el evaluador o programa que traduce un programa, es en sí mismo otro programa”. Esta idea fundamental permitió el transporte y la reproducción) de compiladores y lenguajes de una plataforma computacional a otra. La siguiente imagen muestra esta idea fundamental de un evaluador (traductor) construyendo otra instancia de si mismo ("Drawing Hands" - Maurits Cornelis Escher, 1948)



El Sistema Operacional UNIX es otro ejemplo de la aplicación de la tendencia hacia la Portabilidad que nació entre los años 1967 y 1971. Los creadores del UNIX escribieron los listados fuente en el lenguaje Assembler para la computadora DEC PDP-7 localizada en Bell Laboratories para el año 1968 [3]. Posteriormente, en 1973, los listados fuente fueron re-escritos en un lenguaje llamado C [3]. Es de suponer que el ejemplo que Niklaus Wirth dio en 1965 con el lenguaje EULER motivó el uso del método de escribir Compiladores e Intérpretes (e incluso Sistemas Operacionales como en este caso de UNIX) utilizando un lenguaje X para traducir el mismo lenguaje X.

Otro punto fundamental que revisaremos es la abstracción en la programación. Segun el texto de Abelson y Sussman, existen tres mecanismos para la construcción de ideas complejas a partir de ideas básicas [4]:

* Expresiones primitivas, las cuales representan las entidades más simples del lenguaje de programación.
* Formas de combinación, mediante las cuales se sintetizan elementos compuestos a partir de las entidades más simples.
* Formas de abstracción, mediante las cuales se asignan nombres a los elementos compuestos para luego poder ser manipulados como entidades simples. Este mecanismo de abstracción es fundamental en lenguajes como C++, C#, OBERON, Scheme, Java.

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

[1] Wirth y Amp - Euler: A generalization of Algol, and its Formal Definition – 1965
[2] Joseph Manning - PASCAL-F : A Portable FORTRAN-Based PASCAL Compiler - 1981
[3] Kernighan y Pike - The Unix Programming Environment – 1984
[4] Abelson y Sussman - Structure and Interpretation of Computer Programs - 1996

lunes, abril 26, 2010

Diseño de Computadores en 1950s, Interpretes y el arte de diseñar Lógica digital...1ra Parte



"We are about to study the idea of a computational process.
Computational processes are abstract beings that inhabit
computers. As they evolve, processes manipulate
other abstract things called data.
The evolution of a process is directed by a pattern
of rules called a program.
People create programs to direct processes.
In effect, we conjure the spirits of the computer with our spells."

Structure and Interpretation of Computer Programs
Abelson & Sussman, 1996


"Much of my story takes place in 1967, by which time a great many sophisticated
computer programs had been written all over the world. Computing machines had come
a long way since their invention in the 30s and 40s"

The Genesis of Attribute Grammars
Donald E. Knuth, Stanford University, 1970

"The user of a modern computer faces a bewildering array of languages: languages of machine control; high level languages, which must be translated; languages to express the translation process; and languages to define languages. All these languages are artificial, retricted modes of expression first invented by someone and then tediously learned by others."

A Compiler Generator (XPL language)
McKeeman, Horning, Wortman - 1969

"The computer programs for the Apollo spacecraft will son become the most pacing ítem for the Apollo flights."
Howard W. Tindall, NASA-Especialista asignado al MIT/IL 1966



Introducción

Los siguientes fragmentos e ideas conforman un subconjunto de varias conversaciones que sostuve con Hugh Blair-Smith (HB-S), con el Dr. Ramón Alonso (RA) y con Eldon C. Hall (EH) entre los años 1997 y 2008, conjuntamente con material histórico adicional que intercale en el texto como guía a los temas tocados. Blair-smith quien fuera el diseñador de la Microarquitectura del computador del Apollo, consultor para el software de alta disponibilidad del transbordador espacial y diseñador del software de auto-verificación para uno de los sistemas del nuevo Lunar Orbiter lanzado (hasta donde supe) en el año 2008. El Dr. Ramón Alonso fue el arquitecto del computador de la sonda que el MIT/IL planeaba para una misión a Marte en 1956. Su diseño de computador (desarrollado en conjunto con Halcombe Laning y Ramón Alonso) se convirtió en la base para el computador Apollo de los 1960s. Eldon C. Hall fue el director del proyecto de construcción del computador Apollo. Anterior a este trabajo, Hall ya había ejercido el mismo papel para el proyecto del sistema de guía en el misil Polaris. Uno de los grandes legados que ha dejado Eldon Hall es el haber utilizado circuitos integrados de compuertas en el diseño del computador Apollo, en una época cuando estos "bichos" no eran confiables y muchos fabricantes de computadores no se atrevían a usarlos.

Desde hace varios años he recabado información histórica sobre programas Intérpretes y sus aplicaciones desde los años 1940s. Tomando en cuenta las tendencias en materia de "Virtualización" que han aparecido en los últimos 6 años tendría mucho sentido hacer este recuento. El motivo de quien escribe no es hacer un ejercicio en erudición histórica. Más bien es un resumen/resultado de varios años de investigación a destajo, los cuales se colocan a disposición de cualquier interesado y que sirvan de punto de partida para nuevas investigaciones en historia de la tecnología. Debe disculpar el lector cierto desorden en la organización del texto. Publicar la información de forma más ordenada requeriría todo un documento tipo monografía a parte. Mis ocupaciones laborales me han impedido tener un poco de paz mental para sintetizar el grueso de documentación que tengo en mis manos. Espero contar con la salud suficiente en los próximos años para publicar todo esto en un texto técnico/histórico. El objetivo último de estos escritos es divulgar la cronología de ideas y transferencia de conocimientos que permitieron armar los sistemas de computación que se utilizan hoy día en diferentes actividades. Mi intención es mostrar cómo un método estructurado de diseño/construcción nos permite (partiendo de cero y con solo materias primas básicas) obtener herramientas para la investigación y la creación de más conocimiento.

Hay mucha información histórica que se cruza. Por lo tanto, se incluyen notas y comentarios para guiar al lector y ponerlo en contexto y/o alertarlo sobre inter-relaciones entre tecnologías o hechos históricos. También se hace referencia a textos interesantes sobre estos temas.


Sobre Intérpretes (Virtual Machines) creados para los primeros prototipos del Apollo Guidance Computer - primer uso de este método de distribuir el trabajo en Software

HB-S: As for the interpreter, you certainly have a very early model in that paper, since Mod 3C was, in effect, "AGC Block Zero." Let me give you a few comments off the top of my head, without looking up anything -- though I could do some of that if you have further questions.



Figura 1.

Figura 1: parte del código fuente escrito en Assembler YUL para un modelo de intérprete de instrucciones Mod 3C (tomado del reporte MIT E-1077 - Preliminary Mod 3C Programmers Manual, Blair-Smith, Alonso, Laning - 1961). Este Intérprete utilizaba una Jump Table para localizar las Subrutinas que ejecutan cada Operación de "Alto Nivel". Más adelante en este artículo se muestra una imagen de uso de estas instrucciones de "Alto Nivel" o Ecuaciones.

Figura 2.

En la Figura 2: sección del Software LUMINARY del módulo lunar Apollo que ejecuta el Intérprete (el "CPU de Software"). Específicamente se muestra la Jump Table que despacha a las Subrutinas para ejecución de intrucciones de "Alto Nivel" o Ecuaciones.

HB-S: First of all, the interpreters in all 3 AGC blocks had the same purpose: to reduce the memory usage for double precision (including vector) calculations, at a considerable cost in additional execution time. The additional time was acceptable because that kind of calculation was used only for navigation and guidance functions that were done infrequently and at low priority compared to, say, flight control. I'm pretty sure that the DAP and general flight control never used interpretive language.

HB-S: In the executive, any routine that was going to use interpretive allocated a VAC (Vector Accumulator) block of working memory; any routine that didn't use interpretive allocated the smaller and simpler block size.
HB-S: A note on notation: because so much of our logic was concerned with either interrupts or interpretive, we wanted distinctive abbreviations for those two words. Since the first 5 letters are the same, we used the end pieces "RUPT" and "PRET" as abbreviations in YUL code.

El software en el computador Apollo (Apollo Guidance Computer) fue escrito utilizando dos (2) lenguajes: un lenguaje Assembler básico (que Blair-Smith llamó YUL) y un lenguaje Interpretado más orientado hacia el calculo Vectorial y Matricial con números de precisión doble (28 bits). YUL estaba basado en el Assembler SOAP (Symbolic Optimizing Assembler Program) del computador IBM 650 (como lo indica el propio Blair-Smith en sus anotaciones al libro de Eldon C. Hall - "Annotations to Eldon Hall's Journey to the Moon"). El Intérprete utilizaba una notación polaca de operando y operadores (Polish Prefix). Las operaciones de Navegación y Guía en Apollo implicaban el uso de Vectores de Estado (posición y velocidad) y trabajo con Matrices (como el procedimiento Gaussian Least-Square para determinar la posición en el espacio). Cada 0.1 segundos el Piloto Automático Digital (DAP) entraba en ejecución y una de las funciones del DAP era el de Estimador Óptimo (Optimal Estimator) que implicaba cálculo Vectorial. Para todo esto, la idea de un programa Intérprete fue de mucha utilidad y ahorró espacio de memoria en el computador. Para una muestra de la programación "a bajo nivel" del Software Apollo ver el ensayo monográfico publicado en la MAPLD 2004 - "Attitude Controller Assembly Input Processing": http://web.mit.edu/digitalapollo/Documents/Chapter8/portillo.pdf

El siguiente fragmento proviene de las anotaciones que Blair-Smith hizo sobre el libro de Eldon C. Hall "Journey to the Moon" ("Annotations to Eldon Hall's Journey to the Moon") y en el cual se da la cronología del Assembler YUL:

- Cita Blair-Smith -In 1959, the Model 1A was known as the "Christmas computer" because of a wildly optimistic theory that the machine and its system software would be finished by Christmas of that year. My first assignment, on joining the Lab in September 1959, was to write an "assembler for an unknown number of machines with unknown characteristics," meaning the Mod 1A and whatever would come after it. This was what we now call a "cross-assembler," because it had to run on a "real" machine rather than the (yet unbuilt!) one whose code it was translating from assembly language to binary. The other quality, that it could be easily tweaked up to assemble code for other machines that hadn't been designed yet, does not have a modern term because as far as I know, there had never been, and has never been since, anything quite like it. In honor of the "Christmas computer," I named the assembler the "Yul System" and it served the Mod 1A, Mod 1B, Mod 3S, Mod 3C, AGC4 (Block I AGC), and two versions of the final Block II AGC. At each level, it translated two separate assembly languages: a low-level one in which each line of assembly-language text was turned into a binary instruction word of 11 bits (later 15) that the machine could execute directly, and a higher-level one in which each line was turned into a binary "interpretive instruction" which an interpreter program executed by simulating a considerably smarter computer. The Yul System itself was written in assembly language and ran on an IBM 650, in which memory was a magnetic drum, logic was vacuum tubes, and input/output was punched cards. Later I ported it to assembly language for the Honeywell 800.- Fin de la cita Blair-Smith -

HB-S: In the AGC design, the word length of 15 bits was chosen because it was the smallest size that would accommodate such subsystem variables as angles and accelerometer pulse counts. Also, the double-precision word length of 28 bits and sign was just enough to accommodate vector components for distance and velocity (28 bits is about 250 million, and the distance in feet from Earth to Moon is about 1200 million, and a precision of 5 feet in the last bit was plenty good enough). The only thing we kept in triple precision was Mission Elapsed Time, and we didn't need to use interpretive for that.

HB-S: So there wasn't exactly an "application example." It was simply that anything involving vector calculations (which naturally includes trig) was done in interpretive.

HB-S: As I write this, I've been trying to remember what the Block I interpretive language looked like, but no luck! I'm pretty sure that the idea of using Reverse Polish Prefix notation first arose for Block II. I remember making a pencil sketch of the head of Łukasiewicz, the inventor of regular Polish Prefix notation (or more precisely, what I thought his head ought to have looked like!), and taping it to my office wall. But whether that was in 1962 (Block I) or 1965 (Block II) I can't remember for sure. What is certain is that the Block II interpretive language and the Block II AGC were designed together -- that's why one erasable address (0023?) performed a 7-bit right shift to position the left op code for jump table use.

HB-S: Polish Prefix notation as developed by Lukasiewicz consisted of variable names followed by the operators to use on them. That's OK for hand-held calculators, but too awkward for interpreter use. That's why somebody (not us) invented Reverse Polish Prefix, in which the operators are followed by the variable addresses. As you've seen, our priority for saving space led us to pack 2 interpretive op codes per word, followed by whatever addresses those particular ops need. Having 15 bits for addresses was advantageous too, even if it didn't extend into Superbanks, because the interpreter performed all the necessary bank-switching. But the best part about Polish is that you don't need addresses for short-term intermediate variables, because the structure implies how to push and pop with a stack.



Figura 3.

Breve disertación sobre marcos referenciales y virtualización en Apollo

Blair-Smith afirma en el párrafo anterior que no recuerda como eran las instrucciones para la Virtual Machine desarrollada en el Mod 3C. La figura 3 es muestra de instrucciones del lenguaje seudo-algebraico ejecutadas por el Intérprete. Se trata de un trozo de la subrutina llamada "Coelliptic Sequence Initiation" y es parte del programa LUMINARY del módulo lunar Apollo. Durante el ascenso del módulo lunar hacia la orbita lunar, en el viaje de regreso/encuentro con el módulo de comando, la tripulación alimentaba al PGNS (Primary Guidance and Navigation System - el nombre dado al grupo de programas dentro del AGC que incluía todos los Major Modes de navegación y guia - al PGNS lo tenían como el gran orquestador del ballet orbital ejecutado por Apollo y se pronunciaba "Pings") con varios programas - uno de ellos es este Coelliptic Sequence Init. Aquí podemos ver como era utilizada la notación polaca (Polish Prefix) - instrucción u operador de alto nivel seguida de los operandos. Por ejemplo, en la muestra de listado se observa la instrucción interpretada (de "alto nivel") "DAD". Esta instrucción ejecuta un Double Precision Add (suma de doble precisión), en contraste con la instrucción de máquina (de "bajo nivel") "AD" microprogramada en el Sequence Generator del AGC y ejecutada por la lógica electrónica que se muestra en la figura 11 (Sumador del AGC - construido con lógica basada en NOR Gates). Muchos cálculos con Vectores/Matrices y números de doble precisión (28 bits) que aparecen en los programas de Guía (Major Modes - como este Coelliptic Sequence Init. y el siguiente Delta High) del Software Apollo son resueltas por este Intérprete que nació en el diseño Mod 3C y prosperó hasta Apollo. Otra instrucción muy usada era la multiplicación de una matriz por un vector (el DSKY - Display Keyboard - del computador tenía tres grupos de displays digitales de 7-segmentos para mostrar los 3 componentes vectoriales - figura 3.1). Con estas instrucciones interpretadas se programaba en "alto nivel" la lógica y cálculos de guía y navegación. Al conjunto de Operador + Operandos se le llamaba "Ecuación" (Codigo de Operación seguido de los Operandos) según la notación polaca (ver "MIT's Role in Project Apollo, Volume III; Computer Subsystem, R-700, MIT Instrumentation Laboratory, Cambridge, MA, Aug. 1972" - Eldon C. Hall). De esta manera, el lenguaje básico de programación del AGC quedaba extendido con un lenguaje orientado al anejo de matrices y vectores.



Figura 3.1. Display & Keyboard del Apollo Guidance Computer en el panel principal del módulo de comando. 


El programa, para el caso de la misión Apollo XI, fue bautizado COLOSSUS IIA. Michael Collins, el piloto del módulo de comando, relata su encuentro con COLOSSUS IIA -"My computer had been equipped with a slightly different program which MIT called Colossus IIA; it was aptly named... Colossus IIA was my uncompromising companion, and I would never truly be alone in the command module."

Otra sección del programa LUMINARY (y de los programas COLOSSUS y COMANCHE, incluidos en la memoria Rope del módulo de comando) está dedicada al cálculo de las secciones Cónicas (subrutinas KEPLER y LAMBERT) para la solución de problemas de trayectorias de vuelo producidas por las fuerzas centrípetas que actuaba sobre el punto de masa de la aeronave Apollo. Dichas fuerzas eran ejercidas por los diferentes cuerpos celestes (tierra, luna y sol) que eran considerados centrales en cada punto del recorrido. Estas subrutinas reciben (explicado aquí a modo general) un vector de estados inicial y el tiempo e el cual dicho vector de estados debe ser actualizado a través de una trayectoria cónica (alguna sección cónica: circular, elíptica, parabólica, hiperbólica o rectilínea) respecto al cuerpo celeste (luna, tierra).

El siguiente es un ejemplo de implementación de la subrutina LAMBERT en el lenguaje seudomatemático interpretado:

(tomado del listado del programa COLOSSUS Revisión 88)

40220        LAMBERT           STQ         SETPD                                
02712                                                       RTNLAMB                              
00001                                                       0D                                   
77600                                      BOV                                           
25231                                                       +1                                   
76731                                      SSP          VLOAD*                               
00027                                                       ITERCTR                              
00024                                                       20D                                  
11740                                                       MUTABLE,1                            
14017                                      STODL    1/MU                                 
02673                                                       TDESIRED                             
77675                                      DMPR                                          
11615                                                       BEE19                                
03777                                      STORE    EPSILONL                             
77214                                      SET          VLOAD                                
00474                                                       SLOPESW        
02657                                                       R1VEC          
45115                                      PDVL      CALL  
02665                                                       R2VEC 
11702                                                       GEOM  
16732                                      STODL    SNTH  
02722                                                       MAGVEC2
65301                                      NORM     PDDL  
00047                                                       X1    
00041                                                       R1    
56342                                      SR1          DDV   
65257                                      SL*          PDDL  
20173                                                       0          -6,1
77626                                      STADR                  
75043                                      STORE    CSTH          
44342                                      SR1          BDSU          
11612                                                       D1/4          
02736                                      STORE    1-CSTH        
53106                                      ROUND   BZE           
25473                                                       360LAMB       
65301                                      NORM     PDDL          
00047                                                       X1            
00001                                                       0D            
56342                                      SR1          DDV           
75457                                      SL*          SQRT          
20176                                                       0          -3,1
54325                                      PDDL       SR            
02732                                                       SNTH          
20607                                                       6             

La subrutina LAMBERT es invocada cada vez que se ordena un impulso (propulsión) en el vuelo. Esta basada en el problema de astrodinámica llamado de Lambert. Existen muchoas propiedades interesantes sobre las secciones conicas. El teorema de Lambert (demostrado a traves de metodos geometricos sinteticos y luego demostrado analiticamente por Lagrange) tiene que ver con el tiempo necesario para atravesar un arco eliptico. Lambert demostro que este tiempo depende unicamente de la longitud del eje mayor, de la suma de las distancias de los puntos inicial y final en el arco conformado desde el centro de la fuerza de atraccion (estos puntos se refieren al momento de determinar el tiempo de alcance hacia el punto destino y el unto destino mismo) y de la longitud de la cuerda que une ambos puntos. Este planteamiento pretende determinar la forma de una orbita futura en función a dos observaciones (vectores de estado) y al tiempo transcurrido entre ambas observaciones. Una presentacion de este teorema y sus ramificaciones nos desvia hacia el mundo de la dinamica analitica (matematica aplicada), lejos de nuestro tema de maquinas virtuales y programacion. Para comprender en detalle este y otros problemas recomiendo el texto "Astronautical Guidance" por el Dr. Richard Battin.

Un ejemplo de uso de la subrutina LAMBERT es el programa (Major Mode como se denominaba a cada Job ejecutado por el sistema operativo del AGC "EXECUTIVE") P40 que calculaba la orientación predefinida para el IMU y para el motor DPS. Este Major Mode era invocado a través del comando V37E 40E (VERB + 37 + ENTER, luego 40 + ENTER). 

Los usuarios dialogaban con COLOSSUS o con LUMINARY a través de un lenguaje numérico: dos dígitos decimales que indicaban el verbo o acción requerida (VERB o simplemente V) y dos dígitos decimales que indicaban el objeto de la acción (NOUN o N). Sobre el origen de este lenguaje/interface, Eldon C. Hall indicó

-"The DSKY verb-noun combo was quite ingenious.  It was devised by men in my group who were designing the computer.  I think the primary idea was Dr. Ramon Alonso’s, but many of the features of the computer came from the combined efforts of Ramon, Dr. Albert Hopkins, and Hugh Blair-Smith.  That software and the computer test software was written by other members of my group.  I should have said more about that interface.  It was quite unique. At that time communicating with a computer was difficult.  High level languages were very limited and not designed for functions as required for an astronaut interface.  Entering information into computers was by punched cards so the whole idea of the DSKY was unique.  If you notice the first version of the astronaut control panel was complex with analog meters and many switches.  Techniques for digital displays and entering data into computers manually were almost none existent."

La IMU (Inertial Measurement Unit, referida en el párrafo anterior) es otro ejemplo de la idea de virtualización pero trabajado en un contexto distinto al software. Trataremos de definirla lo más claro posible (ver Figura 3.2). Era como el oído interno y la memoria de posición de la aeronave Apollo. Físicamente parecía un balón de basketball muy pesado, inerte y dormido que al ser alimentado con electricidad (al igual que el AGC) se convertía en el órgano de sentido de orientación. En su organización interna incluía un conjunto de ejes (gimbals) sujetos a la infraestructura de la aeronave por un lado y por el otro sujetos a una plataforma (en forma de una mesa pequeña), de tal modo que la plataforma podía permanecer en reposo o moverse independientemente del estado de reposo o movimiento de la infraestructura de la aeronave. La idea central es la independencia de reposo o movimiento, de tal manera que la plataforma podía situarse en una posición artificial o virtual (independiente de la posición real de la aeronave), reproduciendo (localmente) una orientación en el espacio cartesiano (ejes x, y, z) de objetos (estrellas o planetas). Manteniendo una posición virtual respecto, digamos, a la posición de dos estrellas (previamente catalogadas como puntos en un marco referencial llamado Basic Reference Coordinate System o BRCS) los ejes tenían la capacidad de calcular, eléctricamente, la diferencia entre la orientación de la plataforma y la posición de la infraestructura de la aeronave. Esta diferencia (en forma numérica) era interpretada y procesada por el software de navegación para ejercer dos funciones: 1) presentar dicha diferencia a los usuarios (pilotos); 2) modificar, usando los motores cohetes de control, la posición de la aeronave para alinearla a la orientación de la plataforma inercial que a su vez tenía una orientación con respecto al marco referencial (y por ende a los objetos celestes consultados). Adicionalmente, la plataforma inercial tenia un conjunto de tres acelerómetros que medían la aceleración lineal sobre cada uno de los ejes del espacio cartesiano (x-punto, y-punto, z-punto). En general, el conjunto de los tres ejes o componentes (x, y, z) de posición, más los tres componentes de aceleración (x-punto, y-punto, z-punto) y el tiempo, constituían los denominados Vectores de posición y de velocidad, que en conjunto definían el Vector de Estado de la aeronave en relación al marco referencial: un equivalente del Estado en una 5-tupla (sistema algebraico) de autómata finito en la ciencia de la computación. Se debe remarcar, en este punto, el carácter virtual de este mecanismo: establecido un marco referencial, se ubican ciertos objetos celestes en el espacio circundante, se ubica el punto que se quiere medir o cambiar de posición y por último se traducen las ubicaciones a posiciones en tres ejes cartesianos para operarlos de forma analítica. El sistema PGNCS (pings) solo necesitaba conocer la posición de dos objetos celestes para determinar la posición del universo en general. Durante la planificación de los vuelos se diseñaron seis sistemas coordinados de referencia, dos de los cuales eran el Basic Reference Coordinate System y el IMU Stable Member Coordinate System. Se diseñó incluso un ente matemático, en forma de vector, que permitía transformar entre el marco de referencia BRCS y el marco de referencia local del IMU. Este vector se llamaba Reference to Stable Member Matrix (REFSMMAT). El proceso de transformación, usando el ente matemático REFSMMAT, es similar al proceso de transformación descrito en la referencia [1]. Este cambio entre marcos de referencia constituya un ejemplo, a gran escala, de virtualización, de sustitución de un nivel de abstracción por otro, y todo esto fue ideado a finales de la década de 1950. En otra entrada del blog [2] se describe este esquema referencial basado en vectores.



Figura 3.2



Mostramos, a continuación, un fragmento del código fuente de LUMINARY para el procesamiento del Major Mode P52 (alineación de la plataforma estable del IMU con respecto a un par de estrellas). El programa es invocado, como ya indicamos, usando el Display Keyboard - V37E + 52E:

P52E              TC          BANKCALL  # DO STAR SELECTION
                      CADR     PICAPAR
                      TC           P52I               #  2 STARS NOT AVAILABLE
P52F              TC          INTPRET       #  2 STARS AVAILABLE
                      CALL
                                      R51

R51               EXIT
                      CAF        BIT1
                      TS           STARIND
                      TS           MARKINDX
R51.2             TC          INTPRET
R51.3            CLEAR    CLEAR
                                     TARG2FLG
                                     TARG1FLG
                  EXIT
                  TC              PHASCHNG
                  OCT           05024     #  RESTART GR 4 FOR R52-R53
                  OCT           13000
                  INDEX       STARIND
                  CA              BESTI
                  EXTEND
                  MP              1/6TH
                  TS               STARCODE
R51DSP    CAF            V01N70
                  TC               BANKCALL
                  CADR         GOFLASHR
                  TC              GOTOP00H
                  TC              +5
                  TC              -5
                  CAF           SIX
                  TC              BLANKET
                  TCF            ENDOFJOB
                  TC              CHKSCODE
                  TC              FALTON
                  TC              R51DSP
                  TC              INTPRET
                  RTB            CALL
                                     LOADTIME
                                     PLANET
                  SSP            LXA,1
                                    S1
                                    0
                                    STARIND
                  TIX,1
                                    R51ST
                  STCALL   STARSAV2       #  2ND STAR
                                    R51ST      +1
R51ST       STORE      STARSAV1       #  1ST STAR
                  EXIT


Continuando con la descripción del Intérprete (o computador hecho en Software), vamos a descomponerlo un poco. En su corazón encontramos al "Interpretive CPU" o Dispatcher. Esta es la rutina principal encargada de decodificar los Operadores de cada Ecuación. Es este "Interpretive CPU" el que implementa la "Jump Table" que señalamos en una imagen anterior. Dentro de cada Ecuación, se incluyen dos (2) Operadores de la siguiente manera: 

OP-CODE 1 OP-CODE 2
ADR 1
ADR 2

OP-CODE 3 OP-CODE 4
ADR3
ADR4

El Assembler YUL traduce estas Ecuaciones en palabras de memoria organizadas de la siguiente manera:

bit 15-----------87-------------1
OP-CODE 1 OP-CODE 2
AAAAAAAAA ADR 1 AAAAAAAAAA
AAAAAAAAA ADR 2 AAAAAAAAAA
OP-CODE 3 OP-CODE 4
AAAAAAAAA ADR 3 AAAAAAAAAA
AAAAAAAAA ADR 4 AAAAAAAAAA

Como se aprecia en la figura 3, el programador invoca al "Interpretive CPU" a través de la instrucción "TC INTERPRET" antecediendo al conjunto de instrucciones de "Alto Nivel" que conforman la Ecuación matemática de programa. En todo momento el "Interpretive CPU" debía conocer si se requería una operación de precisión doble, precisión tríple, operación matricial u operación vectorial. El "OP-CODE" la operación de "Alto Nivel" contenía esta información.

Vamos a implementar un ejemplo de formula matemática como seudo-instrucciones (tomado de "E-1758 - Organization of Computation and Control in the Apollo Guidance Computer" - Lawton, T. J. y  Muntz, C. A.). Tomemos la siguiente formulación:

z = a * M(x+y) , tal que "a" es un escalar y "M" una matriz 3x3

se traduce al seudo-lenguaje como

                                     MXV
              VXSC
                                     X
                                     Y
                                     M
                                     A
              STORE          Z


El siguiente es el fragmento del listado en Assembler YUL - programa Colossus (Software del módulo de comando Apollo) correspondiente a la Jump Table del "Interpretive CPU" - Tomado del Virtual AGC compilado y mantenido por Ronald Burkey. En este fragmento veremos los enlaces a subrutina para muchas de las seudo-instrucciones que hemos visto en la subrutina LAMBERT:

CodigoOperación        Instrucción en Assembler YUL

16454     INDJUMP    TCF      VLOAD     #  00 -- LOAD MPAC WITH A VECTOR.
17040                          TCF      TAD       #  01 -- TRIPLE PRECISION ADD TO MPAC.
17624                          TCF      SIGN      #  02 -- COMPLEMENT MPAC (V OR SC) IF X NEG.
17350                          TCF      VXSC      #  03 -- VECTOR TIMES SCALAR.
16652                          TCF      CGOTO     #  04 -- COMPUTED GO TO.
16437                          TCF      TLOAD     #  05 -- LOAD MPAC WITH TRIPLE PRECISION.
16021                          TCF      DLOAD     #  06 -- LOAD MPAC WITH A DP SCALAR.
17573                          TCF      V/SC      #  07 -- VECTOR DIVIDED BY A SCALAR.
16450                          TCF      SLOAD     #  10 -- LOAD MPAC IN SINGLE PRECISION.
16567                          TCF      SSP       #  11 -- SET SINGLE PRECISION INTO X.
16472                          TCF      PDDL      #  12 -- PUSH DOWN MPAC AND RE-LOAD IN DP.
17303                          TCF      MXV       #  13 -- MATRIX POST-MULTIPLIED BY VECTOR.
16526                          TCF      PDVL      #  14 -- PUSH DOWN AND VECTORLOAD.
16575                          TCF      CCALL     #  15 -- COMPUTED CALL.
17306                          TCF      VXM       #  16 -- MATRIX PRE-MULTIPLIED BY VECTOR.
17565                          TCF      TSLC      #  17 -- NORMALIZE MPAC (SCALAR ONLY).
17543                          TCF      DMPR      #  20 -- DP MULTIPLY AND ROUND.
17546                          TCF      DDV       #  21 -- DP DIVIDE BY.
17552                          TCF      BDDV      #  22 -- DP DIVIDE INTO.
17570                          TCF      GSHIFT    #  23 -- GENERAL SHIFT INSTRUCTION
16720                          TCF      VAD       #  24 -- VECTOR ADD.
16716                          TCF      VSU       #  25 -- VECTOR SUBTRACT.
17005                          TCF      BVSU      #  26 -- VECTOR SUBTRACT FROM.
17300                          TCF      DOT       #  27 -- VECTOR DOT PRODUCT.
17427                          TCF      VXV       #  30 -- VECTOR CROSS PRODUCT.
17374                          TCF      VPROJ     #  31 -- VECTOR PROJECTION.
16754                          TCF      DSU       #  32 -- DP SUBTRACT.
17031                          TCF      BDSU      #  33 -- DP SUBTRACT FROM.
16744                          TCF      DAD       #  34 -- DP ADD.
16300                          TCF      +0        #  35 -- AVAILABLE
17541                          TCF      DMP1      #  36 -- DP MULTIPLY.
17562                          TCF      SETPD     #  37 -- SET PUSH DOWN POINTER (DIRECT ONLY)
12371    MISCJUMP  TCF      AXT       #  00 -- ADDRESS TO INDEX TRUE.
12376                          TCF      AXC       #  01 -- ADDRESS TO INDEX COMPLEMENTED.
12401                          TCF      LXA       #  02 -- LOAD INDEX FROM ERASABLE.
12405                          TCF      LXC       #  03 -- LOAD INDEX FROM COMPLEMENT OF ERAS.
12411                          TCF      SXA       #  04 -- STORE INDEX IN ERASABLE.
12417                          TCF      XCHX      #  05 -- EXCHANGE INDEX WITH ERASABLE.
12433                          TCF      INCR      #  06 -- INCREMENT INDEX REGISTER.
12442                          TCF      TIX       #  07 -- TRANSFER ON INDEX.
12425                          TCF      XAD       #  10 -- INDEX REGISTER ADD FROM ERASABLE.
12436                          TCF      XSU       #  11 -- INDEX SUBTRACT FROM ERASABLE.
12514                          TCF      BZE/GOTO  #  12 -- BRANCH ZERO AND GOTO
12521                          TCF      BPL/BMN   #  13 -- BRANCH PLUS AND BRANCH MINUS.
12474                          TCF      RTB/BHIZ  #  14 -- RETURN TO BASIC AND BRANCH HI ZERO.
12534                          TCF      CALL/ITA  #  15 -- CALL AND STORE QPRET.
12543                          TCF      SW/       #  16 -- SWITCH INSTRUCTIONS AND AVAILABLE.
12504                          TCF      BOV(B)    #  17 -- BRANCH ON OVERFLOW TO BASIC OR INT.
                                   COUNT*   $$/INTER                             
                                    BANK     0         #  00 -- EXIT -- DETECTED EARLIER.
13207   UNAJUMP    TCF      SQRT      #  01 -- SQUARE ROOT.
13527                          TCF      SINE      #  02 -- SIN.
13516                          TCF      COSINE    #  03 -- COS.
13607                          TCF      ARCSIN    #  04 -- ARC SIN.
13611                          TCF      ARCCOS    #  05 -- ARC COS.
13174                          TCF      DSQ       #  06 -- DP SQUARE.
12116                          TCF      ROUND     #  07 -- ROUND TO DP.
17637                          TCF      COMP      #  10 -- COMPLEMENT VECTOR OR SCALAR
13232                          TCF      VDEF      #  11 -- VECTOR DEFINE.
13023                          TCF      UNIT      #  12 -- UNIT VECTOR.
13176                          TCF      ABVALABS  #  13 -- LENGTH OF VECTOR OR MAG OF SCALAR.
13245                          TCF      VSQ       #  14 -- SQUARE OF LENGTH OF VECTOR.
16323                          TCF      STADR     #  15 -- PUSH UP ON STORE CODE.
13274                          TCF      RVQ       #  16 -- RETURN VIA QPRET.
13247                          TCF      PUSH      #  17 -- PUSH MPAC DOWN.


Existe una seudo-instrucción RTB la cual era usada para "fabricar" nuevas seudo-instrucciones para el modo Intérprete. Funcionaba en combinación con una Subrutina DANZIG que retornaba el control a la siguiente seudo-instrucción a ser ejecutada. El siguiente es un ejemplo de uso de RTB:


// Primero se invoca la nueva seudo-instrucción (no existente en el cuerpo original del Intérprete en la
   memoria Core-Rope de solo lectura - ejemplo el cuerpo de programa Luminary).


43034        PTOACSM                      RTB      BON                                  
26723                                                 MOVEPCSM                             
04303                                                 CMOONFLG                             
26716                                                 SETMOON                              


// A continuación se define el cuerpo de la nueva seudo-instrucción que formará parte del repertorio disponible a los programadores/matemáticos.

03036        MOVEPCSM          TC            SETBANK                              
55500                                         TS            DIFEQCNT                             
51500                                         INDEX    DIFEQCNT                             
31554                                         CA           RRECTCSM                             
51500                                         INDEX    DIFEQCNT                             
55502                                         TS            RRECT                                
11500                                         CCS         DIFEQCNT                             
12724                                         TCF         MOVEPCSM   +1                        
06061                                         TC           DANZIG                               

El uso de un "Interpretive CPU" dentro del AGC cobraba un precio en consumo de memoria. 700 palabras de la memoria fija (Rope Memory) y 35 palabras de la memoria volátil (Eresable Memory) eran ocupadas por este computador hecho en Software. Sin embargo, el contra-balance era el ahorro en llamadas a Subrutinas (guardar estado ; llamada ; ejecución ; recuperar estado ; retorno) y la posibilidad dada a los programadores de contar con un lenguaje pseudo-matemático que facilitaba traducir las ecuaciones expresadas de forma abstracta en los diseños técnicos de navegación y guía.
Al programar en instrucciones de "Alto Nivel", el ingeniero/programador trabajaba sobre un grupo de máquinas virtuales "apiladas" cada una con su respectivo proceso de fabricación (ensamblado del programa fuente ; generación de código de máquina virtual o "real" a ser luego interpretada por la lógica de micro-secuenciamiento del AGC ; generación de la información para manufactura de la memoria física). El Dr. Albert Hopkins (diseñador del sumador y de la lógica de secuenciamiento del AGC) describió parte de esta traducción/manufactura "apilada" en el informe Space Guidance Navigation and Control - R500 MIT, 1965:
 

- Cita Dr. Albert Hopkins -"It may be instructive to trace briefly the history of part of a mission program-- re-entry guidance, for example -- from the conceptual stage to actual readiness for flight,

A. The mathematical ideas are blocked out roughly, tolerances guessed,
variables and effects judged to be significant or negligible,
such decisions are left to be settled by trial and error.

B. A procedure employing the concepts is worked out, using one
mathematical model for the spacecraft with its guidance and
navigation system, and another for the environment. This procedure
is then employed in a data processor program for testing.

C. The program is compiled, tested, revised, and retested, until the
mathematical properties of the procedure are satisfactory.
Because these programs retain 2 to 4 more digits of precision
than double-precision. AGC programs, the variables at this stage
may be considered free of truncation or round-off error. It
is desirable to do as much pinning down of the procedure as
possible in steps B and C, since these programs run a good
deal faster than real time.

D. An AGC program is written by translating the relevant parts of
the program into AGC assembly language; the more mathematical
parts, such as position and velocity updating, into interpretive
language, and the more logical, such as turning reaction control
jets on and off, into basic.

E. In combination with the utility programs described previously, the AGC
program is assembled. After two or three revisions, when the grammatical
errors that can be detected by the assembler are eliminated, the program
checkout is begun by use of the AGC simulator, another data processor
program, which is described later. In advanced stages of checkout, this
simulation incorporates the part of the program of steps B and C that
models the environment. AGC simulation discovers the numerical properties
of the procedure, since all effects of scaling, truncation, and roundoff
are present. Steps D and E are repeated until the program fulfills the
goals determined in step A. Severe problems may send the engineers back
to step B, or even to step A.

F. Up to this point, everything has been done on the initiative of the 3- or 4-
man "working group'' whose specialty is the particular phase of the mission.
Now, however, this AGC program must be integrated with the rest of the
mission program. Using the updating facilities of the assembler, the working
group transfers its own coding to the mission program and, in qooperation
with the group in charge of program integration, checks out not only
its operation but its ability to "get along with" the other parts of the mission
program, e. g. , staying within its part of the time budget. Here again,
the AGC simulator is the primary tool.

G. At this point, or sometimes before step F, it is necessary to run an AGC
attached to guidance and navigation and ground support equipment. This is
the last procedure devoted entirely to the checkout of an AGC program.
H. When all of steps A through G for a whole mission program have been completed,
the assembly listing of the program is given the status of an engineering
'drawing. Only now are rope memory modules wired; and further
testing is for the benefit of other subsystems as much as of the program."
- Fin de la cita -

1950s fueron los años dorados para la técnica de Interpretes (Virtual Machines). El uso de Virtual Machines como la máquina PL/0 (Pascal) del Prof. Niklaus Wirth a comienzos de los 1970s, el Tiny BASIC de finales de 1970s y como la VM Java o el Run-Time .NET en los años 1990s y 2000 podemos catalogarlos como descendientes de la vieja técnica de programación de los años 1950s (en el caso de la Java VM y el Run-Time .NET pudiéramos tratarlo más como un "revival" de la idea PL/0 del Prof. Wirth). Incluso, para el caso del computador Apollo: al momento de crear el complejo de simuladores para los módulos lunar y de comando y sus comunicaciones con la red global de rastreo y telemetría (Deep Space Network) simulada, los diseñadores tuvieron que crear un simulador para el computador Apollo dentro de uno de los computadores Honeywell. El computador Apollo "real" estuvo listo para 1964. Aquí es importante separar estos desarrollos sobre Virtual Machines de las técnicas de simulación tradicionales. Estas últimas tienen su propia cronología y en algún momento durante los años 1960s se tocaron con las VM por así decirlo. Sin embargo, las técnicas de simulación basadas en modelos matemáticos de ecuaciones diferenciales tuvieron su propia historia, muy densa por cierto y estaban soportadas por computadores analógicos (redes de tubos al vacío electrónicos amplificadores o transistores amplificadores).

HB-S: Within the IL, the Mod 3C Interpreter was preceded by a much smaller one running on Mod 1B (1960), which I think I mentioned in my Eldon annotations. It was followed by one for AGC Block I (1962) that I don't remember specifically, but our 1963 IEEE paper that was published in Bell and Newell's Computer Structures: Readings and Examples shows that it was a similar predecessor to the AGC Block II Interpreter (1964 probably) with its reverse Polish prefix "parenthesis-free" notation.

HB-S: Sometime around 1960 the control computer for the Wright Brothers Wind Tunnel at MIT was a Bendix G-15 (or maybe G-16?). Its native instruction repertoire was generally regarded as so complex and obscure as to be almost unusable, so my friends there always coded in an interpretive language that I guess would be the "Intercom 1000" that turns up when you Google "Bendix G-15."

HB-S: I certainly share Knuth's reverence for the IBM 650, but I would call it a '50s mini-computer, not a PC. Its CPU (with a control panel at one end) was about 3' wide by 6' high by 8' deep, and the card reader/punch was perhaps 5' wide by 4' high by 2' deep. The usual printers, IBM 402 or later the IBM 407, were about 5' wide by 4' high by 4' deep including the paper stacker; these were not connected to the 650, and you had to carry output cards from the punch to the printer. Anyway, all that plus a desk-size keypunch would fit handily in a moderate-size room, say 12' by 9'. (If you want to identify a '50s PC, I'd nominate the Electrodata 101, a drum-storage machine with a cute little pegboard for programming.)

HB-S: In 1957-9 I used an ordinary 650 at Harvard, sometimes experimenting with an interpreter called BLISS (Bell Labs Interpretive System), which emulated a three-address machine.

HB-S: The 650 I used at the Lab, however, was something grander and deserved the name of "mainframe." It included floating-point arithmetic, and some Boolean combinatorial instructions made up specially for MIT. Attached to it was a hard disk unit ("RAMAC") the size of a large refrigerator, and an IBM 727 tape drive so that MAC programs compiled on the 650 could be taken to an IBM 704 "supercomputer" at the GE engine works in Lynn, on the North Shore. Card-driven machines in the room included a plotter and a paper-tape punch in addition to the 407 printer.



Primeros trabajos en el Instrumentation-Lab (luego Draper Lab), y en especial sobre el mítico sistema YUL como Cross-Assembler (posiblemente uno de los primeros en la historia)

HB-S: All the Polaris work took place before I joined the Lab, but I learned a few things about the "welded stick" construction, and about the Polaris computer. Fact 1 (as I remember it) is that the Polaris computer was not a software-programmed device but a digital differential analyzer (DDA). In a funny way, those were like FPGAs, because you programmed them by connecting the elements (digital integrators with respect to time) together: the output of one to one or more inputs of others.

HB-S: That means that what Hal Laning wrote was not parallel to the YUL system's "manufacturing" function, but much closer to Delphi (the "oracle of Apollo"), written by Bob Morse to guide the Gardner-Denver wire-wrap machine. Both programs were converting encoded circuit diagrams into backplane interconnection sequences. I know that Delphi produced a medium (probably Mylar tape like YUL's output) that actually controlled the machine, but I've no idea what Hal's code produced, beyond what you say here about "draw the welded wire matrix." We certainly used ink-on-paper plotters at the time, and that would have made sense in the Polaris context. I'd guess that the drawings were of several layers, first the bottom layer of welds nearest the backplane, then a layer of welds that had to be one level up because they crossed the wires of the first layer, and so on. The welding would have been done manually, following the drawings, with no need for the welder to have any understanding of what logic each connection implemented. Perhaps a layer of potting was applied between one layer and the next ... but there's a lot of guesswork on my part here. You should probably ask Eldon directly how it was done.



En consulta con Eldon Hall (Julio 1999) sobre los procesos de manufactura de los gabinetes y del diseño mecánico del computador Apollo, comentó lo siguiente:

- Cita Eldon Hall -
"I thought you might be interested in some efforts to develop CAD back in the stone age. In the late 1950s Laning wrote a program to lay out the welded wire matrix for the Polaris computer. This would be a job similar to laying out a multilayer printed circuit board. He was successful except the program would split up similar functional elements of logic. The logic designers were not happy with that feature so all the layouts were done manually. The manual approach was carried over into Apollo. The only CAD was in the module to module wiring which generated a set of punched cards that operated the wire wrap machine. That program was developed for Polaris and used for Apollo also.

Dividing the circuits into modules was a major effort in Polaris and Apollo. The circuit designers worked with mechanical engineers to accomplish a satisfactory placement of the electrical components between modules and within modules. Then the mechanical designer completed the module design and detail draftsmen documented the drawings. The mechanical design had to consider heat transfer to keep the components cool and structural strength to survive the vibration, shock and acceleration of the flight."
- fin de la cita - Tomada de un correo personal de Julio 1999.


Figura 4.

Figura 4: manufactura del gabinete contenedor de los Logic Modules (utilizando una máquina herramienta Gardner-Denver con la técnica Wire-Wrap muy utilizada durante los años 1950's y comienzo de los 1960's).



Figura 5.

La figura 5 musra la manufactura de las memorias Core Rope que contenian el Software y datos constantes en el computador Apollo. En estas Core Rope Memory cada bit era "tejido" por damas de edad avanzada que de forma paciente y asistidas por una máquina herramienta hacían la operación de tejido de cada bit. La maquina herramienta era dirigida por un Paper Tape (lo que Blair-Smith llama Mylar Tape) generado por el Assembler YUL en una de sus pasadas. Extendiendo esto último, Blair-Smith escribió en sus anotaciones al libro de Eldon C. Hall ("Annotation to Eldon Hall's Journey to the Moon") lo siguiente:

- Cita Blair-Smith -
This was the other major function of my "Yul System," which I called manufacturing a program. Once the assembled program had been tested to the point where the powers that be were willing to invest the long fabrication cycle to make it into rope, Yul encoded the binary form of the code into a highly specialized 8-channel teletype code (specified by Raytheon for their machine) and punched that into a "paper" tape. As Eldon says, the tape we used for this purpose was not the usual pink paper at all but the more robust material, Mylar: almost untearable, impervious to oil and other factory-environment hazards, and cannot develop extra holes by any small accident.

The image (aquí refiere al fragmento superior derecho de la figura 5 - la dama tejedora de bits) shows the tape reader with its takeup spool on the right, driving the larger machine. Each 8-bit row of the tape set relay switches; when settings were made by reading half a dozen or so of these rows, the fabricating machine shifted the rope frame up or down, and toward or away from the operator. The white plastic funnel (at the left end of the needle in the operator's hand) stayed in a fixed position, and the motion of the rope frame brought a particular core in line with the axis of the pair of funnels: the one you can see and its mirror image on the other side. The operator had a springlike coil of wire inside the needle; what she had to do was poke the needle carefully through the bundle of wires already passing through that core (without scraping any insulation off the 100 or so already threaded through it!), thus adding one more wire to the bundle. Then she pressed a switch to let the machine read more tape and advance the next core to the funnel position, and she passed the needle through the opposite way.- Fin de cita Blair-Smith -




El proceso de traducción desde un listado fuente en Assembler hacia un paper tape con instrucciones de "tejido" es, en cierto modo, similar al proceso de traducción que en otras épocas hacían los operadores de los telares Jacquard: primero se trazaba un boceto (dibujo) de las figuras a ser tejidas; luego, se creaba una secuencia de pasos a ser ejecutados por el cabezal ("head") del telar; la secuencia de pasos era "traducida" de forma manual en tablillas perforadas, las cuales guiaban los pasos del telar. También se puede establecer la similitud entre estos procesos de la siguiente manera: el proceso de traducción del Assembler YUL tiene como objetivo el "tejer" una secuencia de pasos para el procesamiento de datos, mientras que el proceso del telar Jacquard tenía como objetivo el "tejer" imágenes de forma secuencial - Imagen tomada de "An Illustrated History of Computers" por John Kopplin - 2002
Figura 6.

HB-S: Whirlwind was hardware, MIT's (not the Lab's) first in-house computer, and I don't know what Hal did for it. I never used or saw George either, and I don't even know if it generated Whirlwind code, but I'll bet it did, because if it had generated IBM 650 code, I'd have seen and possibly used it. But it was definitely something in the past by 1959, remembered mostly by the reason for its name: "let George do it." What we used to convert algebraic/calculus expressions to 650 code (and later IBM 704 code as well) was MAC, which stood for something really dumb like "Machine Algebraic Compiler," but it was way ahead of its time, and the Shuttle's HAL/S compiler is really just a minor elaboration of MAC.

"George" era uno de los primeros lenguajes algebraicos. Permitía escribir programas utilizando notación algebraica normal (incluso con subíndices y paréntesis). La historia es larga pero (siguiendo los trabajos de Donald Knuth y del propio John Backus) en algún momento de 1954 John Backus y el equipo de IBM que estaba trabajando en el diseño del lenguaje FORTRAN visitaron el MIT/IL para ver los trabajos de Halcombe Laning con "George". Este hecho está registrado en un trabajo sobre lenguajes de programación de alto nivel en los 1950s por Donald Knuth y Luis Trapp Pardo ("The Early Development of Programming Languages", Knuth y Pardo) y en un artículo escrito por el propio John Backus ("Programming in America in the 1950s", Backus). También se relata el encuentro en el libro "Introduction to the Mathematics and Methods of Astrodynamics" por el prof. Richard Battin. Así que "George" pudiera ser considerado como un padre de FORTRAN.

Este uso "no-numérico" (más bien de manejo de símbolos) era una idea que parecía impresionante a muchos técnicos y matemáticos usuarios en los años 1950s y comienzo de los 1960s. En una entrevista realizada en 2007 por el Computer History Museum titulada "Oral History" el Profesor Don Knuth relató la siguiente anécdota. Knuth relata su primer encuentro con un traductor de lenguaje algebraico llamado "IT" que se ejecutaba en una IBM 650. Knuth perforaba una expresión algebraica en una tarjeta, luego colocaba la tarjeta en la lectora del computador y en respuesta la IBM 650 le devolvía el equivalente de la expresión algebraica original en instrucciones de la máquina IBM 650 (este fue el inicio de la carrera de Knuth como constructor de compiladores durante los años 1960s):

- Cita de la entrevista - Computer History Museum
"Knuth: Yeah, the seeds were planted at Case in the following way. First I learned about the 650. Then, I’m not sure when it was but it probably was in the summer of my freshman year, where we got a program from Carnegie -- where you were a student --that was written by Alan Perlis and three other people.

Feigenbaum: “IT”.

Knuth: The IT program, “IT”, standing for Internal Translator.

Feigenbaum: Yeah, it was Perlis, [Harold] van Zoeren, and Joe Smith.

Knuth: In this program you would punch on cards a algebraic formula. You would say, “A = B + C.” Well, in IT, you had to say, “X1 = X2 + X4.” Because you didn’t have a plus sign, you had to say, “A” for the plus sign. So you had to say, “X1 Z X2 A X4.” No, “S,” I guess, was plus, and “A” was for absolute value. But anyway, we had to encode algebra in terms of a small character set, a few letters. There weren’t that many characters you could punch on a card. You punch this thing on a card, and you feed the card into the machine. The lights spin around for a few seconds and then -- punch, punch, punch, punch -- out come machine language instructions that set X1 equal to X2 + X4. Automatic programming coming out of an algebraic formula. Well, this blew my mind. I couldn’t understand how this was possible, to do this miracle where I had just these punches on the card. I could understand how to write a program to factor numbers, but I couldn’t understand how to write a program that would convert algebra into machine instructions.

Feigenbaum: It hadn’t yet occurred to you that the computer was a general symbol-manipulating device.

Knuth: No. No, that occurred to Lady Lovelace, but it didn’t occur to me..."
- Fin de la cita - Computer History Museum

En el capítulo "Boundless interests, A common thread" del libro "Out of Their Minds, The Lives and Discoveries of 15 Great Computer Scientists" (Shasha D., Lazere C. - 1998), el profesor Knuth declara lo siguiente:

- Cita - "Out of Their Minds"
"I got into compilers because I thought the most amazing thing you could do with computers was to have them write their own programs. When computing is applied to computing, that's when computer science reaches an ultimate completeness."- Fin de la cita - "Out of Their Minds"

Para apreciar esa plenitud de idea que refiere Knuth en la cita anterior se recomienda estudiar (y comparar en sus funciones) dos ejemplos que aparecen en el Volumen 1 "The Art of Computer Programming" de Knuth: el Intérprete de la máquina MIX y el programa de diferenciación simbólica en la sección de árboles binarios (el primero recorre una secuencia de instrucciones de máquina, mientras que el segundo "camina" a través de un árbol de símbolos). El apreciar y comparar ambas formas de secuenciar y movimiento constituyen la manera perfecta de comprender esta idea fundamental. En la historia hay muchos ejemplos de las funcionalidades que se derivan de ideas fundamentales y del uso preciso de las herramientas e ideas, las cuales han impactado al ser humano de mente abierta. Tal fue el caso de la solución al problema de determinar la longitud en navegación. Durante muchos años se pensó que el problema de determinar la longitud de un punto en el mar solo tenía solución dentro del ámbito de la observación del movimiento de los cuerpos celestes (lograr manejar la observación de lunas, sol, planetas como si fuesen un gran mecanismo de relojería). Existía, claro, la concepción que el conocimiento preciso de la diferencia entre el tiempo en el punto geográfico de inicio del viaje y el tiempo local del navío daba el elemento fundamental para el calculo, pero los relojes mecánicos en aquella época (finales del siglo XVI y las primeras décadas del siglo XVII) perdían su sincronización (basada en el movimiento de péndulos) por el movimiento del navío. De pronto, un día, un carpintero inglés llamado John Harrison apareció ante el "board" científico (encabezado por el propio Isaac Newton) ordenado por el rey George III. Traía en sus manos la documentación de un reloj de precisión de madera que había desarrollado y el cual no perdía (aparentemente) su sincronización y que (aparentemente) era perfecto para la navegación en mar abierto. La mayoría de los miembros de este "board" eran astrónomos y estaban convencidos que solo a través de la observación del cielo (ese gran mecanismo de relojería aparente, aúnque Newton consideraba que Dios, en tanto en cuanto, re-ajuste dicho mecanismo) era posible determinar la longitud en un punto en el mar. No entendían que, a través de la mecánica de precisión, era posible determinar el tiempo de forma eficaz en el mar. La moraleja de este episodio es que se requiere de seres humanos con mente abierta a nuevas ideas y con una actitud experimental y progresista. Como vemos en su relato, Knuth muestra una mente abierta y una actitud de curiosidad ante lo desconocido. A tal punto que una vez confrontado con eso desconocido, luego se fue a estudiarlo con tal profundidad que se hizo un experto en el tema (la motivación para escribir sus volúmenes del arte de la programación fue el tema de construcción de compiladores).


El computador Whirldwind y los primeros lenguajes algebraicos

Lo novedoso de FORTRAN (y los lenguajes predecesores como George, MAC) es que daba al matemático/ingeniero la posibilidad de incluir en un programa expresiones algebraicas utilizando los tradicionales signos de agrupación (paréntesis) e incluso sin hacer uso de ellos (a través de un sistema de precedencia de operaciones incluida en el programa traductor del lenguaje). Por ejemplo, la siguiente expresión podía ser escrita con y sin símbolos de agrupación:

X.AND..NOT.P.EQ.Q/R*S.OR.L/M.LT.5 - utilizando la precedencia de operadores de la gramática del lenguaje

(X).AND.(.NOT.(P.EQ.(Q/(R*S)))).OR.((L/M).LT.5) - utilizando separadores

Otra facilidad que otorgaba el FORTRAN a los programadores de aplicaciones no-numéricas era el uso especial de GO TO múltiple (COMPUTED GOTO). En FORTRAN era posible expresar una "Jump Table" utilizando una variable como índice y varias etiquetas que apuntan a otras partes del programa (una facilidad que es de mucha utilidad en un programa Intérprete o Virtual Machine):

GO TO (100,200,300,400,500,600,700,800) apuntador

100 .....
200 .....
300 .....
...

El siguiente enlace web lleva a una entrevista realizada a Bob Hughes (Lawrence Livermore National Laboratory) en 1997. Hughes formó parte del equipo de John Backus para el desarrollo del compilador FORTRAN. Uno de los aportes de Hughes fue su idea de utilizar letras-identificador para indicar el tipo de dato de las variables. De esa manera toda variable cuyo identificador que comienza por las letras "i", "j", "k" tiene el tipo de dato Integer. En un momento dado de la entrevista Hughes señala al Assembler del computador CDC 6600 como el mejor. Esta opinión es compartida por quien escribe. Realmente ese lenguaje Assembler llamado COMPASS es muy simétrico en su estructura y modelo de programación: toda instrucción contiene tres (3) registros y las operaciones del tipo Load/Store se hacen a través de registros: http://www.computer-history.info/Page1.dir/pages/Hughes.html

Otro punto interesante son las extensiones que se le hicieron al FORTRAN básico. Una de ellas le otorgaba al lenguaje la posibilidad de manejar estructuras de datos de Listas. La librería FLPL (Fortran List Processing Library) fue creada con este fin. De nuevo el MIT jugó un papel importante en estas iniciativas, pero ahora desde su departamento de Artifitial Inteligence con el Prof. John McCarthy. En el año 1957, McCarthy investigaba la creación de un lenguaje para manejo de expresiones algebraicas pero para su aplicación en la AI. A partir de este estudio nació el lenguaje LISP.



Figura 7.


La figura 7 es una muestra de programas escritos en "George" (tomada del paper "A Program for Translation of Mathematical Equations for Whirlwind", Laning & Zierler - 1954). La figura 8 muestra un "Flexowriter" como el utilizado para perforar las líneas de código en Paper Tapes que luego son leidos por el computador Whirlwind para su compilación. Los Paper Tapes también fueron usados en la manufactura del Software para Apollo: el Assembler YUL generaba un Paper Tape que era utilizado para guiar la máquina herramienta para el "tejido" del Software en las memorias Core Rope de solo lectura.


Figura 8.


HB-S: And yes, they were fairly common in those days. Bell Labs wrote BLISS for the 650 ("Bell Labs Interpretive [Something] System") which simply featured 1-digit op codes with 3 addresses of 3 digits each, plus some 4-digit op codes with 2 addresses--that was a considerable improvement over the 650's native architecture of 2-digit op codes with one 4-digit address and a 4-digit "half-address" that pointed to the next instruction. The Bendix G-16 instruction repertoire was so hard to understand that somebody wrote an interpreter for it just to have an assembler-level language that a reasonable person could write and read; that's how it was used in MIT's Wind Tunnel Lab. And there were many more that I don't remember offhand.

HB-S: It took no great leap of creativity to see that small control computers (the Mars series and Apollo) had such a small repertoire of instructions that an interpreter was the obvious way to have an assembler-level language that was writable and readable by aerospace engineers rather than computer wizards, and to reduce required memory space as well. Also, I'm pretty sure that Al Hopkins and Ray Alonso thought up the Mars Mod 1 interpreter before I came to the Lab -- it wasn't my invention!



Figura 9.

Whirlwind, un gigante metálico de tubos de rayos catódicos y memoria de núcleos magnéticos (Magnetic Core) ya no existe. Sin embargo se conservan algunas de sus partes. En esta fotografía de 1998 aparecen Eldon Hall (director del proyecto Apollo Guidance Computer) y el autor de este trabajo junto a algunos de los arreglos de Tubos electrónicos del Whirlwind que se conservan en el museo del computador en Boston, Ma. Creo que la muestra es parte de la unidad aritmética del computador. Esta afirmación la hago siguiendo fotografías e información que aparecieron en un artículo sobre Whirlwind ("The Whirlwind 1 Computer", Robert R. Everett - 1951) reproducido en el libro "Computer Structures: Readings and Examples" de Gordon Bell (libro extraordinario que recomiendo ampliamente). En la figura 10 aparece el arreglo completo tal y como era en 1950s y el autor del artículo Robert Everett probando un simulador de vuelo en tiempo real manejado por Whirlwind 1 (el computador era parte de todo un sistema de simulación en tiempo real). Whirlwind fue uno de los primeros computadores (algunas referencias del MIT indican que fue el primero) con memoria del tipo Magnetic Core. Además, según un artículo de Maurice Wilkes de 1969 ("The Growth of Interest in Microprogramming", Wilkes), el propio Wilkes indica que la Matriz de Diodos (Diode Matrix) de control del Whirlwind pudiera ser tomada como un ancestro de la memoria de microinstrucciones en el concepto de Microprogramación que Wilkes ideó en los años 1950s. Conectando esto último con la introducción que hicimos al comienzo del escrito: las Diode Matrix como la del whirlwind eran las madres de las instrucciones de máquina complejas microprogramadas como la instrucción BCT (brach on count - especial para controlar y efectuar ciclos constantes de control como "FOR") de la IBM 370, de la instrucción CCS (Count-Compare-Skip) del computador Apollo y además fueron las abuelas de la Virtualización de computadores de hoy día (toda Virtualización lleva implícita un proceso de Interpretación de instrucciones).

El Dr. Richard Battin dio una reseña sobre Whirlwind durante una entrevista otorgada al NASA Johnson Space Center Oral History Project.

- Cita
"MIT's Whilrwind computer was housed in an enormous building, and it had very little capability. It had 1,024 16-bit words of memory. When they turned [the computer] on, they had to first notify the Cambridge powerplant, because it put such a [strain] on their system that they had to be prepared for this. So you have a very primitive computer that's using enough power [for] the city…[to be concerned]. That was the state of the art in computers, and for us to even be talking…[of a computer to be carried in a small spacecraft seemed quite far-fetched. Therefore,] some of the study money…[from NASA] was used…to perfect [an] on-board flight computer. It actually was the grandfather of the Apollo guidance computer."- Fin de la cita




Figura 10.


Organización interna del Apollo Guidance Computer

Blair-Smith hace referencia al trabajo del Dr. Ramón Alonso y Albert Hopkins. Alonso trabajó con Hal Laning en otro proyecto previo al Apollo que consistía en enviarle una sonda al planeta Marte a finales de los 1950s para tomarle fotografías. El computador que ellos diseñaron para aquella sonda utilizaba un elemento conmutador llamado Core-transistor logic: se trata de una tecnología de transistor que solo consume energía (Watts) cuando se activa para hacer algún calculo. El resto del tiempo está dormido consumiendo muy poca energía durante el largo viaje al planeta Marte. Durante mi visita al Draper Lab en 1998 pude ver la maqueta original de esta sonda en el techo de la entrada al laboratorio. Un poco de historia del espacio. Otro punto al cual hace referencia Blair-Smith es el compilador "George". Se trata de un verdadero ancestro del FORTRAN. En su libro "An Introduction to the Mathematics and Methods of Astrodynamics" el Dr. Richard Battin (colega de Laning y quien fuera el jefe directo de Eldon Hall durante el proyecto del computador Apollo) describe cómo el comité de IBM encabezado por John Backus quienes tenían la labor de buscar ideas para el desarrollo de un lenguaje de programación algebraico estándar, visitaron a Laning en el MIT/IL y vieron una demostración de las capacidades de "George" corriendo en aquel monstruo de tubos al vacío electrónicos que era el Whirlwind. Donald Knuth y Pardo dan cuenta de este relato también en su paper sobre la historia de los primeros lenguajes de programación ya señalado anteriormente.

Comentando sobre sus trabajos en el MIT/IL, el Dr. Ramón Alonso indicó:

- cita Dr. Alonso -
Yo entré al Instrumentation Laboratory, entonces parte de MIT y dirigido por C. Stark Draper, el que perfeccionó el giroscopio, en 1959. Me puse a trabajar con Eldon Hall, que estaba entonces a cargo del diseño del computador del cohete Polaris, lanzado de dentro de submarinos.

Pronto me encontré con J. Halcombe Laning (Hal), y por él supe que Milt Traegeser estaba proponiéndole a la Fuerza Aérea el mandarle una sonda a Marte. Laning y Battin son los autores de las (relativamente) famosas "Q-equations," para dirigir misiles a blancos lejanos. En esos días los computadores tenían muy poco poder, y estas ecuaciones son muy eficientes. El computador de Polaris era una versión digital de computador análogo, de una clase que se llamaba "Digital Diferential Analyzer", o DDA, y yo había trabajado con estos en Harvard, cuando estudiante graduado.

Laning me propuso que viera si era posible diseñar/construir un computador "general purpose," es decir, de arquitectura esencialmente moderna, para ir a Marte. El problema era que tenía que gastar muy, muy poca electricidad, ya que todo el poder vendría de células solares. El viaje de ida y vuelta sería muy largo, por supuesto. La función de la sonda era tomar fotos de Marte, y traerlas de vuelta. La computación sería necesaria sólo en media docena de puntos durante el viaje, y con las Q-equations, sólo tendría que estar funcionando unos minutos cada vez. Pero tendría que cumplir con todas las funciones de "guidance," "navigation" y "control."

Mi solución fue un diseño basado en "core-transistor logic," donde todas las unidades lógicas se conectaban por medio de transformadores pequeñitos, de modo que usaban energía solo durante la duración de un pulso, de mas o menos 1 microsegundo. Los transformadores de "cores" estaban hechos de un material que lo llamábamos "ribbon cores," que ya los había usado Harvard en sus computadores, y que tienen memoria.

Siguiendo la arquitectura que hoy en día se llama "Harvard architecture," donde se separa la memoria del programa de la memoria de los datos, diseñé también la memoria principal usando esos "ribbon cores," en la forma de un "core rope."

El resultado fue un modelo experimental 1B, programado por Hugh Blair Smith y Laning. Comprobamos que, aunque la energía usada por instrucción era bastante alta, usaba casi nada en el estado de descanso, que iba a ser el 99.9% del tiempo de la misión.

Laning y yo conseguimos patentes para el "interrupt," donde una señal exterior causa que le programa corriente se suspenda, ejecuta otro programa, y vuelve a resumir el programa original. También nos dieron patentes para lo que hoy en día se llama "Direct Memory Access." Señales del CDU causaban incrementos o decrementos en ciertos registros, completamente transparente al programa, de modo que el programa simplemente leía el contenido de esos registros para saber los ángulos de la plataforma inercial.

Allá por el '61 o '62 se cambió la agencia de aviación a lo que es hoy NASA, y el Instrumentation Lab busco contratos con ella. Albert Hopkins, compañero mío en Harvard, vino a trabajar también al IL, y juntos rediseñamos El Mod 1B con un modelo ya mas apropriado (Mod 3, se llamaba, si me acuerdo bien) para una misión a la luna. Usamos otra vez los mismos elementos, la "core-rope" y el "core-transistor logic."

Toda esta estructura sobrevivió en el AGC. El cambio mayor fue el reemplazo del core-transistor logic por las NOR gates, hechas con circuitos integrados.

Albert y yo estábamos completamente opuestos a estas NOR gates, pero Eldon nos contramandó, en una decisión que creo yo fue, técnicamente, de las mas importantes en el proyecto Apollo.

Si me acuerdo bien, escribimos Laning y yo un informe (R-212?) describiendo el Mod 1B, pero no tengo ya copias de este.
- fin de la cita - Tomada de un correo personal (Julio 1999).


3) Sobre sus comienzos en el mundo de las matemáticas y de la computación y sobre el método que utilizaron para impementar la microarquitectura del computador Apollo con compuertas NOR TTL de tres(3) entradas:

HB-S: Your request for a link between algebra and the layout of NOR gates is very interesting. I don't recall it as much of an algebraic exercise, though of course one must master enough Boolean algebra to realize a number of simple functions (and, or, exclusive or) in NOR logic. I played around a little with the NOR logic to realize one bit position of addition with carry in and carry out, and reminded myself that the greater concerns were:

- how many gates are used;

- how many levels of gates (each with its own delay time) are required for each result;

- how many gates a single signal can safely enter as an input (fan-out rule);

- how many signals can safely enter a single gate as input (fan-in rule).

(The last of those makes sense in a world of 3-input NOR gates if you parallel them together in the "blue-nose" configuration; for instance, a 9-input NOR gate was made by tying the output signal pins of 3 gates together and leaving the load resistors of 2 of them disconnected from Vcc -- those 2 are shown schematically by a solid blue nose without the usual inverting circle.)

HB-S: I think the most complex "expression" in AGC gate-level logic was the explicit-carry adder, in which each of 16 single-bit add/carry circuits fed its carry-out to the next similar circuit, all in a big loop to include end-around carry as required for ones-complement. But this was never written out as a long algebraic expression, to be simplified by algebraic means. When I have a moment, I'll write out the sort of tables we used, and how those were implemented in NOR gates. As I don't have a software package to draw gate diagrams (though one must exist somewhere)




Figura 11. Fragmento del Sumador del Apollo Guidance Computer (mostrando los circuitos Flip-Flop de compuertas NOR logic)


HB-S: My personal road to technology was all paved and signposted at birth, as far as I can tell. When I was three, the road to my grandmother's house in Connecticut went by an old barn whose roof had sagged and nearly collapsed. I named it "Brokeny House" and resolved to come back and fix it when I was grown up! At age twelve, I started a considerable model railroad in HO gauge and worked on that for several years. In high school, math, chemistry and physics reinforced my leanings, especially algebra in which I took great delight in crossing things out and reducing a big complicated mess to a simple answer. Between school and college, I was given a series of Johnson O'Connor tests to measure talents and traits so that my parents could figure the best way to steer me. The result was that my talents for English and math were both very strong (which I could have told them without the tests). A lot of the DNA for that came from my mother's father, who edited math textbooks for McGraw Hill. If he'd been born a generation later, he might have been one of the pioneers like Shannon or Turing. Starting college, I still equated engineering with bridge building, though I chose a number of electrical engineering courses; but when computer programming became available to Harvard undergraduates, I knew within weeks what I had been born to do. When I hear about people who spend years trying to figure out what to do with their lives, I sympathize just to be nice, but they sure don't come from the same planet I do!


Sobre la interacción entre los analistas funcionales y programadores durante el diseño del Software Apollo

HB-S: We didn't have a profiler program for the AGC, since the simulator served to expose all performance problems.  However, I did put code inspection -- well, actually algebra inspection -- to good use.  One evening Bill Widnall, an absolutely brilliant control system engineer but no programmer, was bitching and moaning over how long his calculations took to run, as revealed by the simulator.  I looked at his matrix algebra and saw that rearranging some terms would make the run time proportional to the 3rd power of 3 rather than the 4th power.  It would have taken me weeks to figure out what the matrix algebra ought to do, and he had no training or experience in thinking like a programmer.
We just took care of each other, and that's how Apollo got done!


Sobre la importancia dada a la capacidad de computo (en los sistemas de Guía y Navegación) y sobre la documentación del software

- Cita Dr. Albert Hopkins - tomada del Space Guidance Navigation and Control - R500 MIT, 1965 -
The reasons for having an airborne computer are so numerous that the computer engineer is apt to take the parochial viewpoint that the guidance computer is the principal part of the guidance system, and that the other parts, such as inertial, optical, radar, and radio elements are ancillary units for sensing and communication. This picture of a guidance system is somewhat distorted, but not entirely so, In 1962, J. F. Shea, then Deputy Director of Manned Space Flight at NASA, and presently Apollo Project Manager, said, "Although engineers in each discipline tend to regard their particular developments as the most critical, once the propulsion capability has been provided the key to reliable execution of a wide range of complex, long-duration missions is the computational capacity provided aboard the spacecraft."
- Fin de la cita -

Como punto final se desarrolla el tema de la documentación del software. En múltiples ocasiones se ha escuchado a los nuevos profesionales de la computación afirmando que los buenos programadores (llamados "hackers") no documentan programas. Una especie de código secreto abunda en todos los centros de cómputo en los cuales el autor de este trabajo ha laborado. La mezquindad tecnológica abunda, a veces como forma de reserva de información privilegiada para lograr importancia y una especie de manto de sabiduría. Son estos los principales problemas actuales, como lo eran en el pasado.

- Cita Dr. James Tomayko - Computers in Spaceflight: The NASA Experience -
Overcoming the problems of the Apollo software, NASA did successfully land a man on the moon using programs certifiably adequate for the purpose. No one doubted the quality of the software eventually produced by MIT nor the dedication and ability of the programers and managers at the Instrumentation Lab. It was the process used in software development that caused great concern, and NASA helped to improve it. The lessons of this endeavor were the same learned by almost every other large system development team of the 1960s:

(a) documentation is crucial,
(b) verification must proceed through several levels,
(c) requirements must be clearly defined and carefully managed,
(d) good development plans should be created and executed,
(e) more programmers do not mean faster development.

- Fin de la cita -


Referencias

[1] Multiplicación de Cantidades Decimales: Una cuestión de escala
[2] Conferencia NASA MAPLD 2004 - "Digital Engineering and Computer Design"