Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/GAP/lib/   (Algebra von RWTH Aachen Version 4.15.1©)  Datei vom 18.9.2025 mit Größe 58 kB image not shown  

Quelle  integer.gi   Sprache: unbekannt

 
Spracherkennung für: .gi vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

#############################################################################
##
##  This file is part of GAP, a system for computational discrete algebra.
##  This file's authors include Thomas Breuer, Frank Celler, Stefan Kohl, Werner Nickel, Alice Niemeyer, Martin Schönert, Alex Wegner.
##
##  Copyright of GAP belongs to its developers, whose names are too numerous
##  to list here. Please refer to the COPYRIGHT file for details.
##
##  SPDX-License-Identifier: GPL-2.0-or-later
##


#############################################################################
##
#V  Integers  . . . . . . . . . . . . . . . . . . . . .  ring of the integers
##
BindGlobal( "Integers", Objectify( NewType(
    CollectionsFamily( CyclotomicsFamily ),
    IsIntegers and IsAttributeStoringRep ),
    rec() ) );

SetName( Integers, "Integers" );
SetString( Integers, "Integers" );
SetIsLeftActedOnByDivisionRing( Integers, false );
SetSize( Integers, infinity );
SetLeftActingDomain( Integers, Integers );
SetGeneratorsOfRing( Integers, [ 1 ] );
SetGeneratorsOfLeftModule( Integers, [ 1 ] );
SetIsFinitelyGeneratedMagma( Integers, false );
SetIsFiniteDimensional( Integers, true );
SetUnits( Integers, [ -11 ] );
SetIsWholeFamily( Integers, false );


#############################################################################
##
#V  NonnegativeIntegers . . . . . . . . . .  semiring of nonnegative integers
##
BindGlobal( "NonnegativeIntegers", Objectify( NewType(
    CollectionsFamily( CyclotomicsFamily ),
    IsNonnegativeIntegers and IsAttributeStoringRep ),
    rec() ) );

SetName( NonnegativeIntegers, "NonnegativeIntegers" );
SetString( NonnegativeIntegers, "NonnegativeIntegers" );
SetSize( NonnegativeIntegers, infinity );
SetGeneratorsOfSemiringWithZero( NonnegativeIntegers, [ 1 ] );
SetGeneratorsOfAdditiveMagmaWithZero( NonnegativeIntegers, [ 1 ] );
SetIsFinitelyGeneratedMagma( NonnegativeIntegers, false );
SetRepresentativeSmallest( NonnegativeIntegers, 0 );
SetIsWholeFamily( NonnegativeIntegers, false );


#############################################################################
##
#V  PositiveIntegers  . . . . . . . . . . . . . semiring of positive integers
##
BindGlobal( "PositiveIntegers", Objectify( NewType(
    CollectionsFamily( CyclotomicsFamily ),
    IsPositiveIntegers and IsAttributeStoringRep ),
    rec() ) );

SetName( PositiveIntegers, "PositiveIntegers" );
SetString( PositiveIntegers, "PositiveIntegers" );
SetSize( PositiveIntegers, infinity );
SetGeneratorsOfSemiring( PositiveIntegers, [ 1 ] );
SetGeneratorsOfAdditiveMagma( PositiveIntegers, [ 1 ] );
SetIsFinitelyGeneratedMagma( PositiveIntegers, false );
SetRepresentativeSmallest( PositiveIntegers, 1 );
SetIsWholeFamily( PositiveIntegers, false );


#############################################################################
##
#R  IsCanonicalBasisIntegersRep
##
DeclareRepresentation(
    "IsCanonicalBasisIntegersRep",
    IsAttributeStoringRep,
    [] );
#T is this needed at all?


#############################################################################
##
#M  Basis( Integers )
##
InstallMethod( Basis,
    "for integers (delegate to `CanonicalBasis')",
    [ IsIntegers ], CANONICAL_BASIS_FLAGS,
    CanonicalBasis );


#############################################################################
##
#M  CanonicalBasis( Integers )
##
InstallMethod( CanonicalBasis,
    "for Integers",
    true,
    [ IsIntegers ], 0,
    function( Integers )
    local B;
    B:= Objectify( NewType( FamilyObj( Integers ),
                                IsFiniteBasisDefault
                            and IsCanonicalBasis
                            and IsCanonicalBasisIntegersRep ),
                   rec() );
    SetUnderlyingLeftModule( B, Integers );
    SetBasisVectors( B, [ 1 ] );

    return B;
    end );

InstallMethod( Coefficients,
    "for the canonical basis of Integers",
    IsCollsElms,
    [ IsBasis and IsCanonicalBasis and IsCanonicalBasisIntegersRep,
      IsCyc ], 0,
    function( B, v )
    if IsInt( v ) then
      return [ v ];
    else
      return fail;
    fi;
    end );


#############################################################################
##
#V  Primes  . . . . . . . . . . . . . . . . . . . . . .  list of small primes
##
BindGlobal( "Primes",
  [   2,  3,  5,  71113171923293137414347535961,
     67717379838997,101,103,107,109,113,127,131,137,139,149,151,
    157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,
    257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,
    367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,
    467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,
    599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,
    709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,
    829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,
    967,971,977,983,991,997 ] );
MakeImmutable( Primes );


