예제 #1
0
파일: BigInt.cs 프로젝트: hnordquist/INCC6
 /// <summary>
 /// Constructs a BigInt from a string, using the specified precision and base
 /// </summary>
 /// <param name="init"></param>
 /// <param name="precision"></param>
 /// <param name="numberBase"></param>
 public BigInt(string init, PrecisionSpec precision, int numberBase)
 {
     InitFromString(init, precision, numberBase);
 }
예제 #2
0
        private void Init(PrecisionSpec mantissaPrec)
        {
            int mbWords = ((mantissaPrec.NumBits) >> 5);
            if ((mantissaPrec.NumBits & 31) != 0) mbWords++;
            int newManBits = mbWords << 5;

            //For efficiency, we just use a 32-bit exponent
            exponent = 0;
            mantissa = new BigInt(new PrecisionSpec(newManBits, PrecisionSpec.BaseType.BIN));
            //scratch = new BigInt(new PrecisionSpec(newManBits, PrecisionSpec.BaseType.BIN));
        }
예제 #3
0
        /// <summary>
        /// Get e to the indicated precision
        /// </summary>
        /// <param name="precision">The preicision to perform the calculation to</param>
        /// <returns>e (the number for which the d/dx(e^x) = e^x)</returns>
        public static BigFloat GetE(PrecisionSpec precision)
        {
            if (eCache == null || eCache.mantissa.Precision.NumBits < precision.NumBits)
            {
                CalculateEOnly(precision.NumBits);
                //CalculateFactorials(precision.NumBits);
            }

            BigFloat ret = new BigFloat(precision);
            ret.Assign(eCache);

            return ret;
        }
예제 #4
0
        /// <summary>
        /// Constructs a BigFloat from a BigInt, using the specified precision
        /// </summary>
        /// <param name="value"></param>
        /// <param name="mantissaPrec"></param>
        public BigFloat(BigInt value, PrecisionSpec mantissaPrec)
        {
            if (value.IsZero())
            {
                Init(mantissaPrec);
                SetZero();
                return;
            }

            mantissa = new BigInt(value, mantissaPrec);
            exponent = BigInt.GetMSB(value);
            mantissa.Normalise();
        }
예제 #5
0
 /// <summary>
 /// Copy Constructor - constructs a new BigFloat with the specified precision, copying the old one.
 /// 
 /// The value is rounded towards zero in the case where precision is decreased. The Round() function
 /// should be used beforehand if a correctly rounded result is required.
 /// </summary>
 /// <param name="value"></param>
 /// <param name="mantissaPrec"></param>
 public BigFloat(BigFloat value, PrecisionSpec mantissaPrec)
 {
     Init(mantissaPrec);
     exponent = value.exponent;
     if (mantissa.AssignHigh(value.mantissa)) exponent++;
 }
예제 #6
0
        /// <summary>
        /// Uses the Gauss-Legendre formula for pi
        /// Taken from http://en.wikipedia.org/wiki/Gauss%E2%80%93Legendre_algorithm
        /// </summary>
        /// <param name="numBits"></param>
        private static void CalculatePi(int numBits)
        {
            int bits = numBits + 32;
            //Precision extend taken out.
            PrecisionSpec normalPres = new PrecisionSpec(numBits, PrecisionSpec.BaseType.BIN);
            PrecisionSpec extendedPres = new PrecisionSpec(bits, PrecisionSpec.BaseType.BIN);

            if (scratch.Precision.NumBits != bits)
            {
                scratch = new BigInt(extendedPres);
            }

            //a0 = 1
            BigFloat an = new BigFloat(1, extendedPres);

            //b0 = 1/sqrt(2)
            BigFloat bn = new BigFloat(2, extendedPres);
            bn.Sqrt();
            bn.exponent--;

            //to = 1/4
            BigFloat tn = new BigFloat(1, extendedPres);
            tn.exponent -= 2;

            int pn = 0;

            BigFloat anTemp = new BigFloat(extendedPres);

            int iteration = 0;
            int cutoffBits = numBits >> 5;

            for (iteration = 0; ; iteration++)
            {
                //Save a(n)
                anTemp.Assign(an);

                //Calculate new an
                an.Add(bn);
                an.exponent--;

                //Calculate new bn
                bn.Mul(anTemp);
                bn.Sqrt();

                //Calculate new tn
                anTemp.Sub(an);
                anTemp.mantissa.SquareHiFast(scratch);
                anTemp.exponent += anTemp.exponent + pn + 1 - anTemp.mantissa.Normalise();
                tn.Sub(anTemp);

                anTemp.Assign(an);
                anTemp.Sub(bn);

                if (anTemp.exponent < -(bits - cutoffBits)) break;

                //New pn
                pn++;
            }

            an.Add(bn);
            an.mantissa.SquareHiFast(scratch);
            an.exponent += an.exponent + 1 - an.mantissa.Normalise();
            tn.exponent += 2;
            an.Div(tn);

            pi = new BigFloat(an, normalPres);
            piBy2 = new BigFloat(pi);
            piBy2.exponent--;
            twoPi = new BigFloat(pi, normalPres);
            twoPi.exponent++;
            piRecip = new BigFloat(an.Reciprocal(), normalPres);
            twoPiRecip = new BigFloat(piRecip);
            twoPiRecip.exponent--;
            //1/3 is going to be useful for sin.
            threeRecip = new BigFloat((new BigFloat(3, extendedPres)).Reciprocal(), normalPres);
        }
예제 #7
0
        /// <summary>
        /// Constructs a BigFloat from a 64-bit integer
        /// </summary>
        /// <param name="value"></param>
        /// <param name="mantissaPrec"></param>
        public BigFloat(Int64 value, PrecisionSpec mantissaPrec)
        {
            int mbWords = ((mantissaPrec.NumBits) >> 5);
            if ((mantissaPrec.NumBits & 31) != 0) mbWords++;
            int newManBits = mbWords << 5;

            //For efficiency, we just use a 32-bit exponent
            exponent = 0;
            UInt64 uValue;

            if (value < 0)
            {
                if (value == Int64.MinValue)
                {
                    uValue = 0x80000000;
                }
                else
                {
                    uValue = (UInt64)(-value);
                }
            }
            else
            {
                uValue = (UInt64)value;
            }

            mantissa = new BigInt(value, new PrecisionSpec(newManBits, PrecisionSpec.BaseType.BIN));
            //scratch = new BigInt(new PrecisionSpec(newManBits, PrecisionSpec.BaseType.BIN));

            int bit = BigInt.GetMSB(uValue);
            if (bit == -1) return;

            int shift = mantissa.Precision.NumBits - (bit + 1);
            if (shift > 0)
            {
                mantissa.LSH(shift);
            }
            else
            {
                mantissa.SetHighDigit((uint)(uValue >> (-shift)));
            }
            exponent = bit;
        }
예제 #8
0
파일: BigInt.cs 프로젝트: hnordquist/INCC6
        //*************** Utility Functions **************

        /// <summary>
        /// Casts a BigInt to the new precision provided.
        /// Note: This will return the input if the precision already matches.
        /// </summary>
        /// <param name="input"></param>
        /// <param name="precision"></param>
        /// <returns></returns>
        public static BigInt CastToPrecision(BigInt input, PrecisionSpec precision)
        {
            if (input.pres == precision) return input;
            return new BigInt(input, precision);
        }
