root/trunk/meta/math.d

Revision 160, 4.3 kB (checked in by Don Clugston, 2 years ago)

Many accumulated changes to 'meta'. The most interesting is the one in feqtest, which tests floating point numbers for equality to the number of decimal places given in a string.

Line 
1 /*  Metafunctions mimicing those in std.math
2  *
3  * Compile with -version=testmeta to run unit tests.
4  */
5 module meta.math;
6
7 /* *******************************************
8  * bool isnan!(real x)
9  *
10  *  Return true if and only if x is an IEEE not-a-number
11  */
12 template isnan(real x)
13 {
14   const bool isnan = (x!<>=0);
15 }
16
17 template isPositiveZero(real x)
18 {
19     static if (x==0 && 1.0L/x > 0)
20         const bool isPositiveZero = true;
21     else
22         const bool isPositiveZero = false;
23 }
24
25 template isNegativeZero(real x)
26 {
27     static if (x==0 && 1.0L/x < 0)
28         const bool isNegativeZero = true;
29     else
30         const bool isNegativeZero = false;
31 }
32
33 version(testmeta) {
34
35 static assert( isPositiveZero!(0.0L));
36 static assert( !isPositiveZero!(-0.0L));
37 static assert( !isPositiveZero!(real.nan));
38 static assert( isNegativeZero!(-0.0L));
39 static assert( !isNegativeZero!(0.0L));
40 }
41
42 /*   real abs!(real x) */
43 template abs(real x)
44 {
45   static if (x<0) const real abs = -x;
46   else const real abs = x;
47 }
48
49 /* long abs(long x) */
50 template abs(long x)
51 {
52   static if (x<0) const long abs = -x;
53   else const long abs = x;
54 }
55
56 /* *******************************************
57  * int binaryExponent!(real x)
58  * Returns the binary exponent of a real number x.
59  *
60  * x must not be infinity or nan.
61  */
62 template binaryExponent(real x)
63 {
64   static if (x<0)  const int binaryExponent = .binaryExponent!(-x);
65   else static if (x>0x1p128) const int binaryExponent = .binaryExponent!(x/0x1p128)+ 128;
66   else static if (x<0x1p-128)const int binaryExponent = .binaryExponent!(x*0x1p128)- 128;
67   else static if (x>0x1p32)  const int binaryExponent = .binaryExponent!(x/0x1p32)+ 32;
68   else static if (x<0x1p-32) const int binaryExponent = .binaryExponent!(x*0x1p32)- 32;
69   else static if (x>=2.0)    const int binaryExponent = .binaryExponent!(x/2) + 1;
70   else static if (x<1.0)     const int binaryExponent = .binaryExponent!(x*2) - 1;
71   else                        const int binaryExponent = 0;
72 }
73
74 /* *******************************************
75  *  int decimalExponent!(real x)
76  * Returns the decimal exponent of a real number x.
77  *
78  * x must not be infinity or nan.
79  */
80 template decimalExponent(real x)
81 {
82   static if (x<0) const int decimalExponent = .decimalExponent!(-x);
83   else static if (x<1)
84     const int decimalExponent = -1 - .decimalExponent!(1/x);
85   else static if (x>1e10000L)
86     const int decimalExponent= .decimalExponent!(x/1e10000L) + 10000;
87   else static if (x>1e1000L)
88     const int decimalExponent= .decimalExponent!(x/1e1000L) + 1000;
89   else static if (x>1e100L)
90     const int decimalExponent = .decimalExponent!(x/1e100L) + 100;
91   else static if (x>1e10)
92     const int decimalExponent = .decimalExponent!(x/1e10) + 10;
93   else static if (x>10)
94     const int decimalExponent = .decimalExponent!(x/10) + 1;
95   else const int decimalExponent = 0;
96 }
97
98 /* real binaryMantissa!(real x) */
99 template binaryMantissa(real x)
100 {
101   const real binaryMantissa = x * pow!(2, -.binaryExponent!(x));
102 }
103
104 /* *******************************************
105  * real pow!(real a, int b)
106  * Fast integer powers
107  */
108 template pow(real a, int b)
109 {
110   static if (b==0) const real pow=1.0L;
111   else static if (b<0) const real pow = 1.0L/.pow!(a, -b);
112   else static if (b==1) const real pow = a;
113   else static if (b & 1) const real pow = a * .pow!(a*a, b>>1);
114   else const real pow = .pow!(a*a, b>>1);
115 }
116
117
118 /* *******************************************
119  * creal powz!(creal a, int b)
120  * Fast integer powers of a complex number
121  */
122 template cpow(creal a, int b)
123 {
124   static if (b==0) const creal cpow=1.0L;
125   else static if (b<0) const creal cpow = 1.0L/.cpow!(a, -b);
126   else static if (b==1) const creal cpow = a;
127   else static if (b & 1) const creal cpow = a * .cpow!(a*a, b>>1);
128   else const creal cpow = .cpow!(a*a, b>>1);
129 }
130
131 version(testmeta) {
132
133  static assert( pow!(22, 13) == 282810057883082752L);
134  static assert( isnan!(real.nan));
135  static assert(!isnan!(real.infinity));
136  static assert(binaryExponent!(0x1.54437p+149)==149);
137  static assert(binaryExponent!(0x1.54437p-12)==-12);
138  static assert(binaryExponent!(0x1.54437p0)==0);
139  static assert(decimalExponent!(7e38)==38);
140  static assert(decimalExponent!(7e-38)==-38);
141  static assert(decimalExponent!(1)==0);
142  static assert(decimalExponent!(-300)==2);
143 }
Note: See TracBrowser for help on using the browser.