Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  cfrac.gi   Sprache: unbekannt

 
#############################################################################
##
#W  cfrac.gi               GAP4 Package `FactInt'                 Stefan Kohl
##
##  This file contains functions for factorization using the
##  Continued Fraction Algorithm (Brillhard-Morrison Algorithm).
##
##  Argument of FactorsCFRAC:
##
##  <n>        the integer to be factored
##
##  The result is returned as a list of the prime factors of <n>.
##
#############################################################################

BindGlobal("CFRACSplit", function (n)

  local Digits,
        Multiplier,FactorBase,FactorBaseSize,MaxFactorBaseEl,pi,sqrt,
        Ai,Bi,Ci,Pi,Aj,Bj,Cj,Pj,Ak,Bk,Ck,Pk,Step,CiBuf,CiFact,
        abort1,abort2,AbortingTime1,AbortingTime2,LargePrimeLimit,
        CollectingInterval,CollectingIntervals,NextCollectionAt,
        Factored,FactoredLarge,LargeFactors,UsableFactors,
        FactoredLargeUsable,RelationsLarge,RelPos,Factorizations,
        RelsFB,RelsLarge,RelsTotal,Progress,Remaining,Required,
        LeftMatrix,RightMatrix,CanonFact,Line,Col,Lines,Cols,
        X,Y,YQuadFactors,FactorsFound,p,DependencyNr,Ready,Result,
        Pair1,Pair2,Fact,q,pos,zero,one,i,j,StartingTime,UsedTime;

  StartingTime := Runtime();

  Digits := LogInt(n,10) + 1;

  Info(IntegerFactorizationInfo,2,"CFRAC for n = ",n);
  Info(IntegerFactorizationInfo,2,"Digits              : ",Digits);

  zero := Zero(GF(2)); one := One(GF(2));
  CollectingIntervals := [1000,2000,5000,10000,20000,50000,100000,200000,
                          500000,1000000];
  CollectingInterval := CollectingIntervals[Minimum(Int(Digits/5),
                                            Length(CollectingIntervals))];
  NextCollectionAt := CollectingInterval;

  # Generate the factor base

  Multiplier := n mod 8; n := n * Multiplier;
  FactorBaseSize := QuoInt(Digits^3,200);
  FactorBase := [-1]; pi := 1;
  for i in [2..FactorBaseSize] do
    repeat
      pi := NextPrimeInt(pi);
    until Legendre(n,pi) = 1;
    FactorBase[i] := pi;
  od;
  MaxFactorBaseEl := FactorBase[FactorBaseSize];
  LargePrimeLimit := MaxFactorBaseEl^2;
  Required        := FactorBaseSize + 20;

  Info(IntegerFactorizationInfo,2,"Size of factor base : ",
                                   FactorBaseSize);
  Info(IntegerFactorizationInfo,3,"\nFactor base : \n",FactorBase,"\n");

  # Some initializations

  Factored := [];
  LargeFactors := []; FactoredLarge := [];
  FactoredLargeUsable := []; RelationsLarge := [];

  sqrt := RootInt(n);

  Aj   := sqrt;
  Bk   := 0; Bj := sqrt;
  Ck   := 1; Cj := n - sqrt^2;
  Pk   := 1; Pj := sqrt;

  Step := 1;

  # Abort Trial Division after dividing Ci by the first <AbortingTime> 
  # primes in the factor base if the the unfactored part after that
  # is larger than <abort>

  abort1        := RootInt(n,12)^5;
  abort2        := RootInt(n,3); 
  AbortingTime1 := Maximum(10,QuoInt(FactorBaseSize,20));
  AbortingTime2 := QuoInt(FactorBaseSize,5);

  # Calculate the continued fraction expansion of the square root of n
  # until there are enough factored Ci's
 
  repeat
    
    # Generate the next set of values of the considered five sequences,
    # especially the next Ci

    Step := Step + 1;
    Ai := QuoInt(sqrt + Bj,Cj);   
    Bi := Ai * Cj - Bj;
    Ci := Ck + Ai * (Bj - Bi);
    Pi := (Pk + Ai * Pj) mod n;

    # Trial divide Ci

    if Step > 100 then
      CiBuf := Ci; 
      if Step mod 2 = 0 then CiFact := [];
                        else CiFact := [-1]; 
      fi;
      for i in [2..AbortingTime1] do
        while CiBuf mod FactorBase[i] = 0 do
          CiBuf := CiBuf/FactorBase[i];
          Add(CiFact,FactorBase[i]);
        od;
      od;
      if CiBuf <= abort1 then
        for i in [AbortingTime1 + 1..AbortingTime2] do
          while CiBuf mod FactorBase[i] = 0 do
            CiBuf := CiBuf/FactorBase[i];
            Add(CiFact,FactorBase[i]);
          od;
        od;
        if CiBuf <= abort2 then
          for i in [AbortingTime2 + 1..FactorBaseSize] do
            while CiBuf mod FactorBase[i] = 0 do
              CiBuf := CiBuf/FactorBase[i];
              Add(CiFact,FactorBase[i]);
            od;
          od;
          if CiBuf < LargePrimeLimit then
            if CiBuf = 1 then
              Add(Factored,[Pi,CiFact]);
            else
              Add(LargeFactors,CiBuf);
              Add(CiFact,CiBuf);
              Add(FactoredLarge,[Pi,CiFact]);
            fi;
          fi;   
        fi;
      fi;
    fi;
    
    # Look for usable factorizations with a large factor

    if Step >= NextCollectionAt
    then

      Info(IntegerFactorizationInfo,3,"");
      Info(IntegerFactorizationInfo,3,
           "Collecting relations with a large factor");

      Sort(LargeFactors);
      UsableFactors := Set(List(Filtered(Collected(LargeFactors),
                                Pair1->Pair1[2] > 1),Pair2->Pair2[1]));
      FactoredLargeUsable := 
      Filtered(FactoredLarge,
               Fact->ForAll(Fact[2],q ->   q <= MaxFactorBaseEl 
                                        or q in UsableFactors));
      Sort(FactoredLargeUsable,
           function(f1,f2)
             return   Intersection(f1[2],UsableFactors)[1]
                    < Intersection(f2[2],UsableFactors)[1];
           end);
      RelationsLarge := []; pos := 1; RelPos := 1;
      while pos < Length(FactoredLargeUsable) do
        if   Intersection(FactoredLargeUsable[pos    ][2],UsableFactors)
           = Intersection(FactoredLargeUsable[pos + 1][2],UsableFactors)
        then
          RelationsLarge[RelPos] := 
          [FactoredLargeUsable[pos][1] * FactoredLargeUsable[pos + 1][1],
           Concatenation(FactoredLargeUsable[pos    ][2],
                         FactoredLargeUsable[pos + 1][2])];
          RelPos := RelPos + 1;
        fi;
        pos := pos + 1;
      od;

      RelsFB    := Length(Factored);
      RelsLarge := Length(RelationsLarge);
      RelsTotal := RelsFB + RelsLarge;
      Remaining := Maximum(0,Required - RelsTotal);
      UsedTime  := Int((Runtime() - StartingTime)/1000);
      Progress  := Minimum(100,Int(100 * RelsTotal/Required));

      if InfoLevel(IntegerFactorizationInfo) < 3 then
        Info(IntegerFactorizationInfo,2,
             "Step ",String(Step,9)," : Factored/FB.: ",String(RelsFB,4),
              ", w. Large Fact.: ",String(RelsLarge,4),
              ", Progress :",String(Progress,3),"%");
      fi;  

      Info(IntegerFactorizationInfo,3,
           "Steps                                          : ",
           String(Step,10));
      Info(IntegerFactorizationInfo,3,
           "Complete factorizations over the factor base   : ",
           String(RelsFB,10));
      Info(IntegerFactorizationInfo,3,
           "Total factorizations with a large prime factor : ",
           String(Length(FactoredLarge),10));
      Info(IntegerFactorizationInfo,3,
           "Relations with a large prime factor            : ",
           String(RelsLarge,10));
      Info(IntegerFactorizationInfo,3,
           "Relations remaining to be found                : ",
           String(Remaining,10));
      Info(IntegerFactorizationInfo,3,
           "Elapsed runtime                                : ",
           String(UsedTime,10)," sec.");
      Info(IntegerFactorizationInfo,3,
           "Progress (relations)                           : ",
           String(Progress,10)," %");
      Info(IntegerFactorizationInfo,3,"");

      NextCollectionAt := NextCollectionAt + CollectingInterval;

    fi;

    Ak := Aj; Bk := Bj; Ck := Cj; Pk := Pj;
    Aj := Ai; Bj := Bi; Cj := Ci; Pj := Pi;   

  until Length(Factored) + Length(RelationsLarge) >= Required;

  # Create exponent matrix

  Info(IntegerFactorizationInfo,2,"Creating the exponent matrix");
  LeftMatrix := []; Cols := FactorBaseSize;
  Factorizations := Concatenation(Factored,RelationsLarge);
  Lines := Length(Factorizations);
  for Line in [1..Lines] do
    LeftMatrix [Line] := ListWithIdenticalEntries(Cols,zero);
    CanonFact := Collected(Factorizations[Line][2]);
    for i in [1..Length(CanonFact)] do
      if   CanonFact[i][2] mod 2 = 1 
      then LeftMatrix[Line]
                     [Position(FactorBase,CanonFact[i][1])] := one;
      fi;
    od;
  od;

  # Do Gaussian Elimination

  Info(IntegerFactorizationInfo,2,
       "Doing Gaussian Elimination, #rows = ",Lines,
       ", #columns = ",Cols);
  RightMatrix := NullspaceMat(LeftMatrix);

  # Calculate X and Y such that X^2 = Y^2 mod n 
  # and check if 1 < gcd(X - Y,n) < n

  Info(IntegerFactorizationInfo,2,"Processing the zero rows"); 
  p := 1; FactorsFound := []; DependencyNr := 1; Line := 1; Ready := false;

  while Line <= Length(RightMatrix) and not Ready do 

    X := 1; Y := 1;
    for Col in [1..Lines] do 
      if   RightMatrix[Line][Col] = one
      then X := X * Factorizations[Col][1] mod n; fi;
    od;
    YQuadFactors := 
    Collected(Concatenation(List(Filtered([1..Lines],
                                          i->RightMatrix[Line][i] = one),
                                 j->Factorizations[j][2])));
    for i in [1..Length(YQuadFactors)] do
      Y := Y * YQuadFactors[i][1]^(YQuadFactors[i][2]/2) mod n;
    od;
    if  (X^2 - Y^2) mod n <> 0 
    then Error("Internal Error : X^2 - Y^2 mod n <> 0"); fi;

    p := Gcd(X - Y,n/Multiplier);

    if not p in [1,n/Multiplier] 
    then 
      Info(IntegerFactorizationInfo,2,
           "Dependency no. ",DependencyNr," yielded factor ",p); 
      Add(FactorsFound,p); FactorsFound := Set(FactorsFound);
      if FactorsTD(n/Multiplier,FactorsFound)[2] = [] 
      then Ready := true; fi;
    else
      Info(IntegerFactorizationInfo,2,
           "Dependency no. ",DependencyNr," yielded no factor"); 
    fi;

    Line         := Line + 1; 
    DependencyNr := DependencyNr + 1;

  od;
  
  if   FactorsFound = []
  then Error("\nSorry, CFRAC has failed ...\n",
             "Perhaps the continued fraction expansion of the square\n",
             "root of the number you attempted to factor has properties\n",
             "disadvantageous for obtaining a factorization\n",
             "with this algorithm, try using the MPQS\n\n"); return [n]; fi;
      
  Result := Flat(FactorsTD(n/Multiplier,FactorsFound));

  Info(IntegerFactorizationInfo,1,"The factors are\n",Result);
  Info(IntegerFactorizationInfo,2,"Digit partition : ",
       List(Result,p -> LogInt(p,10) + 1));
  UsedTime := Runtime() - StartingTime;
  Info(IntegerFactorizationInfo,2,
       "CFRAC runtime : ",TimeToString(UsedTime),"\n");

  return Result;
end);

