¿Cómo evaluaron las computadoras Apollo funciones trascendentales como seno, arcotangente, logaritmo?

La navegación con un sextante o las maniobras con ángulos de cardán podrían ser dos ejemplos de casos en los que una computadora Apollo podría necesitar hacer trigonometría.

Las funciones trigonométricas como el seno, el arcotangente, etc. son trascendentales , al igual que los logaritmos. No puede evaluar estas funciones con una expresión simple basada en la multiplicación o la división, por ejemplo, sin al menos un algoritmo iterativo.

Un ingeniero en el terreno tomaría una regla de cálculo para dos o tres dígitos, y para obtener más iría a un libro de trigonometría, registro y otras tablas para obtener más dígitos. Entre dos líneas, puede interpolar a mano para obtener aún más dígitos.

Pero, ¿cómo evaluaron las computadoras Apollo las funciones trascendentales, o al menos cómo se implementaron en los programas los cálculos que requerían el uso de funciones trascendentales?

¿Estás seguro de la necesidad de hacer trigonometría para gimbaling? Estoy bastante seguro de que sería más fácil mantenerse dentro de las matemáticas vectoriales si usa un actuador lineal. De todos modos, las funciones de trigonometría generalmente se implementan mediante la búsqueda de tablas o se aproximan como una expansión de Taylor . No hay fuente directamente relacionada con Apollo, lo siento.
...o ambos, la expansión de Taylor preparando tablas de búsqueda al inicio, en caso de que el almacenamiento permanente sea menos abundante que la RAM.
@Christoph La primera oración comienza con dos instrumentos que probablemente producen datos angulares . Además, lo que se hizo en la década de 1960 en las computadoras en el espacio no está cubierto por cómo se hacen las cosas ahora. Agregaré la historyetiqueta para que quede aún más claro. También podría considerar dónde deberían almacenarse las tablas, había muy poca memoria en las computadoras Apollo.
@Christoph mira aquí: youtu.be/9YA7X5we8ng?t=1283 y también aquí youtu.be/YIBhPsyYCiM?t=273
@Christoph: Ya en 1956 teníamos un algoritmo mejor que Taylor, a saber, CORDIC. No sé si eso se usó en Apolo.
El almacenamiento (tanto permanente como dinámico) era muy importante, por lo que no sorprende que no mantuvieran una mesa.
Uno podría hacer esta misma pregunta de, por ejemplo, calculadoras, o realmente cualquier computadora.
@Joshua considera que estos se desarrollaron a principios de la década de 1960. además de considerar las limitaciones de tamaño y peso para aterrizar en la Luna y regresar a la Tierra, no se trata de "cualquier computadora". De hecho, las tecnologías desarrolladas para computadoras en el programa espacial ayudaron a allanar el camino para las calculadoras científicas "personales" una década después. Es la totalidad de la situación lo que hace que esta pregunta en particular sea convincente.
@MSalters: CORDIC necesita tablas de constantes, alrededor de 50 valores. No es muy útil para las computadoras Apollo con memoria de cuerda central para programa y constantes.
@uhoh, estoy de acuerdo en que la totalidad de la situación es convincente, pero la esencia de la respuesta (expansiones de Taylor) es la misma que si preguntara cómo lo hace mi computadora, al menos cómo entiendo que estos cálculos ocurren hoy.
@Joshua, si bien las implementaciones modernas pueden incluir una o más expansiones de Taylor como semilla (según la función, el pecado es fácil, se encuentra aquí ), ese es solo el comienzo de cómo las computadoras modernas hacen trascendentales de doble precisión. Lo que aprendí de esta respuesta es exactamente cómo se hizo en este caso, el grado de precisión resultante (~1E-04) con el que tuvieron que trabajar, el esfuerzo que se dedicó al escalado previo y posterior y por qué, y el espartano codificación.
@Joshua, todos estos son exclusivos del conjunto específico de restricciones en esta computadora en particular, única en su tipo. A tu uso reduccionista de "es lo mismo que" lo único que puedo decir es "no, no lo es", a lo que podrías responder "sí lo es" y podríamos continuar hasta el infinito.
@Joshua exactamente: todas las computadoras digitales lo hacen con este método o con uno similar. Otra forma de verlo es "¿de dónde vienen las tablas de los libros en los que solíamos buscar estas cosas?" En los viejos tiempos, algunos pobres idiotas tenían que procesar esas series a mano, y más tarde con la ayuda de calculadoras mecánicas que podían multiplicar y dividir. El campo general de estudio se llama "Métodos numéricos" y puede encontrar fácilmente numerosos libros bajo ese título temático.
¡@JamieHanrahan también hay un sitio SE! Coincidentemente, acabo de preguntar ¿Qué algoritmo usa (usó) Excel para las funciones de Bessel que es discontinua en x = 8?
@Uwe en realidad CORDIC se desarrolló específicamente para computadoras de navegación digital en aviones en 1956.
para el registro, incluso es posible enviar el valor a una computadora analógica, calcularlo y leer el resultado en un ADC. Esas cosas se pueden hacer muy rápidamente en una computadora analógica eléctrica. No sé si funciona la trigonometría, pero una computadora analógica mecánica puede hacerlo, aunque más lento.
@Cris Straton: de wikipedia : "cuando hay disponible un multiplicador de hardware (por ejemplo, en un microprocesador DSP), los métodos de búsqueda de tablas y las series de potencia son generalmente más rápidos que CORDIC". La computadora Apollo tenía una multiplicación bastante rápida, Tiempo de ciclo de memoria: 11,7 microsegundos. Tiempo de adición: 23,4 microsegundos. Tiempo de multiplicación: 46,8 microsegundos.
@phuclv: había circuitos electrónicos analógicos de esa época para logaritmos, exponenciaciones, sumas, multiplicaciones y raíces cuadradas, pero no para funciones trigonométricas como seno, coseno y tangente.

