#line 1 "rational.d"
/* Rationale Zahlen */

/* Liefert zu den Integers a und b mit b>1 und ggT(a,b)=1 den Bruch a/b. */
/* I_I_to_RT(a,b) */
/* can trigger GC */
  #define I_I_to_RT  make_ratio

/* Liefert zu den Integers a und b mit b>0 und ggT(a,b)=1 den Bruch a/b */
/* (Ratio oder Integer). */
/* I_I_to_RA(a,b) */
/* can trigger GC */
  local maygc object I_I_to_RA (object a, object b);
/* Methode: */
/* falls b=1, a als Ergebnis, sonst der echte Bruch a/b. */
  local maygc object I_I_to_RA (object a, object b)
  { GCTRIGGER2(a,b); {
    if (eq(b,Fixnum_1))
      return a;
    else
      return I_I_to_RT(a,b);
  }}
  /* define I_I_to_RA(a,b)  (eq(b,Fixnum_1) ? a : I_I_to_RT(a,b)) */

/* Liefert zu den Integers a und b mit b>0 den Bruch a/b (Ratio oder Integer). */
/* can trigger GC */
  local maygc object I_posI_div_RA (object a, object b);
/* Methode: */
/* d:=ggT(a,b). */
/* Falls d=1: I_I_to_RA anwenden, */
/* sonst: I_I_to_RA auf a/d und b/d anwenden. */
  local maygc object I_posI_div_RA (object a, object b)
  { GCTRIGGER2(a,b); {
    pushSTACK(a); pushSTACK(b); /* a,b retten */
    {var object d = I_I_gcd_I(a,b); /* ggT(a,b) >0 */
    if (eq(d,Fixnum_1)) { /* d=1 ? */
      b = popSTACK(); a = popSTACK();
      return I_I_to_RA(a,b);
    } else {
      /* Stackaufbau: a, b. */
      pushSTACK(d);
      STACK_2 = I_I_exquo_I(STACK_2,d); /* a/d bilden */
      d = popSTACK();
      /* Stackaufbau: a/d, b. */
      b = I_I_exquopos_I(popSTACK(),d); /* b/d bilden (b,d>0) */
      return I_I_to_RA(popSTACK(),b); /* (a/d)/(b/d) */
    }
  }}}

/* Liefert zu den Integers a und b den Bruch a/b (Ratio oder Integer). */
/* I_I_div_RA(a,b) */
/* can trigger GC */
  local maygc object I_I_div_RA (object a, object b);
/* Methode: */
/* Falls b=0: Error. */
/* Falls b>0: I_posI_div_RA anwenden. */
/* Falls b<0: I_posI_div_RA auf (- a) und (- b) anwenden. */
  local maygc object I_I_div_RA (object a, object b)
  { GCTRIGGER2(a,b); {
    if (eq(b,Fixnum_0))
      divide_0();
    if (R_minusp(b)) { /* b<0 ? */
      pushSTACK(b); a = I_minus_I(a); b = STACK_0; /* a := (- a) */
      STACK_0 = a; b = I_minus_I(b); a = popSTACK(); /* b := (- b) */
    }
    return I_posI_div_RA(a,b);
  }}

/* Liefert Zähler und Nenner einer rationalen Zahl. */
/* RA_numden_I_I(r, num=,den=); */
/* > r: rationale Zahl */
/* < num: (numerator r) */
/* < den: (denominator r) */
  #define RA_numden_I_I(r,num_assignment,den_assignment)  \
    {                                                                         \
      if (RA_integerp(r)) {                                                   \
        num_assignment r; den_assignment Fixnum_1; /* Zähler = r, Nenner = 1   */\
      } else {                                                                \
        num_assignment TheRatio(r)->rt_num; den_assignment TheRatio(r)->rt_den; \
      }                                                                       \
    }

/* Liefert (- r), wo r eine rationale Zahl ist. */
/* RA_minus_RA(r) */
/* can trigger GC */
  local maygc object RA_minus_RA (object r);
/* Methode: */
/* r Integer -> klar. */
/* r = a/b -> Ergebnis (- a)/b */
  local maygc object RA_minus_RA (object r)
  { GCTRIGGER1(r); {
    if (RA_integerp(r))
      return I_minus_I(r);
    else {
      pushSTACK(TheRatio(r)->rt_den); /* b retten */
      {var object a = TheRatio(r)->rt_num;
      a = I_minus_I(a); /* (- a) */
      /* Immer noch b>1 und ggT(-a,b) = ggT(a,b) = 1 */
      return I_I_to_RT(a,popSTACK());
    }}
  }}

/* (+ r s), wo r und s rationale Zahlen sind. */
/* RA_RA_plus_RA(r,s) */
/* can trigger GC */
  local maygc object RA_RA_plus_RA (object r, object s);
