Exemple #1
0
        // This doesn't work for all cases yet.
        //public Unum(UnumEnvironment environment, float number)
        //{
        //    _environment = environment;

        //    // Handling special cases first.
        //    if (float.IsNaN(number))
        //    {
        //        UnumBits = _environment.QuietNotANumber;
        //        return;
        //    }
        //    if (float.IsPositiveInfinity(number))
        //    {
        //        UnumBits = _environment.PositiveInfinity;
        //        return;
        //    }
        //    if (float.IsNegativeInfinity(number))
        //    {
        //        UnumBits = _environment.NegativeInfinity;
        //        return;
        //    }


        //    UnumBits = new BitMask(_environment.Size);
        //    var floatExponentBits = (BitConverter.ToUInt32(BitConverter.GetBytes(number), 0) << 1) >> 24;

        //    // These are the only uncertain cases that we can safely handle without Ubounds.
        //    if (ExponentSizeMax < ExponentValueToExponentSize((int)floatExponentBits - 127))
        //    {
        //        // The exponent is too big, so we express the number as the largest possible signed value,
        //        // but the Unum is uncertain, meaning that it's finite, but too big to express.
        //        if (floatExponentBits - 127 > 0)
        //            UnumBits = IsPositive() ? LargestPositive : LargestNegative;
        //        else // If the exponent is too small, we will handle it as a signed uncertain zero.
        //        {
        //            UnumBits = new BitMask(Size);
        //            if (!IsPositive()) Negate();
        //        }

        //        SetUncertainityBit(true);

        //        return;
        //    }


        //    var floatFractionBits = (BitConverter.ToUInt32(BitConverter.GetBytes(number), 0) << 9) >> 9;
        //    uint resultFractionSize = 23;
        //    uint floatFractionBitsSize = 23;

        //    if (floatFractionBits == 0) resultFractionSize = 0;
        //    else
        //        while (floatFractionBits % 2 == 0)
        //        {
        //            resultFractionSize -= 1;
        //            floatFractionBits >>= 1;
        //            floatFractionBitsSize = resultFractionSize;
        //        }


        //    var uncertainty = false;

        //    if (FractionSizeMax + 1 < resultFractionSize)
        //    {
        //        resultFractionSize = ((uint)FractionSizeMax - 1);
        //        uncertainty = true;
        //    }
        //    else if (resultFractionSize > 0) resultFractionSize = (resultFractionSize - 1);

        //    var resultFraction = uncertainty ?
        //        new BitMask(new uint[] { floatFractionBits >> (int)floatFractionBitsSize - FractionSizeMax }, Size) :
        //        new BitMask(new uint[] { floatFractionBits }, Size);
        //    var resultExponent = ExponentValueToExponentBits((int)(floatExponentBits - 127), Size);
        //    var floatBits = BitConverter.ToUInt32(BitConverter.GetBytes(number), 0);
        //    var resultSignBit = (floatBits > uint.MaxValue / 2);
        //    var resultExponentSize = (ExponentValueToExponentSize((int)floatExponentBits - 127) - 1);


        //    AssembleUnumBits(resultSignBit, resultExponent, resultFraction,
        //        uncertainty, resultExponentSize, resultFractionSize);
        //}

        /// <summary>
        /// Creates a Unum of the given environment initialized with the value of the uint.
        /// </summary>
        /// <param name="environment">The Unum environment.</param>
        /// <param name="value">The uint value to initialize the new Unum with.</param>
        public Unum(UnumEnvironment environment, uint value)
        {
            _environment = environment;
            // Creating an array of the size needed to call the other constructor.
            // This is necessary because in Hastlayer only arrays with dimensions defined at compile-time are supported.
            var valueArray = new uint[environment.EmptyBitMask.SegmentCount];

            valueArray[0] = value;

            UnumBits = new Unum(environment, valueArray).UnumBits;
        }
Exemple #2
0
        /// <summary>
        /// Shifts the BitMask to the right by the number of trailing zeros.
        /// </summary>
        /// <returns>A BitMask where the trailing zeros are shifted out to the right.</returns>
        public BitMask ShiftOutLeastSignificantZeros()
        {
            var leastSignificantOnePosition = GetLeastSignificantOnePosition();
            var mask = new BitMask(this);

            if (leastSignificantOnePosition == 0)
            {
                return(mask);
            }

            return(mask >> leastSignificantOnePosition - 1);
        }