#############################################################################
##
#V  Primes2 . . . . . . . . . . . . . . . . . . . . . . additional prime list
#V  ProbablePrimes2 . . . . . . . . . . . . . . . . . . additional prime list
##
##  Some primes in `Primes2' are taken from the tables of Richard Brent,
##  which are available at
##  ftp://ftp.comlab.ox.ac.uk/pub/Documents/techpapers/Richard.Brent/factors/
##
##  More factors of cyclotomic numbers are now available via the FactInt
##  package. This should be cleaned up.
##
InstallFlushableValue( Primes2, [
10047871105672011074634112112549121281311220703112323587,
12553493128659271309792713264529134734331382150313960201,
14092193145979591521660115790321160185071883700120381027,
20394401205151112051590921207101215233612225337722366891,
22996651238500612578108326295457283250712887884729010221,
29247661294230412986645132234893325080613685510941540861,
42521761432495894497511347392381477633614854412148912491,
49105547498928515145756155527473564096435673787359302051,
59361349595839676081600162020897635124376562875169566521,
750689937606618185280581935072479665672397685839,
106431697107367629109688713110211473112901153119782433127540261,
134818753134927809136151713147300841155072369160465489164511353,
177237331183794551184481113190295821190771747193707721195019441,
202029703206244761212601841212885833228511817231769777234750601,
272010961280314943283763713297315901305175781308761441319020217,
359390389407865361420778751424256201432853009457315063466344409,
510810301515717329527093491529510939536903681540701761550413361,
603926681616318177632133361715827883724487149745988807763539787,
815702161834019001852133201857643277879399649909139159,
100152317910367455311065264019110613148911693821271390636259,
150341832115270074111636258751164451264117438311691824179209,
182472604118269343011866013003199041514921273575272127431041,
214748364722382362492316281689241394128924817915132550183799,
257674320726640970312767631689290311032129315424173021012311,
315852810131733896013357897971365212084740115863074058036683,
427825536143755782714562284561464991940146989322814795973261,
488516812959605557496622733113663027472368097109096860024417,
706856925771514597017484047069768554236978301182977866608083,
820947537788314186979598959833,
108797336111136876506311898664849124470026771345580977113564461457,
138411695531397196997114425532687150858128531576803314315888756269,
160550564831614816840117056050293171540944811718912870319707683773,
224347448892314047153723535794707241275523212519477353125480398173,
258296917072599473610927669118297279899417292808621160730327152671,
329527998013305780695935532364099399401322414387203884945076044553,
470721396175015093310154410972897566259983535677035086960726444167,
610708176016298304836765247271367692385185397084540935176831835389,
771586739297719284496178009515593839603853898695069661987423871753,
8895988248199810171997,
115868130379125096112091127522693159128011456717128653413121,
129924628343131105292137152587500001158822951431159248456569,
164504919713165768537521168749965921213657222007229890275929,
241931001601269089806001282429005041301077652751332207361361,
368592716837374857981681386478495679392038110671402011881627,
441019876741447600088289461587317509487824887233531968664833,
555915824341593554036769598761682261641625222857654652168021,
761838257287810221830361840139875599918585913061,
10303309382091047623475541111349113976711338367304011273880539247,
12842974007231408429185797153417994785116287449483291654058017289,
17592177655811856458657451209830381260124543350075292481357870461,
25497555429472663568851051273803919170928793479028172932031007403,
31384266051613203431780337342116949636137402219812314363953127297,
44326767985934446437759531453416674040349818576979375625767248687,
60908173237636493405343627671310318289967403393106417432339208719,
80905944342318157179360521873748125673988680508807099361973132609,
94689400044499857737155463,
10052678938039109796071794231395259814848115798461357509,
15919793462773171758657895971815820981315122125996444329,
22542470482159227356329345612316103756293723792163643711,
24517014940753245874111562812805981076243329078814248401,
31280679788951314798233967573268847079819733232924804801,
42272797713043444792103680014592015338486749971617830801,
57583418699431629111304775216728042131072170601370627701,
71316922984999831816523046098962082537460194404837727799,
95052547721497,
110133112994711140737471578113145295143558111150224123975857,
160026187716961204064664440913205367807127911242099935645987,
270547105429567303567967057423332584516519201434502978835771,
475384700124973500805747488153520518327319589560088668384411,
608459012088799637265428480297643170158708221707179356161321,
866802946161469926510094425921990643452963163,
1034150930241911106681813286820711206485768180411357105535093947,
1416258521793067158785569799279116114798915198071628413557556843,
1900857799450121195842349443359121343873686104172646507710984041,
2649263870814793275213592092965128642261252093693208002856867129,
4557772677741827488998884004774354205069471927096957533874046531,
94603753369773619472026608675509,
11264087821629961125576129563323131372281674952271114436295738510501,
18584774046020617186242754184456012098620782556558121180247636732981,
22666879066355177271453650526294493223336838552965339392783590192547,
46329453543600481505447028499293775950942968789000160081451169922001,
70084436712553223763941482182035597700113943448007379787519018560501,
96076791871613611,
133088039373662309144542918285300809145171177264407947,
153560376376050799166003607842448777177722253954175633,
196915704073465747316825425410373433341117531003194129,
380808546861411923489769993189671059538953023961943033,
581283643249112959617886851384381281625552508473588471,
645654335737185721646675035253258729658812288653553079,
768614336404564651862970652262943171909456847814334401,
110087601836488372111958573678532171091245576402371959291,
179591803874107062721925370622711786412305843009213693951,
231258184156281384124612435767138695572615418118891695851,
269161427404003660130113474796142491313358335487319458201,
342109341751011454336023720109092608613747607031112307667,
399908827939946440947108831688795060015079304643216687969,
555991731585017917357821721134009907376106505825833677713,
611590904484145462992136240845359890319520972806333758431,
105277431818882609811480860771531578248118446744069414584321,
268314230360653526113203221559649643556934563155350221618511,
362304545701296757215852312322168839267960912916512835721519,
820642418486342694078665626856628218315187274497124602996457,
105668621839502584913157571957584602258799162715052426691233701,
172827552198815888791195489390796456327201240031591394168814433,
266834785363181152127344120456368919234899358475907408445923469,
846041103974872866961,
251954534234933118314336585247384551319512233793685967117002179453,
397665642994143859039354390421836002042901598198241112969626815581,
116003218789169220534911281243223830200998593717551032119981679046729,
184896053147409877659132766528309169597727520142437717969530394595211,
579126141132756490877216165444023324834061655963681511996418550459487,
105293313660391861035901155285743288572277679887201487636602438195784363,
231669654363683130095909235169662395069356312233402488219476647465854701,
535347624791488552837151604088623657497125653141870035986098720987332873,
950996059627210897943351,
14129004791086549320244391431185706701868962383741,
20475722306573387515750512048568835297380486760231,
27416723625287255350687273042645634792541312037847,
37456038120071661168316434362139336229068656094783,
48053451094923157679814015042939439565996049162197,
72890883833882536644374338235109336690846723986161,
96806477905685890863555599768997162071483134919121,
9842332430037465033595921,
1105303606504929475345963911735415506748076408140121,
1384260723582848564576639317499733663152976533452519,
2627370184401531914482791775582488424179347083438319,
88040095945103834627376781,
100641220283951395639601683140194179307171898833699259,
207617485544258392970753527291280009243618888211558641,
303309617049998388989376043354639323684545612988577649,
618970019642690137449562111913242407367610843676812931,
72226052281055362027576069697248808599285760001152755641,
81705090114313634085681503698206973609150536446402438593,
9080418348371887359375390001,
1473226532114531733135328238315403468930064931175264655869,
1557224490018252877722580844918806327041824690595747113889,
2128362003321762953917879936137201708625305146303973352041,
4253465609158326804591565471948845962828028421155731228333,
123876132205208335762278423601134304196845099262572814573351,
172974812463239310024750410929217648180992721729506406538251,
227376585863531112677002031251,
17863938783631642278582702102792598696228942460402343442913969,
26439999176607287878083969888493340762283952395329506327023033,
5465713352000770660547109750601,
2887019425066220321043711661276970722308812401674174993533367023,
7895808769460932143966013189963188262612316754526107621113329689,
162259276829213363391578010288127163537220852725398851434325720959,
177635683940025046467781066894531,
26798951577838628146900274941449913754733257489862401973357979128773,
52830129037701966313838210461017075457586804596062091175455674392801,
1005201175737082903354093202182516111419697846380955982026777206637491,
38904276017035188056372051839841219,
19146624498137276606805303260645919077923871097285295625344647665764672671,
9519524151770349914726200576714027279,
10350794431055162386718619237468234569,
170141183460469231731687303715884105727,
1056836588644853738704557482552056406147,
6918082374901313855125397665325977135579,
235335702141939072378977155172505285655211,
360426336941693434048414944508078750920763,
1032670816743843860998850056278950666491537,
1461808298382111034194027645506019619578037,
79638304766856507377778616296087448490695649,
169002145064468556765676975247413756542145739,
8166146875847876762859119015147004762656450569,
18607929421228039083223253529869111644362732899,
33083146850190391025301565142735000331370209599,
138497973518827432485604572537024087153816681041,
673267426712748387612994804392183645147042355211,
1489459109360039866456940197095433721664951999121,
4884164093883941177660049098586324302977543600799,
466345922275629775763320748688970211803553256223529,
26828803997912886929710867041891989490486893845712448833,
153159805660301568024613754993807288151489686913246436306439,
1051153199500053598403188407217590190707671147285551702341089650185945215953
] );
IsSSortedList( Primes2 );
# for 41^41-1
ADD_SET(Primes2, 5926187589691497537793497756719);
# for 89^89-1
ADD_SET(Primes2, 4330075309599657322634371042967428373533799534566765522517);
# for 97^97-1
ADD_SET(Primes2, 549180361199324724418373466271912931710271534073773);
ADD_SET(Primes2,  85411410016592864938535742262164288660754818699519364051241927961077872028620787589587608357877);

InstallFlushableValue(ProbablePrimes2, []);
IsSSortedList( ProbablePrimes2 );

if IsHPCGAP then
  ShareSpecialObj(Primes2);
  ShareSpecialObj(ProbablePrimes2);
fi;


#############################################################################
##
#F  BestQuoInt( <n>, <m> )
##
##  `BestQuoInt' returns the best quotient <q> of the integers  <n> and  <m>.
##  This is the quotient such that `<n>-<q>\*<m>' has minimal absolute value.
##  If there are two quotients whose remainders have the same absolute value,
##  then the quotient with the smaller absolute value is chosen.
##
InstallGlobalFunction(BestQuoInt,function ( n, m )
    if   0 <= m  and 0 <= n  then
        return QuoInt( n + QuoInt( m - 12 ), m );
    elif 0 <= m  then
        return QuoInt( n - QuoInt( m - 12 ), m );
    elif 0 <= n  then
        return QuoInt( n - QuoInt( m + 12 ), m );
    else
        return QuoInt( n + QuoInt( m + 12 ), m );
    fi;
end);


#############################################################################
##
#F  ChineseRem( <moduli>, <residues> )  . . . . . . . . . . chinese remainder
##
InstallGlobalFunction(ChineseRem,function ( moduli, residues )
    local   i, c, l, g;

    # combine the residues modulo the moduli
    i := 1;
    c := residues[1];
    l := moduli[1];
    while i < Length(moduli)  do
        i := i + 1;
        g := Gcdex( l, moduli[i] );
        if g.gcd <> 1  and (residues[i]-c) mod g.gcd <> 0  then
            Error("the residues must be equal modulo ",g.gcd);
        fi;
        c := l * (((residues[i]-c) / g.gcd * g.coeff1) mod moduli[i]) + c;
        l := moduli[i] / g.gcd * l;
    od;

    # reduce c into the range [0..l-1]
    c := c mod l;
    return c;
end);


#############################################################################
##
#F  CoefficientsQadic( <i>, <q> ) . . . . . .  <q>-adic representation of <i>
##
InstallMethod( CoefficientsQadic, "for two integers",
    true, [ IsInt, IsInt ], 0,
function( i, q )
    local i1, res, l, qq, i2;
    if q <= 1 then
        Error("2nd argument of CoefficientsQadic should be greater than 1\n");
    fi;
    if i < 0 then
        # if FR package is loaded and supplies an implementation
        # to return a periodic list for negative i
        TryNextMethod();
    fi;
    # represent the integer <i> as <q>-adic number
    if i = 0 then
        return [];
    elif i < q then
        return [i];
    elif i < q^2 then
        i1 := QuoInt(i, q);
        return [i - i1*q, i1];
    elif Log2Int(q)*100 > Log2Int(i) then
        # straight forward loop for result length < 100
        res := [];
        while i > 0 do
          i1 := QuoInt(i, q);
          Add(res, i - i1*q);
          i := i1;
        od;
    else
        # divide and conquer method for large i
        l := QuoInt(LogInt(i, q), 2)+1;
        qq := q^l;
        i2 := QuoInt(i,qq);
        i1 := i - i2*qq;
        res := CoefficientsQadic(i1, q);
        while Length(res) < l do
          Add(res, 0);
        od;
        Append(res, CoefficientsQadic(i2, q));
    fi;
    return res;
end);


#############################################################################
##
#F CoefficientsMultiadic( ints, int )
##
InstallGlobalFunction(CoefficientsMultiadic, function( ints, int )
    local vec, i;
    vec := List( ints, x -> 0 );
    for i in Reversed( [1..Length(ints)] ) do
        vec[i] := RemInt( int, ints[i] );
        int := QuoInt( int, ints[i] );
    od;
    return vec;
end);


#############################################################################
##
#F  DivisorsInt( <n> )  . . . . . . . . . . . . . . .  divisors of an integer
##
BindGlobal("DivisorsIntCache",
List([[1],[1,2],[1,3],[1,2,4],[1,5],[1,2,3,6],[1,7]], Immutable));
if IsHPCGAP then
  MakeImmutable(DivisorsIntCache);
fi;

InstallGlobalFunction(DivisorsInt,function ( n )
    local  divisors, factors, divs;

    # make <n> it nonnegative, handle trivial cases, and get prime factors
    if n < 0  then n := -n;  fi;
    if n = 0  then Error("DivisorsInt: <n> must not be 0");  fi;
    if n <= Length(DivisorsIntCache)  then
        return DivisorsIntCache[n];
    fi;
    factors := Factors(Integers, n );

    # recursive function to compute the divisors
    divs := function ( i, m )
        if Length(factors) < i     then return [ m ];
        elif m mod factors[i] = 0  then return divs(i+1,m*factors[i]);
        else return Concatenation( divs(i+1,m), divs(i+1,m*factors[i]) );
        fi;
    end;

    divisors := divs( 11 );
    Sort( divisors );
    return Immutable(divisors);
end);


#############################################################################
##
#F  FactorsRho( <n>, <inc>, <cluster>, <limit> )   Pollards rho factorization
##
##  `FactorsInt' does trial divisions by the primes less than 1000 to  detect
##  all composites with a factor less than 1000 and primes less than 1000000.
##  After that it calls `FactorsRho(<n>,1,16,8192)' to do the hard work.
##
##  `FactorsRho'  will  return a  list  of factors   and a list  of composite
##  number.   Usually  `FactorsInt'  factors  integers  with   prime  factors
##  $\<1000$ faster.     However  for   integers  with  no   factor  $\<1000$
##  `FactorsRho' will be faster.
##
##  `FactorsRho' uses Pollards $\rho$ method to factor the integer $n = p q$.
##  For a small simple example lets assume we want to factor $667 = 23 * 29$.
##  `FactorsRho' first calls `IsPrimeInt' to avoid trying to factor a prime.
##
##  Then it uses the sequence defined by  $x_0=1, x_{i+1}=(x_i^2+1)$ mod $n$.
##  In our example this is $125261010119712436630, .. $.
##
##  Modulo $p$ it takes on at most $p-1$ different values, thus it eventually
##  becomes recurrent, usually this happens after roughly $2 \sqrt{p}$ steps.
##  In our example modulo 23 we get $1253109139139, .. $.
##
##  Thus there exist pairs $i, j$ such that $x_i = x_j$ mod $p$,  i.e.,  such
##  that $p$ divides $Gcd( n, x_j-x_i )$.  With a bit of luck no other factor
##  of $n$ divides $x_j - x_i$ so we find $p$ if we know such a pair.  In our
##  example $57$ is the first pair, $x_7-x_5=23$, and $Gcd(667,23) = 23$.
##
##  Now it is too expensive to check all pairs, but there also must be  pairs
##  of the form $2^i-1, j$ with $3*2^{i-1} <= j < 4*2^{i-1}$.  In our example
##  $713$ is the first such pair, $x_13-x_7=506$, and $Gcd(667,506) = 23$.
##
##  Thus by taking the gcds of $n$ and $x_j-x_i$ for such pairs, we will find
##  the factor $p$ after approximately $2 \sqrt{p} \<= 2 \sqrt^4{n}$ steps.
##
##  If $Gcd( n, x_j - x_i )$  is not a prime `FactorsRho'  will  call  itself
##  recursively with a different value for <inc>, i.e., it will try to factor
##  the gcd using a different sequence $x_{i+1} = (x_i^2 + inc)$ mod $n$.
##
##  Since the gcd computations are by far the most time consuming part of the
##  algorithm  one can save time by  clustering differences and computing the
##  gcd  only every <cluster>  iteration.  This slightly increases the chance
##  that a gcd is composite, but reduces the runtime by a large amount.
##
##  Finally `FactorsRho' accepts an argument <limit>  which is the number  of
##  iterations  performed by `FactorsRho' before giving up. The default value
##  is  8192  which corresponds to a few minutes  while guaranteeing that all
##  prime factors less than $10^6$ and most less than $10^9$ are found.
##
##  Better descriptions of the algorithm and related topics can be found  in:
##  J. Pollard, A Monte Carlo Method for Factorization, BIT 151975331-334
##  R. Brent, An Improved Monte Carlo Method for Fact., BIT 201980176-184
##  D. Knuth, Seminumerical Algorithms  (TACP II),  AddiWesl,  1973,  369-371
##
DeclareGlobalName( "FactorsRho" );
BindGlobal( "FactorsRho", function ( n, inc, cluster, limit )

    local   i,  sign,  factors,  composite,  x,  y,  k,  z,  g,  tmp,
            IsPrimeOrProbablyPrimeInt;

    # make $n$ positive and handle trivial cases
    sign := 1;
    if n < 0  then sign := -sign;  n := -n;  fi;
    if n < 4  then return [ [ sign * n ], [] ];  fi;
    factors   := [];
    composite := [];
    while n mod 2 = 0  do Add( factors, 2 );  n := n / 2;  od;
    while n mod 3 = 0  do Add( factors, 3 );  n := n / 3;  od;

    if   ValueOption("UseProbabilisticPrimalityTest") = true
    then IsPrimeOrProbablyPrimeInt := IsProbablyPrimeInt;
    else IsPrimeOrProbablyPrimeInt := IsPrimeInt; fi;

    if IsPrimeOrProbablyPrimeInt(n)  then Add( factors, n );  n := 1;  fi;

    # initialize $x_0$
    x := 1;  z := 1;  i := 0;

    # loop until we have factored $n$ completely or run out of patience
    while 1 < n  and 2^i <= limit  do

        # $y = x_{2^i-1}$
        y := x;  i := i + 1;

        # $x_{2^i}, .., x_{3*2^{i-1}-1}$ need not be compared to $x_{2^i-1}$
        for k  in [1..2^(i-1)]  do
            x := (x^2 + inc) mod n;
        od;

        # compare $x_{3*2^{i-1}}, .., x_{4*2^{i-1}-1}$ with $x_{2^i-1}$
        for k  in [1..2^(i-1)]  do
            x := (x^2 + inc) mod n;
            z := z * (x - y) mod n;

            # from time to time compute the gcd
            if k mod cluster = 0  then
                g := GcdInt( n, z );

                # if it is > 1 we have found a factor which need not be prime
                if g > 1  then
                    tmp := FactorsRho(g,inc+1,QuoInt(cluster+1,2),limit);
                    factors   := Concatenation( factors,   tmp[1] );
                    composite := Concatenation( composite, tmp[2] );

                    n := n / g;
                    if IsPrimeOrProbablyPrimeInt(n)  then
                        Add( factors, n );  n := 1;
                    fi;
                fi;
            fi;
        od;
    od;

    # add <n> to the list of composite numbers
    if 1 < n  then
        Add( composite, n );
    fi;

    # sort the list of factors and composite numbers and return it
    Sort(factors);
    Sort(composite);
    if 0 < Length(factors)  then
        factors[1] := sign * factors[1];
    else
        composite[1] := sign * composite[1];
    fi;
    return [ factors, composite ];

end );


#############################################################################
##
#F  FactorsInt( <n> ) . . . . . . . . . . . . . . prime factors of an integer
#F  FactorsInt( <n> : RhoTrials := <trials>)
#F  FactorsInt( <n> : quiet)
##
##  In the second form, FactorsRho is called with a limit of <trials>
##  on the number of trials is performs. The  default is 8192.
##
##  The option `quiet' makes the function return even if the `rho'
##  factorization failed and return the factorization found so far.
##
InstallGlobalFunction(FactorsInt,function ( n )

    local  sign,  factors,  p,  tmp, n_orig, len, rt, tmp2;

    n_orig := n;

    # make $n$ positive and handle trivial cases
    sign := 1;
    if n < 0  then sign := -sign;  n := -n;  fi;
    if n < 4  then return [ sign * n ];  fi;
    factors := [];

    # do trial divisions by the primes less than 1000
    # faster than anything fancier because $n$ mod <small int> is very fast
    for p  in Primes  do
        while n mod p = 0  do Add( factors, p );  n := n / p;  od;
        if n < (p+1)^2 and 1 < n  then Add(factors,n);  n := 1;  fi;
        if n = 1  then factors[1] := sign*factors[1];  return factors;  fi;
    od;

    # do trial divisions by known primes
    atomic readonly Primes2 do
    for p  in Primes2  do
        while n mod p = 0  do Add( factors, p );  n := n / p;  od;
        if p^2 > n then break; fi;
        if n = 1  then factors[1] := sign*factors[1];  return factors;  fi;
    od;
    od;

    # do trial divisions by known probable primes (and issue warning, if found)
    tmp := [];
    atomic readonly ProbablePrimes2 do
    for p  in ProbablePrimes2  do
        while n mod p = 0  do
          AddSet(tmp, p);
          Add( factors, p );
          n := n / p;
        od;
        if n = 1  then break; fi;
    od;
    od;
    if Length(tmp) > 0 then
        Info(InfoPrimeInt, 1 ,
        "FactorsInt: used the following factor(s) which are probably primes:");
        for p in tmp do
          Info(InfoPrimeInt, 1, "      ", p);
        od;
    fi;
    if n = 1  then factors[1] := sign*factors[1];  return factors;  fi;


    # handle perfect powers
    p := SmallestRootInt( n );
    if p < n  then
        while 1 < n  do
            Append( factors, FactorsInt(p) );
            n := n / p;
        od;
        Sort( factors );
        factors[1] := sign * factors[1];
        return factors;
    fi;

    # let `FactorsRho' do the work
      if ValueOption("RhoTrials") <> fail then
        tmp := FactorsRho( n, 116,  ValueOption("RhoTrials") );
      else
        tmp := FactorsRho( n, 1168192 );
      fi;
    if 0 < Length(tmp[2])  then
      if ValueOption("quiet")<>true then
        len := Length(tmp[2]);
        if IsPackageMarkedForLoading("FactInt", "")  then
##            # in general cases we should proceed with the found factors:
##            while len > 0 do
##              Append(tmp[1], Factors(tmp[2][len]));
##              Unbind(tmp[2][len]);
##              len := len-1;
##            od;
          # but this way we miss that FactInt can detect certain numbers of
          # special shape for which it uses lookup tables, therefore for the
          # moment:
          return Factors(n_orig);
        else
          Error( "sorry,  cannot factor ", tmp[2],
            "\ntype 'return;' to try again with a larger number of trials in\n",
            "FactorsRho (or use option 'RhoTrials')\n");
          if ValueOption("RhoTrials") <> fail then
            rt := 5 * ValueOption("RhoTrials");
          else
            rt := 5 * 8192;
          fi;
          while len > 0 do
            tmp2 := FactorsInt(tmp[2][len]: RhoTrials := rt);
            Append(tmp[1], tmp2);
            Unbind(tmp[2][len]);
            len := len-1;
          od;
        fi;
      else
        factors := Concatenation( factors, tmp[2] );
      fi;
    fi;
    factors := Concatenation( factors, tmp[1] );
    Sort( factors );
    factors[1] := sign * factors[1];
    return factors;
end);


#############################################################################
##
#F  PrimeDivisors( <n> ) . . . . . . . . . . . . . . list of prime divisors
##
##  delegating to Factors
##
InstallMethod( PrimeDivisors, "for integer", [ IsInt ], function(n)
  if n = 0 then
    Error( "<n> must be non zero" );
  fi;
  if n < 0 then
    n := -n;
  fi;
  if n = 1 then
    return [];
  fi;
  return Set(Factors(Integers,n));
end);


#############################################################################
##
#M  PartialFactorization( <n>, <effort> ) . . . . . . . . . .  generic method
##
InstallMethod( PartialFactorization,
               "generic method", true, [ IsInt, IsInt ], 0,

  function ( n, effort )

    local  N, sign, factors, p, k, root, rootfactors, rhotrials,
           tmp, CheckAndSortFactors;

    CheckAndSortFactors := function ( )
      factors    := SortedList(factors);
      factors[1] := sign*factors[1];
      if   Product(factors) <> N
      then Error("PartialFactorization: Internal error, wrong result!"); fi;
    end;

    N := n;
    if effort < 0 then effort := 5; fi;

    # make $n$ positive and handle trivial cases
    sign := 1;
    if n < 0  then sign := -sign;  n := -n;  fi;
    if n < 4  then return [ sign * n ];  fi;
    factors := [];

    # least effort: do trial divisions by the primes less than 100
    if effort = 0 then
      for p in Primes{[1..25]} do
        while n mod p = 0 do Add( factors, p ); n := n / p; od;
        if n < (p+1)^2 and 1 < n then Add(factors,n); n := 1; fi;
        if n = 1 then CheckAndSortFactors(); return factors; fi;
      od;
      Add(factors,n); CheckAndSortFactors(); return factors;
    fi;

    # do trial divisions by the primes less than 1000
    # faster than anything fancier because $n$ mod <small int> is very fast
    for p in Primes do
      while n mod p = 0 do Add( factors, p ); n := n / p; od;
      if n < (p+1)^2 and 1 < n then Add(factors,n);  n := 1; fi;
      if n = 1 then CheckAndSortFactors(); return factors; fi;
    od;

    if effort <= 1 then
      Add(factors,n); CheckAndSortFactors();
      return factors;
    fi;

    # do trial divisions by known primes
    atomic readonly Primes2 do
    for p in Primes2 do
      while n mod p = 0 do Add( factors, p ); n := n / p; od;
      if n = 1 then CheckAndSortFactors(); return factors; fi;
    od;
    od;

    # do trial divisions by known probable primes
    tmp := [];
    atomic readonly ProbablePrimes2 do
    for p in ProbablePrimes2 do
      while n mod p = 0 do
        AddSet(tmp, p);
        Add( factors, p );
        n := n / p;
      od;
      if n = 1 then break; fi;
    od;
    od;

    if n = 1 then CheckAndSortFactors(); return factors; fi;

    # handle perfect powers
    root := SmallestRootInt( n );
    if root < n then
      rootfactors := PartialFactorization(root,effort);
      k           := LogInt(n,root);
      rootfactors := Concatenation(List([1..k],i->rootfactors));
      factors     := SortedList(Concatenation(factors,rootfactors));
      CheckAndSortFactors();
      return factors;
    fi;

    if effort = 2 or IsProbablyPrimeInt(n) then
      Add(factors,n); CheckAndSortFactors(); return factors;
    fi;

    # if effort >= 3, use `FactorsRho'
    if ValueOption("RhoTrials") <> fail then
      tmp := FactorsRho(n,1,16,ValueOption("RhoTrials"):
                        UseProbabilisticPrimalityTest);
    else
      if   effort  = 3 then rhotrials := 256;
      elif effort  = 4 then rhotrials := 2048;
      elif effort >= 5 then rhotrials := 8192; fi;
      tmp := FactorsRho(n,1,16,rhotrials:UseProbabilisticPrimalityTest);
    fi;
    factors := SortedList(Concatenation(factors,tmp[1],tmp[2]));
    CheckAndSortFactors();
    return factors;
  end );


#############################################################################
##
#M  PartialFactorization( <n> ) . . . . . partial factorization of an integer
##
InstallOtherMethod( PartialFactorization,
                    "for integers", true, [ IsInt ], 0,
                    n -> PartialFactorization(n,5) );


#############################################################################
##
#F  Gcdex( <m>, <n> ) . . . . . . . . . . greatest common divisor of integers
##
InstallGlobalFunction(Gcdex,function ( m, n )
    local   f, g, h, fm, gm, hm, q;
    if 0 <= m  then f:=m; fm:=1; else f:=-m; fm:=-1; fi;
    if 0 <= n  then g:=n; gm:=0; else g:=-n; gm:=0;  fi;
    while g <> 0  do
        q := QuoInt( f, g );
        h := g;          hm := gm;
        g := f - q * g;  gm := fm - q * gm;
        f := h;          fm := hm;
    od;
    if n = 0  then
        return rec( gcd := f, coeff1 := fm, coeff2 := 0,
                              coeff3 := gm, coeff4 := 1 );
    else
        return rec( gcd := f, coeff1 := fm, coeff2 := (f - fm * m) / n,
                              coeff3 := gm, coeff4 := (0 - gm * m) / n );
    fi;
end);


#############################################################################
##
#F  IsEvenInt( <n> )  . . . . . . . . . . . . . . . . . . test if <n> is even
##
InstallGlobalFunction( IsEvenInt, n -> n mod 2 = 0 );


#############################################################################
##
#F  IsOddInt( <n> ) . . . . . . . . . . . . . . . . . . .  test if <n> is odd
##
InstallGlobalFunction( IsOddInt, n -> n mod 2 = 1 );


#############################################################################
##
#F  IsPrimePowerInt( <n> )  . . . . . . . . . . . test for a power of a prime
##
InstallGlobalFunction( IsPrimePowerInt, function(n)
    local   k, r, s, p, l, q, i;

    # check the argument
    if   n >  1 then k := 2;  s :=  1;
    elif n < -1 then k := 3;  s := -1;  n := -n;
    else return false;
    fi;

    # exclude small divisors, and thereby large exponents
    for p in Primes do
        if p*p > n then return true; fi; # n is prime
        r := PVALUATION_INT(n, p);
        if r > 0 then
            if s = -1 and IsEvenInt(r) then return false; fi;
            return n = p^r;
        fi;
    od;
    l := LogInt( n, p );

    # loop over the possible prime divisors of exponents
    # use Fermat's little theorem to cast out impossible ones:
    # for suppose we had r such that n = r^k. Then by Fermat,
    # n^((q-1)/k) = r^(q-1) is congruent 0 or 1 mod q
    i := Position(Primes, k);
    while k <= l  do
        q := 2*k+1;  while not IsPrimeInt(q)  do q := q+2*k;  od;
        if PowerModInt( n, (q-1)/k, q ) <= 1  then
            r := RootInt( n, k );
            if r ^ k = n  then
                n := r;
                l := QuoInt( l, k );
                continue;
            fi;
        fi;
        if i <> fail and i < Length(Primes) then
            i := i + 1;
            k := Primes[i];
        else
            # need more primes...
            k := NextPrimeInt( k );
            # since we are now beyond the primes in Primes, for which we
            # checked whether they divide n, we might now just as well
            # test if k divides n, too
            r := PVALUATION_INT(n, k);
            if r > 0 then
                if s = -1 and IsEvenInt(r) then return false; fi;
                return n = k^r;
            fi;
        fi;
    od;

    return IsPrimeInt(n);
end);


