Il Fortran iniziale, I/O, FORMAT

wo-the-wizard

Il titolo è fuorviante, riassumo una conversazione con un collega dei tempi antichi riguardo al post Lo sviluppo iniziale dei linguaggi di programmazione.
Naturalmente riguarda il Fortran l’unico linguaggio che c’era sul ‘puter che usavamo. Il programma postato da Knuth e Trabb Pardo (K&T) è per la versione 0 (zero), forse solo virtuale. La prima versione con cui ho avuto a che fare è la IV, anzi un’evoluzione compatibile con la 66 ma c’era codice scritto per la versione II (1958), trasferito da schede a nastri o dischi o semplicemente ricopiato dal listato.
In ogni caso il programma postato da K&T deve essere aggiornato (ehi! 50 anni!): non solo le funzioni non hanno (dalla preistoria) il nome che deve terminare con F ma non ho nemmeno un lettore di schede 😦
E non saprei nemmeno trovare le schede 😦 e la perforatrice 😦

forig

Però il programma prevede la lettura di dati formattati in modo preciso, cosa che da terminale non è agevole (bisogna essere proprio pistini) ma si può fare un formattatore, come i millemila come si usava una volta.

Ah! un altro problema: la gestione dei file: allora si aprivano da OS, il programma lo dava per scontato e alla fine si chiudevano, sempre da OS. I comandi Prime erano rispettivamente OPEN seguito dai parametri che non ricordo ma roba tipo 1 1 (unità 5 in lettura [aggiornamento: il secondo parametro è da verificare, probamilente non come pensavo]) e CLOSE 1 (unità 5); siccome di solito si dovevano chiudere più unità c’era il comodo CLOSE ALL. Su Prime (come con il DEC) i comandi potevano essere abbreviati, nel nostro caso al posto di OPEN bastava O, era il comando più importante iniziante con quella lettera, e C stava per CLOSE.
Quindi, se ricordo bene, il mio command-file per l’esecuzione del programma FMT sarebbe stato così:

O DATI-FREE 1 1
O DATI 2 2
SEG FMT
C ALL

L’istruzione di lancio SEG FMT valeva nell’ipotesi che il programma fosse stato compilato per la versione segmentata (prevista per i programmi grossi) usata (a sproposito) abitualmente. Però se uno era razionale vedeva che bastava la versione normale, anche più veloce quindi la riga sarebbe stata RUN FMT, RUN abbreviabile in R. OK, mode nostalgia OFF.

La versione corrente usa le normali istruzioni OPEN e CLOSE, non disponibili allora. Per evidenziare il nuovo uso il minuscolo, adesso equivalente al maiuscolo, allora vietato.

Ecco fmt.f

C FMT legge in free-format e scrive formattato

      DIMENSION A(11)
      
      open(1, file='dati-free')
      READ(1, *) A
      close(1)
      
      open(2, file='dati')
      WRITE(2, 2) A
      close(2)
2     FORMAT(6F12.4)

      END

Aggiornamento: per il Prime le prime 4 unità di I/O erano predefinite e riservate per cui avrei dovuto usare numeri più alti, tipicamente 5 e 6 al posto di 1 in OPEN e 2 in WRITE.

E questo è il file di dati dati-free

1 10 100 1000 10000 98765 987654
987654.3 2.7818 3.1415 -42

Compilo ed eseguo

f0

ottenendo il file dati

      1.0000     10.0000    100.0000   1000.0000  10000.0000  98765.0000
 987654.0000 987654.3125      2.7818      3.1415    -42.0000

Uh! visto il secondo dato della seconda riga? è 987654.3125 invece del previsto 987654.3000 😳 ma il formato REAL*4 (quello usato per le variabili inizianti con una lettera fuori dell’intervallo [I-N] riservato agli interi) garantisce 7-8 cifre significative.

Per essere proprio sicuri-sicuri si può fare la verifica, con il file verifica.f

C VERIFICA

      DIMENSION A(11)
      
      open(1, file='dati')
      READ(1, 2) A
      close(1)
2     FORMAT(6F12.4)

      DO 3 I = 1, 11
        PRINT *, A(I)
3     CONTINUE     

      END

f1

OK, ci siamo. A questo punto torno al programma di K&P, opportunamente aggiornato (tpk.f).

C     THE TPK ALGORHTM, FORTRAN STYLE
*     aggiornato, modifiche in minuscolo

      FUN(T) = SQRT(ABS(T)) + 5.0**3
      DIMENSION A(11)
1     FORMAT(6F12.4)
      open(1, file = 'dati') 
      READ(1, 1) A
      close(1)
      DO 10 J =1, 11
      I = 11 - J
      Y = FUN(A(I+1))
      IF(400.0 - Y) 4, 8, 8
4     write(*, 5) I
5     FORMAT(I10, 10H TOO LARGE)
      GO TO 10
8     write(*, 9) I, Y
9     FORMAT(I10, F12.7)
10    CONTINUE
      STOP 52525
      end

f2

OK 😀

C’è ancora una cosa emersa ieri: le funzioni, quando non ci sono si fanno. A dire tutta la verità i fortrainers preferivano –di gran lunga– le SUBROUTINEs ma questo sarebbe un altro rant, lunghissimissimo 😉

Era tipico di IBM fornire funzioni che non si avevano (no, niente nomi). Per gioco supponiamo non fossero definite ABS e SQRT.
La prima è banale (e lasciata come esercizio) mentre la seconda è leggermente più impegnativa. Siccome il mondo è vario da adesso in poi continuo con Python 3.x, il Basic dei nostri giorni.

Invece di limitarci alla radice quadrata conviene probabilmente essere più generali; che ne dite di usare i logaritmi? OK, la Wiki (come faremmo senza?) ci dice tutto. Illo tempore probabilmente avrei cercato sul Dwight –hey! c’è online–, c’è il capitolo Logarithmic Functions, p.130
log-x
Per l’esponenziale c’è Exponential Functions a p.125

exp-x

Quindi ecco myfunc.py:

# modulo per Python 3.x; 
# per 2.x importare division from tuture

my_e = 2.71828182845904523536 

def my_log(x):
    r = (x - 1) / (x + 1)
    d = r
    v = d
    c = 1
    while d > 1e-8:
        c += 2
        t = 1
        for i in range(1, c + 1):
            t *= r
        d = 1/c * t
        v += d

    return round(2 * v, 8)

def my_exp(x):
    fact = 1
    t = x/fact
    e = 1 + t
    num = x
    c = 1
    while t > 1.e-8:
        c += 1
        fact *= c
        num *= x
        t = num / fact
        e += t
    st = str(e)
    ppoint = st.index(".")
    if ppoint < 8:
        e = round(e, 8 - ppoint)
    else:
        e = round(e, 1) 

    return e
    
def my_sqrt(x):
    return my_exp(1/2 * my_log(x))

py0

:mrgreen:

Posta un commento o usa questo indirizzo per il trackback.

Rispondi

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo di WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione /  Modifica )

Google photo

Stai commentando usando il tuo account Google. Chiudi sessione /  Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione /  Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione /  Modifica )

Connessione a %s...

Questo sito utilizza Akismet per ridurre lo spam. Scopri come vengono elaborati i dati derivati dai commenti.

%d blogger hanno fatto clic su Mi Piace per questo: