Viewing file: float128-2.c (3.87 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
/* { dg-do run { target { powerpc*-*-linux* } } } */ /* { dg-require-effective-target ppc_float128_sw } */ /* { dg-require-effective-target vsx_hw } */ /* { dg-options "-mvsx -O2" } */
/* * Test program to make sure we are getting more precision than the 53 bits we * get with IEEE double. */
#include <stdio.h> #include <math.h> #include <stdlib.h> #include <stddef.h>
#ifndef TYPE #define TYPE __float128 #endif
#ifndef NO_INLINE #define NO_INLINE __attribute__((__noinline__)) #endif
static TYPE power_of_two (ssize_t) NO_INLINE; static TYPE calc1 (TYPE) NO_INLINE; static TYPE calc2 (TYPE) NO_INLINE; static TYPE calc3 (TYPE) NO_INLINE;
#ifndef POWER2 #define POWER2 60 #endif
/* * Print TYPE in hex. */
#if defined(DEBUG) || defined(DEBUG2) static void print_hex (const char *prefix, TYPE, const char *suffix) NO_INLINE;
#if defined (__i386__) || defined (__x86_64__) || defined (__LITTLE_ENDIAN__) #define ENDIAN_REVERSE(N, MAX) ((MAX) - 1 - (N))
#else #define ENDIAN_REVERSE(N, MAX) (N) #endif
static void print_hex (const char *prefix, TYPE value, const char *suffix) { union { TYPE f128; unsigned char uc[sizeof (TYPE)]; } u;
size_t i;
u.f128 = value; printf ("%s0x", prefix); for (i = 0; i < sizeof (TYPE); i++) printf ("%.2x", u.uc[ ENDIAN_REVERSE (i, sizeof (TYPE)) ]);
printf (", %24.2Lf%s", (long double)value, suffix); } #endif
/* * Return a power of two. */
static TYPE power_of_two (ssize_t num) { TYPE ret = (TYPE) 1.0; ssize_t i;
if (num >= 0) { for (i = 0; i < num; i++) ret *= (TYPE) 2.0; } else { ssize_t num2 = -num; for (i = 0; i < num2; i++) ret /= (TYPE) 2.0; }
#ifdef DEBUG printf ("power_of_two (%2ld) = ", (long) num); print_hex ("", ret, "\n"); #endif
return ret; }
#ifdef ADDSUB static TYPE add (TYPE a, TYPE b) NO_INLINE; static TYPE sub (TYPE a, TYPE b) NO_INLINE;
static TYPE add (TYPE a, TYPE b) { TYPE c; #ifdef DEBUG print_hex ("add, arg1 = ", a, "\n"); print_hex ("add, arg2 = ", b, "\n"); #endif c = a + b; #ifdef DEBUG print_hex ("add, result = ", c, "\n"); #endif return c; }
static TYPE sub (TYPE a, TYPE b) { TYPE c; #ifdef DEBUG print_hex ("sub, arg1 = ", a, "\n"); print_hex ("sub, arg2 = ", b, "\n"); #endif c = a - b; #ifdef DEBUG print_hex ("sub, result = ", c, "\n"); #endif return c; }
#else #define add(x, y) ((x) + (y)) #define sub(x, y) ((x) - (y)) #endif
/* * Various calculations. Add in 2**POWER2, and subtract 2**(POWER2-1) twice, and we should * get the original value. */
static TYPE calc1 (TYPE num) { TYPE num2 = add (power_of_two (POWER2), num); TYPE ret;
#ifdef DEBUG print_hex ("calc1 (before call) = ", num2, "\n"); #endif
ret = calc2 (num2);
#ifdef DEBUG print_hex ("calc1 (after call) = ", ret, "\n"); #endif
return ret; }
static TYPE calc2 (TYPE num) { TYPE num2 = sub (num, power_of_two (POWER2-1)); TYPE ret;
#ifdef DEBUG print_hex ("calc2 (before call) = ", num2, "\n"); #endif
ret = calc3 (num2);
#ifdef DEBUG print_hex ("calc2 (after call) = ", ret, "\n"); #endif
return ret; }
static TYPE calc3 (TYPE num) { TYPE ret = sub (num, (((TYPE) 2.0) * power_of_two (POWER2-2)));
#ifdef DEBUG print_hex ("calc3 = ", ret, "\n"); #endif
return ret; }
int main (void) { TYPE input, output;
#ifdef DEBUG printf ("Testing, %ld bytes\n", (long) sizeof (TYPE)); #endif
input = power_of_two (-1); if ((double)input != 0.5) { #if defined(DEBUG) || defined(DEBUG2) print_hex ("Input should be 0.5: ", output, "\n"); return 1; #else __builtin_abort (); #endif }
output = calc1 (input); if ((double)output != 0.5) { #if defined(DEBUG) || defined(DEBUG2) print_hex ("Output should be 0.5: ", output, "\n"); return 1; #else __builtin_abort (); #endif }
return 0; }
|