/// <summary> /// This method returns the calculated amount of subbatches which is assumed to be the opimum. /// To determine all possible subbatches, the batchsize must be factorized into its primes. /// </summary> /// <param name="keyTranslator"></param> /// <returns></returns> public int GetAmountOfSubbatches(IKeyTranslator keyTranslator) { if (this.keyTranslator != keyTranslator) { //init code: this.keyTranslator = keyTranslator; //Find factors of OpenCL batch size: List <Msieve.Factor> factors = Msieve.TrivialFactorization(keyTranslator.GetOpenCLBatchSize()); amountOfSubbatchesFactors = new List <int>(); foreach (var fac in factors) { for (int i = 0; i < fac.count; i++) { amountOfSubbatchesFactors.Add((int)fac.factor); } } amountOfSubbatches = keyTranslator.GetOpenCLBatchSize(); batchSizeFactors = new List <int>(); DecreaseAmountOfSubbatches(); lastDuration = TimeSpan.MaxValue; optimisticDecrease = false; lastStepIncrease = false; if (openCLMode == 1) //normal load { DecreaseAmountOfSubbatches(); } } return(amountOfSubbatches); }
/// <summary> /// dynamically loads the msieve dll file and sets the callbacks /// </summary> private void initMsieveDLL() { msieveDLL = Msieve.GetMsieveDLL(); msieve = msieveDLL.GetType("Msieve.msieve"); //init msieve with callbacks: MethodInfo initMsieve = msieve.GetMethod("initMsieve"); Object callback_struct = Activator.CreateInstance(msieveDLL.GetType("Msieve.callback_struct")); FieldInfo prepareSievingField = msieveDLL.GetType("Msieve.callback_struct").GetField("prepareSieving"); FieldInfo putTrivialFactorlistField = msieveDLL.GetType("Msieve.callback_struct").GetField("putTrivialFactorlist"); Delegate prepareSievingDel = MulticastDelegate.CreateDelegate(msieveDLL.GetType("Msieve.prepareSievingDelegate"), this, "prepareSieving"); Delegate putTrivialFactorlistDel = MulticastDelegate.CreateDelegate(msieveDLL.GetType("Msieve.putTrivialFactorlistDelegate"), this, "putTrivialFactorlist"); prepareSievingField.SetValue(callback_struct, prepareSievingDel); putTrivialFactorlistField.SetValue(callback_struct, putTrivialFactorlistDel); initMsieve.Invoke(null, new object[1] { callback_struct }); }
public BigInteger[] Solve() { /* Solving a linear equation over a residue class is not so trivial if the modulus is not a prime. * This is because residue classes with a composite modulus is not a field, which means that not all elements * of this ring do have an inverse. * We cope with this problem by factorizing the modulus in its prime factors and solving gauss over them * separately (in the case of p^q (q>1) by using "hensel lifting"). * We can use the chinese remainder theorem to get the solution we need then. * But what happens if we aren't able to factorize the modulus completely, because this is to inefficient? * There is a simple trick to cope with that: * Try the gauss algorithm with the composite modulus. Either you have luck and it works out without a problem * (in this case we can just go on), or the gauss algorithm will have a problem inverting some number. * In the last case, we can search for the gcd of this number and the composite modulus. This gcd is a factor of the modulus, * so that solving the equation helped us finding the factorization. */ FiniteFieldGauss gauss = new FiniteFieldGauss(); HenselLifting hensel = new HenselLifting(); List <Msieve.Factor> modfactors = Msieve.TrivialFactorization(mod); List <KeyValuePair <BigInteger[], Msieve.Factor> > results; //Stores the partial solutions together with their factors bool tryAgain; try { do { results = new List <KeyValuePair <BigInteger[], Msieve.Factor> >(); tryAgain = false; for (int i = 0; i < modfactors.Count; i++) { if (modfactors[i].prime) //mod prime { if (modfactors[i].count == 1) { results.Add(new KeyValuePair <BigInteger[], Msieve.Factor>(gauss.Solve(MatrixCopy(), modfactors[i].factor), modfactors[i])); } else { results.Add(new KeyValuePair <BigInteger[], Msieve.Factor>(hensel.Solve(MatrixCopy(), modfactors[i].factor, modfactors[i].count), modfactors[i])); } } else //mod composite { //Try using gauss: try { BigInteger[] res = gauss.Solve(MatrixCopy(), modfactors[i].factor); results.Add(new KeyValuePair <BigInteger[], Msieve.Factor>(res, modfactors[i])); //Yeah, we had luck :) } catch (NotInvertibleException ex) { //We found a factor of modfactors[i]: BigInteger notInvertible = ex.NotInvertibleNumber; List <Msieve.Factor> morefactors = Msieve.TrivialFactorization(modfactors[i].factor / notInvertible); List <Msieve.Factor> morefactors2 = Msieve.TrivialFactorization(notInvertible); modfactors.RemoveAt(i); ConcatFactorLists(modfactors, morefactors); ConcatFactorLists(modfactors, morefactors2); tryAgain = true; break; } } } } while (tryAgain); } catch (LinearDependentException ex) { //We have to throw away dependent rows and try again later: Array.Sort(ex.RowsToDelete, (a, b) => (b - a)); foreach (int row in ex.RowsToDelete) { matrix.RemoveAt(row); } return(null); } BigInteger[] result = new BigInteger[size]; //"glue" the results together: for (int i = 0; i < size; i++) { List <KeyValuePair <BigInteger, BigInteger> > partSolItem = new List <KeyValuePair <BigInteger, BigInteger> >(); for (int c = 0; c < results.Count; c++) { partSolItem.Add(new KeyValuePair <BigInteger, BigInteger>(results[c].Key[i], BigInteger.Pow(results[c].Value.factor, results[c].Value.count))); } result[i] = CRT(partSolItem); } return(result); }