diff --git a/verinum.cc b/verinum.cc index b6f247751..18a83c614 100644 --- a/verinum.cc +++ b/verinum.cc @@ -1053,15 +1053,17 @@ verinum pow(const verinum&left, const verinum&right) long pow_count = right.as_long(); // We need positive and negative one in a few places. - verinum one (verinum::V0, left.len(), left.has_len()); + unsigned len = left.len(); + // Positive one must be at least two bits wide! + verinum one (verinum::V0, (len<2) ? 2 : len, left.has_len()); one.has_sign(left.has_sign()); one.set(0, verinum::V1); - verinum m_one (verinum::V1, left.len(), left.has_len()); + verinum m_one (verinum::V1, len, left.has_len()); m_one.has_sign(true); // If either the right or left values are undefined we return 'bx. if (!right.is_defined() || !left.is_defined()) { - result = verinum(verinum::Vx, left.len(), left.has_len()); + result = verinum(verinum::Vx, len, left.has_len()); result.has_sign(left.has_sign()); // If the right value is zero we need to set the result to 1. } else if (pow_count == 0) { @@ -1069,7 +1071,7 @@ verinum pow(const verinum&left, const verinum&right) } else if (pow_count < 0) { // 0 ** is 'bx. if (left.is_zero()) { - result = verinum(verinum::Vx, left.len(), left.has_len()); + result = verinum(verinum::Vx, len, left.has_len()); result.has_sign(left.has_sign()); // 1 ** is 1. } else if (left == one) { @@ -1083,7 +1085,7 @@ verinum pow(const verinum&left, const verinum&right) } // Everything else is 0. } else { - result = verinum(verinum::V0, left.len(), left.has_len()); + result = verinum(verinum::V0, len, left.has_len()); result.has_sign(left.has_sign()); } } diff --git a/vvp/arith.cc b/vvp/arith.cc index 321cc4dd4..f6ada760e 100644 --- a/vvp/arith.cc +++ b/vvp/arith.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2010 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2011 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 @@ -438,11 +438,14 @@ void vvp_arith_pow::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit, return; } - double ad, bd; + double ad, bd, resd; vector4_to_value(op_a_, ad, true); vector4_to_value(op_b_, bd, true); + /* 2**-1 and -2**-1 are defined to be zero. */ + if ((bd == -1) && (fabs(ad) == 2.0)) resd = 0.0; + else resd = pow(ad, bd); - res4 = vvp_vector4_t(wid_, pow(ad, bd)); + res4 = vvp_vector4_t(wid_, resd); } else { vvp_vector2_t a2 (op_a_); vvp_vector2_t b2 (op_b_); diff --git a/vvp/vthread.cc b/vvp/vthread.cc index 60113d050..333032639 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2010 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2011 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 @@ -3989,10 +3989,13 @@ bool of_POW_S(vthread_t thr, vvp_code_t cp) } /* Calculate the result using the double pow() function. */ - double xd, yd; + double xd, yd, resd; vector4_to_value(xv, xd, true); vector4_to_value(yv, yd, true); - vvp_vector4_t res = vvp_vector4_t(wid, pow(xd, yd)); + /* 2**-1 and -2**-1 are defined to be zero. */ + if ((yd == -1.0) && (fabs(xd) == 2.0)) resd = 0.0; + else resd = pow(xd, yd); + vvp_vector4_t res = vvp_vector4_t(wid, resd); /* Copy the result. */ for (unsigned jdx = 0; jdx < wid; jdx += 1)