private static Float PowerOfTwo(int exp) { Contracts.Assert(0 <= exp && exp < ExpInf); return(FloatUtils.GetPowerOfTwoSingle(exp)); }
public static bool TryParse(out Single value, string s, int ichMin, int ichLim, out int ichEnd) { bool neg = false; ulong num = 0; long exp = 0; ichEnd = ichMin; if (!TryParseCore(s, ref ichEnd, ichLim, ref neg, ref num, ref exp)) { return(TryParseSpecial(out value, s, ref ichEnd, ichLim)); } if (num == 0) { value = 0; goto LDone; } // The Single version simply looks up the power of 10 in a table (as a Double), casts num // to Double, multiples, then casts to Single. Double res; if (exp >= 0) { if (exp == 0) { res = 1; } else if (exp > _mpe10Dbl.Length) { value = Single.PositiveInfinity; goto LDone; } else { res = _mpe10Dbl[(int)exp - 1]; } } else { if (-exp > _mpne10Dbl.Length) { value = 0; goto LDone; } res = _mpne10Dbl[-(int)exp - 1]; } // REVIEW: casting ulong to Double doesn't always get the answer correct. // Casting a non-negative long does work, though, so we jump through hoops to make // sure the top bit is clear and cast to long before casting to Double. Double tmp; if ((long)num >= 0) { tmp = (Double)(long)num; } else { tmp = (Double)(long)((num >> 1) | (num & 1)); tmp += tmp; } res *= tmp; value = (Single)res; LDone: if (neg) { value = -value; } #if COMPARE_BCL if (!_failed) { string str = s.Substring(ichMin, ichEnd - ichMin); Single x; if (!Single.TryParse(str, out x)) { // Single.TryParse doesn't gracefully handle overflow to infinity. if (!Single.IsPositiveInfinity(value) && !Single.IsNegativeInfinity(value)) { _failed = true; Contracts.Assert(false, string.Format("Single.TryParse failed on: {0}", str)); } } else if (FloatUtils.GetBits(x) != FloatUtils.GetBits(value)) { // Double.TryParse gets negative zero wrong! if (FloatUtils.GetBits(x) != 0 || FloatUtils.GetBits(value) != 0x80000000U || !neg) { _failed = true; Contracts.Assert(false, string.Format("FloatParser disagrees with Single.TryParse on: {0} ({1} vs {2})", str, FloatUtils.GetBits(x), FloatUtils.GetBits(value))); } } } #endif return(true); }
public static bool TryParse(out Double value, string s, int ichMin, int ichLim, out int ichEnd) { bool neg = false; ulong num = 0; long exp = 0; ichEnd = ichMin; if (!TryParseCore(s, ref ichEnd, ichLim, ref neg, ref num, ref exp)) { return(TryParseSpecial(out value, s, ref ichEnd, ichLim)); } if (num == 0) { value = 0; goto LDone; } ulong mul; int e2; if (exp >= 0) { if (exp == 0) { // REVIEW: casting ulong to Double doesn't always get the answer correct. // Casting a non-negative long does work, though, so we jump through hoops to make // sure the top bit is clear and cast to long before casting to Double. if ((long)num >= 0) { value = (Double)(long)num; } else { value = (Double)(long)((num >> 1) | (num & 1)); value += value; } goto LDone; } if (exp <= 22 && num < (1UL << 53)) { // Can just use Double division, since both 10^|exp| and num can be exactly represented in Double. // REVIEW: there are potential other "easy" cases, like when num isn't less than 2^54, but // it ends with enough zeros that it can be made so by shifting. Contracts.Assert((long)(Double)(long)num == (long)num); value = (Double)(long)num * _mpe10Dbl[exp - 1]; goto LDone; } if (exp > _mpe10Man.Length) { value = Double.PositiveInfinity; goto LDone; } int index = (int)exp - 1; mul = _mpe10Man[index]; e2 = _mpe10e2[index]; } else { if (-exp <= 22 && num < (1UL << 53)) { // Can just use Double division, since both 10^|exp| and num can be exactly represented in Double. // REVIEW: there are potential other "easy" cases, like when num isn't less than 2^54, but // it ends with enough zeros that it can be made so by shifting. Contracts.Assert((long)(Double)(long)num == (long)num); value = (Double)(long)num / _mpe10Dbl[-exp - 1]; goto LDone; } if (-exp > _mpne10Man.Length) { value = 0; goto LDone; } int index = -(int)exp - 1; mul = _mpne10Man[index]; e2 = -_mpne10ne2[index]; } // Normalize the mantissa and initialize the base-2 (biased) exponent. // Ensure that the high bit is set. if ((num & 0xFFFFFFFF00000000UL) == 0) { num <<= 32; e2 -= 32; } if ((num & 0xFFFF000000000000UL) == 0) { num <<= 16; e2 -= 16; } if ((num & 0xFF00000000000000UL) == 0) { num <<= 8; e2 -= 8; } if ((num & 0xF000000000000000UL) == 0) { num <<= 4; e2 -= 4; } if ((num & 0xC000000000000000UL) == 0) { num <<= 2; e2 -= 2; } // Don't force the top bit to be non-zero, since we'll just have to clear it later.... // if ((num & 0x8000000000000000UL) == 0) { num <<= 1; e2 -= 1; } // The high bit of mul is 1, and at least one of the top two bits of num is non-zero. // Taking the high 64 bits of the 128 bit result should give us enough bits to get the // right answer most of the time. Note, that it's not guaranteed that we always get the // right answer. Guaranteeing that takes much more work.... See the paper by David Gay at // http://www.ampl.com/REFS/rounding.pdf. Contracts.Assert((num & TopTwoBits) != 0); Contracts.Assert((mul & TopBit) != 0); // Multiply mul into num, keeping the high ulong. // REVIEW: Can this be made faster? It would be nice to use the _umul128 intrinsic. ulong hi1 = mul >> 32; ulong lo1 = mul & 0xFFFFFFFFUL; ulong hi2 = num >> 32; ulong lo2 = num & 0xFFFFFFFFUL; num = hi1 * hi2; hi1 *= lo2; hi2 *= lo1; num += hi1 >> 32; num += hi2 >> 32; hi1 <<= 32; hi2 <<= 32; if ((hi1 += hi2) < hi2) { num++; } lo1 *= lo2; if ((lo1 += hi1) < hi1) { num++; } // Cast to long first since ulong => Double is broken. Contracts.Assert((num & TopThreeBits) != 0); if ((long)num >= 0) { // Capture a non-zero lo to avoid an artificial tie. if (lo1 != 0) { num |= 1; } value = (Double)(long)num; } else { if ((lo1 | (num & 1)) != 0) { num |= 2; } value = (Double)(long)(num >> 1); e2++; } // Adjust the base-2 exponent. e2 += 0x3FF; if (e2 >= 0x7FF) { Contracts.Assert(exp > 0); value = Double.PositiveInfinity; goto LDone; } if (e2 <= 0) { // Break the exponent adjustment into two operations. Contracts.Assert(exp < 0); mul = 1UL << 52; unsafe { value *= *(Double *)&mul; } e2 += 0x3FF - 1; Contracts.Assert(e2 > 0); } // Multiply by the exponent adjustment. Contracts.Assert(0 < e2 & e2 < 0x7FF); mul = (ulong)e2 << 52; unsafe { value *= *(Double *)&mul; } LDone: if (neg) { value = -value; } #if COMPARE_BCL string str = s.Substring(ichMin, ichEnd - ichMin); Double x; if (!Double.TryParse(str, out x)) { // Double.TryParse doesn't gracefully handle overflow to infinity. if (!Double.IsPositiveInfinity(value) && !Double.IsNegativeInfinity(value)) { if (!_failed) { _failed = true; Contracts.Assert(false, string.Format("Double.TryParse failed on: {0}", str)); } } } else if (FloatUtils.GetBits(x) != FloatUtils.GetBits(value)) { // Double.TryParse gets negative zero wrong! if (FloatUtils.GetBits(x) != 0 || FloatUtils.GetBits(value) != TopBit || !neg) { System.Diagnostics.Debug.WriteLine("*** FloatParser disagrees with Double.TryParse on: {0} ({1} vs {2})", str, FloatUtils.GetBits(x), FloatUtils.GetBits(value)); } } #endif return(true); }
/// <summary> /// Finds the bins for Single values (and integer labels) /// </summary> /// <param name="maxBins">Maximum number of bins</param> /// <param name="minBinSize">Minimum number of values per bin (stopping condition for greedy bin splitting)</param> /// <param name="nLabels">Cardinality of the labels</param> /// <param name="values">The feature values</param> /// <param name="labels">The corresponding label values</param> /// <returns>An array of split points, no more than <paramref name="maxBins"/> total (but maybe less), ending with PositiveInfinity</returns> public Single[] FindBins(int maxBins, int minBinSize, int nLabels, IList <Single> values, IList <int> labels) { // prepare the values: count distinct values and populate the value pair array _valueCount = values.Count; _labelCardinality = nLabels; _maxBins = maxBins; _minBinSize = minBinSize; Contracts.Assert(_valueCount == labels.Count); _distinctValueCount = 0; var seenValues = new HashSet <Single>(); var valuePairs = new ValuePair <Single> [_valueCount]; for (int i = 0; i < _valueCount; i++) { valuePairs[i] = new ValuePair <Single>(values[i], labels[i]); if (seenValues.Add(values[i])) { _distinctValueCount++; } } Array.Sort(valuePairs); // populate the cumulative counts with unique values _cumulativeCounts = new int[_distinctValueCount, _labelCardinality + 1]; var distinctValues = new Single[_distinctValueCount]; Single curValue = Single.NegativeInfinity; int curIndex = -1; foreach (var pair in valuePairs) { Contracts.Assert(pair.Value >= curValue); if (pair.Value > curValue || curIndex < 0) { curValue = pair.Value; curIndex++; distinctValues[curIndex] = curValue; if (curIndex > 0) { for (int i = 0; i < _labelCardinality + 1; i++) { _cumulativeCounts[curIndex, i] = _cumulativeCounts[curIndex - 1, i]; } } } _cumulativeCounts[curIndex, pair.Label]++; _cumulativeCounts[curIndex, _labelCardinality]++; } Contracts.Assert(curIndex == _distinctValueCount - 1); var boundaries = FindBinsCore(); Contracts.Assert(Utils.Size(boundaries) > 0); Contracts.Assert(boundaries.Length == 1 && boundaries[0] == 0 || boundaries[0] > 0, "boundaries are exclusive, can't have 0"); Contracts.Assert(boundaries[boundaries.Length - 1] == _distinctValueCount); // transform boundary indices back into bin upper bounds var numUpperBounds = boundaries.Length; Single[] result = new Single[numUpperBounds]; for (int i = 0; i < numUpperBounds - 1; i++) { var split = boundaries[i]; result[i] = BinFinderBase.GetSplitValue(distinctValues[split - 1], distinctValues[split]); // Even though distinctValues may contain infinities, the boundaries may not be infinite: // GetSplitValue(a,b) only returns +-inf if a==b==+-inf, // and distinctValues won't contain more than one +inf or -inf. Contracts.Assert(FloatUtils.IsFinite(result[i])); } result[numUpperBounds - 1] = Single.PositiveInfinity; AssertStrictlyIncreasing(result); return(result); }