diff --git a/eval_tree.cc b/eval_tree.cc index 09b4f3bb6..f19734175 100644 --- a/eval_tree.cc +++ b/eval_tree.cc @@ -1727,8 +1727,7 @@ NetECReal* NetESFunc::evaluate_itor_(const NetExpr*arg_) const return new NetECReal(verireal(0.0)); } - if (arg >= 0.0) arg = floor(arg + 0.5); - else arg = ceil(arg - 0.5); + arg = std::round(arg); return new NetECReal(verireal(arg)); } diff --git a/verinum.cc b/verinum.cc index edebf1aae..2c79630fa 100644 --- a/verinum.cc +++ b/verinum.cc @@ -37,10 +37,7 @@ using namespace std; */ extern "C" long int lround(double x) { - if (x >= 0.0) - return (long)floor(x+0.5); - else - return (long)ceil(x-0.5); + return (long)std::round(x); } #endif diff --git a/verireal.cc b/verireal.cc index 6297bc31c..d5352d6e7 100644 --- a/verireal.cc +++ b/verireal.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2021 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2025 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -71,15 +71,8 @@ long verireal::as_long() const double out = value_; double outf; - if (out >= 0.0) { - outf = floor(out); - if (out >= (outf + 0.5)) - outf += 1.0; - } else { - outf = ceil(out); - if (out <= (outf - 0.5)) - outf -= 1.0; - } + outf = std::round(out); + return (long) outf; } @@ -88,15 +81,8 @@ int64_t verireal::as_long64(int shift) const double out = value_ * pow(10.0,shift); double outf; - if (out >= 0.0) { - outf = floor(out); - if (out >= (outf + 0.5)) - outf += 1.0; - } else { - outf = ceil(out); - if (out <= (outf - 0.5)) - outf -= 1.0; - } + outf = std::round(out); + return (int64_t) outf; } diff --git a/vvp/config.h.in b/vvp/config.h.in index 1ce525449..f2dba606c 100644 --- a/vvp/config.h.in +++ b/vvp/config.h.in @@ -145,10 +145,7 @@ typedef unsigned long vvp_time64_t; */ inline long int lround(double x) { - if (x >= 0.0) - return (long)floor(x+0.5); - else - return (long)ceil(x-0.5); + return (long)std::round(x); } #endif /* HAVE_LROUND */ @@ -160,10 +157,7 @@ inline long int lround(double x) */ inline int64_t i64round(double x) { - if (x >= 0.0) - return (int64_t)floor(x+0.5); - else - return (int64_t)ceil(x-0.5); + return (int64_t)std::round(x); } #else /* HAVE_LLROUND */ # define i64round llround diff --git a/vvp/vpi_callback.cc b/vvp/vpi_callback.cc index f779027a6..d35015926 100644 --- a/vvp/vpi_callback.cc +++ b/vvp/vpi_callback.cc @@ -949,23 +949,6 @@ void vvp_signal_value::get_signal_value(struct t_vpi_value*vp) } } -static double vlg_round(double rval) -{ - if (rval >= 0.0) { - return floor(rval + 0.5); - } else { - return ceil(rval - 0.5); - } -} - -static uint64_t vlg_round_to_u64(double rval) -{ - // Directly casting a negative double to an unsigned integer types is - // undefined behavior and behaves differently on different architectures. - // Cast to signed integer first to get the behavior we want. - return static_cast(static_cast(vlg_round(rval))); -} - static void real_signal_value(struct t_vpi_value*vp, double rval) { static const size_t RBUF_SIZE = 64 + 1; @@ -984,7 +967,7 @@ static void real_signal_value(struct t_vpi_value*vp, double rval) if (rval != rval || (rval && (rval == 0.5*rval))) { rval = 0.0; } else { - rval = vlg_round(rval); + rval = std::round(rval); } vp->value.integer = (PLI_INT32)rval; break; @@ -993,7 +976,7 @@ static void real_signal_value(struct t_vpi_value*vp, double rval) if (std::isnan(rval)) snprintf(rbuf, RBUF_SIZE, "%s", "nan"); else - snprintf(rbuf, RBUF_SIZE, "%0.0f", vlg_round(rval)); + snprintf(rbuf, RBUF_SIZE, "%0.0f", std::round(rval)); vp->value.str = rbuf; break; diff --git a/vvp/vpi_priv.cc b/vvp/vpi_priv.cc index ed21f1f2b..4630c531f 100644 --- a/vvp/vpi_priv.cc +++ b/vvp/vpi_priv.cc @@ -880,14 +880,7 @@ static PLI_INT32 get_real_as_int(double real) return 0; } - /* Round away from zero. */ - if (real >= 0.0) { - rtn = floor(real); - if (real >= (rtn + 0.5)) rtn += 1.0; - } else { - rtn = ceil(real); - if (real <= (rtn - 0.5)) rtn -= 1.0; - } + rtn = std::round(real); return (PLI_INT32) rtn; } diff --git a/vvp/vpi_priv.h b/vvp/vpi_priv.h index c63d5c0b4..a666471b8 100644 --- a/vvp/vpi_priv.h +++ b/vvp/vpi_priv.h @@ -1157,4 +1157,12 @@ extern int vpip_delay_selection; /* A flag to disable output to MCD bit 0. */ extern bool vpip_mcd0_disable; +inline uint64_t vlg_round_to_u64(double rval) +{ + // Directly casting a negative double to an unsigned integer types is + // undefined behavior and behaves differently on different architectures. + // Cast to signed integer first to get the behavior we want. + return static_cast(static_cast(std::round(rval))); +} + #endif /* IVL_vpi_priv_H */ diff --git a/vvp/vpi_vthr_vector.cc b/vvp/vpi_vthr_vector.cc index 503eff6a3..ceaf6b413 100644 --- a/vvp/vpi_vthr_vector.cc +++ b/vvp/vpi_vthr_vector.cc @@ -87,15 +87,6 @@ static int vthr_word_get(int code, vpiHandle ref) } } -static double vlg_round(double rval) -{ - if (rval >= 0.0) { - return floor(rval + 0.5); - } else { - return ceil(rval - 0.5); - } -} - static void vthr_real_get_value(vpiHandle ref, s_vpi_value*vp) { const __vpiVThrWord*obj = dynamic_cast<__vpiVThrWord*>(ref); @@ -127,7 +118,7 @@ static void vthr_real_get_value(vpiHandle ref, s_vpi_value*vp) if (val != val || (val && (val == 0.5*val))) { val = 0.0; } else { - val = vlg_round(val); + val = std::round(val); } vp->value.integer = (PLI_INT32)val; break; @@ -136,22 +127,22 @@ static void vthr_real_get_value(vpiHandle ref, s_vpi_value*vp) if (std::isnan(val)) snprintf(rbuf, RBUF_USE_SIZE, "%s", "nan"); else - snprintf(rbuf, RBUF_USE_SIZE, "%0.0f", vlg_round(val)); + snprintf(rbuf, RBUF_USE_SIZE, "%0.0f", std::round(val)); vp->value.str = rbuf; break; case vpiOctStrVal: - snprintf(rbuf, RBUF_USE_SIZE, "%" PRIo64, (uint64_t)vlg_round(val)); + snprintf(rbuf, RBUF_USE_SIZE, "%" PRIo64, vlg_round_to_u64(val)); vp->value.str = rbuf; break; case vpiHexStrVal: - snprintf(rbuf, RBUF_USE_SIZE, "%" PRIx64, (uint64_t)vlg_round(val)); + snprintf(rbuf, RBUF_USE_SIZE, "%" PRIx64, vlg_round_to_u64(val)); vp->value.str = rbuf; break; case vpiBinStrVal: { - uint64_t vali = (uint64_t)vlg_round(val); + uint64_t vali = vlg_round_to_u64(val); unsigned len = 0; while (vali > 0) { @@ -159,7 +150,7 @@ static void vthr_real_get_value(vpiHandle ref, s_vpi_value*vp) vali /= 2; } - vali = (uint64_t)vlg_round(val); + vali = vlg_round_to_u64(val); for (unsigned idx = 0 ; idx < len ; idx += 1) { rbuf[len-idx-1] = (vali & 1)? '1' : '0'; vali /= 2; diff --git a/vvp/vthread.cc b/vvp/vthread.cc index 067c17885..e1d84722e 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -2380,10 +2380,7 @@ bool of_CVT_SR(vthread_t thr, vvp_code_t cp) bool of_CVT_UR(vthread_t thr, vvp_code_t cp) { double r = thr->pop_real(); - if (r >= 0.0) - thr->words[cp->bit_idx[0]].w_uint = (uint64_t)floor(r+0.5); - else - thr->words[cp->bit_idx[0]].w_uint = (uint64_t)ceil(r-0.5); + thr->words[cp->bit_idx[0]].w_uint = vlg_round_to_u64(r); return true; }