root/trunk/helix/basic.d

Revision 10, 11.0 kB (checked in by nail, 3 years ago)

Added unit uniform engines to random.d
Added isPowerOf2 to basic.d

Line 
1 /*
2 Redistribution and use in source and binary forms, with or without
3 modification, are permitted provided that the following conditions
4 are met:
5
6     Redistributions of source code must retain the above copyright
7     notice, this list of conditions and the following disclaimer.
8
9     Redistributions in binary form must reproduce the above
10     copyright notice, this list of conditions and the following
11     disclaimer in the documentation and/or other materials provided
12     with the distribution.
13
14     Neither name of Victor Nakoryakov nor the names of
15     its contributors may be used to endorse or promote products
16     derived from this software without specific prior written
17     permission.
18
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23 REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
30 OF THE POSSIBILITY OF SUCH DAMAGE.
31
32 Copyright (C) 2006. Victor Nakoryakov.
33 */
34 /**
35 Module provides _basic numeric routines that are oftenly used in other
36 modules or helpful in projects that use helix.
37
38 Authors:
39     Victor Nakoryakov, nail-mail[at]mail.ru
40 */
41 module helix.basic;
42
43 import std.math;
44 private import helix.config;
45
46 /**
47 Approximate equality function. In fact it's just a copy of phobos'es feqrel function,
48 but with modifcation that make it suitable for comparison of almost zero numbers.
49 However the cost of such possibility is little calculation overhead.
50
51 Params:
52     x, y        = Numbers to compare.
53     relprec     = Minimal number of mantissa bits that have to be _equal in x and y
54                   to suppose their's equality. Makes sense in comparisons of values
55                   enough far from zero.
56     absprec     = If absolute difference between x and y is less than 2^(-absprec)
57                   they supposed to be _equal. Makes sense in comparisons of values
58                   enough near to zero.
59                 
60 Returns:
61     true if x and y are supposed to be _equal, false otherwise.
62 */
63 bool equal(real x, real y, int relprec = defrelprec, int absprec = defabsprec)
64 {
65     /* Author: Don Clugston, 18 Aug 2005.
66      */
67
68     if (x == y)
69         return true; // ensure diff!=0, cope with INF.
70
71     real diff = fabs(x - y);
72    
73     ushort *pa = cast(ushort*)(&x);
74     ushort *pb = cast(ushort*)(&y);
75     ushort *pd = cast(ushort*)(&diff);
76
77     // This check is added by me. If absolute difference between
78     // x and y is less than 2^(-absprec) then count them equal.
79     if (pd[4] < 0x3FFF - absprec)
80         return true;
81
82     // The difference in abs(exponent) between x or y and abs(x-y)
83     // is equal to the number of mantissa bits of x which are
84     // equal to y. If negative, x and y have different exponents.
85     // If positive, x and y are equal to 'bitsdiff' bits.
86     // AND with 0x7FFF to form the absolute value.
87     // To avoid out-by-1 errors, we subtract 1 so it rounds down
88     // if the exponents were different. This means 'bitsdiff' is
89     // always 1 lower than we want, except that if bitsdiff==0,
90     // they could have 0 or 1 bits in common.
91     int bitsdiff = ( ((pa[4]&0x7FFF) + (pb[4]&0x7FFF)-1)>>1) - pd[4];
92
93     if (pd[4] == 0)
94     {   // Difference is denormal
95         // For denormals, we need to add the number of zeros that
96         // lie at the start of diff's mantissa.
97         // We do this by multiplying by 2^real.mant_dig
98         diff *= 0x1p+63;
99         return bitsdiff + real.mant_dig - pd[4] >= relprec;
100     }
101
102     if (bitsdiff > 0)
103         return bitsdiff + 1 >= relprec; // add the 1 we subtracted before
104
105     // Avoid out-by-1 errors when factor is almost 2.
106     return (bitsdiff == 0) ? (relprec <= 1) : false;
107 }
108
109
110 template EqualityByNorm(T)
111 {
112     bool equal(T a, T b, int relprec = defrelprec, int absprec = defabsprec)
113     {
114         return .equal((b - a).normSquare, 0.l, relprec, absprec);
115     }
116 }
117
118
119 bool less(real a, real b, int relprec = defrelprec, int absprec = defabsprec)
120 {
121     return a < b && !equal(a, b, relprec, absprec);
122 }
123
124
125 bool greater(real a, real b, int relprec = defrelprec, int absprec = defabsprec)
126 {
127     return a > b && !equal(a, b, relprec, absprec);
128 }
129
130 /**
131 Linear interpolation function.
132 Returns:
133     Value interpolated from a to b by value of t. If t is not within range [0; 1]
134     linear extrapolation is applied.
135 */
136 real lerp(real a, real b, real t)
137 {
138     return a * (1 - t) + b * t;
139 }
140
141
142 template Lerp(T)
143 {
144     T lerp(T a, T b, real t)
145     {
146         return a * (1 - t) + b * t;
147     }
148 }
149
150 /**
151 Contains min and max functions for generic types that provide
152 opCmp.
153 */
154 template MinMax(T)
155 {
156     /**
157     Returns:
158         Maximal of a and b.
159     */
160     T max(T a, T b)
161     {
162         return (a > b) ? a : b;
163     }
164
165     /**
166     Returns:
167         Minimal of a and b.
168     */
169     T min(T a, T b)
170     {
171         return (a < b) ? a : b;
172     }
173 }
174
175 /// Introduce min and max functions for basic numeric types.
176 alias MinMax!(bit).min      min;
177 alias MinMax!(bit).max      max; /// ditto
178 alias MinMax!(byte).min     min; /// ditto
179 alias MinMax!(byte).max     max; /// ditto
180 alias MinMax!(ubyte).min    min; /// ditto
181 alias MinMax!(ubyte).max    max; /// ditto
182 alias MinMax!(short).min    min; /// ditto
183 alias MinMax!(short).max    max; /// ditto
184 alias MinMax!(ushort).min   min; /// ditto
185 alias MinMax!(ushort).max   max; /// ditto
186 alias MinMax!(int).min      min; /// ditto
187 alias MinMax!(int).max      max; /// ditto
188 alias MinMax!(uint).min     min; /// ditto
189 alias MinMax!(uint).max     max; /// ditto
190 alias MinMax!(long).min     min; /// ditto
191 alias MinMax!(long).max     max; /// ditto
192 alias MinMax!(ulong).min    min; /// ditto
193 alias MinMax!(ulong).max    max; /// ditto
194 alias MinMax!(float).min    min; /// ditto
195 alias MinMax!(float).max    max; /// ditto
196 alias MinMax!(double).min   min; /// ditto
197 alias MinMax!(double).max   max; /// ditto
198 alias MinMax!(real).min     min; /// ditto
199 alias MinMax!(real).max     max; /// ditto
200
201
202 /**
203 Contains clamping functions for generic types to which min and max
204 functions can be applied.
205 */
206 template Clamp(T)
207 {
208     /**
209     Makes value of x to be not less than inf. Method can change value of x.
210     Returns:
211         Copy of x after clamping is applied.
212     */
213     T clampBelow(inout T x, T inf)
214     {
215         return x = max(x, inf);
216     }
217
218     /**
219     Makes value of x to be not greater than sup. Method can change value of x.
220     Returns:
221         Copy of x after clamping is applied.
222     */
223     T clampAbove(inout T x, T sup)
224     {
225         return x = min(x, sup);
226     }
227
228     /**
229     Makes value of x to be nor less than inf nor greater than sup.
230     Method can change value of x.
231     Returns:
232         Copy of x after clamping is applied.
233     */
234     T clamp(inout T x, T inf, T sup)
235     {
236         clampBelow(x, inf);
237         return clampAbove(x, sup);
238     }
239 }
240
241 /// Introduce clamping functions for basic numeric types.
242 alias Clamp!(bit).clampBelow    clampBelow;
243 alias Clamp!(bit).clampAbove    clampAbove; /// ditto
244 alias Clamp!(bit).clamp         clamp;      /// ditto
245 alias Clamp!(byte).clampBelow   clampBelow; /// ditto
246 alias Clamp!(byte).clampAbove   clampAbove; /// ditto
247 alias Clamp!(byte).clamp        clamp;      /// ditto
248 alias Clamp!(ubyte).clampBelow  clampBelow; /// ditto
249 alias Clamp!(ubyte).clampAbove  clampAbove; /// ditto
250 alias Clamp!(ubyte).clamp       clamp;      /// ditto
251 alias Clamp!(short).clampBelow  clampBelow; /// ditto
252 alias Clamp!(short).clampAbove  clampAbove; /// ditto
253 alias Clamp!(short).clamp       clamp;      /// ditto
254 alias Clamp!(ushort).clampBelow clampBelow; /// ditto
255 alias Clamp!(ushort).clampAbove clampAbove; /// ditto
256 alias Clamp!(ushort).clamp      clamp;      /// ditto
257 alias Clamp!(int).clampBelow    clampBelow; /// ditto
258 alias Clamp!(int).clampAbove    clampAbove; /// ditto
259 alias Clamp!(int).clamp         clamp;      /// ditto
260 alias Clamp!(uint).clampBelow   clampBelow; /// ditto
261 alias Clamp!(uint).clampAbove   clampAbove; /// ditto
262 alias Clamp!(uint).clamp        clamp;      /// ditto
263 alias Clamp!(long).clampBelow   clampBelow; /// ditto
264 alias Clamp!(long).clampAbove   clampAbove; /// ditto
265 alias Clamp!(long).clamp        clamp;      /// ditto
266 alias Clamp!(ulong).clampBelow  clampBelow; /// ditto
267 alias Clamp!(ulong).clampAbove  clampAbove; /// ditto
268 alias Clamp!(ulong).clamp       clamp;      /// ditto
269 alias Clamp!(float).clampBelow  clampBelow; /// ditto
270 alias Clamp!(float).clampAbove  clampAbove; /// ditto
271 alias Clamp!(float).clamp       clamp;      /// ditto
272 alias Clamp!(double).clampBelow clampBelow; /// ditto
273 alias Clamp!(double).clampAbove clampAbove; /// ditto
274 alias Clamp!(double).clamp      clamp;      /// ditto
275 alias Clamp!(real).clampBelow   clampBelow; /// ditto
276 alias Clamp!(real).clampAbove   clampAbove; /// ditto
277 alias Clamp!(real).clamp        clamp;      /// ditto
278
279 /** Contains swap function for generic types. */
280 template SimpleSwap(T)
281 {
282     /** Swaps values of a and b. */
283     void swap(inout T a, inout T b)
284     {
285         T temp = a;
286         a = b;
287         b = temp;
288     }
289 }
290
291 /// Introduces swap function for basic numeric types.
292 alias SimpleSwap!(bit).swap    swap;
293 alias SimpleSwap!(byte).swap   swap; /// ditto
294 alias SimpleSwap!(ubyte).swap  swap; /// ditto
295 alias SimpleSwap!(short).swap  swap; /// ditto
296 alias SimpleSwap!(ushort).swap swap; /// ditto
297 alias SimpleSwap!(int).swap    swap; /// ditto
298 alias SimpleSwap!(uint).swap   swap; /// ditto
299 alias SimpleSwap!(long).swap   swap; /// ditto
300 alias SimpleSwap!(ulong).swap  swap; /// ditto
301 alias SimpleSwap!(float).swap  swap; /// ditto
302 alias SimpleSwap!(double).swap swap; /// ditto
303 alias SimpleSwap!(real).swap   swap; /// ditto
304
305
306
307 template isSigned(int_t)
308 {
309     static if (
310         is (int_t == byte)  ||
311         is (int_t == short) ||
312         is (int_t == int)   ||
313         is (int_t == long) )
314     {
315         const bool isSigned = true;
316     }
317     else static if (
318         is (int_t == ubyte)  ||
319         is (int_t == ushort) ||
320         is (int_t == uint)   ||
321         is (int_t == ulong) )
322     {
323         const bool isSigned = false;
324     }
325     else
326         static assert(0); // template is instanciated with non-integral type
327 }
328
329 template isUnsigned(int_t)
330 {
331     const bool isUnsigned = !isSigned!(int_t);
332 }
333
334 template isPowerOf2(ulong x)
335 {
336     static if (((x - 1) & x) == 0)
337         const bool isPowerOf2 = true;
338     else
339         const bool isPowerOf2 = false;
340 }
341
342 unittest
343 {
344     static assert(isPowerOf2!(0));
345     static assert(isPowerOf2!(1));
346     static assert(isPowerOf2!(2));
347     static assert(!isPowerOf2!(3));
348 }
Note: See TracBrowser for help on using the browser.