/* { dg-options "-std=gnu99 -D_GNU_SOURCE -pthread" } */ /* { dg-do run { target i?86-*-linux* i?86-*-gnu* x86_64-*-linux* } } */ /* N1150 5.2: Conversions among decimal floating types and between decimal floating types and generic floating types. C99 6.3.1.5(3) New. Perform conversions between DFP types in which the assigned value cannot be represented exactly in the result and must be rounded correctly according to the current rounding mode. Normally this would not be part of compiler testing, but conversions are currently handled in libgcc via decNumber. */ #include #include #include #include #include #include "dfp-round.h" extern void abort (void); static __thread int failcnt = 0; /* Support compiling the test to report individual failures; default is to abort as soon as a check fails. */ #ifdef DBG #include #define FAILURE { printf ("failed at line %d\n", __LINE__); failcnt++; } #else #define FAILURE abort (); #endif pthread_mutex_t mut1 = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t mut2 = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t mut3 = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t mut4 = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t mut5 = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t cond1 = PTHREAD_COND_INITIALIZER; pthread_cond_t cond2 = PTHREAD_COND_INITIALIZER; pthread_cond_t cond3 = PTHREAD_COND_INITIALIZER; pthread_cond_t cond4 = PTHREAD_COND_INITIALIZER; pthread_cond_t cond5 = PTHREAD_COND_INITIALIZER; pthread_barrier_t bar1; pthread_barrier_t bar2; pthread_barrier_t bar3; pthread_barrier_t bar4; pthread_barrier_t bar5; __thread _Decimal32 d32; __thread _Decimal64 d64; __thread _Decimal128 d128; _Decimal32 d64_to_d32 (_Decimal64 d) { return d; } _Decimal64 d128_to_d64 (_Decimal128 d) { return d; } _Decimal32 d128_to_d32 (_Decimal128 d) { return d; } int do_d64_to_d32 (_Decimal64 orig, _Decimal32 exp) { d64 = orig; d32 = d64_to_d32 (d64); return (d32 == exp); } int do_d128_to_d32 (_Decimal128 orig, _Decimal32 exp) { d128 = orig; d32 = d128_to_d32 (d128); return (d32 == exp); } int do_d128_to_d64 (_Decimal128 orig, _Decimal64 exp) { d128 = orig; d64 = d128_to_d64 (d128); return (d64 == exp); } void * downward (void *arg) { int err; DFP_SETROUND (FE_DEC_DOWNWARD); err = pthread_mutex_lock (&mut1); if (err != 0) error (EXIT_FAILURE, err, "downward: failed to lock"); err = pthread_barrier_wait (&bar1); if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD) { puts ("downward: barrier_wait failed"); exit (1); } err = pthread_cond_wait (&cond1, &mut1); if (err != 0) error (EXIT_FAILURE, err, "downward: failed to wait"); err = pthread_mutex_unlock (&mut1); if (err != 0) error (EXIT_FAILURE, err, "downward: failed to unlock"); if (!do_d64_to_d32 (1.1111125dd, 1.111112df)) FAILURE if (!do_d64_to_d32 (1.1111135dd, 1.111113df)) FAILURE if (!do_d64_to_d32 (-1.1111125dd, -1.111113df)) FAILURE if (!do_d64_to_d32 (-1.1111135dd, -1.111114df)) FAILURE if (!do_d128_to_d32 (1.1111125dl, 1.111112df)) FAILURE if (!do_d128_to_d32 (1.1111135dl, 1.111113df)) FAILURE if (!do_d128_to_d32 (-1.1111125dl, -1.111113df)) FAILURE if (!do_d128_to_d32 (-1.1111135dl, -1.111114df)) FAILURE if (!do_d128_to_d64 (1.1111111111111125dl, 1.111111111111112dd)) FAILURE if (!do_d128_to_d64 (1.1111111111111135dl, 1.111111111111113dd)) FAILURE if (!do_d128_to_d64 (-1.1111111111111125dl, -1.111111111111113dd)) FAILURE if (!do_d128_to_d64 (-1.1111111111111135dl, -1.111111111111114dd)) FAILURE #ifdef DBG if (failcnt) printf ("downward: %d fails\n", failcnt); #endif return (void *) (ptrdiff_t) failcnt; } void * tonearest (void *arg) { int err; DFP_SETROUND (FE_DEC_TONEAREST); err = pthread_mutex_lock (&mut2); if (err != 0) error (EXIT_FAILURE, err, "tonearest: failed to lock"); err = pthread_barrier_wait (&bar2); if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD) { puts ("tonearest: barrier_wait failed"); exit (1); } err = pthread_cond_wait (&cond2, &mut2); if (err != 0) error (EXIT_FAILURE, err, "tonearest: failed to wait"); err = pthread_mutex_unlock (&mut2); if (err != 0) error (EXIT_FAILURE, err, "tonearest: failed to unlock"); if (!do_d64_to_d32 (1.1111125dd, 1.111112df)) FAILURE if (!do_d64_to_d32 (1.1111135dd, 1.111114df)) FAILURE if (!do_d64_to_d32 (-1.1111125dd, -1.111112df)) FAILURE if (!do_d64_to_d32 (-1.1111135dd, -1.111114df)) FAILURE if (!do_d128_to_d32 (1.1111125dl, 1.111112df)) FAILURE if (!do_d128_to_d32 (1.1111135dl, 1.111114df)) FAILURE if (!do_d128_to_d32 (-1.1111125dl, -1.111112df)) FAILURE if (!do_d128_to_d32 (-1.1111135dl, -1.111114df)) FAILURE if (!do_d128_to_d64 (1.1111111111111125dl, 1.111111111111112dd)) FAILURE if (!do_d128_to_d64 (1.1111111111111135dl, 1.111111111111114dd)) FAILURE if (!do_d128_to_d64 (-1.1111111111111125dl, -1.111111111111112dd)) FAILURE if (!do_d128_to_d64 (-1.1111111111111135dl, -1.111111111111114dd)) FAILURE #ifdef DBG if (failcnt) printf ("tonearest: %d fails\n", failcnt); #endif return (void *) (ptrdiff_t) failcnt; } void * toneareastfromzero (void *arg) { int err; DFP_SETROUND (FE_DEC_TONEARESTFROMZERO); err = pthread_mutex_lock (&mut3); if (err != 0) error (EXIT_FAILURE, err, "toneareastfromzero: failed to lock"); err = pthread_barrier_wait (&bar3); if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD) { puts ("toneareastfromzero: barrier_wait failed"); exit (1); } err = pthread_cond_wait (&cond3, &mut3); if (err != 0) error (EXIT_FAILURE, err, "toneareastfromzero: failed to wait"); err = pthread_mutex_unlock (&mut3); if (err != 0) error (EXIT_FAILURE, err, "toneareastfromzero: failed to unlock"); if (!do_d64_to_d32 (1.1111125dd, 1.111113df)) FAILURE if (!do_d64_to_d32 (1.1111135dd, 1.111114df)) FAILURE if (!do_d64_to_d32 (-1.1111125dd, -1.111113df)) FAILURE if (!do_d64_to_d32 (-1.1111135dd, -1.111114df)) FAILURE if (!do_d128_to_d32 (1.1111125dl, 1.111113df)) FAILURE if (!do_d128_to_d32 (1.1111135dl, 1.111114df)) FAILURE if (!do_d128_to_d32 (-1.1111125dl, -1.111113df)) FAILURE if (!do_d128_to_d32 (-1.1111135dl, -1.111114df)) FAILURE if (!do_d128_to_d64 (1.1111111111111125dl, 1.111111111111113dd)) FAILURE if (!do_d128_to_d64 (1.1111111111111135dl, 1.111111111111114dd)) FAILURE if (!do_d128_to_d64 (-1.1111111111111125dl, -1.111111111111113dd)) FAILURE if (!do_d128_to_d64 (-1.1111111111111135dl, -1.111111111111114dd)) FAILURE #ifdef DBG if (failcnt) printf ("toneareastfromzero: %d fails\n", failcnt); #endif return (void *) (ptrdiff_t) failcnt; } void * towardzero (void *arg) { int err; DFP_SETROUND (FE_DEC_TOWARDZERO); err = pthread_mutex_lock (&mut4); if (err != 0) error (EXIT_FAILURE, err, "towardzero: failed to lock"); err = pthread_barrier_wait (&bar4); if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD) { puts ("towardzero: barrier_wait failed"); exit (1); } err = pthread_cond_wait (&cond4, &mut4); if (err != 0) error (EXIT_FAILURE, err, "towardzero: failed to wait"); err = pthread_mutex_unlock (&mut4); if (err != 0) error (EXIT_FAILURE, err, "towardzero: failed to unlock"); if (!do_d64_to_d32 (1.1111125dd, 1.111112df)) FAILURE if (!do_d64_to_d32 (1.1111135dd, 1.111113df)) FAILURE if (!do_d64_to_d32 (-1.1111125dd, -1.111112df)) FAILURE if (!do_d64_to_d32 (-1.1111135dd, -1.111113df)) FAILURE if (!do_d128_to_d32 (1.1111125dl, 1.111112df)) FAILURE if (!do_d128_to_d32 (1.1111135dl, 1.111113df)) FAILURE if (!do_d128_to_d32 (-1.1111125dl, -1.111112df)) FAILURE if (!do_d128_to_d32 (-1.1111135dl, -1.111113df)) FAILURE if (!do_d128_to_d64 (1.1111111111111125dl, 1.111111111111112dd)) FAILURE if (!do_d128_to_d64 (1.1111111111111135dl, 1.111111111111113dd)) FAILURE if (!do_d128_to_d64 (-1.1111111111111125dl, -1.111111111111112dd)) FAILURE if (!do_d128_to_d64 (-1.1111111111111135dl, -1.111111111111113dd)) FAILURE #ifdef DBG if (failcnt) printf ("towardzero: %d fails\n", failcnt); #endif return (void *) (ptrdiff_t) failcnt; } void * upward (void *arg) { int err; DFP_SETROUND (FE_DEC_UPWARD); err = pthread_mutex_lock (&mut5); if (err != 0) error (EXIT_FAILURE, err, "upward: failed to lock"); err = pthread_barrier_wait (&bar5); if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD) { puts ("upward: barrier_wait failed"); exit (1); } err = pthread_cond_wait (&cond5, &mut5); if (err != 0) error (EXIT_FAILURE, err, "upward: failed to wait"); err = pthread_mutex_unlock (&mut5); if (err != 0) error (EXIT_FAILURE, err, "upward: failed to unlock"); if (!do_d64_to_d32 (1.1111125dd, 1.111113df)) FAILURE if (!do_d64_to_d32 (1.1111135dd, 1.111114df)) FAILURE if (!do_d64_to_d32 (-1.1111125dd, -1.111112df)) FAILURE if (!do_d64_to_d32 (-1.1111135dd, -1.111113df)) FAILURE if (!do_d128_to_d32 (1.1111125dl, 1.111113df)) FAILURE if (!do_d128_to_d32 (1.1111135dl, 1.111114df)) FAILURE if (!do_d128_to_d32 (-1.1111125dl, -1.111112df)) FAILURE if (!do_d128_to_d32 (-1.1111135dl, -1.111113df)) FAILURE if (!do_d128_to_d64 (1.1111111111111125dl, 1.111111111111113dd)) FAILURE if (!do_d128_to_d64 (1.1111111111111135dl, 1.111111111111114dd)) FAILURE if (!do_d128_to_d64 (-1.1111111111111125dl, -1.111111111111112dd)) FAILURE if (!do_d128_to_d64 (-1.1111111111111135dl, -1.111111111111113dd)) FAILURE #ifdef DBG if (failcnt) printf ("upward: %d fails\n", failcnt); #endif return (void *) (ptrdiff_t) failcnt; } int main (void) { int err; int count = 0; void *ret; pthread_t down, up, tozero, fromzero, nearest; if (pthread_barrier_init (&bar1, NULL, 2) != 0 || pthread_barrier_init (&bar2, NULL, 2) != 0 || pthread_barrier_init (&bar3, NULL, 2) != 0 || pthread_barrier_init (&bar4, NULL, 2) != 0 || pthread_barrier_init (&bar5, NULL, 2) != 0) { puts ("parent: failed to init barrier"); return 1; } if (pthread_create (&down, NULL, downward, NULL) != 0) { puts ("parent: failed to create"); return 1; } if (pthread_create (&nearest, NULL, tonearest, NULL) != 0) { puts ("create failed"); return 1; } if (pthread_create (&fromzero, NULL, toneareastfromzero, NULL) != 0) { puts ("create failed"); return 1; } if (pthread_create (&up, NULL, upward, NULL) != 0) { puts ("create failed"); return 1; } if (pthread_create (&tozero, NULL, towardzero, NULL) != 0) { puts ("create failed"); return 1; } err = pthread_barrier_wait (&bar1); if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD) { puts ("parent: failed to wait barrier 1"); return 1; } err = pthread_barrier_wait (&bar2); if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD) { puts ("parent: failed to wait barrier 2"); return 1; } err = pthread_barrier_wait (&bar3); if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD) { puts ("parent: failed to wait barrier 3"); return 1; } err = pthread_barrier_wait (&bar4); if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD) { puts ("parent: failed to wait barrier 4"); return 1; } err = pthread_barrier_wait (&bar5); if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD) { puts ("parent: failed to wait barrier 5"); return 1; } err = pthread_mutex_lock (&mut1); if (err != 0) error (EXIT_FAILURE, err, "parent: lock failed"); err = pthread_mutex_lock (&mut2); if (err != 0) error (EXIT_FAILURE, err, "parent: lock failed"); err = pthread_mutex_lock (&mut3); if (err != 0) error (EXIT_FAILURE, err, "parent: lock failed"); err = pthread_mutex_lock (&mut4); if (err != 0) error (EXIT_FAILURE, err, "parent: lock failed"); err = pthread_mutex_lock (&mut5); if (err != 0) error (EXIT_FAILURE, err, "parent: lock failed"); err = pthread_cond_signal(&cond1); if (err != 0) error (EXIT_FAILURE, err, "parent: broadcast failed"); err = pthread_cond_signal(&cond2); if (err != 0) error (EXIT_FAILURE, err, "parent: broadcast failed"); err = pthread_cond_signal(&cond3); if (err != 0) error (EXIT_FAILURE, err, "parent: broadcast failed"); err = pthread_cond_signal(&cond4); if (err != 0) error (EXIT_FAILURE, err, "parent: broadcast failed"); err = pthread_cond_signal(&cond5); if (err != 0) error (EXIT_FAILURE, err, "parent: broadcast failed"); err = pthread_mutex_unlock (&mut1); if (err != 0) { puts ("parent: failed to unlock"); return 1; } err = pthread_mutex_unlock (&mut2); if (err != 0) { puts ("parent: failed to unlock"); return 1; } err = pthread_mutex_unlock (&mut3); if (err != 0) { puts ("parent: failed to unlock"); return 1; } err = pthread_mutex_unlock (&mut4); if (err != 0) { puts ("parent: failed to unlock"); return 1; } err = pthread_mutex_unlock (&mut5); if (err != 0) { puts ("parent: failed to unlock"); return 1; } if (pthread_join (down, &ret) != 0) { puts ("pthread_join failed"); return 1; } count += (int) (ptrdiff_t) ret; if (pthread_join (up, &ret) != 0) { puts ("pthread_join failed"); return 1; } count += (int) (ptrdiff_t) ret; if (pthread_join (tozero, &ret) != 0) { puts ("pthread_join failed"); return 1; } count += (int) (ptrdiff_t) ret; if (pthread_join (fromzero, &ret) != 0) { puts ("pthread_join failed"); return 1; } count += (int) (ptrdiff_t) ret; if (pthread_join (nearest, &ret) != 0) { puts ("pthread_join failed"); return 1; } count += (int) (ptrdiff_t) ret; if (count) { #ifdef DBG printf ("Total: %d fails\n", count); #endif abort (); } return 0; }