/** DEBUT BIGINT addition(BIGINT, BIGINT); DEBUT **/ BIGINT addition(BIGINT nb1, BIGINT nb2) { BIGINT resultat; int tmp; unsigned int retenue = 0; initListe(&resultat); /// Gestion du signe du résultat /// if(nb1.signe == MOINS && nb2.signe == PLUS) { nb1.signe = PLUS; resultat = soustraction(nb1, nb2); resultat.signe = MOINS; return resultat; } else if (nb1.signe == PLUS && nb2.signe == MOINS) { nb2.signe = PLUS; return resultat = soustraction(nb1, nb2); } else if(nb1.signe == MOINS && nb2.signe == MOINS) { resultat.signe = MOINS; nb1.signe = PLUS; nb2.signe = PLUS; } while(!listeVide(nb1) && !listeVide(nb2)) { tmp = nb1.fin->valeur + nb2.fin->valeur + retenue; retenue = tmp / 10; empilerListe(&resultat, tmp % 10); nb1.fin = nb1.fin->precedent; nb2.fin = nb2.fin->precedent; } /// Necessaire si nb1.nbEl > nb2.nbEl, il faut finir l'addition avec le reste des chiffres de nb1.nbEl /// /** J'ai séparé volontairement cette condition de la boucle principale, pour éviter une condition qui n'est pas nécessaire ** dans le cas ou nb1.nbEl = nb2.nbEl. Cela ajoute une répétition dans l'ecriture mais un léger gain en performance **/ while(!listeVide(nb1)) { tmp = nb1.fin->valeur + retenue; retenue = tmp / 10; empilerListe(&resultat, tmp % 10); nb1.fin = nb1.fin->precedent; } /// Necessaire si nb2.nbEl > nb1.nbEl, il faut finir l'addition avec le reste des chiffres de nb2.nbEl /// /** J'ai séparé volontairement cette condition de la boucle principale, pour éviter une condition qui n'est pas nécessaire ** dans le cas ou nb2.nbEl = nb1.nbEl. Cela ajoute une répétition dans l'ecriture mais un léger gain en performance **/ while(!listeVide(nb2)) { tmp = nb2.fin->valeur + retenue; retenue = tmp / 10; empilerListe(&resultat, tmp % 10); nb2.fin = nb2.fin->precedent; } /// Ajout de la retenue de fin, si elle existe. Exemple 99 + 10 = 1 retenue et 09 => 109 // if(retenue) empilerListe(&resultat, 1); nettoyerNb(&resultat); return resultat; }
void CommandeManager::calculer(QString& chaine) throw(LogMessage){ QStringList liste = chaine.split(' ',QString::SkipEmptyParts); for(QStringList::Iterator it = liste.begin();it!=liste.end();++it){ QString current = *it; if(current.contains(QRegExp("'.*"))){ QString expr=""; do{ expr+=current; expr+=" "; it++; current = *it; } while(!current.contains(QRegExp(".*'"))); expr+=current; _pile->empilerExpression(expr); } else if(current.contains(QRegExp("^\\+$"))) addition(); else if(current.contains(QRegExp("^\\-$"))) soustraction(); else if(current.contains(QRegExp("^\\*$"))) multiplication(); else if(current.contains(QRegExp("^/$"))) division(); else{ try{ _pile->empilerConstante(_factory.getConstante(current)); } catch(LogMessage& msg){ throw; } } } }
Solutions resoudre_second_degre(Complexe b, Complexe c) { Complexe quatre_c = {c.re * 4, c.im *4}; Complexe moins_b = {- b.re, - b.im}; Complexe deux_a = {2, 2}; Complexe delta = sqrt(soustraction(multiplication(b,b), quatre_c)); Complexe z1; Complexe z2; if (delta.re == 0 && delta.im == 0) { Complexe p = z1 = division(moins_b, deux_a); z2 = z1; } else { z1 = division(addition(moins_b, delta), deux_a); z2 = division(soustraction(moins_b, delta), deux_a); } Solutions s = {z1, z2}; return s; }
char *modulo(char *base, char *operators, char *expr1, char *expr2) { char tmp[2]; tmp[0] = base[1]; tmp[1] = '\0'; while (is_sup(base, expr1, expr2)) { my_strcpy(expr1, soustraction(base, operators, expr1, expr2)); } return (expr1); }
/** DEBUT BIGINT divisionScolaire(BIGINT, BIGINT); DEBUT **/ BIGINT divisionScolaire(BIGINT nb1, BIGINT nb2) { BIGINT resultat, ligne; BIGINT tmp; initListe(&resultat); initListe(&ligne); /// Variable pour vidage mémoire des calculs intermédiaires /// initListe(&tmp); /// Gestion du signe du résultat /// resultat.signe = nb1.signe * nb2.signe; nb1.signe = PLUS; nb2.signe = PLUS; if(comparer_nb(nb1, nb2) == INF) { empilerListe(&resultat, 0); return resultat; } else if(comparer_nb(nb1, nb2) == EGAL) { empilerListe(&resultat, 1); return resultat; } else if(nb2.debut->valeur == 0 && nb2.nbEl == 1) { /// Impossible de diviser par zero /// return; } while(!listeVide(nb1)) { insererFin(&ligne, 0); ligne.fin->valeur = nb1.debut->valeur; insererFin(&resultat, 0); nettoyerNb(&ligne); while(comparer_nb(ligne, nb2) >= EGAL) { resultat.fin->valeur += 1; tmp = soustraction(ligne, nb2); viderListe(&ligne); ligne = tmp; } nb1.debut = nb1.debut->suivant; } nettoyerNb(&resultat); return resultat; }
/* Subtraction of any number of matrices */ Ref sub_call(ref_list args){ if (args->length < 1 ) { set_err(EMISSARG, "need at least one argument"); return NULL; } if (arg_isMatrix(args->list[0]) == false) return NULL; Matrix m = CAST_REF2MATRIX(args->list[0]); Matrix sub = copyMatrix(m); if (sub == NULL) return NULL; unsigned int i; for (i = 1; i < args->length; i++){ if (arg_isMatrix(args->list[i]) == false) goto error; m = CAST_REF2MATRIX(args->list[i]); if (m->nrows != sub->nrows || m->ncols != sub->ncols) { set_err(EMXDIM,"dimensions don't match"); goto error; } Matrix tmp = soustraction(sub, m); if (tmp == NULL ) goto error; dropMatrix(sub); sub = tmp; } /* Return a reference */ Ref r = new_vref(NULL, sub, MATRIX); if (r == NULL) dropMatrix(sub); return r; error: dropMatrix(sub); return NULL; }
char *division(char *base, char *operators, char *expr1, char *expr2) { char *res; char tmp[2]; tmp[0] = base[1]; tmp[1] = '\0'; if ((res = malloc(sizeof(*res) * my_strlen(expr1) + my_strlen(expr2) + 1)) == 0) return (NULL); res[0] = base[0]; res[1] = '\0'; if (((indice_in_base(base, expr2[0]) == 1)) && (my_strlen(expr2) == 1)) return (expr1); while (is_sup(base, expr1, expr2)) { my_strcpy(expr1, soustraction(base, operators, expr1, expr2)); my_strcpy(res, addition(base, res, tmp)); } return (res); }
char *modulo(char *base, char *operators,char *expr1,char *expr2) { char tmp[2]; tmp[0] = base[1]; tmp[1] = '\0'; while (is_sup(base, expr1, expr2)) { my_strcpy(expr1, soustraction(base, operators, expr1, expr2)); } int nb; int nb2; int nb3; int nb4; int nb5; int nb6; nb = 3%1; nb2 = 2%4; nb3 = -4%2; nb4 = 4%-2; nb5 = 2%6; nb6 = -4%-4; my_putstr("\n 3%1 :: "); my_put_nbr(nb); /* my_putstr("\n 2%4;"); my_put_nbr(nb2); my_putstr("\n -4%2; "); my_put_nbr(nb3); my_putstr("\n 4%-2; "); my_put_nbr(nb4); my_putstr("\n 2%6; "); my_put_nbr(nb5); my_putstr("\n -4%-4 "); my_put_nbr(nb6);*/ my_putstr("FIN::::::::"); return (expr1); }
/** * Entrée d'une commande (STDIN) et retour d'une réponse appropriée (STDOUT). * Retourne -1 lors d'une demande de quitter le programme, ou 0 si on continue. * * Invite l'utilisateur à entrer des commandes au format postfixe (ex: 3 2 + 5 * =a). */ int traitement_commande() { printf("> "); char* entree = entreeDynamique(stdin); if(entree == NULL) { printf("Pas assez de mémoire pour allouer l'entrée.\n"); return 0; } if(strcmp(entree, "\0") == 0) { // Si l'utilisateur quitte ou entre une ligne vide. free(entree); return -1; } // Les différentes parties sont séparées par des espaces. char* partie = strtok(entree, " "); // Pile des commandes entrées, une fois exécutées. pile* commandes = malloc(sizeof(pile)); if(commandes == NULL) { printf("Entrée invalide. La mémoire maximale a été dépassée.\n"); free(entree); return 0; } pile_init(commandes); do { if(strcmp(partie, "+") == 0 || strcmp(partie, "-") == 0 || strcmp(partie, "*") == 0) { if(pile_count(commandes) >= 2) { num* r; num* b = pile_pop(commandes); num* a = pile_pop(commandes); if(strcmp(partie, "+") == 0) { r = addition(a, b, a->positif, b->positif); } else if(strcmp(partie, "-") == 0) { r = soustraction(a, b, a->positif, b->positif); } else if(strcmp(partie, "*") == 0) { r = multiplication(a, b); } if(r == NULL) { printf("Mauvais calcul !\n"); superFree(a); superFree(b); free(entree); free(commandes); return 0; } pile_push(commandes, r); } else { printf("Erreur: il manque une entree pour faire une operation !\n"); free(entree); free(commandes); return 0; } } else if(partie[0] == '=' && strlen(partie) == 2 && partie[1] >= 'a' && partie[1] <= 'z') { // Assignation de variable, on assigne et on continue comme si de rien n'était. if(pile_count(commandes) > 0) { variables[(int) partie[1] % 32] = pile_peek(commandes); } else { printf("Que voulez-vous assigner ? Il manque quelque chose...\n"); free(entree); free(commandes); return 0; } } else if(strlen(partie) == 1 && partie[0] >= 'a' && partie[0] <= 'z') { // Variable, on met sa valeur dans la pile d'opérations. if(variables[(int) partie[0] % 32] != NULL) { pile_push(commandes, variables[(int) partie[0] % 32]); } else { printf("La variable '%c' n'est pas encore définie.\n", partie[0]); free(commandes); free(entree); return 0; } } else { int est_un_nombre = 1; int i = 0; while(i < strlen(partie)) { if(partie[i] < '0' || partie[i] > '9') { est_un_nombre = 0; break; } i++; } if(est_un_nombre == 1) { // Valeur, on la met dans un nombre à précision infinie et on met sa référence dans la pile. num* valeur = malloc(sizeof(num)); if(valeur == NULL) { printf("Entrée invalide. La mémoire maximale a été dépassée.\n"); free(entree); free(commandes); return 0; } strToBigNum(partie, valeur); pile_push(commandes, valeur); } else { // Caractère non-valide. printf("Les éléments doivent tous être des variables (a-z, minuscule), des opérateurs ou bien des valeurs positives entières.\n"); return 0; } } } while(partie = strtok(NULL, " ")); if(partie != NULL) { free(partie); } if(entree != NULL) { free(entree); } if(pile_count(commandes) == 1) { printNum(pile_pop(commandes)); } else { printf("Erreur de syntaxe, veuillez completer vos calculs !\n"); } free(commandes->data); free(commandes); return 0; }
/** * Opération d'addition. */ num* addition(num* a, num* b, int ancien_a_positif, int ancien_b_positif) { if(a->positif == 0 && b->positif == 1) { a->positif = 1; return soustraction(b, a, ancien_b_positif, ancien_a_positif); // Vu que a et b sont inversés, leur "ancien_a_positif" et "ancien_b_positif" aussi. } if(a->positif == 1 && b->positif == 0) { b->positif = 1; return soustraction(a, b, ancien_a_positif, ancien_b_positif); } if(a->positif == 0 && b->positif == 0) { b->positif = 1; return soustraction(a, b, ancien_a_positif, ancien_b_positif); } setupNombres(a, b); cell* cA = a->nombre; cell* cB = b->nombre; if(!cA || !cB) { return NULL; } cell* result = malloc(sizeof(cell)); memcheck(result); num* r = malloc(sizeof(num)); memcheck(r); r->longueur = 0; int fini = 0; int intermediaire = 0; int carry = 0; cell* newUnit = NULL; r->nombre = result; while(!fini) { fini = cA->suivant == NULL && cB->suivant == NULL; intermediaire = cA->chiffre + cB->chiffre + carry; if(intermediaire > 9) { carry = 1; intermediaire -= 10; } else { carry = 0; } result->chiffre = intermediaire; if(!fini) { // Ajustement des pointeurs pour le prochain round si pertinent. newUnit = malloc(sizeof(cell)); memcheck(newUnit); newUnit->suivant = NULL; newUnit->precedent = result; result->suivant = newUnit; result = newUnit; } cA = cA->suivant; cB = cB->suivant; r->longueur++; } if(newUnit == NULL) { // Cas particulier où on n'a pas de "carry" et un seul digit dans chaque opérande (ex : 2+2). result->suivant = NULL; r->dernier = result; } else { newUnit->suivant = NULL; r->dernier = newUnit; } if(carry) { cell* carryCell = malloc(sizeof(cell)); memcheck(carryCell); carryCell->chiffre = carry; carryCell->precedent = result; result->suivant = carryCell; carryCell->suivant = NULL; r->dernier = carryCell; r->longueur++; } r->positif = 1; a->positif = ancien_a_positif; b->positif = ancien_b_positif; return r; }
/** DEBUT BIGINT multiplicationKaratsuba(BIGINT, BIGINT); DEBUT **/ BIGINT multiplicationKaratsuba(BIGINT nb1, BIGINT nb2) { BIGINT x0, x1, y0, y1, p0, p1, p2, resultat; BIGINT tmp, tmp2; int m, i, signe_nb1, signe_nb2; signe_nb1 = nb1.signe; signe_nb2 = nb2.signe; nb1.signe = PLUS; nb2.signe = PLUS; nb1.signe = PLUS; nb2.signe = PLUS; initListe(&resultat); /// Variables pour calculs intermédiaires /// initListe(&x0); initListe(&x1); initListe(&y0); initListe(&y1); initListe(&p0); initListe(&p1); initListe(&p2); /// Variables pour vidage mémoire des calculs intermédiaires /// initListe(&tmp); initListe(&tmp2); /// On enlève les 0 devant nb1 et nb2, car la taille du nombre est importante dans l'execution de l'algorithme de karatsuba /// nettoyerNb(&nb1); nettoyerNb(&nb2); /// m = milieu du plus grand nombre. Exemple : 9828839 => m = 4, 192893 => m = 3 /// m = (max_element(nb1, nb2) + 1) / 2; /// Creation de x0 et x1, dont nb1 = x1 * B^m + x0 /// if(nb1.nbEl <= m) { x0 = clone(nb1); empilerListe(&x1, 0); } else { for(i = 0; i < m; i += 1) { empilerListe(&x0, nb1.fin->valeur); nb1.fin = nb1.fin->precedent; } while(!listeVide(nb1)) { empilerListe(&x1, nb1.fin->valeur); nb1.fin = nb1.fin->precedent; } } /// Creation de y0 et y1, dont nb2 = y1 * B^m + y0 /// if(nb2.nbEl <= m) { y0 = clone(nb2); empilerListe(&y1, 0); } else { for(i = 0; i < m; i += 1) { empilerListe(&y0, nb2.fin->valeur); nb2.fin = nb2.fin->precedent; } while(!listeVide(nb2)) { empilerListe(&y1, nb2.fin->valeur); nb2.fin = nb2.fin->precedent; } } /// On enlève les 0 devant x0, x1, y0 et y1, car la taille du nombre est importante dans l'execution de l'algorithme de karatsuba /// nettoyerNb(&x0); nettoyerNb(&x1); nettoyerNb(&y0); nettoyerNb(&y1); /// Calculs d'après l'algorithme de karatsuba (voir description) /// p0 = multiplication(x0, y0); p2 = multiplication(x1, y1); tmp = addition(x0, x1); tmp2 = addition(y0, y1); p1 = multiplication(tmp, tmp2); viderListe(&tmp); viderListe(&tmp2); viderListe(&x0); viderListe(&x1); viderListe(&y0); viderListe(&y1); tmp = soustraction(p1, p2); p1 = soustraction(tmp, p0); viderListe(&tmp); puissancede10(&p1, m); puissancede10(&p2, (m * 2)); tmp = addition(p0, p2); resultat = addition(p1, tmp); viderListe(&tmp); /// Gestion du signe du résultat /// resultat.signe = signe_nb1 * signe_nb2; return resultat; }
Ref speedtest_cmd(ref_list args){ puts("Starting test..."); bool doplot = true; keepgoing = true; Fun f = (Fun) args->list[0]->inst; int min = (int) (*(float*) ((Var)args->list[1]->inst)->val); int max = (int) (*(float*) ((Var)args->list[2]->inst)->val); int step = (int) (*(float*) ((Var)args->list[3]->inst)->val); if ( min > max || step == 0) { set_err(ENOVAL, "infinite tests are not allowed"); return NULL; } /* Optional parameter */ if (args->length > 4 && cmptype_ref(FLOAT, args->list[4])) { int countdown = (int) (*(float*) ((Var)args->list[4]->inst)->val); signal(SIGALRM, stop_speedtest); alarm(countdown); } /* Points list */ clock_t* y_time = malloc (sizeof(clock_t) * (max-min)/step + 1); int* x_size = malloc (sizeof(int) * (max-min)/step + 1); if (y_time == NULL || x_size == NULL){ free(x_size); free(y_time); return NULL; } int i,j; for ( i = min, j=0; i <= max && keepgoing ; i += step, j++){ /* Generate matrices. Note: they don't need to be initialized */ Matrix m1 = newMatrix(i,i), m2 = newMatrix(i,i), ret = NULL; float* f1 = malloc(sizeof(float)); if (m1 == NULL || m2 == NULL || f1 == NULL){ perror(""); keepgoing = false; doplot = false; } /* Start test */ clock_t start = clock(); if (f->fun == mult_call) { ret = multiplication(m1,m2); } else if ( f->fun == sub_call) { ret = soustraction(m1,m2); } else if (f->fun == addition_call){ ret = addition(m1,m2); } else if (f->fun == transpose_call){ ret = transpose(m1); } else if (f->fun == determinant_call){ determinant(m1, f1); } else if (f->fun == invert_call){ invert(m1,&ret); } else if (f->fun == rank_call ){ rank(m1); } else { printf("Sorry...cannot test this function\n"); keepgoing = false; doplot = false; } /* Finish test */ clock_t end = clock(); /* Store result */ x_size[j] = i; y_time[j] = end-start; dropMatrix(m1); dropMatrix(m2); dropMatrix(ret); free(f1); } alarm(0); // Remove countdown if (doplot == true) plot(args->list[0]->name, x_size, y_time, j); free(x_size); free(y_time); return NO_REF; }