[Beignet] [PATCH 1/2] add built-in function "frexp"

Zhigang Gong zhigang.gong at linux.intel.com
Mon Jul 15 20:55:51 PDT 2013



On Fri, Jul 12, 2013 at 12:49:15PM +0800, Homer Hsing wrote:
> 
> Signed-off-by: Homer Hsing <homer.xing at intel.com>
> ---
>  backend/src/ocl_stdlib.h | 27 +++++++++++++++++++++++++++
>  1 file changed, 27 insertions(+)
> 
> diff --git a/backend/src/ocl_stdlib.h b/backend/src/ocl_stdlib.h
> index fbdc703..8de29d7 100644
> --- a/backend/src/ocl_stdlib.h
> +++ b/backend/src/ocl_stdlib.h
> @@ -5174,6 +5174,33 @@ DEF(16)
>  #undef DEC8
>  #undef DEC16
>  
> +INLINE_OVERLOADABLE float frexp(float x, int *exp) {
> +  uint u = as_uint(x);
> +  *exp = ((u >> 23) & 255) - 126;
> +  u = (u & (0x807FFFFFu)) | 0x3F000000;
> +  return as_float(u);
> +}
This is not totally comply with the frexp's definiton.
There are three contion you need to take care:
1. 0.
2. Nan.
3. normal value.

The above implementation only take the third one. Here is a reference implementation
in libc for the doulbe type, for your reference:

double
frexp(value, eptr)
        double value;
        int *eptr;
{
        union {
                double v;
                struct ieee_double s;
        } u;

        if (value) {
                /*
                 * Fractions in [0.5..1.0) have an exponent of 2^-1.
                 * Leave Inf and NaN alone, however.
                 * WHAT ABOUT DENORMS?
                 */
                u.v = value;
                if (u.s.dbl_exp != DBL_EXP_INFNAN) {
                        *eptr = u.s.dbl_exp - (DBL_EXP_BIAS - 1);
                        u.s.dbl_exp = DBL_EXP_BIAS - 1;
                }
                return (u.v);
        } else {
                *eptr = 0;
                return (0.0);
        }
}.

Thus you may also want to enhance your unit test case to cover all
the three cases. And you may want to use frexp from libm directly.

> +
> +INLINE_OVERLOADABLE float2 frexp(float2 x, int2 *exp) {
> +  return (float2)(frexp(x.s0, (int *)exp), frexp(x.s1, 1 + (int *)exp));
> +}
> +
> +INLINE_OVERLOADABLE float3 frexp(float3 x, int3 *exp) {
> +  return (float3)(frexp(x.s0, (int *)exp), frexp(x.s1, 1 + (int *)exp), frexp(x.s2, 2 + (int *)exp));
> +}
> +
> +INLINE_OVERLOADABLE float4 frexp(float4 x, int4 *exp) {
> +  return (float4)(frexp(x.s0, (int *)exp), frexp(x.s1, 1 + (int *)exp), frexp(x.s2, 2 + (int *)exp), frexp(x.s3, 3 + (int *)exp));
> +}
> +
> +INLINE_OVERLOADABLE float8 frexp(float8 x, int8 *exp) {
> +  return (float8)(frexp(x.s0, (int *)exp), frexp(x.s1, 1 + (int *)exp), frexp(x.s2, 2 + (int *)exp), frexp(x.s3, 3 + (int *)exp), frexp(x.s4, 4 + (int *)exp), frexp(x.s5, 5 + (int *)exp), frexp(x.s6, 6 + (int *)exp), frexp(x.s7, 7 + (int *)exp));
> +}
> +
> +INLINE_OVERLOADABLE float16 frexp(float16 x, int16 *exp) {
> +  return (float16)(frexp(x.s0, (int *)exp), frexp(x.s1, 1 + (int *)exp), frexp(x.s2, 2 + (int *)exp), frexp(x.s3, 3 + (int *)exp), frexp(x.s4, 4 + (int *)exp), frexp(x.s5, 5 + (int *)exp), frexp(x.s6, 6 + (int *)exp), frexp(x.s7, 7 + (int *)exp), frexp(x.s8, 8 + (int *)exp), frexp(x.s9, 9 + (int *)exp), frexp(x.sa, 10 + (int *)exp), frexp(x.sb, 11 + (int *)exp), frexp(x.sc, 12 + (int *)exp), frexp(x.sd, 13 + (int *)exp), frexp(x.se, 14 + (int *)exp), frexp(x.sf, 15 + (int *)exp));
> +}
> +
>  INLINE_OVERLOADABLE float degrees(float radians) { return (180 / M_PI_F) * radians; }
>  INLINE_OVERLOADABLE float2 degrees(float2 r) { return (float2)(degrees(r.s0), degrees(r.s1)); }
>  INLINE_OVERLOADABLE float3 degrees(float3 r) { return (float3)(degrees(r.s0), degrees(r.s1), degrees(r.s2)); }
> -- 
> 1.8.1.2
> 
> _______________________________________________
> Beignet mailing list
> Beignet at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/beignet


More information about the Beignet mailing list