]> www.ginac.de Git - cln.git/blob - src/rational/elem/cl_RA_plus.cc
* All Files have been modified for inclusion of namespace cln;
[cln.git] / src / rational / elem / cl_RA_plus.cc
1 // binary operator +
2
3 // General includes.
4 #include "cl_sysdep.h"
5
6 // Specification.
7 #include "cln/rational.h"
8
9
10 // Implementation.
11
12 #include "cl_RA.h"
13 #include "cln/integer.h"
14 #include "cl_I.h"
15
16 namespace cln {
17
18 const cl_RA operator+ (const cl_RA& r, const cl_RA& s)
19 {
20 // Methode (vgl. [Buchberger, Collins, Loos: Computer Algebra, S.200-201])
21 // r,s beide Integers -> klar.
22 // r=a/b, s=c -> Ergebnis (a+b*c)/b
23 //   (mit b>1 und ggT(a+b*c,b) = ggT(a,b) = 1)
24 //   Bei c=0 direkt r als Ergebnis.
25 // r=a, s=c/d -> Ergebnis (a*d+c)/d
26 //   (mit d>1 und ggT(a*d+c,d) = ggT(c,d) = 1)
27 //   Bei a=0 direkt s als Ergebnis.
28 // r=a/b, s=c/d:
29 //   g:=ggT(b,d)>0.
30 //   Falls g=1:
31 //     Ergebnis (a*d+b*c)/(b*d),
32 //     (mit b*d>1 wegen b>1, d>1, und
33 //      ggT(a*d+b*c,b*d) = 1
34 //      wegen ggT(a*d+b*c,b) = ggT(a*d,b) = 1 (wegen ggT(a,b)=1 und ggT(d,b)=1)
35 //      und   ggT(a*d+b*c,d) = ggT(b*c,d) = 1 (wegen ggT(b,d)=1 und ggT(c,d)=1)
36 //     )
37 //   Sonst b' := b/g, d' := d/g. e := a*d'+b'*c, f:= b'*d = b*d'.
38 //   Es ist g = ggT(g*b',g*d') = g*ggT(b',d'), also ggT(b',d')=1.
39 //   Es ist r+s = (a*d+b*c)/(b*d) = (nach Kürzen mit g) e/f.
40 //   Außerdem:
41 //     ggT(a,b') teilt ggT(a,b)=1, also ggT(a,b')=1. Mit ggT(d',b')=1 folgt
42 //     1 = ggT(a*d',b') = ggT(a*d'+b'*c,b') = ggT(e,b').
43 //     ggT(c,d') teilt ggT(c,d)=1, also ggT(c,d')=1. Mit ggT(b',d')=1 folgt
44 //     1 = ggT(b'*c,d') = ggT(a*d'+b'*c,d') = ggT(e,d').
45 //     Daher ist ggT(e,f) = ggT(e,b'*d'*g) = ggT(e,g).
46 //   Errechne daher h=ggT(e,g).
47 //   Bei h=1 ist e/f das Ergebnis (mit f>1, da d>1, und ggT(e,f)=1),
48 //   sonst ist (e/h)/(f/h) das Ergebnis.
49         if (integerp(s)) {
50                 // s ist Integer
51                 DeclareType(cl_I,s);
52                 if (eq(s,0)) { return r; } // s=0 -> r als Ergebnis
53                 if (integerp(r)) {
54                         // beides Integers
55                         DeclareType(cl_I,r);
56                         return r+s;
57                 } else {
58                         DeclareType(cl_RT,r);
59                         var const cl_I& a = numerator(r);
60                         var const cl_I& b = denominator(r);
61                         var const cl_I& c = s;
62                         // r = a/b, s = c.
63                         return I_I_to_RT(a+b*c,b);
64                 }
65         } else {
66                 // s ist Ratio
67                 DeclareType(cl_RT,s);
68                 if (integerp(r)) {
69                         // r ist Integer
70                         DeclareType(cl_I,r);
71                         if (eq(r,0)) { return s; } // r=0 -> s als Ergebnis
72                         var const cl_I& a = r;
73                         var const cl_I& c = numerator(s);
74                         var const cl_I& d = denominator(s);
75                         // r = a, s = c/d.
76                         return I_I_to_RT(a*d+c,d);
77                 } else {
78                         // r,s beide Ratios
79                         DeclareType(cl_RT,r);
80                         var const cl_I& a = numerator(r);
81                         var const cl_I& b = denominator(r);
82                         var const cl_I& c = numerator(s);
83                         var const cl_I& d = denominator(s);
84                         var cl_I g = gcd(b,d); // g = ggT(b,d) >0 bilden
85                         if (eq(g,1))
86                                 // g=1 -> Ergebnis (a*d+b*c)/(b*d)
87                                 return I_I_to_RT(a*d+b*c,b*d);
88                         // g>1
89                         var cl_I bp = exquopos(b,g); // b' := b/g (b,g>0)
90                         var cl_I dp = exquopos(d,g); // d' := d/g (d,g>0)
91                         var cl_I e = a*dp+bp*c; // e := a*d'+b'*c
92                         var cl_I f = bp*d; // f := b'*d
93                         var cl_I h = gcd(e,g); // h := ggT(e,g)
94                         if (eq(h,1))
95                                 // h=1
96                                 return I_I_to_RT(e,f);
97                         // h>1
98                         return I_I_to_RA(exquo(e,h),exquopos(f,h)); // (e/h)/(f/h) als Ergebnis
99                 }
100         }
101 }
102
103 }  // namespace cln