/// <summary> /// Converts a double value to its binary encoding, given a floating point format. /// </summary> /// <param name="value">The value to be encoded</param> /// <param name="fmt">The floating point format to be assumed</param> /// <returns>The binary encoding</returns> public static StdLogicVector ToSLV(this double value, FloatFormat fmt) { StdLogicVector sign; StdLogicVector exponent; StdLogicVector mantissa; if (double.IsInfinity(value)) { sign = double.IsNegativeInfinity(value) ? (StdLogicVector)"1" : (StdLogicVector)"0"; exponent = StdLogicVector._1s(fmt.ExponentWidth); mantissa = StdLogicVector._0s(fmt.FractionWidth); } else if (double.IsNaN(value)) { sign = (StdLogicVector)"0"; exponent = StdLogicVector._1s(fmt.ExponentWidth); mantissa = StdLogicVector._1s(fmt.FractionWidth); } else { sign = value < 0.0 ? (StdLogicVector)"1" : (StdLogicVector)"0"; double absvalue = Math.Abs(value); int exp = 0; while (absvalue >= 2.0) { absvalue *= 0.5; exp++; } while (absvalue > 0.0 && absvalue < 1.0) { absvalue *= 2.0; exp--; } if (absvalue == 0.0) { return(StdLogicVector._0s(fmt.TotalWidth)); } else if (exp <= -fmt.Bias) { // denomalized exponent = StdLogicVector._0s(fmt.ExponentWidth); absvalue *= (double)(1L << (fmt.FractionWidth + 1)); long mant = (long)absvalue; mantissa = StdLogicVector.FromLong(mant, fmt.FractionWidth); } else { absvalue -= 1.0; absvalue *= (double)(1L << fmt.FractionWidth); long mant = (long)absvalue; mantissa = StdLogicVector.FromLong(mant, fmt.FractionWidth); exponent = StdLogicVector.FromLong(exp + fmt.Bias, fmt.ExponentWidth); } } return(sign.Concat(exponent.Concat(mantissa))); }
/// <summary> /// Converts a binary encoding, given as an StdLogicVector with respect to a floating point format to its /// double representation. /// </summary> /// <param name="slv">The binary encoding</param> /// <param name="fmt">The floating point format to be assumed</param> /// <returns>The double representation</returns> public static double ToFloat(this StdLogicVector slv, FloatFormat fmt) { if (slv.Size != fmt.TotalWidth) { throw new ArgumentException("Vector does not match specified floating point format"); } slv = slv.ProperValue; StdLogicVector mantissa = slv[fmt.FractionWidth - 1, 0]; StdLogicVector exponent = slv[fmt.FractionWidth + fmt.ExponentWidth - 1, fmt.FractionWidth]; StdLogic sign = slv[fmt.FractionWidth + fmt.ExponentWidth]; int exp = (int)exponent.ULongValue - fmt.Bias; if (exponent.Equals(StdLogicVector._0s(fmt.ExponentWidth))) { // denormalized long mant = mantissa.LongValue; double result = (double)mant * Math.Pow(2.0, exp - 1); return(result); } else if (exponent.Equals(StdLogicVector._1s(fmt.ExponentWidth))) { // Infinity / NaN if (mantissa.Equals(StdLogicVector._0s(fmt.FractionWidth))) { // infinity if (sign == '1') { return(double.NegativeInfinity); } else { return(double.PositiveInfinity); } } else { // NaN return(double.NaN); } } else { // normalized StdLogicVector number = StdLogicVector._1s(1).Concat(mantissa); ulong mant = number.ULongValue; double result = (double)mant * Math.Pow(2.0, exp - fmt.FractionWidth); if (sign == '1') { result = -result; } return(result); } }
/// <summary> /// Converts a double value to its binary encoding, given a floating point format. /// </summary> /// <param name="value">The value to be encoded</param> /// <param name="fmt">The floating point format to be assumed</param> /// <returns>The binary encoding</returns> public static StdLogicVector ToSLV(this double value, FloatFormat fmt) { StdLogicVector sign; StdLogicVector exponent; StdLogicVector mantissa; if (double.IsInfinity(value)) { sign = double.IsNegativeInfinity(value) ? (StdLogicVector)"1" : (StdLogicVector)"0"; exponent = StdLogicVector._1s(fmt.ExponentWidth); mantissa = StdLogicVector._0s(fmt.FractionWidth); } else if (double.IsNaN(value)) { sign = (StdLogicVector)"0"; exponent = StdLogicVector._1s(fmt.ExponentWidth); mantissa = StdLogicVector._1s(fmt.FractionWidth); } else { sign = value < 0.0 ? (StdLogicVector)"1" : (StdLogicVector)"0"; double absvalue = Math.Abs(value); int exp = 0; while (absvalue >= 2.0) { absvalue *= 0.5; exp++; } while (absvalue > 0.0 && absvalue < 1.0) { absvalue *= 2.0; exp--; } if (absvalue == 0.0) { return StdLogicVector._0s(fmt.TotalWidth); } else if (exp <= -fmt.Bias) { // denomalized exponent = StdLogicVector._0s(fmt.ExponentWidth); absvalue *= (double)(1L << (fmt.FractionWidth+1)); long mant = (long)absvalue; mantissa = StdLogicVector.FromLong(mant, fmt.FractionWidth); } else { absvalue -= 1.0; absvalue *= (double)(1L << fmt.FractionWidth); long mant = (long)absvalue; mantissa = StdLogicVector.FromLong(mant, fmt.FractionWidth); exponent = StdLogicVector.FromLong(exp + fmt.Bias, fmt.ExponentWidth); } } return sign.Concat(exponent.Concat(mantissa)); }
public FloatFormat GetResultFormat() { FloatFormat fmt; switch (ResultPrecision) { case EPrecision.Single: fmt = FloatFormat.SingleFormat; break; case EPrecision.Double: fmt = FloatFormat.DoubleFormat; break; case EPrecision.Custom: fmt = new FloatFormat(ResultExponentWidth, ResultFractionWidth); break; default: throw new NotImplementedException(); } return fmt; }
/// <summary> /// Converts a binary encoding, given as an StdLogicVector with respect to a floating point format to its /// double representation. /// </summary> /// <param name="slv">The binary encoding</param> /// <param name="fmt">The floating point format to be assumed</param> /// <returns>The double representation</returns> public static double ToFloat(this StdLogicVector slv, FloatFormat fmt) { if (slv.Size != fmt.TotalWidth) throw new ArgumentException("Vector does not match specified floating point format"); slv = slv.ProperValue; StdLogicVector mantissa = slv[fmt.FractionWidth - 1, 0]; StdLogicVector exponent = slv[fmt.FractionWidth + fmt.ExponentWidth - 1, fmt.FractionWidth]; StdLogic sign = slv[fmt.FractionWidth + fmt.ExponentWidth]; int exp = (int)exponent.ULongValue - fmt.Bias; if (exponent.Equals(StdLogicVector._0s(fmt.ExponentWidth))) { // denormalized long mant = mantissa.LongValue; double result = (double)mant * Math.Pow(2.0, exp - 1); return result; } else if (exponent.Equals(StdLogicVector._1s(fmt.ExponentWidth))) { // Infinity / NaN if (mantissa.Equals(StdLogicVector._0s(fmt.FractionWidth))) { // infinity if (sign == '1') return double.NegativeInfinity; else return double.PositiveInfinity; } else { // NaN return double.NaN; } } else { // normalized StdLogicVector number = StdLogicVector._1s(1).Concat(mantissa); ulong mant = number.ULongValue; double result = (double)mant * Math.Pow(2.0, exp - fmt.FractionWidth); if (sign == '1') result = -result; return result; } }