예제 #9
0
        /// <summary>
        /// GetSDTMultiplicityResult() calculates Singles, Doubles, and Triples rates plus related metadata.
        /// 
        /// This utility method works for both Slow- and Fast-Background Multiplicity Analyzers.
        /// 
        /// Note that the input parameter "accidentalsHistogram" need not be normalized,
        /// and that a normalized-accidentals distribution will be included in output and will be valid
        /// for both slow and fast accidentals.
        /// 
        /// </summary>
        /// <param name="realsPlusAccidentalsHistogram"> The histogram of gate populations. </param>
        /// <param name="accidentalsHistogram"> The histogram of gate populations - NOT NORMALIZED. </param>
        /// <param name="wasFastAccidentals"> true or false.  Affects how PTsingles are calculated, etc. </param>
        /// <param name="multiplicityGateWidth"> as a UInt64, in 100-nanosecond tics. </param>
        /// <param name="multiplicityDeadDelay"> as a UInt64, in 100-nanosecond tics. </param>
        /// <param name="accidentalsDelay"> as a UInt64, in 100-nanosecond tics. </param>
        /// <param name="deadTimeCoeffTinNanoSecs"> as a double, in nanoseconds. </param>
        /// <param name="deadTimeCoeffAinMicroSecs"> as a double, in microseconds. </param>
        /// <param name="deadTimeCoeffBinPicoSecs"> as a double, in picoseconds. </param>
        /// <param name="deadTimeCoeffCinNanoSecs"> as a double, in nanoseconds. </param>
        /// <param name="totalMeasurementTime"> as a double, in seconds. </param>
        /// <param name="normedAccidentalsHistogram">  UInt64[]. </param>
        /// <returns></returns>
        public MultiplicityResult GetSDTMultiplicityResult(UInt64[] realsPlusAccidentalsHistogram,
                                                           UInt64[] accidentalsHistogram,
                                                           Boolean wasFastAccidentals,
                                                           UInt64 multiplicityGateWidth,
                                                           UInt64 multiplicityDeadDelay,
                                                           UInt64 accidentalsDelay,
                                                           double deadTimeCoeffTinNanoSecs,
                                                           double deadTimeCoeffAinMicroSecs,
                                                           double deadTimeCoeffBinPicoSecs,
                                                           double deadTimeCoeffCinNanoSecs,
                                                           double totalMeasurementTime,
                                                           UInt64[] normedAccidentalsHistogram = null)
        {
            MultiplicityResult result;
            double phi;
            double gateInSeconds;
            UInt32 biggestKey, biggestAKey;
            int arrayLength;
            double[] alpha;
            double[] beta;
            BigFloat[] α = new BigFloat[0], β = new BigFloat[0];

            result = new MultiplicityResult();
            if (wasFastAccidentals == true)
            {
                result.isSlowBackground = false;
            }
            else
            {
                result.isSlowBackground = true;
            }

            //store parameters
            result.multiplicityGateWidth = multiplicityGateWidth;
            result.multiplicityDeadDelay = multiplicityDeadDelay;
            result.accidentalsDelay = accidentalsDelay;
            result.deadTimeCoefficientTinNanoSecs = deadTimeCoeffTinNanoSecs;
            result.deadTimeCoefficientAinMicroSecs = deadTimeCoeffAinMicroSecs;
            result.deadTimeCoefficientBinPicoSecs = deadTimeCoeffBinPicoSecs;
            result.deadTimeCoefficientCinNanoSecs = deadTimeCoeffCinNanoSecs;

            //copy the real-plus-accidental multiplicity histogram
            biggestKey = 0;
            arrayLength = realsPlusAccidentalsHistogram.Length;
            for (int i = 0; i < arrayLength; i++)
            {
                if (realsPlusAccidentalsHistogram[i] > 0)
                {
                    result.realPlusAccidentalDistribution.Add((UInt64)i, realsPlusAccidentalsHistogram[i]);
                    biggestKey = (UInt32)i;
                }
            }
            result.maxRABin = biggestKey;

            //copy the accidental-only histogram
            biggestAKey = 0;
            arrayLength = accidentalsHistogram.Length;
            for (int i = 0; i < arrayLength; i++)
            {
                if (accidentalsHistogram[i] > 0)
                {
                    result.accidentalDistribution.Add((UInt32)i, accidentalsHistogram[i]);
                    biggestAKey = (UInt32)i;
                }
            }
            result.maxABin = biggestAKey;

            //************************************************************
            //Normalize the AccidentalDistribution, 
            //scaling the FastBackgroundAnalysis result in proportion 
            //to the number of Real+Accidental gate
            UInt64 numAccidentalGates = 0;
            UInt64 numRealPlusAccidentalGates = 0;
            foreach (KeyValuePair<UInt64, UInt64> pair in result.realPlusAccidentalDistribution)
            {
                numRealPlusAccidentalGates += pair.Value;
            }

            // compute the normalization param and recompute the unnormalizaed array from this one (code does not seem to work JFL)
            if (normedAccidentalsHistogram != null)
            {
                for (int i = 0; i < normedAccidentalsHistogram.Length; i++)
                {
                    if (normedAccidentalsHistogram[i] > 0)
                    {
                        result.normalizedAccidentalDistribution.Add((UInt32)i, normedAccidentalsHistogram[i]);
                    }
                }

                UInt64 numNAccidentalGates = 0;

                foreach (ulong no in normedAccidentalsHistogram)
                {
                    numNAccidentalGates += no;
                }

                double denormalizingRatio;
                UInt64 denormalizedRate;
                denormalizingRatio = ((double)numNAccidentalGates) / ((double)numRealPlusAccidentalGates);

                result.accidentalDistribution.Clear();
                foreach (KeyValuePair<UInt64, UInt64> pair in result.normalizedAccidentalDistribution)
                {
                    denormalizedRate = (UInt64)(pair.Value * denormalizingRatio);
                    result.accidentalDistribution.Add(pair.Key, denormalizedRate);
                    biggestAKey = (UInt32)pair.Key;
                }
                result.maxABin = biggestAKey;

                foreach (KeyValuePair<UInt64, UInt64> pair in result.accidentalDistribution)
                {
                    numAccidentalGates += pair.Value;
                }

            }
            else
            {
                foreach (KeyValuePair<UInt64, UInt64> pair in result.accidentalDistribution)
                {
                    numAccidentalGates += pair.Value;
                }


                double normalizingRatio;
                UInt64 normalizedRate;
                normalizingRatio = ((double)numRealPlusAccidentalGates) / ((double)numAccidentalGates);

                result.normalizedAccidentalDistribution.Clear();
                foreach (KeyValuePair<UInt64, UInt64> pair in result.accidentalDistribution)
                {
                    normalizedRate = (UInt64)(pair.Value * normalizingRatio);
                    result.normalizedAccidentalDistribution.Add(pair.Key, normalizedRate);
                }
            }


            //*** END Normalizing the AccidentalDistribution *************


            //store the bigger key...
            if (biggestAKey > biggestKey)
            {
                biggestKey = biggestAKey;
            }
            if (biggestKey < 2)
            {
                biggestKey = 2;  //...minimum size for data-output arrays...
            }

            alpha = new double[biggestKey + 1];
            beta = new double[biggestKey + 1];

            gateInSeconds = ((double)multiplicityGateWidth) * this.ticSizeInSeconds;
            phi = (deadTimeCoeffTinNanoSecs / 1E9) / gateInSeconds;
            bool standard = true;  // dev note: this toggle signals use of BigNum when FP overflow is detected
            int axover = 0, bxover = 0;
            //calculate the alphas
            alpha[0] = 0.0;
            alpha[1] = 1.0;
            for (int n = 2; n <= biggestKey; n++)
            {
                if (phi > 1e-20)
                {
                    alpha[n] = 1.0;
                    if (standard)
                    {
                        for (int k = 0; k <= (n - 2); k++)
                        {
                            double alphaCoeff;
                            alphaCoeff = this.binomialCoefficient((n - 1), (k + 1))
                                         * Math.Pow((double)(k + 1), (double)k)
                                         * Math.Pow(phi, (double)k)
                                         / (Math.Pow((1.0 - ((k + 1) * phi)), (double)(k + 2)));
                            alpha[n] += alphaCoeff;
                            if (Double.IsInfinity(alpha[n]) || Double.IsNaN(alpha[n]))
                            {
                                result.warnings.Add("Overflow alpha at n = " + n + ", k = " + k);
                                alpha[n] = 0;
                                axover = n;
                                standard = false; k = n; n = n - 1; // redo the loop
                                α = new BigFloat[biggestKey + 1];
                            }
                        }
                    }
                    else
                    {
                        // INCCCycleConditioning.calc_alpha_beta 
                        PrecisionSpec ps128 = new PrecisionSpec(128, PrecisionSpec.BaseType.BIN);
                        BigFloat one = new BigFloat(1, ps128);
                        BigFloat combination;
                        BigFloat sum;
                        double raise1, power1, power2;
                        double log1, log2, log3;
                        BigFloat exp1, exp2, exp3;
                        /* calculate alpha array */
                        sum = new BigFloat(0, ps128);
                        for (int k = 0; k <= (n - 2); k++)
                        {
                            combination = new BigFloat(binomialCoefficient((n - 1), (k + 1)), ps128);
                            raise1 = (double)(k + 1);
                            power1 = (double)k;
                            power2 = (double)(k + 2);
                            log1 = Math.Log(raise1);
                            log2 = Math.Log(phi);
                            log3 = Math.Log(1.0 - raise1 * phi);
                            exp1 = BigFloat.Exp(new BigFloat(log1 * power1, ps128));
                            exp2 = BigFloat.Exp(new BigFloat(log2 * power1, ps128));
                            exp3 = BigFloat.Exp(new BigFloat(log3 * power2, ps128));
                            sum += combination * exp1 * exp2 / exp3;
                        }
                        α[n] = new BigFloat(one + sum, ps128);
                    }
                }
                else
                {
                    alpha[n] = 1.0;
                }
            }

            //calculate the betas
            standard = true;
            beta[0] = 0.0;
            beta[1] = 0.0;
            beta[2] = alpha[2] - 1.0;
            for (int n = 3; n <= biggestKey; n++)
            {
                if (phi > 1e-20)
                {
                    beta[n] = alpha[n] - 1.0;
                    if (standard)
                    {
                        for (int k = 0; k <= (n - 3); k++)
                        {
                            double betaCoeff;
                            betaCoeff = this.binomialCoefficient((n - 1), (k + 2))
                                        * (k + 1)
                                        * Math.Pow((double)(k + 2), (double)k)
                                        * Math.Pow(phi, (double)k)
                                        / (Math.Pow((1.0 - ((k + 2) * phi)), (double)(k + 3)));
                            beta[n] += betaCoeff;
                            if (Double.IsInfinity(beta[n]) || Double.IsNaN(beta[n]))
                            {
                                result.warnings.Add("Overflow beta at n = " + n + ", k = " + k);
                                beta[n] = 0;
                                bxover = n;
                                standard = false; k = n; n = n - 1; // redo the loop
                                β = new BigFloat[biggestKey + 1];
                            }
                        }
                    }
                    else
                    {
                        PrecisionSpec ps128 = new PrecisionSpec(128, PrecisionSpec.BaseType.BIN);
                        BigFloat one = new BigFloat(1, ps128);
                        BigFloat combination;
                        BigFloat sum;
                        double raise1, power1, power2;
                        double log1, log2, log3;
                        BigFloat exp1, exp2, exp3;
                        sum = new BigFloat(0, ps128);
                        for (int k = 0; k <= n - 3; k++)
                        {
                            combination = new BigFloat(binomialCoefficient((n - 1), (k + 2)), ps128);
                            raise1 = (double)(k + 2);
                            power1 = (double)k;
                            power2 = (double)(k + 3);
                            log1 = Math.Log(raise1);
                            log2 = Math.Log(phi);
                            log3 = Math.Log(1.0 - raise1 * phi);
                            exp1 = BigFloat.Exp(new BigFloat(log1 * power1, ps128));
                            exp2 = BigFloat.Exp(new BigFloat(log2 * power1, ps128));
                            exp3 = BigFloat.Exp(new BigFloat(log3 * power2, ps128));
                            sum += combination * (new BigFloat(k + 1, ps128)) * exp1 * exp2 / exp3;
                        }
                        β[n] = α[n] - one + sum;
                    }
                }
                else
                {
                    beta[n] = 0.0;
                }
            }

            //store the alpha and beta coefficients
            result.alpha = new double[biggestKey + 1];
            result.beta = new double[biggestKey + 1];
            for (int i = 0; i <= biggestKey; i++)
            {
                result.alpha[i] = alpha[i];
                result.beta[i] = beta[i];
            }

            double lastGoodD = 0;
            for (int i = axover; axover > 0 && i <= biggestKey; i++)
            {
                double d;
                bool good = Double.TryParse(α[i].ToString(), System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture.NumberFormat, out d);  // what to do when it is really larger than a double?
                if (!good)
                {
                    result.alpha[i] = lastGoodD;
                    result.warnings.Add(String.Format("α[{0}] conversion failed on {1}", i, α[i].ToString()));
                }
                else
                {
                    lastGoodD = d;
                    result.alpha[i] = d;
                }
            }

            for (int i = bxover; bxover > 0 && i <= biggestKey; i++)
            {
                double d;
                bool good = Double.TryParse(β[i].ToString(), System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture.NumberFormat, out d); 
                if (!good)
                {
                    result.beta[i] = lastGoodD;
                    result.warnings.Add(String.Format("β[{0}] conversion failed on {1}", i, β[i].ToString()));  // URGENT: alpha/beta arrays are to be transformed from doubles to BigFloat types when this conversion happens to overflow                
                 }
                else
                {
                    lastGoodD = d;
                    result.beta[i] = d;
                }
            }

            //NOTE: in the following calculations,
            //variables named RAxxx refer to "Reals Plus Accidentals" phenomena, and
            //variables named Axxx  refer to "Accidentals" phenomena (such as, fast-background counting)

            //calculate the factorial moments
            double RAfactorialMoment0, RAfactorialMoment1, RAfactorialMoment2, RAfactorialMoment3;
            double AfactorialMoment0, AfactorialMoment1, AfactorialMoment2, AfactorialMoment3;
            double RAfactorialMomentAlpha1, AfactorialMomentAlpha1;
            double RAfactorialMomentBeta2, AfactorialMomentBeta2;
            RAfactorialMoment0 = 0.0;
            RAfactorialMoment1 = 0.0;
            RAfactorialMoment2 = 0.0;
            RAfactorialMoment3 = 0.0;
            AfactorialMoment0 = 0.0;
            AfactorialMoment1 = 0.0;
            AfactorialMoment2 = 0.0;
            AfactorialMoment3 = 0.0;
            RAfactorialMomentAlpha1 = 0.0;
            AfactorialMomentAlpha1 = 0.0;
            RAfactorialMomentBeta2 = 0.0;
            AfactorialMomentBeta2 = 0.0;

            for (int i = 0; i <= biggestKey; i++)
            {
                UInt64 gateCount;
                int j = i + 1;
                int k = i + 2;
                int L = i + 3;

                if (result.realPlusAccidentalDistribution.TryGetValue((UInt64)i, out gateCount))
                {
                    RAfactorialMoment0 += (double)gateCount;
                }
                if (result.accidentalDistribution.TryGetValue((UInt64)i, out gateCount))
                {
                    AfactorialMoment0 += gateCount;
                }

                if (j <= biggestKey)
                {
                    if (result.realPlusAccidentalDistribution.TryGetValue((UInt64)j, out gateCount))
                    {
                        RAfactorialMoment1 += (double)(((UInt64)j) * gateCount);
                        RAfactorialMomentAlpha1 += alpha[j] * ((double)gateCount);
                    }
                    if (result.accidentalDistribution.TryGetValue((UInt64)j, out gateCount))
                    {
                        AfactorialMoment1 += (double)(((UInt64)j) * gateCount);
                        AfactorialMomentAlpha1 += alpha[j] * ((double)gateCount);
                    }
                }

                if (k <= biggestKey)
                {
                    if (result.realPlusAccidentalDistribution.TryGetValue((UInt32)k, out gateCount))
                    {
                        RAfactorialMoment2 += (double)(((UInt64)(k * (k - 1) / 2)) * gateCount);
                        RAfactorialMomentBeta2 += beta[k] * ((double)gateCount);
                    }
                    if (result.accidentalDistribution.TryGetValue((UInt32)k, out gateCount))
                    {
                        AfactorialMoment2 += (double)(((UInt64)(k * (k - 1) / 2)) * gateCount);
                        AfactorialMomentBeta2 += beta[k] * ((double)gateCount);
                    }
                }

                if (L <= biggestKey)
                {
                    if (result.realPlusAccidentalDistribution.TryGetValue((UInt32)L, out gateCount))
                    {
                        RAfactorialMoment3 += ((double)(((UInt64)(L * (L - 1) * (L - 2))) * gateCount)) / 6.0;
                    }
                    if (result.accidentalDistribution.TryGetValue((UInt32)L, out gateCount))
                    {
                        AfactorialMoment3 += ((double)(((UInt64)(L * (L - 1) * (L - 2))) * gateCount)) / 6.0;
                    }
                }
            }

            //store the factorial moments
            result.RAfactorialMoment0 = RAfactorialMoment0;
            result.RAfactorialMoment1 = RAfactorialMoment1;
            result.RAfactorialMoment2 = RAfactorialMoment2;
            result.RAfactorialMoment3 = RAfactorialMoment3;
            result.AfactorialMoment0 = AfactorialMoment0;
            result.AfactorialMoment1 = AfactorialMoment1;
            result.AfactorialMoment2 = AfactorialMoment2;
            result.AfactorialMoment3 = AfactorialMoment3;

            //NOTE: in the following calculations,
            //variables named PTxxx refer to "Pulse Triggered" phenomena, and
            //variables named RTxxx refer to "Regularly Triggered" phenomena (such as, fast-background counting)

            //penultimately, use all this to calculate the SDT rates
            double PTsingles, RTsingles, normRAfactorialMoment1, normRAfactorialMoment2;
            double normRAfactorialMomentAlpha1, normRAfactorialMomentBeta2;
            double normAfactorialMoment0, normAfactorialMoment1, normAfactorialMoment2, normAfactorialMoment3;
            double normAfactorialMomentAlpha1, normAfactorialMomentBeta2;

            if (wasFastAccidentals)
            {
                PTsingles = RAfactorialMoment0;
                double gateFactor = numAccidentalGates / Math.Floor(totalMeasurementTime / (multiplicityGateWidth * this.ticSizeInSeconds));
                RTsingles = AfactorialMoment1 / gateFactor;
                normRAfactorialMoment1 = RAfactorialMoment1 / PTsingles;
                normRAfactorialMoment2 = RAfactorialMoment2 / PTsingles;
                //NOT USED:  double normRAfactorialMoment3 = RAfactorialMoment3 / PTsingles;
                normRAfactorialMomentAlpha1 = RAfactorialMomentAlpha1 / PTsingles;
                normRAfactorialMomentBeta2 = RAfactorialMomentBeta2 / PTsingles;
                normAfactorialMoment0 = AfactorialMoment0 / numAccidentalGates;
                normAfactorialMoment1 = AfactorialMoment1 / numAccidentalGates;
                normAfactorialMoment2 = AfactorialMoment2 / numAccidentalGates;
                normAfactorialMoment3 = AfactorialMoment3 / numAccidentalGates;
                normAfactorialMomentAlpha1 = AfactorialMomentAlpha1 / numAccidentalGates;
                normAfactorialMomentBeta2 = AfactorialMomentBeta2 / numAccidentalGates;
            }
            else
            {
                PTsingles = AfactorialMoment0;  //XXX SHOULDN'T THIS BE RAfactorialMoment0 not AfactorialMoment0???, answer, no, the two values should be the same, RA and A of 0 are identical for "slow"
                RTsingles = AfactorialMoment0;
                normRAfactorialMoment1 = RAfactorialMoment1 / PTsingles;
                normRAfactorialMoment2 = RAfactorialMoment2 / PTsingles;
                //NOT USED:  double normRAfactorialMoment3 = RAfactorialMoment3 / PTsingles;
                normRAfactorialMomentAlpha1 = RAfactorialMomentAlpha1 / PTsingles;
                normRAfactorialMomentBeta2 = RAfactorialMomentBeta2 / PTsingles;
                normAfactorialMoment0 = AfactorialMoment0 / RTsingles;
                normAfactorialMoment1 = AfactorialMoment1 / RTsingles;
                normAfactorialMoment2 = AfactorialMoment2 / RTsingles;
                normAfactorialMoment3 = AfactorialMoment3 / RTsingles;
                normAfactorialMomentAlpha1 = AfactorialMomentAlpha1 / RTsingles;
                normAfactorialMomentBeta2 = AfactorialMomentBeta2 / RTsingles;
            }

            double RTdoubles = (0.5 / (multiplicityGateWidth * this.ticSizeInSeconds)) * ((2.0 * normAfactorialMoment2) - Math.Pow(normAfactorialMoment1, 2.0));
            double RTtriples = (0.16667 / (multiplicityGateWidth * this.ticSizeInSeconds))
                               * ((6.0 * normAfactorialMoment3) - (6.0 * normAfactorialMoment1 * normAfactorialMoment2) + (2.0 * Math.Pow(normAfactorialMoment1, 3)));

            double PTdoubles = PTsingles * (normRAfactorialMoment1 - normAfactorialMoment1);
            double PTtriples;
            double PTtriplesDTcoef;
            if (AfactorialMoment0 != 0.0)
            {
                PTtriples = PTsingles * ((normRAfactorialMoment2 - normAfactorialMoment2)
                                       - ((normAfactorialMoment1 / normAfactorialMoment0)
                                          * (normRAfactorialMoment1 - normAfactorialMoment1)));
                PTtriplesDTcoef = PTsingles * ((normRAfactorialMomentBeta2 - normAfactorialMomentBeta2)
                                               - ((normAfactorialMomentAlpha1 / normAfactorialMoment0)
                                                  * (normRAfactorialMomentAlpha1 - normAfactorialMomentAlpha1)));
            }
            else
            {
                PTtriples = 0.0;
                PTtriplesDTcoef = 0.0;
            }

            if (totalMeasurementTime > 1E-12)
            {
                PTsingles /= totalMeasurementTime;
                PTdoubles /= totalMeasurementTime;
                PTtriples /= totalMeasurementTime;
                PTtriplesDTcoef /= totalMeasurementTime;
            }
            else
            {
                PTsingles = 0.0;
                PTdoubles = 0.0;
                PTtriples = 0.0;
                PTtriplesDTcoef = 0.0;
            }

            //store the SDT rates
            result.singlesRatePerSecond = PTsingles;
            result.doublesRatePerSecond = PTdoubles;
            result.triplesRatePerSecond = PTtriples;

            //now that rates are calculated, calculate the dead-time corrections

            // dead time correction coefficients for RT rates (INCC as well as H&C)
            // determined experimentally using D/T ratio - see analysisComparison/triplesDeadTime.xls
            // the best fit (poly3) used to reproduce the trend
            // note: valid only for sources in the range of ~100n/s - ~500,000 n/s
            /** NOT USED ***
            double DTcoeffT0_RT = 3.42854465;
            double DTcoeffT1_RT = 3.35351651E-6;
            double DTcoeffT2_RT = -5.83706327E-12;
            double DTcoeffT3_RT = 2.03604973E-17;
             ***************/

            // dead time correction coefficients for PT rates with background calculated using H&C consecutive gates
            // determined experimentally using D/T ratio - see analysisComparison/triplesDeadTime.xls
            // the best fit (poly3) used to reproduce the trend
            // note: valid only for sources in the range of ~100n/s - ~500,000 n/s
            /** NOT USED ***
            double DTcoeffT0_PT = 2.78760077;
            double DTcoeffT1_PT = 2.86078894E-6;
            double DTcoeffT2_PT = -8.21994836E-12;
            double DTcoeffT3_PT = 9.45195862E-17;
             ***************/

            /** NOT USED ***
            double DTcoeffA_RT = 0.2063;  // these values were determined using two source method
            double DTcoeffB_RT = 0.04256;
             ***************/

            double DTcoeffA = deadTimeCoeffAinMicroSecs;
            double DTcoeffB = deadTimeCoeffBinPicoSecs;
            double DTcoeffC = deadTimeCoeffCinNanoSecs;
            double DTcoeffT = deadTimeCoeffTinNanoSecs;

            double exponent = ((DTcoeffA / 1E6) + ((DTcoeffB / 1E12) * PTsingles)) * PTsingles;
            double PTsinglesDTcorr = PTsingles * Math.Exp(exponent / 4.0);
            double PTdoublesDTcorr = PTdoubles * Math.Exp(exponent);
            double PTtriplesDTcorr = PTtriplesDTcoef * Math.Exp((DTcoeffT / 1E9) * PTsingles);

            /** NOT USED ***
            double RTsinglesDTcorr = RTsingles * Math.Exp(( ((DTcoeffA/1E6) + ((DTcoeffB/1E12)*RTsingles)) *RTsingles)/4.0);
            double RTdoublesDTcorr = RTdoubles * Math.Exp( ((DTcoeffA_RT/1E6) + ((DTcoeffB_RT/1E12)*RTsingles)) *RTsingles);
            double RTtriplesDTcorr = RTtriples* (( (DTcoeffT3_RT*Math.Pow(RTsingles,3)) 
                                                   + (DTcoeffT2_RT*Math.Pow(RTsingles,2)) 
                                                   + (DTcoeffT1_RT*RTsingles)
                                                   + DTcoeffT0_RT)
                                                 /DTcoeffT0_RT); 
             ***************/

            //store the dead-time corrected values
            result.deadTimeCorrectedSinglesRate = PTsinglesDTcorr;
            result.deadTimeCorrectedDoublesRate = PTdoublesDTcorr;
            result.deadTimeCorrectedTriplesRate = PTtriplesDTcorr;

            //Calculate the Dytlewski Dead-Time-Corrected Rates, based upon
            //N. Dytlewski, Dead-time corrections for multiplicity counters,
            //Nuclear Instruments and Methods in Physics Research A305(1991)492-494
            double P03, P02, P13, P12, P23;
            P03 = Math.Pow((1.0 - (2.0 * phi)), 3.0);
            P02 = Math.Pow((1.0 - phi), 2.0);
            P13 = (2.0 * Math.Pow((1.0 - phi), 3.0)) - (2.0 * P03);
            P12 = 1.0 - P02;
            P23 = 1.0 + P03 - (2.0 * Math.Pow((1.0 - phi), 3.0));
            result.dytlewskiDeadTimeCorrectedTriplesRate = PTtriples / P03;
            //Martyn made me do it. hn 2.6.2015
            result.deadTimeCorrectedTriplesRate = result.dytlewskiDeadTimeCorrectedTriplesRate;
            result.dytlewskiDeadTimeCorrectedDoublesRate = (PTdoubles / P02) + ((PTtriples * P13) / (P02 * P03));
            result.dytlewskiDeadTimeCorrectedSinglesRate = PTsingles + ((P12 * PTdoubles) / P02) + (PTtriples * (((P12 * P13) / (P02 * P03)) - (P23 / P03)));

            return (result);
        }