#############################################################################
##
#F  LcmInt( <m>, <n> )  . . . . . . . . . . least common multiple of integers
##
InstallGlobalFunction(LcmInt, LCM_INT);


#############################################################################
##
#F  LogInt( <n>, <base> ) . . . . . . . . . . . . . . logarithm of an integer
##
InstallGlobalFunction(LogInt,function ( n, base )
    local   log, p;

    # check arguments
    if not IsInt(n) or n    <= 0  then
        Error("<n> must be a positive integer");
    fi;
    if not IsInt(base) or base <= 1  then
        Error("<base> must be an integer greater than 1");
    fi;

    # `log(b)' returns $log_b(n)$ and divides `n' by `b^log(b)'
##      log := function ( b )
##          local   i;
##          if b > n  then return 0;  fi;
##          i := log( b^2 );
##          if b > n  then return 2 * i;
##          else  n := QuoInt( n, b );  return 2 * i + 1;  fi;
##      end;
##
##      return log( base );
  if n < base then
    return 0;
  elif base = 2 then
    return Log2Int(n);
  elif base = 8 then
    return QuoInt(Log2Int(n), 3);
  elif base = 16 then
    return QuoInt(Log2Int(n), 4);
  elif IsSmallIntRep(n) then
    log := 1;
    p := base * base;
    while p <= n do
      log := log + 1;
      p := p * base;
    od;
    return log;
  elif base = 10 then
    log := QuoInt(Log2Int(n) * 10^6 , 3321929);
    return log + LogInt(QuoInt(n, 10^log), 10);
  else
    log := QuoInt(Log2Int(n), Log2Int(base)+1);
    if log = 0 then
      log := 1;
    fi;
    return log + LogInt(QuoInt(n, base^log), base);
  fi;
end);

#############################################################################
##
#F  NextPrimeInt( <n> ) . . . . . . . . . . . . . . . . . . next larger prime
##
InstallGlobalFunction(NextPrimeInt,function ( n )
    if   -3 = n             then n := -2;
    elif -3 < n  and n < 2  then n :=  2;
    elif n mod 2 = 0        then n := n+1;
    else                         n := n+2;
    fi;
    while not IsPrimeInt(n)  do
        if n mod 6 = 1  then n := n+4;
        else                 n := n+2;
        fi;
    od;
    return n;
end);


#############################################################################
##
#F  PowerModInt(<r>,<e>,<m>)  . . . . . . power of one integer modulo another
##
InstallGlobalFunction(PowerModInt, POWERMODINT);


#############################################################################
##
#F  PrevPrimeInt( <n> ) . . . . . . . . . . . . . . .  previous smaller prime
##
##  `PrevPrimeInt' returns the largest prime  which is strictly smaller  than
##  the integer <n>.
##
InstallGlobalFunction(PrevPrimeInt,function ( n )
    if    3 = n             then n :=  2;
    elif -2 < n  and n < 3  then n := -2;
    elif n mod 2 = 0        then n := n-1;
    else                         n := n-2;
    fi;
    while not IsPrimeInt(n)  do
        if n mod 6 = 5  then n := n-4;
        else                 n := n-2;
        fi;
    od;
    return n;
end);


#############################################################################
##
#F  PrimePowerInt( <n> )  . . . . . . . . . . . . . . . . prime powers of <n>
##
InstallGlobalFunction(PrimePowersInt,function( n )
    if n = 1  then
        return [];
    elif n = 0  then
        Error( "<n> must be non zero" );
    elif n < 0  then
        n := -1 * n;
    fi;
    return Flat(Collected(Factors(Integers,n)));

end);


#############################################################################
##
#F  RootInt( <n> )  . . . . . . . . . . . . . . . . . . .  root of an integer
#F  RootInt( <n>, <k> )
##
InstallGlobalFunction(RootInt,function ( arg )
    local   n, k, r, s, t;

    # get the arguments
    if   Length(arg) = 1  then n := arg[1];  k := 2;
    elif Length(arg) = 2  then n := arg[1];  k := arg[2];
    else Error("usage: `Root( <n> )' or `Root( <n>, <k> )'");
    fi;

    # ask the kernel to compute the root; this can only fail for
    # huge values of k and enormously huge values of n
    r := ROOT_INT(n, k);
    if r <> fail then
        return r;
    fi;

    # r is the first approximation, s the second, we need: root <= s < r
    r := n;  s := 2^( QuoInt( LogInt(n,2), k ) + 1 ) - 1;

    # do Newton iterations until the approximations stop decreasing
    while s < r  do
        r := s;  t := r^(k-1);  s := QuoInt( n + (k-1)*r*t, k*t );
    od;

    # and that's the integer part of the root
    return r;
end);


#############################################################################
##
#F  AbsInt( <n> ) . . . . . . . . . . . . . . .  absolute value of an integer
##
#InstallGlobalFunction( AbsInt, ABS_INT );
InstallGlobalFunction( AbsInt, ABS_RAT ); # support rationals for backwards compatibility


#############################################################################
##
#F  AbsoluteValue( <n> )
##
InstallMethod( AbsoluteValue, "rationals", [IsRat], ABS_RAT );


#############################################################################
##
#F  SignInt( <n> )  . . . . . . . . . . . . . . . . . . .  sign of an integer
##
#InstallGlobalFunction( SignInt, SIGN_INT );
InstallGlobalFunction( SignInt, SIGN_RAT ); # support rationals for backwards compatibility


#############################################################################
##
#F  SmallestRootInt( <n> )  . . . . . . . . . . . smallest root of an integer
##
InstallGlobalFunction(SmallestRootInt,function ( n )
    local   k, r, s, p, l, q, i;

    # check the argument
    if   n > 0  then k := 2;  s :=  1;
    elif n < 0  then k := 3;  s := -1;  n := -n;
    else return 0;
    fi;

    # exclude small divisors, and thereby large exponents
    for p in Primes do
        if p*p > n then return s * n; fi;
        if n mod p = 0 then break; fi;
    od;
    l := LogInt( n, p );

    # loop over the possible prime divisors of exponents
    # use Fermat's little theorem to cast out impossible ones:
    # for suppose we had r such that n = r^k. Then by Fermat,
    # n^((q-1)/k) = r^(q-1) is congruent 0 or 1 mod q
    i := Position(Primes, k);
    while k <= l  do
        q := 2*k+1;  while not IsPrimeInt(q)  do q := q+2*k;  od;
        if PowerModInt( n, (q-1)/k, q ) <= 1  then
            r := RootInt( n, k );
            if r ^ k = n  then
                n := r;
                l := QuoInt( l, k );
                continue;
            fi;
        fi;
        if i <> fail and i < Length(Primes) then
            i := i + 1;
            k := Primes[i];
        else
            k := NextPrimeInt( k );
        fi;
    od;

    return s * n;
end);