/* Methode (vgl. [Buchberger, Collins, Loos: Computer Algebra, S.200-201]) */
/* r,s beide Integers -> klar. */
/* r=a/b, s=c -> Ergebnis (a+b*c)/b */
/*   (mit b>1 und ggT(a+b*c,b) = ggT(a,b) = 1) */
/*   Bei c=0 direkt r als Ergebnis. */
/* r=a, s=c/d -> Ergebnis (a*d+c)/d */
/*   (mit d>1 und ggT(a*d+c,d) = ggT(c,d) = 1) */
/*   Bei a=0 direkt s als Ergebnis. */
/* r=a/b, s=c/d: */
/*   g:=ggT(b,d)>0. */
/*   Falls g=1: */
/*     Ergebnis (a*d+b*c)/(b*d), */
/*     (mit b*d>1 wegen b>1, d>1, und */
/*      ggT(a*d+b*c,b*d) = 1 */
/*      wegen ggT(a*d+b*c,b) = ggT(a*d,b) = 1 (wegen ggT(a,b)=1 und ggT(d,b)=1) */
/*      und   ggT(a*d+b*c,d) = ggT(b*c,d) = 1 (wegen ggT(b,d)=1 und ggT(c,d)=1) */
/*     ) */
/*   Sonst b' := b/g, d' := d/g. e := a*d'+b'*c, f:= b'*d = b*d'. */
/*   Es ist g = ggT(g*b',g*d') = g*ggT(b',d'), also ggT(b',d')=1. */
/*   Es ist r+s = (a*d+b*c)/(b*d) = (nach Kürzen mit g) e/f. */
/*   Außerdem: */
/*     ggT(a,b') teilt ggT(a,b)=1, also ggT(a,b')=1. Mit ggT(d',b')=1 folgt */
/*     1 = ggT(a*d',b') = ggT(a*d'+b'*c,b') = ggT(e,b'). */
/*     ggT(c,d') teilt ggT(c,d)=1, also ggT(c,d')=1. Mit ggT(b',d')=1 folgt */
/*     1 = ggT(b'*c,d') = ggT(a*d'+b'*c,d') = ggT(e,d'). */
/*     Daher ist ggT(e,f) = ggT(e,b'*d'*g) = ggT(e,g). */
/*   Errechne daher h=ggT(e,g). */
/*   Bei h=1 ist e/f das Ergebnis (mit f>1, da d>1, und ggT(e,f)=1), */
/*   sonst ist (e/h)/(f/h) das Ergebnis. */
  local maygc object RA_RA_plus_RA (object r, object s)
  { GCTRIGGER2(r,s); {
    if (RA_integerp(s)) {
      /* s ist Integer */
      if (eq(s,Fixnum_0)) /* s=0 -> r als Ergebnis */
        return r;
      if (RA_integerp(r))
        /* beides Integers */
        return I_I_plus_I(r,s);
      else {
        /* r = a/b, s = c. */
        {var object x = TheRatio(r)->rt_den; /* b */
        pushSTACK(x); pushSTACK(TheRatio(r)->rt_num); /* b und a retten */
        x = I_I_mult_I(x,s); /* b*c */
        x = I_I_plus_I(popSTACK(),x); /* a+b*c */
        return I_I_to_RT(x,popSTACK()); /* Bruch (a+b*c)/b */
      }}
    } else {
      /* s ist Ratio */
      if (RA_integerp(r)) {
        /* r ist Integer */
        if (eq(r,Fixnum_0)) /* r=0 -> s als Ergebnis */
          return s;
        /* r = a, s = c/d. */
        {var object x = TheRatio(s)->rt_den; /* d */
        pushSTACK(x); pushSTACK(TheRatio(s)->rt_num); /* d und c retten */
        x = I_I_mult_I(r,x); /* a*d */
        x = I_I_plus_I(x,popSTACK()); /* a*d+c */
        return I_I_to_RT(x,popSTACK()); /* Bruch (a*d+c)/d */
      }} else {
        /* r,s beide Ratios */
        {var object g;
        {
          {var object b;
          {var object d;
          pushSTACK(TheRatio(r)->rt_num); /* a retten */
          pushSTACK(b = TheRatio(r)->rt_den); /* b retten */
          pushSTACK(TheRatio(s)->rt_num); /* c retten */
          pushSTACK(d = TheRatio(s)->rt_den); /* d retten */
          /* Stackaufbau: a, b, c, d. */
          g = I_I_gcd_I(b,d); /* g = ggT(b,d) >0 bilden */
        }}}
        if (eq(g,Fixnum_1)) {
          /* g=1 -> Ergebnis (a*d+b*c)/(b*d) */
          {var object x;
          STACK_3 = I_I_mult_I(STACK_3,STACK_0); /* a*d */
          /* Stackaufbau: a*d, b, c, d. */
          x = I_I_mult_I(STACK_2,STACK_1); /* b*c */
          STACK_3 = I_I_plus_I(STACK_3,x); /* a*d+b*c */
          /* Stackaufbau: a*d+b*c, b, c, d. */
          x = I_I_mult_I(STACK_2,STACK_0); skipSTACK(3); /* b*d */
          return I_I_to_RT(popSTACK(),x); /* (a*d+b*c)/(b*d) */
        }} else {
          /* g>1 */
          {var object x;
          pushSTACK(g);
          /* Stackaufbau: a, b, c, d, g. */
          STACK_3 = I_I_exquopos_I(STACK_3,g); /* b' := b/g (b,g>0) */
          /* Stackaufbau: a, b', c, d, g. */
          x = I_I_exquopos_I(STACK_1,STACK_0); /* d' := d/g (d,g>0) */
          STACK_4 = I_I_mult_I(STACK_4,x); /* a*d' */
          /* Stackaufbau: a*d', b', c, d, g. */
          x = I_I_mult_I(STACK_3,STACK_2); /* b'*c */
          STACK_4 = I_I_plus_I(STACK_4,x); /* e := a*d'+b'*c */
          /* Stackaufbau: e, b', c, d, g. */
          STACK_3 = I_I_mult_I(STACK_3,STACK_1); /* f := b'*d */
          /* Stackaufbau: e, f, c, d, g. */
          x = I_I_gcd_I(STACK_4,STACK_0); skipSTACK(3); /* h := ggT(e,g) */
          /* Stackaufbau: e, f. */
          if (eq(x,Fixnum_1)) {
            /* h=1 */
            {var object f = popSTACK();
            {var object e = popSTACK();
            return I_I_to_RT(e,f); /* Bruch e/f bilden */
          }}} else {
            /* h>1 */
            pushSTACK(x);
            /* Stackaufbau: e, f, h. */
            STACK_2 = I_I_exquo_I(STACK_2,x); /* e/h bilden */
            /* Stackaufbau: e/h, f, h. */
            x = popSTACK(); /* h */
            x = I_I_exquopos_I(popSTACK(),x); /* f/h bilden (f,h>0) */
            return I_I_to_RA(popSTACK(),x); /* (e/h)/(f/h) als Ergebnis */
          }
        }}
      }}
    }
  }}