예제 #10
0
파일: BigInt.cs 프로젝트: hnordquist/INCC6
        /// <summary>
        /// Constructs a BigInt from an Int32
        /// </summary>
        /// <param name="input"></param>
        /// <param name="precision"></param>
        public BigInt(Int32 input, PrecisionSpec precision)
        {
            Init(precision);
            if (input < 0)
            {
                sign = true;

                if (input == Int32.MinValue)
                {
                    digitArray[0] = 0x80000000;
                }
                else
                {
                    digitArray[0] = (UInt32)(-input);
                }
            }
            else
            {
                digitArray[0] = ((UInt32)input);
            }
        }
예제 #11
0
파일: BigInt.cs 프로젝트: hnordquist/INCC6
        /// <summary>
        /// Constructs a BigInt from a UInt32
        /// </summary>
        /// <param name="input"></param>
        /// <param name="precision"></param>
        public BigInt(Int64 input, PrecisionSpec precision)
        {
            Init(precision);
            if (input < 0) sign = true;

            digitArray[0] = (UInt32)(input & 0xffffffff);

            if (digitArray.Length >= 2)
            {
                if (input == Int64.MinValue)
                {
                    digitArray[1] = 0x80000000;
                }
                else
                {
                    digitArray[1] = (UInt32)((input >> 32) & 0x7fffffff);
                }
            }
        }