#############################################################################
##
#M  RingByGenerators( <elms> ) . . . . . . .  ring generated by some integers
##
InstallMethod( RingByGenerators,
    "method that catches the cases of `Integers' and subrings of `Integers'",
    [ IsCyclotomicCollection ],
    SUM_FLAGS, # test this before doing anything else
    function( elms )
      if ForAll( elms, IsInt ) then
        # check that the number of generators is bigger than one
        # to avoid infinite recursion
        if Length( elms ) > 1 then
          return RingByGenerators( [ Gcd(elms) ] );
        elif elms[1] = 1 then
          return Integers;
        else
          TryNextMethod();
        fi;
      else
        TryNextMethod();
      fi;
    end );


#############################################################################
##
#M  RingWithOneByGenerators( <elms> ) . . . . ring generated by some integers
##
InstallMethod( RingWithOneByGenerators,
    "method that catches the cases of `Integers'",
    [ IsCyclotomicCollection ],
    SUM_FLAGS, # test this before doing anything else
    function( elms )
      if ForAll( elms, IsInt ) then
        return Integers;
      else
        TryNextMethod();
      fi;
    end );


#############################################################################
##
#M  DefaultRingByGenerators( <elms> ) default ring generated by some integers
##
InstallMethod( DefaultRingByGenerators,
    "method that catches the cases of `(Gaussian)Integers' and cycl. fields",
    [ IsCyclotomicCollection ],
    SUM_FLAGS, # test this before doing anything else
    function( elms )
      if ForAll( elms, IsInt ) then
        return Integers;
      elif ForAll( elms, IsGaussInt ) then
        return GaussianIntegers;
      else
        return DefaultField( elms );
      fi;
    end );


#############################################################################
##
#M  DefaultRingByGenerators( <mats> ) .  for a list of n x n integer matrices
##
InstallMethod( DefaultRingByGenerators,
               "for lists of n x n integer matrices", true,
               [ IsCyclotomicCollCollColl and IsFinite ],

  function ( mats )
    local d;
    if IsEmpty(mats) or not ForAll(mats,IsRectangularTable and IsMatrix) then
       TryNextMethod();
    fi;
    d := Length( mats[1] );
    if d=0 then
       TryNextMethod();
    fi;
    if not ForAll( mats, m -> Length(m)=d and Length(m[1])=d ) then
       TryNextMethod();
    fi;
    if not ForAll( mats, m -> ForAll( m, r -> ForAll(r,IsInt))) then
       TryNextMethod();
    fi;
    return FullMatrixAlgebra(Integers,d);
  end );


#############################################################################
##
#M  Enumerator( Integers )
##
##  $a_n = \frac{n}{2}$ if $n$ is even, and
##  $a_n = \frac{1-n}{2}$ otherwise.
##
InstallMethod( Enumerator,
    "for integers",
    [ IsIntegers ],
    Integers -> EnumeratorByFunctions( Integers,
        rec( ElementNumber := function( e, n )
               if n mod 2 = 0 then
                 return n / 2;
               else
                 return ( 1 - n ) / 2;
               fi;
               end,

             NumberElement := function( e, x )
               local pos;
               if not IsInt( x ) then
                 return fail;
               elif 0 < x then
                 pos:= 2 * x;
               else
                 pos:= -2 * x + 1;
               fi;
               return pos;
               end ) ) );


#############################################################################
##
#M  EuclideanDegree( Integers, <n> ) . . . . . . . . . . . . . absolute value
##
InstallMethod( EuclideanDegree,
    "for integers",
    true,
    [ IsIntegers, IsInt ], 0,
    function ( Integers, n )
    if n < 0  then
        return -n;
    else
        return n;
    fi;
    end );


#############################################################################
##
#M  EuclideanQuotient( Integers, <n>, <m> )   . . . . . .  Euclidean quotient
##
InstallMethod( EuclideanQuotient,
    "for integers",
    true,
    [ IsIntegers, IsInt, IsInt ], 0,
    function ( Integers, n, m )
    return QuoInt( n, m );
    end );


#############################################################################
##
#M  EuclideanRemainder( Integers, <n>, <m> )  . . . . . . Euclidean remainder
##
InstallMethod( EuclideanRemainder,
    "for integers",
    true,
    [ IsIntegers, IsInt, IsInt ], 0,
    function ( Integers, n, m )
    return RemInt( n, m );
    end );


#############################################################################
##
#M  Factors( Integers, <n> )  . . . . . . . . . . factorization of an integer
##
InstallMethod( Factors,
    "for integers",
    true,
    [ IsIntegers, IsInt ], 0,
    function ( Integers, n )
    return FactorsInt( n );
    end );


#############################################################################
##
#M  IsIrreducibleRingElement( Integers, <n> )
##
InstallMethod( IsIrreducibleRingElement,
    "for integers",
    true,
    [ IsIntegers, IsInt ], 0,
    function ( Integers, n )
    return IsPrimeInt( n );
    end );


#############################################################################
##
#M  IsPrime( Integers, <n> )  . . . . . .  test whether an integer is a prime
##
InstallMethod( IsPrime,
    "for integers",
    true,
    [ IsIntegers, IsInt ], 0,
    function ( Integers, n )
    return IsPrimeInt( n );
    end );


#############################################################################
##
#M  Iterator( Integers )
##
##  uses the succession $01, -12, -23, -3, \ldots$, that is,
##  $a_n = \frac{n}{2}$ if $n$ is even, and $a_n = \frac{1-n}{2}$
##  otherwise.
##
InstallMethod( Iterator,
    "for `Integers'",
    [ IsIntegers ],
    Integers -> IteratorByFunctions( rec(
        NextIterator := function( iter )
            iter!.counter:= iter!.counter + 1;
            if iter!.counter mod 2 = 0 then
              return iter!.counter / 2;
            else
              return ( 1 - iter!.counter ) / 2;
            fi;
            end,
        IsDoneIterator := ReturnFalse,
        ShallowCopy := iter -> rec( counter:= iter!.counter ),
        PrintObj := function(iter)
            local msg;
            msg := "<iterator of Integers at ";
            if iter!.counter mod 2 = 0 then
              Append(msg, String(iter!.counter / 2));
            else
              Append(msg, String((1 - iter!.counter) / 2));
            fi;
            Append(msg,">");
            Print(msg);
          end,
        counter := 0 ) ) );


#############################################################################
##
#M  Iterator( PositiveIntegers )
##
InstallMethod( Iterator,
    "for `PositiveIntegers'",
    [ IsPositiveIntegers ],
    IsPositiveIntegers -> IteratorByFunctions( rec(
        NextIterator := function( iter )
            iter!.counter:= iter!.counter + 1;
              return iter!.counter;
            end,
        IsDoneIterator := ReturnFalse,
        ShallowCopy := iter -> rec( counter:= iter!.counter ),

        counter := 0 ) ) ); # 0, since we first increment then return


#############################################################################
##
#M  LcmOp( Integers, <n>, <m> ) . . . . . . least common multiple of integers
##
InstallMethod( LcmOp,
    "for integers",
    true,
    [ IsIntegers, IsInt, IsInt ], 0,
    function ( Integers, n, m )
    return LcmInt( n, m );
    end );


#############################################################################
##
#M  Log( <n>, <base> )
##
InstallMethod( Log,
    "for two integers",
    true,
    [ IsInt, IsInt ], 0,
    LogInt );


#############################################################################
##
#M  PowerMod( Integers, <r>, <e>, <m> ) . . . power of an integer mod another
##
InstallMethod( PowerMod,
    "for integers",
    true,
    [ IsIntegers, IsInt, IsInt, IsInt ], 0,
    function ( Integers, r, e, m )
    return PowerModInt( r, e, m );
    end );