/* (- r s), wo r und s rationale Zahlen sind. */
/* RA_RA_minus_RA(r,s) */
/* can trigger GC */
  local maygc object RA_RA_minus_RA (object r, object s);
#if 0
/* Methode: */
/* (+ r (- s)) */
  local maygc object RA_RA_minus_RA (object r, object s)
  { GCTRIGGER2(r,s); {
    pushSTACK(r); s = RA_minus_RA(s);
    return RA_RA_plus_RA(popSTACK(),s);
  }}
#else
/* Methode (vgl. [Buchberger, Collins, Loos: Computer Algebra, S.200-201]) */
/* r,s beide Integers -> klar. */
/* r=a/b, s=c -> Ergebnis (a-b*c)/b */
/*   (mit b>1 und ggT(a-b*c,b) = ggT(a,b) = 1) */
/*   Bei c=0 direkt r als Ergebnis. */
/* r=a, s=c/d -> Ergebnis (a*d-c)/d */
/*   (mit d>1 und ggT(a*d-c,d) = ggT(-c,d) = ggT(c,d) = 1) */
/*   Bei a=0 direkt -s = (-c)/d als Ergebnis. */
/* r=a/b, s=c/d: */
/*   g:=ggT(b,d)>0. */
/*   Falls g=1: */
/*     Ergebnis (a*d-b*c)/(b*d), */
/*     (mit b*d>1 wegen b>1, d>1, und */
/*      ggT(a*d-b*c,b*d) = 1 */
/*      wegen ggT(a*d-b*c,b) = ggT(a*d,b) = 1 (wegen ggT(a,b)=1 und ggT(d,b)=1) */
/*      und   ggT(a*d-b*c,d) = ggT(b*c,d) = 1 (wegen ggT(b,d)=1 und ggT(c,d)=1) */
/*     ) */
/*   Sonst b' := b/g, d' := d/g. e := a*d'-b'*c, f:= b'*d = b*d'. */
/*   Es ist g = ggT(g*b',g*d') = g*ggT(b',d'), also ggT(b',d')=1. */
/*   Es ist r-s = (a*d-b*c)/(b*d) = (nach Kürzen mit g) e/f. */
/*   Außerdem: */
/*     ggT(a,b') teilt ggT(a,b)=1, also ggT(a,b')=1. Mit ggT(d',b')=1 folgt */
/*     1 = ggT(a*d',b') = ggT(a*d'-b'*c,b') = ggT(e,b'). */
/*     ggT(c,d') teilt ggT(c,d)=1, also ggT(c,d')=1. Mit ggT(b',d')=1 folgt */
/*     1 = ggT(b'*c,d') = ggT(a*d'-b'*c,d') = ggT(e,d'). */
/*     Daher ist ggT(e,f) = ggT(e,b'*d'*g) = ggT(e,g). */
/*   Errechne daher h=ggT(e,g). */
/*   Bei h=1 ist e/f das Ergebnis (mit f>1, da d>1, und ggT(e,f)=1), */
/*   sonst ist (e/h)/(f/h) das Ergebnis. */
  local maygc object RA_RA_minus_RA (object r, object s)
  { GCTRIGGER2(r,s); {
    if (RA_integerp(s)) {
      /* s ist Integer */
      if (eq(s,Fixnum_0)) /* s=0 -> r als Ergebnis */
        return r;
      if (RA_integerp(r))
        /* beides Integers */
        return I_I_minus_I(r,s);
      else {
        /* r = a/b, s = c. */
        {var object x = TheRatio(r)->rt_den; /* b */
        pushSTACK(x); pushSTACK(TheRatio(r)->rt_num); /* b und a retten */
        x = I_I_mult_I(x,s); /* b*c */
        x = I_I_minus_I(popSTACK(),x); /* a-b*c */
        return I_I_to_RT(x,popSTACK()); /* Bruch (a-b*c)/b */
      }}
    } else {
      /* s ist Ratio */
      if (RA_integerp(r)) {
        /* r ist Integer */
        if (eq(r,Fixnum_0)) {
          /* r=0 -> -s = (-c)/d als Ergebnis */
          pushSTACK(TheRatio(s)->rt_den); /* d */
          s = I_minus_I(TheRatio(s)->rt_num); /* -c */
          return I_I_to_RT(s,popSTACK());
        }
        /* r = a, s = c/d. */
        {var object x = TheRatio(s)->rt_den; /* d */
        pushSTACK(x); pushSTACK(TheRatio(s)->rt_num); /* d und c retten */
        x = I_I_mult_I(r,x); /* a*d */
        x = I_I_minus_I(x,popSTACK()); /* a*d-c */
        return I_I_to_RT(x,popSTACK()); /* Bruch (a*d-c)/d */
      }} else {
        /* r,s beide Ratios */
        {var object g;
        {
          {var object b;
          {var object d;
          pushSTACK(TheRatio(r)->rt_num); /* a retten */
          pushSTACK(b = TheRatio(r)->rt_den); /* b retten */
          pushSTACK(TheRatio(s)->rt_num); /* c retten */
          pushSTACK(d = TheRatio(s)->rt_den); /* d retten */
          /* Stackaufbau: a, b, c, d. */
          g = I_I_gcd_I(b,d); /* g = ggT(b,d) >0 bilden */
        }}}
        if (eq(g,Fixnum_1)) {
          /* g=1 -> Ergebnis (a*d-b*c)/(b*d) */
          {var object x;
          STACK_3 = I_I_mult_I(STACK_3,STACK_0); /* a*d */
          /* Stackaufbau: a*d, b, c, d. */
          x = I_I_mult_I(STACK_2,STACK_1); /* b*c */
          STACK_3 = I_I_minus_I(STACK_3,x); /* a*d-b*c */
          /* Stackaufbau: a*d-b*c, b, c, d. */
          x = I_I_mult_I(STACK_2,STACK_0); skipSTACK(3); /* b*d */
          return I_I_to_RT(popSTACK(),x); /* (a*d-b*c)/(b*d) */
        }} else {
          /* g>1 */
          {var object x;
          pushSTACK(g);
          /* Stackaufbau: a, b, c, d, g. */
          STACK_3 = I_I_exquopos_I(STACK_3,g); /* b' := b/g (b,g>0) */
          /* Stackaufbau: a, b', c, d, g. */
          x = I_I_exquopos_I(STACK_1,STACK_0); /* d' := d/g (d,g>0) */
          STACK_4 = I_I_mult_I(STACK_4,x); /* a*d' */
          /* Stackaufbau: a*d', b', c, d, g. */
          x = I_I_mult_I(STACK_3,STACK_2); /* b'*c */
          STACK_4 = I_I_minus_I(STACK_4,x); /* e := a*d'-b'*c */
          /* Stackaufbau: e, b', c, d, g. */
          STACK_3 = I_I_mult_I(STACK_3,STACK_1); /* f := b'*d */
          /* Stackaufbau: e, f, c, d, g. */
          x = I_I_gcd_I(STACK_4,STACK_0); skipSTACK(3); /* h := ggT(e,g) */
          /* Stackaufbau: e, f. */
          if (eq(x,Fixnum_1)) {
            /* h=1 */
            {var object f = popSTACK();
            {var object e = popSTACK();
            return I_I_to_RT(e,f); /* Bruch e/f bilden */
          }}} else {
            /* h>1 */
            pushSTACK(x);
            /* Stackaufbau: e, f, h. */
            STACK_2 = I_I_exquo_I(STACK_2,x); /* e/h bilden */
            /* Stackaufbau: e/h, f, h. */
            x = popSTACK(); /* h */
            x = I_I_exquopos_I(popSTACK(),x); /* f/h bilden (f,h>0) */
            return I_I_to_RA(popSTACK(),x); /* (e/h)/(f/h) als Ergebnis */
          }
        }}
      }}
    }
  }}