Respuestas (3)

Dado que el código del Apolo 11 está en GitHub, pude encontrar el código que parece una implementación de funciones de seno y coseno: vea aquí el módulo de comando y aquí el módulo de aterrizaje lunar (parece que es el mismo código).

Para mayor comodidad, aquí hay una copia del código:

 # Page 1102
            BLOCK   02

# SINGLE PRECISION SINE AND COSINE

            COUNT*  $$/INTER
SPCOS       AD      HALF            # ARGUMENTS SCALED AT PI
SPSIN       TS      TEMK
            TCF     SPT
            CS      TEMK
SPT         DOUBLE
            TS      TEMK
            TCF     POLLEY
            XCH     TEMK
            INDEX   TEMK
            AD      LIMITS
            COM
            AD      TEMK
            TS      TEMK
            TCF     POLLEY
            TCF     ARG90
POLLEY      EXTEND
            MP      TEMK
            TS      SQ
            EXTEND
            MP      C5/2
            AD      C3/2
            EXTEND
            MP      SQ
            AD      C1/2
            EXTEND
            MP      TEMK
            DDOUBL
            TS      TEMK
            TC      Q
ARG90       INDEX   A
            CS      LIMITS
            TC      Q       # RESULT SCALED AT 1.

El comentario

# SINGLE PRECISION SINE AND COSINE

indica que lo siguiente es de hecho una implementación de las funciones seno y coseno.

La información sobre el tipo de ensamblador utilizado se puede encontrar en Wikipedia .

Explicación parcial del código:

La subrutina SPSINrealmente calcula pecado ( π X ) , y SPCOScalcula porque ( π X ) .

La subrutina SPCOSprimero suma un medio a la entrada y luego procede a calcular el seno (esto es válido debido a porque ( π X ) = pecado ( π ( X + 1 2 ) ) ). El argumento se duplica al comienzo de la SPTsubrutina. Es por eso que ahora tenemos que calcular pecado ( π 2 y ) por y = 2 X .

La subrutina POLLEYcalcula una aproximación polinomial casi de Taylor de pecado ( π 2 X ) . Primero, almacenamos X 2 en el registro SQ (donde X denota la entrada). Esto se utiliza para calcular el polinomio.

( ( ( C 5 / 2 X 2 ) + C 3 / 2 ) X 2 + C 1 / 2 ) X .
Los valores de las constantes se pueden encontrar en el mismo repositorio de GitHub y son

C 5 / 2 = .0363551 ( π 2 ) 5 1 2 5 ! C 3 / 2 = .3216147 ( π 2 ) 3 1 2 3 ! C 1 / 2 = .7853134 π 2 1 2

que se parecen a los primeros coeficientes de Taylor para la función 1 2 pecado ( π 2 X ) .