예제 #12
0
파일: BigInt.cs 프로젝트: hnordquist/INCC6
 /// <summary>
 /// Constructs a BigInt from a UInt64
 /// </summary>
 /// <param name="input"></param>
 /// <param name="precision"></param>
 public BigInt(UInt64 input, PrecisionSpec precision)
 {
     Init(precision);
     digitArray[0] = (UInt32)(input & 0xffffffff);
     if (digitArray.Length > 1) digitArray[1] = (UInt32)(input >> 32);
 }
예제 #13
0
파일: BigInt.cs 프로젝트: hnordquist/INCC6
 /// <summary>
 /// Constructs a BigInt from a UInt32
 /// </summary>
 /// <param name="input"></param>
 /// <param name="precision"></param>
 public BigInt(UInt32 input, PrecisionSpec precision)
 {
     Init(precision);
     digitArray[0] = input;
 }
예제 #14
0
파일: BigInt.cs 프로젝트: hnordquist/INCC6
        /// <summary>
        /// Constructs a bigint from the input, matching the new precision provided
        /// </summary>
        public BigInt(BigInt input, PrecisionSpec precision)
        {
            //Casts the input to the new precision.
            Init(precision);
            int Min = (input.digitArray.Length < digitArray.Length) ? input.digitArray.Length : digitArray.Length;

            for (int i = 0; i < Min; i++)
            {
                digitArray[i] = input.digitArray[i];
            }

            sign = input.sign;
        }
