diff --git a/include/lccrt.h b/include/lccrt.h index bbf1f83..a6b1841 100644 --- a/include/lccrt.h +++ b/include/lccrt.h @@ -770,6 +770,7 @@ extern int lccrt_varinit_is_array( lccrt_vi_ptr vi); extern int lccrt_varinit_is_str( lccrt_vi_ptr vi); extern int lccrt_varinit_is_addr_var( lccrt_vi_ptr vi); extern int lccrt_varinit_is_addr_func( lccrt_vi_ptr vi); +extern int lccrt_varinit_cmp( lccrt_t_ptr t0, lccrt_vi_ptr vi0, lccrt_t_ptr t1, lccrt_vi_ptr vi1); extern lccrt_oi_ptr lccrt_oper_iterator_new( lccrt_ctx_ptr ctx); extern lccrt_oi_ptr lccrt_oper_iterator_delete( lccrt_oi_ptr iter); diff --git a/lib/irv/lccrt_var.c b/lib/irv/lccrt_var.c index 5961c29..a96c9c9 100644 --- a/lib/irv/lccrt_var.c +++ b/lib/irv/lccrt_var.c @@ -14,6 +14,13 @@ #include "lccrt_real.h" +#define CMP_WITH_SIGN( type, a, b) ({ \ + type x = (type)(a); \ + type y = (type)(b); \ + int r = (x < y) ? -1 : ((x == y) ? 0 : +1); \ + r; \ +}) + /** * Пропустить typename определения в типе. */ @@ -455,6 +462,61 @@ lccrt_varinit_is_addr_func( lccrt_varinit_ptr vi) return (r); } /* lccrt_varinit_is_addr_func */ +int +lccrt_varinit_cmp( lccrt_type_ptr t0, lccrt_varinit_ptr vi0, lccrt_type_ptr t1, lccrt_varinit_ptr vi1) +{ + int r = 0; + + if ( (t0 == t1) ) { + int zh0 = lccrt_varinit_is_zero_or_hex( vi0); + int zh1 = lccrt_varinit_is_zero_or_hex( vi1); + + if ( zh0 && zh1 ) { + r = CMP_WITH_SIGN( uint64_t, + lccrt_varinit_get_zero_or_hex64( vi0), + lccrt_varinit_get_zero_or_hex64( vi1)); + } else if ( zh0 ) { + r = -1; + } else if ( zh1 ) { + r = +1; + } else if ( lccrt_varinit_is_addr_var( vi0) + && lccrt_varinit_is_addr_var( vi1) ) + { + lccrt_var_ptr av0 = lccrt_varinit_get_addr_var( vi0); + lccrt_var_ptr av1 = lccrt_varinit_get_addr_var( vi1); + uint64_t n0 = lccrt_varinit_get_num_elems( vi0); + uint64_t n1 = lccrt_varinit_get_num_elems( vi1); + + r = (av0 == av1) ? CMP_WITH_SIGN( uint64_t, n0, n1) : CMP_WITH_SIGN( uintptr_t, av0, av1); + + } else if ( lccrt_varinit_is_addr_var( vi0) ) { + r = -1; + } else if ( lccrt_varinit_is_addr_var( vi1) ) { + r = +1; + } else if ( lccrt_varinit_is_addr_func( vi0) + && lccrt_varinit_is_addr_func( vi1) ) + { + lccrt_f_ptr f0 = lccrt_varinit_get_addr_func( vi0); + lccrt_f_ptr f1 = lccrt_varinit_get_addr_func( vi1); + uint64_t n0 = lccrt_varinit_get_num_elems( vi0); + uint64_t n1 = lccrt_varinit_get_num_elems( vi1); + + r = (f0 == f1) ? CMP_WITH_SIGN( uint64_t, n0, n1) : CMP_WITH_SIGN( uintptr_t, f0, f1); + + } else if ( lccrt_varinit_is_addr_func( vi0) ) { + r = -1; + } else if ( lccrt_varinit_is_addr_func( vi1) ) { + r = +1; + } else { + r = CMP_WITH_SIGN( uintptr_t, vi0, vi1); + } + } else { + r = CMP_WITH_SIGN( uintptr_t, t0, t1); + } + + return (r); +} /* lccrt_varinit_cmp */ + /** * Создание новой переменной. */ diff --git a/tools/lccrt_s/include/lccrt_s.h b/tools/lccrt_s/include/lccrt_s.h index 5de8b66..199b138 100644 --- a/tools/lccrt_s/include/lccrt_s.h +++ b/tools/lccrt_s/include/lccrt_s.h @@ -478,6 +478,10 @@ extern uint64_t __lccrt_fptoui_sat_i64f80( __lccrt_f80_t); extern __lccrt_uint128_t __lccrt_fptoui_sat_i128f32( __lccrt_f32_t); extern __lccrt_uint128_t __lccrt_fptoui_sat_i128f64( __lccrt_f64_t); +extern int __lccrt_isfpclass_f32( __lccrt_f32_t value, int32_t fpclss); +extern int __lccrt_isfpclass_f64( __lccrt_f64_t value, int32_t fpclss); +extern int __lccrt_isfpclass_f80( __lccrt_f80_t value, int32_t fpclss); + extern __lccrt_nint96_t __lccrt_fshl_i96( __lccrt_nint96_t, __lccrt_nint96_t, __lccrt_nint96_t); extern void __lccrt_vecbitpack( void *dst, void *src, int64_t veclen, int64_t elembitsize); diff --git a/tools/lccrt_s/src/lccrt_n.c b/tools/lccrt_s/src/lccrt_n.c index f3635ba..1969dfa 100644 --- a/tools/lccrt_s/src/lccrt_n.c +++ b/tools/lccrt_s/src/lccrt_n.c @@ -3976,3 +3976,85 @@ __lccrt_bswap_128( __lccrt_uint128_t v) return (r); } /* __lccrt_bswap_128 */ + +/** + * fpclass bits: + * 0 - Signaling NaN + * 1 - Quiet NaN + * 2 - Negative infinity + * 3 - Negative normal + * 4 - Negative subnormal + * 5 - Negative zero + * 6 - Positive zero + * 7 - Positive subnormal + * 8 - Positive normal + * 9 - Positive infinity + */ +int +__lccrt_isfpclass_f32( __lccrt_f32_t x, int32_t fpclss) { + if ( ((fpclss >> 0) & 0x1) != ((fpclss >> 1) & 0x1) ) { + __builtin_fprintf( stderr, "error: %s doesn't support snan/qnan separately\n", __FUNCTION__); + } + if ( (fpclss >> 0) & 0x1 ) if ( __builtin_isnan( x) ) return 1; + if ( (fpclss >> 1) & 0x1 ) if ( __builtin_isnan( x) ) return 1; + if ( (fpclss >> 2) & 0x1 ) if ( __builtin_isinf_sign( x) == -1 ) return 1; + if ( (fpclss >> 3) & 0x1 ) if ( __builtin_isnormal( x) && (x < 0) ) return 1; + if ( (fpclss >> 5) & 0x1 ) if ( x == -0.0 ) return 1; + if ( (fpclss >> 6) & 0x1 ) if ( x == +0.0 ) return 1; + if ( (fpclss >> 8) & 0x1 ) if ( __builtin_isnormal( x) && (x > 0) ) return 1; + if ( (fpclss >> 9) & 0x1 ) if ( __builtin_isinf_sign( x) == +1 ) return 1; + if ( ((fpclss >> 4) && 0x1) || ((fpclss >> 7) & 0x1) ) { + if ( __builtin_isfinite( x) && !__builtin_isnormal( x) ) { + if ( (fpclss >> 4) & 0x1 ) if ( x < 0.0 ) return 1; + if ( (fpclss >> 7) & 0x1 ) if ( x > 0.0 ) return 1; + } + } + + return (0); +} /* __lccrt_isfpclass_f32 */ + +int +__lccrt_isfpclass_f64( __lccrt_f64_t x, int32_t fpclss) { + if ( ((fpclss >> 0) & 0x1) != ((fpclss >> 1) & 0x1) ) { + __builtin_fprintf( stderr, "error: %s doesn't support snan/qnan separately\n", __FUNCTION__); + } + if ( (fpclss >> 0) & 0x1 ) if ( __builtin_isnan( x) ) return 1; + if ( (fpclss >> 1) & 0x1 ) if ( __builtin_isnan( x) ) return 1; + if ( (fpclss >> 2) & 0x1 ) if ( __builtin_isinf_sign( x) == -1 ) return 1; + if ( (fpclss >> 3) & 0x1 ) if ( __builtin_isnormal( x) && (x < 0) ) return 1; + if ( (fpclss >> 5) & 0x1 ) if ( x == -0.0 ) return 1; + if ( (fpclss >> 6) & 0x1 ) if ( x == +0.0 ) return 1; + if ( (fpclss >> 8) & 0x1 ) if ( __builtin_isnormal( x) && (x > 0) ) return 1; + if ( (fpclss >> 9) & 0x1 ) if ( __builtin_isinf_sign( x) == +1 ) return 1; + if ( ((fpclss >> 4) && 0x1) || ((fpclss >> 7) & 0x1) ) { + if ( __builtin_isfinite( x) && !__builtin_isnormal( x) ) { + if ( (fpclss >> 4) & 0x1 ) if ( x < 0.0 ) return 1; + if ( (fpclss >> 7) & 0x1 ) if ( x > 0.0 ) return 1; + } + } + + return (0); +} /* __lccrt_isfpclass_f64 */ + +int +__lccrt_isfpclass_f80( __lccrt_f80_t x, int32_t fpclss) { + if ( ((fpclss >> 0) & 0x1) != ((fpclss >> 1) & 0x1) ) { + __builtin_fprintf( stderr, "error: %s doesn't support snan/qnan separately\n", __FUNCTION__); + } + if ( (fpclss >> 0) & 0x1 ) if ( __builtin_isnan( x) ) return 1; + if ( (fpclss >> 1) & 0x1 ) if ( __builtin_isnan( x) ) return 1; + if ( (fpclss >> 2) & 0x1 ) if ( __builtin_isinf_sign( x) == -1 ) return 1; + if ( (fpclss >> 3) & 0x1 ) if ( __builtin_isnormal( x) && (x < 0) ) return 1; + if ( (fpclss >> 5) & 0x1 ) if ( x == -0.0 ) return 1; + if ( (fpclss >> 6) & 0x1 ) if ( x == +0.0 ) return 1; + if ( (fpclss >> 8) & 0x1 ) if ( __builtin_isnormal( x) && (x > 0) ) return 1; + if ( (fpclss >> 9) & 0x1 ) if ( __builtin_isinf_sign( x) == +1 ) return 1; + if ( ((fpclss >> 4) && 0x1) || ((fpclss >> 7) & 0x1) ) { + if ( __builtin_isfinite( x) && !__builtin_isnormal( x) ) { + if ( (fpclss >> 4) & 0x1 ) if ( x < 0.0 ) return 1; + if ( (fpclss >> 7) & 0x1 ) if ( x > 0.0 ) return 1; + } + } + + return (0); +} /* __lccrt_isfpclass_f80 */