#############################################################################
##
#M  Quotient( <Integers>, <n>, <m> )  . . . . . . .  quotient of two integers
##
InstallMethod( Quotient,
    "for integers",
    true,
    [ IsIntegers, IsInt, IsInt ], 0,
    function ( Integers, n, m )
    local   q;
    if m = 0 then
        return fail;
    fi;
    q := QuoInt( n, m );
    if n <> q * m  then
        q := fail;
    fi;
    return q;
    end );


#############################################################################
##
#M  QuotientMod( Integers , <r>, <s>, <m> ) . . . . . . . quotient modulo <m>
##
InstallMethod( QuotientMod,
    "for integers",
    true,
    [ IsIntegers, IsInt, IsInt, IsInt ], 0,
    function ( Integers, r, s, m )
    local g;
    if m = 1 then
        return 0;
    else
        r := r mod m;
        if r = 0 then return 0; fi;  # as required by QuotientMod documentation
        s := s mod m;
        if s = 0 then return fail; fi;

        g := GcdInt( r, s );
        r := r / g;
        s := s / g;
        g := GcdInt( g, m );
        m := m / g;
        if GcdInt( s, m ) <> 1 then
            return fail;
        fi;
        return r * INVMODINT(s, m) mod m;
    fi;
    end );


#############################################################################
##
#M  QuotientRemainder( Integers, <n>, <m> ) . . . . . . . . . . . quo and rem
##
InstallMethod( QuotientRemainder,
    "for integers",
    true,
    [ IsIntegers, IsInt, IsInt ], 0,
    function ( Integers, n, m )
      local q;
      q := QuoInt(n,m);
      #T kernel function should compute remainder at same time
      return [ q, n - q * m ];
    end );


#############################################################################
##
#M  Random( Integers )  . . . . . . . . . . . . . . . . . . .  random integer
##
##  returns pseudo random integers between $-10$ and $10$
##  distributed according to a binomial distribution.
##
##  \begintt
##  gap> Random( Integers );
##  1
##  gap> Random( Integers );
##  -4
##  \endtt
##
##  To generate uniformly distributed integers from a range, use the
##  construct `Random( [ <low> .. <high> ] )'.
##
BindGlobal( "NrBitsInt", function ( n )
    local   nr, nr64;
    nr64:=[0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
           1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6];
    nr := 0;
    while 0 < n  do
        nr := nr + nr64[ n mod 64 + 1 ];
        n := QuoInt( n, 64 );
    od;
    return nr;
end );

InstallMethodWithRandomSource(Random,
    "for a random source and `Integers'", true,
    [IsRandomSource, IsIntegers],
    0,
    function( rg, Integers )
    return NrBitsInt( Random( rg, 02^20-1 ) ) - 10;
    end );



#############################################################################
##
#M  Root( <n>, <k> )
##
InstallMethod( Root,
    "for two integers",
    true,
    [ IsInt, IsInt ], 0,
    RootInt );


#############################################################################
##
#M  RoundCyc( <cyc> ) . . . . . . . . . . cyclotomic integer near to <cyc>
##
InstallMethod( RoundCyc, "Integer", true, [ IsInt ], 0,  x->x );


#############################################################################
##
#M  RoundCycDown( <cyc> ) . . . . . . . . . . cyclotomic integer near to <cyc>
##
InstallMethod( RoundCycDown, "Integer", true, [ IsInt ], 0,  x->x );


#############################################################################
##
#M  StandardAssociate( Integers, <n> )  . . . . . . . . . . .  absolute value
##
InstallMethod( StandardAssociate,
    "for integers",
    true,
    [ IsIntegers, IsInt ], 0,
    function ( Integers, n )
    if n < 0  then
        return -n;
    else
        return n;
    fi;
    end );

#############################################################################
##
#M  StandardAssociateUnit( Integers, <n> )
##
InstallMethod( StandardAssociateUnit,
    "for integers",
    true,
    [ IsIntegers, IsInt ], 0,
    function ( Integers, n )
    if n < 0 then
        return -1;
    else
        return 1;
    fi;
    end );


#############################################################################
##
#M  Valuation( <n>, <m> )
##
InstallOtherMethod( Valuation,
    "for two integers",
    IsIdenticalObj,
    [ IsInt, IsInt ],
    0,
function( n, m )
    if n = 0  then
        return infinity;
    fi;
    return PVALUATION_INT( n, m );
end );


#############################################################################
##
#M  \in( <n>, <Integers> )  . . . . . . . . . .  membership test for integers
##
InstallMethod( \in,
    "for integers",
    IsElmsColls,
    [ IsCyclotomic, IsIntegers ], 0,
    function( n, Integers )
    return IsInt( n );
    end );


#############################################################################
##
#M  \in( <n>, <PositiveIntegers> )
##
InstallMethod( \in,
    "for positive integers",
    IsElmsColls,
    [ IsCyclotomic, IsPositiveIntegers ], 0,
    function( n, PositiveIntegers )
    return IsPosInt( n );
    end );


#############################################################################
##
#M  \in( <n>, <NonnegativeIntegers> )
##
InstallMethod( \in,
    "for nonnegative integers",
    IsElmsColls,
    [ IsCyclotomic, IsNonnegativeIntegers ], 0,
    function( n, NonnegativeIntegers )
    return IsPosInt( n ) or IsZeroCyc( n );
    end );


#############################################################################
##
#F  PrintFactorsInt( <n> )  . . . . . . . . print factorization of an integer
##
InstallGlobalFunction(PrintFactorsInt,function ( n )
    Print( StringPP( n ) );
end);

#############################################################################
##
#M  Iterator( <posint> ) . . . . . . . . . . . . .give more informative error
##
##  This method is mainly there to trap the "natural" error
##  for i in 3 do ... od;
##

InstallOtherMethod(Iterator, "more helpful error for integers", true,
        [IsPosInt], 0,
        function(n)
    Error("You cannot loop over the integer ",n,
          " did you mean the range [1..",n,"]");
end);

##  The behaviour of View(String) for large integers can be configured via a
##  user preference.
DeclareUserPreference( rec(
  name:= "MaxBitsIntView",
  description:= [
    "Maximal bit length of integers to <C>View</C> unabbreviated.  \
Default is about <M>30</M> lines of a <M>80</M> character wide terminal.  \
Set this to <C>0</C> to avoid abbreviated ints."
    ],
  default:= 8000,
  check:= val -> IsInt( val ) and 0 <= val,
  ) );
##  give only a short info if |n| is larger than 2^GAPInfo.MaxBitsIntView
InstallMethod(ViewString, "for integer", [IsInt], function(n)
  local mb, l, start, trail;
  mb := UserPreference("MaxBitsIntView");
  if not IsSmallIntRep(n) and mb <> fail and
      mb > 64 and Log2Int(n) > mb then
    if n < 0 then
      l := LogInt(-n, 10);
      trail := String(-n mod 1000);
    else
      l := LogInt(n, 10);
      trail := String(n mod 1000);
    fi;
    start := String(QuoInt(n, 10^(l-2)));
    while Length(trail) < 3 do
      trail := Concatenation("0", trail);
    od;
    return Concatenation("<integer ",start,"...",trail," (",
                         String(l+1)," digits)>");
  else
    return String(n);
  fi;
end);

[Dauer der Verarbeitung: 0.61 Sekunden]