예제 #15
0
        private static void CalculateFactorials(int numBits)
        {
            System.Collections.Generic.List<BigFloat> list = new System.Collections.Generic.List<BigFloat>(64);
            System.Collections.Generic.List<BigFloat> list2 = new System.Collections.Generic.List<BigFloat>(64);

            PrecisionSpec extendedPrecision = new PrecisionSpec(numBits + 1, PrecisionSpec.BaseType.BIN);
            PrecisionSpec normalPrecision = new PrecisionSpec(numBits, PrecisionSpec.BaseType.BIN);

            BigFloat factorial = new BigFloat(1, extendedPrecision);
            BigFloat reciprocal;

            //Calculate e while we're at it
            BigFloat e = new BigFloat(1, extendedPrecision);

            list.Add(new BigFloat(factorial, normalPrecision));

            for (int i = 1; i < Int32.MaxValue; i++)
            {
                BigFloat number = new BigFloat(i, extendedPrecision);
                factorial.Mul(number);

                if (factorial.exponent > numBits) break;

                list2.Add(new BigFloat(factorial, normalPrecision));
                reciprocal = factorial.Reciprocal();

                e.Add(reciprocal);
                list.Add(new BigFloat(reciprocal, normalPrecision));
            }

            //Set the cached static values.
            inverseFactorialCache = list.ToArray();
            factorialCache = list2.ToArray();
            invFactorialCutoff = numBits;
            eCache = new BigFloat(e, normalPrecision);
            eRCPCache = new BigFloat(e.Reciprocal(), normalPrecision);
        }
예제 #16
0
        //************************** Conversions *************************

        /// <summary>
        /// Converts a BigFloat to an BigInt with the specified precision
        /// </summary>
        /// <param name="n1">The number to convert</param>
        /// <param name="precision">The precision to convert it with</param>
        /// <param name="round">Do we round the number if we are truncating the mantissa?</param>
        /// <returns></returns>
        public static BigInt ConvertToInt(BigFloat n1, PrecisionSpec precision, bool round)
        {
            BigInt ret = new BigInt(precision);

            int numBits = n1.mantissa.Precision.NumBits;
            int shift = numBits - (n1.exponent + 1);

            BigFloat copy = new BigFloat(n1);
            bool inc = false;

            //Rounding
            if (copy.mantissa.Precision.NumBits > ret.Precision.NumBits)
            {
                inc = true;

                for (int i = copy.exponent + 1; i <= ret.Precision.NumBits; i++)
                {
                    if (copy.mantissa.GetBitFromTop(i) == 0)
                    {
                        inc = false;
                        break;
                    }
                }
            }

            if (shift > 0)
            {
                copy.mantissa.RSH(shift);
            }
            else if (shift < 0)
            {
                copy.mantissa.LSH(-shift);
            }

            ret.Assign(copy.mantissa);

            if (inc) ret.Increment();

            return ret;
        }
예제 #17
0
        private static void CalculateEOnly(int numBits)
        {
            PrecisionSpec extendedPrecision = new PrecisionSpec(numBits + 1, PrecisionSpec.BaseType.BIN);
            PrecisionSpec normalPrecision = new PrecisionSpec(numBits, PrecisionSpec.BaseType.BIN);

            int iExponent = (int)(Math.Sqrt(numBits));

            BigFloat factorial = new BigFloat(1, extendedPrecision);
            BigFloat constant = new BigFloat(1, extendedPrecision);
            constant.exponent -= iExponent;
            BigFloat numerator = new BigFloat(constant);
            BigFloat reciprocal;

            //Calculate the 2^iExponent th root of e
            BigFloat e = new BigFloat(1, extendedPrecision);

            int i;
            for (i = 1; i < Int32.MaxValue; i++)
            {
                BigFloat number = new BigFloat(i, extendedPrecision);
                factorial.Mul(number);
                reciprocal = factorial.Reciprocal();
                reciprocal.Mul(numerator);

                if (-reciprocal.exponent > numBits) break;

                e.Add(reciprocal);
                numerator.Mul(constant);
                System.GC.Collect();
            }

            for (i = 0; i < iExponent; i++)
            {
                numerator.Assign(e);
                e.Mul(numerator);
            }

            //Set the cached static values.
            eCache = new BigFloat(e, normalPrecision);
            eRCPCache = new BigFloat(e.Reciprocal(), normalPrecision);
        }
예제 #18
0
 /// <summary>
 /// Constructs a BigFloat of the required precision
 /// 
 /// Sets the value to zero
 /// </summary>
 /// <param name="mantissaPrec"></param>
 public BigFloat(PrecisionSpec mantissaPrec)
 {
     Init(mantissaPrec);
 }
예제 #19
0
        /// <summary>
        /// Calculates the odd reciprocals of the natural numbers (for atan series)
        /// </summary>
        /// <param name="numBits"></param>
        /// <param name="terms"></param>
        private static void CalculateReciprocals(int numBits, int terms)
        {
            int bits = numBits + 32;
            PrecisionSpec extendedPres = new PrecisionSpec(bits, PrecisionSpec.BaseType.BIN);
            PrecisionSpec normalPres = new PrecisionSpec(numBits, PrecisionSpec.BaseType.BIN);

            System.Collections.Generic.List<BigFloat> list = new System.Collections.Generic.List<BigFloat>(terms);

            for (int i = 0; i < terms; i++)
            {
                BigFloat term = new BigFloat(i*2 + 1, extendedPres);
                list.Add(new BigFloat(term.Reciprocal(), normalPres));
            }

            reciprocals = list.ToArray();
        }
예제 #20
0
        /// <summary>
        /// Constructs a big float from a UInt32 to the required precision
        /// </summary>
        /// <param name="value"></param>
        /// <param name="mantissaPrec"></param>
        public BigFloat(UInt32 value, PrecisionSpec mantissaPrec)
        {
            int mbWords = ((mantissaPrec.NumBits) >> 5);
            if ((mantissaPrec.NumBits & 31) != 0) mbWords++;
            int newManBits = mbWords << 5;

            //For efficiency, we just use a 32-bit exponent
            exponent = 0;

            mantissa = new BigInt(value, new PrecisionSpec(newManBits, PrecisionSpec.BaseType.BIN));
            //scratch = new BigInt(mantissa.Precision);

            int bit = BigInt.GetMSB(value);
            if (bit == -1) return;

            int shift = mantissa.Precision.NumBits - (bit + 1);
            mantissa.LSH(shift);
            exponent = bit;
        }
예제 #21
0
        /// <summary>
        /// Constructs a BigFloat from a 64-bit unsigned integer
        /// </summary>
        /// <param name="value"></param>
        /// <param name="mantissaPrec"></param>
        public BigFloat(UInt64 value, PrecisionSpec mantissaPrec)
        {
            int mbWords = ((mantissaPrec.NumBits) >> 5);
            if ((mantissaPrec.NumBits & 31) != 0) mbWords++;
            int newManBits = mbWords << 5;

            //For efficiency, we just use a 32-bit exponent
            exponent = 0;

            int bit = BigInt.GetMSB(value);

            mantissa = new BigInt(value, new PrecisionSpec(newManBits, PrecisionSpec.BaseType.BIN));
            //scratch = new BigInt(mantissa.Precision);

            int shift = mantissa.Precision.NumBits - (bit + 1);
            if (shift > 0)
            {
                mantissa.LSH(shift);
            }
            else
            {
                mantissa.SetHighDigit((uint)(value >> (-shift)));
            }
            exponent = bit;
        }
예제 #22
0
        private void Exp(int numBits)
        {
            if (IsSpecialValue)
            {
                if (SpecialValue == SpecialValueType.ZERO)
                {
                    //e^0 = 1
                    exponent = 0;
                    mantissa.SetHighDigit(0x80000000);
                }
                else if (SpecialValue == SpecialValueType.INF_MINUS)
                {
                    //e^-inf = 0
                    SetZero();
                }

                return;
            }

            PrecisionSpec prec = new PrecisionSpec(numBits, PrecisionSpec.BaseType.BIN);
            numBits = prec.NumBits;

            if (scratch.Precision.NumBits != prec.NumBits)
            {
                scratch = new BigInt(prec);
            }

            if (inverseFactorialCache == null || invFactorialCutoff < numBits)
            {
                CalculateFactorials(numBits);
            }

            //let x = 1 * 'this'.mantissa (i.e. 1 <= x < 2)
            //exp(2^n * x) = e^(2^n * x) = (e^x)^2n = exp(x)^2n

            int oldExponent = 0;

            if (exponent > -4)
            {
                oldExponent = exponent + 4;
                exponent = -4;
            }

            BigFloat thisSave = new BigFloat(this, prec);
            BigFloat temp = new BigFloat(1, prec);
            BigFloat temp2 = new BigFloat(this, prec);
            BigFloat res = new BigFloat(1, prec);
            int length = inverseFactorialCache.Length;

            int iterations;
            for (int i = 1; i < length; i++)
            {
                //temp = x^i
                temp.Mul(thisSave);
                temp2.Assign(inverseFactorialCache[i]);
                temp2.Mul(temp);

                if (temp2.exponent < -(numBits + 4)) { iterations = i; break; }

                res.Add(temp2);
            }

            //res = exp(x)
            //Now... x^(2^n) = (x^2)^(2^(n - 1))
            for (int i = 0; i < oldExponent; i++)
            {
                res.mantissa.SquareHiFast(scratch);
                int shift = res.mantissa.Normalise();
                res.exponent = res.exponent << 1;
                res.exponent += 1 - shift;
            }

            //Deal with +/- inf
            if (res.exponent == Int32.MaxValue)
            {
                res.mantissa.Zero();
            }

            Assign(res);
        }
예제 #23
0
        /// <summary>
        /// Construct a BigFloat from a double-precision floating point number
        /// </summary>
        /// <param name="value"></param>
        /// <param name="mantissaPrec"></param>
        public BigFloat(double value, PrecisionSpec mantissaPrec)
        {
            if (value == 0.0)
            {
                Init(mantissaPrec);
                return;
            }

            bool sign = (value < 0) ? true : false;

            long bits = BitConverter.DoubleToInt64Bits(value);
            // Note that the shift is sign-extended, hence the test against -1 not 1
            int valueExponent = (int)((bits >> 52) & 0x7ffL);
            long valueMantissa = bits & 0xfffffffffffffL;

            //The mantissa is stored with the top bit implied.
            valueMantissa = valueMantissa | 0x10000000000000L;

            //The exponent is biased by 1023.
            exponent = valueExponent - 1023;

            //Round the number of bits to the nearest word.
            int mbWords = ((mantissaPrec.NumBits) >> 5);
            if ((mantissaPrec.NumBits & 31) != 0) mbWords++;
            int newManBits = mbWords << 5;

            mantissa = new BigInt(new PrecisionSpec(newManBits, PrecisionSpec.BaseType.BIN));
            //scratch = new BigInt(new PrecisionSpec(newManBits, PrecisionSpec.BaseType.BIN));

            if (newManBits >= 64)
            {
                //The mantissa is 53 bits now, so add 11 to put it in the right place.
                mantissa.SetHighDigits(valueMantissa << 11);
            }
            else
            {
                //To get the top word of the mantissa, shift up by 11 and down by 32 = down by 21
                mantissa.SetHighDigit((uint)(valueMantissa >> 21));
            }

            mantissa.Sign = sign;
        }
예제 #24
0
        /// <summary>
        /// Calculates ln(2) and returns -10^(n/2 + a bit) for reuse, using the AGM method as described in
        /// http://lacim.uqam.ca/~plouffe/articles/log2.pdf
        /// </summary>
        /// <param name="numBits"></param>
        /// <returns></returns>
        private static void CalculateLog2(int numBits)
        {
            //Use the AGM method formula to get log2 to N digits.
            //R(a0, b0) = 1 / (1 - Sum(2^-n*(an^2 - bn^2)))
            //log(1/2) = R(1, 10^-n) - R(1, 10^-n/2)
            PrecisionSpec normalPres = new PrecisionSpec(numBits, PrecisionSpec.BaseType.BIN);
            PrecisionSpec extendedPres = new PrecisionSpec(numBits + 1, PrecisionSpec.BaseType.BIN);
            BigFloat a0 = new BigFloat(1, extendedPres);
            BigFloat b0 = TenPow(-(int)((double)((numBits >> 1) + 2) * 0.302), extendedPres);
            BigFloat pow10saved = new BigFloat(b0);
            BigFloat firstAGMcacheSaved = new BigFloat(extendedPres);

            //save power of 10 (in normal precision)
            pow10cache = new BigFloat(b0, normalPres);

            ln2cache = R(a0, b0);

            //save the first half of the log calculation
            firstAGMcache = new BigFloat(ln2cache, normalPres);
            firstAGMcacheSaved.Assign(ln2cache);

            b0.MulPow2(-1);
            ln2cache.Sub(R(a0, b0));

            //Convert to log(2)
            ln2cache.mantissa.Sign = false;

            //Save magic constant for newton log
            //First guess in range 1 <= x < 2 is x0 = ln2 * (x - 1) + C
            logNewtonConstant = new BigFloat(ln2cache);
            logNewtonConstant.Mul(new BigFloat(3, extendedPres));
            logNewtonConstant.exponent--;
            logNewtonConstant.Sub(new BigFloat(1, extendedPres));
            logNewtonConstant = new BigFloat(logNewtonConstant, normalPres);

            //Save the inverse.
            log2ecache = new BigFloat(ln2cache);
            log2ecache = new BigFloat(log2ecache.Reciprocal(), normalPres);

            //Now cache log10
            //Because the log functions call this function to the precision to which they
            //are called, we cannot call them without causing an infinite loop, so we need
            //to inline the code.
            log10recip = new BigFloat(10, extendedPres);

            {
                int power2 = log10recip.exponent + 1;
                log10recip.exponent = -1;

                //BigFloat res = new BigFloat(firstAGMcache);
                BigFloat ax = new BigFloat(1, extendedPres);
                BigFloat bx = new BigFloat(pow10saved);
                bx.Mul(log10recip);

                BigFloat r = R(ax, bx);

                log10recip.Assign(firstAGMcacheSaved);
                log10recip.Sub(r);

                ax.Assign(ln2cache);
                ax.Mul(new BigFloat(power2, log10recip.mantissa.Precision));
                log10recip.Add(ax);
            }

            log10recip = log10recip.Reciprocal();
            log10recip = new BigFloat(log10recip, normalPres);


            //Trim to n bits
            ln2cache = new BigFloat(ln2cache, normalPres);
        }
예제 #25
0
        /// <summary>
        /// Constructs a BigFloat from a string
        /// </summary>
        /// <param name="value"></param>
        /// <param name="mantissaPrec"></param>
        public BigFloat(string value, PrecisionSpec mantissaPrec)
        {
            Init(mantissaPrec);

            PrecisionSpec extendedPres = new PrecisionSpec(mantissa.Precision.NumBits + 1, PrecisionSpec.BaseType.BIN);
            BigFloat ten = new BigFloat(10, extendedPres);
            BigFloat iPart = new BigFloat(extendedPres);
            BigFloat fPart = new BigFloat(extendedPres);
            BigFloat tenRCP = ten.Reciprocal();

            if (value.Contains(System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NaNSymbol))
            {
                SetNaN();
                return;
            }
            else if (value.Contains(System.Globalization.CultureInfo.CurrentCulture.NumberFormat.PositiveInfinitySymbol))
            {
                SetInfPlus();
                return;
            }
            else if (value.Contains(System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NegativeInfinitySymbol))
            {
                SetInfMinus();
                return;
            }

            string decimalpoint = System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator;

            char[] digitChars = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ',', '.' };

            //Read in the integer part up the the decimal point.
            bool sign = false;
            value = value.Trim();

            int i = 0;

            if (value.Length > i && value[i] == '-')
            {
                sign = true;
                i++;
            }

            if (value.Length > i && value[i] == '+')
            {
                i++;
            }

            for ( ; i < value.Length; i++)
            {
                //break on decimal point
                if (value[i] == decimalpoint[0]) break;

                int digit = Array.IndexOf(digitChars, value[i]);
                if (digit < 0) break;

                //Ignore place separators (assumed either , or .)
                if (digit > 9) continue;

                if (i > 0) iPart.Mul(ten);
                iPart.Add(new BigFloat(digit, extendedPres));
            }

            //If we've run out of characters, assign everything and return
            if (i == value.Length)
            {
                iPart.mantissa.Sign = sign;
                exponent = iPart.exponent;
                if (mantissa.AssignHigh(iPart.mantissa)) exponent++;
                return;
            }

            //Assign the characters after the decimal point to fPart
            if (value[i] == '.' && i < value.Length - 1)
            {
                BigFloat RecipToUse = new BigFloat(tenRCP);

                for (i++; i < value.Length; i++)
                {
                    int digit = Array.IndexOf(digitChars, value[i]);
                    if (digit < 0) break;
                    BigFloat temp = new BigFloat(digit, extendedPres);
                    temp.Mul(RecipToUse);
                    RecipToUse.Mul(tenRCP);
                    fPart.Add(temp);
                }
            }

            //If we're run out of characters, add fPart and iPart and return
            if (i == value.Length)
            {
                iPart.Add(fPart);
                iPart.mantissa.Sign = sign;
                exponent = iPart.exponent;
                if (mantissa.AssignHigh(iPart.mantissa)) exponent++;
                return;
            }

            if (value[i] == '+' || value[i] == '-') i++;

            if (i == value.Length)
            {
                iPart.Add(fPart);
                iPart.mantissa.Sign = sign;
                exponent = iPart.exponent;
                if (mantissa.AssignHigh(iPart.mantissa)) exponent++;
                return;
            }

            //Look for exponential notation.
            if ((value[i] == 'e' || value[i] == 'E') && i < value.Length - 1)
            {
                //Convert the exponent to an int.
                int exp;

                try
                {
                    exp = System.Convert.ToInt32(new string(value.ToCharArray(i + 1, value.Length - (i + 1))));
                }
                catch (Exception)
                {
                    iPart.Add(fPart);
                    iPart.mantissa.Sign = sign;
                    exponent = iPart.exponent;
                    if (mantissa.AssignHigh(iPart.mantissa)) exponent++;
                    return;
                }

                //Raise or lower 10 to the power of the exponent
                BigFloat acc = new BigFloat(1, extendedPres);
                BigFloat temp = new BigFloat(1, extendedPres);

                int powerTemp = exp;

                BigFloat multiplierToUse;

                if (exp < 0)
                {
                    multiplierToUse = new BigFloat(tenRCP);
                    powerTemp = -exp;
                }
                else
                {
                    multiplierToUse = new BigFloat(ten);
                }

                //Fast power function
                while (powerTemp != 0)
                {
                    temp.Mul(multiplierToUse);
                    multiplierToUse.Assign(temp);

                    if ((powerTemp & 1) != 0)
                    {
                        acc.Mul(temp);
                    }

                    powerTemp >>= 1;
                }

                iPart.Add(fPart);
                iPart.Mul(acc);
                iPart.mantissa.Sign = sign;
                exponent = iPart.exponent;
                if (mantissa.AssignHigh(iPart.mantissa)) exponent++;

                return;
            }

            iPart.Add(fPart);
            iPart.mantissa.Sign = sign;
            exponent = iPart.exponent;
            if (mantissa.AssignHigh(iPart.mantissa)) exponent++;

        }
예제 #26
0
        private static BigFloat TenPow(int power, PrecisionSpec precision)
        {
            BigFloat acc = new BigFloat(1, precision);
            BigFloat temp = new BigFloat(1, precision);

            int powerTemp = power;

            BigFloat multiplierToUse = new BigFloat(10, precision);

            if (power < 0)
            {
                multiplierToUse = multiplierToUse.Reciprocal();
                powerTemp = -power;
            }

            //Fast power function
            while (powerTemp != 0)
            {
                temp.Mul(multiplierToUse);
                multiplierToUse.Assign(temp);

                if ((powerTemp & 1) != 0)
                {
                    acc.Mul(temp);
                }

                powerTemp >>= 1;
            }

            return acc;
        }
예제 #27
0
        //******************** Mathematical Constants *******************

        /// <summary>
        /// Gets pi to the indicated precision
        /// </summary>
        /// <param name="precision">The precision to perform the calculation to</param>
        /// <returns>pi (the ratio of the area of a circle to its diameter)</returns>
        public static BigFloat GetPi(PrecisionSpec precision)
        {
            if (pi == null || precision.NumBits <= pi.mantissa.Precision.NumBits)
            {
                CalculatePi(precision.NumBits);
            }

            BigFloat ret = new BigFloat (precision);
            ret.Assign(pi);

            return ret;
        }
예제 #28
0
        private static BigFloat R(BigFloat a0, BigFloat b0)
        {
            //Precision extend taken out.
            int bits = a0.mantissa.Precision.NumBits;
            PrecisionSpec extendedPres = new PrecisionSpec(bits, PrecisionSpec.BaseType.BIN);
            BigFloat an = new BigFloat(a0, extendedPres);
            BigFloat bn = new BigFloat(b0, extendedPres);
            BigFloat sum = new BigFloat(extendedPres);
            BigFloat term = new BigFloat(extendedPres);
            BigFloat temp1 = new BigFloat(extendedPres);
            BigFloat one = new BigFloat(1, extendedPres);

            int iteration = 0;

            for (iteration = 0; ; iteration++)
            {
                //Get the sum term for this iteration.
                term.Assign(an);
                term.Mul(an);
                temp1.Assign(bn);
                temp1.Mul(bn);
                //term = an^2 - bn^2
                term.Sub(temp1);
                //term = 2^(n-1) * (an^2 - bn^2)
                term.exponent += iteration - 1;
                sum.Add(term);

                if (term.exponent < -(bits - 8)) break;

                //Calculate the new AGM estimates.
                temp1.Assign(an);
                an.Add(bn);
                //a(n+1) = (an + bn) / 2
                an.MulPow2(-1);

                //b(n+1) = sqrt(an*bn)
                bn.Mul(temp1);
                bn.Sqrt();
            }

            one.Sub(sum);
            one = one.Reciprocal();
            return new BigFloat(one, a0.mantissa.Precision);
        }
예제 #29
0
        /// <summary>
        /// Newton's method reciprocal, fastest for larger precisions over 15,000 bits.
        /// </summary>
        /// <returns>The reciprocal 1/this</returns>
        public BigFloat ReciprocalNewton()
        {
            if (mantissa.IsZero())
            {
                exponent = Int32.MaxValue;
                return null;
            }

            bool oldSign = mantissa.Sign;
            int oldExponent = exponent;

            //Kill exponent for now (will re-institute later)
            exponent = 0;

            bool topBit = mantissa.IsTopBitOnlyBit();

            PrecisionSpec curPrec = new PrecisionSpec(32, PrecisionSpec.BaseType.BIN);

            BigFloat reciprocal = new BigFloat(curPrec);
            BigFloat constant2 = new BigFloat(curPrec);
            BigFloat temp = new BigFloat(curPrec);
            BigFloat thisPrec = new BigFloat(this, curPrec);

            reciprocal.exponent = 1;
            reciprocal.mantissa.SetHighDigit(3129112985u);

            constant2.exponent = 1;
            constant2.mantissa.SetHighDigit(0x80000000u);

            //D is deliberately left negative for all the following operations.
            thisPrec.mantissa.Sign = true;

            //Initial estimate.
            reciprocal.Add(thisPrec);

            //mantissa.Sign = false;

            //Shift down into 0.5 < this < 1 range
            thisPrec.mantissa.RSH(1);

            //Iteration.
            int accuracyBits = 2;
            int mantissaBits = mantissa.Precision.NumBits;

            //Each iteration is a pass of newton's method for RCP.
            //The is a substantial optimisation to be done here...
            //You can double the number of bits for the calculations
            //at each iteration, meaning that the whole process only
            //takes some constant multiplier of the time for the
            //full-scale multiplication.
            while (accuracyBits < mantissaBits)
            {
                //Increase the precision as needed
                if (accuracyBits >= curPrec.NumBits / 2)
                {
                    int newBits = curPrec.NumBits * 2;
                    if (newBits > mantissaBits) newBits = mantissaBits;
                    curPrec = new PrecisionSpec(newBits, PrecisionSpec.BaseType.BIN);

                    reciprocal = new BigFloat(reciprocal, curPrec);

                    constant2 = new BigFloat(curPrec);
                    constant2.exponent = 1;
                    constant2.mantissa.SetHighDigit(0x80000000u);

                    temp = new BigFloat(temp, curPrec);

                    thisPrec = new BigFloat(this, curPrec);
                    thisPrec.mantissa.Sign = true;
                    thisPrec.mantissa.RSH(1);
                }

                //temp = Xn
                temp.exponent = reciprocal.exponent;
                temp.mantissa.Assign(reciprocal.mantissa);
                //temp = -Xn * D
                temp.Mul(thisPrec);
                //temp = -Xn * D + 2 (= 2 - Xn * D)
                temp.Add(constant2);
                //reciprocal = X(n+1) = Xn * (2 - Xn * D)
                reciprocal.Mul(temp);

                accuracyBits *= 2;
            }

            //'reciprocal' is now the reciprocal of the shifted down, zero-exponent mantissa of 'this'
            //Restore the mantissa.
            //mantissa.LSH(1);
            exponent = oldExponent;
            //mantissa.Sign = oldSign;

            if (topBit)
            {
                reciprocal.exponent = -(oldExponent);
            }
            else
            {
                reciprocal.exponent = -(oldExponent + 1);
            }
            reciprocal.mantissa.Sign = oldSign;

            return reciprocal;
        }
예제 #30
0
파일: BigInt.cs 프로젝트: hnordquist/INCC6
 /// <summary>
 /// Constructs a bigint from the string, with the desired precision, using base 10
 /// </summary>
 /// <param name="init"></param>
 /// <param name="precision"></param>
 public BigInt(string init, PrecisionSpec precision)
 {
     InitFromString(init, precision, 10);
 }