¡Estos valores no son exactos! Así que esta es una aproximación polinomial, que está muy cerca de la aproximación de Taylor, pero aún mejor (ver más abajo, también gracias a @uhoh y @zch).

Finalmente, el resultado se duplica con el DDOUBLcomando y la subrutina POLLEYdevuelve una aproximación a pecado ( π 2 X ) .

En cuanto a la escala (primero la mitad, luego el doble, ...), @Christopher mencionó en los comentarios que el número de punto fijo de 16 bits solo podía almacenar valores de -1 a +1. Por lo tanto, es necesario escalar. Consulte aquí para obtener una fuente y más detalles sobre la representación de datos. Los detalles de las instrucciones del ensamblador se pueden encontrar en la misma página.

¿Qué tan precisa es esta aproximación casi de Taylor? Aquí puede ver un gráfico en WolframAlpha para el seno, y parece una buena aproximación para X desde 0.6 a + .6 . La función coseno y su aproximación se representan aquí . (Espero que nunca hayan tenido que calcular el coseno para un valor π 2 , porque entonces el error sería desagradablemente grande).

@uhoh escribió un código de Python , que compara los coeficientes C 1 / 2 , C 3 / 2 , C 5 / 2 del código Apollo con los coeficientes de Taylor y calcula los coeficientes óptimos (basados ​​en el error máximo para π 2 X π 2 y error cuadrático en ese dominio). Muestra que los coeficientes de Apolo están más cerca de los coeficientes óptimos que los coeficientes de Taylor.

En este gráfico las diferencias entre pecado ( π X ) y se muestran las aproximaciones (Apollo/Taylor). Se puede ver que la aproximación de Taylor es mucho peor para X .3 , pero mucho mejor para X .1 . Matemáticamente, esto no es una gran sorpresa, porque las aproximaciones de Taylor solo se definen localmente y, por lo tanto, a menudo solo son útiles cerca de un solo punto (aquí X = 0 ).

Tenga en cuenta que para esta aproximación polinomial solo necesita cuatro multiplicaciones y dos sumas ( MPy ADen el código). Para la computadora de orientación Apollo , la memoria y los ciclos de CPU solo estaban disponibles en pequeñas cantidades.

Hay algunas formas de aumentar la precisión y el rango de entrada, que habrían estado disponibles para ellos, pero daría como resultado más código y más tiempo de cálculo. Por ejemplo, explotar la simetría y la periodicidad del seno y el coseno, usar la expansión de Taylor para el coseno o simplemente agregar más términos de la expansión de Taylor habría mejorado la precisión y también habría permitido valores de entrada grandes arbitrarios.