Exemple #3
0
        public static BitMask ExponentValueToExponentBits(int value, ushort size)
        {
            var exponent     = new BitMask((uint)((value < 0) ? -value : value), size);
            var exponentSize = ExponentValueToExponentSize(value);

            exponent += (uint)(1 << (exponentSize - 1)) - 1; // Applying bias

            if (value < 0)                                   // In case of a negative exponent the
            {
                exponent -= (uint)(-2 * value);
            }

            return(exponent);
        }
Exemple #4
0
        public static BitMask AddAlignedFractions(BitMask left, BitMask right, bool signBitsMatch)
        {
            var mask = new BitMask(left.Size);

            if (signBitsMatch)
            {
                mask = left + right;
            }
            else
            {
                mask = left > right ? left - right : right - left;
            }

            return(mask);
        }
Exemple #5
0
        // This doesn't work for all cases yet.
        //public Unum(UnumEnvironment environment, double x)
        //{
        //    _environment = environment;
        //    UnumBits = _environment.EmptyBitMask;

        //    // Handling special cases first.
        //    if (double.IsNaN(x))
        //    {
        //        UnumBits = QuietNotANumber;
        //        return;
        //    }
        //    if (double.IsPositiveInfinity(x))
        //    {
        //        UnumBits = PositiveInfinity;
        //        return;
        //    }
        //    if (double.IsNegativeInfinity(x))
        //    {
        //        UnumBits = NegativeInfinity;
        //        return;
        //    }


        //    var doubleBits = BitConverter.ToUInt64(BitConverter.GetBytes(x), 0);
        //    SetSignBit((doubleBits > ulong.MaxValue / 2));


        //    var doubleFractionBits = (BitConverter.ToUInt64(BitConverter.GetBytes(x), 0) << 12) >> 12;
        //    uint resultFractionSize = 52;

        //    if (doubleFractionBits == 0) resultFractionSize = 0;
        //    else
        //    {
        //        while (doubleFractionBits % 2 == 0)
        //        {
        //            resultFractionSize -= 1;
        //            doubleFractionBits >>= 1;
        //        }

        //    }


        //    var uncertainty = false;

        //    if (FractionSizeMax < resultFractionSize - 1)
        //    {
        //        SetFractionSizeBits((uint)(FractionSizeMax - 1));
        //        uncertainty = true;
        //    }
        //    else SetFractionSizeBits(resultFractionSize - 1);


        //    var doubleExponentBits = (BitConverter.ToUInt64(BitConverter.GetBytes(x), 0) << 1) >> 53;

        //    // These are the only uncertain cases that we can safely handle without Ubounds.
        //    if (ExponentSizeMax < ExponentValueToExponentSize((int)doubleExponentBits - 1023))
        //    {
        //        // The exponent is too big, so we express the number as the largest possible signed value,
        //        // but the Unum is uncertain, meaning that it's finite, but too big to express.
        //        if (doubleExponentBits - 1023 > 0)
        //            UnumBits = IsPositive() ? LargestPositive : LargestNegative;
        //        else // If the exponent is too small, we will handle it as a signed uncertain zero.
        //        {
        //            UnumBits = _environment.EmptyBitMask;
        //            if (!IsPositive()) Negate();
        //        }

        //        SetUncertainityBit(true);

        //        return;
        //    }


        //    var exponentSizeBits = ExponentValueToExponentSize((int)doubleExponentBits - 1023) - 1;
        //    SetExponentSizeBits(exponentSizeBits);

        //    var doubleFraction = new uint[2];
        //    doubleFraction[0] = (uint)((doubleFractionBits << 32) >> 32);
        //    doubleFraction[1] = (uint)((doubleFractionBits >> 32));

        //    if (uncertainty)
        //    {
        //        SetFractionBits(Size > 32 ?
        //            // This is necessary because Hastlayer enables only one size of BitMasks.
        //            new BitMask(doubleFraction, Size) >> ((int)resultFractionSize - (int)FractionSize()) :
        //            // The lower 32 bits wouldn't fit in anyway.
        //            new BitMask(new uint[] { doubleFraction[1] }, Size) >> ((int)resultFractionSize - FractionSizeMax));

        //        SetUncertainityBit(true);
        //    }
        //    else
        //        SetFractionBits(Size > 32 ?
        //            // This is necessary because Hastlayer enables only one size of BitMasks.
        //            new BitMask(doubleFraction, Size) :
        //            // The lower 32 bits wouldn't fit in anyway.
        //            new BitMask(new uint[] { doubleFraction[1] }, Size));


        //    SetExponentBits(ExponentValueToExponentBits((int)(doubleExponentBits - 1023), Size));
        //}

        #endregion

        #region Methods to set the values of individual Unum structure elements



        /// <summary>
        /// Assembles the Unum from its pre-computed parts.
        /// </summary>
        /// <param name="signBit">The SignBit of the Unum.</param>
        /// <param name="exponent">The biased notation of the exponent of the Unum.</param>
        /// <param name="fraction">The fraction of the Unum without the hidden bit.</param>
        /// <param name="uncertainityBit">The value of the uncertainity bit (Ubit).</param>
        /// <param name="exponentSize">The Unum's exponent size, in a notation that is one less than the actual value.</param>
        /// <param name="fractionSize">The Unum's fraction size, in a notation that is one less than the actual value.</param>
        /// <returns>The BitMask representing the whole Unum with all the parts set.</returns>
        private BitMask AssembleUnumBits(bool signBit, BitMask exponent, BitMask fraction,
                                         bool uncertainityBit, byte exponentSize, ushort fractionSize)
        {
            var wholeUnum = new BitMask(exponentSize, Size) << FractionSizeSize;

            wholeUnum += fractionSize;

            if (uncertainityBit)
            {
                wholeUnum += UncertaintyBitMask;
            }

            wholeUnum += fraction << UnumTagSize;
            wholeUnum += exponent << (UnumTagSize + fractionSize + 1);

            if (signBit)
            {
                wholeUnum += SignBitMask;
            }

            return(wholeUnum);
        }