#endif

/* (1+ r), wo r eine rationale Zahl ist. */
/* RA_1_plus_RA(r) */
/* can trigger GC */
  local maygc object RA_1_plus_RA (object r);
/* Methode: */
/* Falls r ein Integer ist: I_1_plus_I anwenden */
/* Falls r = a/b: (a+b)/b, wobei b>1 und ggT(a+b,b)=ggT(a,b)=1 ist. */
  local maygc object RA_1_plus_RA (object r)
  { GCTRIGGER1(r); {
    if (RA_integerp(r))
      return I_1_plus_I(r);
    else {
      {var object x;
      x = TheRatio(r)->rt_den; pushSTACK(x); /* b */
      x = I_I_plus_I(TheRatio(r)->rt_num,x); /* a+b */
      return I_I_to_RT(x,popSTACK()); /* (a+b)/b */
    }}
  }}

/* (1- r), wo r eine rationale Zahl ist. */
/* RA_minus1_plus_RA(r) */
/* can trigger GC */
  local maygc object RA_minus1_plus_RA (object r);
/* Methode: */
/* Falls r ein Integer ist: I_minus1_plus_I anwenden */
/* Falls r = a/b: (a-b)/b, wobei b>1 und ggT(a-b,b)=ggT(a,b)=1 ist. */
  local maygc object RA_minus1_plus_RA (object r)
  { GCTRIGGER1(r); {
    if (RA_integerp(r)) {
      return I_minus1_plus_I(r);
    } else {
      {var object x;
      x = TheRatio(r)->rt_den; pushSTACK(x); /* b */
      x = I_I_minus_I(TheRatio(r)->rt_num,x); /* a-b */
      return I_I_to_RT(x,popSTACK()); /* (a-b)/b */
    }}
  }}