Lo estoy leyendo, pero no es fácil porque no estoy familiarizado con el lenguaje de programación. A primera vista parece una aproximación de Taylor, pero no estoy seguro. Editaré cuando tenga más.
Estoy en ello... Creo que tiene que ver con la escala.
La escala se debe al hecho de que la precisión simple solo puede almacenar valores de -1 a +1 :). La precisión es de alrededor de 13 bits, lo que se ajusta al tipo de precisión simple (16 bits, uno de los cuales es el bit de signo y el otro era un bit de paridad no accesible para el software).
Dios mío... No he visto ensamblaje desde la universidad, no puedo imaginar tener que escribir una computadora de guía completa usando nada más que códigos OP y funciones de bajo nivel. También bienvenido al SE, brillante respuesta.
@Christoph Así que supongo que era una representación de punto fijo y no de punto flotante, ¿correcto? Además, ¿tiene un enlace que pueda agregar a la respuesta (o que pueda editar)?
@uhoh: los problemas de escala se solucionaron ahora e incluí gráficos para comparar la función con la aproximación. Parece ajustarse a algunos valores.
Encontré esa información en el Manual del programador de Virtual AGC .
Sobre el tema: gráfico de error . El error máximo dentro del dominio sería alrededor de 0.0001
@supinf Oh, he estado viendo evolucionar tu respuesta todo el tiempo. El enlace alfa de Wolfram también es útil para comprender el alcance del escalado antes y después. ¡Excelente investigación matemática y de código también!
@MagicOctopusUrn Tampoco la mayoría de la gente. Excluyendo a las personas que lo hacen por diversión, ASM hoy en día está más o menos limitado a la ingeniería inversa, la gente que hace compiladores y el tipo de plataformas integradas de ultra bajo costo/capacidad/rendimiento donde el trabajo es tanto EE como CS.
Lo que también es bueno, es especialmente preciso cerca de los (frecuentemente) 0, 30 y 60 grados.
Gran respuesta. No se puede calcular exactamente una función trascendental algebraicamente, pero existen aproximaciones que son lo suficientemente buenas para la ingeniería. La regla de cálculo y las tablas tampoco son exactas.
"Espero que nunca hayan tenido que calcular el coseno para un valor ≥ π/2". No es necesario utilizar la relación cos(π - α) = -cos(α). Usando esta y otras relaciones similares, solo se debe calcular el rango 0 ≤ α ≤ π/4. Estas transformaciones pueden usarse para sin, cos, tan y cot. Puede haber otras funciones dentro del código del Apolo 11 que usen estas transformaciones cuando sean posibles argumentos más grandes.
Estupendo análisis! Nunca he tenido mucho éxito tratando de leer el ensamblado de AGC yo mismo. Bienvenido a bordo.
¡Bonito! Esto me hace querer escribir mi propio emulador AGC y probarlo :-)
¿Es posible que algunas de las instrucciones cerca del comienzo hayan estado truncando 2x al rango +/-1 y luego invirtiendo si eso se ajusta? Si es así, el comportamiento de cos() habría sido limpio para cualquier ángulo.
@MagicOctopusUrn Los Brogrammers entre nosotros que afirman que "las niñas no saben programar" deben tomar nota de que este código fue desarrollado por una mujer .
Taylor se basa en derivadas en un solo punto, no es el mejor ajuste (mínimo error máximo) en un rango. Por lo tanto, se espera que se utilice un polinomio similar, pero diferente.
@philipp De hecho, escribí un pequeño artículo sobre ella: la imagen de ella parada junto a una pila de programas de ensamblaje más alta que ella siempre me inspiró. La programación requiere un cableado específico del cerebro, no un tipo específico de persona en mi opinión :).
¡Mis lecturas de aritmómetro están por las nubes!
@supinf, de hecho, parece que los coeficientes están optimizados para dar buenos resultados sobre ± π/2. Una comprobación rápida da casi los mismos números que en el programa, en lugar de los valores nominales de una expansión de Taylor adecuada en x=0. pastebin.com/UnVudQs4 Respuesta muy perspicaz por cierto, ¡gracias de nuevo!
@Philip: Este código fue desarrollado por un equipo de hombres en su mayoría y pocas mujeres dirigido por Magaret Hamilton. No dijo aquí si era la única mujer en el equipo.
@uhoh Entonces, lo que hicieron fue mucho mejor que la aproximación de Taylor (@zch ya sugirió esto). He editado y también vinculado a su código python. Gran análisis: muestra que el error cuadrático medio era más importante para ellos que el error máximo.
@supinf el script pastebin (rima con papelera) fue solo una prueba rápida. La minimización puede ser sorprendentemente complicada y no me tomé el tiempo para analizarla a fondo, por lo que he retrocedido un poco en su discusión sobre los resultados. ¡Gracias!
Espero ayudar así algún día. Por toda mi cabeza por ahora. Muy humillante.
La elección de C como constante es una pista moderada de que el polinomio en cuestión no es una expansión de Taylor, sino una expansión en cuadratura en los polinomios de Chebyshev o algo similar.
@EP: No había pensado en eso, pero tenía curiosidad de cómo la función parecía tener un rango útil tan amplio, ya que mi propia experiencia con la serie Taylor sugería que el rango útil es mucho más pequeño. Sin embargo, aceptar una pérdida de precisión en los puntos más cercanos a cero permite que los puntos más alejados sean mucho más precisos.
@uhoh Dado que los problemas de minimización son convexos y también existe el mensaje es 'Optimización finalizada con éxito'. para resmrs y resmax, tenía bastante confianza en los resultados. También maxiter y maxfev donde no se alcanzaron. Pero al menos está claro que los coeficientes de Apolo son mucho mejores que los coeficientes de Taylor
Los algoritmos de @supinf no son perfectos, y podemos tener 100% de fe en su perfección hasta que nos muerdan una vez El módulo de optimización ofrece una gran cantidad de algoritmos muy diferentes para elegir, creo que el siguiente paso sería probar varios y ver solo qué tan cerca están sus resultados entre sí, o en este caso probarlo analíticamente para ver si es al menos un máximo local. Tamaño finito de X array podría hacerlo no convexo de una manera peculiar, la función minimizada podría no ser uniforme (gradiente discontinuo).
@supinf space.stackexchange.com/questions/31102/… es otra pregunta relacionada si te apetece explicar eso también :).
@Uwe Esta página acredita a los autores de los subprogramas individuales de AGC; aunque se inclina por los hombres, veo 5 nombres probablemente femeninos en la lista. ibiblio.org/apollo
@supinf Tengo otra pregunta sobre el código AGC si está interesado. space.stackexchange.com/q/31196/195
@NathanTuggy lo que el mundo necesita ahora más que nunca es un "mejor paréntesis" ;-)
Me pregunto cómo se ve este código en NASM... agregado a la lista de proyectos.
@Philipp No puedo ver cómo el comentario de Magic Octopus Urn al que estás respondiendo supuestamente implica que "las chicas no pueden programar", ni ningún otro comentario de los que he leído en este sitio. No haber visto el código ensamblador desde la época de la universidad tampoco implica necesariamente que uno sea un "programador", sea lo que sea que signifique ese término. Por último, pero no menos importante, es bastante irrazonable suponer que este código base fue escrito en su totalidad por una sola persona, independientemente de si era hombre o mujer, y a través de esta suposición ignorar el tiempo y el esfuerzo de todo el equipo de programación. .
@Philipp Por esas razones, parece que el propósito principal de su comentario es hacer algún tipo de declaración retórica fuera de tema relacionada con la política de identidad, en lugar de compartir información útil y constructiva, y lo encuentro bastante inapropiado en este contexto. y entorno.

También pediste el logaritmo, así que hagamos esto también. A diferencia de las funciones seno y coseno, esta no se implementa únicamente con un enfoque similar a una serie de Taylor. El algoritmo se basa en cambiar la entrada y contar el número de cambios necesarios para llegar a la escala requerida. No sé el nombre de este algoritmo, esta respuesta en SO describe el principio básico.

La LOGimplementación es parte del módulo CGM_GEOMETRY y está etiquetada

SUBRUTINA PARA CALCULAR EL LOGOTIPO NATURAL

La rutina utiliza la NORMinstrucción ensambladora, que, según su documentación , desplaza a la izquierda el número en el acumulador (registro "MPAC"), hasta que termina con un valor 0.5 y "casi 1 " [1] , y escribe el número de operaciones de desplazamiento realizadas en la ubicación de memoria especificada como su segundo argumento (el significado matemático de la operación de desplazamiento a la izquierda es exponenciación binaria 2 norte , los exponentes en el argumento de un logaritmo se pueden expresar como factores y los productos en el argumento se pueden expresar como sumas, por lo que la simplificación de yo norte ( 2 C s C a yo mi d ) en C C o norte s t + yo norte ( s C a yo mi d ) trabaja, donde C es el número de turnos y C o norte s t es el valor precalculado de yo norte ( 2 ) ).

Luego usa un polinomio de tercer grado para aproximar yo norte en ese intervalo, con coeficientes codificados [3] :

ingrese la descripción de la imagen aquí

Eventualmente, el conteo de turnos obtenido anteriormente se vuelve a multiplicar (por la constante 0.0216608494 [2] , usando SHORTMP).

La presión de optimización debe haber sido tan alta que no corrigieron el signo invertido antes de regresar de la subrutina, lo que requirió que todos los sitios de llamadas lo tuvieran en cuenta.

Aplicación de la subrutina logarítmica:
por ejemplo, como parte de la predicción de rango en el control de reentrada.

---

[1] el formato de almacenamiento para un número de doble precisión se construyó a partir de dos palabras de 16 bits donde el MSB de cada uno es el signo y forma una representación del rango en complemento a uno 1 < X < 1 pero el LSB es un bit de paridad. Por lo tanto, tratamos con un formato de 30 bits que contiene dos bits de signo, lo que genera un dolor de cabeza para la implementación del emulador.

[2] el lenguaje ensamblador ACG lo permite CLOG2/32como nombre identificador. Esto causó más dolores de cabeza para la implementación del emulador .

[3] ¿cómo se encontraron los coeficientes? Los comentarios del código sobre la lista de ensamblaje del módulo de trigonometría interpretativa (sí, los astronautas podrían hacer que el ACG interprete instrucciones dinámicas) sugieren que el método se basó en trabajos de C. Hastings, especialmente Aproximaciones para computadoras digitales. Prensa de la Universidad de Princeton, 1955 . El polinomio más complejo de ese tipo en ACG es uno de séptimo orden, mismo módulo, para calcular a r C C o s ( X ) 1 X PAG ( X ) ).