#############################################################################
##
#F  FactorsCFRAC( <n>, [ <ContinueFromFile>, <PagingDir> ] )
##
InstallGlobalFunction( FactorsCFRAC,

function ( n )

  local  FactorsList, StandardFactorsList, m,
         Ready, Pos, Passno;

  if   not (IsInt(n) and n > 1)
  then Error("Usage : FactorsCFRAC( <n> ), ",
             "where <n> has to be an integer > 1"); fi;

  if   ValueOption("NoPreprocessing") = true 
  then FactorsList := Flat(FactorsTD(n));
  else Info(IntegerFactorizationInfo,2,
            "Doing some preprocessing using Pollard's Rho");
       FactorsList := Flat(FactorsRho(n,1,16,8192)); 
  fi;

  Passno := 0;
  repeat
    Passno := Passno + 1;
    Info(IntegerFactorizationInfo,3,"Pass no. ",Passno);

    StandardFactorsList := [[],[]];
    for m in FactorsList do 
      if IsProbablyPrimeInt(m) then Add(StandardFactorsList[1],m);
                       else Add(StandardFactorsList[2],m); fi;
    od;
    ApplyFactoringMethod(FactorsPowerCheck,[FactorsCFRAC,"FactorsCFRAC"],
                         StandardFactorsList,infinity);
    FactorsList := Flat(StandardFactorsList);

    for Pos in [1..Length(FactorsList)] do 
      if   not IsProbablyPrimeInt(FactorsList[Pos]) 
      then FactorsList[Pos] := CFRACSplit(FactorsList[Pos]); fi;
    od;
    FactorsList := Flat(FactorsList);
    Ready := ForAll(FactorsList,IsProbablyPrimeInt);
  until Ready;

  Sort(FactorsList);
  FactorizationCheck(n,FactorsList);
  return FactorsList;
end);

#############################################################################
##
#E  cfrac.gi . . . . . . . . . . . . . . . . . . . . . . . . . . .  ends here

[ Dauer der Verarbeitung: 0.2 Sekunden  (vorverarbeitet)  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge