/********************************************************************* * * * BASIC FUNCTIONS FOR ANY MATHS PROGRAM * * * * (Module to link with any program using Function.cpp) * * ------------------------------------------------------------------ * * Alain Reverchon, 1989, France [BIBLI 14] * * * * C++ english version by J-P Moreau, Paris * * (reduced to meet the need of fonction.cpp). * * (www.jpmoreau.fr) * ********************************************************************** Note: the use of type ar_nombre is optional. */ #include "armath.h" char ar_temp [80], ar_temp_2 [80]; //print a message to screen void ar_aff(char *s) { printf("%s", s); } //************* RATIONAL APPROXIMATION OF A REAL NUMBER // return a fraction p/q near the real number r. void ar_calcule_rationnel (double r, long *p, long *q) { double ab, ax; long lastp , lastq, inter, ac; *p = 0; *q = 1; if (fabs (r) > 1E-8) { ax = fabs (r); ab = ax; ac = (long) ab; *p = ac; lastp = 1; lastq = 0; while (1E7 * fabs (ax * *q - *p) > ax * *q) { ab = 1 / (ab - ac); ac = (long) ab; inter = ac * *p + lastp; lastp = *p; *p = inter; inter = ac * *q + lastq; lastq = *q; *q = inter; if ((*q > 1E7) || (*p * *q > 1E9)) { *p = lastp / lastq; *q = 1; ax = *p; } } } if (r < 0) *p = -*p; } //********************* DISPLAY A RATIONAL APPROXIMATION // p/q of a real number r. void ar_aff_rationnel (double r) { long p, q; ar_calcule_rationnel (r, &p, &q); if ((q != 1) && (labs (p) < 32700) && (labs (q) < 32700)) { sprintf (ar_temp_2, " # %ld / %ld", p, q); ar_aff (ar_temp_2); } } //********************** DISPLAY INTEGER WITH NAME void ar_aff_long (char *tx, long x) { sprintf (ar_temp_2, "%s%ld", tx, x); ar_aff (ar_temp_2); } void ar_aff_long_ln (char *tx, long x) { ar_aff_long (tx, x); ar_aff ("\n"); } //********************* DISPLAY REAL and RATIONAL APPR. WITH NAME void ar_aff_reel (char *tx, double r, int rat) { sprintf (ar_temp_2, "%s %24.12lf", tx, r); ar_aff (ar_temp_2); if (rat) ar_aff_rationnel (r); } //********************* DISPLAY REAL and RATIONAL APPR. WITH NAME // and go to next line void ar_aff_reel_ln (char *tx, double r, int rat) { ar_aff_reel (tx, r, rat); ar_aff ("\n"); } //Macro to update sign #define UPDATE \ negatif = ((resul.p > 0) && (resul.q < 0)) || \ ((resul.q > 0) && (resul.p < 0)); \ resul.p = (long) labs (resul.p / s); \ resul.q = (long) labs (resul.q / s); \ if (negatif) resul.p = - resul.p; //return position of char c in string ch int ar_strfind (char *ch, char c) { unsigned int i; for (i = 0; i < strlen (ch); i++) if (ch [i] == c) return (i); return (-1); } //********************* Calculate GCD of 2 long integers long ar_pgcd (long a, long b) { long ir; a = labs (a); b = labs (b); if ((a == 0) || (b == 0)) return (1); if (a < b) { ir = a; a = b; b = ir; } do { ir = a % b; a = b; b = ir; } while (ir > 0); return (a); } //***************** Transform a string into a number of type ar_nombre // accepted inputs: integer, rational p/q, real number // Note: the type ar_nombre is defined in header file armath.h //-------------------------------------------------------------------- int ar_anal_nombre (ar_nombre *n, char *ch) { int j; long r; n->reel = AR_NON; //return FALSE if ((j = ar_strfind (ch, '/')) > -1) { // CASE RATIONAL strncpy (ar_temp_2, ch, j); ar_temp_2 [j] = 0; if ((n->p = atol (ar_temp_2)) == 0) return (AR_NON); if ((n->q = atol (&ch [j + 1])) == 0) return (AR_NON); r = ar_pgcd (n->p, n->q); n->p /= r; n->q /= r; n->valeur = (double) n->p / (double) n->q; } else { /* CAS REEL */ if ((n->valeur = atof (ch)) == 0) if (strcmp (ch, "0")) return (AR_NON); n->reel = (ar_strfind (ch, '.') != -1) || (n->valeur > AR_GRAND); if (! n->reel) { // CASE INTEGER n->p = (long) n->valeur; n->q = 1; } } return (AR_OUI); //return TRUE } //********************* Transform an integer into a number // of type ar_nombre (integer,rational or real) void ar_set_nombre (ar_nombre *n, long l) { n->reel = AR_NON; n->p = l; n->q = 1; n->valeur = (double) l; } //********************* Multiply two numbers of type ar_nombre int ar_multiplie_nombre (ar_nombre *x, ar_nombre *y, ar_nombre *z) { ar_nombre resul; long s; int negatif; resul.reel = (x->reel) || (y->reel); resul.valeur = x->valeur * y->valeur; if (resul.valeur == 0) { resul.p = 0; resul.q = 1; } else { if ((labs (x->p) > AR_GRAND) || (labs (x->q) > AR_GRAND) || (labs (y->p) > AR_GRAND) || (labs (y->q) > AR_GRAND) || (fabs (resul.valeur) > AR_GRAND)) resul.reel = AR_OUI; if (! resul.reel) { resul.p = x->p * y->p; resul.q = x->q * y->q; s = ar_pgcd (resul.p, resul.q); UPDATE } } COPYNOM (z, &resul); return (AR_OUI); } //************************* Divide two numbers of type ar_nombre int ar_divise_nombre (ar_nombre *x, ar_nombre *y, ar_nombre *z) { ar_nombre resul; long s; int negatif; if (y->valeur == 0) return (AR_NON); resul.reel = (x->reel) || (y->reel); resul.valeur = x->valeur / y->valeur; if ((labs (x->p) > AR_GRAND) || (labs (x->q) > AR_GRAND) || (labs (y->p) > AR_GRAND) || (labs (y->q) > AR_GRAND)) resul.reel = AR_OUI; if (! resul.reel) { resul.p = x->p * y->q; resul.q = x->q * y->p; s = ar_pgcd (resul.p, resul.q); UPDATE } COPYNOM (z, &resul); return (AR_OUI); } //**************************** Add two numbers of type ar_nombre int ar_addition_nombre (ar_nombre *x, ar_nombre *y, ar_nombre *z) { ar_nombre resul; long s; int negatif; if (x->valeur == 0) COPYNOM (&resul, y); else if (y->valeur == 0) COPYNOM (&resul, x); else { resul.reel = (x->reel) || (y->reel); resul.valeur = x->valeur + y->valeur; if ((labs (x->p) > AR_GRAND) || (labs (x->q) > AR_GRAND) || (labs (y->p) > AR_GRAND) || (labs (y->q) > AR_GRAND) || (fabs (resul.valeur) > AR_GRAND)) resul.reel = AR_OUI; if (! resul.reel) { resul.p = x->p * y->q + x->q * y->p; resul.q = x->q * y->q; s = ar_pgcd (x->q, y->q); UPDATE } } COPYNOM (z, &resul); return (AR_OUI); } //********************** Display a number of type ar_nombre // (integer,rational p/q or real) void ar_aff_nombre (ar_nombre *n) { if (n->reel) ar_aff_reel ("", n->valeur, AR_SANSAPPRO); else { ar_aff_long ((n->valeur > 0) ? "+ " : "- ", labs (n->p)); if (labs (n->q) != 1) ar_aff_long (" / ", labs (n->q)); } ar_aff ("\n"); } // end of file armath.cpp