Sospecho que se usa la ecuación ln(arg) = ln((2^a)*b) = a*ln(2) + ln(b). a es el número de desplazamientos necesario para obtener 0,5 < b < 1, de modo que arg = (2^a)*b. Pero debería haber una constante ln(2) = 0.693147 que no pude encontrar. Pero ln(2)/32 = 0,02166 está cerca de la constante 0,0215738898. 32 * .0215738898 es 0,69036.
a segunda vista, hay un polinomio involucrado. la línea 274 evalúa un polinomio de tercer grado (línea 276, 2+1) con coeficientes .031335467 etc. que siguen. Emularé eso y agregaré una trama si tengo tiempo más tarde.
@Uwe La constante para en ( 2 ) / 32 está presente en la línea 302.
0.0216608494 * 32 es 0.693147181 de hecho. Todavía estoy luchando con ese extraño complemento de doble precisión con desbordamiento y almacenamiento de paridad, no me acerque todavía con un intento de emulación en C.
@uhoh Me parece que 0.031335467 ( 1 X ) + 0.0130145859 ( 1 X ) 2 + 0.0215738898 ( 1 X ) 3 es una buena aproximación de en ( X ) / 32 por X Entre 0.5 y 1 .
@Litho: buen hallazgo en la línea 302. Debería haber buscado más en la parte inferior. Es increíble que los 9 dígitos de la constante sean los mismos que los calculados con mi vieja hp32S. Una constante de 30 bits puede contener hasta 9 dígitos decimales, por lo que solo el último dígito decimal 4 se pierde en la representación binaria.
@Litho sí, ¡bien!
@dlatikay Tengo otra pregunta sobre el código AGC si está interesado. space.stackexchange.com/q/31196/195

Una adición a la respuesta de @supinf :

a) La inicial DOUBLEenSPT

b) desbordamientos para la entrada x (registro A) por encima de +0,5 (+90°) y subdesbordamientos para x por debajo de -0,5 (-90°). En este caso, Aes >+1 o <-1 y lo siguiente TSalmacena el valor corregido (efectivamente suma uno, si está por debajo de -1, o resta uno, si está por encima de +1) TEMKy lo establece Aen +1 ( desbordamiento) o -1 (desbordamiento). Además , se ignora el salto TCFa .POLLEY

c) se XCHintercambia TEMKcon A, por lo que Acontiene el valor corregido y TEMK±1 ahora.

d) INDEXsuma el valor de TEMK(±1) al valor de la siguiente ADinstrucción, que corrige silenciosamente los desbordamientos. Como LIMITSes igual a -0,5, esto da como resultado una suma de 0,5 en el caso de desbordamiento (-0,5 + +1 = 0,5) y una resta de 0,5 en el caso de subdesbordamiento (-0,5 + -1 = -1,5 = -0,5) .

e) COMniega el valor de A– esto incluye invertir el bit de desbordamiento – y

f) el final ADsuma uno en el caso de overflow y resta uno en el caso de underflow. ADno realiza una corrección de desbordamiento antes de la adición y establece el indicador de desbordamiento después. Entonces, cada valor desbordado (>+135° y <-135°) volverá al rango [-1,+1].

Visualización de los cálculos de af

Si esto se ADdesborda o se desborda (no veo forma de que esto suceda), se establece Aen ±1, salta ARG90y se establece Aen -( LIMITS+ A), que es -(-0.5+1)=-(+0.5)=-0.5 en el caso de desbordamiento y -(-0.5-1)=-(-1.5)=-(-0.5)=+0.5 en el caso de subdesbordamiento. Inicialmente pensé que esto sucedería para x > +135° o x < -135°, pero no parece ser el caso.

Pero esto de ajustar la carcasa <-90° y >+90° me parece un poco incorrecto. Yo esperaría que la línea f fuera de (+0.5,+1.0) a (+1.0,+0.0) y de (-0.5,-1.0) a (-1.0,-0.0). Ese sería el caso si COMsigue directamente XCHsin el paso d.

Corríjame, si tengo algunas piezas incorrectas, recientemente vi ese código y traté de resolverlo con el conjunto de instrucciones AGC .