Note: This website is archived. For up-to-date information about D projects and development, please visit wiki.dlang.org.

root/trunk/etc/longrational.d

Revision 20, 10.9 kB (checked in by danielrh, 21 years ago)

added the changes required to get vec working with all basic types

Line 
1 /*
2 Copyright (c) 2004 Daniel Horn
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8 1. Redistributions of source code must retain the above copyright
9    notice, this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11    notice, this list of conditions and the following disclaimer in the
12    documentation and/or other materials provided with the distribution.
13 3. The name of the author may not be used to endorse or promote products
14    derived from this software without specific prior written permission.
15
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 module etc.longrational;
28 /*
29 version (Long) {
30 }else {
31   import bigint.bigint;
32   alias bigint.bigint.Int Int;
33 }
34 */
35
36 /*
37 version (Long) {
38 }else {
39   template TypeCreate(T:Int) {
40     Int make (int i) {
41       return new Int(i);
42     }
43     real retrieve (Int k) {
44       return std.string.atof(k.toString());
45     }
46     long retrieveLong (Int k) {
47       return k.toLong();
48     }
49     Int make (char[] i) {
50       return new Int (i);
51     }
52   }
53   template ToString (T:Int) {
54     char[] toString(T a) {
55       return a.toString();
56     }
57   }
58   alias TypeCreate!(Int).make makeType;
59 }
60 version (Long) {
61 }else {
62 template Zero(T:Int) {
63   Int zero() {
64     static Int z = new Int(0);
65     return z;
66   }
67   Int one () {
68     static Int o = new Int(1);
69     return o;
70   }
71 }
72 */
73
74 struct BigRational(T, int rat, Allocator) {
75   private import std.string;
76   private import std.math;
77
78   static BigRational ZERO() {
79     static BigRational z = BigRational();
80     return z;
81   }
82   static BigRational ONE() {
83     static BigRational o=BigRational.create(Allocator.one,
84                         Allocator.one);
85     return o;
86   }
87   static BigRational MINUS_ONE() {
88     static BigRational o=BigRational.create(-Allocator.one,
89                         Allocator.one);
90     return o;
91   }
92   static BigRational TWO() {
93     static BigRational o=BigRational.create(Allocator.one+Allocator.one,
94                         Allocator.one);
95     return o;
96   }
97  private:
98   T n;
99   T d;
100   static T int_pow (T a, T b) {
101     if (b==Allocator.zero) return Allocator.one;
102     if (b==Allocator.one) return a;
103     static T two =Allocator.one+Allocator.one;
104     T half_b = b/two;
105     T tmp=int_pow(a,half_b);
106     if (a%tmp!=Allocator.zero) {
107     return a*tmp*tmp;
108     }else {
109       return tmp*tmp;
110     }
111   }
112   static T int_gcd_recurse (T less, T more) {
113     T zero = Allocator.zero;
114     if (less==zero)
115       return more;
116     T amb = more%less;
117     if (amb==zero) {
118       return less;
119     }
120     return int_gcd_recurse(amb,less);
121   }
122   static T int_abs (T a) {
123     T zero = Allocator.zero;
124     return a<zero?-a:a;
125   }
126   static T int_gcd (T aa,  T bb) {
127     T a = int_abs(aa);
128     T b = int_abs(bb);
129     return int_gcd_recurse(a<b?a:b,a<b?b:a);
130   }
131   static T int_modshr(T a) {
132     static T zero = Allocator.zero;
133     static T one = Allocator.one;
134     static T two = one+one;
135     if (a%two!=zero&&a!=one)
136       return a/two+one;
137     return a/two;
138   }
139   static T int_sqrt(T a) {
140     if (a==Allocator.one) {
141       return Allocator.one;
142     }
143     if (a==Allocator.zero)
144       return Allocator.zero;
145     T guess = int_modshr(a);
146     T mag = int_modshr(guess);
147     while (mag>Allocator.zero) {
148       T sqrguess = guess*guess;
149       if (sqrguess==a)
150     return guess;
151       if (sqrguess<a) {
152     guess=guess+mag;
153       }else {
154     guess=guess-mag;
155       }     
156       mag=int_modshr(mag);
157     }
158     assert (guess*guess==a);
159     return guess;
160   }
161   BigRational InternalRationalize() {
162     if (d<Allocator.zero) {
163       n=-n;
164       d=-d;
165     }
166     if (rat!=0)
167       return Rationalize();
168     return *this;
169   }
170  public:
171   int wholeNumber() {
172     Rationalize();
173     return d==Allocator.one;
174   }
175   BigRational sqrt () {
176     Rationalize();
177     return create(int_sqrt(n),int_sqrt(d));
178   }
179   real toReal() {
180     Rationalize();
181     return Allocator.retrieve(n/d)+Allocator.retrieve(n%d)/Allocator.retrieve(d);
182   }
183   static BigRational opCall (BigRational r) {
184     return create(r.n,r.d);
185   }
186   BigRational abs() {
187     if ((*this)>=BigRational.ZERO)
188       return *this;
189     return -*this;
190   }
191   long toLong() {
192     Rationalize();
193     return Allocator.retrieveLong(n/d);
194   } 
195   static BigRational create (T nn) {
196     BigRational r;
197     r.n=nn;
198     r.d=Allocator.one;
199     return r;
200   }
201
202   static BigRational create (T nn, T dd) {
203     BigRational r;
204     r.n=nn;
205     r.d=dd;
206     return r;
207   }
208   static BigRational opCall (real r) {
209     if (r<0) return -opCall(-r);
210     if (r==0) return opCall();
211     T d=Allocator.one;
212     while (r!=std.math.floor(r)) {
213       r*=2;
214       d=d+d;
215     }
216     return create(Allocator.make(std.string.toString(r)),d);
217   }
218   static BigRational opCall (double r) {
219     return opCall(cast(real)r);
220   }
221   static BigRational opCall (float r) {
222     return opCall(cast(real)r);
223   }
224   static BigRational opCall (long nn, ulong dd) {
225     BigRational r;
226     r.n=Allocator.make(nn);
227     r.d=Allocator.make(dd);
228     return r;
229   }
230   static BigRational opCall (long nn) {
231     BigRational r;
232     r.n=Allocator.make(nn);
233     r.d=Allocator.one;
234     return r;
235   }
236   static BigRational opCall (int nn) {
237     return opCall(cast(long)nn);
238   }
239   static BigRational opCall (uint nn) {
240     return opCall(cast(long)nn);
241   }
242   static BigRational opCall (ulong nn) {
243     return opCall(cast(long)nn);
244   }
245
246   static BigRational opCall (char[] nn, char[] dd) {
247     BigRational r;
248     r.n=Allocator.make(nn);
249     r.d=Allocator.make(dd);
250     return r;
251   }
252   static BigRational opCall (char[] nn) {
253     BigRational r;
254     r.n=Allocator.make(nn);
255     r.d=Allocator.one;
256     return r;
257   }
258   static BigRational opCall () {
259     BigRational r;
260     r.n = Allocator.zero;
261     r.d = Allocator.one;
262     //char* tmp = std.string.toStringz(ToString!(T).toString();
263     return r;
264   }
265   BigRational Rationalize() {
266     T k = int_gcd(n,d);
267     n=n/k;
268     d=d/k;
269     return *this;
270   }
271   void swap(inout BigRational b) {
272     T bn=b.n;
273     T bd=b.d;
274     b.n=n;
275     b.d=d;
276     n=bn;
277     d=bd;
278   }
279   BigRational opNeg() {
280     return create(-n,d).InternalRationalize();
281   }
282   T IntegerPart() {
283     return n/d;
284   }
285   T Floor() {
286     T k = n/d;
287     if (n<Allocator.zero&&k*d!=n)
288       k=k-Allocator.one;
289     return k;
290   }
291   BigRational floor() {
292     return BigRational.create(Floor());
293   }
294   T Ceil() {
295     T k = n/d;
296     if (k>Allocator.zero&&k*d!=n)
297       k=k+Allocator.one;
298     return k;
299   }
300   BigRational ceil() {
301     return BigRational.create(Ceil());
302   }
303   BigRational pow(T b) {
304     return create(int_pow(n,b),int_pow(d,b));
305   }
306   BigRational Fraction() {
307     BigRational ret = *this-create(Floor(),Allocator.one);
308     //    if (ret<BigRational())
309     //      ret+=BigRational(Allocator.one,Allocator.one);
310     return ret;
311   }
312   int isFloat() {
313     static T zero = Allocator.zero;
314     static T one = Allocator.one;
315     static T two = one+one;
316     T g = int_gcd(n,d);
317     g= d/g;
318     T cur = one;
319     while (cur<=g) {
320       if (cur==g)
321     return 1;
322       cur=cur*two;
323     }
324     return 0;
325   }
326   T FractionalFloat(uint term) {
327     static T zero = Allocator.zero;
328     static T one = Allocator.one;
329     static T two = one+one;
330     assert (isFloat());
331     BigRational frac = Fraction();
332     T cur=one;
333     T ret=zero;
334     uint i=0;
335     while (frac!=ZERO&&(term==0||i++<term)) {
336       frac*=TWO;
337       if (frac>=ONE) {
338     ret=ret+cur;
339     frac=frac-ONE;
340       }
341       cur=cur*two;
342     }
343     return ret;
344   }
345
346   bit[] FractionalBits(uint term) {
347     assert (isFloat());
348     BigRational frac = Fraction();
349     bit[] ret;
350     uint i=0;
351     while (frac!=ZERO&&(term==0||i++<term)) {
352       frac*=TWO;
353       ret.length=ret.length+1;
354       if (frac>=ONE) {
355     ret[ret.length-1]=1;
356     frac-=ONE;
357       }else{
358     ret[ret.length-1]=0;
359       }
360     }
361     return ret;
362   }
363   BigRational opMulAssign(BigRational b) {
364     n=n*b.n;
365     d=d*b.d;
366     InternalRationalize();
367     return *this;
368   }
369   BigRational opMul(BigRational b) {
370     return create(n*b.n,d*b.d).InternalRationalize();
371   }
372   BigRational opAddAssign(BigRational b) {
373     n=n*b.d+b.n*d;
374     d=d*b.d;
375     return InternalRationalize();
376   }
377   BigRational opAdd(BigRational b) {
378     return create(n*b.d+d*b.n,d*b.d).InternalRationalize();
379   }
380   BigRational opAdd(long b) {
381     return *this+create(Allocator.make(b),Allocator.one);
382   }
383   BigRational opSubAssign(BigRational b) {
384     n=n*b.d-b.n*d;
385     d=d*b.d;
386     return InternalRationalize();
387   }
388   BigRational opSub(BigRational b) {
389     return create(n*b.d-d*b.n,d*b.d).InternalRationalize();
390   }
391   /*  BigRational opSub_r(BigRational b) {
392     return create(d*b.n-n*b.d,d*b.d).InternalRationalize();
393     }*/
394   BigRational opDivAssign(BigRational b) {
395     n=n*b.d;
396     d=d*b.n;
397     InternalRationalize();
398     return *this;
399   }
400   BigRational opDiv(BigRational b) {
401     return create(n*b.d,d*b.n).InternalRationalize();
402   }
403   /*
404   BigRational opDiv_r(BigRational b) {
405     return create(d*b.n,n*b.d).InternalRationalize();
406   }
407   */
408   BigRational opModAssign(BigRational b) {
409     n = (n*b.d) % (b.n*d);
410     d = b.d*d;
411     InternalRationalize();
412     return *this;
413   }
414   BigRational opMod(BigRational b) {
415     return create((n*b.d) % (b.n*d),b.d*d).InternalRationalize();
416   }
417   /*
418   BigRational opMod_r(BigRational b) {
419     return create((b.n*d)%(n*b.d), b.d*d).InternalRationalize();
420   }
421   */
422   int opEquals (BigRational r) {
423     //char * tmp = std.string.toStringz(std.string.toString(n));
424     //char * tmp1 = std.string.toStringz(std.string.toString(d));
425     //printf ("M %s %s\t",tmp,tmp1);
426
427     return (n*r.d==d*r.n)?1:0;
428   }
429   int opCmp (BigRational rr) {   
430     T thus = n*rr.d;
431     T r  = rr.n*d;
432     if (thus<r) return -1;
433     if (thus>r) return 1;
434     return 0;
435   }
436   char[] toString(){
437     BigRational r=*this;
438     r.Rationalize();
439     return Allocator.toString(r.n)~"/"~Allocator.toString(r.d);
440   }
441   BigRational print () {
442     //printf ("%d/%d=",cast(int)n,cast(int)d);
443
444     BigRational r=*this;
445     r.Rationalize();
446     char * num=std.string.toStringz(Allocator.toString(r.n));
447     char * den=std.string.toStringz(Allocator.toString(r.d));
448     printf ("%s/%s",num,den);
449     //printf ("=%d/%d",cast(int)n,cast(int)d);
450     return *this;
451   }
452 }
453 /*
454 version (Long){
455   alias BigRational!(long,1) Rational;
456 }else {
457   alias BigRational!(Int,1) Rational;
458 }
459 alias Rational rational;
460 */
461 import etc.typecreate.intrinsiccreate;
462 alias etc.typecreate.intrinsiccreate.TypeCreate!(long) TC;
463 alias BigRational!(long, 1, TC ) rational;
Note: See TracBrowser for help on using the browser.