Progresul hardware, episodul 66: Alte planuri legate de numere, inclusiv pentru „ăla micu'” (Veritonul) - Septembrie 2018

La CARONTE am mai pus loc pentru un parametru care dictează cu câte elemente să se meargă prin fișierul din care se citește, față de început. Ca să nu mai scriu mereu înăuntru, ci chiar la rulare. Dacă trebuiesc lăsate deoparte primele 60000000 de numere din /GHIDALS.NUM2, atunci ./CARONTE /GHIDALS.NUM2 60000000.

În ultima vreme am mai mărit performanța redenumirii fișierelor - când un .NUM2 trebuie făcut .NUM1 pentru că s-a terminat culegerea de numere noi, sau un .NUM1 să devină .NUM pentru că a fost sortat crescător, sau un fișier-rezultat să fie redenumit înaintea extensiei .NUM2, ca să nu coincidă cu unul deja existent. Și aici, și la cazurile „2 la 1” și „1 la 0” de mai sus, trebuie evitată denumirea care concide cu a altui fișier care există, pentru asta se verifică dacă acel fișier există deja (și dacă nu este gol, dar poate fi suficient să existe), și atunci, dacă un GHIDALS.NUM2 trebuie să devină NUM1 și există deja un GHIDALS.NUM1 pe disc, atunci GHIDALS2.NUM1 (se preferă pornirea de la o cifră înaintea punctului de extensie, la redenumirile de nevoie), sau dacă este deja și GHIDALS2, atunci înainte de punct se crește de la „2” la „3” caracterul care deosebește numele fișierelor, și la nevoie tot așa mai departe, la cazurile de redenumire de fișiere.

