source: libcfa/src/math.hfa @ a983cbf

Last change on this file since a983cbf was 600478d, checked in by Peter A. Buhr <pabuhr@…>, 17 months ago

change ceiling function to work with negative values

  • Property mode set to 100644
File size: 25.8 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// math.hfa --
8//
9// Author           : Peter A. Buhr
10// Created On       : Mon Apr 18 23:37:04 2016
11// Last Modified By : Peter A. Buhr
12// Last Modified On : Sat Jun 17 18:42:45 2023
13// Update Count     : 198
14//
15
16#pragma once
17
18#include <math.h>
19#include <complex.h>
20
21//---------------------------------------
22
23#include "common.hfa"
24#include "bits/debug.hfa"
25
26//---------------------- General ----------------------
27
28static inline __attribute__((always_inline)) {
29        float ?%?( float x, float y ) { return fmodf( x, y ); }
30        float fmod( float x, float y ) { return fmodf( x, y ); }
31        double ?%?( double x, double y ) { return fmod( x, y ); }
32        // extern "C" { double fmod( double, double ); }
33        long double ?%?( long double x, long double y ) { return fmodl( x, y ); }
34        long double fmod( long double x, long double y ) { return fmodl( x, y ); }
35
36        float remainder( float x, float y ) { return remainderf( x, y ); }
37        // extern "C" { double remainder( double, double ); }
38        long double remainder( long double x, long double y ) { return remainderl( x, y ); }
39
40        float remquo( float x, float y, int * quo ) { return remquof( x, y, quo ); }
41        // extern "C" { double remquo( double x, double y, int * quo ); }
42        long double remquo( long double x, long double y, int * quo ) { return remquol( x, y, quo ); }
43        [ int, float ] remquo( float x, float y ) { int quo; x = remquof( x, y, &quo ); return [ quo, x ]; }
44        [ int, double ] remquo( double x, double y ) { int quo; x = remquo( x, y, &quo ); return [ quo, x ]; }
45        [ int, long double ] remquo( long double x, long double y ) { int quo; x = remquol( x, y, &quo ); return [ quo, x ]; }
46
47        [ float, float ] div( float x, float y ) { y = modff( x / y, &x ); return [ x, y ]; }
48        [ double, double ] div( double x, double y ) { y = modf( x / y, &x ); return [ x, y ]; }
49        [ long double, long double ] div( long double x, long double y ) { y = modfl( x / y, &x ); return [ x, y ]; }
50
51        float fma( float x, float y, float z ) { return fmaf( x, y, z ); }
52        // extern "C" { double fma( double, double, double ); }
53        long double fma( long double x, long double y, long double z ) { return fmal( x, y, z ); }
54
55        float fdim( float x, float y ) { return fdimf( x, y ); }
56        // extern "C" { double fdim( double, double ); }
57        long double fdim( long double x, long double y ) { return fdiml( x, y ); }
58
59        float nan( const char tag[] ) { return nanf( tag ); }
60        // extern "C" { double nan( const char [] ); }
61        long double nan( const char tag[] ) { return nanl( tag ); }
62} // distribution
63
64//---------------------- Exponential ----------------------
65
66static inline __attribute__((always_inline)) {
67        float exp( float x ) { return expf( x ); }
68        // extern "C" { double exp( double ); }
69        long double exp( long double x ) { return expl( x ); }
70        float _Complex exp( float _Complex x ) { return cexpf( x ); }
71        double _Complex exp( double _Complex x ) { return cexp( x ); }
72        long double _Complex exp( long double _Complex x ) { return cexpl( x ); }
73
74        float exp2( float x ) { return exp2f( x ); }
75        // extern "C" { double exp2( double ); }
76        long double exp2( long double x ) { return exp2l( x ); }
77        //float _Complex exp2( float _Complex x ) { return cexp2f( x ); }
78        //double _Complex exp2( double _Complex x ) { return cexp2( x ); }
79        //long double _Complex exp2( long double _Complex x ) { return cexp2l( x ); }
80
81        float expm1( float x ) { return expm1f( x ); }
82        // extern "C" { double expm1( double ); }
83        long double expm1( long double x ) { return expm1l( x ); }
84
85        float pow( float x, float y ) { return powf( x, y ); }
86        // extern "C" { double pow( double, double ); }
87        long double pow( long double x, long double y ) { return powl( x, y ); }
88        float _Complex pow( float _Complex x, float _Complex y ) { return cpowf( x, y ); }
89        double _Complex pow( double _Complex x, double _Complex y ) { return cpow( x, y ); }
90        long double _Complex pow( long double _Complex x, long double _Complex y ) { return cpowl( x, y ); }
91} // distribution
92
93//---------------------- Logarithm ----------------------
94
95static inline __attribute__((always_inline)) {
96        float log( float x ) { return logf( x ); }
97        // extern "C" { double log( double ); }
98        long double log( long double x ) { return logl( x ); }
99        float _Complex log( float _Complex x ) { return clogf( x ); }
100        double _Complex log( double _Complex x ) { return clog( x ); }
101        long double _Complex log( long double _Complex x ) { return clogl( x ); }
102
103        // O(1) polymorphic integer log2, using clz, which returns the number of leading 0-bits, starting at the most
104        // significant bit (single instruction on x86)
105        int log2( unsigned int n ) { return n == 0 ? -1 : sizeof(n) * __CHAR_BIT__ - 1 - __builtin_clz( n ); }
106        long int log2( unsigned long int n ) { return n == 0 ? -1 : sizeof(n) * __CHAR_BIT__ - 1 - __builtin_clzl( n ); }
107        long long int log2( unsigned long long int n ) { return n == 0 ? -1 : sizeof(n) * __CHAR_BIT__ - 1 - __builtin_clzll( n ); }
108        float log2( float x ) { return log2f( x ); }
109        // extern "C" { double log2( double ); }
110        long double log2( long double x ) { return log2l( x ); }
111        // float _Complex log2( float _Complex x ) { return clog2f( x ); }
112        // double _Complex log2( double _Complex x ) { return clog2( x ); }
113        // long double _Complex log2( long double _Complex x ) { return clog2l( x ); }
114
115        float log10( float x ) { return log10f( x ); }
116        // extern "C" { double log10( double ); }
117        long double log10( long double x ) { return log10l( x ); }
118        // float _Complex log10( float _Complex x ) { return clog10f( x ); }
119        // double _Complex log10( double _Complex x ) { return clog10( x ); }
120        // long double _Complex log10( long double _Complex x ) { return clog10l( x ); }
121
122        float log1p( float x ) { return log1pf( x ); }
123        // extern "C" { double log1p( double ); }
124        long double log1p( long double x ) { return log1pl( x ); }
125
126        int ilogb( float x ) { return ilogbf( x ); }
127        // extern "C" { int ilogb( double ); }
128        int ilogb( long double x ) { return ilogbl( x ); }
129
130        float logb( float x ) { return logbf( x ); }
131        // extern "C" { double logb( double ); }
132        long double logb( long double x ) { return logbl( x ); }
133
134        float sqrt( float x ) { return sqrtf( x ); }
135        // extern "C" { double sqrt( double ); }
136        long double sqrt( long double x ) { return sqrtl( x ); }
137        float _Complex sqrt( float _Complex x ) { return csqrtf( x ); }
138        double _Complex sqrt( double _Complex x ) { return csqrt( x ); }
139        long double _Complex sqrt( long double _Complex x ) { return csqrtl( x ); }
140
141        float cbrt( float x ) { return cbrtf( x ); }
142        // extern "C" { double cbrt( double ); }
143        long double cbrt( long double x ) { return cbrtl( x ); }
144
145        float hypot( float x, float y ) { return hypotf( x, y ); }
146        // extern "C" { double hypot( double, double ); }
147        long double hypot( long double x, long double y ) { return hypotl( x, y ); }
148} // distribution
149
150static inline unsigned long long log2_u32_32( unsigned long long val ) {
151        enum {
152                TABLE_BITS = 6,
153                TABLE_SIZE = (1 << TABLE_BITS) + 2,
154        };
155        // for(i; TABLE_SIZE) {
156        //      table[i] = (unsigned long long)(log2(1.0 + i / pow(2, TABLE_BITS)) * pow(2, 32)));
157        // }
158        static const unsigned long long table[] = {
159                0x0000000000, 0x0005b9e5a1, 0x000b5d69ba, 0x0010eb389f,
160                0x001663f6fa, 0x001bc84240, 0x002118b119, 0x002655d3c4,
161                0x002b803473, 0x00309857a0, 0x00359ebc5b, 0x003a93dc98,
162                0x003f782d72, 0x00444c1f6b, 0x0049101eac, 0x004dc4933a,
163                0x005269e12f, 0x00570068e7, 0x005b888736, 0x006002958c,
164                0x00646eea24, 0x0068cdd829, 0x006d1fafdc, 0x007164beb4,
165                0x00759d4f80, 0x0079c9aa87, 0x007dea15a3, 0x0081fed45c,
166                0x0086082806, 0x008a064fd5, 0x008df988f4, 0x0091e20ea1,
167                0x0095c01a39, 0x009993e355, 0x009d5d9fd5, 0x00a11d83f4,
168                0x00a4d3c25e, 0x00a8808c38, 0x00ac241134, 0x00afbe7fa0,
169                0x00b3500472, 0x00b6d8cb53, 0x00ba58feb2, 0x00bdd0c7c9,
170                0x00c1404ead, 0x00c4a7ba58, 0x00c80730b0, 0x00cb5ed695,
171                0x00ceaecfea, 0x00d1f73f9c, 0x00d53847ac, 0x00d8720935,
172                0x00dba4a47a, 0x00ded038e6, 0x00e1f4e517, 0x00e512c6e5,
173                0x00e829fb69, 0x00eb3a9f01, 0x00ee44cd59, 0x00f148a170,
174                0x00f446359b, 0x00f73da38d, 0x00fa2f045e, 0x00fd1a708b,
175                0x0100000000, 0x0102dfca16,
176        };
177        _Static_assert((sizeof(table) / sizeof(table[0])) == TABLE_SIZE, "TABLE_SIZE should be accurate");
178        // starting from val = (2 ** i)*(1 + f) where 0 <= f < 1
179        // log identities mean log2(val) = log2((2 ** i)*(1 + f)) = log2(2**i) + log2(1+f)
180        //
181        // getting i is easy to do using builtin_clz (count leading zero)
182        //
183        // we want to calculate log2(1+f) independently to have a many bits of precision as possible.
184        //     val = (2 ** i)*(1 + f) = 2 ** i   +   f * 2 ** i
185        // isolating f we get
186        //     val - 2 ** i = f * 2 ** i
187        //     (val - 2 ** i) / 2 ** i = f
188        //
189        // we want to interpolate from the table to get the values
190        // and compromise by doing quadratic interpolation (rather than higher degree interpolation)
191        //
192        // for the interpolation we want to shift everything the fist sample point
193        // so our parabola becomes x = 0
194        // this further simplifies the equations
195        //
196        // the consequence is that we need f in 2 forms:
197        //  - finding the index of x0
198        //  - finding the distance between f and x0
199        //
200        // since sample points are equidistant we can significantly simplify the equations
201
202        // get i
203        const unsigned long long bits = sizeof(val) * __CHAR_BIT__;
204        const unsigned long long lz = __builtin_clzl(val);
205        const unsigned long long i = bits - 1 - lz;
206
207        // get the fractinal part as a u32.32
208        const unsigned long long frac = (val << (lz + 1)) >> 32;
209
210        // get high order bits for the index into the table
211        const unsigned long long idx0 = frac >> (32 - TABLE_BITS);
212
213        // get the x offset, i.e., the difference between the first sample point and the actual fractional part
214        const long long udx = frac - (idx0 << (32 - TABLE_BITS));
215        /* paranoid */ verify((idx0 + 2) < TABLE_SIZE);
216
217        const long long y0 = table[idx0 + 0];
218        const long long y1 = table[idx0 + 1];
219        const long long y2 = table[idx0 + 2];
220
221        // from there we can quadraticly interpolate to get the data, using the lagrange polynomial
222        // normally it would look like:
223        //     double r0 = y0 * ((x - x1) / (x0 - x1)) * ((x - x2) / (x0 - x2));
224        //     double r1 = y1 * ((x - x0) / (x1 - x0)) * ((x - x2) / (x1 - x2));
225        //     double r2 = y2 * ((x - x0) / (x2 - x0)) * ((x - x1) / (x2 - x1));
226        // but since the spacing between sample points is fixed, we can simplify it and extract common expressions
227        const long long f1 = (y1 - y0);
228        const long long f2 = (y2 - y0);
229        const long long a = f2 - (f1 * 2l);
230        const long long b = (f1 * 2l) - a;
231
232        // Now we can compute it in the form (ax + b)x + c (which avoid repeating steps)
233        long long sum = ((a*udx) >> (32 - TABLE_BITS))  + b;
234        sum = (sum*udx) >> (32 - TABLE_BITS + 1);
235        sum = y0 + sum;
236
237        return (i << 32) + (sum);
238} // log2_u32_32
239
240//---------------------- Trigonometric ----------------------
241
242static inline __attribute__((always_inline)) {
243        float sin( float x ) { return sinf( x ); }
244        // extern "C" { double sin( double ); }
245        long double sin( long double x ) { return sinl( x ); }
246        float _Complex sin( float _Complex x ) { return csinf( x ); }
247        double _Complex sin( double _Complex x ) { return csin( x ); }
248        long double _Complex sin( long double _Complex x ) { return csinl( x ); }
249
250        float cos( float x ) { return cosf( x ); }
251        // extern "C" { double cos( double ); }
252        long double cos( long double x ) { return cosl( x ); }
253        float _Complex cos( float _Complex x ) { return ccosf( x ); }
254        double _Complex cos( double _Complex x ) { return ccos( x ); }
255        long double _Complex cos( long double _Complex x ) { return ccosl( x ); }
256
257        float tan( float x ) { return tanf( x ); }
258        // extern "C" { double tan( double ); }
259        long double tan( long double x ) { return tanl( x ); }
260        float _Complex tan( float _Complex x ) { return ctanf( x ); }
261        double _Complex tan( double _Complex x ) { return ctan( x ); }
262        long double _Complex tan( long double _Complex x ) { return ctanl( x ); }
263
264        float asin( float x ) { return asinf( x ); }
265        // extern "C" { double asin( double ); }
266        long double asin( long double x ) { return asinl( x ); }
267        float _Complex asin( float _Complex x ) { return casinf( x ); }
268        double _Complex asin( double _Complex x ) { return casin( x ); }
269        long double _Complex asin( long double _Complex x ) { return casinl( x ); }
270
271        float acos( float x ) { return acosf( x ); }
272        // extern "C" { double acos( double ); }
273        long double acos( long double x ) { return acosl( x ); }
274        float _Complex acos( float _Complex x ) { return cacosf( x ); }
275        double _Complex acos( double _Complex x ) { return cacos( x ); }
276        long double _Complex acos( long double _Complex x ) { return cacosl( x ); }
277
278        float atan( float x ) { return atanf( x ); }
279        // extern "C" { double atan( double ); }
280        long double atan( long double x ) { return atanl( x ); }
281        float _Complex atan( float _Complex x ) { return catanf( x ); }
282        double _Complex atan( double _Complex x ) { return catan( x ); }
283        long double _Complex atan( long double _Complex x ) { return catanl( x ); }
284
285        float atan2( float x, float y ) { return atan2f( x, y ); }
286        // extern "C" { double atan2( double, double ); }
287        long double atan2( long double x, long double y ) { return atan2l( x, y ); }
288
289        // alternative name for atan2
290        float atan( float x, float y ) { return atan2f( x, y ); }
291        double atan( double x, double y ) { return atan2( x, y ); }
292        long double atan( long double x, long double y ) { return atan2l( x, y ); }
293} // distribution
294
295//---------------------- Hyperbolic ----------------------
296
297static inline __attribute__((always_inline)) {
298        float sinh( float x ) { return sinhf( x ); }
299        // extern "C" { double sinh( double ); }
300        long double sinh( long double x ) { return sinhl( x ); }
301        float _Complex sinh( float _Complex x ) { return csinhf( x ); }
302        double _Complex sinh( double _Complex x ) { return csinh( x ); }
303        long double _Complex sinh( long double _Complex x ) { return csinhl( x ); }
304
305        float cosh( float x ) { return coshf( x ); }
306        // extern "C" { double cosh( double ); }
307        long double cosh( long double x ) { return coshl( x ); }
308        float _Complex cosh( float _Complex x ) { return ccoshf( x ); }
309        double _Complex cosh( double _Complex x ) { return ccosh( x ); }
310        long double _Complex cosh( long double _Complex x ) { return ccoshl( x ); }
311
312        float tanh( float x ) { return tanhf( x ); }
313        // extern "C" { double tanh( double ); }
314        long double tanh( long double x ) { return tanhl( x ); }
315        float _Complex tanh( float _Complex x ) { return ctanhf( x ); }
316        double _Complex tanh( double _Complex x ) { return ctanh( x ); }
317        long double _Complex tanh( long double _Complex x ) { return ctanhl( x ); }
318
319        float asinh( float x ) { return asinhf( x ); }
320        // extern "C" { double asinh( double ); }
321        long double asinh( long double x ) { return asinhl( x ); }
322        float _Complex asinh( float _Complex x ) { return casinhf( x ); }
323        double _Complex asinh( double _Complex x ) { return casinh( x ); }
324        long double _Complex asinh( long double _Complex x ) { return casinhl( x ); }
325
326        float acosh( float x ) { return acoshf( x ); }
327        // extern "C" { double acosh( double ); }
328        long double acosh( long double x ) { return acoshl( x ); }
329        float _Complex acosh( float _Complex x ) { return cacoshf( x ); }
330        double _Complex acosh( double _Complex x ) { return cacosh( x ); }
331        long double _Complex acosh( long double _Complex x ) { return cacoshl( x ); }
332
333        float atanh( float x ) { return atanhf( x ); }
334        // extern "C" { double atanh( double ); }
335        long double atanh( long double x ) { return atanhl( x ); }
336        float _Complex atanh( float _Complex x ) { return catanhf( x ); }
337        double _Complex atanh( double _Complex x ) { return catanh( x ); }
338        long double _Complex atanh( long double _Complex x ) { return catanhl( x ); }
339} // distribution
340
341//---------------------- Error / Gamma ----------------------
342
343static inline __attribute__((always_inline)) {
344        float erf( float x ) { return erff( x ); }
345        // extern "C" { double erf( double ); }
346        long double erf( long double x ) { return erfl( x ); }
347        // float _Complex erf( float _Complex );
348        // double _Complex erf( double _Complex );
349        // long double _Complex erf( long double _Complex );
350
351        float erfc( float x ) { return erfcf( x ); }
352        // extern "C" { double erfc( double ); }
353        long double erfc( long double x ) { return erfcl( x ); }
354        // float _Complex erfc( float _Complex );
355        // double _Complex erfc( double _Complex );
356        // long double _Complex erfc( long double _Complex );
357
358        float lgamma( float x ) { return lgammaf( x ); }
359        // extern "C" { double lgamma( double ); }
360        long double lgamma( long double x ) { return lgammal( x ); }
361        float lgamma( float x, int * sign ) { return lgammaf_r( x, sign ); }
362        double lgamma( double x, int * sign ) { return lgamma_r( x, sign ); }
363        long double lgamma( long double x, int * sign ) { return lgammal_r( x, sign ); }
364
365        float tgamma( float x ) { return tgammaf( x ); }
366        // extern "C" { double tgamma( double ); }
367        long double tgamma( long double x ) { return tgammal( x ); }
368} // distribution
369
370//---------------------- Nearest Integer ----------------------
371
372inline __attribute__((always_inline)) static {
373        signed char floor( signed char n, signed char align ) { return n / align * align; }
374        unsigned char floor( unsigned char n, unsigned char align ) { return n / align * align; }
375        short int floor( short int n, short int align ) { return n / align * align; }
376        unsigned short int floor( unsigned short int n, unsigned short int align ) { return n / align * align; }
377        int floor( int n, int align ) { return n / align * align; }
378        unsigned int floor( unsigned int n, unsigned int align ) { return n / align * align; }
379        long int floor( long int n, long int align ) { return n / align * align; }
380        unsigned long int floor( unsigned long int n, unsigned long int align ) { return n / align * align; }
381        long long int floor( long long int n, long long int align ) { return n / align * align; }
382        unsigned long long int floor( unsigned long long int n, unsigned long long int align ) { return n / align * align; }
383
384        // forall( T | { T ?/?( T, T ); T ?*?( T, T ); } )
385        // T floor( T n, T align ) { return n / align * align; }
386
387        signed char ceiling_div( signed char n, char align ) { return (n + (align - 1)) / align; }
388        unsigned char ceiling_div( unsigned char n, unsigned char align ) { return (n + (align - 1)) / align; }
389        short int ceiling_div( short int n, short int align ) { return (n + (align - 1)) / align; }
390        unsigned short int ceiling_div( unsigned short int n, unsigned short int align ) { return (n + (align - 1)) / align; }
391        int ceiling_div( int n, int align ) { return (n + (align - 1)) / align; }
392        unsigned int ceiling_div( unsigned int n, unsigned int align ) { return (n + (align - 1)) / align; }
393        long int ceiling_div( long int n, long int align ) { return (n + (align - 1)) / align; }
394        unsigned long int ceiling_div( unsigned long int n, unsigned long int align ) { return (n + (align - 1)) / align; }
395        long long int ceiling_div( long long int n, long long int align ) { return (n + (align - 1)) / align; }
396        unsigned long long int ceiling_div( unsigned long long int n, unsigned long long int align ) { return (n + (align - 1)) / align; }
397
398        signed char ceiling( signed char n, char align ) {
399                align = align < 0 ? -align : align;                             // align must be signed
400                typeof(n) trunc = floor( n, align );
401                return n >= 0 ? trunc + (trunc != n ? align : 0) : trunc;
402        }
403        unsigned char ceiling( unsigned char n, unsigned char align ) {
404                typeof(n) trunc = floor( n, align );
405                return n >= 0 ? trunc + (trunc != n ? align : 0) : trunc;
406        }
407        short int ceiling( short int n, short int align ) {
408                align = align < 0 ? -align : align;                             // align must be signed
409                typeof(n) trunc = floor( n, align );
410                return n >= 0 ? trunc + (trunc != n ? align : 0) : trunc;
411        }
412        unsigned short int ceiling( unsigned short int n, unsigned short int align ) {
413                typeof(n) trunc = floor( n, align );
414                return n >= 0 ? trunc + (trunc != n ? align : 0) : trunc;
415        }
416        int ceiling( int n, int align ) {
417                align = align < 0 ? -align : align;                             // align must be signed
418                typeof(n) trunc = floor( n, align );
419                return n >= 0 ? trunc + (trunc != n ? align : 0) : trunc;
420        }
421        unsigned int ceiling( unsigned int n, unsigned int align ) {
422                typeof(n) trunc = floor( n, align );
423                return n >= 0 ? trunc + (trunc != n ? align : 0) : trunc;
424        }
425        long int ceiling( long int n, long int align ) {
426                align = align < 0 ? -align : align;                             // align must be signed
427                typeof(n) trunc = floor( n, align );
428                return n >= 0 ? trunc + (trunc != n ? align : 0) : trunc;
429        }
430        unsigned long int ceiling( unsigned long int n, unsigned long int align ) {
431                typeof(n) trunc = floor( n, align );
432                return n >= 0 ? trunc + (trunc != n ? align : 0) : trunc;
433        }
434        long long int ceiling( long long int n, signed long long int align ) {
435                align = align < 0 ? -align : align;                             // align must be signed
436                typeof(n) trunc = floor( n, align );
437                return n >= 0 ? trunc + (trunc != n ? align : 0) : trunc;
438        }
439        unsigned long long int ceiling( unsigned long long int n, unsigned long long int align ) {
440                typeof(n) trunc = floor( n, align );
441                return n >= 0 ? trunc + (trunc != n ? align : 0) : trunc;
442        }
443
444        float floor( float x ) { return floorf( x ); }
445        // extern "C" { double floor( double ); }
446        long double floor( long double x ) { return floorl( x ); }
447
448        float ceil( float x ) { return ceilf( x ); }
449        // extern "C" { double ceil( double ); }
450        long double ceil( long double x ) { return ceill( x ); }
451
452        float trunc( float x ) { return truncf( x ); }
453        // extern "C" { double trunc( double ); }
454        long double trunc( long double x ) { return truncl( x ); }
455
456        float rint( float x ) { return rintf( x ); }
457        // extern "C" { double rint( double x ); }
458        long double rint( long double x ) { return rintl( x ); }
459        long int rint( float x ) { return lrintf( x ); }
460        long int rint( double x ) { return lrint( x ); }
461        long int rint( long double x ) { return lrintl( x ); }
462        long long int rint( float x ) { return llrintf( x ); }
463        long long int rint( double x ) { return llrint( x ); }
464        long long int rint( long double x ) { return llrintl( x ); }
465
466        long int lrint( float x ) { return lrintf( x ); }
467        // extern "C" { long int lrint( double ); }
468        long int lrint( long double x ) { return lrintl( x ); }
469        long long int llrint( float x ) { return llrintf( x ); }
470        // extern "C" { long long int llrint( double ); }
471        long long int llrint( long double x ) { return llrintl( x ); }
472
473        float nearbyint( float x ) { return nearbyintf( x ); }
474        // extern "C" { double nearbyint( double ); }
475        long double nearbyint( long double x ) { return nearbyintl( x ); }
476
477        float round( float x ) { return roundf( x ); }
478        // extern "C" { double round( double x ); }
479        long double round( long double x ) { return roundl( x ); }
480        long int round( float x ) { return lroundf( x ); }
481        long int round( double x ) { return lround( x ); }
482        long int round( long double x ) { return lroundl( x ); }
483        long long int round( float x ) { return llroundf( x ); }
484        long long int round( double x ) { return llround( x ); }
485        long long int round( long double x ) { return llroundl( x ); }
486
487        long int lround( float x ) { return lroundf( x ); }
488        // extern "C" { long int lround( double ); }
489        long int lround( long double x ) { return lroundl( x ); }
490        long long int llround( float x ) { return llroundf( x ); }
491        // extern "C" { long long int llround( double ); }
492        long long int llround( long double x ) { return llroundl( x ); }
493} // distribution
494
495//---------------------- Manipulation ----------------------
496
497static inline __attribute__((always_inline)) {
498        float copysign( float x, float y ) { return copysignf( x, y ); }
499        // extern "C" { double copysign( double, double ); }
500        long double copysign( long double x, long double y ) { return copysignl( x, y ); }
501
502        float frexp( float x, int * ip ) { return frexpf( x, ip ); }
503        // extern "C" { double frexp( double, int * ); }
504        long double frexp( long double x, int * ip ) { return frexpl( x, ip ); }
505
506        float ldexp( float x, int exp2 ) { return ldexpf( x, exp2 ); }
507        // extern "C" { double ldexp( double, int ); }
508        long double ldexp( long double x, int exp2 ) { return ldexpl( x, exp2 ); }
509
510        [ float, float ] modf( float x ) { float i; x = modff( x, &i ); return [ i, x ]; }
511        float modf( float x, float * i ) { return modff( x, i ); }
512        [ double, double ] modf( double x ) { double i; x = modf( x, &i ); return [ i, x ]; }
513        // extern "C" { double modf( double, double * ); }
514        [ long double, long double ] modf( long double x ) { long double i; x = modfl( x, &i ); return [ i, x ]; }
515        long double modf( long double x, long double * i ) { return modfl( x, i ); }
516
517        float nextafter( float x, float y ) { return nextafterf( x, y ); }
518        // extern "C" { double nextafter( double, double ); }
519        long double nextafter( long double x, long double y ) { return nextafterl( x, y ); }
520
521        float nexttoward( float x, long double y ) { return nexttowardf( x, y ); }
522        // extern "C" { double nexttoward( double, long double ); }
523        long double nexttoward( long double x, long double y ) { return nexttowardl( x, y ); }
524
525        float scalbn( float x, int exp ) { return scalbnf( x, exp ); }
526        // extern "C" { double scalbn( double, int ); }
527        long double scalbn( long double x, int exp ) { return scalbnl( x, exp ); }
528        float scalbn( float x, long int exp ) { return scalblnf( x, exp ); }
529        double scalbn( double x, long int exp ) { return scalbln( x, exp ); }
530        long double scalbn( long double x, long int exp ) { return scalblnl( x, exp ); }
531
532        float scalbln( float x, long int exp ) { return scalblnf( x, exp ); }
533        // extern "C" { double scalbln( double, long int ); }
534        long double scalbln( long double x, long int exp ) { return scalblnl( x, exp ); }
535} // distribution
536
537//---------------------------------------
538
539static inline __attribute__((always_inline)) {
540        forall( T | { void ?{}( T &, one_t ); T ?+?( T, T ); T ?-?( T, T );T ?*?( T, T ); } )
541        T lerp( T x, T y, T a ) { return x * ((T){1} - a) + y * a; }
542
543        forall( T | { void ?{}( T &, zero_t ); void ?{}( T &, one_t ); int ?<?( T, T ); } )
544        T step( T edge, T x ) { return x < edge ? (T){0} : (T){1}; }
545
546        forall( T | { void ?{}( T &, int ); T clamp( T, T, T ); T ?-?( T, T ); T ?*?( T, T ); T ?/?( T, T ); } )
547        T smoothstep( T edge0, T edge1, T x ) { T t = clamp( (x - edge0) / (edge1 - edge0), (T){0}, (T){1} ); return t * t * ((T){3} - (T){2} * t); }
548} // distribution
549
550// Local Variables: //
551// mode: c //
552// tab-width: 4 //
553// End: //
Note: See TracBrowser for help on using the repository browser.