source: libcfa/src/math.hfa@ 5a7789f

Last change on this file since 5a7789f was 7c012e8, checked in by Peter A. Buhr <pabuhr@…>, 2 years ago

simplify computation for ceiling, add unsigned qualifiers on one_t constants in ceiling_div

  • Property mode set to 100644
File size: 25.5 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 : Sun Jun 18 08:13:53 2023
13// Update Count : 202
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 // force divide before multiply
374 signed char floor( signed char n, signed char align ) { return (n / align) * align; }
375 unsigned char floor( unsigned char n, unsigned char align ) { return (n / align) * align; }
376 short int floor( short int n, short int align ) { return (n / align) * align; }
377 unsigned short int floor( unsigned short int n, unsigned short int align ) { return (n / align) * align; }
378 int floor( int n, int align ) { return (n / align) * align; }
379 unsigned int floor( unsigned int n, unsigned int align ) { return (n / align) * align; }
380 long int floor( long int n, long int align ) { return (n / align) * align; }
381 unsigned long int floor( unsigned long int n, unsigned long int align ) { return (n / align) * align; }
382 long long int floor( long long int n, long long int align ) { return (n / align) * align; }
383 unsigned long long int floor( unsigned long long int n, unsigned long long int align ) { return (n / align) * align; }
384
385 // forall( T | { T ?/?( T, T ); T ?*?( T, T ); } )
386 // T floor( T n, T align ) { return (n / align) * align; }
387
388 signed char ceiling_div( signed char n, char align ) { return (n + (align - 1hh)) / align; }
389 unsigned char ceiling_div( unsigned char n, unsigned char align ) { return (n + (align - 1hhu)) / align; }
390 short int ceiling_div( short int n, short int align ) { return (n + (align - 1h)) / align; }
391 unsigned short int ceiling_div( unsigned short int n, unsigned short int align ) { return (n + (align - 1hu)) / align; }
392 int ceiling_div( int n, int align ) { return (n + (align - 1n)) / align; }
393 unsigned int ceiling_div( unsigned int n, unsigned int align ) { return (n + (align - 1nu)) / align; }
394 long int ceiling_div( long int n, long int align ) { return (n + (align - 1l)) / align; }
395 unsigned long int ceiling_div( unsigned long int n, unsigned long int align ) { return (n + (align - 1lu)) / align; }
396 long long int ceiling_div( long long int n, long long int align ) { return (n + (align - 1ll)) / align; }
397 unsigned long long int ceiling_div( unsigned long long int n, unsigned long long int align ) { return (n + (align - 1llu)) / align; }
398
399 signed char ceiling( signed char n, char align ) {
400 typeof(n) trunc = floor( n, align );
401 return n < 0 || n == trunc ? trunc : trunc + align;
402 }
403 unsigned char ceiling( unsigned char n, unsigned char align ) {
404 typeof(n) trunc = floor( n, align );
405 return n == trunc ? trunc : trunc + align;
406 }
407 short int ceiling( short int n, short int align ) {
408 typeof(n) trunc = floor( n, align );
409 return n < 0 || n == trunc ? trunc : trunc + align;
410 }
411 unsigned short int ceiling( unsigned short int n, unsigned short int align ) {
412 typeof(n) trunc = floor( n, align );
413 return n == trunc ? trunc : trunc + align;
414 }
415 int ceiling( int n, int align ) {
416 typeof(n) trunc = floor( n, align );
417 return n < 0 || n == trunc ? trunc : trunc + align;
418 }
419 unsigned int ceiling( unsigned int n, unsigned int align ) {
420 typeof(n) trunc = floor( n, align );
421 return n == trunc ? trunc : trunc + align;
422 }
423 long int ceiling( long int n, long int align ) {
424 typeof(n) trunc = floor( n, align );
425 return n < 0 || n == trunc ? trunc : trunc + align;
426 }
427 unsigned long int ceiling( unsigned long int n, unsigned long int align ) {
428 typeof(n) trunc = floor( n, align );
429 return n == trunc ? trunc : trunc + align;
430 }
431 long long int ceiling( long long int n, signed long long int align ) {
432 typeof(n) trunc = floor( n, align );
433 return n < 0 || n == trunc ? trunc : trunc + align;
434 }
435 unsigned long long int ceiling( unsigned long long int n, unsigned long long int align ) {
436 typeof(n) trunc = floor( n, align );
437 return n == trunc ? trunc : trunc + align;
438 }
439
440 float floor( float x ) { return floorf( x ); }
441 // extern "C" { double floor( double ); }
442 long double floor( long double x ) { return floorl( x ); }
443
444 float ceil( float x ) { return ceilf( x ); }
445 // extern "C" { double ceil( double ); }
446 long double ceil( long double x ) { return ceill( x ); }
447
448 float trunc( float x ) { return truncf( x ); }
449 // extern "C" { double trunc( double ); }
450 long double trunc( long double x ) { return truncl( x ); }
451
452 float rint( float x ) { return rintf( x ); }
453 // extern "C" { double rint( double x ); }
454 long double rint( long double x ) { return rintl( x ); }
455 long int rint( float x ) { return lrintf( x ); }
456 long int rint( double x ) { return lrint( x ); }
457 long int rint( long double x ) { return lrintl( x ); }
458 long long int rint( float x ) { return llrintf( x ); }
459 long long int rint( double x ) { return llrint( x ); }
460 long long int rint( long double x ) { return llrintl( x ); }
461
462 long int lrint( float x ) { return lrintf( x ); }
463 // extern "C" { long int lrint( double ); }
464 long int lrint( long double x ) { return lrintl( x ); }
465 long long int llrint( float x ) { return llrintf( x ); }
466 // extern "C" { long long int llrint( double ); }
467 long long int llrint( long double x ) { return llrintl( x ); }
468
469 float nearbyint( float x ) { return nearbyintf( x ); }
470 // extern "C" { double nearbyint( double ); }
471 long double nearbyint( long double x ) { return nearbyintl( x ); }
472
473 float round( float x ) { return roundf( x ); }
474 // extern "C" { double round( double x ); }
475 long double round( long double x ) { return roundl( x ); }
476 long int round( float x ) { return lroundf( x ); }
477 long int round( double x ) { return lround( x ); }
478 long int round( long double x ) { return lroundl( x ); }
479 long long int round( float x ) { return llroundf( x ); }
480 long long int round( double x ) { return llround( x ); }
481 long long int round( long double x ) { return llroundl( x ); }
482
483 long int lround( float x ) { return lroundf( x ); }
484 // extern "C" { long int lround( double ); }
485 long int lround( long double x ) { return lroundl( x ); }
486 long long int llround( float x ) { return llroundf( x ); }
487 // extern "C" { long long int llround( double ); }
488 long long int llround( long double x ) { return llroundl( x ); }
489} // distribution
490
491//---------------------- Manipulation ----------------------
492
493static inline __attribute__((always_inline)) {
494 float copysign( float x, float y ) { return copysignf( x, y ); }
495 // extern "C" { double copysign( double, double ); }
496 long double copysign( long double x, long double y ) { return copysignl( x, y ); }
497
498 float frexp( float x, int * ip ) { return frexpf( x, ip ); }
499 // extern "C" { double frexp( double, int * ); }
500 long double frexp( long double x, int * ip ) { return frexpl( x, ip ); }
501
502 float ldexp( float x, int exp2 ) { return ldexpf( x, exp2 ); }
503 // extern "C" { double ldexp( double, int ); }
504 long double ldexp( long double x, int exp2 ) { return ldexpl( x, exp2 ); }
505
506 [ float, float ] modf( float x ) { float i; x = modff( x, &i ); return [ i, x ]; }
507 float modf( float x, float * i ) { return modff( x, i ); }
508 [ double, double ] modf( double x ) { double i; x = modf( x, &i ); return [ i, x ]; }
509 // extern "C" { double modf( double, double * ); }
510 [ long double, long double ] modf( long double x ) { long double i; x = modfl( x, &i ); return [ i, x ]; }
511 long double modf( long double x, long double * i ) { return modfl( x, i ); }
512
513 float nextafter( float x, float y ) { return nextafterf( x, y ); }
514 // extern "C" { double nextafter( double, double ); }
515 long double nextafter( long double x, long double y ) { return nextafterl( x, y ); }
516
517 float nexttoward( float x, long double y ) { return nexttowardf( x, y ); }
518 // extern "C" { double nexttoward( double, long double ); }
519 long double nexttoward( long double x, long double y ) { return nexttowardl( x, y ); }
520
521 float scalbn( float x, int exp ) { return scalbnf( x, exp ); }
522 // extern "C" { double scalbn( double, int ); }
523 long double scalbn( long double x, int exp ) { return scalbnl( x, exp ); }
524 float scalbn( float x, long int exp ) { return scalblnf( x, exp ); }
525 double scalbn( double x, long int exp ) { return scalbln( x, exp ); }
526 long double scalbn( long double x, long int exp ) { return scalblnl( x, exp ); }
527
528 float scalbln( float x, long int exp ) { return scalblnf( x, exp ); }
529 // extern "C" { double scalbln( double, long int ); }
530 long double scalbln( long double x, long int exp ) { return scalblnl( x, exp ); }
531} // distribution
532
533//---------------------------------------
534
535static inline __attribute__((always_inline)) {
536 forall( T | { void ?{}( T &, one_t ); T ?+?( T, T ); T ?-?( T, T );T ?*?( T, T ); } )
537 T lerp( T x, T y, T a ) { return x * ((T){1} - a) + y * a; }
538
539 forall( T | { void ?{}( T &, zero_t ); void ?{}( T &, one_t ); int ?<?( T, T ); } )
540 T step( T edge, T x ) { return x < edge ? (T){0} : (T){1}; }
541
542 forall( T | { void ?{}( T &, int ); T clamp( T, T, T ); T ?-?( T, T ); T ?*?( T, T ); T ?/?( T, T ); } )
543 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); }
544} // distribution
545
546// Local Variables: //
547// mode: c //
548// tab-width: 4 //
549// End: //
Note: See TracBrowser for help on using the repository browser.