Exemple #6
0
 public BitMask(BitMask source)
 {
     Size         = source.Size;
     SegmentCount = source.SegmentCount;
     Segments     = source.Segments;
 }
Exemple #7
0
        public static Unum AddExactUnums(Unum left, Unum right)
        {
            // It could be only FractionSizeMax + 2 long if that would be Hastlayer-compatible (it isn't due to static
            // array sizes).
            var scratchPad = new BitMask(left._environment.Size);

            // Handling special cases first.
            if (left.IsNan() || right.IsNan())
            {
                return(new Unum(left._environment, left.QuietNotANumber));
            }

            if ((left.IsPositiveInfinity() && right.IsNegativeInfinity()) ||
                (left.IsNegativeInfinity() && right.IsPositiveInfinity()))
            {
                return(new Unum(left._environment, left.QuietNotANumber));
            }

            if (left.IsPositiveInfinity() || right.IsPositiveInfinity())
            {
                return(new Unum(left._environment, left.PositiveInfinity));
            }

            if (left.IsNegativeInfinity() || right.IsNegativeInfinity())
            {
                return(new Unum(left._environment, left.NegativeInfinity));
            }

            var exponentValueDifference = left.ExponentValueWithBias() - right.ExponentValueWithBias();
            var signBitsMatch           = left.IsPositive() == right.IsPositive();
            var resultSignBit           = false;
            var biggerBitsMovedToLeft   = 0;
            var smallerBitsMovedToLeft  = 0;
            var resultExponentValue     = 0;


            if (exponentValueDifference == 0) // Exponents are equal.
            {
                resultExponentValue = left.ExponentValueWithBias();

                // We align the fractions so their Most Significant Bit gets to the leftmost position that the
                // FractionSize allows. This way the digits that won't fit automatically get lost.
                biggerBitsMovedToLeft  = left.FractionSizeMax + 1 - (left.FractionSize() + 1);
                smallerBitsMovedToLeft = left.FractionSizeMax + 1 - (right.FractionSize() + 1);
                // Adding the aligned Fractions.
                scratchPad = AddAlignedFractions(
                    left.FractionWithHiddenBit() << biggerBitsMovedToLeft,
                        right.FractionWithHiddenBit() << smallerBitsMovedToLeft,
                        signBitsMatch);


                if (!signBitsMatch)
                {
                    // If the value of the Hidden Bits match we just compare the fractions,
                    // and get the Sign of the bigger one.
                    if (left.HiddenBitIsOne() == right.HiddenBitIsOne())
                    {
                        resultSignBit = left.Fraction() >= right.Fraction()
                            ? !left.IsPositive()   // Left Fraction is bigger.
                            : !right.IsPositive(); // Right Fraction is bigger.
                    }
                    // Otherwise we get the Sign of the number that has a Hidden Bit set.
                    else
                    {
                        resultSignBit = left.HiddenBitIsOne() ? !left.IsPositive() : !right.IsPositive();
                    }
                }
                else
                {
                    resultSignBit = !left.IsPositive();
                }
            }
            else if (exponentValueDifference > 0) // Left Exponent is bigger.
            {
                // We align the fractions according to their exponent values so the Most Significant Bit  of the bigger
                // number gets to the leftmost position that the  FractionSize allows.
                // This way the digits that won't fit automatically get lost.
                resultSignBit          = !left.IsPositive();
                resultExponentValue    = left.ExponentValueWithBias();
                biggerBitsMovedToLeft  = left.FractionSizeMax + 1 - (left.FractionSize() + 1);
                smallerBitsMovedToLeft = left.FractionSizeMax + 1 - (right.FractionSize() + 1) - exponentValueDifference;

                scratchPad = left.FractionWithHiddenBit() << biggerBitsMovedToLeft;
                // Adding the aligned Fractions.
                scratchPad = AddAlignedFractions(scratchPad,
                                                 right.FractionWithHiddenBit() << smallerBitsMovedToLeft, signBitsMatch);
            }
            else // Right Exponent is bigger.
            {
                // We align the fractions according to their exponent values so the Most Significant Bit  of the bigger
                // number gets to the leftmost position that the  FractionSize allows.
                // This way the digits that won't fit automatically get lost.
                resultSignBit          = !right.IsPositive();
                resultExponentValue    = right.ExponentValueWithBias();
                biggerBitsMovedToLeft  = left.FractionSizeMax + 1 - (right.FractionSize() + 1);
                smallerBitsMovedToLeft = left.FractionSizeMax + 1 - (left.FractionSize() + 1) + exponentValueDifference;

                scratchPad = right.FractionWithHiddenBit() << biggerBitsMovedToLeft;
                // Adding the aligned Fractions.
                scratchPad = AddAlignedFractions(scratchPad,
                                                 left.FractionWithHiddenBit() << smallerBitsMovedToLeft, signBitsMatch);
            }

            // Calculating how the addition changed the exponent of the result.
            var exponentChange = scratchPad.GetMostSignificantOnePosition() - (left.FractionSizeMax + 1);
            var resultExponent = new BitMask(left._environment.Size) +
                                 ExponentValueToExponentBits(resultExponentValue + exponentChange, left.Size);
            // Calculating the ExponentSize needed to the excess-k notation of the results Exponent value.
            var resultExponentSize = (byte)(ExponentValueToExponentSize(resultExponentValue + exponentChange) - 1);

            var resultUbit = false;

            if (smallerBitsMovedToLeft < 0)
            {
                resultUbit = true;                             // There are lost digits, so we set the ubit to 1.
            }
            // If there are no lost digits, we can shift out the least significant zeros to save space.
            else
            {
                scratchPad = scratchPad.ShiftOutLeastSignificantZeros();
            }

            ushort resultFractionSize = 0;

            //Calculating the results FractionSize.
            if (scratchPad.GetMostSignificantOnePosition() == 0) // If the Fraction is zero, so is the FractionSize.
            {
                resultExponent     = scratchPad;                 // 0
                resultExponentSize = 0;                          // If the Fraction is zero, so is the ExponentSize.
            }
            else
            {
                resultFractionSize = (ushort)(scratchPad.GetMostSignificantOnePosition() - 1);
            }


            if (resultExponent.GetMostSignificantOnePosition() != 0) // Erase the hidden bit if it is set.
            {
                scratchPad         = scratchPad.SetZero((ushort)(scratchPad.GetMostSignificantOnePosition() - 1));
                resultFractionSize = (ushort)(resultFractionSize == 0 ? 0 : resultFractionSize - 1);
            }

            // This is temporary, for the imitation of float behaviour. Now the Ubit works as a flag for rounded values.
            // When Ubounds will be implemented this should be handled in the addition operator.
            if ((!left.IsExact()) || (!right.IsExact()))
            {
                resultUbit = true;
            }

            // Setting the parts of the result Unum to the calculated values.
            var resultBitMask = left.AssembleUnumBits(resultSignBit, resultExponent, scratchPad,
                                                      resultUbit, resultExponentSize, resultFractionSize);

            return(new Unum(left._environment, resultBitMask));
        }