/* RA_RA_comp(r,s) vergleicht zwei rationale Zahlen r und s. */
/* Ergebnis: 0 falls r=s, +1 falls r>s, -1 falls r<s. */
/* can trigger GC */
  local maygc signean RA_RA_comp (object r, object s);
/* Methode: */
/* r,s Integer -> klar */
/* r<0, s>=0 -> r<s. */
/* r>=0, s<0 -> r>s. */
/* r Integer, s Ratio: r=a, s=b/c. Vergleiche a*c und b. */
/* r Ratio, s Integer: r=a/b, s=c. Vergleiche a und b*c. */
/* r,s Ratios: r=a/b, s=c/d. Vergleiche a*d und b*c. */
  local maygc signean RA_RA_comp (object r, object s)
  { GCTRIGGER2(r,s); {
    /* 1. Schritt: Test, ob beides Integers: */
    if (RA_integerp(r) && RA_integerp(s))
      return I_I_comp(r,s);
    /* r,s nicht beide Integers. */
    /* 2. Schritt: Test, ob die Vorzeichen bereits das Ergebnis hergeben: */
    if (R_minusp(r)) {
      if (!R_minusp(s)) /* r<0, s>=0 -> r<s */
        return signean_minus;
    } else {
      if (R_minusp(s)) /* r>=0, s<0 -> r>s */
        return signean_plus;
    }
    /* r,s haben gleiches Vorzeichen. */
    /* 3. Schritt: Fallunterscheidung nach Typen */
    if (RA_integerp(r)) {
      /* r Integer, s Ratio: r=a, s=b/c. Vergleiche a*c und b. */
      pushSTACK(TheRatio(s)->rt_num); /* b */
      r = I_I_mult_I(r,TheRatio(s)->rt_den); /* a*c */
      return I_I_comp(r,popSTACK()); /* mit b vergleichen */
    } else if (RA_integerp(s)) {
      /* r Ratio, s Integer: r=a/b, s=c. Vergleiche a und b*c. */
      pushSTACK(TheRatio(r)->rt_num); /* a */
      s = I_I_mult_I(TheRatio(r)->rt_den,s); /* b*c */
      return I_I_comp(popSTACK(),s); /* und a damit vergleichen */
    } else {
      /* r,s Ratios: r=a/b, s=c/d. Vergleiche a*d und b*c. */
      pushSTACK(TheRatio(r)->rt_num); /* a */
      pushSTACK(TheRatio(s)->rt_den); /* d */
      /* Stackaufbau: a, d. */
      {var object x = I_I_mult_I(TheRatio(r)->rt_den,TheRatio(s)->rt_num); /* b*c */
      {var object a = STACK_1;
      STACK_1 = x;
      /* Stackaufbau: b*c, d. */
      x = I_I_mult_I(a,popSTACK()); /* a*d */
      return I_I_comp(x,popSTACK()); /* a*d und b*c vergleichen */
    }}}
  }}

/* Kehrwert (/ r), wo r eine rationale Zahl ist. */
/* RA_div_RA(r) */
/* can trigger GC */
  local maygc object RA_div_RA (object r);
/* Methode: */
/* r=0 -> Error. */
/* a:=(numerator r), b:=(denominator r). */
/* a>0 -> Ergebnis b/a (mit ggT(b,a)=1). */
/* a<0 -> Ergebnis (- b)/(- a) (mit ggT(-b,-a)=1). */
  local maygc object RA_div_RA (object r)
  { GCTRIGGER1(r); {
    if (eq(r,Fixnum_0)) /* Test auf 0 */
      divide_0();
    {var object a;
    {var object b;
    RA_numden_I_I(r,a=,b=); /* a:=(numerator r), b:=(denominator r) */
    if (R_minusp(a)) {
      /* a<0 */
      pushSTACK(a); b = I_minus_I(b); a = STACK_0; /* b := (- b) */
      STACK_0 = b; a = I_minus_I(a); b = popSTACK(); /* a := (- a) */
    }
    return I_I_to_RA(b,a);
  }}}}

/* Liefert (* r r), wo r eine rationale Zahl ist. */
/* RA_square_RA(r) */
/* can trigger GC */
  local maygc object RA_square_RA (object r);
/* Methode: */
/* r Integer -> klar. */
/* r = a/b -> Ergebnis a^2/b^2 */
  local maygc object RA_square_RA (object r)
  { GCTRIGGER1(r); {
    if (RA_integerp(r))
      /* r Integer */
      return I_square_I(r);
    else {
      /* r=a/b */
      {var object a;
      {var object b;
      pushSTACK(TheRatio(r)->rt_den); /* b retten */
      a = TheRatio(r)->rt_num;
      a = I_square_I(a); /* a^2 */
      b = STACK_0; STACK_0 = a;
      b = I_square_I(b); /* b^2 */
      a = popSTACK();
      /* Immer noch b^2>1 und ggT(a^2,b^2) = ggT(a,b)^2 = 1 */
      return I_I_to_RT(a,b);
    }}}
  }}