Dacă se întâmplă să se ajungă la „9” înaintea punctului și trebuie și mai departe, atunci se adună 8 în loc de 1 la acel caracter, ca să se sară peste semnele speciale aflate în codul  ASCII între cifra 9 (cod 57) și litera A (65), adică :, ;, <, =, >, ? și @, ca după /GHIDALS9.NUM2 (sau NUM1, NUM) să vină /GHIDALSA.NUM2 și nu ceva cu <, =, > și tot așa. Este adevărat că după codul 90 mai vin niște semne speciale (91-96, unde sunt [, \, ], ^, _ și `), și nu am tratat și ipoteza asta, tocmai pentru că sper că peste tot, și pe SLI PLUS cu numerele mici, și pe Veriton la GIGM.TXT cu 16 GB de DDR3, vor fi suficiente redenumirile cu cifre de la 0 sau 2 la 9 și apoi cu cele 26 de litere mari englezești care au 65-90 în ASCII (cele mici sunt cu 97-122), adică maxim 34-36 de segmente pe un același fișier sau atâtea cazuri de redenumire la pornirea unui program cu numerele, terminarea lui sau terminarea unei sortări. Nu văd cum ar fi peste 36 de cazuri de nume pentru un același fișier dat, chiar când sunt mai multe întreruperi ale rulării programului său. În fine, la nevoi de programare, vin răspunsuri algoritmice.

În perspectiva folosirii unui GIGM.TXT pe Veriton, se prea poate să am nevoie și acolo de circentizare (=segmentare) și de lituanizare (=sortare), cu o memorie mai mică, de 16 GB; acel fișier ar putea avea și el suficienți GB cât să fie nevoie de segmentarea actualizării lui (vecungul, vecung) și de celelalte tratări segmentate ale numerelor, în raport cu memoria disponibilă. Aparatul algoritmic va trebui să fie gata de răspuns, dar acolo fișierele vor trebui adaptate pentru tipurile de date native (întregi de 64 de biți, long double), căci de mepezetele nu este nevoie pe unde cei mai mari divizori impari sunt pe 64 de biți. Să ne amintim cum în 2010 a trebuit ieșit din exclusivitatea limitatoare a tipurilor de date native, cu MIRACL și-ale sale Flash și Big, tocmai pentru că era nevoie de vederea numerelor mai mari, cu divizori impari pe măsură, apoi în 2012 a fost descoperită și puterea GMP-ului.

Pentru numerele cu unsigned long long (alias gmp_ui, întreg pe 64 de biți fără semn) și long double, am făcut mai demult niște funcții de tipul MODIFSUM, nefolosite încă însă, dar nu și MODPRIM și NUMSIMPL, care până acum au fost folosite exclusiv pentru mepezetele. FACTORSUBM cu atât mai puțin. Rămâne de văzut cât de greu va fi să le modific (cu salvare ca fișiere noi, desigur), pentru accesul la numere peste 19-20 de cifre va trebui să folosesc long double în loc de gmp_ui, care totuși este întreg ca mpz_t, iar trecerea la un tip de date neîntreg o să aducă probleme în plus, pe lângă schimbarea sintaxei cu care m-am obișnuit la mepezetele.

O problemă va fi chiar citirea din fișier a numerelor mari, interpretabile ca long double, care ar trebui scrise de forma divizorul mare impar * puterea de 2 cu care sunt divizibile; din dificultatea discriminării lor de numerele mai mici, care vor putea fi scrise integral în fișier, citirea inițială va trebui făcută ca string (char *Y) pentru toate numerele, și dacă lungimea lui Y este minim 20, să se verifice dacă are semnul * în el și long double să ia, cu înmulțire, părțile de dinainte și de după asterisc. Scrierea asta diferențiată în GIGM.TXT va trebui făcută și inițial, la derivarea lui din GIG52.TXT, și pe urmă, la actualizare - vecungizare. Și citirea va trebui să deosebească numerele - la NUMSIMPL, MODPRIM, MODIFSUM, FACTORSUBM (?) și vecungizare. De fapt, vecungizarea și sortarea pot fi mai departe bazate pe mpz_t, tipurile de date exclusiv native fiind pentru căutarea de numere noi. Dar când se citește direct în long double, numerele de maxim 19 cifre pot fi luate ca atare, pe când cele mai mari, mai ales peste 2^64 (2^64 însuși sigur nu va fi pe-acolo, având o abundență necorespunzătoare), vor trebui prelucrate special, cu despărțirea în doi divizori cu semnul înmulțirii.

Așa ar fi scenariul refolosirii Veritonului la numere. Aș putea să scot de tot Windowsul de pe Hitachi și să dedic tot hard diskul acela Arch Linuxului și numerelor, cred că boot loader-ul va putea fi pus tot pe HDD și nu pe un stick USB, dar desigur că va trebui reinstalat Arch Linuxul acolo.


Extragerea numerelor din GIG52.TXT pentru GIGM.TXT se poate face cu o funcție ca:

void GIGM() {
        char Y[150], TEXT[50] = "/run/media/root/3TB/GIG52.TXT", t;
        FILE *F1 = fopen(TEXT, "r"), *F2 = fopen("/GIGM.TXT", "w");
        gmp_ui PP = LUNGHEZ2(TEXT), PP1 = URC1(F1, 19, Y, t, 50000000U, PP, ':');
        printf("Totul: %llu, la 19 e: %llu.\n", PP, PP1);
        rewind(F1);
        mpz_t u, v, v1, w;
        int l;
        mpz_inits(u, v, v1, w, NULL);
        mpz_ui_pow_ui(w, 2, 64);
       
        CITR(8200000, F2, F1, PP1);
        rewind(F1);
        fseek(F1, PP1, SEEK_CUR);
       
        while(1) {
            if(ftell(F1) == PP)
                break;

            fgets(Y, 150, F1);
            mpz_set_str(u, Y, 10);
            l = mpz_scan1(u, 0);
            mpz_set_ui(v, 0);
            mpz_setbit(v, l);
            mpz_divexact(v1, u, v);
            if(mpz_cmp(v1, w) < 0) {//v1*v
                //gmp_fprintf(F2, "%Zd*%Zd\n", v1, v);
                fputs(Y, F2);
            }
        }
       
        fclose(F1);
        fclose(F2);
        mpz_clears(u, v, v1, w, NULL);
}

Pentru citirea din GIGM.TXT, până la 19 cifre long doublele poate să ia numerele ca atare, eventual folosind tot URC1()-ul, dar pentru „înmulțite” ar trebui așa:

void CITGIGM(gmp_ui PP1, gmp_ui PP) {//De la punctul cu 19 cifre.
    char Y[100];
    long double a;
    gmp_ui s1, s2;
    int i, m;

    FILE *F = fopen("/GIGM.TXT", "r");
    fseek(F, PP1, SEEK_CUR);

    while(1) {
        if(ftell(F) == PP)
            break;
        fgets(Y, 100, F);//De aici prelucrarea stringului.
        m = strlen(Y);
        s1 = 0;
        for(i = 0; Y[i] != '*'; i++) {
            s1 = s1*10 + (Y[i] - 48);
            }
       
        a = s1;
        s1 = 0;
        i++;
        for(; i < m; i++) {
            s1 = s*10 + (Y[i] - 48);
            }
       
        a *= s1;
        }
}


Sau numerele să fie toate scrise întregi în GIGM.TXT, ca mepezetele, iar la căutare convertite din mpz_t în long double, dar pentru cele peste 19 cifre sau, expres, pentru cele peste 2^64, să se facă trecerea în long double după modelul de aici:

while(1) {//De la PP1 de 19 cifre în sus.
        if(ftell(F) == PP)
            break;

        fgets(Y, 100, F);       
        mpz_set_str(u, Y, 10);
        //Sau:
        //gmp_fscanf(F, "%Zd", u);
        s1 = 1;
        s1 <<= mpz_scan1(u, 0);//Parul.
        mpz_divexact_ui(u, u, s1);//Imparul.
        a = s1; a *= mpz_get_ui(u);
        }
       
Iar pentru citire să se folosească la GIGM() numai și direct partea cu până la PP, fără discriminare pentru cele de maxim 19 cifre, dar pragul de 19 cifre să fie păstrat pentru la citire. Adică tot se face URC1().
       
Și vecungizarea să fie în mpz_t. Așa, nu va mai fi nevoie de prelucrări cu stele prin fișiere.

De separat factorii primi ai acestor numere, cei exclusivi, de ceilalți factori străini din CF52.TXT.
Asta trebuie să ajungă pe Veriton.


În 2019 cred că va trebui să-mi țin firea în fața noilor Threadrippere și să aștept anul 2020, cu o nouă generație de procesoare, bani mai mulți și... memoria DDR5.

Comentarii

Postări populare