internal int SetFromCRTNumber( CRTBase ToSet, ChineseRemainder SetFrom ) { try { if( NumbersArray == null ) throw( new Exception( "Bug: The NumbersArray should have been set up already." )); // ToSet.SetToZero(); // CRTBaseArray[0] is 1. if( SetFrom.GetDigitAt( 0 ) == 1 ) { ToSet.SetToOne(); // 1 times 1 for this base. CRTAccumulateForBaseMultiples.SetToOne(); } else { ToSet.SetToZero(); CRTAccumulateForBaseMultiples.SetToZero(); } int HighestNonZeroDigit = 1; // Count starts at 1, so it's at the prime 3. for( int Count = 1; Count < ChineseRemainder.DigitsArraySize; Count++ ) { int Prime = (int)IntMath.GetPrimeAt( Count ); int AccumulateDigit = CRTAccumulateForBaseMultiples.GetDigitAt( Count ); int CRTInputTestDigit = SetFrom.GetDigitAt( Count ); int BaseDigit = CRTBaseArray[Count].GetDigitAt( Count ); if( BaseDigit == 0 ) throw( new Exception( "This never happens. BaseDigit == 0." )); int BaseMult = CRTInputTestDigit; if( BaseMult < AccumulateDigit ) BaseMult += Prime; BaseMult -= AccumulateDigit; int Inverse = MultInverseArray[Count, BaseDigit]; BaseMult = (BaseMult * Inverse) % Prime; ToSet.SetDigitAt( BaseMult, Count ); if( BaseMult != 0 ) HighestNonZeroDigit = Count; // Notice that this is using CRTBaseArray and not // CRTBaseModArray. // This would be very fast in parallel hardware, // but not in software that has to do each digit // one at a time. CRTAccumulatePart.Copy( CRTBaseArray[Count] ); CRTAccumulatePart.Multiply( NumbersArray[BaseMult] ); CRTAccumulateForBaseMultiples.Add( CRTAccumulatePart ); } return HighestNonZeroDigit; } catch( Exception Except ) { throw( new Exception( "Exception in SetFromCRTNumber(): " + Except.Message )); } }