/* Liefert (* r s), wo r und s rationale Zahlen sind. */
/* RA_RA_mult_RA(r,s) */
/* can trigger GC */
  local maygc object RA_RA_mult_RA (object r, object s);
/* Methode (vgl. [Buchberger, Collins, Loos: Computer Algebra, S.201]) */
/* r,s beide Integers -> klar. */
/* r=a/b, s=c -> */
/*   Bei c=0 Ergebnis 0. */
/*   g:=ggT(b,c). */
/*   Falls g=1: Ergebnis (a*c)/b (mit b>1, ggT(a*c,b)=1). */
/*   Sonst: b':=b/g, c':=c/g, Ergebnis (a*c')/b' (mit ggT(a*c',b')=1). */
/* r=a, s=c/d analog. */
/* r=a/b, s=c/d -> */
/*   g:=ggT(a,d), h:=ggT(b,c). */
/*   a':=a/g, d':=d/g (nur bei g>1 bedeutet das Rechnung). */
/*   b':=b/h, c':=c/h (nur bei h>1 bedeutet das Rechnung). */
/*   Ergebnis ist = (a'*c')/(b'*d'). */
  local maygc object RA_RA_mult_RA (object r, object s)
  { GCTRIGGER2(r,s); {
    {var object a;
    {var object b;
    {var object c;
    if (RA_integerp(s)) {
      /* s Integer */
      if (RA_integerp(r))
        /* beides Integer */
        return I_I_mult_I(r,s);
      else {
        /* r=a/b, s=c */
        a = TheRatio(r)->rt_num; b = TheRatio(r)->rt_den; c = s;
        mixed: /* Bilde a/b * c */
        if (eq(c,Fixnum_0)) /* c=0 -> Ergebnis 0 */
          return c;
        pushSTACK(b); pushSTACK(a); pushSTACK(c);
        /* Stackaufbau: b, a, c. */
        {var object g = I_I_gcd_I(b,c); /* g := ggT(b,c) */
        if (eq(g,Fixnum_1)) {
          /* g=1 */
          c = popSTACK(); /* c */
          c = I_I_mult_I(popSTACK(),c); /* a*c */
          return I_I_to_RT(c,popSTACK()); /* (a*c)/b */
        } else {
          /* g>1 */
          pushSTACK(g);
          /* Stackaufbau: b, a, c, g. */
          STACK_3 = I_I_exquopos_I(STACK_3,g); /* b' := b/g (b,g>0) */
          /* Stackaufbau: b', a, c, g. */
          g = popSTACK();
          c = I_I_exquo_I(popSTACK(),g); /* c' := c/g */
          c = I_I_mult_I(popSTACK(),c); /* a*c' */
          return I_I_to_RA(c,popSTACK()); /* (a*c')/b' */
        }
      }}
    } else {
      /* s ist Ratio */
      if (RA_integerp(r)) {
        /* r=c, s=a/b */
        a = TheRatio(s)->rt_num; b = TheRatio(s)->rt_den; c = r;
        goto mixed;
      } else {
        /* r,s beide Ratios */
        {var object d;
        a = TheRatio(r)->rt_num; pushSTACK(a); /* a */
        pushSTACK(TheRatio(r)->rt_den); /* b */
        d = TheRatio(s)->rt_den; pushSTACK(d); /* d */
        pushSTACK(TheRatio(s)->rt_num); /* c */
        /* Stackaufbau: a, b, d, c. */
        {
          {var object g = I_I_gcd_I(a,d); /* g := ggT(a,d) */
          if (!eq(g,Fixnum_1)) {
            /* bei g>1: dividiere a und d durch g */
            a = STACK_3; STACK_3 = g;
            a = I_I_exquo_I(a,g); /* a':=a/g */
            g = STACK_3; STACK_3 = a;
            STACK_1 = I_I_exquopos_I(STACK_1,g); /* d':=d/g (d,g>0) */
          }
        }}
        /* Stackaufbau: a', b, d', c. */
        {
          {var object h = I_I_gcd_I(STACK_2,STACK_0); /* h := ggT(b,c) */
          if (!eq(h,Fixnum_1)) {
            /* bei h>1: dividiere c und b durch h */
            c = STACK_0; STACK_0 = h;
            c = I_I_exquo_I(c,h); /* c':=c/h */
            h = STACK_0; STACK_0 = c;
            STACK_2 = I_I_exquopos_I(STACK_2,h); /* b':=b/h (b,h>0) */
          }
        }}
        /* Stackaufbau: a', b', d', c'. */
        c = popSTACK(); STACK_2 = I_I_mult_I(STACK_2,c); /* a'*c' */
        /* Stackaufbau: a'*c', b', d'. */
        d = popSTACK(); d = I_I_mult_I(popSTACK(),d); /* b'*d' */
        /* Stackaufbau: a'*c'. */
        return I_I_to_RA(popSTACK(),d); /* (a'*c')/(b'*d') */
      }}
    }
  }}}}}