Exemple #8
0
        public BitMask ExponentMask()
        {
            var exponentMask = new BitMask(1, Size);

            return(((exponentMask << ExponentSize()) - 1) << (FractionSize() + UnumTagSize));
        }
Exemple #9
0
        public BitMask FractionMask()
        {
            var fractionMask = new BitMask(1, Size);

            return(((fractionMask << FractionSize()) - 1) << UnumTagSize);
        }
Exemple #10
0
        /// <summary>
        /// Creates a Unum initialized with a value that is defined by the bits in a uint array.
        /// </summary>
        /// <param name="environment">The Unum environment.</param>
        /// <param name="value">
        /// The uint array which defines the Unum's value as an integer.
        /// To use with Hastlayer this should be the same size as the BitMasks in the given environment.
        /// </param>
        /// <param name="negative">Defines whether the number is positive or not.</param>
        public Unum(UnumEnvironment environment, uint[] value, bool negative = false)
        {
            _environment = environment;

            UnumBits = new BitMask(value, environment.Size);
            if (UnumBits == _environment.EmptyBitMask)
            {
                return;
            }

            // Handling the case when the number wouldn't fit in the range of the environment.
            if (UnumHelper.LargestExpressablePositiveInteger(environment) != environment.EmptyBitMask)
            {
                if (UnumBits > UnumHelper.LargestExpressablePositiveInteger(environment))
                {
                    UnumBits = negative ? environment.LargestNegative | environment.UncertaintyBitMask
                        : environment.LargestPositive | environment.UncertaintyBitMask;
                    return;
                }
            }
            var uncertainityBit = false;

            // Putting the actual value in a BitMask.
            var exponent = new BitMask(value, Size);

            // The value of the exponent is one less than the number of binary digits in the integer.
            var exponentValue = new BitMask((uint)(exponent.GetMostSignificantOnePosition() - 1), Size);

            // Calculating the number of bits needed to represent the value of the exponent.
            var exponentSize = exponentValue.GetMostSignificantOnePosition();

            // If the value of the exponent is not a power of 2,
            // then one more bit is needed to represent the biased value.
            if ((exponentValue.GetLowest32Bits() & exponentValue.GetLowest32Bits() - 1) > 0)
            {
                exponentSize++;
            }

            // Handling input numbers that don't fit in the range of the given environment.
            if (exponentSize > ExponentSizeMax)
            {
                UnumBits = negative ? (environment.LargestNegative | environment.UncertaintyBitMask) - 1
                    : (environment.LargestPositive | environment.UncertaintyBitMask) - 1;
                return;
            }
            // Calculating the bias from the number of bits representing the exponent.
            var bias = exponentSize == 0 ? 0 : (1 << exponentSize - 1) - 1;

            // Applying the bias to the exponent.
            exponent = exponentValue + (uint)bias;

            // Putting the actual value in a BitMask.
            var fraction = new BitMask(value, Size);

            // Shifting out the zeros after the least significant 1-bit.
            fraction = fraction.ShiftOutLeastSignificantZeros();

            // Calculating the number of bits needed to represent the fraction.
            var fractionSize = fraction.GetMostSignificantOnePosition();


            /* If there's a hidden bit and it's 1,
             * then the most significant 1-bit of the fraction is stored there,
             * so we're removing it from the fraction and decreasing fraction size accordingly. */
            if (exponent.GetLowest32Bits() > 0)
            {
                fractionSize--;
                fraction = fraction.SetZero(fractionSize);
            }
            // Handling input numbers that fit in the range, but are too big to represent exactly.
            if (fractionSize > FractionSizeMax)
            {
                fraction        = fraction >> FractionSizeMax - fractionSize;
                uncertainityBit = true;
            }

            UnumBits = AssembleUnumBits(negative, exponent, fraction,
                                        uncertainityBit, (byte)(exponentSize > 0 ? --exponentSize : 0), (ushort)(fractionSize > 0 ? --fractionSize : 0));
        }
Exemple #11
0
        public BitMask                   MinRealU => _environment.MinRealU; // "minrealu"

        #endregion

        #region Unum constructors

        public Unum(UnumEnvironment environment)
        {
            _environment = environment;

            UnumBits = new BitMask(_environment.Size);
        }