(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.target/
powerpc/
float128-2.c
       1  /* { dg-do run { target { powerpc*-*-linux* } } } */
       2  /* { dg-require-effective-target ppc_float128_sw } */
       3  /* { dg-require-effective-target vsx_hw } */
       4  /* { dg-options "-mvsx -O2" } */
       5  
       6  /*
       7   * Test program to make sure we are getting more precision than the 53 bits we
       8   * get with IEEE double.
       9   */
      10  
      11  #include <stdio.h>
      12  #include <math.h>
      13  #include <stdlib.h>
      14  #include <stddef.h>
      15  
      16  #ifndef TYPE
      17  #define TYPE __float128
      18  #endif
      19  
      20  #ifndef NO_INLINE
      21  #define NO_INLINE __attribute__((__noinline__))
      22  #endif
      23  
      24  static TYPE power_of_two (ssize_t) NO_INLINE;
      25  static TYPE calc1 (TYPE) NO_INLINE;
      26  static TYPE calc2 (TYPE) NO_INLINE;
      27  static TYPE calc3 (TYPE) NO_INLINE;
      28  
      29  #ifndef POWER2
      30  #define POWER2 60
      31  #endif
      32  
      33  
      34  /*
      35   * Print TYPE in hex.
      36   */
      37  
      38  
      39  #if defined(DEBUG) || defined(DEBUG2)
      40  static void print_hex (const char *prefix, TYPE, const char *suffix) NO_INLINE;
      41  
      42  #if defined (__i386__) || defined (__x86_64__) || defined (__LITTLE_ENDIAN__)
      43  #define ENDIAN_REVERSE(N, MAX)        ((MAX) - 1 - (N))
      44  
      45  #else
      46  #define ENDIAN_REVERSE(N, MAX)        (N)
      47  #endif
      48  
      49  static void
      50  print_hex (const char *prefix, TYPE value, const char *suffix)
      51  {
      52    union {
      53      TYPE f128;
      54      unsigned char uc[sizeof (TYPE)];
      55    } u;
      56  
      57    size_t i;
      58  
      59    u.f128 = value;
      60    printf ("%s0x", prefix);
      61    for (i = 0; i < sizeof (TYPE); i++)
      62      printf ("%.2x", u.uc[ ENDIAN_REVERSE (i, sizeof (TYPE)) ]);
      63  
      64    printf (", %24.2Lf%s", (long double)value, suffix);
      65  }
      66  #endif
      67  
      68  
      69  /*
      70   * Return a power of two.
      71   */
      72  
      73  static TYPE
      74  power_of_two (ssize_t num)
      75  {
      76    TYPE ret = (TYPE) 1.0;
      77    ssize_t i;
      78  
      79    if (num >= 0)
      80      {
      81        for (i = 0; i < num; i++)
      82  	ret *= (TYPE) 2.0;
      83      }
      84    else
      85      {
      86        ssize_t num2 = -num;
      87        for (i = 0; i < num2; i++)
      88  	ret /= (TYPE) 2.0;
      89      }
      90  
      91  #ifdef DEBUG
      92    printf ("power_of_two (%2ld)   = ", (long) num);
      93    print_hex ("", ret, "\n");
      94  #endif
      95  
      96    return ret;
      97  }
      98  
      99  
     100  #ifdef ADDSUB
     101  static TYPE add (TYPE a, TYPE b) NO_INLINE;
     102  static TYPE sub (TYPE a, TYPE b) NO_INLINE;
     103  
     104  static TYPE
     105  add (TYPE a, TYPE b)
     106  {
     107    TYPE c;
     108  #ifdef DEBUG
     109    print_hex ("add, arg1           = ", a, "\n");
     110    print_hex ("add, arg2           = ", b, "\n");
     111  #endif
     112    c = a + b;
     113  #ifdef DEBUG
     114    print_hex ("add, result         = ", c, "\n");
     115  #endif
     116    return c;
     117  }
     118  
     119  static TYPE
     120  sub (TYPE a, TYPE b)
     121  {
     122    TYPE c;
     123  #ifdef DEBUG
     124    print_hex ("sub, arg1           = ", a, "\n");
     125    print_hex ("sub, arg2           = ", b, "\n");
     126  #endif
     127    c = a - b;
     128  #ifdef DEBUG
     129    print_hex ("sub, result         = ", c, "\n");
     130  #endif
     131    return c;
     132  }
     133  
     134  #else
     135  #define add(x, y) ((x) + (y))
     136  #define sub(x, y) ((x) - (y))
     137  #endif
     138  
     139  /*
     140   * Various calculations.  Add in 2**POWER2, and subtract 2**(POWER2-1) twice, and we should
     141   * get the original value.
     142   */
     143  
     144  static TYPE
     145  calc1 (TYPE num)
     146  {
     147    TYPE num2 = add (power_of_two (POWER2), num);
     148    TYPE ret;
     149  
     150  #ifdef DEBUG
     151    print_hex ("calc1 (before call) = ", num2, "\n");
     152  #endif
     153  
     154    ret = calc2 (num2);
     155  
     156  #ifdef DEBUG
     157    print_hex ("calc1 (after call)  = ", ret, "\n");
     158  #endif
     159  
     160    return ret;
     161  }
     162  
     163  static TYPE
     164  calc2 (TYPE num)
     165  {
     166    TYPE num2 = sub (num, power_of_two (POWER2-1));
     167    TYPE ret;
     168  
     169  #ifdef DEBUG
     170    print_hex ("calc2 (before call) = ", num2, "\n");
     171  #endif
     172  
     173    ret = calc3 (num2);
     174  
     175  #ifdef DEBUG
     176    print_hex ("calc2 (after call)  = ", ret, "\n");
     177  #endif
     178  
     179    return ret;
     180  }
     181  
     182  static TYPE
     183  calc3 (TYPE num)
     184  {
     185    TYPE ret = sub (num, (((TYPE) 2.0) * power_of_two (POWER2-2)));
     186  
     187  #ifdef DEBUG
     188    print_hex ("calc3               = ", ret, "\n");
     189  #endif
     190  
     191    return ret;
     192  }
     193  
     194  
     195  int
     196  main (void)
     197  {
     198    TYPE input, output;
     199  
     200  #ifdef DEBUG
     201    printf ("Testing, %ld bytes\n", (long) sizeof (TYPE));
     202  #endif
     203  
     204    input = power_of_two (-1);
     205    if ((double)input != 0.5)
     206      {
     207  #if defined(DEBUG) || defined(DEBUG2)
     208        print_hex ("Input should be 0.5:  ", output, "\n");
     209        return 1;
     210  #else
     211        __builtin_abort ();
     212  #endif
     213      }
     214  
     215    output = calc1 (input);
     216    if ((double)output != 0.5)
     217      {
     218  #if defined(DEBUG) || defined(DEBUG2)
     219        print_hex ("Output should be 0.5: ", output, "\n");
     220        return 1;
     221  #else
     222        __builtin_abort ();
     223  #endif
     224      }
     225  
     226    return 0;
     227  }