/* Liefert (/ r s), wo r und s rationale Zahlen sind. */
/* RA_RA_div_RA(r,s) */
/* can trigger GC */
  local maygc object RA_RA_div_RA (object r, object s);
/* Methode: */
/* (* r (/ s)) */
  local maygc object RA_RA_div_RA (object r, object s)
  { GCTRIGGER2(r,s); {
    if (RA_integerp(r) && RA_integerp(s)) /* r und s Integers? */
      return I_I_div_RA(r,s); /* ja -> schnell abhandeln */
    pushSTACK(r);
    s = RA_div_RA(s); /* (/ s) */
    return RA_RA_mult_RA(popSTACK(),s);
  }}

/* Liefert ganzzahligen und gebrochenen Anteil einer rationalen Zahl. */
/* (q,r) := (truncate x) */
/* RA_truncate_I_RA(x); */
/* > x: rationale Zahl */
/* < STACK_1: Quotient q, ein Integer */
/* < STACK_0: Rest r, eine rationale Zahl */
/* Erniedrigt STACK um 2 */
/* can trigger GC */
  local maygc void RA_truncate_I_RA (object x);
/* Methode: */
/* x Integer -> (q,r) := (x,0) */
/* x Ratio a/b -> */
/*   (truncate a b) liefert q und r. */
/*   Liefere q und r/b (mit b>1 und ggT(r,b)=ggT(r+q*b,b)=ggT(a,b)=1). */
  local maygc void RA_truncate_I_RA (object x)
  { GCTRIGGER1(x); {
    if (RA_integerp(x)) {
      pushSTACK(x); pushSTACK(Fixnum_0); /* (q,r) := (x,0) */
    } else {
      {var object b = TheRatio(x)->rt_den;
      pushSTACK(b);
      I_I_truncate_I_I(TheRatio(x)->rt_num,b); /* (truncate a b) */
      /* Stackaufbau: b, q, r. */
      b = STACK_2;
      STACK_2 = STACK_1; /* q unverändert */
      {var object r = popSTACK();
      STACK_0 = I_I_to_RT(r,b);
    }}}
  }}

/* Liefert ganzzahligen und gebrochenen Anteil einer rationalen Zahl. */
/* (q,r) := (floor x) */
/* RA_floor_I_RA(x); */
/* > x: rationale Zahl */
/* < STACK_1: Quotient q, ein Integer */
/* < STACK_0: Rest r, eine rationale Zahl */
/* Erniedrigt STACK um 2 */
/* can trigger GC */
  local maygc void RA_floor_I_RA (object x);
/* Methode: */
/* x Integer -> (q,r) := (x,0) */
/* x Ratio a/b -> */
/*   (floor a b) liefert q und r. */
/*   Liefere q und r/b (mit b>1 und ggT(r,b)=ggT(r+q*b,b)=ggT(a,b)=1). */
  local maygc void RA_floor_I_RA (object x)
  { GCTRIGGER1(x); {
    if (RA_integerp(x)) {
      pushSTACK(x); pushSTACK(Fixnum_0); /* (q,r) := (x,0) */
    } else {
      {var object b = TheRatio(x)->rt_den;
      pushSTACK(b);
      I_I_floor_I_I(TheRatio(x)->rt_num,b); /* (floor a b) */
      /* Stackaufbau: b, q, r. */
      b = STACK_2;
      STACK_2 = STACK_1; /* q unverändert */
      {var object r = popSTACK();
      STACK_0 = I_I_to_RT(r,b);
    }}}
  }}

/* Liefert ganzzahligen und gebrochenen Anteil einer rationalen Zahl. */
/* (q,r) := (ceiling x) */
/* RA_ceiling_I_RA(x); */
/* > x: rationale Zahl */
/* < STACK_1: Quotient q, ein Integer */
/* < STACK_0: Rest r, eine rationale Zahl */
/* Erniedrigt STACK um 2 */
/* can trigger GC */
  local maygc void RA_ceiling_I_RA (object x);
/* Methode: */
/* x Integer -> (q,r) := (x,0) */
/* x Ratio a/b -> */
/*   (ceiling a b) liefert q und r. */
/*   Liefere q und r/b (mit b>1 und ggT(r,b)=ggT(r+q*b,b)=ggT(a,b)=1). */
  local maygc void RA_ceiling_I_RA (object x)
  { GCTRIGGER1(x); {
    if (RA_integerp(x)) {
      pushSTACK(x); pushSTACK(Fixnum_0); /* (q,r) := (x,0) */
    } else {
      {var object b = TheRatio(x)->rt_den;
      pushSTACK(b);
      I_I_ceiling_I_I(TheRatio(x)->rt_num,b); /* (ceiling a b) */
      /* Stackaufbau: b, q, r. */
      b = STACK_2;
      STACK_2 = STACK_1; /* q unverändert */
      {var object r = popSTACK();
      STACK_0 = I_I_to_RT(r,b);
    }}}
  }}

