ext/congruence_solver/congruences.c in congruence_solver-0.4.0 vs ext/congruence_solver/congruences.c in congruence_solver-0.5.0

- old
+ new

@@ -1,35 +1,36 @@ #include "arith_utils.h" #include "prime_gen.h" #include <stdlib.h> #include <stdio.h> -static int * adjust_coeffs_to_mod(int degree, int * coeffs, int mod); -static int * solve_prime_power_congruence(int degree, int coeffs[], int prime, int power); -static int * solve_system_of_order_1_congruence_sets(int numOfSets, int * lengthsOfSets, int ** sets, int mods[]); +static long * adjust_coeffs_to_mod(int degree, long * coeffs, long mod); +static long * solve_prime_power_congruence(int degree, long coeffs[], long prime, int power); +static long * solve_system_of_order_1_congruence_sets(int numOfSets, int * lengthsOfSets, long ** sets, long mods[]); -int chinese_remainder_solution(int numberOfEquations, int scals[], int mods[]){ +long chinese_remainder_solution(int numberOfEquations, long scals[], long mods[]){ int i; - int x = 0; - int m = mods[0]; - int modCoeff; + long long x = 0; + long m = mods[0]; + long modCoeff; for(i=1; i<numberOfEquations; i++){ m *= mods[i]; } for(i=0; i<numberOfEquations; i++){ modCoeff = m/mods[i]; - x += modCoeff*mod_inv(modCoeff % mods[i], mods[i])*scals[i]; + x += (long long) modCoeff*mod_inv(modCoeff % mods[i], mods[i])*scals[i] % m; + x %= m; } return x % m; } -int * adjust_coeffs_to_mod(int degree, int * coeffs, int mod){ - int * adjustedCoeffs = calloc(degree+1, sizeof(int)); +long * adjust_coeffs_to_mod(int degree, long * coeffs, long mod){ + long * adjustedCoeffs = calloc(degree+1, sizeof(long)); int i; for(i = 0; i <= degree; i++){ adjustedCoeffs[i] = coeffs[i] % mod; if(adjustedCoeffs[i] < 0){ @@ -39,23 +40,23 @@ return adjustedCoeffs; } -int * brute_force_congruence(int degree, int coeffs[], int primeMod){ +long * brute_force_congruence(int degree, long coeffs[], long primeMod){ //assumes a prime modulus. split congruences of composite modulus into systems of congrueneces //of prime modulus and/or apply the lifting theorem to make use of this function //solve a0x^n + a1x^n-1... = 0 (mod mod) where n is the order a0, a1, ... are coeffieicients //also assumes positive representation of coeffs - int * adjustedCoeffs = adjust_coeffs_to_mod(degree, coeffs, primeMod); - int * solutionList = calloc(degree+1, sizeof(int)); - int * solutions = solutionList+1; + long * adjustedCoeffs = adjust_coeffs_to_mod(degree, coeffs, primeMod); + long * solutionList = calloc(degree+1, sizeof(long)); + long * solutions = solutionList+1; int numberOfSolutions = 0; - int x; + long x; - - for(x = 0; x < primeMod && numberOfSolutions <= degree; x++){ + #pragma omp parallel for + for(x = 0; x < primeMod; x++){ if(mod_eval_polynomial(degree, adjustedCoeffs, primeMod, x) == 0){ solutions[numberOfSolutions++] = x; } } @@ -65,45 +66,42 @@ return solutionList; } -static int * solve_prime_power_congruence(int funcDegree, int funcCoeffs[], int prime, int power){ - - int * adjustedCoeffs; - - int * baseSolutionList; +static long * solve_prime_power_congruence(int funcDegree, long funcCoeffs[], long prime, int power){ + long * baseSolutionList; int numOfBaseSolutions; - int * baseSolutions; + long * baseSolutions; - int * liftedSolutions; + long * liftedSolutions; int numOfLiftedSolutions; - int coeff; + long coeff; int derivDegree; - int * derivCoeffs; - int deriv; - long int divFunc; + long * derivCoeffs; + long deriv; + long func; int i, j, t; - int currentMod; + long currentMod; if(power == 1){ baseSolutions = brute_force_congruence(funcDegree, funcCoeffs, prime); return baseSolutions; } baseSolutionList = solve_prime_power_congruence(funcDegree, funcCoeffs, prime, power-1); numOfBaseSolutions = *baseSolutionList; baseSolutions = baseSolutionList+1; - liftedSolutions = calloc(prime*numOfBaseSolutions+1, sizeof(int)); + liftedSolutions = calloc(prime*numOfBaseSolutions+1, sizeof(long)); numOfLiftedSolutions = 0; derivDegree = funcDegree-1; - derivCoeffs = calloc(derivDegree+1, sizeof(int)); + derivCoeffs = calloc(derivDegree+1, sizeof(long)); currentMod = prime; for(j = 1; j < power; j++){ currentMod *= prime; } @@ -118,18 +116,18 @@ for(j = 0; j < numOfBaseSolutions; j++){ deriv = mod_eval_polynomial(derivDegree, derivCoeffs, prime, baseSolutions[j]); - divFunc = (eval_polynomial(funcDegree, funcCoeffs, baseSolutions[j]) / (currentMod/prime)) % prime; + func = mod_eval_polynomial(funcDegree, funcCoeffs, currentMod, baseSolutions[j]); if(deriv % prime != 0){ - t = (-divFunc*mod_inv(deriv, prime) % prime) + prime; + t = ((-func / (currentMod/prime))*mod_inv(deriv, currentMod) % prime) + prime; liftedSolutions[++numOfLiftedSolutions] = baseSolutions[j] + t*prime; } - else if(divFunc % prime == 0){ + else if(func == 0){ for(t = 1; t <= prime; t++){ liftedSolutions[++numOfLiftedSolutions] = baseSolutions[j] + t*(currentMod/prime); } } } @@ -142,26 +140,26 @@ return liftedSolutions; } -static int * solve_system_of_order_1_congruence_sets(int numOfSets, int * setLengths, int * * sets, int * mods){ +static long * solve_system_of_order_1_congruence_sets(int numOfSets, int * setLengths, long * * sets, long * mods){ //allocate perumtation array - int * divAry = calloc(numOfSets, sizeof(int)); - int * scalAry = calloc(numOfSets, sizeof(int)); + long * divAry = calloc(numOfSets, sizeof(long)); + long * scalAry = calloc(numOfSets, sizeof(long)); int i, j; int numOfSolutions; - int * solutionAry; - int * dest; + long * solutionAry; + long * dest; int idx; for(i = 0, numOfSolutions = 1; i < numOfSets; i++){ divAry[i] = numOfSolutions; numOfSolutions *= setLengths[i]; } - solutionAry = calloc(numOfSolutions+1, sizeof(int)); + solutionAry = calloc(numOfSolutions+1, sizeof(long)); solutionAry[0] = numOfSolutions; dest = solutionAry+1; for(i = 0; i < numOfSolutions; i++){ for(j = 0; j < numOfSets; j++){ @@ -173,28 +171,28 @@ } return solutionAry; } -int * solve_congruence(int funcDegree, int funcCoeffs[], int mod){ - int * solutionList; +long * solve_congruence(int funcDegree, long funcCoeffs[], long mod){ + long * solutionList; - int * modFactorList = prime_factors(mod); - int numOfModFactors = *modFactorList; - int * modFactors = modFactorList+1; + long * modFactorList = prime_factors(mod); + long numOfModFactors = *modFactorList; + long * modFactors = modFactorList+1; - int * * primePowerSolutions = calloc(numOfModFactors, sizeof(int *)); - int * primePowers = calloc(numOfModFactors, sizeof(int)); + long * * primePowerSolutions = calloc(numOfModFactors, sizeof(long *)); + long * primePowers = calloc(numOfModFactors, sizeof(long)); int * primePowerSolutionLengths = calloc(numOfModFactors, sizeof(int *)); int power; - int i; + int i,j,k; for(i = 0; i < numOfModFactors; i++){ - primePowers[i] = modFactors[i]; + primePowers[i] = modFactors[i]; power = 1; - + while(mod % (primePowers[i]*modFactors[i]) == 0){ primePowers[i] *= modFactors[i]; power++; } @@ -212,16 +210,5 @@ free(primePowers); free(modFactorList); return solutionList; } - -/* -int * solve_system_of_congruences(int numOfFuncs, int * funcDegrees, int ** funcCoeffs, int * mods){ - int i; - int * * funcSolutionSets = calloc(numOfFuncs, sizeof(int *)); - for(i=0; i<numOfFuncs; i++){ - funcSolutionSets[i] = solve_congruence(funcDegrees[i], funcCoeffs[i], mods[i]); - } - return solve_system_of_congruence_sets(numOfFuncs, funcSolutionSets, mods); -} -*/ \ No newline at end of file