/* Liefert ganzzahligen und gebrochenen Anteil einer rationalen Zahl. */
/* (q,r) := (round x) */
/* RA_round_I_RA(x); */
/* > x: rationale Zahl */
/* < STACK_1: Quotient q, ein Integer */
/* < STACK_0: Rest r, eine rationale Zahl */
/* Erniedrigt STACK um 2 */
/* can trigger GC */
  local maygc void RA_round_I_RA (object x);
/* Methode: */
/* x Integer -> (q,r) := (x,0) */
/* x Ratio a/b -> */
/*   (round a b) liefert q und r. */
/*   Liefere q und r/b (mit b>1 und ggT(r,b)=ggT(r+q*b,b)=ggT(a,b)=1). */
  local maygc void RA_round_I_RA (object x)
  { GCTRIGGER1(x); {
    if (RA_integerp(x)) {
      pushSTACK(x); pushSTACK(Fixnum_0); /* (q,r) := (x,0) */
    } else {
      {var object b = TheRatio(x)->rt_den;
      pushSTACK(b);
      I_I_round_I_I(TheRatio(x)->rt_num,b); /* (round a b) */
      /* Stackaufbau: b, q, r. */
      b = STACK_2;
      STACK_2 = STACK_1; /* q unverändert */
      {var object r = popSTACK();
      STACK_0 = I_I_to_RT(r,b);
    }}}
  }}

/* RA_I_expt_RA(x,y) = (expt x y), wo x eine rationale Zahl und y ein Integer >0 ist. */
/* can trigger GC */
  local object RA_I_expt_RA (object x, object y);
  /* Methode: */
  /* x Integer -> klar */
  /* x Ratio a/b -> x^y = (a^y)/(b^y), gekürzt, mit b^y>=b>1. */
  local maygc object RA_I_expt_RA (object x, object y)
  { GCTRIGGER2(x,y); {
    if (RA_integerp(x))
      return I_I_expt_I(x,y);
    else {
      pushSTACK(y);
      pushSTACK(TheRatio(x)->rt_den);
      x = I_I_expt_I(TheRatio(x)->rt_num,y); /* a^y */
      y = STACK_1; STACK_1 = x;
      x = I_I_expt_I(popSTACK(),y); /* b^y */
      return I_I_to_RT(popSTACK(),x); /* (a^y)/(b^y) */
    }
  }}

/* Stellt fest, ob eine rationale Zahl >=0 das Quadrat einer rationalen Zahl */
/* ist. */
/* RA_sqrtp(x) */
/* > x: eine rationale Zahl >=0 */
/* < result: exakte Wurzel (sqrt x) falls x Quadrat, nullobj sonst */
/* can trigger GC */
  local maygc object RA_sqrtp (object x);
/* Methode: */
/* Bei Integers: klar. */
/* Bei Brüchen a/b : muss a=c^2 und b=d^2 sein. Dann ist die Wurzel = c/d */
/* (mit ggT(c,d)=1 und d>1). */
  local maygc object RA_sqrtp (object x)
  { GCTRIGGER1(x); {
    if (RA_integerp(x))
      return I_sqrtp(x);
    else {
      /* x ist Ratio */
      pushSTACK(TheRatio(x)->rt_num); /* Zähler retten */
      x = TheRatio(x)->rt_den;
      {var object h = I_sqrtp(x); /* Nenner auf Quadratzahl testen */
      if (eq(h,nullobj)) {
        skipSTACK(1); return nullobj;
      }
      x = STACK_0; STACK_0 = h;
      h = I_sqrtp(x); /* Zähler auf Quadratzahl testen */
      if (eq(h,nullobj)) {
        skipSTACK(1); return nullobj;
      }
      /* beides Quadratzahlen -> Quotient der Wurzeln bilden */
      return I_I_to_RT(h,popSTACK());
    }}
  }}

/* Stellt fest, ob eine rationale Zahl >=0 die n-te Potenz einer rationalen Zahl */
/* ist. */
/* RA_rootp(x,n) */
/* > x: eine rationale Zahl >=0 */
/* > n: ein Integer >0 */
/* < result: exakte n-te Wurzel (expt x (/ n)) falls eine n-te Potenz, nullobj sonst */
/* can trigger GC */
  local maygc object RA_rootp (object x, object n);
/* Methode: */
/* Bei Integers: klar. */
/* Bei Brüchen a/b : muss a=c^n und b=d^n sein. Dann ist die Wurzel = c/d */
/* (mit ggT(c,d)=1 und d>1). */
  local maygc object RA_rootp (object x, object n)
  { GCTRIGGER2(x,n); {
    if (RA_integerp(x))
      return I_rootp(x,n);
    else {
      /* x ist Ratio */
      pushSTACK(TheRatio(x)->rt_num); pushSTACK(n); /* Zähler und n retten */
      x = TheRatio(x)->rt_den;
      {var object h = I_rootp(x,n); /* Nenner auf n-te Potenz testen */
      if (eq(h,nullobj)) {
        skipSTACK(2); return nullobj;
      }
      n = popSTACK(); x = STACK_0; STACK_0 = h;
      h = I_rootp(x,n); /* Zähler auf n-te Potenz testen */
      if (eq(h,nullobj)) {
        skipSTACK(1); return nullobj;
      }
      /* beides n-te Potenzen -> Quotient der Wurzeln bilden */
      return I_I_to_RT(h,popSTACK());
    }}
  }}

