1############################################################################# 2## 3#W rcwamap.gi GAP4 Package `RCWA' Stefan Kohl 4## 5## This file contains implementations of methods and functions for computing 6## with rcwa mappings of 7## 8## - the ring Z of the integers, of 9## - the ring Z^2, of 10## - the semilocalizations Z_(pi) of the ring of integers, and of 11## - the polynomial rings GF(q)[x] in one variable over a finite field. 12## 13## See the definitions given in the file rcwamap.gd. 14## 15############################################################################# 16 17############################################################################# 18## 19#F RCWAInfo . . . . . . . . . . . . . . . . . . set info level of `InfoRCWA' 20## 21InstallGlobalFunction( RCWAInfo, 22 function ( n ) SetInfoLevel( InfoRCWA, n ); end ); 23 24############################################################################# 25## 26#S Implications between the categories of rcwa mappings. /////////////////// 27## 28############################################################################# 29 30InstallTrueMethod( IsMapping, IsRcwaMapping ); 31InstallTrueMethod( IsRcwaMapping, IsRcwaMappingOfZOrZ_pi ); 32InstallTrueMethod( IsRcwaMappingOfZOrZ_pi, IsRcwaMappingOfZ ); 33InstallTrueMethod( IsRcwaMappingOfZOrZ_pi, IsRcwaMappingOfZ_pi ); 34InstallTrueMethod( IsRcwaMapping, IsRcwaMappingOfZxZ ); 35InstallTrueMethod( IsRcwaMapping, IsRcwaMappingOfGFqx ); 36 37############################################################################# 38## 39#S Shorthands for commonly used filters. /////////////////////////////////// 40## 41############################################################################# 42 43BindGlobal( "IsRcwaMappingInStandardRep", 44 IsRcwaMapping and IsRcwaMappingStandardRep ); 45BindGlobal( "IsRcwaMappingOfZInStandardRep", 46 IsRcwaMappingOfZ and IsRcwaMappingStandardRep ); 47BindGlobal( "IsRcwaMappingOfZ_piInStandardRep", 48 IsRcwaMappingOfZ_pi and IsRcwaMappingStandardRep ); 49BindGlobal( "IsRcwaMappingOfZOrZ_piInStandardRep", 50 IsRcwaMappingOfZOrZ_pi and IsRcwaMappingStandardRep ); 51BindGlobal( "IsRcwaMappingOfZxZInStandardRep", 52 IsRcwaMappingOfZxZ and IsRcwaMappingStandardRep ); 53BindGlobal( "IsRcwaMappingOfGFqxInStandardRep", 54 IsRcwaMappingOfGFqx and IsRcwaMappingStandardRep ); 55 56BindGlobal( "IsRcwaMappingInSparseRep", 57 IsRcwaMapping and IsRcwaMappingSparseRep ); 58BindGlobal( "IsRcwaMappingOfZInSparseRep", 59 IsRcwaMappingOfZ and IsRcwaMappingSparseRep ); 60BindGlobal( "IsRcwaMappingOfZ_piInSparseRep", # unused so far 61 IsRcwaMappingOfZ_pi and IsRcwaMappingSparseRep ); 62BindGlobal( "IsRcwaMappingOfZOrZ_piInSparseRep", 63 IsRcwaMappingOfZOrZ_pi and IsRcwaMappingSparseRep ); 64BindGlobal( "IsRcwaMappingOfZxZInSparseRep", # unused so far 65 IsRcwaMappingOfZxZ and IsRcwaMappingSparseRep ); 66BindGlobal( "IsRcwaMappingOfGFqxInSparseRep", # unused so far 67 IsRcwaMappingOfGFqx and IsRcwaMappingSparseRep ); 68 69############################################################################# 70## 71#S The families of rcwa mappings. ////////////////////////////////////////// 72## 73############################################################################# 74 75############################################################################# 76## 77#V RcwaMappingsOfZFamily . . . . . . . the family of all rcwa mappings of Z 78## 79BindGlobal( "RcwaMappingsOfZFamily", 80 NewFamily( "RcwaMappingsFamily( Integers )", 81 IsRcwaMappingOfZ, 82 CanEasilySortElements, CanEasilySortElements ) ); 83SetFamilySource( RcwaMappingsOfZFamily, FamilyObj( 1 ) ); 84SetFamilyRange ( RcwaMappingsOfZFamily, FamilyObj( 1 ) ); 85SetUnderlyingRing( RcwaMappingsOfZFamily, Integers ); 86 87############################################################################# 88## 89#V RcwaMappingsOfZxZFamily . . . . . the family of all rcwa mappings of Z^2 90## 91BindGlobal( "RcwaMappingsOfZxZFamily", 92 NewFamily( "RcwaMappingsFamily( Integers^2 )", 93 IsRcwaMappingOfZxZ, 94 CanEasilySortElements, CanEasilySortElements ) ); 95SetFamilySource( RcwaMappingsOfZxZFamily, FamilyObj( [ 1, 1 ] ) ); 96SetFamilyRange ( RcwaMappingsOfZxZFamily, FamilyObj( [ 1, 1 ] ) ); 97SetUnderlyingLeftModule( RcwaMappingsOfZxZFamily, Integers^2 ); 98 99## Internal variables storing the rcwa mapping families used in the 100## current GAP session. 101 102BindGlobal( "Z_PI_RCWAMAPPING_FAMILIES", [] ); 103BindGlobal( "GFQX_RCWAMAPPING_FAMILIES", [] ); 104 105############################################################################# 106## 107#F RcwaMappingsOfZ_piFamily( <R> ) 108## 109## Returns the family of all rcwa mappings of a given semilocalization <R> 110## of the ring of integers. 111## 112InstallGlobalFunction( RcwaMappingsOfZ_piFamily, 113 114 function ( R ) 115 116 local fam, name; 117 118 if not IsZ_pi( R ) 119 then Error("usage: RcwaMappingsOfZ_piFamily( <R> )\n", 120 "where <R> = Z_pi( <pi> ) for a set of primes <pi>.\n"); 121 fi; 122 fam := First( Z_PI_RCWAMAPPING_FAMILIES, 123 fam -> UnderlyingRing( fam ) = R ); 124 if fam <> fail then return fam; fi; 125 name := Concatenation( "RcwaMappingsFamily( ", 126 String( R ), " )" ); 127 fam := NewFamily( name, IsRcwaMappingOfZ_pi, 128 CanEasilySortElements, CanEasilySortElements ); 129 SetUnderlyingRing( fam, R ); 130 SetFamilySource( fam, FamilyObj( 1 ) ); 131 SetFamilyRange ( fam, FamilyObj( 1 ) ); 132 MakeReadWriteGlobal( "Z_PI_RCWAMAPPING_FAMILIES" ); 133 Add( Z_PI_RCWAMAPPING_FAMILIES, fam ); 134 MakeReadOnlyGlobal( "Z_PI_RCWAMAPPING_FAMILIES" ); 135 136 return fam; 137 end ); 138 139############################################################################# 140## 141#F RcwaMappingsOfGFqxFamily( <R> ) 142## 143## Returns the family of all rcwa mappings of a given polynomial ring <R> 144## in one variable over a finite field. 145## 146InstallGlobalFunction( RcwaMappingsOfGFqxFamily, 147 148 function ( R ) 149 150 local fam, x; 151 152 if not ( IsUnivariatePolynomialRing( R ) 153 and IsFiniteFieldPolynomialRing( R ) ) 154 then Error("usage: RcwaMappingsOfGFqxFamily( <R> ) for a ", 155 "univariate polynomial ring <R> over a finite field.\n"); 156 fi; 157 x := IndeterminatesOfPolynomialRing( R )[ 1 ]; 158 fam := First( GFQX_RCWAMAPPING_FAMILIES, 159 fam -> IsIdenticalObj( UnderlyingRing( fam ), R ) ); 160 if fam <> fail then return fam; fi; 161 fam := NewFamily( Concatenation( "RcwaMappingsFamily( ", 162 String( R ), " )" ), 163 IsRcwaMappingOfGFqx, 164 CanEasilySortElements, CanEasilySortElements ); 165 SetUnderlyingIndeterminate( fam, x ); 166 SetUnderlyingRing( fam, R ); 167 SetFamilySource( fam, FamilyObj( x ) ); 168 SetFamilyRange ( fam, FamilyObj( x ) ); 169 MakeReadWriteGlobal( "GFQX_RCWAMAPPING_FAMILIES" ); 170 Add( GFQX_RCWAMAPPING_FAMILIES, fam ); 171 MakeReadOnlyGlobal( "GFQX_RCWAMAPPING_FAMILIES" ); 172 173 return fam; 174 end ); 175 176############################################################################# 177## 178#F RcwaMappingsFamily( <R> ) . . . family of rcwa mappings over the ring <R> 179## 180InstallGlobalFunction( RcwaMappingsFamily, 181 182 function ( R ) 183 184 if IsIntegers( R ) then return RcwaMappingsOfZFamily; 185 elif IsZxZ( R ) then return RcwaMappingsOfZxZFamily; 186 elif IsZ_pi( R ) then return RcwaMappingsOfZ_piFamily( R ); 187 elif IsUnivariatePolynomialRing( R ) and IsFiniteFieldPolynomialRing( R ) 188 then return RcwaMappingsOfGFqxFamily( R ); 189 else Error("Sorry, rcwa mappings over ",R," are not yet implemented.\n"); 190 fi; 191 end ); 192 193############################################################################# 194## 195#F RcwaMappingsType( <R> ) . . . . . . . . . . filter: rcwa mappings of <R> 196## 197InstallGlobalFunction( RcwaMappingsType, 198 199 function ( R ) 200 if IsIntegers( R ) then return IsRcwaMappingOfZ; 201 elif IsZxZ( R ) then return IsRcwaMappingOfZxZ; 202 elif IsZ_pi( R ) then return IsRcwaMappingOfZ_pi; 203 elif IsUnivariatePolynomialRing( R ) and IsFiniteFieldPolynomialRing( R ) 204 then return IsRcwaMappingOfGFqx; 205 else return fail; fi; 206 end ); 207 208############################################################################# 209## 210#S The methods for the general-purpose constructor for rcwa mappings. ////// 211## 212############################################################################# 213 214############################################################################# 215## 216#F RCWAMAPPING_COMPRESS_COEFFICIENT_LIST( <coeffs> ) . . . . . . . . utility 217## 218## This function takes care of that equal coefficient triples are always 219## also identical, in order to save memory. 220## 221BindGlobal( "RCWAMAPPING_COMPRESS_COEFFICIENT_LIST", 222 223 function ( coeffs ) 224 225 local cset, i; 226 227 cset := Set(coeffs); 228 for i in [1..Length(coeffs)] do 229 coeffs[i] := cset[PositionSorted(cset,coeffs[i])]; 230 od; 231 end ); 232 233############################################################################# 234## 235#M RcwaMapping( <R>, <modulus>, <coeffs> ) . . . . method (a) in the manual 236## 237InstallMethod( RcwaMapping, 238 "rcwa mapping by ring, modulus and coefficients (RCWA)", 239 ReturnTrue, [ IsRing, IsRingElement, IsList ], 0, 240 241 function ( R, modulus, coeffs ) 242 243 if not modulus in R then TryNextMethod(); fi; 244 if IsIntegers(R) or IsZ_pi(R) 245 then return RcwaMapping(R,coeffs); 246 elif IsPolynomialRing(R) 247 then return RcwaMapping(Size(LeftActingDomain(R)),modulus,coeffs); 248 else TryNextMethod(); fi; 249 end ); 250 251############################################################################# 252## 253#M RcwaMapping( <R>, <modulus>, <coeffs> ) . . . . method (a) in the manual 254## 255InstallMethod( RcwaMapping, 256 "rcwa mapping by ring = Z^2, modulus and coefficients (RCWA)", 257 ReturnTrue, [ IsRowModule, IsMatrix, IsList ], 0, 258 259 function ( R, modulus, coeffs ) 260 261 local residues, errormessage, i; 262 263 errormessage := Concatenation("construction of an rcwa mapping of Z^2:", 264 "\nmathematically incorrect arguments.\n"); 265 266 if not IsZxZ(R) or DimensionsMat(modulus) <> [2,2] 267 or not ForAll(Flat(modulus),IsInt) or DeterminantMat(modulus) = 0 268 or Length(coeffs) <> DeterminantMat(modulus) 269 or not ForAll(coeffs,IsList) 270 or not Set(List(coeffs,Length)) in [[2],[3]] 271 or not ( Length(coeffs[1])=2 272 and ForAll( coeffs, c -> c[1] in R and IsList(c[2]) 273 and Length(c[2])=3 274 and IsMatrix(c[2][1]) 275 and ForAll(Flat(c[2][1]),IsInt) 276 and c[2][2] in R 277 and IsInt(c[2][3]) and c[2][3] <> 0 ) 278 or Length(coeffs[1])=3 279 and ForAll( coeffs, c -> IsMatrix(c[1]) 280 and ForAll(Flat(c[1]),IsInt) 281 and c[2] in R 282 and IsInt(c[3]) and c[3] <> 0 ) ) 283 then Error(errormessage); return fail; fi; 284 285 modulus := HermiteNormalFormIntegerMat(modulus); 286 residues := AllResidues(R,modulus); 287 288 if Length(coeffs[1]) = 2 then 289 for i in [1..Length(coeffs)] do 290 coeffs[i][1] := coeffs[i][1] mod modulus; 291 od; 292 Sort( coeffs, function ( c1, c2 ) return c1[1] < c2[1]; end ); 293 if List(coeffs,c->c[1]) <> residues 294 then Error(errormessage); return fail; fi; 295 coeffs := List(coeffs,c->c[2]); 296 fi; 297 298 if not ForAll( [1..Length(residues)], 299 i -> ( residues[i]*coeffs[i][1] + coeffs[i][2] ) 300 mod coeffs[i][3] = [ 0, 0 ] ) 301 then Error(errormessage); return fail; fi; 302 303 return RcwaMappingNC(R,modulus,coeffs); 304 end ); 305 306############################################################################# 307## 308#M RcwaMappingNC( <R>, <modulus>, <coeffs> ) . . NC-method (a) in the manual 309## 310InstallMethod( RcwaMappingNC, 311 "rcwa mapping by ring, modulus and coefficients (RCWA)", 312 ReturnTrue, [ IsRing, IsRingElement, IsList ], 0, 313 314 function ( R, modulus, coeffs ) 315 316 if not modulus in R then TryNextMethod(); fi; 317 if IsIntegers(R) or IsZ_pi(R) 318 then return RcwaMappingNC(R,coeffs); 319 elif IsPolynomialRing(R) 320 then return RcwaMappingNC(Size(LeftActingDomain(R)),modulus,coeffs); 321 else TryNextMethod(); fi; 322 end ); 323 324############################################################################# 325## 326#M RcwaMappingNC( <R>, <modulus>, <coeffs> ) . . NC-method (a) in the manual 327## 328InstallMethod( RcwaMappingNC, 329 "rcwa mapping by ring = Z^2, modulus and coefficients (RCWA)", 330 ReturnTrue, [ IsRowModule, IsMatrix, IsList ], 0, 331 332 function ( R, modulus, coeffs ) 333 334 local ReduceRcwaMappingOfZxZ, result; 335 336 ReduceRcwaMappingOfZxZ := function ( f ) 337 338 local m, c, d, divs, res, resRed, mRed, cRed, 339 nraffs, identres, pos, i; 340 341 m := f!.modulus; c := f!.coeffs; 342 for i in [1..Length(c)] do 343 c[i] := c[i]/Gcd(Flat(c[i])); 344 if c[i][3] < 0 then c[i] := -c[i]; fi; 345 od; 346 nraffs := Length(Set(c)); 347 res := AllResidues(R,m); 348 divs := Superlattices(m); 349 mRed := m; cRed := c; 350 for d in divs do 351 if DeterminantMat(d) < nraffs then continue; fi; 352 resRed := List(res,r->r mod d); 353 identres := EquivalenceClasses([1..Length(c)],i->resRed[i]); 354 if ForAll(identres,res->Length(Set(c{res}))=1) then 355 mRed := d; 356 pos := List(identres,cl->cl[1]); 357 resRed := res{pos}; 358 cRed := Permuted(c{pos},SortingPerm(resRed)); 359 break; 360 fi; 361 od; 362 RCWAMAPPING_COMPRESS_COEFFICIENT_LIST(cRed); 363 f!.modulus := Immutable(mRed); 364 f!.coeffs := Immutable(cRed); 365 end; 366 367 if not IsZxZ( R ) then TryNextMethod( ); fi; 368 369 modulus := HermiteNormalFormIntegerMat( modulus ); 370 371 result := Objectify( NewType( RcwaMappingsOfZxZFamily, 372 IsRcwaMappingOfZxZInStandardRep ), 373 rec( modulus := modulus, 374 coeffs := coeffs ) ); 375 SetSource( result, R ); 376 SetRange ( result, R ); 377 378 ReduceRcwaMappingOfZxZ( result ); 379 380 return result; 381 end ); 382 383############################################################################# 384## 385#M RcwaMapping( <R>, <coeffs> ) . . . . . . . . . . method (b) in the manual 386## 387InstallMethod( RcwaMapping, 388 "rcwa mapping by ring and coefficients (RCWA)", 389 ReturnTrue, [ IsRing, IsList ], 0, 390 391 function ( R, coeffs ) 392 393 if IsIntegers(R) 394 then return RcwaMapping(coeffs); 395 elif IsZ_pi(R) 396 then return RcwaMapping(NoninvertiblePrimes(R),coeffs); 397 else TryNextMethod(); fi; 398 end ); 399 400############################################################################# 401## 402#M RcwaMappingNC( <R>, <coeffs> ) . . . . . . . NC-method (b) in the manual 403## 404InstallMethod( RcwaMappingNC, 405 "rcwa mapping by ring and coefficients (RCWA)", 406 ReturnTrue, [ IsRing, IsList ], 0, 407 408 function ( R, coeffs ) 409 410 if IsIntegers(R) 411 then return RcwaMappingNC(coeffs); 412 elif IsZ_pi(R) 413 then return RcwaMappingNC(NoninvertiblePrimes(R),coeffs); 414 else TryNextMethod(); fi; 415 end ); 416 417############################################################################# 418## 419#M RcwaMapping( <coeffs> ) . . . . . . . . . . . . method (c) in the manual 420## 421InstallMethod( RcwaMapping, 422 "rcwa mapping of Z by coefficients (RCWA)", 423 true, [ IsList ], 10, 424 425 function ( coeffs ) 426 427 local quiet; 428 429 if not IsList( coeffs[1] ) or not IsInt( coeffs[1][1] ) 430 or Length( coeffs[1] ) = 5 431 then TryNextMethod( ); fi; 432 quiet := ValueOption("BeQuiet") = true; 433 if not ( ForAll(Flat(coeffs),IsInt) 434 and ForAll(coeffs, IsList) 435 and ForAll(coeffs, c -> Length(c) = 3) 436 and ForAll([0..Length(coeffs) - 1], 437 n -> coeffs[n + 1][3] <> 0 and 438 (n * coeffs[n + 1][1] + coeffs[n + 1][2]) 439 mod coeffs[n + 1][3] = 0 and 440 ( (n + Length(coeffs)) * coeffs[n + 1][1] 441 + coeffs[n + 1][2]) 442 mod coeffs[n + 1][3] = 0)) 443 then if quiet then return fail; fi; 444 Error("the coefficients ",coeffs," do not define a proper ", 445 "rcwa mapping of Z.\n"); 446 fi; 447 return RcwaMappingNC( coeffs ); 448 end ); 449 450############################################################################# 451## 452#M RcwaMappingNC( <coeffs> ) . . . . . . . . . . NC-method (c) in the manual 453## 454InstallMethod( RcwaMappingNC, 455 "rcwa mapping of Z by coefficients (RCWA)", 456 true, [ IsList ], 10, 457 458 function ( coeffs ) 459 460 local ReduceRcwaMappingOfZ, Result; 461 462 ReduceRcwaMappingOfZ := function ( f ) 463 464 local c, m, fact, p, cRed, cRedBuf, n; 465 466 c := f!.coeffs; m := f!.modulus; 467 for n in [1..Length(c)] do 468 c[n] := c[n]/Gcd(c[n]); 469 if c[n][3] < 0 then c[n] := -c[n]; fi; 470 od; 471 fact := Set(FactorsInt(m)); cRed := c; 472 for p in fact do 473 repeat 474 cRedBuf := StructuralCopy(cRed); 475 cRed := List([1..p], i -> cRedBuf{[(i - 1) * m/p + 1 .. i * m/p]}); 476 if Length(Set(cRed)) = 1 477 then cRed := cRed[1]; m := m/p; else cRed := cRedBuf; fi; 478 until cRed = cRedBuf or m mod p <> 0; 479 od; 480 RCWAMAPPING_COMPRESS_COEFFICIENT_LIST(cRed); 481 f!.coeffs := Immutable(cRed); 482 f!.modulus := Length(cRed); 483 end; 484 485 if not IsList( coeffs[1] ) or not IsInt( coeffs[1][1] ) 486 or Length( coeffs[1] ) = 5 487 then TryNextMethod( ); fi; 488 Result := Objectify( NewType( RcwaMappingsOfZFamily, 489 IsRcwaMappingOfZInStandardRep ), 490 rec( coeffs := coeffs, 491 modulus := Length(coeffs) ) ); 492 SetSource(Result, Integers); 493 SetRange (Result, Integers); 494 ReduceRcwaMappingOfZ(Result); 495 return Result; 496 end ); 497 498############################################################################# 499## 500#M RcwaMapping( <perm>, <range> ) . . . . . . . . . method (d) in the manual 501## 502InstallMethod( RcwaMapping, 503 "rcwa mapping of Z by permutation and range (RCWA)", 504 true, [ IsPerm, IsRange ], 0, 505 506 function ( perm, range ) 507 508 local quiet; 509 510 quiet := ValueOption("BeQuiet") = true; 511 if Permutation(perm,range) = fail 512 then if quiet then return fail; fi; 513 Error("the permutation ",perm," does not act on the range ", 514 range,".\n"); 515 fi; 516 return RcwaMappingNC( perm, range ); 517 end ); 518 519############################################################################# 520## 521#M RcwaMappingNC( <perm>, <range> ) . . . . . . NC-method (d) in the manual 522## 523InstallMethod( RcwaMappingNC, 524 "rcwa mapping of Z by permutation and range (RCWA)", 525 true, [ IsPerm, IsRange ], 0, 526 527 function ( perm, range ) 528 529 local result, coeffs, min, max, m, n, r; 530 531 min := Minimum(range); max := Maximum(range); 532 m := max - min + 1; coeffs := []; 533 for n in [min..max] do 534 r := n mod m + 1; 535 coeffs[r] := [1, n^perm - n, 1]; 536 od; 537 result := RcwaMappingNC( coeffs ); 538 SetIsBijective(result,true); 539 SetIsTame(result,true); SetIsIntegral(result,true); 540 SetOrder(result,Order(RestrictedPerm(perm,range))); 541 return result; 542 end ); 543 544############################################################################# 545## 546#M RcwaMapping( <modulus>, <values> ) . . . . . . . method (e) in the manual 547## 548InstallMethod( RcwaMapping, 549 "rcwa mapping of Z by modulus and values (RCWA)", 550 true, [ IsInt, IsList ], 0, 551 552 function ( modulus, values ) 553 554 local f, coeffs, pts, r, quiet; 555 556 quiet := ValueOption("BeQuiet") = true; 557 coeffs := []; 558 for r in [1..modulus] do 559 pts := Filtered(values, pt -> pt[1] mod modulus = r - 1); 560 if Length(pts) < 2 561 then if quiet then return fail; fi; 562 Error("the mapping is not given at at least 2 points <n> ", 563 "with <n> mod ",modulus," = ",r - 1,".\n"); 564 fi; 565 od; 566 f := RcwaMappingNC( modulus, values ); 567 if Mod(f) mod Div(f) <> 0 or not ForAll(values,t -> t[1]^f = t[2]) 568 then if quiet then return fail; fi; 569 Error("the values ",values," do not define a proper ", 570 "rcwa mapping of Z.\n"); 571 fi; 572 return f; 573 end ); 574 575############################################################################# 576## 577#M RcwaMappingNC( <modulus>, <values> ) . . . . NC-method (e) in the manual 578## 579InstallMethod( RcwaMappingNC, 580 "rcwa mapping of Z by modulus and values (RCWA)", 581 true, [ IsInt, IsList ], 0, 582 583 function ( modulus, values ) 584 585 local coeffs, pts, r; 586 587 coeffs := []; 588 for r in [1..modulus] do 589 pts := Filtered(values, pt -> pt[1] mod modulus = r - 1); 590 coeffs[r] := [ pts[1][2] - pts[2][2], 591 pts[1][2] * (pts[1][1] - pts[2][1]) 592 - pts[1][1] * (pts[1][2] - pts[2][2]), 593 pts[1][1] - pts[2][1]]; 594 od; 595 return RcwaMappingNC( coeffs ); 596 end ); 597 598############################################################################# 599## 600#M RcwaMapping( <pi>, <coeffs> ) . . . . . . . . . method (f) in the manual 601## 602InstallMethod( RcwaMapping, 603 "rcwa mapping by noninvertible primes and coeff's (RCWA)", 604 true, [ IsObject, IsList ], 0, 605 606 function ( pi, coeffs ) 607 608 local R, quiet; 609 610 quiet := ValueOption("BeQuiet") = true; 611 if IsInt(pi) then pi := [pi]; fi; R := Z_pi(pi); 612 if not ( IsList(pi) and ForAll(pi,IsInt) 613 and IsSubset(Union(pi,[1]),Set(Factors(Length(coeffs)))) 614 and ForAll(Flat(coeffs), x -> IsRat(x) and Intersection(pi, 615 Set(Factors(DenominatorRat(x))))=[]) 616 and ForAll(coeffs, IsList) 617 and ForAll(coeffs, c -> Length(c) = 3) 618 and ForAll([0..Length(coeffs) - 1], 619 n -> coeffs[n + 1][3] <> 0 and 620 NumeratorRat(n * coeffs[n + 1][1] 621 + coeffs[n + 1][2]) 622 mod StandardAssociate(R,coeffs[n + 1][3]) = 0 623 and NumeratorRat( (n + Length(coeffs)) 624 * coeffs[n + 1][1] 625 + coeffs[n + 1][2]) 626 mod StandardAssociate(R,coeffs[n + 1][3]) = 0)) 627 then if quiet then return fail; fi; 628 Error("the coefficients ",coeffs," do not define a proper ", 629 "rcwa mapping of Z_(",pi,").\n"); 630 fi; 631 return RcwaMappingNC(pi,coeffs); 632 end ); 633 634############################################################################# 635## 636#M RcwaMappingNC( <pi>, <coeffs> ) . . . . . . . NC-method (f) in the manual 637## 638InstallMethod( RcwaMappingNC, 639 "rcwa mapping by noninvertible primes and coeff's (RCWA)", 640 true, [ IsObject, IsList ], 0, 641 642 function ( pi, coeffs ) 643 644 local ReduceRcwaMappingOfZ_pi, f, R, fam; 645 646 ReduceRcwaMappingOfZ_pi := function ( f ) 647 648 local c, m, pi, d_pi, d_piprime, divs, d, cRed, n, i; 649 650 c := f!.coeffs; m := f!.modulus; 651 pi := NoninvertiblePrimes(Source(f)); 652 for n in [1..Length(c)] do 653 if c[n][3] < 0 then c[n] := -c[n]; fi; 654 d_pi := Gcd(Product(Filtered(Factors(Gcd(NumeratorRat(c[n][1]), 655 NumeratorRat(c[n][2]))), 656 p -> p in pi or p = 0)), 657 NumeratorRat(c[n][3])); 658 d_piprime := c[n][3]/Product(Filtered(Factors(NumeratorRat(c[n][3])), 659 p -> p in pi)); 660 c[n] := c[n] / (d_pi * d_piprime); 661 od; 662 divs := DivisorsInt(m); i := 1; 663 repeat 664 d := divs[i]; i := i + 1; 665 cRed := List([1..m/d], i -> c{[(i - 1) * d + 1 .. i * d]}); 666 until Length(Set(cRed)) = 1; 667 cRed := cRed[1]; 668 RCWAMAPPING_COMPRESS_COEFFICIENT_LIST(cRed); 669 f!.coeffs := Immutable(cRed); 670 f!.modulus := Length(cRed); 671 end; 672 673 if IsInt(pi) then pi := [pi]; fi; 674 if not IsList(pi) or not ForAll(pi,IsInt) or not ForAll(coeffs,IsList) 675 then TryNextMethod(); fi; 676 R := Z_pi(pi); fam := RcwaMappingsFamily( R ); 677 f := Objectify( NewType( fam, IsRcwaMappingOfZ_piInStandardRep ), 678 rec( coeffs := coeffs, 679 modulus := Length(coeffs) ) ); 680 SetSource(f,R); SetRange(f,R); 681 ReduceRcwaMappingOfZ_pi(f); 682 return f; 683 end ); 684 685############################################################################# 686## 687#M RcwaMapping( <q>, <modulus>, <coeffs> ) . . . . method (g) in the manual 688## 689InstallMethod( RcwaMapping, 690 Concatenation("rcwa mapping by finite field size, ", 691 "modulus and coefficients (RCWA)"), 692 true, [ IsInt, IsPolynomial, IsList ], 0, 693 694 function ( q, modulus, coeffs ) 695 696 local d, x, P, p, quiet; 697 698 quiet := ValueOption("BeQuiet") = true; 699 if not ( IsPosInt(q) and IsPrimePowerInt(q) 700 and ForAll(coeffs, IsList) 701 and ForAll(coeffs, c -> Length(c) = 3) 702 and ForAll(Flat(coeffs), IsPolynomial) 703 and Length(Set(List(Flat(coeffs), 704 IndeterminateNumberOfLaurentPolynomial)))=1) 705 then if quiet then return fail; fi; 706 Error("see RCWA manual for information on how to construct\n", 707 "an rcwa mapping of a polynomial ring.\n"); 708 fi; 709 d := DegreeOfLaurentPolynomial(modulus); 710 x := IndeterminateOfLaurentPolynomial(coeffs[1][1]); 711 P := AllGFqPolynomialsModDegree(q,d,x); 712 if not ForAll([1..Length(P)], 713 i -> IsZero( (coeffs[i][1]*P[i] + coeffs[i][2]) 714 mod coeffs[i][3])) 715 then Error("the coefficients ",coeffs," do not define a proper ", 716 "rcwa mapping.\n"); 717 fi; 718 return RcwaMappingNC( q, modulus, coeffs ); 719 end ); 720 721############################################################################# 722## 723#M RcwaMappingNC( <q>, <modulus>, <coeffs> ) . . NC-method (g) in the manual 724## 725InstallMethod( RcwaMappingNC, 726 Concatenation("rcwa mapping by finite field size, ", 727 "modulus and coefficients (RCWA)"), 728 true, [ IsInt, IsPolynomial, IsList ], 0, 729 730 function ( q, modulus, coeffs ) 731 732 local ReduceRcwaMappingOfGFqx, f, R, fam, ind; 733 734 ReduceRcwaMappingOfGFqx := function ( f ) 735 736 local c, m, F, q, x, deg, r, fact, d, degd, 737 sigma, csorted, numresred, numresd, mred, rred, 738 n, l, i; 739 740 c := f!.coeffs; m := f!.modulus; 741 for n in [1..Length(c)] do 742 d := Gcd(c[n]); 743 c[n] := c[n]/(d * LeadingCoefficient(c[n][3])); 744 od; 745 deg := DegreeOfLaurentPolynomial(m); 746 F := CoefficientsRing(UnderlyingRing(FamilyObj(f))); 747 q := Size(F); 748 x := UnderlyingIndeterminate(FamilyObj(f)); 749 r := AllGFqPolynomialsModDegree(q,deg,x); 750 fact := Difference(Factors(m),[One(m)]); 751 for d in fact do 752 degd := DegreeOfLaurentPolynomial(d); 753 repeat 754 numresd := q^degd; numresred := q^(deg-degd); 755 mred := m/d; 756 rred := List(r, P -> P mod mred); 757 sigma := SortingPerm(rred); 758 csorted := Permuted(c,sigma); 759 if ForAll([1..numresred], 760 i->Length(Set(csorted{[(i-1)*numresd+1..i*numresd]}))=1) 761 then m := mred; 762 deg := deg - degd; 763 r := AllGFqPolynomialsModDegree(q,deg,x); 764 c := csorted{[1, 1 + numresd .. 1 + (numresred-1) * numresd]}; 765 fi; 766 until m <> mred or not IsZero(m mod d); 767 od; 768 RCWAMAPPING_COMPRESS_COEFFICIENT_LIST(c); 769 f!.coeffs := Immutable(c); 770 f!.modulus := m; 771 end; 772 773 ind := IndeterminateNumberOfLaurentPolynomial( coeffs[1][1] ); 774 R := PolynomialRing( GF( q ), [ ind ] ); 775 fam := RcwaMappingsFamily( R ); 776 f := Objectify( NewType( fam, IsRcwaMappingOfGFqxInStandardRep ), 777 rec( coeffs := coeffs, 778 modulus := modulus ) ); 779 SetUnderlyingField( f, CoefficientsRing( R ) ); 780 SetSource( f, R ); SetRange( f, R ); 781 ReduceRcwaMappingOfGFqx( f ); 782 return f; 783 end ); 784 785############################################################################# 786## 787#M RcwaMapping( <P1>, <P2> ) . . . . . . . . . . . method (h) in the manual 788## 789InstallMethod( RcwaMapping, 790 "rcwa mapping by two class partitions (RCWA)", 791 true, [ IsList, IsList ], 0, 792 793 function ( P1, P2 ) 794 795 local result; 796 797 if not ( ForAll(Concatenation(P1,P2),IsResidueClass) 798 and Length(P1) = Length(P2) 799 and Sum(List(P1,Density)) = 1 800 and Union(P1) = UnderlyingRing(FamilyObj(P1[1]))) 801 then TryNextMethod(); fi; 802 result := RcwaMappingNC(P1,P2); 803 IsBijective(result); 804 return result; 805 end ); 806 807############################################################################# 808## 809#M RcwaMappingNC( <P1>, <P2> ) . . . . . . . . . NC-method (h) in the manual 810## 811InstallMethod( RcwaMappingNC, 812 "rcwa mapping by two class partitions (RCWA)", 813 true, [ IsList, IsList ], 0, 814 815 function ( P1, P2 ) 816 817 local R, coeffs, m, res, r1, m1, r2, m2, i, j; 818 819 if not IsResidueClassUnion(P1[1]) then TryNextMethod(); fi; 820 R := UnderlyingRing(FamilyObj(P1[1])); 821 m := Lcm(R,List(P1,Modulus)); res := AllResidues(R,m); 822 coeffs := List(res,r->[1,0,1]*One(R)); 823 for i in [1..Length(P1)] do 824 r1 := Residue(P1[i]); m1 := Modulus(P1[i]); 825 r2 := Residue(P2[i]); m2 := Modulus(P2[i]); 826 for j in Filtered([1..Length(res)],j->res[j] mod m1 = r1) do 827 coeffs[j] := [m2,m1*r2-m2*r1,m1]; 828 od; 829 od; 830 return RcwaMappingNC(R,m,coeffs); 831 end ); 832 833############################################################################# 834## 835#M RcwaMappingNC( <P1>, <P2> ) . . . . NC-method (h) in the manual, for Z^2 836## 837InstallMethod( RcwaMappingNC, 838 "rcwa mapping by two class partitions of Z^2 (RCWA)", 839 true, [ IsList, IsList ], 0, 840 841 function ( P1, P2 ) 842 843 local R, coeffs, m, res, affectedpos, t, r1, m1, r2, m2, i, j; 844 845 if not IsResidueClassUnionOfZxZ(P1[1]) then TryNextMethod(); fi; 846 R := UnderlyingRing(FamilyObj(P1[1])); 847 m := Lcm(List(P1,Modulus)); res := AllResidues(R,m); 848 coeffs := List(res,r->[[[1,0],[0,1]],[0,0],1]); 849 for i in [1..Length(P1)] do 850 r1 := Residue(P1[i]); m1 := Modulus(P1[i]); 851 r2 := Residue(P2[i]); m2 := Modulus(P2[i]); 852 affectedpos := Filtered([1..Length(res)],j->res[j] mod m1 = r1); 853 t := [m1^-1*m2,r2-r1*m1^-1*m2,1]; 854 t := t * Lcm(List(Flat(t),DenominatorRat)); 855 for i in affectedpos do coeffs[i] := t; od; 856 od; 857 return RcwaMappingNC(R,m,coeffs); 858 end ); 859 860############################################################################# 861## 862#M RcwaMapping( <cycles> ) . . . . . . . . . . . . method (i) in the manual 863## 864InstallMethod( RcwaMapping, 865 "rcwa mapping by class cycles (RCWA)", true, [ IsList ], 0, 866 867 function ( cycles ) 868 869 local CheckClassCycles, R; 870 871 CheckClassCycles := function ( R, cycles ) 872 873 if not ( ForAll(cycles,IsList) 874 and ForAll(Flat(cycles),S->IsResidueClass(S) 875 and IsSubset(R,S))) 876 or ForAny(Combinations(Flat(cycles),2),s->Intersection(s) <> []) 877 then Error("there is no rcwa mapping of ",R," having the class ", 878 "cycles ",cycles,".\n"); 879 fi; 880 end; 881 882 if not IsList(cycles[1]) or not IsResidueClass(cycles[1][1]) 883 then TryNextMethod(); fi; 884 R := cycles[1][1]; 885 if not (IsRing(R) or IsZxZ(R)) 886 then R := UnderlyingRing(FamilyObj(R)); fi; 887 CheckClassCycles(R,cycles); 888 return RcwaMappingNC(cycles); 889 end ); 890 891############################################################################# 892## 893#M RcwaMapping( <cycles> ) . method (i), variation for rc. with fixed rep's 894## 895InstallMethod( RcwaMapping, 896 "rcwa mapping by class cycles (fixed rep's) (RCWA)", 897 true, [ IsList ], 0, 898 899 function ( cycles ) 900 901 local CheckClassCycles, R; 902 903 CheckClassCycles := function ( R, cycles ) 904 905 if not ( ForAll(cycles,IsList) 906 and ForAll(Flat(cycles),S->IsResidueClassWithFixedRep(S) 907 and UnderlyingRing(FamilyObj(S)) = R)) 908 or ForAny(Combinations(Flat(cycles),2), 909 s->Intersection(List([s[1],s[2]], 910 AsOrdinaryUnionOfResidueClasses)) <> []) 911 then Error("there is no rcwa mapping of ",R," having the class ", 912 "cycles ",cycles,".\n"); 913 fi; 914 end; 915 916 if not IsList(cycles[1]) 917 or not IsResidueClassWithFixedRepresentative(cycles[1][1]) 918 then TryNextMethod(); fi; 919 R := UnderlyingRing(FamilyObj(cycles[1][1])); 920 CheckClassCycles(R,cycles); 921 return RcwaMappingNC(cycles); 922 end ); 923 924############################################################################# 925## 926#M RcwaMappingNC( <cycles> ) . . . . . . . . . . NC-method (i) in the manual 927## 928InstallMethod( RcwaMappingNC, 929 "rcwa mapping by class cycles (RCWA)", true, [ IsList ], 0, 930 931 function ( cycles ) 932 933 local result, R, coeffs, m, res, cyc, pre, im, affectedpos, 934 r1, r2, m1, m2, pos, i; 935 936 if not IsResidueClass(cycles[1][1]) 937 and not IsResidueClassWithFixedRepresentative(cycles[1][1]) 938 then TryNextMethod(); fi; 939 940 R := cycles[1][1]; 941 if not (IsRing(R) or IsZxZ(R)) 942 then R := UnderlyingRing(FamilyObj(R)); fi; 943 if not IsIntegers(R) and not IsZ_pi(R) 944 and not ( IsUnivariatePolynomialRing(R) 945 and IsFiniteFieldPolynomialRing(R)) 946 then TryNextMethod(); fi; 947 948 m := Lcm(List(Union(cycles),Modulus)); 949 res := AllResidues(R,m); 950 coeffs := List(res,r->[1,0,1]*One(R)); 951 for cyc in cycles do 952 if Length(cyc) <= 1 then continue; fi; 953 for pos in [1..Length(cyc)] do 954 pre := cyc[pos]; im := cyc[pos mod Length(cyc) + 1]; 955 r1 := Residue(pre); m1 := Modulus(pre); 956 r2 := Residue(im); m2 := Modulus(im); 957 affectedpos := Filtered([1..Length(res)], 958 i->res[i] mod m1 = r1 mod m1); 959 for i in affectedpos do coeffs[i] := [m2,m1*r2-m2*r1,m1]; od; 960 od; 961 od; 962 if IsIntegers(R) 963 then result := RcwaMappingNC(coeffs); 964 elif IsZ_pi(R) 965 then result := RcwaMappingNC(R,coeffs); 966 elif IsPolynomialRing(R) 967 then result := RcwaMappingNC(R,Lcm(List(Flat(cycles),Modulus)),coeffs); 968 fi; 969 Assert(4,Order(result)=Lcm(List(cycles,Length))); 970 SetIsBijective(result,true); SetIsTame(result,true); 971 SetOrder(result,Lcm(List(cycles,Length))); 972 return result; 973 end ); 974 975############################################################################# 976## 977#M RcwaMappingNC( <cycles> ) . . . . . NC-method (i) in the manual, for Z^2 978## 979InstallMethod( RcwaMappingNC, 980 "rcwa mapping of Z^2 by class cycles (RCWA)", true, 981 [ IsList ], 0, 982 983 function ( cycles ) 984 985 local result, R, coeffs, m, res, cyc, pre, im, affectedpos, t, 986 r1, r2, m1, m2, pos, i; 987 988 if not IsResidueClass(cycles[1][1]) 989 or not IsResidueClassUnionOfZxZ(cycles[1][1]) 990 then TryNextMethod(); fi; 991 992 R := UnderlyingRing(FamilyObj(cycles[1][1])); 993 m := Lcm(List(Union(cycles),Modulus)); 994 res := AllResidues(R,m); 995 coeffs := List(res,r->[[[1,0],[0,1]],[0,0],1]); 996 for cyc in cycles do 997 if Length(cyc) <= 1 then continue; fi; 998 for pos in [1..Length(cyc)] do 999 pre := cyc[pos]; im := cyc[pos mod Length(cyc) + 1]; 1000 r1 := Residue(pre); m1 := Modulus(pre); 1001 r2 := Residue(im); m2 := Modulus(im); 1002 affectedpos := Filtered([1..Length(res)],i->res[i] mod m1 = r1); 1003 t := [m1^-1*m2,r2-r1*m1^-1*m2,1]; 1004 t := t * Lcm(List(Flat(t),DenominatorRat)); 1005 for i in affectedpos do coeffs[i] := t; od; 1006 od; 1007 od; 1008 result := RcwaMapping(R,m,coeffs); 1009 Assert(4,Order(result)=Lcm(List(cycles,Length))); 1010 SetIsBijective(result,true); SetIsTame(result,true); 1011 SetOrder(result,Lcm(List(cycles,Length))); 1012 return result; 1013 end ); 1014 1015############################################################################# 1016## 1017#M RcwaMapping( <expression> ) . . . . . . . . . . method (j) in the manual 1018## 1019InstallMethod( RcwaMapping, 1020 "rcwa mapping of Z by expression, given as a string (RCWA)", 1021 true, [ IsString ], 0, 1022 1023 function ( expression ) 1024 if IsSubset( "0123456789-,()crs^*/", expression ) 1025 then return RcwaMappingNC( expression ); 1026 else TryNextMethod(); fi; 1027 end ); 1028 1029############################################################################# 1030## 1031#M RcwaMappingNC( <expression> ) . . . . . . . . NC-method (j) in the manual 1032## 1033InstallMethod( RcwaMappingNC, 1034 "rcwa mapping of Z by expression, given as a string (RCWA)", 1035 true, [ IsString ], 0, 1036 1037 function ( expression ) 1038 1039 local ValueExpression, ValueElementaryExpression; 1040 1041 ValueElementaryExpression := function ( exp ) 1042 1043 local ints, cycle, i; 1044 1045 if IsSubset("0123456789-",exp) then return Int(exp); fi; 1046 ints := List(Filtered(SplitString(exp,"()[],crs"), 1047 s->s<>""),Int); 1048 if Length(ints) = 2 then 1049 if 's' in exp 1050 then return ClassShift(ints); 1051 else return ClassReflection(ints); fi; 1052 elif Length(ints) = 4 then 1053 return ClassTransposition(ints); 1054 elif Length(ints) mod 2 = 0 then 1055 cycle := []; 1056 for i in [1,3..Length(ints)-1] do 1057 Add(cycle,ResidueClass(ints[i],ints[i+1])); 1058 od; 1059 return RcwaMapping([cycle]); 1060 else Error("unknown type of rcwa permutation\n"); fi; 1061 end; 1062 1063 ValueExpression := function ( exp ) 1064 1065 local brackets, parts, part, operators, 1066 values, valuesexp, value, i, j; 1067 1068 if IsSubset("0123456789-,()crs",exp) 1069 then return ValueElementaryExpression(exp); fi; 1070 1071 brackets := 0; parts := []; operators := []; part := ""; 1072 for i in [1..Length(exp)] do 1073 Add(part,exp[i]); 1074 if exp[i] = '(' then 1075 brackets := brackets + 1; 1076 elif exp[i] = ')' then 1077 brackets := brackets - 1; 1078 if brackets = 0 then 1079 Add(parts,part); part := ""; 1080 fi; 1081 elif brackets = 0 and exp[i] in "*/^" then 1082 Add(operators,exp[i]); 1083 Add(parts,part{[1..Length(part)-1]}); part := ""; 1084 fi; 1085 od; 1086 Add(parts,part); 1087 parts := Filtered(parts,part->Intersection(part,"0123456789")<>""); 1088 for i in [1..Length(parts)] do 1089 if parts[i][1] = '(' 1090 then parts[i] := parts[i]{[2..Length(parts[i])-1]}; fi; 1091 od; 1092 values := List(parts,ValueExpression); 1093 valuesexp := ShallowCopy(values); 1094 for i in [1..Length(operators)] do 1095 if operators[i] = '^' then 1096 valuesexp[i] := valuesexp[i]^valuesexp[i+1]; 1097 valuesexp[i+1] := fail; 1098 fi; 1099 od; 1100 valuesexp := Filtered(valuesexp,val->val<>fail); 1101 1102 operators := Filtered(operators,op->op<>'^'); 1103 value := valuesexp[1]; 1104 for i in [1..Length(operators)] do 1105 if operators[i] = '*' 1106 then value := value * valuesexp[i+1]; 1107 elif operators[i] = '/' 1108 then value := value / valuesexp[i+1]; 1109 else Error("RcwaMapping: unknown operator: ",operators[i],"\n"); fi; 1110 od; 1111 1112 return value; 1113 end; 1114 1115 return ValueExpression( BlankFreeString( expression ) ); 1116 end ); 1117 1118############################################################################# 1119## 1120#M RcwaMapping( <R>, <f>, <g> ) . rcwa mapping of Z^2 by two rcwa map's of Z 1121#M RcwaMapping( <f>, <g> ) 1122## 1123InstallMethod( RcwaMapping, 1124 "rcwa mapping of Z^2 by two rcwa mappings of Z (RCWA)", 1125 ReturnTrue, 1126 [ IsRowModule, IsRcwaMappingOfZ, IsRcwaMappingOfZ ], 0, 1127 function ( R, f, g ) 1128 if IsZxZ(R) then return RcwaMappingNC(f,g); 1129 else TryNextMethod(); fi; 1130 end ); 1131 1132InstallMethod( RcwaMapping, 1133 "rcwa mapping of Z^2 by two rcwa mappings of Z (RCWA)", 1134 IsIdenticalObj, [ IsRcwaMappingOfZ, IsRcwaMappingOfZ ], 0, 1135 function ( f, g ) return RcwaMappingNC(f,g); end ); 1136 1137############################################################################# 1138## 1139#M RcwaMappingNC( <f>, <g> ) . rcwa mapping of Z^2 by two rcwa mappings of Z 1140## 1141InstallMethod( RcwaMappingNC, 1142 "rcwa mapping of Z^2 by two rcwa mappings of Z (RCWA)", 1143 IsIdenticalObj, [ IsRcwaMappingOfZ, IsRcwaMappingOfZ ], 0, 1144 1145 function ( f, g ) 1146 1147 local result, m, mf, mg, c, cf, cg, res, r, t, d, d1, d2; 1148 1149 mf := Modulus(f); mg := Modulus(g); 1150 m := [[mf,0],[0,mg]]; res := AllResidues(Integers^2,m); 1151 cf := Coefficients(f); cg := Coefficients(g); c := []; 1152 for r in res do 1153 t := [cf[r[1]+1],cg[r[2]+1]]; 1154 d := Lcm(t[1][3],t[2][3]); d1 := d/t[1][3]; d2 := d/t[2][3]; 1155 Add(c,[[[t[1][1]*d1,0],[0,t[2][1]*d2]],[t[1][2]*d1,t[2][2]*d2],d]); 1156 od; 1157 result := RcwaMapping(Integers^2,m,c); 1158 if ForAny([f,g],HasIsClassTransposition) 1159 then IsClassTransposition(result); fi; 1160 return result; 1161 end ); 1162 1163############################################################################# 1164## 1165#M RcwaMapping( <coeffs> ) . . . rcwa mapping of Z in sparse representation 1166## 1167InstallMethod( RcwaMapping, 1168 "rcwa mapping of Z in sparse representation (RCWA)", 1169 true, [ IsList ], 5, 1170 1171 function ( coeffs ) 1172 1173 local result; 1174 1175 if not ForAll(coeffs,c->IsList(c) and Length(c)=5 and ForAll(c,IsInt)) 1176 then TryNextMethod(); fi; 1177 1178 if ForAny(coeffs,c->c[2] = 0 or c[5] = 0) then 1179 Error("zero in modulus or denominator not allowed.\n"); 1180 return fail; 1181 fi; 1182 if ForAny(Combinations([1..Length(coeffs)],2), 1183 i->( coeffs[i[1]][1]-coeffs[i[2]][1]) 1184 mod Gcd(coeffs[i[1]][2],coeffs[i[2]][2]) = 0) 1185 then Error("rcwa mapping must be single-valued.\n"); return fail; fi; 1186 if Sum(List(coeffs,c->1/c[2])) <> 1 1187 then Error("rcwa mapping must be total.\n"); return fail; fi; 1188 1189 return RcwaMappingNC(coeffs); 1190 end ); 1191 1192############################################################################# 1193## 1194#M RcwaMappingNC( <coeffs> ) . . rcwa mapping of Z in sparse representation 1195## 1196InstallMethod( RcwaMappingNC, 1197 "rcwa mapping of Z in sparse representation (RCWA)", 1198 true, [ IsList ], 5, 1199 1200 function ( coeffs ) 1201 1202 local result, modulus, coeffset, coeffcoll, cls, redcls, cl, 1203 d, d_red, res, res_d, div, m, r, r_red, range, i, j; 1204 1205 if not ForAll(coeffs,c->IsList(c) and Length(c)=5) 1206 or not ForAll(coeffs[1],IsInt) 1207 then TryNextMethod(); fi; 1208 1209 for i in [1..Length(coeffs)] do 1210 coeffs[i][2] := AbsInt(coeffs[i][2]); 1211 coeffs[i][1] := coeffs[i][1] mod coeffs[i][2]; 1212 coeffs[i]{[3..5]} := coeffs[i]{[3..5]}/Gcd(coeffs[i]{[3..5]}); 1213 if coeffs[i][5] < 0 then coeffs[i]{[3..5]} := -coeffs[i]{[3..5]}; fi; 1214 od; 1215 1216 coeffset := Set(List(coeffs,c->c{[3..5]})); 1217 coeffcoll := List(coeffset,c->[]); 1218 for i in [1..Length(coeffs)] do 1219 j := PositionSorted(coeffset,coeffs[i]{[3..5]}); 1220 Add(coeffcoll[j],coeffs[i]); 1221 od; 1222 1223 coeffs := []; 1224 for i in [1..Length(coeffset)] do 1225 1226 cls := Set(coeffcoll[i],c->c{[1,2]}); 1227 if Length(cls) > 1 then 1228 1229 d_red := Gcd(DifferencesList(List(cls,cl->cl[1]))); 1230 d_red := Gcd(d_red,Gcd(List(cls,cl->cl[2]))); 1231 r_red := cls[1][1] mod d_red; 1232 redcls := List(cls,cl->[(cl[1]-r_red)/d_red,cl[2]/d_red]); 1233 m := Lcm(List(redcls,cl->cl[2])); 1234 res := []; 1235 for cl in redcls do 1236 for j in [0..m/cl[2]-1] do Add(res,cl[1]+j*cl[2]); od; 1237 od; 1238 res := Set(res); 1239 1240 redcls := []; 1241 div := DivisorsInt(m); 1242 for d in div do 1243 res_d := Set(res mod d); 1244 for r in res_d do 1245 range := List([0..m/d-1],j->r+j*d); 1246 if IsSubset(res,range) then 1247 Add(redcls,[r,d]); 1248 res := Difference(res,range); 1249 if res = [] then break; fi; 1250 if Length(res) < m/d then break; fi; 1251 fi; 1252 od; 1253 if res = [] then break; fi; 1254 od; 1255 1256 cls := List(redcls,cl->[cl[1]*d_red+r_red,cl[2]*d_red]); 1257 1258 # Erroneous reduction process: doesn't cope with cases like 1259 # 0(3) U 1(6) U 5(6) = 1(2) U 0(6). 1260 # 1261 # repeat 1262 # oldcls := ShallowCopy(cls); 1263 # mods := Set(List(oldcls,cl->cl[2])); 1264 # for m in mods do 1265 # resm := List(Set(Filtered(cls,cl->cl[2]=m)),c->c[1]); 1266 # if Length(resm) >= 2 then 1267 # for p in Set(Factors(m)) do 1268 # for r in Filtered(resm,res->res<m/p) do 1269 # # range := [r,r+m/p..m-m/p+r]; -> range restriction (<2^28) 1270 # range := List([0..p-1],j->j*(m/p)+r); 1271 # if IsSubset(resm,range) then 1272 # cls := Difference(cls,List(range,r->[r,m])); 1273 # Add(cls,[r,m/p]); 1274 # fi; 1275 # od; 1276 # od; 1277 # fi; 1278 # od; 1279 # cls := Set(cls); 1280 # until cls = oldcls; 1281 1282 fi; 1283 1284 for cl in cls do 1285 Add(coeffs,Concatenation(cl,coeffset[i])); 1286 od; 1287 1288 od; 1289 1290 # SortParallel(List(coeffs,c->[c[2],c[1]]),coeffs); -> problematic? 1291 coeffs := Set(coeffs); 1292 modulus := Lcm(List(coeffs,c->c[2])); 1293 1294 MakeImmutable(coeffs); 1295 result := Objectify( NewType( RcwaMappingsOfZFamily, 1296 IsRcwaMappingOfZ 1297 and IsRcwaMappingSparseRep ), 1298 rec( modulus := modulus, 1299 coeffs := coeffs ) ); 1300 SetSource(result,Integers); 1301 SetRange (result,Integers); 1302 1303 return result; 1304 end ); 1305 1306############################################################################# 1307## 1308#S Conversion of rcwa mappings between standard and sparse representation. / 1309## 1310############################################################################# 1311 1312############################################################################# 1313## 1314#M SparseRepresentation( <f> ) 1315## 1316InstallMethod( SparseRepresentation, 1317 "for rcwa mappings in standard representation (RCWA)", 1318 true, [ IsRcwaMappingInStandardRep ], 0, 1319 1320 function ( f ) 1321 1322 local result, attrs, attrsetters, props, propsetters, attr, prop, 1323 R, coeffs, src, sparse, cl, r, m, c, i; 1324 1325 R := Source(f); 1326 coeffs := f!.coeffs; 1327 1328 src := Set(Flat(List(LargestSourcesOfAffineMappings(f), 1329 AsUnionOfFewClasses))); 1330 sparse := []; 1331 for cl in src do 1332 r := Residue(cl); m := Modulus(cl); 1333 if IsRcwaMappingOfZ(f) 1334 then c := coeffs[r+1]; 1335 else c := coeffs[Position(AllResidues(R,m),r)]; fi; 1336 Add(sparse,[r,m,c[1],c[2],c[3]]); 1337 od; 1338 1339 sparse := Set(sparse); 1340 1341 result := Objectify(NewType(FamilyObj(f),RcwaMappingsType(R) 1342 and IsRcwaMappingSparseRep), 1343 rec(modulus := f!.modulus, coeffs := sparse)); 1344 1345 # Copy over representation-independent attributes and properties. 1346 1347 attrs := List( Intersection( RCWA_REP_INDEPENDENT_ATTRIBUTES, 1348 KnownAttributesOfObject( f ) ), 1349 ValueGlobal ); 1350 attrsetters := List(attrs,Setter); 1351 for i in [1..Length(attrs)] do attrsetters[i](result,attrs[i](f)); od; 1352 1353 props := List( Intersection( RCWA_REP_INDEPENDENT_PROPERTIES, 1354 KnownPropertiesOfObject( f ) ), 1355 ValueGlobal ); 1356 propsetters := List(props,Setter); 1357 for i in [1..Length(props)] do propsetters[i](result,props[i](f)); od; 1358 1359 return result; 1360 end ); 1361 1362############################################################################# 1363## 1364#M SparseRepresentation( <f> ) 1365## 1366InstallMethod( SparseRepresentation, 1367 "for rcwa mappings in sparse representation (RCWA)", 1368 true, [ IsRcwaMappingInSparseRep ], 0, f -> f ); 1369 1370############################################################################# 1371## 1372#M StandardRepresentation( <f> ) 1373## 1374InstallMethod( StandardRepresentation, 1375 "for rcwa mappings in sparse representation (RCWA)", 1376 true, [ IsRcwaMappingInSparseRep ], 0, 1377 1378 function ( f ) 1379 1380 local result, attrs, attrsetters, props, propsetters, 1381 R, modulus, coeffs, src, sparse, res, cl, r, m, c, n, i; 1382 1383 R := Source(f); 1384 modulus := f!.modulus; 1385 sparse := f!.coeffs; 1386 1387 if IsRing(R) then 1388 coeffs := List([1..NumberOfResidues(R,modulus)],r->[1,0,1]*One(R)); 1389 elif IsZxZ(R) then 1390 coeffs := List([1..NumberOfResidues(R,modulus)], 1391 r->[[[1,0],[0,1]],[0,0],1]); 1392 fi; 1393 1394 res := AllResidues(R,modulus); 1395 for i in [1..Length(sparse)] do 1396 c := sparse[i]; 1397 r := c[1]; m := c[2]; 1398 if IsRcwaMappingOfZ(f) then 1399 for n in [r+1,r+m+1..modulus-m+r+1] do 1400 coeffs[n] := c{[3..5]}; 1401 od; 1402 else 1403 for n in PositionsProperty(res,el->el mod m = r) do 1404 coeffs[n] := c{[3..5]}; 1405 od; 1406 fi; 1407 od; 1408 1409 result := Objectify(NewType(FamilyObj(f),RcwaMappingsType(R) 1410 and IsRcwaMappingStandardRep), 1411 rec( modulus := modulus, coeffs := coeffs )); 1412 1413 # Copy over representation-independent attributes and properties. 1414 1415 attrs := List( Intersection( RCWA_REP_INDEPENDENT_ATTRIBUTES, 1416 KnownAttributesOfObject( f ) ), 1417 ValueGlobal ); 1418 attrsetters := List(attrs,Setter); 1419 for i in [1..Length(attrs)] do attrsetters[i](result,attrs[i](f)); od; 1420 1421 props := List( Intersection( RCWA_REP_INDEPENDENT_PROPERTIES, 1422 KnownPropertiesOfObject( f ) ), 1423 ValueGlobal ); 1424 propsetters := List(props,Setter); 1425 for i in [1..Length(props)] do propsetters[i](result,props[i](f)); od; 1426 1427 return result; 1428 end ); 1429 1430############################################################################# 1431## 1432#M StandardRepresentation( <f> ) 1433## 1434InstallMethod( StandardRepresentation, 1435 "for rcwa mappings in standard representation (RCWA)", 1436 true, [ IsRcwaMappingInStandardRep ], 0, f -> f ); 1437 1438############################################################################# 1439## 1440#S ExtRepOfObj / ObjByExtRep for rcwa mappings. //////////////////////////// 1441## 1442############################################################################# 1443 1444############################################################################# 1445## 1446#M ExtRepOfObj( <f> ) . . . . . . . . . . . . . . . . . . for rcwa mappings 1447## 1448InstallMethod( ExtRepOfObj, 1449 "for rcwa mappings (RCWA)", true, [ IsRcwaMapping ], 0, 1450 f -> [ Modulus( f ), ShallowCopy( Coefficients( f ) ) ] ); 1451 1452############################################################################# 1453## 1454#M ExtRepOfObj( <ct> ) . . . . . . . . . . . . . . for class transpositions 1455## 1456InstallMethod( ExtRepOfObj, 1457 "for class transpositions (RCWA)", true, 1458 [ IsRcwaMapping and IsClassTransposition ], 0, 1459 1460 function ( ct ) 1461 1462 local cls; 1463 1464 cls := TransposedClasses(ct); 1465 return [ Residue(cls[1]), Mod(cls[1]), Residue(cls[2]), Mod(cls[2]) ]; 1466 end ); 1467 1468############################################################################# 1469## 1470#M ObjByExtRep( <fam>, <l> ) . rcwa mapping, by list [ <modulus>, <coeffs> ] 1471## 1472InstallMethod( ObjByExtRep, 1473 "rcwa mapping, by list [ <modulus>, <coefficients> ] (RCWA)", 1474 ReturnTrue, [ IsFamily, IsList ], 0, 1475 1476 function ( fam, l ) 1477 1478 local R; 1479 1480 if not HasUnderlyingRing(fam) or Length(l) <> 2 then TryNextMethod(); fi; 1481 R := UnderlyingRing(fam); 1482 if fam <> RcwaMappingsFamily(R) then TryNextMethod(); fi; 1483 if ForAll(l[2],c->IsList(c) and Length(c)=5) 1484 then return RcwaMappingNC(l[2]); # sparse rep., of Z 1485 else return RcwaMappingNC(R,l[1],l[2]); fi; 1486 end ); 1487 1488############################################################################# 1489## 1490#S Creating new rcwa mappings from rcwa mappings of the same ring. ///////// 1491## 1492############################################################################# 1493 1494############################################################################# 1495## 1496#M PiecewiseMapping( <sources>, <maps> ) . . . . . . for rcwa mappings of Z 1497## 1498InstallMethod( PiecewiseMapping, 1499 "for rcwa mappings of Z (RCWA)", 1500 ReturnTrue, [ IsList, IsList ], 0, 1501 1502 function ( sources, maps ) 1503 1504 local map, coeffs, f, c, S, t, cls, cl, i; 1505 1506 if Length(sources) <> Length(maps) 1507 or not ForAll(sources,IsListOrCollection) 1508 or not ForAll(maps,IsMapping) 1509 then return fail; fi; 1510 if not ForAll(sources,IsResidueClassUnionOfZ) 1511 or not ForAll(maps,IsRcwaMappingOfZ) 1512 or not IsIntegers(Union(sources)) 1513 or Sum(List(sources,Density)) <> 1 1514 then TryNextMethod(); fi; 1515 1516 maps := List(maps,SparseRep); 1517 coeffs := []; 1518 for i in [1..Length(maps)] do 1519 S := sources[i]; 1520 f := maps[i]; 1521 c := Coefficients(f); 1522 for t in c do 1523 cls := AsUnionOfFewClasses(Intersection(ResidueClass(t[1],t[2]),S)); 1524 for cl in cls do 1525 Add(coeffs,[Residue(cl),Modulus(cl),t[3],t[4],t[5]]); 1526 od; 1527 od; 1528 od; 1529 map := RcwaMapping(coeffs); 1530 return SparseRep(map); 1531 end ); 1532 1533############################################################################# 1534## 1535#S Creating new rcwa mappings from rcwa mappings of different rings. /////// 1536## 1537############################################################################# 1538 1539############################################################################# 1540## 1541#F LocalizedRcwaMapping( <f>, <p> ) 1542## 1543InstallGlobalFunction( LocalizedRcwaMapping, 1544 1545 function ( f, p ) 1546 if not IsRcwaMappingOfZ(f) or not IsInt(p) or not IsPrimeInt(p) 1547 then Error("usage: see ?LocalizedRcwaMapping( f, p )\n"); fi; 1548 return SemilocalizedRcwaMapping( f, [ p ] ); 1549 end ); 1550 1551############################################################################# 1552## 1553#F SemilocalizedRcwaMapping( <f>, <pi> ) 1554## 1555InstallGlobalFunction( SemilocalizedRcwaMapping, 1556 1557 function ( f, pi ) 1558 if IsRcwaMappingOfZ(f) and IsList(pi) and ForAll(pi,IsPosInt) 1559 and ForAll(pi,IsPrimeInt) and IsSubset(pi,Factors(Modulus(f))) 1560 then return RcwaMapping(Z_pi(pi),ShallowCopy(Coefficients(f))); 1561 else Error("usage: see ?SemilocalizedRcwaMapping( f, pi )\n"); fi; 1562 end ); 1563 1564############################################################################# 1565## 1566#M ProjectionsToCoordinates( <f> ) . . . . . . . . for rcwa mappings of Z^2 1567## 1568InstallMethod( ProjectionsToCoordinates, 1569 "rcwa mapping of Z^2 to two rcwa mappings of Z (RCWA)", true, 1570 [ IsRcwaMappingOfZxZ ], 0, 1571 1572 function ( f ) 1573 1574 local m, mf, mg, c, cf, cg, res, t, t1, t2, r, i; 1575 1576 m := Modulus(f); c := Coefficients(f); 1577 res := AllResidues(Integers^2,m); 1578 mf := m[1][1]; mg := m[2][2]; cf := []; cg := []; 1579 for i in [1..Length(res)] do 1580 t := c[i]; r := res[i]; 1581 t1 := [t[1][1][1],t[2][1],t[3]]; t1 := t1/Gcd(t1); 1582 t2 := [t[1][2][2],t[2][2],t[3]]; t2 := t2/Gcd(t2); 1583 if not IsBound(cf[r[1]+1]) then cf[r[1]+1] := t1; 1584 elif cf[r[1]+1] <> t1 then return fail; fi; 1585 if not IsBound(cg[r[2]+1]) then cg[r[2]+1] := t2; 1586 elif cg[r[2]+1] <> t2 then return fail; fi; 1587 if t[1][1][2] <> 0 or t[1][2][1] <> 0 then return fail; fi; 1588 od; 1589 return [ RcwaMapping(cf), RcwaMapping(cg) ]; 1590 end ); 1591 1592############################################################################# 1593## 1594#M Projection( <f>, <coord> ) . proj. of an rcwa mapping of Z^2 to 1 coord. 1595## 1596InstallOtherMethod( Projection, 1597 "for rcwa mappings of Z^2 (RCWA)", 1598 ReturnTrue, [ IsRcwaMappingOfZxZ, IsPosInt ], 0, 1599 1600 function ( f, coord ) 1601 1602 local m, c, c_proj, proj; 1603 1604 if not coord in [1,2] then return fail; fi; # there are only 2 coord's 1605 1606 proj := ProjectionsToCoordinates(f); # maybe even both projections exist 1607 if proj <> fail then return proj[coord]; fi; 1608 1609 m := Modulus(f); # check whether the choice of the affine partial mapping 1610 # depends only on the specified coordinate: 1611 if m[1][2] <> 0 or m[2][1] <> 0 or m[3-coord][3-coord] <> 1 1612 then return fail; fi; 1613 1614 c := Coefficients(f); # check for dependency on other coordinate: 1615 if not ForAll(c,t->t[1][3-coord][coord]=0) then return fail; fi; 1616 1617 # build coefficient list in one dimension: 1618 c_proj := List(c,t->[t[1][coord][coord],t[2][coord],t[3]]); 1619 1620 return RcwaMapping(c_proj); 1621 end ); 1622 1623############################################################################# 1624## 1625#S The automorphism switching action on negative and nonnegative integers. / 1626## 1627############################################################################# 1628 1629############################################################################# 1630## 1631#M Mirrored( <f> ) . . . . . . . . . for rcwa mappings of Z in standard rep. 1632#M Mirrored( <f> ) . . . . . . . . . for rcwa mappings of Z in sparse rep. 1633## 1634InstallOtherMethod( Mirrored, 1635 "for rcwa mappings of Z in standard rep. (RCWA)", 1636 true, [ IsRcwaMappingOfZInStandardRep ], 0, 1637 f -> f^RcwaMapping( [ [ -1, -1, 1 ] ] ) ); 1638InstallOtherMethod( Mirrored, 1639 "for rcwa mappings of Z in sparse rep. (RCWA)", 1640 true, [ IsRcwaMappingOfZInSparseRep ], 0, 1641 f -> f^RcwaMapping( [ [ 0, 1, -1, -1, 1 ] ] ) ); 1642 1643############################################################################# 1644## 1645#S Constructors and basic methods for special types of rcwa permutations. // 1646## 1647############################################################################# 1648 1649############################################################################# 1650## 1651#F ClassShift( <R>, <r>, <m> ) . . . . . . . . . . . . . class shift nu_r(m) 1652#F ClassShift( <r>, <m> ) . . . . . . . . . . . . . . . . . . . . . (dito) 1653#F ClassShift( <R>, <cl> ) . . . . . . class shift nu_r(m), where cl = r(m) 1654#F ClassShift( <cl> ) . . . . . . . . . . . . . . . . . . . . . . . (dito) 1655#F ClassShift( <R> ) . . . . . . . . . . . . . class shift nu_R: n -> n + 1 1656## 1657## (Enclosing the argument list in list brackets is permitted.) 1658## 1659InstallGlobalFunction( ClassShift, 1660 1661 function ( arg ) 1662 1663 local result, R, coeff, idcoeff, res, pos, r, m, latex; 1664 1665 if Length(arg) = 1 and IsList(arg[1]) then arg := arg[1]; fi; 1666 1667 if IsZxZ(arg[1]) 1668 or IsRowVector(arg[1]) and Length(arg[1]) = 2 and ForAll(arg[1],IsInt) 1669 or IsResidueClassOfZxZ(arg[1]) 1670 then return CallFuncList(ClassShiftOfZxZ,arg); fi; 1671 1672 if not Length(arg) in [1..3] 1673 or Length(arg) = 1 and not IsResidueClass(arg[1]) 1674 or Length(arg) = 2 1675 and not ( ForAll(arg,IsRingElement) 1676 or IsRing(arg[1]) 1677 and IsResidueClass(arg[2]) 1678 and arg[1] = UnderlyingRing(FamilyObj(arg[2]))) 1679 or Length(arg) = 3 1680 and not ( IsRing(arg[1]) 1681 and IsSubset(arg[1],arg{[2,3]})) 1682 then Error("usage: see ?ClassShift( r, m )\n"); fi; 1683 1684 if IsRing(arg[1]) then R := arg[1]; arg := arg{[2..Length(arg)]}; fi; 1685 if IsBound(R) and IsEmpty(arg) 1686 then arg := [0,1] * One(R); 1687 elif IsResidueClass(arg[1]) 1688 then if not IsBound(R) then R := UnderlyingRing(FamilyObj(arg[1])); fi; 1689 arg := [Residue(arg[1]),Modulus(arg[1])] * One(R); 1690 elif not IsBound(R) then R := DefaultRing(arg[2]); fi; 1691 arg := arg * One(R); # Now we know R, and we have arg = [r,m]. 1692 1693 m := StandardAssociate(R,arg[2]); 1694 r := arg[1] mod m; 1695 res := AllResidues(R,m); 1696 idcoeff := [1,0,1]*One(R); 1697 coeff := List(res,r->idcoeff); 1698 pos := PositionSorted(res,r); 1699 coeff[pos] := [1,m,1]*One(R); 1700 result := RcwaMapping(R,m,coeff); 1701 SetIsClassShift(result,true); SetIsBijective(result,true); 1702 if Characteristic(R) = 0 1703 then SetOrder(result,infinity); 1704 else SetOrder(result,Characteristic(R)); fi; 1705 SetIsTame(result,true); 1706 SetBaseRoot(result,result); SetPowerOverBaseRoot(result,1); 1707 if IsIntegers(R) then 1708 SetSmallestRoot(result,result); SetPowerOverSmallestRoot(result,1); 1709 fi; 1710 SetFactorizationIntoCSCRCT(result,[result]); 1711 1712 latex := ValueOption("LaTeXString"); 1713 if latex = fail then 1714 if IsOne(m) then 1715 SetLaTeXString(result,"\\nu"); 1716 else 1717 SetLaTeXString(result,Concatenation("\\nu_{",String(r),"(", 1718 String(m),")}")); 1719 fi; 1720 elif not IsEmpty(latex) then SetLaTeXString(result,latex); fi; 1721 1722 return result; 1723 end ); 1724 1725############################################################################# 1726## 1727#F ClassShiftOfZxZ( <R>, <r>, <m>, <coord> ) class shift nu_r(m),c; c=coord 1728#F ClassShiftOfZxZ( <r>, <m>, <coord> ) . . . . . . . . . . . . . . (dito) 1729#F ClassShiftOfZxZ( <R>, <cl>, <coord> ) . . class shift nu_r(m),c; cl=r(m) 1730#F ClassShiftOfZxZ( <cl>, <coord> ) . . . . . . . . . . . . . . . . (dito) 1731#F ClassShiftOfZxZ( <R>, <coord> ) . . . . . . . . . . . class shift nu_R_c 1732## 1733## This function is called by `ClassShift' if the first argument is either 1734## Integers^2, a row vector of length 2 with integer entries or a residue 1735## class of Integers^2. Enclosing the argument list in list brackets is 1736## permitted. 1737## 1738InstallGlobalFunction( ClassShiftOfZxZ, 1739 1740 function ( arg ) 1741 1742 local result, R, M, r, m, coord, cl, coeff, idcoeff, res, pos, latex; 1743 1744 R := Integers^2; M := FullMatrixAlgebra(Integers,2); 1745 1746 if Length(arg) = 1 and IsList(arg[1]) then arg := arg[1]; fi; 1747 1748 coord := arg[Length(arg)]; arg := arg{[1..Length(arg)-1]}; 1749 if IsZxZ(arg[1]) then arg := arg{[2..Length(arg)]}; fi; 1750 1751 if not coord in [1,2] 1752 or not Length(arg) in [0..2] 1753 or Length(arg) = 1 and not IsResidueClassOfZxZ(arg[1]) 1754 or Length(arg) = 2 and not (arg[1] in R and arg[2] in M) 1755 then Error("usage: see ?ClassShift( r, m, coord )\n"); fi; 1756 1757 if arg = [] then cl := R; 1758 elif Length(arg) = 1 then cl := arg[1]; 1759 else cl := ResidueClass(arg[1],arg[2]); fi; 1760 1761 r := Residue(cl); m := Modulus(cl); 1762 1763 res := AllResidues(R,m); 1764 idcoeff := [[[1,0],[0,1]],[0,0],1]; 1765 coeff := ListWithIdenticalEntries(Length(res),idcoeff); 1766 pos := PositionSorted(res,r); 1767 coeff[pos] := [[[1,0],[0,1]],m[coord],1]; 1768 result := RcwaMapping(R,m,coeff); 1769 SetIsClassShift(result,true); SetIsBijective(result,true); 1770 SetOrder(result,infinity); 1771 SetIsTame(result,true); 1772 SetBaseRoot(result,result); SetPowerOverBaseRoot(result,1); 1773 SetFactorizationIntoCSCRCT(result,[result]); 1774 1775 latex := ValueOption("LaTeXString"); 1776 if latex = fail then 1777 latex := Concatenation("\\nu_{",ViewString(cl),",",String(coord),"}"); 1778 latex := ReplacedString(latex,"Z","\\mathbb{Z}"); 1779 SetLaTeXString(result,latex); 1780 elif not IsEmpty(latex) then SetLaTeXString(result,latex); fi; 1781 1782 return result; 1783 end ); 1784 1785############################################################################# 1786## 1787#M IsClassShift( <sigma> ) . . . . . . . . . . . . . . . . for rcwa mappings 1788## 1789InstallMethod( IsClassShift, 1790 "for rcwa mappings (RCWA)", true, [ IsRcwaMapping ], 0, 1791 sigma -> IsResidueClass(Support(sigma)) 1792 and sigma = ClassShift(Support(sigma)) ); 1793 1794############################################################################# 1795## 1796#M IsPowerOfClassShift( <sigma> ) . . . . . . . . . . for rcwa mappings of Z 1797## 1798InstallMethod( IsPowerOfClassShift, "for rcwa mappings of Z (RCWA)", true, 1799 [ IsRcwaMappingOfZ ], 0, 1800 1801 function ( sigma ) 1802 1803 local cl, c; 1804 1805 if not IsClassWiseOrderPreserving(sigma) then return false; fi; 1806 if IsSignPreserving(sigma) then return IsOne(sigma); fi; 1807 if not IsBijective(sigma) then return false; fi; 1808 cl := Support(sigma); 1809 if not IsResidueClass(cl) then return false; fi; 1810 if Mod(sigma) <> Mod(cl) then return false; fi; 1811 return true; 1812 end ); 1813 1814############################################################################# 1815## 1816#M String( <cs> ) . . . . . . . . . . . . . . . . . . . . . for class shifts 1817#M ViewString( <cs> ) . . . . . . . . . . . . . . . . . . . for class shifts 1818#M PrintObj( <cs> ) . . . . . . . . . . . . . . . . . . . . for class shifts 1819#M ViewObj( <cs> ) . . . . . . . . . . . . . . . . . . . . for class shifts 1820## 1821InstallMethod( String, "for class shifts (RCWA)", true, 1822 [ IsRcwaMapping and IsClassShift ], SUM_FLAGS, 1823 1824 function ( cs ) 1825 1826 local str; 1827 1828 if IsRcwaMappingOfZ(cs) then 1829 str := Concatenation(List(["ClassShift(",Residue(Support(cs)),",", 1830 Modulus(Support(cs))],String)); 1831 else 1832 str := Concatenation(List(["ClassShift(",Source(cs),",", 1833 Residue(Support(cs)),",", 1834 Modulus(Support(cs))],String)); 1835 fi; 1836 if IsRcwaMappingOfZxZ(cs) then 1837 Append(str,","); 1838 Append(str,String(PositionNonZero(Residue(Support(cs))^cs 1839 -Residue(Support(cs))))); 1840 fi; 1841 return Concatenation(BlankFreeString(str),")"); 1842 end ); 1843 1844InstallMethod( ViewString, "for class shifts (RCWA)", true, 1845 [ IsRcwaMapping and IsClassShift ], SUM_FLAGS, 1846 1847 function ( cs ) 1848 1849 local cl, name, suppname; 1850 1851 if ValueOption("PrintNotation") = true 1852 then return String(cs); fi; 1853 if ValueOption("AbridgedNotation") = true 1854 then name := "cs"; else name := "ClassShift"; fi; 1855 cl := Support(cs); 1856 if IsRing(cl) or IsZxZ(cl) then suppname := RingToString(cl); 1857 else suppname := ViewString(cl); fi; 1858 if IsRing(Source(cs)) then 1859 return Concatenation(List([name,"( ",suppname," )"],String)); 1860 elif IsRcwaMappingOfZxZ(cs) then 1861 return Concatenation(List([name,"( ",suppname,", ", 1862 PositionNonZero(Residue(Support(cs))^cs 1863 -Residue(Support(cs)))," )"], 1864 String)); 1865 else TryNextMethod(); fi; 1866 end ); 1867 1868InstallMethod( ViewString, "for powers of class shifts of Z (RCWA)", true, 1869 [ IsRcwaMappingOfZ and IsPowerOfClassShift ], SUM_FLAGS, 1870 1871 function ( cs ) 1872 if IsClassShift(cs) then TryNextMethod(); fi; 1873 return Concatenation(ViewString(ClassShift(Support(cs))),"^", 1874 String(First(List(Coefficients(cs),c->c[2]), 1875 b->b<>0)/Modulus(cs))); 1876 end ); 1877 1878InstallMethod( PrintObj, "for class shifts (RCWA)", true, 1879 [ IsRcwaMapping and IsClassShift ], SUM_FLAGS+10, 1880 function ( cs ) Print( String( cs ) ); end ); 1881 1882InstallMethod( ViewObj, "for class shifts (RCWA)", true, 1883 [ IsRcwaMapping and IsClassShift ], 20, 1884 function ( cs ) Print( ViewString( cs ) ); end ); 1885 1886InstallMethod( ViewObj, "for powers of class shifts (RCWA)", true, 1887 [ IsRcwaMapping and IsPowerOfClassShift ], 20, 1888 function ( cs ) Print( ViewString( cs ) ); end ); 1889 1890############################################################################# 1891## 1892#F ClassReflection( <R>, <r>, <m> ) . . . . class reflection varsigma_r(m) 1893#F ClassReflection( <r>, <m> ) . . . . . . . . . . . . . . . . . . . (dito) 1894#F ClassReflection( <R>, <cl> ) . class reflection varsigma_r(m), cl = r(m) 1895#F ClassReflection( <cl> ) . . . . . . . . . . . . . . . . . . . . . (dito) 1896#F ClassReflection( <R> ) . . . . . . class reflection varsigma_R: n -> -n 1897## 1898## (Enclosing the argument list in list brackets is permitted.) 1899## 1900InstallGlobalFunction( ClassReflection, 1901 1902 function ( arg ) 1903 1904 local result, R, coeff, idcoeff, res, pos, r, m, latex; 1905 1906 if Length(arg) = 1 and IsList(arg[1]) then arg := arg[1]; fi; 1907 1908 if IsZxZ(arg[1]) 1909 or IsRowVector(arg[1]) and Length(arg[1]) = 2 and ForAll(arg[1],IsInt) 1910 or IsResidueClassOfZxZ(arg[1]) 1911 then 1912 return CallFuncList(ClassRotationOfZxZ, 1913 Concatenation(arg,[[[-1,0],[0,-1]]])); 1914 fi; 1915 1916 if not Length(arg) in [1..3] 1917 or Length(arg) = 1 and not IsResidueClass(arg[1]) 1918 or Length(arg) = 2 1919 and not ( ForAll(arg,IsRingElement) 1920 or IsRing(arg[1]) 1921 and IsResidueClass(arg[2]) 1922 and arg[1] = UnderlyingRing(FamilyObj(arg[2]))) 1923 or Length(arg) = 3 1924 and not ( IsRing(arg[1]) 1925 and IsSubset(arg[1],arg{[2,3]})) 1926 then Error("usage: see ?ClassReflection( r, m )\n"); fi; 1927 1928 if IsRing(arg[1]) then R := arg[1]; arg := arg{[2..Length(arg)]}; fi; 1929 if IsBound(R) and IsEmpty(arg) 1930 then arg := [0,1] * One(R); 1931 elif IsResidueClass(arg[1]) 1932 then if not IsBound(R) then R := UnderlyingRing(FamilyObj(arg[1])); fi; 1933 arg := [Residue(arg[1]),Modulus(arg[1])] * One(R); 1934 elif not IsBound(R) then R := DefaultRing(arg[2]); fi; 1935 if Characteristic(R) = 2 then return One(RCWA(R)); fi; # Now we know R... 1936 arg := arg * One(R); # ...and we have arg = [r,m]. 1937 1938 m := StandardAssociate(R,arg[2]); 1939 r := arg[1] mod m; 1940 res := AllResidues(R,m); 1941 idcoeff := [1,0,1]*One(R); 1942 coeff := List(res,r->idcoeff); 1943 pos := PositionSorted(res,r); 1944 coeff[pos] := [-1,2*r,1]*One(R); 1945 result := RcwaMapping(R,m,coeff); 1946 SetIsClassReflection(result,true); 1947 SetRotationFactor(result,-1); 1948 SetIsBijective(result,true); 1949 SetOrder(result,2); SetIsTame(result,true); 1950 SetFactorizationIntoCSCRCT(result,[result]); 1951 1952 latex := ValueOption("LaTeXString"); 1953 if latex = fail then 1954 if IsOne(m) then 1955 SetLaTeXString(result,"\\varsigma"); 1956 else 1957 SetLaTeXString(result,Concatenation("\\varsigma_{",String(r),"(", 1958 String(m),")}")); 1959 fi; 1960 elif not IsEmpty(latex) then SetLaTeXString(result,latex); fi; 1961 1962 return result; 1963 end ); 1964 1965############################################################################# 1966## 1967#M IsClassReflection( <sigma> ) . . . . . . . . . . . . . for rcwa mappings 1968## 1969InstallMethod( IsClassReflection, 1970 "for rcwa mappings (RCWA)", true, [ IsRcwaMapping ], 0, 1971 sigma -> IsResidueClass(Union(Support(sigma), 1972 ExcludedElements(Support(sigma)))) and 1973 sigma = ClassReflection(Union(Support(sigma), 1974 ExcludedElements(Support(sigma)))) ); 1975 1976############################################################################# 1977## 1978#M String( <cr> ) . . . . . . . . . . . . . . . . . . for class reflections 1979#M ViewString( <cr> ) . . . . . . . . . . . . . . . . for class reflections 1980## 1981InstallMethod( String, "for class reflections (RCWA)", true, 1982 [ IsRcwaMapping and IsClassReflection ], SUM_FLAGS, 1983 1984 function ( cr ) 1985 if IsRcwaMappingOfZ(cr) then 1986 return Concatenation(List(["ClassReflection(", 1987 Residue(Support(cr)),",", 1988 Modulus(Support(cr)),")"],BlankFreeString)); 1989 else 1990 return Concatenation(List(["ClassReflection(",Source(cr),",", 1991 Residue(Support(cr)),",", 1992 Modulus(Support(cr)),")"],BlankFreeString)); 1993 fi; 1994 end ); 1995 1996InstallMethod( ViewString, "for class reflections (RCWA)", true, 1997 [ IsRcwaMapping and IsClassReflection ], SUM_FLAGS, 1998 1999 function ( cr ) 2000 2001 local cl, name, suppname; 2002 2003 if ValueOption("PrintNotation") = true 2004 then return String(cr); fi; 2005 if ValueOption("AbridgedNotation") = true 2006 then name := "cr"; else name := "ClassReflection"; fi; 2007 cl := Union(Support(cr),ExcludedElements(Support(cr))); 2008 if IsRing(cl) or IsZxZ(cl) then suppname := RingToString(cl); 2009 else suppname := ViewString(cl); fi; 2010 return Concatenation(List([name,"( ",suppname," )"],String)); 2011 end ); 2012 2013############################################################################# 2014## 2015#F ClassRotation( <R>, <r>, <m>, <u> ) . . . . . class rotation rho_(r(m),u) 2016#F ClassRotation( <r>, <m>, <u> ) . . . . . . . . . . . . . . . . . (dito) 2017#F ClassRotation( <R>, <cl>, <u> ) . class rotation rho_(r(m),u), cl = r(m) 2018#F ClassRotation( <cl>, <u> ) . . . . . . . . . . . . . . . . . . . (dito) 2019#F ClassRotation( <R>, <u> ) . . . . . . . class rotation rho_(R,u): n -> un 2020## 2021## (Enclosing the argument list in list brackets is permitted.) 2022## 2023InstallGlobalFunction( ClassRotation, 2024 2025 function ( arg ) 2026 2027 local result, R, coeff, idcoeff, res, pos, r, m, u, latex; 2028 2029 if Length(arg) = 1 and IsList(arg[1]) then arg := arg[1]; fi; 2030 2031 if IsZxZ(arg[1]) 2032 or IsRowVector(arg[1]) and Length(arg[1]) = 2 and ForAll(arg[1],IsInt) 2033 or IsResidueClassOfZxZ(arg[1]) 2034 then return CallFuncList(ClassRotationOfZxZ,arg); fi; 2035 2036 if not Length(arg) in [2..4] 2037 or Length(arg) = 2 2038 and not ( IsResidueClass(arg[1]) 2039 and IsCollsElms(FamilyObj(arg[1]),FamilyObj(arg[2]))) 2040 or Length(arg) = 3 2041 and not ( ForAll(arg,IsRingElement) 2042 or IsRing(arg[1]) 2043 and IsResidueClass(arg[2]) 2044 and arg[1] = UnderlyingRing(FamilyObj(arg[2])) 2045 and arg[3] in arg[1]) 2046 or Length(arg) = 4 2047 and not ( IsRing(arg[1]) 2048 and IsSubset(arg[1],arg{[2,3,4]})) 2049 then Error("usage: see ?ClassRotation( r, m, u )\n"); fi; 2050 2051 if IsRing(arg[1]) then R := arg[1]; arg := arg{[2..Length(arg)]}; fi; 2052 if IsBound(R) and Length(arg) = 1 2053 then arg := [0,1,arg[1]] * One(R); 2054 elif IsResidueClass(arg[1]) 2055 then if not IsBound(R) then R := UnderlyingRing(FamilyObj(arg[1])); fi; 2056 arg := [Residue(arg[1]),Modulus(arg[1]),arg[2]] * One(R); 2057 elif not IsBound(R) then R := DefaultRing(arg{[2,3]}); fi; 2058 arg := arg * One(R); # Now we know R, and we have arg = [r,m,u]. 2059 2060 m := StandardAssociate(R,arg[2]); 2061 r := arg[1] mod m; 2062 u := arg[3]; 2063 2064 if IsOne( u) then return One(RCWA(R)); 2065 elif IsOne(-u) then return ClassReflection(ResidueClass(R,m,r)); fi; 2066 2067 res := AllResidues(R,m); 2068 idcoeff := [1,0,1]*One(R); 2069 coeff := List(res,r->idcoeff); 2070 pos := PositionSorted(res,r); 2071 coeff[pos] := [u,(1-u)*r,1]*One(R); 2072 result := RcwaMapping(R,m,coeff); 2073 SetIsClassRotation(result,true); 2074 SetRotationFactor(result,u); 2075 SetIsBijective(result,true); 2076 SetOrder(result,Order(u)); SetIsTame(result,true); 2077 SetBaseRoot(result,result); SetPowerOverBaseRoot(result,1); 2078 SetFactorizationIntoCSCRCT(result,[result]); 2079 2080 latex := ValueOption("LaTeXString"); 2081 if latex = fail then 2082 if IsOne(m) then 2083 SetLaTeXString(result,Concatenation("\\rho_{",String(u),"}")); 2084 else 2085 SetLaTeXString(result,Concatenation("\\rho_{",String(r),"(", 2086 String(m),"),",String(u),"}")); 2087 fi; 2088 elif not IsEmpty(latex) then SetLaTeXString(result,latex); fi; 2089 2090 return result; 2091 end ); 2092 2093############################################################################# 2094## 2095#F ClassRotationOfZxZ( ... ) . . . . . . . . . . . . . class rotation of Z^2 2096## 2097## This function is called by `ClassRotation' if the first argument is 2098## either Integers^2, a row vector of length 2 with integer entries or 2099## a residue class of Integers^2. For recognized arguments, see there. 2100## 2101InstallGlobalFunction( ClassRotationOfZxZ, 2102 2103 function ( arg ) 2104 2105 local result, R, mats, r, m, u, uimg, M, U, Uimg, cl, 2106 coeff, idcoeff, res, pos, latex; 2107 2108 if Length(arg) = 1 and IsList(arg[1]) then arg := arg[1]; fi; 2109 2110 R := Integers^2; mats := FullMatrixAlgebra(Integers,2); 2111 2112 u := arg[Length(arg)]; arg := arg{[1..Length(arg)-1]}; 2113 if IsZxZ(arg[1]) then arg := arg{[2..Length(arg)]}; fi; 2114 2115 if not u in mats or not DeterminantMat(u) in [-1,1] 2116 or not Length(arg) in [0..2] 2117 or Length(arg) = 1 and not IsResidueClassOfZxZ(arg[1]) 2118 or Length(arg) = 2 and not (arg[1] in R and arg[2] in mats) 2119 then Error("usage: see ?ClassRotation( r, m, u )\n"); fi; 2120 2121 if IsOne(u) then return IdentityRcwaMappingOfZxZ; fi; 2122 2123 if arg = [] then cl := R; 2124 elif Length(arg) = 1 then cl := arg[1]; 2125 else cl := ResidueClass(arg[1],arg[2]); fi; 2126 2127 r := Residue(cl); m := Modulus(cl); 2128 2129 res := AllResidues(R,m); 2130 idcoeff := [[[1,0],[0,1]],[0,0],1]; 2131 coeff := ListWithIdenticalEntries(Length(res),idcoeff); 2132 2133 M := NullMat(3,3); 2134 M{[1..2]}{[1..2]} := m; 2135 M[3][3] := 1; 2136 M[3]{[1..2]} := r; 2137 2138 U := NullMat(3,3); 2139 U{[1..2]}{[1..2]} := u; 2140 U[3][3] := 1; 2141 2142 Uimg := U^M; 2143 Uimg := Uimg * Lcm(List(Flat(Uimg),DenominatorRat)); 2144 uimg := Uimg{[1..2]}{[1..2]}; 2145 2146 pos := PositionSorted(res,r); 2147 coeff[pos] := [uimg,Uimg[3]{[1..2]},Uimg[3][3]]; 2148 2149 result := RcwaMapping(R,m,coeff); 2150 2151 SetIsClassRotation(result,true); 2152 SetRotationFactor(result,u); 2153 if IsOne(-u) then SetIsClassReflection(result,true); fi; 2154 SetIsBijective(result,true); 2155 SetOrder(result,Order(u)); 2156 SetIsTame(result,true); 2157 SetBaseRoot(result,result); SetPowerOverBaseRoot(result,1); 2158 SetFactorizationIntoCSCRCT(result,[result]); 2159 2160 latex := ValueOption("LaTeXString"); 2161 if latex = fail then 2162 latex := Concatenation("\\rho_{",ViewString(cl), 2163 ",",BlankFreeString(u),"}"); 2164 latex := ReplacedString(latex,"Z","\\mathbb{Z}"); 2165 SetLaTeXString(result,latex); 2166 elif not IsEmpty(latex) then SetLaTeXString(result,latex); fi; 2167 2168 return result; 2169 end ); 2170 2171############################################################################# 2172## 2173#M IsClassRotation( <sigma> ) . . . . . . . . . . . . . . for rcwa mappings 2174## 2175InstallMethod( IsClassRotation, 2176 "for rcwa mappings (RCWA)", true, [ IsRcwaMapping ], 0, 2177 2178 function ( sigma ) 2179 2180 local S, u, c; 2181 2182 S := Union(Support(sigma),ExcludedElements(Support(sigma))); 2183 if not IsResidueClass(S) then return false; fi; 2184 c := First(Coefficients(sigma),c->not IsOne(c[1])); 2185 if c = fail then return false; else u := c[1]; fi; 2186 if sigma = ClassRotation(S,u) then 2187 SetRotationFactor(sigma,u); 2188 return true; 2189 else return false; fi; 2190 end ); 2191 2192############################################################################# 2193## 2194#M IsClassRotation( <sigma> ) . . . . . . . . . . . . for class reflections 2195## 2196InstallTrueMethod( IsClassRotation, IsClassReflection ); 2197 2198############################################################################# 2199## 2200#M String( <cr> ) . . . . . . . . . . . . . . . . . . . for class rotations 2201#M ViewString( <cr> ) . . . . . . . . . . . . . . . . . for class rotations 2202#M PrintObj( <cr> ) . . . . . . . . . . . . . . . . . . for class rotations 2203#M ViewObj( <cr> ) . . . . . . . . . . . . . . . . . . for class rotations 2204## 2205InstallMethod( String, "for class rotations (RCWA)", true, 2206 [ IsRcwaMapping and IsClassRotation ], SUM_FLAGS-10, 2207 cr -> Concatenation(List(["ClassRotation(",Source(cr),",", 2208 Residue(Support(cr)),",", 2209 Modulus(Support(cr)),",", 2210 RotationFactor(cr),")"], 2211 BlankFreeString))); 2212 2213InstallMethod( ViewString, "for class rotations (RCWA)", true, 2214 [ IsRcwaMapping and IsClassRotation ], SUM_FLAGS-10, 2215 2216 function ( cr ) 2217 2218 local cl, name, suppname; 2219 2220 if ValueOption("PrintNotation") = true 2221 then return String(cr); fi; 2222 if ValueOption("AbridgedNotation") = true 2223 then name := "cr"; else name := "ClassRotation"; fi; 2224 cl := Union(Support(cr:BeQuiet),ExcludedElements(Support(cr))); 2225 if IsRing(cl) or IsZxZ(cl) then suppname := RingToString(cl); 2226 else suppname := ViewString(cl); fi; 2227 return Concatenation(List([name,"( ",suppname,", ", 2228 RotationFactor(cr)," )"],String)); 2229 end ); 2230 2231InstallMethod( PrintObj, "for class rotations (RCWA)", true, 2232 [ IsRcwaMapping and IsClassRotation ], SUM_FLAGS+10, 2233 function ( cr ) Print( String( cr ) ); end ); 2234 2235InstallMethod( ViewObj, "for class rotations (RCWA)", true, 2236 [ IsRcwaMapping and IsClassRotation ], 20, 2237 function ( cr ) Print( ViewString( cr ) ); end ); 2238 2239############################################################################# 2240## 2241#F ClassTransposition( <R>, <r1>, <m1>, <r2>, <m2> ) . . class transposition 2242#F ClassTransposition( <r1>, <m1>, <r2>, <m2> ) tau_r1(m1),r2(m2) 2243#F ClassTransposition( <R>, <cl1>, <cl2> ) . . . dito, cl1=r1(m1) cl2=r2(m2) 2244#F ClassTransposition( <cl1>, <cl2> ) . . . . . . . . . . . . . . . (dito) 2245## 2246## (Enclosing the argument list in list brackets is permitted.) 2247## 2248InstallGlobalFunction( ClassTransposition, 2249 2250 function ( arg ) 2251 2252 local result, is_usual_ct, type, R, r1, m1, r2, m2, cl1, cl2, h, latex; 2253 2254 if Length(arg) = 1 and IsList(arg[1]) then arg := arg[1]; fi; 2255 2256 if IsZxZ(arg[1]) 2257 or IsRowVector(arg[1]) and Length(arg[1]) = 2 and ForAll(arg[1],IsInt) 2258 or IsResidueClassOfZxZ(arg[1]) 2259 then return CallFuncList(ClassTranspositionOfZxZ,arg); fi; 2260 2261 if not Length(arg) in [2..5] 2262 or Length(arg) = 2 and not (ForAll(arg,IsResidueClass) 2263 or ForAll(arg,IsResidueClassWithFixedRep)) 2264 or Length(arg) = 3 2265 and not ( IsRing(arg[1]) and ForAll(arg{[2,3]},IsResidueClass) 2266 and arg[1] = UnderlyingRing(FamilyObj(arg[2])) 2267 and arg[1] = UnderlyingRing(FamilyObj(arg[3]))) 2268 or Length(arg) = 4 and not ForAll(arg,IsRingElement) 2269 or Length(arg) = 5 and not ( IsRing(arg[1]) 2270 and IsSubset(arg[1],arg{[2..5]})) 2271 then Error("usage: see ?ClassTransposition( r1, m1, r2, m2 )\n"); fi; 2272 2273 if IsRing(arg[1]) then R := arg[1]; arg := arg{[2..Length(arg)]}; fi; 2274 if IsResidueClass(arg[1]) or IsResidueClassWithFixedRep(arg[1]) 2275 then if not IsBound(R) then R := UnderlyingRing(FamilyObj(arg[1])); fi; 2276 arg := [Residue(arg[1]),Modulus(arg[1]), 2277 Residue(arg[2]),Modulus(arg[2])] * One(R); 2278 elif not IsBound(R) then R := DefaultRing(arg{[2,4]}); fi; 2279 arg := arg * One(R); # Now we know R, and we have arg = [r1,m1,r2,m2]. 2280 2281 r1 := arg[1]; m1 := arg[2]; r2 := arg[3]; m2 := arg[4]; 2282 2283 if IsZero(m1*m2) or IsZero((r1-r2) mod Gcd(R,m1,m2)) then 2284 Error("ClassTransposition: The residue classes must be disjoint.\n"); 2285 fi; 2286 2287 is_usual_ct := m1 = StandardAssociate(R,m1) 2288 and m2 = StandardAssociate(R,m2) 2289 and r1 mod m1 = r1 and r2 mod m2 = r2; 2290 2291 if [m1,r1] > [m2,r2] 2292 then h := r1; r1 := r2; r2 := h; h := m1; m1 := m2; m2 := h; fi; 2293 2294 if is_usual_ct then 2295 cl1 := ResidueClass(R,m1,r1); 2296 cl2 := ResidueClass(R,m2,r2); 2297 else 2298 cl1 := ResidueClassWithFixedRepresentative(R,m1,r1); 2299 cl2 := ResidueClassWithFixedRepresentative(R,m2,r2); 2300 fi; 2301 2302 result := RcwaMapping([[cl1,cl2]]); 2303 2304 if is_usual_ct then SetIsClassTransposition(result,true); fi; 2305 SetIsGeneralizedClassTransposition(result,true); 2306 SetTransposedClasses(result,[cl1,cl2]); 2307 2308 latex := ValueOption("LaTeXString"); 2309 if latex = fail then 2310 if IsIntegers(R) and [m1,m2] = [2,2] then 2311 SetLaTeXString(result,"\\tau"); 2312 else 2313 SetLaTeXString(result,Concatenation("\\tau_{", 2314 String(r1),"(",String(m1),"),", 2315 String(r2),"(",String(m2),")}")); 2316 fi; 2317 elif not IsEmpty(latex) then SetLaTeXString(result,latex); fi; 2318 2319 if is_usual_ct then SetFactorizationIntoCSCRCT(result,[result]); fi; 2320 2321 return result; 2322 end ); 2323 2324############################################################################# 2325## 2326#F ClassTranspositionOfZxZ( ... ) . . . . . . . . class transposition of Z^2 2327## 2328## This function is called by `ClassTransposition' if the first argument 2329## is either Integers^2, a row vector of length 2 with integer entries 2330## or a residue class of Integers^2. For recognized arguments, see there. 2331## 2332InstallGlobalFunction( ClassTranspositionOfZxZ, 2333 2334 function ( arg ) 2335 2336 local result, R, M, r1, m1, r2, m2, cl1, cl2, h, latex; 2337 2338 if Length(arg) = 1 and IsList(arg[1]) then arg := arg[1]; fi; 2339 2340 R := Integers^2; M := FullMatrixAlgebra(Integers,2); 2341 2342 if not Length(arg) in [2..5] 2343 or Length(arg) = 2 and not ForAll(arg,IsResidueClassOfZxZ) 2344 or Length(arg) = 3 and not (IsZxZ(arg[1]) 2345 and ForAll(arg{[2,3]},IsResidueClassOfZxZ)) 2346 or Length(arg) = 4 and not ( arg[1] in R and arg[2] in M 2347 and arg[3] in R and arg[4] in M ) 2348 or Length(arg) = 5 and not ( IsZxZ(arg[1]) 2349 and arg[2] in R and arg[3] in M 2350 and arg[4] in R and arg[5] in M ) 2351 then Error("usage: see ?ClassTransposition( r1, m1, r2, m2 )\n"); fi; 2352 2353 if IsZxZ(arg[1]) then arg := arg{[2..Length(arg)]}; fi; 2354 if IsResidueClass(arg[1]) then 2355 arg := [Residue(arg[1]),Modulus(arg[1]), 2356 Residue(arg[2]),Modulus(arg[2])]; 2357 fi; # Now we have arg = [r1,m1,r2,m2]. 2358 2359 r1 := arg[1]; m1 := arg[2]; r2 := arg[3]; m2 := arg[4]; 2360 2361 if [m1,r1] > [m2,r2] 2362 then h := r1; r1 := r2; r2 := h; h := m1; m1 := m2; m2 := h; fi; 2363 2364 if DeterminantMat(m1*m2) = 0 then 2365 Error("ClassTransposition:\n", 2366 "The moduli of the residue classes must be invertible.\n"); 2367 fi; 2368 2369 cl1 := ResidueClass(R,m1,r1); 2370 cl2 := ResidueClass(R,m2,r2); 2371 2372 if Intersection(cl1,cl2) <> [] then 2373 Error("ClassTransposition: The residue classes must be disjoint.\n"); 2374 fi; 2375 2376 result := RcwaMapping([[cl1,cl2]]); 2377 2378 SetIsClassTransposition(result,true); 2379 SetIsGeneralizedClassTransposition(result,true); 2380 SetTransposedClasses(result,[cl1,cl2]); 2381 2382 latex := ValueOption("LaTeXString"); 2383 if latex = fail then 2384 latex := Concatenation("\\tau_{",ViewString(cl1),",", 2385 ViewString(cl2),"}"); 2386 latex := ReplacedString(latex,"Z","\\mathbb{Z}"); 2387 SetLaTeXString(result,latex); 2388 elif not IsEmpty(latex) then SetLaTeXString(result,latex); fi; 2389 2390 SetFactorizationIntoCSCRCT(result,[result]); 2391 2392 return result; 2393 end ); 2394 2395############################################################################# 2396## 2397#M IsClassTransposition( <sigma> ) . . . . . . . . . . . . for rcwa mappings 2398## 2399InstallMethod( IsClassTransposition, 2400 "for rcwa mappings (RCWA)", true, [ IsRcwaMapping ], 0, 2401 2402 function ( sigma ) 2403 2404 local cls; 2405 2406 if IsOne(sigma) then return false; fi; 2407 if not IsBijective(sigma) then return false; fi; 2408 if HasOrder(sigma) and Order(sigma) <> 2 then return false; fi; 2409 if IsRcwaMappingStandardRep(sigma) 2410 and Length(Set(Coefficients(sigma))) > 3 2411 then return false; fi; 2412 if IsRcwaMappingSparseRep(sigma) 2413 and Length(Set(Coefficients(sigma),c->c{[3..5]})) > 3 2414 then return false; fi; 2415 cls := AsUnionOfFewClasses(Support(sigma)); 2416 if Length(cls) = 1 then cls := SplittedClass(cls[1],2); fi; 2417 if Length(cls) > 2 then return false; fi; 2418 if sigma = ClassTransposition(cls) 2419 then SetTransposedClasses(sigma,cls); 2420 SetIsGeneralizedClassTransposition(sigma,true); 2421 return true; 2422 else return false; fi; 2423 end ); 2424 2425############################################################################# 2426## 2427#M IsClassTransposition( <sigma> ) . . . . . . . . for rcwa mappings of Z^2 2428## 2429InstallMethod( IsClassTransposition, 2430 "for rcwa mappings of Z^2 (RCWA)", true, 2431 [ IsRcwaMappingOfZxZ ], 0, 2432 2433 function ( sigma ) 2434 2435 local cls, split; 2436 2437 if IsOne(sigma) then return false; fi; 2438 if Length(Set(Coefficients(sigma))) > 3 then return false; fi; 2439 cls := AsUnionOfFewClasses(Support(sigma:BeQuiet)); 2440 if Length(cls) = 1 then 2441 for split in List([[2,1],[1,2]],v->SplittedClass(cls[1],v)) do 2442 if sigma = ClassTransposition(split) then 2443 SetTransposedClasses(sigma,split); 2444 SetIsGeneralizedClassTransposition(sigma,true); return true; 2445 fi; 2446 od; 2447 return false; 2448 elif Length(cls) = 2 then 2449 if sigma = ClassTransposition(cls) then 2450 SetTransposedClasses(sigma,cls); 2451 SetIsGeneralizedClassTransposition(sigma,true); return true; 2452 fi; 2453 else return false; fi; 2454 end ); 2455 2456############################################################################# 2457## 2458#M IsGeneralizedClassTransposition( <sigma> ) . . . . . . for rcwa mappings 2459## 2460InstallMethod( IsGeneralizedClassTransposition, 2461 "for rcwa mappings (RCWA)", true, [ IsRcwaMapping ], 0, 2462 2463 function ( sigma ) 2464 2465 local cls, cls_fixedrep, affsrc, r1, m1, r2, m2; 2466 2467 if HasIsClassTransposition(sigma) and IsClassTransposition(sigma) 2468 then return true; fi; 2469 if IsOne(sigma) or not IsBijective(sigma) 2470 or Length(Set(Coefficients(sigma))) > 3 2471 then return false; fi; 2472 affsrc := LargestSourcesOfAffineMappings(sigma); 2473 if Length(affsrc) > 3 then return false; fi; 2474 cls := Filtered(affsrc,cl->IsResidueClass(cl) 2475 and IsSubset(Support(sigma),cl)); 2476 if Length(cls) <> 2 then return false; fi; 2477 if Permutation(sigma,cls) = (1,2) then 2478 m1 := Modulus(cls[1]); r1 := Residue(cls[1]); 2479 m2 := Modulus(cls[2]); r2 := r1^sigma; 2480 if not IsClassWiseOrderPreserving(sigma) then m2 := -m2; fi; 2481 cls_fixedrep := [ ResidueClassWithFixedRep(Source(sigma),m1,r1), 2482 ResidueClassWithFixedRep(Source(sigma),m2,r2) ]; 2483 Assert(4,sigma=ClassTransposition(cls_fixedrep)); 2484 SetTransposedClasses(sigma,cls_fixedrep); 2485 return true; 2486 else return false; fi; 2487 end ); 2488 2489############################################################################# 2490## 2491#M TransposedClasses( <sigma> ) . . . . . . . . . . for class transpositions 2492## 2493InstallMethod( TransposedClasses, 2494 "for class transpositions (RCWA)", true, [ IsRcwaMapping ], 0, 2495 2496 function ( ct ) 2497 if IsClassTransposition(ct) or IsGeneralizedClassTransposition(ct) 2498 then return TransposedClasses(ct); 2499 else TryNextMethod(); fi; 2500 end ); 2501 2502############################################################################# 2503## 2504#M String( <ct> ) . . . . . . . . . . . . . . . . . for class transpositions 2505#M ViewString( <ct> ) . . . . . . . . . . . . . . . for class transpositions 2506#M PrintObj( <ct> ) . . . . . . . . . . . . . . . . for class transpositions 2507#M ViewObj( <ct> ) . . . . . . . . . . . . . . . . for class transpositions 2508## 2509InstallMethod( String, "for class transpositions (RCWA)", true, 2510 [ IsRcwaMapping and IsGeneralizedClassTransposition ], 2511 SUM_FLAGS, 2512 2513 function ( ct ) 2514 2515 local type, cls, str; 2516 2517 cls := TransposedClasses(ct); 2518 if ForAll(cls,IsResidueClass) 2519 then type := "ClassTransposition("; 2520 else type := "GeneralizedClassTransposition("; fi; 2521 if IsRcwaMappingOfZ(ct) then 2522 str := Concatenation(List([type, 2523 Residue(cls[1]),",",Modulus(cls[1]),",", 2524 Residue(cls[2]),",",Modulus(cls[2]),")"], 2525 BlankFreeString)); 2526 else 2527 str := Concatenation(List([type,Source(ct),",", 2528 Residue(cls[1]),",",Modulus(cls[1]),",", 2529 Residue(cls[2]),",",Modulus(cls[2]),")"], 2530 BlankFreeString)); 2531 fi; 2532 return BlankFreeString(str); 2533 end ); 2534 2535InstallMethod( ViewString, "for class transpositions (RCWA)", true, 2536 [ IsRcwaMapping and IsGeneralizedClassTransposition ], 2537 SUM_FLAGS, 2538 2539 function ( ct ) 2540 2541 local cls, name; 2542 2543 if ValueOption("PrintNotation") = true then return String(ct); fi; 2544 2545 cls := TransposedClasses(ct); 2546 if ForAll(cls,IsResidueClass) 2547 then name := "ClassTransposition"; 2548 else name := "GeneralizedClassTransposition"; fi; 2549 if ValueOption("CycleNotation") <> false 2550 and ValueOption("AbridgedNotation") <> false 2551 then return Filtered(Concatenation(List(["( ",cls[1],", ", 2552 cls[2]," )"], 2553 ViewString)),ch->ch<>'\"'); 2554 else return Filtered(Concatenation(List([name,"( ",cls[1],", ", 2555 cls[2]," )"], 2556 ViewString)),ch->ch<>'\"'); 2557 fi; 2558 2559 end ); 2560 2561InstallMethod( PrintObj, "for class transpositions (RCWA)", true, 2562 [ IsRcwaMapping and IsGeneralizedClassTransposition ], 2563 SUM_FLAGS+10, function ( ct ) Print( String( ct ) ); end ); 2564 2565InstallMethod( ViewObj, "for class transpositions (RCWA)", true, 2566 [ IsRcwaMapping and IsGeneralizedClassTransposition ], 20, 2567 function ( ct ) Print( ViewString( ct ) ); end ); 2568 2569############################################################################# 2570## 2571#M SplittedClassTransposition( <ct>, <k> ) . . . . . . . 2-argument version 2572## 2573InstallMethod( SplittedClassTransposition, 2574 "default method (RCWA)", ReturnTrue, 2575 [ IsRcwaMapping and IsClassTransposition, IsObject ], 0, 2576 function ( ct, k ) 2577 return SplittedClassTransposition(ct,k,false); 2578 end ); 2579 2580############################################################################# 2581## 2582#M SplittedClassTransposition( <ct>, <k>, <cross> ) . . . 3-argument version 2583## 2584InstallMethod( SplittedClassTransposition, 2585 "for a class transposition (RCWA)", ReturnTrue, 2586 [ IsRcwaMapping and IsClassTransposition, 2587 IsObject, IsBool ], 0, 2588 2589 function ( ct, k, cross ) 2590 2591 local cls, pairs; 2592 2593 if IsZero(k) or not k in Source(ct) then TryNextMethod(); fi; 2594 cls := List(TransposedClasses(ct),cl->SplittedClass(cl,k)); 2595 if cross then pairs := Cartesian(cls); 2596 else pairs := TransposedMat(cls); fi; 2597 return List(pairs,ClassTransposition); 2598 end ); 2599 2600############################################################################# 2601## 2602#F ClassPairs( [ <P> ], <m> ) 2603#F ClassPairs( [ <R> ], <m> ) 2604## 2605## In the one-argument version, this function returns a list of all 2606## unordered pairs of disjoint residue classes of Z with modulus <= <m>. 2607## If the option "divisors" is set, the list contains only those pairs of 2608## residue classes where the moduli divide <m>. 2609## 2610## In the two-argument version, if <P> is a set of primes, the function 2611## returns a list of all unordered pairs of disjoint residue classes of Z 2612## whose moduli are less than or equal to <m> and factor completely 2613## over <P>. 2614## 2615## If <R> is a ring, the function does the following: 2616## 2617## - If <R> is either the ring of integers or a semilocalization thereof, 2618## it returns a list of all unordered pairs of disjoint residue classes 2619## of <R> with modulus <= <m>. 2620## 2621## - If <R> is a univariate polynomial ring over a finite field, it 2622## returns a list of all unordered pairs of disjoint residue classes 2623## of <R> whose moduli have degree less than <m>. 2624## 2625## - If <R> is Integers^2, it returns a list of all unordered pairs of 2626## disjoint residue classes whose moduli have determinant at most <m>. 2627## 2628## The purpose of this function is to generate a list of all 2629## class transpositions whose moduli do not exceed a given bound. 2630## For reasons of saving time or memory, it may return pairs of 2631## residue classes [r1(m1),r2(m2)] in the form of 4-tuples [r1,m1,r2,m2] 2632## of ring elements. Regardless of whether it does so or not, one can 2633## always obtain the corresponding list of class transpositions by 2634## List( ClassPairs( <R>, <m> ), ClassTransposition ); 2635## 2636InstallGlobalFunction( ClassPairs, 2637 2638 function ( arg ) 2639 2640 local R, P, m, tuples, moduli, Degree, classes, 2641 m1, r1, m2, r2, d, i, j, usage; 2642 2643 usage := "usage: ClassPairs( [ <R> | <P> ], <m> )\n"; 2644 2645 if Length(arg) = 1 then 2646 m := arg[1]; 2647 if IsInt(m) then R := Integers; else R := DefaultRing(m); fi; 2648 elif Length(arg) = 2 then 2649 if IsRing(arg[1]) or IsZxZ(arg[1]) then 2650 R := arg[1]; 2651 elif IsList(arg[1]) and ForAll(arg[1],p->IsPosInt(p) and IsPrime(p)) 2652 then R := Integers; P := arg[1]; 2653 else Error(usage); return fail; fi; 2654 m := arg[2]; 2655 else Error(usage); return fail; fi; 2656 2657 if IsIntegers(R) or IsZ_pi(R) then 2658 tuples := []; 2659 if ValueOption("divisors") = true then 2660 moduli := Difference(DivisorsInt(m),[1]); 2661 elif IsBound(P) then 2662 moduli := Difference(AllSmoothIntegers(P,m),[1]); 2663 else 2664 moduli := [2..m]; 2665 fi; 2666 for i in [1..Length(moduli)] do 2667 m2 := moduli[i]; 2668 for j in [1..i] do 2669 m1 := moduli[j]; 2670 d := Gcd(m1,m2); 2671 for r1 in [0..m1-1] do 2672 for r2 in [0..m2-1] do 2673 if m1 = m2 and r1 > r2 then continue; fi; 2674 if (r1 - r2) mod d <> 0 then 2675 Add(tuples,[r1,m1,r2,m2]); 2676 fi; 2677 od; 2678 od; 2679 od; 2680 od; 2681 tuples := Set(tuples); 2682 if IsZ_pi(R) then 2683 tuples := Filtered(tuples,t->IsSubset(NoninvertiblePrimes(R), 2684 Factors(t[2]*t[4]))); 2685 fi; 2686 elif IsUnivariatePolynomialRing(R) and IsField(LeftActingDomain(R)) 2687 and IsFinite(LeftActingDomain(R)) 2688 then 2689 Degree := DegreeOfUnivariateLaurentPolynomial; 2690 tuples := []; 2691 moduli := Filtered(AllResidues(R,m),r->IsPosInt(Degree(r))); 2692 for m1 in moduli do 2693 for m2 in moduli do 2694 if m1 > m2 then continue; fi; 2695 for r1 in AllResidues(R,m1) do 2696 for r2 in AllResidues(R,m2) do 2697 if (m1 <> m2 or r1 < r2) and not IsZero((r1-r2) mod Gcd(m1,m2)) 2698 then Add(tuples,[r1,m1,r2,m2]); fi; 2699 od; 2700 od; 2701 od; 2702 od; 2703 elif IsZxZ(R) then 2704 moduli := All2x2IntegerMatricesInHNFWithDeterminantUpTo(m); 2705 classes := Concatenation(List(moduli,m->AllResidueClassesModulo(R,m))); 2706 tuples := Filtered(Combinations(classes,2), 2707 t->Intersection(t[1],t[2])=[]); 2708 else 2709 Error("ClassPairs: Sorry, the ring ",R,"\n",String(" ",19), 2710 "is currently not supported by this function.\n"); 2711 fi; 2712 return tuples; 2713 end ); 2714 2715InstallValue( CLASS_PAIRS, [ 6, ClassPairs(6) ] ); 2716InstallValue( CLASS_PAIRS_LARGE, CLASS_PAIRS ); 2717 2718############################################################################# 2719## 2720#F NumberClassPairs( <m> ) . . compute Length( ClassPairs( m ) ) efficiently 2721#F NrClassPairs( <m> ) 2722## 2723InstallGlobalFunction( NumberClassPairs, 2724 2725 function ( m ) 2726 2727 local nr, coprimes, m1, m2, modlist, mods, d; 2728 2729 if not IsPosInt( m ) then Error("usage: NrClassPairs( <m> )\n"); fi; 2730 2731 coprimes := Union([[1,1]],Filtered(Combinations([1..Int(m/2)],2), 2732 t->Gcd(t) = 1)); 2733 nr := 0; 2734 for d in [2..m] do 2735 modlist := Filtered(d*coprimes,mods->Maximum(mods)<=m); 2736 for mods in modlist do 2737 m1 := mods[1]; m2 := mods[2]; 2738 if m1 = m2 then nr := nr + m1 * (m1 - 1)/2; 2739 else nr := nr + (d - 1)/d * m1 * m2; 2740 fi; 2741 od; 2742 od; 2743 2744 return nr; 2745 end ); 2746 2747############################################################################# 2748## 2749#M PrimeSwitch( <p> ) . . . . . . . . . . . . . . . for an odd prime number 2750## 2751InstallMethod( PrimeSwitch, 2752 "for an odd prime number (RCWA)", true, [ IsPosInt ], 0, 2753 2754 function ( p ) 2755 if p = 2 or not IsPrimeInt(p) 2756 then Error("PrimeSwitch( <p> ): <p> must be an odd prime\n"); fi; 2757 return PrimeSwitch(p,1); 2758 end ); 2759 2760############################################################################# 2761## 2762#M PrimeSwitch( <p>, <k> ) . for an odd prime number and a positive integer 2763## 2764InstallMethod( PrimeSwitch, 2765 "for an odd prime number and a positive integer (RCWA)", 2766 ReturnTrue, [ IsPosInt, IsPosInt ], 0, 2767 2768 function ( p, k ) 2769 2770 local result, facts, kstr, latex; 2771 2772 if p = 2 or not IsPrimeInt(p) 2773 then Error("PrimeSwitch( <p>, <k> ): <p> must be an odd prime\n"); fi; 2774 facts := List([[k,2*k*p,0,8*k],[2*k*p-k,2*k*p,4*k,8*k], 2775 [0,4*k,k,2*k*p],[2*k,4*k,2*k*p-k,2*k*p], 2776 [2*k,2*k*p,k,4*k*p],[4*k,2*k*p,2*k*p+k,4*k*p]], 2777 ClassTransposition); 2778 result := Product(facts); SetIsPrimeSwitch(result,true); 2779 SetIsTame(result,false); SetOrder(result,infinity); 2780 SetBaseRoot(result,result); SetPowerOverBaseRoot(result,1); 2781 SetFactorizationIntoCSCRCT(result,facts); 2782 SetFactorizationIntoCSCRCT(result^-1,Reversed(facts)); 2783 latex := ValueOption("LaTeXString"); 2784 if latex = fail then 2785 if k=1 then kstr := ""; else kstr := Concatenation(",",String(k)); fi; 2786 SetLaTeXString(result,Concatenation("\\sigma_{",String(p),kstr,"}")); 2787 elif not IsEmpty(latex) then SetLaTeXString(result,latex); fi; 2788 return result; 2789 end ); 2790 2791############################################################################# 2792## 2793#M PrimeSwitch( <p>, <r>, <m> ) . for odd prime number, residue and modulus 2794## 2795InstallMethod( PrimeSwitch, 2796 "for an odd prime number, a residue and a modulus (RCWA)", 2797 ReturnTrue, [ IsPosInt, IsInt, IsPosInt ], 0, 2798 2799 function ( p, r, m ) 2800 2801 local result, facts, mp, r1, r2, rc, latex; 2802 2803 if p = 2 or not IsPrimeInt(p) or m mod 4 <> 0 then 2804 Error("PrimeSwitch( <p>, <r>, <m> ): <p> must be an odd prime ", 2805 "and <m> must be\na multiple of 4\n"); 2806 return fail; 2807 fi; 2808 2809 r := r mod m; r1 := 1 - r mod 2; 2810 if r < m/2 then r2 := r+m/2; else r2 := r-m/2; fi; 2811 facts := List([[r1,m/2,r2,m],[r2,m,r1,p*m/2],[r mod (m/2),m/2,r1,p*m/2]], 2812 ClassTransposition); 2813 result := Product(facts); 2814 2815 SetIsPrimeSwitch(result,true); 2816 SetIsTame(result,false); SetOrder(result,infinity); 2817 SetBaseRoot(result,result); SetPowerOverBaseRoot(result,1); 2818 SetFactorizationIntoCSCRCT(result,facts); 2819 SetFactorizationIntoCSCRCT(result^-1,Reversed(facts)); 2820 latex := ValueOption("LaTeXString"); 2821 if latex = fail then 2822 SetLaTeXString(result,Concatenation("\\sigma_{",String(p),",", 2823 String(r),"(",String(m),")}")); 2824 elif not IsEmpty(latex) then SetLaTeXString(result,latex); fi; 2825 2826 return result; 2827 end ); 2828 2829############################################################################# 2830## 2831#M PrimeSwitch( <p>, <cl> ) . . for an odd prime number and a residue class 2832## 2833InstallMethod( PrimeSwitch, 2834 "for an odd prime number and a residue class (RCWA)", 2835 ReturnTrue, [ IsPosInt, IsUnionOfResidueClassesOfZ ], 0, 2836 2837 function ( p, cl ) 2838 if p = 2 or not IsPrimeInt(p) 2839 then Error("PrimeSwitch( <p>, <cl> ): <p> must be an odd prime\n"); fi; 2840 if not IsResidueClass(cl) then TryNextMethod(); fi; 2841 return PrimeSwitch(p,Residue(cl),Mod(cl)); 2842 end ); 2843 2844############################################################################# 2845## 2846#M IsPrimeSwitch( <g> ) . . . . . . . . . . . . . . . for rcwa mappings of Z 2847## 2848InstallMethod( IsPrimeSwitch, 2849 "for rcwa mappings of Z (RCWA)", 2850 true, [ IsRcwaMappingOfZ ], 0, 2851 2852 function ( g ) 2853 2854 local p, cl, k; 2855 2856 if not IsBijective(g) or not IsSignPreserving(g) then return false; fi; 2857 p := Maximum(Factors(Mult(g))); 2858 if Mult(g) <> p or Div(g) <> 2 then return false; fi; 2859 cl := Multpk(g,p,1); 2860 if not IsResidueClass(cl) then return false; fi; 2861 k := Mod(cl)/4; 2862 if IsInt(k) and g = PrimeSwitch(p,k) then return true; fi; 2863 return g = PrimeSwitch(p,cl); 2864 end ); 2865 2866############################################################################# 2867## 2868#M String( <sigma_p> ) . . . . . . . . . . . . . . . . . for prime switches 2869#M ViewString( <sigma_p> ) . . . . . . . . . . . . . . . for prime switches 2870#M PrintObj( <sigma_p> ) . . . . . . . . . . . . . . . . for prime switches 2871#M ViewObj( <sigma_p> ) . . . . . . . . . . . . . . . . for prime switches 2872## 2873InstallMethod( String, "for prime switches (RCWA)", true, 2874 [ IsRcwaMapping and IsPrimeSwitch ], SUM_FLAGS, 2875 2876 function ( sigma_p ) 2877 2878 local p, k, kstr, cl; 2879 2880 p := Maximum(Factors(Multiplier(sigma_p))); 2881 k := 1/(4*Density(Multpk(sigma_p,p,1))); 2882 if IsInt(k) and sigma_p = PrimeSwitch(p,k) then 2883 if k = 1 then kstr := ""; 2884 else kstr := Concatenation(",",String(k)); fi; 2885 return Concatenation("PrimeSwitch(",String(p),kstr,")"); 2886 else 2887 cl := Multpk(sigma_p,p,1); 2888 if sigma_p = PrimeSwitch(p,cl) then 2889 return Concatenation("PrimeSwitch(",String(p),",", 2890 String(Residue(cl)),",",String(Mod(cl)),")"); 2891 else return fail; fi; 2892 fi; 2893 end ); 2894 2895InstallMethod( ViewString, "for prime switches (RCWA)", true, 2896 [ IsRcwaMapping and IsPrimeSwitch ], SUM_FLAGS, 2897 2898 function ( ps ) 2899 2900 local name; 2901 2902 if ValueOption("PrintNotation") = true 2903 then return String(ps); fi; 2904 if ValueOption("AbridgedNotation") = true 2905 then name := "ps"; else name := "PrimeSwitch"; fi; 2906 return ReplacedString(String(ps),"PrimeSwitch",name); 2907 end ); 2908 2909InstallMethod( PrintObj, "for prime switches (RCWA)", true, 2910 [ IsRcwaMapping and IsPrimeSwitch ], SUM_FLAGS+10, 2911 function ( sigma_p ) Print( String( sigma_p ) ); end ); 2912 2913InstallMethod( ViewObj, "for prime switches (RCWA)", true, 2914 [ IsRcwaMapping and IsPrimeSwitch ], 20, 2915 function ( sigma_p ) Print( ViewString( sigma_p ) ); end ); 2916 2917############################################################################# 2918## 2919#F mKnot( <m> ) . . . . . . an rcwa permutation of Timothy P. Keller's type 2920## 2921InstallGlobalFunction ( mKnot, 2922 2923 function ( m ) 2924 2925 local result; 2926 2927 if not IsPosInt(m) or m mod 2 <> 1 or m = 1 2928 then Error("usage: see ?mKnot( m )\n"); fi; 2929 result := RcwaMapping(List([0..m-1],r->[m+(-1)^r,(-1)^(r+1)*r,m])); 2930 SetIsBijective(result,true); 2931 SetIsTame(result,false); SetOrder(result,infinity); 2932 SetName(result,Concatenation("mKnot(",String(m),")")); 2933 SetLaTeXString(result,Concatenation("\\kappa_{",String(m),"}")); 2934 return result; 2935 end ); 2936 2937############################################################################# 2938## 2939#F ClassUnionShift( <S> ) . . . . . shift of rc.-union <S> by Modulus( <S> ) 2940## 2941InstallGlobalFunction( ClassUnionShift, 2942 2943 function ( S ) 2944 2945 local R, m, res, resS, r, c, f; 2946 2947 R := UnderlyingRing(FamilyObj(S)); 2948 m := Modulus(S); resS := Residues(S); res := AllResidues(R,m); 2949 c := List(res,r->[1,0,1]*One(R)); 2950 for r in resS do c[PositionSorted(res,r)] := [1,m,1]*One(R); od; 2951 return RcwaMapping(R,m,c); 2952 end ); 2953 2954############################################################################# 2955## 2956#S Methods for `String', `Print', `View', `Display' and `LaTeX'. /////////// 2957## 2958############################################################################# 2959 2960############################################################################# 2961## 2962#M String( <f> ) . . . . . . . . . . . . . . . . . . for rcwa mappings of Z 2963## 2964InstallMethod( String, 2965 "for rcwa mappings of Z (RCWA)", true, 2966 [ IsRcwaMappingOfZ ], 0, 2967 2968 function ( arg ) 2969 2970 local f, lng, s; 2971 2972 f := arg[1]; if Length(arg) > 1 then lng := arg[2]; fi; 2973 s := Concatenation( "RcwaMapping( ", String( Coefficients(f) ), " )" ); 2974 if IsBound(lng) then s := String(s,lng); fi; 2975 return s; 2976 end ); 2977 2978############################################################################# 2979## 2980#M String( <f> ) . . . . . . . . . . . . . . . . . for rcwa mappings of Z^2 2981## 2982InstallMethod( String, 2983 "for rcwa mappings of Z^2 (RCWA)", true, 2984 [ IsRcwaMappingOfZxZInStandardRep ], 0, 2985 2986 function ( arg ) 2987 2988 local f, lng, s; 2989 2990 f := arg[1]; if Length(arg) > 1 then lng := arg[2]; fi; 2991 s := Concatenation( "RcwaMapping( Integers^2, ", String( Modulus(f) ), 2992 ", ", String( Coefficients(f) ), " )" ); 2993 if IsBound(lng) then s := String(s,lng); fi; 2994 return s; 2995 end ); 2996 2997############################################################################# 2998## 2999#M String( <f> ) . . . . . . . . . . . . . . . . for rcwa mappings of Z_(pi) 3000## 3001InstallMethod( String, 3002 "for rcwa mappings of Z_(pi) (RCWA)", 3003 true, [ IsRcwaMappingOfZ_piInStandardRep ], 0, 3004 3005 function ( arg ) 3006 3007 local f, lng, s; 3008 3009 f := arg[1]; if Length(arg) > 1 then lng := arg[2]; fi; 3010 s := Concatenation( "RcwaMapping( ", 3011 String(NoninvertiblePrimes(Source(f))), ", ", 3012 String(Coefficients(f)), " )" ); 3013 if IsBound(lng) then s := String(s,lng); fi; 3014 return s; 3015 end ); 3016 3017############################################################################# 3018## 3019#M String( <f> ) . . . . . . . . . . . . . . . for rcwa mappings of GF(q)[x] 3020## 3021InstallMethod( String, 3022 "for rcwa mappings of GF(q)[x] (RCWA)", 3023 true, [ IsRcwaMappingOfGFqxInStandardRep ], 0, 3024 3025 function ( arg ) 3026 3027 local f, lng, s; 3028 3029 f := arg[1]; if Length(arg) > 1 then lng := arg[2]; fi; 3030 s := Concatenation( "RcwaMapping( ", 3031 String(Size(UnderlyingField(f))), ", ", 3032 String(Modulus(f)), ", ", 3033 String(Coefficients(f)), " )" ); 3034 if IsBound(lng) then s := String(s,lng); fi; 3035 return s; 3036 end ); 3037 3038############################################################################# 3039## 3040#M String( <f> ) . . . . . . . . . . . . . for rcwa mappings with base root 3041#M ViewString( <f> ) . . . . . . . . . . . for rcwa mappings with base root 3042## 3043InstallMethod( String, "for rcwa mappings with base root (RCWA)", true, 3044 [ IsRcwaMapping and HasBaseRoot ], 20, 3045 f -> Concatenation(String(BaseRoot(f)),"^", 3046 String(PowerOverBaseRoot(f))) ); 3047 3048InstallMethod( ViewString, "for rcwa mappings with base root (RCWA)", true, 3049 [ IsRcwaMapping and HasBaseRoot ], 0, 3050 f -> Concatenation(ViewString(BaseRoot(f)),"^", 3051 String(PowerOverBaseRoot(f))) ); 3052 3053############################################################################# 3054## 3055#M PrintObj( <f> ) . . . . . . . . . . . . . . . . . for rcwa mappings of Z 3056## 3057InstallMethod( PrintObj, 3058 "for rcwa mappings of Z (RCWA)", true, 3059 [ IsRcwaMappingOfZ ], SUM_FLAGS, 3060 3061 function ( f ) 3062 Print( "RcwaMapping( ", Coefficients(f), " )" ); 3063 end ); 3064 3065############################################################################# 3066## 3067#M PrintObj( <f> ) . . . . . . . . . . . . . . . . for rcwa mappings of Z^2 3068## 3069InstallMethod( PrintObj, 3070 "for rcwa mappings of Z^2 (RCWA)", true, 3071 [ IsRcwaMappingOfZxZInStandardRep ], SUM_FLAGS, 3072 3073 function ( f ) 3074 Print( "RcwaMapping( Integers^2, ", 3075 Modulus(f), ", ", Coefficients(f), " )" ); 3076 end ); 3077 3078############################################################################# 3079## 3080#M PrintObj( <f> ) . . . . . . . . . . . . . . . for rcwa mappings of Z_(pi) 3081## 3082InstallMethod( PrintObj, 3083 "for rcwa mappings of Z_(pi) (RCWA)", true, 3084 [ IsRcwaMappingOfZ_piInStandardRep ], SUM_FLAGS, 3085 3086 function ( f ) 3087 Print( "RcwaMapping( ", 3088 NoninvertiblePrimes(Source(f)), ", ", Coefficients(f), " )" ); 3089 end ); 3090 3091############################################################################# 3092## 3093#M PrintObj( <f> ) . . . . . . . . . . . . . . for rcwa mappings of GF(q)[x] 3094## 3095InstallMethod( PrintObj, 3096 "for rcwa mappings of GF(q)[x] (RCWA)", true, 3097 [ IsRcwaMappingOfGFqxInStandardRep ], SUM_FLAGS, 3098 3099 function ( f ) 3100 Print( "RcwaMapping( ", Size(UnderlyingField(f)), 3101 ", ", Modulus(f), ", ", Coefficients(f), " )" ); 3102 end ); 3103 3104############################################################################# 3105## 3106#M ViewObj( <f> ) . . . . . . . . . . . . . . . . . . . . for rcwa mappings 3107## 3108InstallMethod( ViewObj, 3109 "for rcwa mappings (RCWA)", true, [ IsRcwaMapping ], 0, 3110 3111 function ( f ) 3112 3113 local cycles, cyclenotation, i, j; 3114 3115 if IsZero(f) or IsOne(f) then View(f); return; fi; 3116 if HasBaseRoot(f) then 3117 View(BaseRoot(f)); Print("^",PowerOverBaseRoot(f)); return; 3118 fi; 3119 if IsOne(Modulus(f)) then Display(f:NoLineFeed); return; fi; 3120 cyclenotation := ValueOption("CycleNotation"); 3121 if IsRcwaMappingOfZ(f) and cyclenotation <> false 3122 and ( HasIsBijective(f) or cyclenotation = true ) and IsBijective(f) 3123 and ( cyclenotation = true or Length(Set(Coefficients(f))) <= 10 ) 3124 and ( cyclenotation = true or HasIsTame(f) or IsIntegral(f) ) 3125 and IsSignPreserving(f) and IsTame(f) 3126 then 3127 cycles := Filtered(Cycles(f,RespectedPartition(f)), 3128 cycle->Length(cycle)>1); 3129 for i in [1..Length(cycles)] do 3130 Print("( "); 3131 for j in [1..Length(cycles[i])] do 3132 Print(ViewString(cycles[i][j])); 3133 if j < Length(cycles[i]) then Print(", "); fi; 3134 od; 3135 Print(" )"); 3136 if i < Length(cycles) then Print(" "); fi; 3137 od; 3138 else 3139 Print("<"); 3140 if HasIsTame(f) and not (HasOrder(f) and IsInt(Order(f))) 3141 then if IsTame(f) then Print("tame "); else Print("wild "); fi; fi; 3142 if HasIsBijective(f) and IsBijective(f) 3143 then Print("rcwa permutation"); 3144 elif HasIsInjective(f) and IsInjective(f) 3145 then Print("injective rcwa mapping"); 3146 elif HasIsSurjective(f) and IsSurjective(f) 3147 then Print("surjective rcwa mapping"); 3148 else Print("rcwa mapping"); 3149 fi; 3150 Print(" of ",RingToString(Source(f))); 3151 Print(" with modulus ",ModulusAsFormattedString(Modulus(f))); 3152 if IsRcwaMappingSparseRep(f) then 3153 Print(" and ",Length(f!.coeffs)," affine parts"); 3154 fi; 3155 if HasOrder(f) and not (HasIsTame(f) and not IsTame(f)) 3156 then Print(", of order ",Order(f)); fi; 3157 Print(">"); 3158 fi; 3159 end ); 3160 3161############################################################################# 3162## 3163#M ViewObj( <elm> ) . . . . . . . for elements of group rings of rcwa groups 3164## 3165InstallMethod( ViewObj, 3166 "for elements of group rings of rcwa groups (RCWA)", 3167 ReturnTrue, [ IsElementOfFreeMagmaRing ], 100, 3168 3169 function ( elm ) 3170 3171 local l, grpelms, coeffs, supplng, g, i; 3172 3173 if not IsRcwaMapping(CoefficientsAndMagmaElements(One(elm))[1]) then 3174 TryNextMethod(); 3175 fi; 3176 l := CoefficientsAndMagmaElements(elm); 3177 grpelms := l{[1,3..Length(l)-1]}; 3178 coeffs := l{[2,4..Length(l)]}; 3179 supplng := Length(grpelms); 3180 if not ForAll(grpelms,IsRcwaMapping) then TryNextMethod(); fi; 3181 if supplng = 0 then Print("0"); return; fi; 3182 for i in [1..supplng] do 3183 if coeffs[i] < 0 then 3184 if i > 1 then Print(" - "); else Print("-"); fi; 3185 else 3186 if i > 1 then Print(" + "); fi; 3187 fi; 3188 if AbsInt(coeffs[i]) > 1 then Print(AbsInt(coeffs[i]),"*"); fi; 3189 ViewObj(grpelms[i]); 3190 if i < supplng then Print("\n"); fi; 3191 od; 3192 end ); 3193 3194############################################################################# 3195## 3196#M Display( <f> ) . . . . . . . . . . . . . . . . . . . . for rcwa mappings 3197## 3198## Displays the rcwa mapping <f> in nice human-readable form. 3199## 3200InstallMethod( Display, 3201 "for rcwa mappings (RCWA)", true, [ IsRcwaMapping ], 10, 3202 3203 function ( f ) 3204 3205 local StringAffineMapping, StringAffineMappingOfZ, 3206 StringAffineMappingOfZxZ, StringAffineMappingOfZ_pi, 3207 StringAffineMappingOfGFqx, 3208 3209 R, F, F_el, F_elints, m, c, src, img, res, idcoeffs, inds, 3210 P, Pcl, D, affs, affstrings, maxafflng, lines, line, maxlinelng, 3211 cycles, cl, str, ustr, ringname, varname, maxsrclng, maximglng, 3212 looppos, prefix, col, i, j; 3213 3214 StringAffineMappingOfZ := function ( t ) 3215 3216 local append, str, a, b, c, n; 3217 3218 append := function ( arg ) 3219 str := CallFuncList(Concatenation, 3220 Concatenation([str],List(arg,String))); 3221 end; 3222 3223 a := t[1]; b := t[2]; c := t[3]; 3224 str := ""; n := varname; 3225 3226 if c > 1 and Number([a,b],n->n<>0) > 1 then append("("); fi; 3227 if a <> 0 then 3228 if a = -1 then append("-"); elif a <> 1 then append(a); fi; 3229 append(n); 3230 if b > 0 then 3231 if m = 1 then append(" + "); else append("+"); fi; 3232 fi; 3233 fi; 3234 if a = 0 or b <> 0 then 3235 if a = 0 or b > 0 then append(b); else 3236 if m = 1 then append(" - ",-b); 3237 else append(b); fi; 3238 fi; 3239 fi; 3240 if c > 1 and Number([a,b],n->n<>0) > 1 then append(")"); fi; 3241 if c > 1 then append("/",c); fi; 3242 3243 return str; 3244 end; 3245 3246 StringAffineMappingOfZxZ := function ( t ) 3247 3248 local Stringaff, append, str, 3249 a, b, c, d, e, f, g, d1, d2, g1, g2, m, n; 3250 3251 Stringaff := function ( a, b, c, d ) 3252 if d > 1 and Number([a,b,c],n->n<>0) > 1 then append("("); fi; 3253 if a <> 0 then 3254 if a = -1 then append("-"); elif a <> 1 then append(a); fi; 3255 append(m); 3256 if b > 0 or (b = 0 and c > 0) then append("+"); fi; 3257 fi; 3258 if b <> 0 then 3259 if b = -1 then append("-"); elif b <> 1 then append(b); fi; 3260 append(n); 3261 if c > 0 then append("+"); fi; 3262 fi; 3263 if (a = 0 and b = 0) or c <> 0 then append(c); fi; 3264 if d > 1 and Number([a,b,c],n->n<>0) > 1 then append(")"); fi; 3265 if d > 1 then append("/",d); fi; 3266 end; 3267 3268 append := function ( arg ) 3269 str := CallFuncList(Concatenation, 3270 Concatenation([str],List(arg,String))); 3271 end; 3272 3273 str := ""; 3274 m := varname{[2]}; n := varname{[4]}; 3275 a := t[1][1][1]; b := t[1][1][2]; 3276 c := t[1][2][1]; d := t[1][2][2]; 3277 e := t[2][1]; f := t[2][2]; 3278 g := t[3]; 3279 d1 := Gcd(a,c,e,g); d2 := Gcd(b,d,f,g); 3280 a := a/d1; c := c/d1; e := e/d1; g1 := g/d1; 3281 b := b/d2; d := d/d2; f := f/d2; g2 := g/d2; 3282 append("("); 3283 Stringaff(a,c,e,g1); append(","); Stringaff(b,d,f,g2); 3284 append(")"); 3285 3286 return str; 3287 end; 3288 3289 StringAffineMappingOfZ_pi := function ( t ) 3290 3291 local append, str, a, b, c, n; 3292 3293 append := function ( arg ) 3294 str := CallFuncList(Concatenation, 3295 Concatenation([str],List(arg,String))); 3296 end; 3297 3298 a := t[1]; b := t[2]; c := t[3]; 3299 str := ""; n := varname; 3300 3301 if c = 1 3302 then if a = 0 3303 then append(b); 3304 else if AbsInt(a) <> 1 then append(a," "); 3305 elif a = -1 then append("-"); 3306 fi; 3307 append(n); 3308 if b > 0 then append(" + ", b); 3309 elif b < 0 then append(" - ",-b); 3310 fi; 3311 fi; 3312 elif b = 0 then if AbsInt(a) <> 1 then append(a," "); 3313 elif a = -1 then append("-"); 3314 fi; 3315 append(n," / ",c); 3316 else append("("); 3317 if AbsInt(a) <> 1 then append(a," "); 3318 elif a = -1 then append("-"); 3319 fi; 3320 append(n); 3321 if b > 0 then append(" + ", b); 3322 elif b < 0 then append(" - ",-b); 3323 fi; 3324 append(") / ",c); 3325 fi; 3326 3327 return str; 3328 end; 3329 3330 StringAffineMappingOfGFqx := function ( t ) 3331 3332 local append, factorstr, str, a, b, c, P, one, zero, x; 3333 3334 append := function ( arg ) 3335 str := CallFuncList(Concatenation, 3336 Concatenation([str],List(arg,String))); 3337 end; 3338 3339 factorstr := function ( p ) 3340 if Length(CoefficientsOfLaurentPolynomial(p)[1]) <= 1 3341 then return String(p); 3342 else return Concatenation("(",String(p),")"); fi; 3343 end; 3344 3345 a := t[1]; b := t[2]; c := t[3]; 3346 str := ""; P := varname; 3347 3348 one := One(a); zero := Zero(a); 3349 x := IndeterminateOfLaurentPolynomial(a); 3350 3351 if c = one 3352 then if a = zero 3353 then append(b); 3354 else if not a in [-one,one] then append(factorstr(a),"*",P); 3355 elif a = one then append(P); else append("-",P); fi; 3356 if b <> zero then append(" + ",b); fi; 3357 fi; 3358 elif b = zero then if not a in [-one,one] 3359 then append(factorstr(a),"*",P); 3360 elif a = one then append(P); 3361 else append("-",P); fi; 3362 append("/",factorstr(c)); 3363 else append("("); 3364 if not a in [-one,one] 3365 then append(factorstr(a),"*",P," + ",b,")/",factorstr(c)); 3366 elif a <> one and a = -one 3367 then append("-",P," + ",b,")/",factorstr(c)); 3368 else append(P," + ",b,")/",factorstr(c)); 3369 fi; 3370 fi; 3371 3372 return str; 3373 end; 3374 3375 R := Source(f); 3376 3377 if ValueOption("xdvi") = true and IsIntegers(R) 3378 then LaTeXAndXDVI(f); return; fi; 3379 3380 # If option "AsTable" is set, use old-style format: 3381 if ValueOption("AsTable") = true or ValueOption("table") = true 3382 then TryNextMethod(); fi; 3383 3384 if IsRcwaMappingOfZ(f) 3385 then StringAffineMapping := StringAffineMappingOfZ; 3386 elif IsRcwaMappingOfZxZ(f) 3387 then StringAffineMapping := StringAffineMappingOfZxZ; 3388 elif IsRcwaMappingOfZ_pi(f) 3389 then StringAffineMapping := StringAffineMappingOfZ_pi; 3390 elif IsRcwaMappingOfGFqx(f) 3391 then StringAffineMapping := StringAffineMappingOfGFqx; fi; 3392 3393 m := Modulus(f); c := Coefficients(f); res := AllResidues(R,m); 3394 3395 prefix := false; ringname := RingToString(Source(f)); 3396 3397 if IsRcwaMappingOfGFqx(f) then varname := "P"; 3398 elif IsRcwaMappingOfZxZ(f) then 3399 varname := First(List(["varnames","VarNames"],ValueOption), 3400 names->names<>fail); 3401 if varname = fail then varname := "mn"; fi; 3402 if Length(varname) = 2 then 3403 varname := Concatenation("(",varname{[1]},",",varname{[2]},")"); 3404 fi; 3405 else varname := "n"; fi; 3406 3407 if IsOne(f) then Print("Identity rcwa mapping of ",ringname); 3408 elif IsZero(f) then Print("Zero rcwa mapping of ",ringname); 3409 elif IsOne(m) and IsRcwaMappingStandardRep(f) and IsZero(c[1][1]) 3410 then Print("Constant rcwa mapping of ",ringname," with value ",c[1][2]); 3411 elif IsOne(m) and IsRcwaMappingSparseRep(f) and IsZero(c[1][3]) 3412 then Print("Constant rcwa mapping of ",ringname," with value ",c[1][4]); 3413 else 3414 if not IsOne(m) then Print("\n"); fi; 3415 3416 if HasIsTame(f) and not (HasOrder(f) and IsInt(Order(f))) then 3417 if IsTame(f) then Print("Tame "); else Print("Wild "); fi; 3418 prefix := true; 3419 fi; 3420 if HasIsBijective(f) and IsBijective(f) 3421 then if prefix then Print("rcwa permutation"); 3422 else Print("Rcwa permutation"); fi; 3423 prefix := true; 3424 elif HasIsInjective(f) and IsInjective(f) 3425 then if prefix then Print("injective rcwa mapping"); 3426 else Print("Injective rcwa mapping"); fi; 3427 prefix := true; 3428 elif HasIsSurjective(f) and IsSurjective(f) 3429 then if prefix then Print("surjective rcwa mapping"); 3430 else Print("Surjective rcwa mapping"); fi; 3431 prefix := true; 3432 fi; 3433 if not prefix then Print("Rcwa mapping"); fi; 3434 Print(" of ",ringname); 3435 3436 if IsOne(m) then 3437 3438 if IsRcwaMappingStandardRep(f) then 3439 Print(": ",varname," -> ",StringAffineMapping(c[1])); 3440 elif IsRcwaMappingSparseRep(f) then 3441 Print(": ",varname," -> ",StringAffineMapping(c[1]{[3..5]})); 3442 fi; 3443 3444 else 3445 3446 Print(" with modulus ",ModulusAsFormattedString(m)); 3447 if IsRcwaMappingSparseRep(f) then 3448 Print(" and ",Length(c)," affine parts"); 3449 fi; 3450 if HasOrder(f) and not (HasIsTame(f) and not IsTame(f)) 3451 then Print(", of order ",Order(f)); fi; 3452 Print("\n\n"); 3453 3454 if IsRcwaMappingOfZ(f) and HasIsBijective(f) and IsBijective(f) 3455 and (HasIsTame(f) and IsTame(f) or IsIntegral(f)) 3456 and IsSignPreserving(f) and ValueOption("CycleNotation") <> false 3457 then 3458 cycles := Filtered(Cycles(f,RespectedPartition(f)), 3459 cycle->Length(cycle)>1); 3460 maxlinelng := SizeScreen()[1]; col := 1; 3461 for i in [1..Length(cycles)] do 3462 Print("( "); col := col + 2; 3463 for j in [1..Length(cycles[i])] do 3464 str := ViewString(cycles[i][j]); 3465 Print(str); col := col + Length(str); 3466 if j < Length(cycles[i]) then 3467 Print(", "); col := col + 2; 3468 if col + Length(str) + 8 >= maxlinelng then 3469 Print("\n "); col := 3; 3470 fi; 3471 fi; 3472 od; 3473 Print(" )"); col := col + 2; 3474 if i < Length(cycles) then 3475 if col + 20 >= maxlinelng 3476 then Print("\n"); col := 1; 3477 else Print(" "); col := col + 1; fi; 3478 else Print("\n\n"); 3479 fi; 3480 od; 3481 return; # done. 3482 fi; 3483 3484 if IsRcwaMappingOfZ(f) and ValueOption("AsClassMapping") = true then 3485 if not IsRcwaMappingInSparseRep(f) 3486 then c := Coefficients(SparseRep(f)); fi; 3487 src := []; 3488 for i in [1..Length(c)] do 3489 Add(src,ResidueClass(c[i][1],c[i][2])); 3490 od; 3491 img := List(src,cl->cl^f); 3492 looppos := Filtered([1..Length(c)],i->img[i]<>src[i] 3493 and Intersection(src[i],img[i])<>[]); 3494 src := List(src,ViewString); 3495 img := List(img,ViewString); 3496 maxsrclng := Maximum(List(src,Length)); 3497 maximglng := Maximum(List(img,Length)); 3498 for i in [1..Length(src)] do 3499 Print(" ",String(src[i],maxsrclng)," -> ",img[i]); 3500 if i in looppos then 3501 Print(String("",maximglng-Length(img[i]))," loop"); 3502 fi; 3503 if c[i]{[3..5]} = [1,0,1] then 3504 Print(String("",maximglng-Length(img[i]))," id"); 3505 fi; 3506 Print("\n"); 3507 od; 3508 if ValueOption("NoLineFeed") <> true then Print("\n"); fi; 3509 return; # done. 3510 fi; 3511 3512 P := ShallowCopy(LargestSourcesOfAffineMappings(f)); 3513 D := List(P,src->[1/Density(src),src]); 3514 #i := First([1..Length(P)],j->IsOne(RestrictedMapping(f,P[j]))); 3515 if IsRing(R) then idcoeffs := [1,0,1] * One(R); 3516 elif IsZxZ(R) then idcoeffs := [[[1,0],[0,1]],[0,0],1]; fi; 3517 if IsRcwaMappingStandardRep(f) then 3518 i := First([1..Length(P)], 3519 j -> c[First([1..Length(res)],k->res[k] in P[j])] 3520 = idcoeffs); 3521 elif IsRcwaMappingOfZInSparseRep(f) then 3522 i := First([1..Length(P)], 3523 j -> c[PositionProperty(c,d->d[1] in P[j])]{[3..5]} 3524 = idcoeffs); 3525 fi; 3526 if i <> fail then D[i][1] := infinity; fi; # constant mappings -> end 3527 3528 SortParallel(D,P); 3529 3530 if IsRcwaMappingStandardRep(f) then 3531 affs := List(P,preimg->c[First([1..Length(res)], 3532 i->res[i] in preimg)]); 3533 elif IsRcwaMappingSparseRep(f) then 3534 affs := List(P,preimg->First(c,d->d[1] in preimg){[3..5]}); 3535 fi; 3536 3537 Pcl := List(P,AsUnionOfFewClasses); 3538 3539 affstrings := List(affs,StringAffineMapping); 3540 3541 if IsRcwaMappingOfGFqx(f) and IsPrimeField(LeftActingDomain(R)) then 3542 F := LeftActingDomain(R); 3543 F_el := List(AsList(F),String); 3544 F_elints := List(List(AsList(F),Int),String); 3545 for i in [1..Length(affstrings)] do 3546 for j in [1..Length(F_el)] do 3547 affstrings[i] := ReplacedString(affstrings[i], 3548 F_el[j],F_elints[j]); 3549 od; 3550 od; 3551 fi; 3552 3553 maxafflng := Maximum(List(affstrings,Length)); 3554 3555 maxlinelng := SizeScreen()[1] - Length(varname) - 11; 3556 lines := [String("/",Length(varname)+8)]; 3557 3558 for i in [1..Length(affs)] do 3559 line := String(affstrings[i],-maxafflng); 3560 if i < Length(affs) or Length(Pcl[i]) <= 2 3561 or (IsRcwaMappingOfZOrZ_pi(f) and Length(Pcl[i]) <= 4) 3562 then 3563 Append(line," if "); 3564 Append(line,varname); 3565 Append(line," in "); 3566 str := DisplayString(P[i]); 3567 if Length(line) + Length(str) <= maxlinelng then 3568 Append(line,str); 3569 else 3570 for j in [1..Length(Pcl[i])] do 3571 str := ViewString(Pcl[i][j]); 3572 if j = Length(Pcl[i]) 3573 then ustr := ""; else ustr := " U "; fi; 3574 if Length(line) + Length(str) + Length(ustr) > maxlinelng 3575 and j > 1 3576 then 3577 Add(lines,line); 3578 line := String(" ",maxafflng+Length(" if ")+Length(varname) 3579 +Length(" in ")); 3580 fi; 3581 Append(line,str); 3582 Append(line,ustr); 3583 od; 3584 fi; 3585 else 3586 Append(line," otherwise"); 3587 fi; 3588 Add(lines,line); 3589 od; 3590 if Length(lines) mod 2 = 1 3591 then Add(lines,String("|",Length(varname)+8)); fi; 3592 Add(lines,String("\\",Length(varname)+8)); 3593 3594 for i in [2..Length(lines)-1] do 3595 if i = (Length(lines)+1)/2 then 3596 lines[i] := Concatenation(" ",varname," |-> < ",lines[i]); 3597 elif not '|' in lines[i] then 3598 lines[i] := Concatenation(String("|",Length(varname)+8)," ", 3599 lines[i]); 3600 fi; 3601 od; 3602 3603 if IsRcwaMappingOfGFqx(f) and IsPrimeField(LeftActingDomain(R)) then 3604 for i in [1..Length(lines)] do 3605 for j in [1..Length(F_el)] do 3606 lines[i] := ReplacedString(lines[i],F_el[j],F_elints[j]); 3607 od; 3608 od; 3609 fi; 3610 3611 for i in [1..Length(lines)] do 3612 Print(lines[i],"\n"); 3613 od; 3614 3615 fi; 3616 3617 fi; 3618 3619 if ValueOption("NoLineFeed") <> true then Print("\n"); fi; 3620 end ); 3621 3622############################################################################# 3623## 3624#M Display( <f> ) . . . . . . . . . . . . . . . . . . . . for rcwa mappings 3625## 3626## Displays the rcwa mapping <f> as a table, in the "old-style" format used 3627## by RCWA since its first release in 2005. 3628## 3629InstallMethod( Display, 3630 "for rcwa mappings (RCWA)", 3631 true, [ IsRcwaMappingInStandardRep ], 0, 3632 3633 function ( f ) 3634 3635 local IdChars, DisplayAffineMappingOfZ, DisplayAffineMappingOfZxZ, 3636 DisplayAffineMappingOfZ_pi, DisplayAffineMappingOfGFqx, 3637 R, m, c, r, poses, pos, i, scr, l1, l2, l3, 3638 str, ringname, mapname, varname, imageexpr, 3639 mstr, mcharstop, maxreschars, flushlng, prefix; 3640 3641 IdChars := function ( n, ch ) 3642 return Concatenation( ListWithIdenticalEntries( n, ch ) ); 3643 end; 3644 3645 DisplayAffineMappingOfZ := function ( t ) 3646 3647 local a, b, c; 3648 3649 a := t[1]; b := t[2]; c := t[3]; 3650 if c = 1 3651 then if a = 0 3652 then Print(b); 3653 else if AbsInt(a) <> 1 then Print(a); 3654 elif a = -1 then Print("-"); 3655 fi; 3656 Print("n"); 3657 if b > 0 then Print(" + ", b); 3658 elif b < 0 then Print(" - ",-b); 3659 fi; 3660 fi; 3661 elif b = 0 then if AbsInt(a) <> 1 then Print(a); 3662 elif a = -1 then Print("-"); 3663 fi; 3664 Print("n/",c); 3665 else Print("("); 3666 if AbsInt(a) <> 1 then Print(a); 3667 elif a = -1 then Print("-"); 3668 fi; 3669 Print("n"); 3670 if b > 0 then Print(" + ", b); 3671 elif b < 0 then Print(" - ",-b); 3672 fi; 3673 Print(")/",c); 3674 fi; 3675 end; 3676 3677 DisplayAffineMappingOfZxZ := function ( t ) 3678 3679 local Print_vxa, PrintAff, 3680 a, b, c, d, e, f, g, d1, d2, g1, g2, m, n; 3681 3682 Print_vxa := function ( ) 3683 if IsOne( a) then Print("v"); 3684 elif IsOne(-a) then Print("-v"); 3685 else Print("v * ",BlankFreeString(a)); fi; 3686 end; 3687 3688 PrintAff := function ( a, b, c, d ) 3689 if d > 1 and Number([a,b,c],n->n<>0) > 1 then Print("("); fi; 3690 if a <> 0 then 3691 if a = -1 then Print("-"); elif a <> 1 then Print(a); fi; 3692 Print(m); 3693 if b > 0 or (b = 0 and c > 0) then Print("+"); fi; 3694 fi; 3695 if b <> 0 then 3696 if b = -1 then Print("-"); elif b <> 1 then Print(b); fi; 3697 Print(n); 3698 if c > 0 then Print("+"); fi; 3699 fi; 3700 if c <> 0 then Print(c); fi; 3701 if d > 1 and Number([a,b,c],n->n<>0) > 1 then Print(")"); fi; 3702 if d > 1 then Print("/",d); fi; 3703 end; 3704 3705 if varname = "v" then 3706 a := t[1]; b := t[2]; c := t[3]; 3707 if c = 1 3708 then if IsZero(a) 3709 then Print(BlankFreeString(b)); 3710 else Print_vxa(); 3711 if not IsZero(b) 3712 then Print(" + ",BlankFreeString(b)); fi; 3713 fi; 3714 elif IsZero(b) then Print_vxa(); Print("/",c); 3715 else Print("("); 3716 if IsZero(a) 3717 then Print(BlankFreeString(b)); 3718 else Print_vxa(); Print(" + ",BlankFreeString(b)); 3719 fi; 3720 Print(")/",c); 3721 fi; 3722 elif Length(varname) = 5 then 3723 m := varname{[2]}; n := varname{[4]}; 3724 a := t[1][1][1]; b := t[1][1][2]; 3725 c := t[1][2][1]; d := t[1][2][2]; 3726 e := t[2][1]; f := t[2][2]; 3727 g := t[3]; 3728 d1 := Gcd(a,c,e,g); d2 := Gcd(b,d,f,g); 3729 a := a/d1; c := c/d1; e := e/d1; g1 := g/d1; 3730 b := b/d2; d := d/d2; f := f/d2; g2 := g/d2; 3731 Print("["); 3732 PrintAff(a,c,e,g1); Print(","); PrintAff(b,d,f,g2); 3733 Print("]"); 3734 else Print("<unknown output format>"); fi; 3735 end; 3736 3737 DisplayAffineMappingOfZ_pi := function ( t ) 3738 3739 local a, b, c; 3740 3741 a := t[1]; b := t[2]; c := t[3]; 3742 if c = 1 3743 then if a = 0 3744 then Print(b); 3745 else if AbsInt(a) <> 1 then Print(a," "); 3746 elif a = -1 then Print("-"); 3747 fi; 3748 Print("n"); 3749 if b > 0 then Print(" + ", b); 3750 elif b < 0 then Print(" - ",-b); 3751 fi; 3752 fi; 3753 elif b = 0 then if AbsInt(a) <> 1 then Print(a," "); 3754 elif a = -1 then Print("-"); 3755 fi; 3756 Print("n / ",c); 3757 else Print("("); 3758 if AbsInt(a) <> 1 then Print(a," "); 3759 elif a = -1 then Print("-"); 3760 fi; 3761 Print("n"); 3762 if b > 0 then Print(" + ", b); 3763 elif b < 0 then Print(" - ",-b); 3764 fi; 3765 Print(") / ",c); 3766 fi; 3767 end; 3768 3769 DisplayAffineMappingOfGFqx := function ( t, maxlng ) 3770 3771 local append, factorstr, str, a, b, c, one, zero, x; 3772 3773 append := function ( arg ) 3774 str := CallFuncList(Concatenation, 3775 Concatenation([str],List(arg,String))); 3776 end; 3777 3778 factorstr := function ( p ) 3779 if Length(CoefficientsOfLaurentPolynomial(p)[1]) <= 1 3780 then return String(p); 3781 else return Concatenation("(",String(p),")"); fi; 3782 end; 3783 3784 a := t[1]; b := t[2]; c := t[3]; 3785 one := One(a); zero := Zero(a); 3786 x := IndeterminateOfLaurentPolynomial(a); 3787 str := ""; 3788 if c = one 3789 then if a = zero 3790 then append(b); 3791 else if not a in [-one,one] then append(factorstr(a),"*P"); 3792 elif a = one then append("P"); else append("-P"); fi; 3793 if b <> zero then append(" + ",b); fi; 3794 fi; 3795 elif b = zero then if not a in [-one,one] 3796 then append(factorstr(a),"*P"); 3797 elif a = one then append("P"); 3798 else append("-P"); fi; 3799 append("/",factorstr(c)); 3800 else append("("); 3801 if not a in [-one,one] 3802 then append(factorstr(a),"*P + ",b,")/",factorstr(c)); 3803 elif a <> one and a = -one 3804 then append("-P + ",b,")/",factorstr(c)); 3805 else append("P + ",b,")/",factorstr(c)); 3806 fi; 3807 fi; 3808 if Length(str) > maxlng then str := "< ... >"; fi; 3809 Print(str); 3810 end; 3811 3812 if ValueOption("AsTable") <> true and ValueOption("table") <> true 3813 then TryNextMethod(); fi; 3814 3815 R := Source(f); 3816 if ValueOption("xdvi") = true and IsIntegers(R) 3817 then LaTeXAndXDVI(f); return; fi; 3818 3819 m := Modulus(f); c := Coefficients(f); r := AllResidues(R,m); 3820 if HasName(f) and ValueOption("PrintName") <> fail then 3821 mapname := Name(f); 3822 if Position(mapname,'^') <> fail 3823 then mapname := Concatenation("(",mapname,")"); fi; 3824 else mapname := "Image of "; fi; 3825 prefix := false; ringname := RingToString(Source(f)); 3826 if IsRcwaMappingOfGFqx(f) then varname := "P"; 3827 elif IsRcwaMappingOfZxZ(f) then 3828 varname := First(List(["varnames","VarNames"],ValueOption), 3829 names->names<>fail); 3830 if varname = fail then varname := "mn"; fi; 3831 if Length(varname) = 2 then 3832 varname := Concatenation("[",varname{[1]},",",varname{[2]},"]"); 3833 fi; 3834 else varname := "n"; fi; 3835 maxreschars := Maximum(List(List(r,BlankFreeString),Length)); 3836 if IsOne(f) 3837 then Print("Identity rcwa mapping of ",ringname); 3838 elif IsZero(f) 3839 then Print("Zero rcwa mapping of ",ringname); 3840 elif IsOne(m) and IsZero(c[1][1]) 3841 then Print("Constant rcwa mapping of ",ringname, 3842 " with value ",c[1][2]); 3843 else if not IsOne(m) then Print("\n"); fi; 3844 if HasIsTame(f) and not (HasOrder(f) and IsInt(Order(f))) then 3845 if IsTame(f) then Print("Tame "); else Print("Wild "); fi; 3846 prefix := true; 3847 fi; 3848 if HasIsBijective(f) and IsBijective(f) 3849 then if prefix then Print("rcwa permutation"); 3850 else Print("Rcwa permutation"); fi; 3851 prefix := true; 3852 elif HasIsInjective(f) and IsInjective(f) 3853 then if prefix then Print("injective rcwa mapping"); 3854 else Print("Injective rcwa mapping"); fi; 3855 prefix := true; 3856 elif HasIsSurjective(f) and IsSurjective(f) 3857 then if prefix then Print("surjective rcwa mapping"); 3858 else Print("Surjective rcwa mapping"); fi; 3859 prefix := true; 3860 fi; 3861 if not prefix then Print("Rcwa mapping"); fi; 3862 Print(" of ",ringname); 3863 if IsOne(m) then 3864 Print(": ",varname," -> "); 3865 if IsRcwaMappingOfZ(f) 3866 then DisplayAffineMappingOfZ(c[1]); 3867 elif IsRcwaMappingOfZxZ(f) 3868 then DisplayAffineMappingOfZxZ(c[1]); 3869 elif IsRcwaMappingOfZ_pi(f) 3870 then DisplayAffineMappingOfZ_pi(c[1]); 3871 else DisplayAffineMappingOfGFqx(c[1],SizeScreen()[1]-48); fi; 3872 else 3873 Print(" with modulus ",ModulusAsFormattedString(m)); 3874 if HasOrder(f) and not (HasIsTame(f) and not IsTame(f)) 3875 then Print(", of order ",Order(f)); fi; 3876 Print("\n\n"); 3877 scr := SizeScreen()[1] - 2; 3878 if IsRcwaMappingOfZOrZ_pi(f) then l1 := Int(scr/2); 3879 elif IsRcwaMappingOfZxZ(f) then l1 := Int(2*scr/5); 3880 else l1 := Int(scr/3); fi; 3881 mstr := ModulusAsFormattedString(m); 3882 if l1 - Length(mstr) - 6 <= 0 then mstr := "<modulus>"; fi; 3883 mcharstop := Length(mstr) + Length(varname) - 1; 3884 l2 := Int((l1 - mcharstop - 6)/2); 3885 l3 := Int((scr - l1 - Length(mapname) - 3)/2); 3886 if l3 < 3 3887 then mapname := "Image of "; l3 := Int((scr-l1-12)/2); fi; 3888 if Length(varname) = 5 then l3 := l3 - 2; fi; 3889 if mapname = "Image of " 3890 then imageexpr := Concatenation(mapname,varname); 3891 else imageexpr := Concatenation(varname,"^",mapname); fi; 3892 flushlng := l1 - maxreschars - 1; 3893 Print(IdChars(l2," "),varname," mod ",mstr, 3894 IdChars(l1-l2-mcharstop-6," "),"|",IdChars(l3," "), 3895 imageexpr,"\n",IdChars(l1,"-"),"+",IdChars(scr-l1-1,"-")); 3896 poses := AsSortedList(List(Set(c),t->Positions(c,t))); 3897 for pos in poses do 3898 str := " "; 3899 for i in pos do 3900 if IsRcwaMappingOfZOrZ_pi(f) then 3901 Append(str,String(r[i],maxreschars+1)); 3902 else 3903 Append(str,String(BlankFreeString(r[i]),-(maxreschars+1))); 3904 fi; 3905 if Length(str) >= flushlng then 3906 if Length(str) < l1 3907 then Print("\n",String(str, -l1),"| "); 3908 else Print("\n",String(" < ... > ",-l1),"| "); fi; 3909 str := " "; 3910 fi; 3911 od; 3912 if str <> " " 3913 then Print("\n",String(str, -l1),"| "); fi; 3914 if IsRcwaMappingOfZ(f) 3915 then DisplayAffineMappingOfZ(c[pos[1]]); 3916 elif IsRcwaMappingOfZxZ(f) 3917 then DisplayAffineMappingOfZxZ(c[pos[1]]); 3918 elif IsRcwaMappingOfZ_pi(f) 3919 then DisplayAffineMappingOfZ_pi(c[pos[1]]); 3920 else DisplayAffineMappingOfGFqx(c[pos[1]],scr-l1-4); fi; 3921 od; 3922 Print("\n"); 3923 fi; 3924 fi; 3925 if ValueOption("NoLineFeed") <> true then Print("\n"); fi; 3926 end ); 3927 3928############################################################################# 3929## 3930#M LaTeXStringRcwaMapping( <f> ) . . . . . . . . . . for rcwa mappings of Z 3931## 3932InstallMethod( LaTeXStringRcwaMapping, 3933 "for rcwa mappings of Z in standard rep. (RCWA)", 3934 true, [ IsRcwaMappingOfZInStandardRep ], 0, 3935 3936 function ( f ) 3937 3938 local LaTeXAffineMappingOfZ, append, indent, varname, german, 3939 gens, c, m, res, P, str, affs, affstrings, maxafflng, i, j; 3940 3941 append := function ( arg ) 3942 str := CallFuncList(Concatenation, 3943 Concatenation([str],List(arg,String))); 3944 end; 3945 3946 LaTeXAffineMappingOfZ := function ( t ) 3947 3948 local append, str, a, b, c, n; 3949 3950 append := function ( arg ) 3951 str := CallFuncList(Concatenation, 3952 Concatenation([str],List(arg,String))); 3953 end; 3954 3955 a := t[1]; b := t[2]; c := t[3]; 3956 str := ""; n := varname; 3957 3958 if c > 1 and Number([a,b],n->n<>0) > 1 then append("("); fi; 3959 if a <> 0 then 3960 if a = -1 then append("-"); elif a <> 1 then append(a); fi; 3961 append(n); 3962 if b > 0 then append("+"); fi; 3963 fi; 3964 if a = 0 or b <> 0 then append(b); fi; 3965 if c > 1 and Number([a,b],n->n<>0) > 1 then append(")"); fi; 3966 if c > 1 then append("/",c); fi; 3967 3968 return str; 3969 end; 3970 3971 if HasLaTeXString(f) then return LaTeXString(f); fi; 3972 3973 indent := ValueOption("Indentation"); 3974 if not IsPosInt(indent) 3975 then indent := ""; else indent := String(" ",indent); fi; 3976 str := indent; 3977 3978 if ValueOption("Factorization") = true and IsBijective(f) then 3979 gens := List(FactorizationIntoCSCRCT(f),LaTeXString); 3980 append(" &"); 3981 for i in [1..Length(gens)] do 3982 append(gens[i]); 3983 if i < Length(gens) then 3984 if i mod 5 = 0 then append(" \\\\\n"); fi; 3985 if i mod 5 in [2,4] then append("\n"); fi; 3986 append(" \\cdot "); 3987 if i mod 5 = 0 then append("&"); fi; 3988 else append("\n"); fi; 3989 od; 3990 return str; 3991 fi; 3992 3993 german := ValueOption("German") = true 3994 or ValueOption("german") = true; 3995 varname := First(List(["varname","VarName"],ValueOption), 3996 name->name<>fail); 3997 if varname = fail then varname := "n"; fi; 3998 3999 c := Coefficients(f); m := Length(c); 4000 if m = 1 then 4001 return Concatenation("n \\ \\mapsto \\ ",LaTeXAffineMappingOfZ(c[1])); 4002 fi; 4003 res := AllResidues(Integers,m); 4004 4005 append("n \\ \\mapsto \\\n",indent,"\\begin{cases}\n"); 4006 4007 P := ShallowCopy(LargestSourcesOfAffineMappings(f)); 4008 Sort(P,function(Pi,Pj) return Density(Pi)>Density(Pj); end); 4009 4010 affs := List(P,preimg->c[First([1..Length(res)],i->res[i] in preimg)]); 4011 P := List(P,AsUnionOfFewClasses); 4012 4013 affstrings := List( affs, LaTeXAffineMappingOfZ ); 4014 maxafflng := Maximum( List( affstrings, Length ) ); 4015 4016 for i in [1..Length(P)] do 4017 append(indent," ",affstrings[i], 4018 String("",maxafflng-Length(affstrings[i]))); 4019 if german then append(" & \\text{falls}"); 4020 else append(" & \\text{if}"); fi; 4021 append(" \\ ",varname," \\in "); 4022 for j in [1..Length(P[i])] do 4023 append(String(Residue(P[i][j])),"(",String(Modulus(P[i][j])),")"); 4024 if j < Length(P[i]) then append(" \\cup "); fi; 4025 od; 4026 if i = Length(P) then append(".\n"); else append(", \\\\\n"); fi; 4027 od; 4028 4029 append(indent,"\\end{cases}\n"); 4030 return str; 4031 end ); 4032 4033############################################################################# 4034## 4035#M LaTeXStringRcwaMapping( <f> ) . . . . . . . . . for rcwa mappings of Z^2 4036## 4037InstallMethod( LaTeXStringRcwaMapping, 4038 "for rcwa mappings of Z^2 (RCWA)", 4039 true, [ IsRcwaMappingOfZxZ ], 0, 4040 4041 function ( f ) 4042 4043 local LaTeXAffineMappingOfZxZ, append, indent, varname, german, 4044 gens, c, m, res, P, str, affs, affstrings, maxafflng, i, j; 4045 4046 append := function ( arg ) 4047 str := CallFuncList(Concatenation, 4048 Concatenation([str],List(arg,String))); 4049 end; 4050 4051 LaTeXAffineMappingOfZxZ := function ( t ) 4052 4053 local append, LaTeXaff, str, 4054 a, b, c, d, e, f, g, d1, d2, g1, g2, m, n; 4055 4056 append := function ( arg ) 4057 str := CallFuncList(Concatenation, 4058 Concatenation([str],List(arg,String))); 4059 end; 4060 4061 LaTeXaff := function ( a, b, c, d ) 4062 if d > 1 and Number([a,b,c],n->n<>0) > 1 then append("("); fi; 4063 if a <> 0 then 4064 if a = -1 then append("-"); elif a <> 1 then append(a); fi; 4065 append(m); 4066 if b > 0 or (b = 0 and c > 0) then append("+"); fi; 4067 fi; 4068 if b <> 0 then 4069 if b = -1 then append("-"); elif b <> 1 then append(b); fi; 4070 append(n); 4071 if c > 0 then append("+"); fi; 4072 fi; 4073 if (a = 0 and b = 0) or c <> 0 then append(c); fi; 4074 if d > 1 and Number([a,b,c],n->n<>0) > 1 then append(")"); fi; 4075 if d > 1 then append("/",d); fi; 4076 end; 4077 4078 str := ""; 4079 m := varname{[1]}; n := varname{[2]}; 4080 a := t[1][1][1]; b := t[1][1][2]; 4081 c := t[1][2][1]; d := t[1][2][2]; 4082 e := t[2][1]; f := t[2][2]; 4083 g := t[3]; 4084 d1 := Gcd(a,c,e,g); d2 := Gcd(b,d,f,g); 4085 a := a/d1; c := c/d1; e := e/d1; g1 := g/d1; 4086 b := b/d2; d := d/d2; f := f/d2; g2 := g/d2; 4087 append("("); 4088 LaTeXaff(a,c,e,g1); append(","); LaTeXaff(b,d,f,g2); 4089 append(")"); 4090 return str; 4091 end; 4092 4093 if HasLaTeXString(f) then return LaTeXString(f); fi; 4094 4095 indent := ValueOption("Indentation"); 4096 if not IsPosInt(indent) 4097 then indent := ""; else indent := String(" ",indent); fi; 4098 str := indent; 4099 4100 if ValueOption("Factorization") = true and IsBijective(f) then 4101 gens := List(FactorizationIntoCSCRCT(f),LaTeXString); 4102 append(" &"); 4103 for i in [1..Length(gens)] do 4104 append(gens[i]); 4105 if i < Length(gens) then 4106 if i mod 2 = 0 then append(" \\\\\n"); else append("\n"); fi; 4107 append(" \\cdot "); 4108 if i mod 2 = 0 then append("&"); fi; 4109 else append("\n"); fi; 4110 od; 4111 return str; 4112 fi; 4113 4114 german := ValueOption("German") = true 4115 or ValueOption("german") = true; 4116 varname := First(List(["varnames","VarNames"],ValueOption), 4117 names->names<>fail); 4118 if varname = fail then varname := "mn"; fi; 4119 4120 c := Coefficients(f); m := Modulus(f); 4121 if IsOne(m) then 4122 return Concatenation("(",varname{[1]},",",varname{[2]},")", 4123 "\\ \\mapsto \\ ", 4124 LaTeXAffineMappingOfZxZ(c[1])); 4125 fi; 4126 res := AllResidues(Integers^2,m); 4127 4128 append("(",varname{[1]},",",varname{[2]},")","\\ \\mapsto \\\n", 4129 indent,"\\begin{cases}\n"); 4130 4131 P := ShallowCopy(LargestSourcesOfAffineMappings(f)); 4132 Sort(P,function(Pi,Pj) return Density(Pi)>Density(Pj); end); 4133 4134 affs := List(P,preimg->c[First([1..Length(res)],i->res[i] in preimg)]); 4135 P := List(P,AsUnionOfFewClasses); 4136 4137 affstrings := List( affs, LaTeXAffineMappingOfZxZ ); 4138 maxafflng := Maximum( List( affstrings, Length ) ); 4139 4140 for i in [1..Length(P)] do 4141 append(indent," ",affstrings[i], 4142 String("",maxafflng-Length(affstrings[i]))); 4143 if german then append(" & \\text{falls}"); 4144 else append(" & \\text{if}"); fi; 4145 append(" \\ (",varname{[1]},",",varname{[2]},") \\in "); 4146 for j in [1..Length(P[i])] do 4147 append(ReplacedString(ViewString(P[i][j]),"Z","\\mathbb{Z}")); 4148 if j < Length(P[i]) then append(" \\cup "); fi; 4149 od; 4150 if i = Length(P) then append(".\n"); else append(", \\\\\n"); fi; 4151 od; 4152 4153 append(indent,"\\end{cases}\n"); 4154 return str; 4155 end ); 4156 4157############################################################################# 4158## 4159#M LaTeXAndXDVI( <f> ) . . . . . . . . . . . . . . . for rcwa mappings of Z 4160## 4161InstallMethod( LaTeXAndXDVI, 4162 "for rcwa mappings of Z", true, [ IsRcwaMappingOfZ ], 0, 4163 4164 function ( f ) 4165 4166 local tmpdir, file, stream, str, latex, dvi, m, sizes, size, 4167 jectivity, cwop; 4168 4169 tmpdir := DirectoryTemporary( ); 4170 file := Filename(tmpdir,"rcwamap.tex"); 4171 stream := OutputTextFile(file,false); 4172 SetPrintFormattingStatus(stream,false); 4173 AppendTo(stream,"\\documentclass[fleqn]{article}\n", 4174 "\\usepackage{amsmath}\n", 4175 "\\usepackage{amssymb}\n\n", 4176 "\\setlength{\\paperwidth}{84cm}\n", 4177 "\\setlength{\\textwidth}{80cm}\n", 4178 "\\setlength{\\paperheight}{59.5cm}\n", 4179 "\\setlength{\\textheight}{57cm}\n\n", 4180 "\\begin{document}\n\n"); 4181 sizes := ["Huge","huge","Large","large"]; 4182 m := Modulus(f); 4183 if ValueOption("Factorization") <> true 4184 then size := LogInt(Int(m/16)+1,2)+1; 4185 else size := Int(Length(FactorizationIntoCSCRCT(f))/50) + 1; fi; 4186 if size < 5 then AppendTo(stream,"\\begin{",sizes[size],"}\n\n"); fi; 4187 if IsBijective(f) then jectivity := " bijective"; 4188 elif IsInjective(f) then jectivity := "n injective, but not surjective"; 4189 elif IsSurjective(f) then jectivity := " surjective, but not injective"; 4190 else jectivity := " neither injective nor surjective"; fi; 4191 if IsClassWiseOrderPreserving(f) 4192 then cwop := " class-wise order-preserving"; else cwop := ""; fi; 4193 AppendTo(stream,"\\noindent A",jectivity,cwop, 4194 " rcwa mapping of \\(\\mathbb{Z}\\) \\newline\nwith modulus ", 4195 String(Modulus(f)),", multiplier ",String(Multiplier(f)), 4196 " and divisor ",String(Divisor(f)),", given by\n"); 4197 AppendTo(stream,"\\begin{align*}\n"); 4198 str := LaTeXStringRcwaMapping(f:Indentation:=2); 4199 AppendTo(stream,str,"\\end{align*}"); 4200 if HasIsTame(f) then 4201 if IsTame(f) then AppendTo(stream,"\nThis mapping is tame."); 4202 else AppendTo(stream,"\nThis mapping is wild."); fi; 4203 fi; 4204 if HasOrder(f) then 4205 AppendTo(stream,"\nThe order of this mapping is \\(", 4206 IntOrInfinityToLaTeX(Order(f)),"\\)."); 4207 fi; 4208 if HasIsTame(f) or HasOrder(f) then AppendTo(stream," \\newline"); fi; 4209 if IsBijective(f) then 4210 if IsClassWiseOrderPreserving(f) then 4211 AppendTo(stream,"\n\\noindent The determinant of this mapping is ", 4212 String(Determinant(f)),", and its sign is ", 4213 String(Sign(f)),"."); 4214 else 4215 AppendTo(stream,"\n\\noindent The sign of this mapping is ", 4216 String(Sign(f)),"."); 4217 fi; 4218 fi; 4219 if size < 5 then AppendTo(stream,"\n\n\\end{",sizes[size],"}"); fi; 4220 AppendTo(stream,"\n\n\\end{document}\n"); 4221 latex := Filename(DirectoriesSystemPrograms( ),"latex"); 4222 Process(tmpdir,latex,InputTextNone( ),OutputTextNone( ),[file]); 4223 dvi := Filename(DirectoriesSystemPrograms( ),"xdvi"); 4224 Process(tmpdir,dvi,InputTextNone( ),OutputTextNone( ), 4225 ["-paper","a1r","rcwamap.dvi"]); 4226 end ); 4227 4228############################################################################# 4229## 4230#M LaTeXAndXDVI( <f> ) . . . . . . . . . . . . . . for rcwa mappings of ZxZ 4231## 4232InstallMethod( LaTeXAndXDVI, 4233 "for rcwa mappings of ZxZ", true, [ IsRcwaMappingOfZxZ ], 0, 4234 4235 function ( f ) 4236 4237 local tmpdir, file, stream, str, latex, dvi, jectivity, cwop; 4238 4239 tmpdir := DirectoryTemporary( ); 4240 file := Filename(tmpdir,"rcwamap.tex"); 4241 stream := OutputTextFile(file,false); 4242 SetPrintFormattingStatus(stream,false); 4243 AppendTo(stream,"\\documentclass[fleqn]{article}\n", 4244 "\\usepackage{amsmath}\n", 4245 "\\usepackage{amssymb}\n\n", 4246 "\\setlength{\\paperwidth}{84cm}\n", 4247 "\\setlength{\\textwidth}{80cm}\n", 4248 "\\setlength{\\paperheight}{59.5cm}\n", 4249 "\\setlength{\\textheight}{57cm}\n\n", 4250 "\\begin{document}\n\n"); 4251 if IsBijective(f) then jectivity := " bijective"; 4252 elif IsInjective(f) then jectivity := "n injective, but not surjective"; 4253 elif IsSurjective(f) then jectivity := " surjective, but not injective"; 4254 else jectivity := " neither injective nor surjective"; fi; 4255 if IsClassWiseOrderPreserving(f) 4256 then cwop := " class-wise order-preserving"; else cwop := ""; fi; 4257 AppendTo(stream,"\\noindent A",jectivity,cwop, 4258 " rcwa mapping of \\(\\mathbb{Z}^2\\) with modulus ", 4259 "\\(",ReplacedString(ModulusAsFormattedString(Modulus(f)),"Z", 4260 "\\mathbb{Z}"), 4261 "\\), given by\n"); 4262 AppendTo(stream,"\\begin{align*}\n"); 4263 str := LaTeXStringRcwaMapping(f:Indentation:=2); 4264 AppendTo(stream,str,"\\end{align*}"); 4265 if HasIsTame(f) then 4266 if IsTame(f) then AppendTo(stream,"\nThis mapping is tame."); 4267 else AppendTo(stream,"\nThis mapping is wild."); fi; 4268 fi; 4269 if HasOrder(f) then 4270 AppendTo(stream,"\nThe order of this mapping is \\(", 4271 IntOrInfinityToLaTeX(Order(f)),"\\)."); 4272 fi; 4273 if HasIsTame(f) or HasOrder(f) then AppendTo(stream," \\newline"); fi; 4274 AppendTo(stream,"\n\n\\end{document}\n"); 4275 latex := Filename(DirectoriesSystemPrograms( ),"latex"); 4276 Process(tmpdir,latex,InputTextNone( ),OutputTextNone( ),[file]); 4277 dvi := Filename(DirectoriesSystemPrograms( ),"xdvi"); 4278 Process(tmpdir,dvi,InputTextNone( ),OutputTextNone( ), 4279 ["-paper","a1r","rcwamap.dvi"]); 4280 end ); 4281 4282############################################################################# 4283## 4284#S Comparing rcwa mappings. //////////////////////////////////////////////// 4285## 4286############################################################################# 4287 4288############################################################################# 4289## 4290#M \=( <f>, <g> ) . . . . . . . . . . . . . for rcwa mappings of Z or Z_(pi) 4291## 4292InstallMethod( \=, 4293 "for two rcwa mappings of Z or Z_(pi), standard rep. (RCWA)", 4294 IsIdenticalObj, 4295 [ IsRcwaMappingOfZOrZ_piInStandardRep, 4296 IsRcwaMappingOfZOrZ_piInStandardRep ], 0, 4297 function ( f, g ) return f!.coeffs = g!.coeffs; end ); 4298InstallMethod( \=, 4299 "for two rcwa mappings of Z or Z_(pi), sparse rep. (RCWA)", 4300 IsIdenticalObj, 4301 [ IsRcwaMappingOfZOrZ_piInSparseRep, 4302 IsRcwaMappingOfZOrZ_piInSparseRep ], 0, 4303 function ( f, g ) return f!.coeffs = g!.coeffs; end ); 4304 4305############################################################################# 4306## 4307#M \=( <f>, <g> ) . . . . . . . . . . . . . . . . . for rcwa mappings of Z^2 4308## 4309InstallMethod( \=, 4310 "for two rcwa mappings of Z^2 (RCWA)", 4311 IsIdenticalObj, 4312 [ IsRcwaMappingOfZxZInStandardRep, 4313 IsRcwaMappingOfZxZInStandardRep ], 0, 4314 4315 function ( f, g ) 4316 return f!.modulus = g!.modulus and f!.coeffs = g!.coeffs; 4317 end ); 4318 4319############################################################################# 4320## 4321#M \=( <f>, <g> ) . . . . . . . . . . . . . . for rcwa mappings of GF(q)[x] 4322## 4323InstallMethod( \=, 4324 "for two rcwa mappings of GF(q)[x] (RCWA)", 4325 IsIdenticalObj, 4326 [ IsRcwaMappingOfGFqxInStandardRep, 4327 IsRcwaMappingOfGFqxInStandardRep ], 0, 4328 4329 function ( f, g ) 4330 return f!.modulus = g!.modulus and f!.coeffs = g!.coeffs; 4331 end ); 4332 4333############################################################################# 4334## 4335#M \=( <f>, <g> ) . . . . . . . for rcwa mappings, standard vs. sparse rep. 4336#M \=( <f>, <g> ) . . . . . . . for rcwa mappings, sparse vs. standard rep. 4337## 4338InstallMethod( \=, 4339 "for two rcwa mappings, standard vs. sparse rep. (RCWA)", 4340 IsIdenticalObj, 4341 [ IsRcwaMappingInStandardRep, IsRcwaMappingInSparseRep ], 0, 4342 function ( f, g ) return SparseRepresentation(f) = g; end ); 4343InstallMethod( \=, 4344 "for two rcwa mappings, sparse vs. standard rep. (RCWA)", 4345 IsIdenticalObj, 4346 [ IsRcwaMappingInSparseRep, IsRcwaMappingInStandardRep ], 0, 4347 function ( f, g ) return f = SparseRepresentation(g); end ); 4348 4349############################################################################# 4350## 4351#M \<( <f>, <g> ) . . . . . . . . . . . . for rcwa mappings in standard rep. 4352#M \<( <f>, <g> ) . . . . . . . . . . . . . for rcwa mappings in sparse rep. 4353#M \<( <f>, <g> ) . . . . . . . for rcwa mappings: standard vs. sparse rep. 4354#M \<( <f>, <g> ) . . . . . . . for rcwa mappings: sparse vs. standard rep. 4355## 4356## Total ordering of rcwa maps (for technical purposes, only). 4357## More methods are needed as soon as further representations of 4358## rcwa mappings are implemented. 4359## 4360InstallMethod( \<, 4361 "for rcwa mappings in standard rep. (RCWA)", IsIdenticalObj, 4362 [ IsRcwaMappingInStandardRep, IsRcwaMappingInStandardRep ], 0, 4363 4364 function ( f, g ) 4365 if f!.modulus <> g!.modulus 4366 then return f!.modulus < g!.modulus; 4367 else return f!.coeffs < g!.coeffs; fi; 4368 end ); 4369 4370InstallMethod( \<, 4371 "for rcwa mappings in sparse rep. (RCWA)", IsIdenticalObj, 4372 [ IsRcwaMappingInSparseRep, IsRcwaMappingInSparseRep ], 0, 4373 4374 function ( f, g ) 4375 4376 local r, m, cf, cg; 4377 4378 if f!.modulus <> g!.modulus 4379 then return f!.modulus < g!.modulus; 4380 elif f = g 4381 then return false; else 4382 m := f!.modulus; r := 0; 4383 while r < m do 4384 cf := First(f!.coeffs,c->c[1] = r mod c[2]){[3..5]}; 4385 cg := First(g!.coeffs,c->c[1] = r mod c[2]){[3..5]}; 4386 if cf <> cg then return cf < cg; fi; 4387 r := r + 1; 4388 od; 4389 fi; 4390 end ); 4391 4392InstallMethod( \<, 4393 "for rcwa mappings: standard vs. sparse rep. (RCWA)", 4394 IsIdenticalObj, 4395 [ IsRcwaMappingInStandardRep, IsRcwaMappingInSparseRep ], 0, 4396 4397 function ( f, g ) 4398 4399 local r, m, cf, cg; 4400 4401 if f!.modulus <> g!.modulus 4402 then return f!.modulus < g!.modulus; 4403 elif f = g 4404 then return false; else 4405 m := f!.modulus; r := 0; 4406 while r < m do 4407 cf := f!.coeffs[r+1]; 4408 cg := First(g!.coeffs,c->c[1] = r mod c[2]){[3..5]}; 4409 if cf <> cg then return cf < cg; fi; 4410 r := r + 1; 4411 od; 4412 fi; 4413 end ); 4414 4415InstallMethod( \<, 4416 "for rcwa mappings: sparse vs. standard rep. (RCWA)", 4417 IsIdenticalObj, 4418 [ IsRcwaMappingInSparseRep, IsRcwaMappingInStandardRep ], 0, 4419 4420 function ( f, g ) 4421 4422 local r, m, cf, cg; 4423 4424 if f!.modulus <> g!.modulus 4425 then return f!.modulus < g!.modulus; 4426 elif f = g 4427 then return false; else 4428 m := f!.modulus; r := 0; 4429 while r < m do 4430 cf := First(f!.coeffs,c->c[1] = r mod c[2]){[3..5]}; 4431 cg := g!.coeffs[r+1]; 4432 if cf <> cg then return cf < cg; fi; 4433 r := r + 1; 4434 od; 4435 fi; 4436 end ); 4437 4438############################################################################# 4439## 4440#S On the zero- and the identity rcwa mapping. ///////////////////////////// 4441## 4442############################################################################# 4443 4444############################################################################# 4445## 4446#V ZeroRcwaMappingOfZ . . . . . . . . . . . . . . . . zero rcwa mapping of Z 4447#V ZeroRcwaMappingOfZxZ . . . . . . . . . . . . . . zero rcwa mapping of Z^2 4448## 4449InstallValue( ZeroRcwaMappingOfZ, RcwaMapping( [ [ 0, 0, 1 ] ] ) ); 4450SetIsZero( ZeroRcwaMappingOfZ, true ); 4451SetImagesSource( ZeroRcwaMappingOfZ, [ 0 ] ); 4452InstallValue( ZeroRcwaMappingOfZxZ, 4453 RcwaMapping( Integers^2, [ [ 1, 0 ], [ 0, 1 ] ], 4454 [ [ [ [ 0, 0 ], [ 0, 0 ] ], [ 0, 0 ], 1 ] ] ) ); 4455SetIsZero( ZeroRcwaMappingOfZxZ, true ); 4456SetImagesSource( ZeroRcwaMappingOfZ, [ 0, 0 ] ); 4457 4458############################################################################# 4459## 4460#M Zero( <f> ) . . . . . . . . . . . for rcwa mappings of Z in standard rep. 4461#M Zero( <f> ) . . . . . . . . . . . . for rcwa mappings of Z in sparse rep. 4462#M Zero( <f> ) . . . . . . . . . . . . . . . . . . for rcwa mappings of Z^2 4463## 4464## Zero rcwa mapping of Z or Z^2, respectively. 4465## 4466InstallMethod( Zero, "for rcwa mappings of Z in standard rep. (RCWA)", true, 4467 [ IsRcwaMappingOfZInStandardRep ], 0, 4468 f -> ZeroRcwaMappingOfZ ); 4469InstallMethod( Zero, "for rcwa mappings of Z in sparse rep. (RCWA)", true, 4470 [ IsRcwaMappingOfZInSparseRep ], 0, 4471 f -> SparseRep( ZeroRcwaMappingOfZ ) ); 4472InstallMethod( Zero, "for rcwa mappings of Z^2 (RCWA)", true, 4473 [ IsRcwaMappingOfZxZInStandardRep ], 0, 4474 f -> ZeroRcwaMappingOfZxZ ); 4475 4476############################################################################# 4477## 4478#M Zero( <f> ) . . . . . . . . . . . . . . . . . for rcwa mappings of Z_(pi) 4479## 4480## Zero rcwa mapping of Z_(pi). 4481## 4482InstallMethod( Zero, "for rcwa mappings of Z_(pi) (RCWA)", true, 4483 [ IsRcwaMappingOfZ_piInStandardRep ], 0, 4484 4485 function ( f ) 4486 4487 local zero; 4488 4489 zero := RcwaMappingNC( NoninvertiblePrimes(Source(f)), [ [ 0, 0, 1 ] ] ); 4490 SetIsZero( zero, true ); 4491 SetImagesSource( zero, [ 0 ] ); 4492 return zero; 4493 end ); 4494 4495############################################################################# 4496## 4497#M Zero( <f> ) . . . . . . . . . . . . . . . . for rcwa mappings of GF(q)[x] 4498## 4499## Zero rcwa mapping of GF(q)[x]. 4500## 4501InstallMethod( Zero, "for rcwa mappings of GF(q)[x] (RCWA)", true, 4502 [ IsRcwaMappingOfGFqxInStandardRep ], 0, 4503 4504 function ( f ) 4505 4506 local zero; 4507 4508 zero := RcwaMappingNC( Size(UnderlyingField(f)), One(Source(f)), 4509 [ [ 0, 0, 1 ] ] * One(Source(f)) ); 4510 SetIsZero( zero, true ); 4511 SetImagesSource( zero, [ Zero(Source(f)) ] ); 4512 return zero; 4513 end ); 4514 4515############################################################################# 4516## 4517#M IsZero( <f> ) . . . . . . . . . . . . . . . . . . . . . for rcwa mappings 4518## 4519## <f> = zero rcwa mapping? 4520## 4521InstallMethod( IsZero, "for rcwa mappings in standard rep. (RCWA)", 4522 true, [ IsRcwaMappingInStandardRep ], 0, 4523 4524 function ( f ) 4525 if not IsRing( Source( f ) ) then TryNextMethod( ); fi; 4526 return f!.coeffs = [ [ 0, 0, 1 ] ] * One( Source( f ) ); 4527 end ); 4528 4529InstallMethod( IsZero, "for rcwa mappings of Z in sparse rep. (RCWA)", 4530 true, [ IsRcwaMappingOfZInSparseRep ], 0, 4531 f -> f!.coeffs = [ [ 0, 1, 0, 0, 1 ] ] ); 4532 4533InstallMethod( IsZero, "for rcwa mappings of Z^2 (RCWA)", true, 4534 [ IsRcwaMappingOfZxZInStandardRep ], 0, 4535 f -> f = ZeroRcwaMappingOfZxZ ); 4536 4537############################################################################# 4538## 4539#V IdentityRcwaMappingOfZ . . . . . . . . . . . . identity rcwa mapping of Z 4540#V IdentityRcwaMappingOfZxZ . . . . . . . . . . identity rcwa mapping of Z^2 4541## 4542InstallValue( IdentityRcwaMappingOfZ, RcwaMapping( [ [ 1, 0, 1 ] ] ) ); 4543SetIsOne( IdentityRcwaMappingOfZ, true ); 4544InstallValue( IdentityRcwaMappingOfZxZ, 4545 RcwaMapping( Integers^2, [ [ 1, 0 ], [ 0, 1 ] ], 4546 [ [ [ [ 1, 0 ], [ 0, 1 ] ], [ 0, 0 ], 1 ] ] ) ); 4547SetIsOne( IdentityRcwaMappingOfZxZ, true ); 4548 4549############################################################################# 4550## 4551#M One( <f> ) . . . . . . . . . . . for rcwa mappings of Z in standard rep. 4552#M One( <f> ) . . . . . . . . . . . . for rcwa mappings of Z in sparse rep. 4553#M One( <f> ) . . . . . . . . . . . . . . . . . . . for rcwa mappings of Z^2 4554## 4555## Identity rcwa mapping of Z or Z^2, respectively. 4556## 4557InstallMethod( One, "for rcwa mappings of Z in standard rep. (RCWA)", true, 4558 [ IsRcwaMappingOfZInStandardRep ], 0, 4559 f -> IdentityRcwaMappingOfZ ); 4560InstallMethod( One, "for rcwa mappings of Z in sparse rep. (RCWA)", true, 4561 [ IsRcwaMappingOfZInSparseRep ], 0, 4562 f -> SparseRep( IdentityRcwaMappingOfZ ) ); 4563InstallMethod( One, "for rcwa mappings of Z^2 (RCWA)", true, 4564 [ IsRcwaMappingOfZxZInStandardRep ], 0, 4565 f -> IdentityRcwaMappingOfZxZ ); 4566 4567############################################################################# 4568## 4569#M One( <f> ) . . . . . . . . . . . . . . . . . for rcwa mappings of Z_(pi) 4570## 4571## Identity rcwa mapping of Z_(pi). 4572## 4573InstallMethod( One, "for rcwa mappings of Z_(pi) (RCWA)", true, 4574 [ IsRcwaMappingOfZ_piInStandardRep ], 0, 4575 4576 function ( f ) 4577 4578 local one; 4579 4580 one := RcwaMappingNC( NoninvertiblePrimes(Source(f)), [ [ 1, 0, 1 ] ] ); 4581 SetIsOne( one, true ); return one; 4582 end ); 4583 4584############################################################################# 4585## 4586#M One( <f> ) . . . . . . . . . . . . . . . . for rcwa mappings of GF(q)[x] 4587## 4588## Identity rcwa mapping of GF(q)[x]. 4589## 4590InstallMethod( One, "for rcwa mappings of GF(q)[x] (RCWA)", true, 4591 [ IsRcwaMappingOfGFqxInStandardRep ], 0, 4592 4593 function ( f ) 4594 4595 local one; 4596 4597 one := RcwaMappingNC( Size(UnderlyingField(f)), One(Source(f)), 4598 [ [ 1, 0, 1 ] ] * One( Source( f ) ) ); 4599 SetIsOne( one, true ); return one; 4600 end ); 4601 4602############################################################################# 4603## 4604#M IsOne( <f> ) . . . . . . . . . . . . . . . . . . . . . for rcwa mappings 4605## 4606## <f> = identity rcwa mapping? 4607## 4608InstallMethod( IsOne, "for rcwa mappings in standard rep. (RCWA)", 4609 true, [ IsRcwaMappingInStandardRep ], 0, 4610 4611 function ( f ) 4612 if not IsRing( Source( f ) ) then TryNextMethod( ); fi; 4613 return f!.coeffs = [ [ 1, 0, 1 ] ] * One( Source( f ) ); 4614 end ); 4615 4616InstallMethod( IsOne, "for rcwa mappings of Z in sparse rep. (RCWA)", 4617 true, [ IsRcwaMappingOfZInSparseRep ], 0, 4618 f -> f!.coeffs = [ [ 0, 1, 1, 0, 1 ] ] ); 4619 4620InstallMethod( IsOne, "for rcwa mappings of Z^2 (RCWA)", true, 4621 [ IsRcwaMappingOfZxZInStandardRep ], 0, 4622 f -> f = IdentityRcwaMappingOfZxZ ); 4623 4624############################################################################# 4625## 4626#M ViewString( <zero> ) . . . . . . . . . . . . . for the zero rcwa mapping 4627#M ViewString( <one> ) . . . . . . . . . . . for the identity rcwa mapping 4628## 4629InstallMethod( ViewString, "for the zero rcwa mapping (RCWA)", true, 4630 [ IsRcwaMapping and IsZero ], 0, 4631 f -> Concatenation("ZeroMapping( ",String(Source(f)),", ", 4632 String(Source(f))," )") ); 4633 4634InstallMethod( ViewString, "for the identity rcwa mapping (RCWA)", true, 4635 [ IsRcwaMapping and IsOne ], 0, 4636 f -> Concatenation("IdentityMapping( ", 4637 String(Source(f))," )") ); 4638 4639############################################################################# 4640## 4641#S Accessing the components of an rcwa mapping object. ///////////////////// 4642## 4643############################################################################# 4644 4645############################################################################# 4646## 4647#M Modulus( <f> ) . . . . . . . for rcwa mappings in standard representation 4648#M Modulus( <f> ) . . . . . . . . for rcwa mappings in sparse representation 4649## 4650InstallMethod( Modulus, "for rcwa mappings in standard rep. (RCWA)", 4651 true, [ IsRcwaMappingInStandardRep ], 0, f -> f!.modulus ); 4652InstallMethod( Modulus, "for rcwa mappings in sparse rep. (RCWA)", 4653 true, [ IsRcwaMappingInSparseRep ], 0, f -> f!.modulus ); 4654 4655############################################################################# 4656## 4657#M Coefficients( <f> ) . . . . for rcwa mappings in standard representation 4658#M Coefficients( <f> ) . . . . . for rcwa mappings in sparse representation 4659## 4660InstallMethod( Coefficients, "for rcwa mappings in standard rep. (RCWA)", 4661 true, [ IsRcwaMappingInStandardRep ], 0, f -> f!.coeffs ); 4662InstallMethod( Coefficients, "for rcwa mappings in sparse rep. (RCWA)", 4663 true, [ IsRcwaMappingInSparseRep ], 0, f -> f!.coeffs ); 4664 4665############################################################################# 4666## 4667#S Methods for the attributes and properties derived from the coefficients. 4668## 4669############################################################################# 4670 4671############################################################################# 4672## 4673#M Multiplier( <f> ) . . . . . . . . . . . . . . . . . . . for rcwa mappings 4674## 4675InstallMethod( Multiplier, "for rcwa mappings in standard rep. (RCWA)", 4676 true, [ IsRcwaMappingInStandardRep ], 0, 4677 f -> Lcm( UnderlyingRing( FamilyObj( f ) ), 4678 List( f!.coeffs, c -> c[1] ) ) ); 4679InstallMethod( Multiplier, "for rcwa mappings in sparse rep. (RCWA)", 4680 true, [ IsRcwaMappingInSparseRep ], 0, 4681 f -> Lcm( UnderlyingRing( FamilyObj( f ) ), 4682 List( f!.coeffs, c -> c[3] ) ) ); 4683InstallMethod( Multiplier, "for rcwa mappings of Z^2 (RCWA)", true, 4684 [ IsRcwaMappingOfZxZInStandardRep ], 10, 4685 f -> Lcm( List( f!.coeffs, c -> c[1] ) ) ); 4686InstallMethod( Multiplier, "for rcwa mappings of Z_(pi) (RCWA)", true, 4687 [ IsRcwaMappingOfZ_piInStandardRep ], 10, 4688 f -> Lcm( List( f!.coeffs, 4689 c -> StandardAssociate(Source(f),c[1]) ) ) ); 4690 4691############################################################################# 4692## 4693#M Divisor( <f> ) . . . . . . . . . . . . . . . . . . . . for rcwa mappings 4694## 4695InstallMethod( Divisor, "for rcwa mappings in standard rep. (RCWA)", 4696 true, [ IsRcwaMappingInStandardRep ], 0, 4697 f -> Lcm( UnderlyingRing( FamilyObj( f ) ), 4698 List( f!.coeffs, c -> c[3] ) ) ); 4699InstallMethod( Divisor, "for rcwa mappings in sparse rep. (RCWA)", 4700 true, [ IsRcwaMappingInSparseRep ], 0, 4701 f -> Lcm( UnderlyingRing( FamilyObj( f ) ), 4702 List( f!.coeffs, c -> c[5] ) ) ); 4703InstallMethod( Divisor, "for rcwa mappings of Z^2 (RCWA)", true, 4704 [ IsRcwaMappingOfZxZInStandardRep ], 0, 4705 f -> Lcm( Integers, List( f!.coeffs, c -> c[3] ) ) ); 4706 4707############################################################################# 4708## 4709#M IsIntegral( <f> ) . . . . . . . . . . . . . . . . . . . for rcwa mappings 4710## 4711InstallMethod( IsIntegral, "for rcwa mappings (RCWA)", true, 4712 [ IsRcwaMapping ], 0, f -> IsOne( Divisor( f ) ) ); 4713 4714############################################################################# 4715## 4716#M IsBalanced( <f> ) . . . . . . . . . . . . . . . . . . . for rcwa mappings 4717## 4718InstallMethod( IsBalanced, "for rcwa mappings (RCWA)", true, 4719 [ IsRcwaMapping ], 0, 4720 f -> Set( Factors( Multiplier( f ) ) ) 4721 = Set( Factors( Divisor( f ) ) ) ); 4722InstallMethod( IsBalanced, "for rcwa mappings of Z^2 (RCWA)", true, 4723 [ IsRcwaMappingOfZxZ ], 0, 4724 f -> Set( Factors( DeterminantMat( Multiplier( f ) ) ) ) 4725 = Set( Factors( Divisor( f ) ) ) ); 4726 4727############################################################################# 4728## 4729#M PrimeSet( <f> ) . . . . . . . . . . . . . . . . . . . . for rcwa mappings 4730## 4731InstallMethod( PrimeSet, "for rcwa mappings (RCWA)", true, 4732 [ IsRcwaMapping ], 0, 4733 4734 function ( f ) 4735 if IsZero(Multiplier(f)) 4736 then Error("PrimeSet: Multiplier must not be zero.\n"); fi; 4737 return Filtered( Union( Factors(Source(f),Modulus(f)), 4738 Factors(Source(f),Multiplier(f)), 4739 Factors(Source(f),Divisor(f)) ), 4740 x -> IsIrreducibleRingElement( Source( f ), x ) ); 4741 end ); 4742 4743InstallMethod( PrimeSet, "for rcwa mappings of Z^2 (RCWA)", true, 4744 [ IsRcwaMappingOfZxZ ], 0, 4745 4746 function ( f ) 4747 if IsZero(Multiplier(f)) 4748 then Error("PrimeSet: Multiplier must not be zero.\n"); fi; 4749 return Filtered( Union( # Factors(DeterminantMat(Modulus(f))), 4750 Factors(DeterminantMat(Multiplier(f))), 4751 Factors(Divisor(f)) ), IsPrimeInt ); 4752 end ); 4753 4754############################################################################# 4755## 4756#M IsClassWiseTranslating( <f> ) . . . . . . . . . . . . . for rcwa mappings 4757## 4758InstallMethod( IsClassWiseTranslating, 4759 "for rcwa mappings in standard rep. (RCWA)", true, 4760 [ IsRcwaMappingInStandardRep ], 0, 4761 f -> ForAll(Coefficients(f),c->IsOne(c[1]) and IsOne(c[3])) ); 4762InstallMethod( IsClassWiseTranslating, 4763 "for rcwa mappings in sparse rep. (RCWA)", true, 4764 [ IsRcwaMappingInSparseRep ], 0, 4765 f -> ForAll(Coefficients(f),c->IsOne(c[3]) and IsOne(c[5])) ); 4766 4767############################################################################# 4768## 4769#M IsClassWiseOrderPreserving( <f> ) . for rcwa mappings of Z, Z^2 or Z_(pi) 4770## 4771InstallMethod( IsClassWiseOrderPreserving, 4772 "for rcwa mappings of Z or Z_(pi) in standard rep. (RCWA)", 4773 true, [ IsRcwaMappingOfZOrZ_piInStandardRep ], 0, 4774 f -> ForAll( f!.coeffs, c -> c[ 1 ] > 0 ) ); 4775InstallMethod( IsClassWiseOrderPreserving, 4776 "for rcwa mappings of Z or Z_(pi) in sparse rep. (RCWA)", 4777 true, [ IsRcwaMappingOfZOrZ_piInSparseRep ], 0, 4778 f -> ForAll( f!.coeffs, c -> c[ 3 ] > 0 ) ); 4779InstallMethod( IsClassWiseOrderPreserving, 4780 "for rcwa mappings of Z^2 (RCWA)", true, 4781 [ IsRcwaMappingOfZxZInStandardRep ], 0, 4782 f -> ForAll( f!.coeffs, c -> DeterminantMat( c[ 1 ] ) > 0 ) ); 4783 4784############################################################################# 4785## 4786#M ClassWiseOrderPreservingOn( <f> ) for rcwa mappings of Z, Z^2 or Z_(pi) 4787## 4788InstallMethod( ClassWiseOrderPreservingOn, 4789 "for rcwa mappings of Z or Z_(pi) in standard rep. (RCWA)", 4790 true, [ IsRcwaMappingOfZOrZ_piInStandardRep ], 0, 4791 f -> ResidueClassUnion( Source( f ), Modulus( f ), 4792 Filtered( [ 0 .. Modulus( f ) - 1 ], 4793 r -> Coefficients( f )[r+1][1] > 0 ) ) ); 4794InstallMethod( ClassWiseOrderPreservingOn, 4795 "for rcwa mappings of Z in sparse rep. (RCWA)", 4796 true, [ IsRcwaMappingOfZInSparseRep ], 0, 4797 f -> Union( List( Filtered( f!.coeffs, c -> c[3] > 0 ), 4798 d -> ResidueClass( d[1], d[2] ) ) ) ); 4799InstallMethod( ClassWiseOrderPreservingOn, 4800 "for rcwa mappings of Z^2 (RCWA)", 4801 true, [ IsRcwaMappingOfZxZ ], 0, 4802 f -> ResidueClassUnion( Source( f ), Modulus( f ), 4803 AllResidues( Source( f ), Modulus( f ) ) 4804 {Filtered([ 1 .. DeterminantMat( Modulus( f ) ) ], 4805 r -> DeterminantMat(Coefficients(f)[r][1]) > 0)} ) ); 4806 4807############################################################################# 4808## 4809#M ClassWiseOrderReversingOn( <f> ) . for rcwa mappings of Z, Z^2 or Z_(pi) 4810## 4811InstallMethod( ClassWiseOrderReversingOn, 4812 "for rcwa mappings of Z or Z_(pi) in standard rep. (RCWA)", 4813 true, [ IsRcwaMappingOfZOrZ_piInStandardRep ], 0, 4814 f -> ResidueClassUnion( Source( f ), Modulus( f ), 4815 Filtered( [ 0 .. Modulus( f ) - 1 ], 4816 r -> Coefficients( f )[r+1][1] < 0 ) ) ); 4817InstallMethod( ClassWiseOrderReversingOn, 4818 "for rcwa mappings of Z in sparse rep. (RCWA)", 4819 true, [ IsRcwaMappingOfZInSparseRep ], 0, 4820 f -> Union( List( Filtered( f!.coeffs, c -> c[3] < 0 ), 4821 d -> ResidueClass( d[1], d[2] ) ) ) ); 4822InstallMethod( ClassWiseOrderReversingOn, 4823 "for rcwa mappings of Z^2 (RCWA)", 4824 true, [ IsRcwaMappingOfZxZ ], 0, 4825 f -> ResidueClassUnion( Source( f ), Modulus( f ), 4826 AllResidues( Source( f ), Modulus( f ) ) 4827 {Filtered([ 1 .. DeterminantMat( Modulus( f ) ) ], 4828 r -> DeterminantMat(Coefficients(f)[r][1]) < 0)} ) ); 4829 4830############################################################################# 4831## 4832##M ClassWiseConstantOn( <f> ) . . . . for rcwa mappings of Z, Z^2 or Z_(pi) 4833## 4834InstallMethod( ClassWiseConstantOn, 4835 "for rcwa mappings of Z or Z_(pi) in standard rep. (RCWA)", 4836 true, [ IsRcwaMappingOfZOrZ_piInStandardRep ], 0, 4837 f -> ResidueClassUnion( Source( f ), Modulus( f ), 4838 Filtered( [ 0 .. Modulus( f ) - 1 ], 4839 r -> Coefficients( f )[r+1][1] = 0 ) ) ); 4840InstallMethod( ClassWiseConstantOn, 4841 "for rcwa mappings of Z in sparse rep. (RCWA)", 4842 true, [ IsRcwaMappingOfZInSparseRep ], 0, 4843 f -> Union( List( Filtered( f!.coeffs, c -> c[3] = 0 ), 4844 d -> ResidueClass( d[1], d[2] ) ) ) ); 4845InstallMethod( ClassWiseConstantOn, 4846 "for rcwa mappings of Z^2 (RCWA)", 4847 true, [ IsRcwaMappingOfZxZ ], 0, 4848 f -> ResidueClassUnion( Source( f ), Modulus( f ), 4849 AllResidues( Source( f ), Modulus( f ) ) 4850 {Filtered([ 1 .. DeterminantMat( Modulus( f ) ) ], 4851 r -> IsZero(Coefficients(f)[r][1]))} ) ); 4852 4853############################################################################# 4854## 4855#P IsSignPreserving( <f> ) . . . . . . . . . . . . . for rcwa mappings of Z 4856## 4857InstallMethod( IsSignPreserving, "for rcwa mappings of Z (RCWA)", true, 4858 [ IsRcwaMappingOfZ ], 0, 4859 4860 function ( f ) 4861 4862 local bound, ind; 4863 4864 if not IsClassWiseOrderPreserving(f) then return false; fi; 4865 if IsRcwaMappingStandardRep(f) then ind := 2; 4866 elif IsRcwaMappingSparseRep(f) then ind := 4; 4867 else TryNextMethod(); fi; 4868 bound := Maximum(1,Maximum(List(Coefficients(f),c->AbsInt(c[ind])))); 4869 return Minimum([0..bound]^f) >= 0 and Maximum([-bound..-1]^f) < 0; 4870 end ); 4871 4872############################################################################# 4873## 4874#M IncreasingOn( <f> ) . . . . . . . . . for rcwa mappings in standard rep. 4875## 4876InstallMethod( IncreasingOn, "for rcwa mappings in standard rep. (RCWA)", 4877 true, [ IsRcwaMappingInStandardRep ], 0, 4878 4879 function ( f ) 4880 4881 local R, m, c, selection; 4882 4883 R := Source(f); m := Modulus(f); c := Coefficients(f); 4884 if IsRing(R) then 4885 selection := Filtered([1..NumberOfResidues(R,m)], 4886 r -> NumberOfResidues(R,c[r][3]) 4887 < NumberOfResidues(R,c[r][1])); 4888 elif IsZxZ(R) then 4889 selection := Filtered([1..NumberOfResidues(R,m)], 4890 r -> c[r][3]^2 < NumberOfResidues(R,c[r][1])); 4891 else TryNextMethod(); fi; 4892 return ResidueClassUnion(R,m,AllResidues(R,m){selection}); 4893 end ); 4894 4895############################################################################# 4896## 4897#M IncreasingOn( <f> ) . . . . . . . . for rcwa mappings of Z in sparse rep. 4898## 4899InstallMethod( IncreasingOn, "for rcwa mappings of Z in sparse rep. (RCWA)", 4900 true, [ IsRcwaMappingOfZInSparseRep ], 0, 4901 4902 function ( f ) 4903 if ValueOption("classes") = true then 4904 return Set(Filtered(f!.coeffs,c->AbsInt(c[3])>c[5]), 4905 c->ResidueClass(c[1],c[2])); 4906 else 4907 return ResidueClassUnion(Integers, 4908 List(Filtered(f!.coeffs,c->AbsInt(c[3])>c[5]), 4909 c->c{[1,2]})); 4910 fi; 4911 end ); 4912 4913############################################################################# 4914## 4915#M DecreasingOn( <f> ) . . . . . . . . . for rcwa mappings in standard rep. 4916## 4917InstallMethod( DecreasingOn, "for rcwa mappings in standard rep. (RCWA)", 4918 true, [ IsRcwaMappingInStandardRep ], 0, 4919 4920 function ( f ) 4921 4922 local R, m, c, selection; 4923 4924 R := Source(f); m := Modulus(f); c := Coefficients(f); 4925 if IsRing(R) then 4926 selection := Filtered([1..NumberOfResidues(R,m)], 4927 r -> NumberOfResidues(R,c[r][3]) 4928 > NumberOfResidues(R,c[r][1])); 4929 elif IsZxZ(R) then 4930 selection := Filtered([1..NumberOfResidues(R,m)], 4931 r -> c[r][3]^2 > NumberOfResidues(R,c[r][1])); 4932 else TryNextMethod(); fi; 4933 return ResidueClassUnion(R,m,AllResidues(R,m){selection}); 4934 end ); 4935 4936############################################################################# 4937## 4938#M DecreasingOn( <f> ) . . . . . . . . for rcwa mappings of Z in sparse rep. 4939## 4940InstallMethod( DecreasingOn, "for rcwa mappings of Z in sparse rep. (RCWA)", 4941 true, [ IsRcwaMappingOfZInSparseRep ], 0, 4942 4943 function ( f ) 4944 if ValueOption("classes") = true then 4945 return Set(Filtered(f!.coeffs,c->AbsInt(c[3])<c[5]), 4946 c->ResidueClass(c[1],c[2])); 4947 else 4948 return ResidueClassUnion(Integers, 4949 List(Filtered(f!.coeffs,c->AbsInt(c[3])<c[5]), 4950 c->c{[1,2]})); 4951 fi; 4952 end ); 4953 4954############################################################################# 4955## 4956#M ShiftsUpOn( <f> ) . . . . . . . . . . . . . . . . for rcwa mappings of Z 4957## 4958InstallMethod( ShiftsUpOn, "for rcwa mappings of Z in standard rep. (RCWA)", 4959 true, [ IsRcwaMappingOfZInStandardRep ], 0, 4960 f -> ResidueClassUnion( Integers, Modulus(f), 4961 Filtered( [0..Modulus(f)-1], 4962 r -> Coefficients(f)[r+1]{[1,3]} = [1,1] 4963 and Coefficients(f)[r+1][2] > 0 ) ) ); 4964InstallMethod( ShiftsUpOn, "for rcwa mappings of Z in sparse rep. (RCWA)", 4965 true, [ IsRcwaMappingOfZInSparseRep ], 0, 4966 4967 function ( f ) 4968 if ValueOption("classes") = true then 4969 return Set(Filtered(f!.coeffs, 4970 c->c{[3,5]}=[1,1] and c[4]>0), 4971 c->ResidueClass(c[1],c[2])); 4972 else 4973 return ResidueClassUnion(Integers, 4974 List(Filtered(f!.coeffs, 4975 c->c{[3,5]}=[1,1] and c[4]>0), 4976 c->c{[1,2]})); 4977 fi; 4978 end ); 4979 4980############################################################################# 4981## 4982#M ShiftsDownOn( <f> ) . . . . . . . . . . . . . . . for rcwa mappings of Z 4983## 4984InstallMethod( ShiftsDownOn, 4985 "for rcwa mappings of Z in standard rep. (RCWA)", 4986 true, [ IsRcwaMappingOfZInStandardRep ], 0, 4987 f -> ResidueClassUnion( Integers, Modulus(f), 4988 Filtered( [0..Modulus(f)-1], 4989 r -> Coefficients(f)[r+1]{[1,3]} = [1,1] 4990 and Coefficients(f)[r+1][2] < 0 ) ) ); 4991InstallMethod( ShiftsDownOn, "for rcwa mappings of Z in sparse rep. (RCWA)", 4992 true, [ IsRcwaMappingOfZInSparseRep ], 0, 4993 4994 function ( f ) 4995 if ValueOption("classes") = true then 4996 return Set(Filtered(f!.coeffs, 4997 c->c{[3,5]}=[1,1] and c[4]<0), 4998 c->ResidueClass(c[1],c[2])); 4999 else 5000 return ResidueClassUnion(Integers, 5001 List(Filtered(f!.coeffs, 5002 c->c{[3,5]}=[1,1] and c[4]<0), 5003 c->c{[1,2]})); 5004 fi; 5005 end ); 5006 5007############################################################################# 5008## 5009#M MaximalShift( <f> ) . . . . . . . . . . . . . . . for rcwa mappings of Z 5010## 5011InstallMethod( MaximalShift, 5012 "for rcwa mappings of Z in standard rep. (RCWA)", 5013 true, [ IsRcwaMappingOfZInStandardRep ], 0, 5014 f -> Maximum( List( f!.coeffs, c -> AbsInt(c[2]) ) ) ); 5015InstallMethod( MaximalShift, 5016 "for rcwa mappings of Z in sparse rep. (RCWA)", 5017 true, [ IsRcwaMappingOfZInSparseRep ], 0, 5018 f -> Maximum( List( f!.coeffs, c -> AbsInt(c[4]) ) ) ); 5019 5020############################################################################# 5021## 5022#M LargestSourcesOfAffineMappings( <f> ) for rcwa mappings in standard rep. 5023## 5024InstallMethod( LargestSourcesOfAffineMappings, 5025 "for rcwa mappings in standard rep. (RCWA)", 5026 true, [ IsRcwaMappingInStandardRep ], 0, 5027 5028 function ( f ) 5029 5030 local R, m, c, r; 5031 5032 R := Source(f); 5033 m := Modulus(f); 5034 c := Coefficients(f); 5035 r := AllResidues(R,m); 5036 5037 return Set(EquivalenceClasses([1..NumberOfResidues(R,m)],i->c[i]), 5038 cl->ResidueClassUnion(R,m,r{cl})); 5039 end ); 5040 5041############################################################################# 5042## 5043#M LargestSourcesOfAffineMappings( <f> ) . for rcwa mappings in sparse rep. 5044## 5045InstallMethod( LargestSourcesOfAffineMappings, 5046 "for rcwa mappings of Z in sparse rep. (RCWA)", 5047 true, [ IsRcwaMappingOfZInSparseRep ], 0, 5048 f -> Set(EquivalenceClasses(f!.coeffs,c->c{[3..5]}), 5049 cl->ResidueClassUnion(Integers, 5050 List(cl,c->c{[1,2]}))) ); 5051 5052############################################################################# 5053## 5054#M FixedPointsOfAffinePartialMappings( <f> ) for rcwa mapping of Z or Z_(pi) 5055## 5056InstallMethod( FixedPointsOfAffinePartialMappings, 5057 "for rcwa mappings of Z or Z_(pi) (RCWA)", 5058 true, [ IsRcwaMappingOfZOrZ_pi ], 0, 5059 5060 function ( f ) 5061 5062 local m, c, fixedpoints, r; 5063 5064 if not IsRcwaMappingStandardRep(f) then f := StandardRep(f); fi; 5065 5066 m := Modulus(f); c := Coefficients(f); 5067 fixedpoints := []; 5068 for r in [1..m] do 5069 if c[r][1] = c[r][3] 5070 then if c[r][2] = 0 then fixedpoints[r] := Rationals; 5071 else fixedpoints[r] := []; fi; 5072 else fixedpoints[r] := [ c[r][2]/(c[r][3]-c[r][1]) ]; fi; 5073 od; 5074 5075 return fixedpoints; 5076 end ); 5077 5078############################################################################# 5079## 5080#M ImageDensity( <f> ) . . . . . . . . . for rcwa mappings in standard rep. 5081## 5082InstallMethod( ImageDensity, "for rcwa mappings in standard rep. (RCWA)", 5083 true, [ IsRcwaMappingInStandardRep ], 0, 5084 5085 function ( f ) 5086 5087 local R, c, m; 5088 5089 R := Source(f); c := Coefficients(f); 5090 m := NumberOfResidues(R,Modulus(f)); 5091 if IsRing(R) then 5092 return Sum([1..m],r->NumberOfResidues(R,c[r][3])/ 5093 NumberOfResidues(R,c[r][1]))/m; 5094 elif IsZxZ(R) then 5095 return Sum([1..m],r->c[r][3]^2/NumberOfResidues(R,c[r][1]))/m; 5096 else TryNextMethod(); fi; 5097 end ); 5098 5099############################################################################# 5100## 5101#M ImageDensity( <f> ) . . . . . . . . . . . for rcwa mappings in sparse rep. 5102## 5103InstallMethod( ImageDensity, "for rcwa mappings of Z in sparse rep. (RCWA)", 5104 true, [ IsRcwaMappingOfZInSparseRep ], 0, 5105 f -> Sum(List(f!.coeffs,c->c[5]/(c[2]*c[3]))) ); 5106 5107############################################################################# 5108## 5109#M DensityOfSetOfFixedPoints( <f> ) for rcwa mappings of Z in standard rep. 5110## 5111InstallMethod( DensityOfSetOfFixedPoints, 5112 "for rcwa mappings in standard rep. (RCWA)", 5113 true, [ IsRcwaMappingOfZInStandardRep ], 0, 5114 f->Number(Coefficients(f),c->c=[1,0,1])/Mod(f) ); 5115 5116############################################################################# 5117## 5118#M DensityOfSetOfFixedPoints( <f> ) . for rcwa mappings of Z in sparse rep. 5119## 5120InstallMethod( DensityOfSetOfFixedPoints, 5121 "for rcwa mappings in sparse rep. (RCWA)", 5122 true, [ IsRcwaMappingOfZInSparseRep ], 0, 5123 f->Sum(List(Filtered(Coefficients(f),c->c{[3..5]}=[1,0,1]), 5124 c->1/c[2])) ); 5125 5126############################################################################# 5127## 5128#M DensityOfSupport( <f> ) . . . . . . . . . . . . . for rcwa mappings of Z 5129## 5130InstallMethod( DensityOfSupport, "for rcwa mappings (RCWA)", 5131 true, [ IsRcwaMappingOfZ ], 0, 5132 f -> 1 - DensityOfSetOfFixedPoints( f ) ); 5133 5134############################################################################# 5135## 5136#M Multpk( <f>, <p>, <k> ) . . . . . for rcwa mappings of Z in standard rep. 5137## 5138InstallMethod( Multpk, "for rcwa mappings of Z in standard rep. (RCWA)", 5139 true, [ IsRcwaMappingOfZInStandardRep, IsInt, IsInt ], 0, 5140 5141 function ( f, p, k ) 5142 5143 local m, c, res; 5144 5145 m := Modulus(f); c := Coefficients(f); 5146 res := Filtered([0..m-1],r->PadicValuation(c[r+1][1]/c[r+1][3],p)=k); 5147 return ResidueClassUnion(Integers,m,res); 5148 end ); 5149 5150############################################################################# 5151## 5152#M Multpk( <f>, <p>, <k> ) . . . . . . for rcwa mappings of Z in sparse rep. 5153## 5154InstallMethod( Multpk, "for rcwa mappings of Z in sparse rep. (RCWA)", 5155 true, [ IsRcwaMappingOfZInSparseRep, IsInt, IsInt ], 0, 5156 5157 function ( f, p, k ) 5158 return ResidueClassUnion(Integers, 5159 List(Filtered(f!.coeffs, 5160 c->PadicValuation(c[3]/c[5],p)=k), 5161 c->c{[1,2]})); 5162 end ); 5163 5164############################################################################# 5165## 5166#M Multpk( <f>, <p>, <k> ) . . . . . . . . . . . . for rcwa mappings of Z^2 5167## 5168InstallMethod( Multpk, "for rcwa mappings of Z^2 (RCWA)", true, 5169 [ IsRcwaMappingOfZxZ, IsInt, IsInt ], 0, 5170 5171 function ( f, p, k ) 5172 5173 local R, m, c, r; 5174 5175 R := Source(f); m := Modulus(f); c := Coefficients(f); 5176 r := Filtered([1..NumberOfResidues(R,m)], 5177 i->PadicValuation(DeterminantMat(c[i][1])/c[i][3]^2,p)=k); 5178 return ResidueClassUnion(R,m,AllResidues(R,m){r}); 5179 end ); 5180 5181############################################################################# 5182## 5183#M MultDivType( <f> ) . . . . . . . . for rcwa mappings of Z in standard rep. 5184## 5185InstallMethod( MultDivType, 5186 "for rcwa mappings of Z in standard rep. (RCWA)", 5187 true, [ IsRcwaMappingOfZInStandardRep ], 0, 5188 f->List(Collected(List(Coefficients(f),c->c[1]/c[3])), 5189 t->[t[1],t[2]/Mod(f)]) ); 5190 5191############################################################################# 5192## 5193#M MultDivType( <f> ) . . . . . . . . for rcwa mappings of Z in sparse rep. 5194## 5195InstallMethod( MultDivType, 5196 "for rcwa mappings of Z in sparse rep. (RCWA)", 5197 true, [ IsRcwaMappingOfZInSparseRep ], 0, 5198 f->List(EquivalenceClasses(f!.coeffs,c->c[3]/c[5]), 5199 cl->[cl[1][3]/cl[1][5],Sum(List(cl,c->1/c[2]))]) ); 5200 5201############################################################################# 5202## 5203#M MappedPartitions( <g> ) . . . . . . . for rcwa mappings in standard rep. 5204## 5205InstallMethod( MappedPartitions, "for rcwa mappings in standard rep. (RCWA)", 5206 true, [ IsRcwaMappingInStandardRep ], 0, 5207 5208 function ( g ) 5209 5210 local P; 5211 5212 P := AllResidueClassesModulo( Source(g), Mod(g) ); 5213 return [ List(P,Density), List(P^g,Density) ]; 5214 end ); 5215 5216############################################################################# 5217## 5218#M MappedPartitions( <g> ) . . . . . . for rcwa mappings of Z in sparse rep. 5219## 5220InstallMethod( MappedPartitions, 5221 "for rcwa mappings of Z in sparse rep. (RCWA)", 5222 true, [ IsRcwaMappingOfZInSparseRep ], 0, 5223 g -> [List(g!.coeffs,c->1/c[2]), 5224 List(g!.coeffs,c->c[5]/(c[2]*c[3]))] ); 5225 5226############################################################################# 5227## 5228#M HashValueOfRcwaMapping( <f>, <m> ) . . . . . . . . for rcwa mappings of Z 5229## 5230InstallMethod( HashValueOfRcwaMapping, 5231 "for rcwa mappings of Z (RCWA)", ReturnTrue, 5232 [ IsRcwaMappingOfZ, IsPosInt ], 0, 5233 5234 function ( f, m ) 5235 5236 local c, n, max, i; 5237 5238 if not IsRcwaMappingOfZInSparseRep(f) 5239 and not IsRcwaMappingOfZInStandardRep(f) 5240 then TryNextMethod(); fi; 5241 c := Coefficients(f); max := m^3; n := 1; 5242 for i in [1..Length(c)] do 5243 n := (n*c[i][1]+c[i][2])*c[i][3]+c[i][1]; 5244 if Length(c[i]) = 5 then n := (n+c[i][4])*c[i][5]+c[i][3]; fi; 5245 if AbsInt(n) > max then break; fi; 5246 od; 5247 return n mod m + 1; 5248 end ); 5249 5250############################################################################# 5251## 5252#S The support of an rcwa mapping. ///////////////////////////////////////// 5253## 5254############################################################################# 5255 5256############################################################################# 5257## 5258#M MovedPoints( <f> ) . . . . . . . . . . for rcwa mappings in standard rep. 5259## 5260## The set of moved points (support) of the rcwa mapping <f>. 5261## 5262InstallMethod( MovedPoints, 5263 "for rcwa mappings in standard rep. (RCWA)", 5264 true, [ IsRcwaMappingInStandardRep ], 0, 5265 5266 function ( f ) 5267 5268 local R, m, c, residues, indices, 5269 fixedpoint, fixedpoints, fixedline, fixedlines, 5270 A, b, d, mat, i, quiet; 5271 5272 R := Source(f); m := Modulus(f); c := Coefficients(f); 5273 residues := AllResidues(R,m); 5274 if IsRcwaMappingOfZOrZ_pi(f) 5275 then indices := Filtered([1..Length(residues)],i->c[i]<>[1,0,1]); 5276 elif IsRcwaMappingOfZxZ(f) 5277 then indices := Filtered([1..Length(residues)], 5278 i->c[i]<>[[[1,0],[0,1]],[0,0],1]); 5279 else indices := Filtered([1..Length(residues)],i->c[i]<>[1,0,1]*One(R)); 5280 fi; 5281 quiet := ValueOption("BeQuiet") = true; 5282 fixedpoints := []; fixedlines := []; 5283 if IsRing(R) then 5284 for i in indices do 5285 if c[i]{[1,3]} <> [1,1] * One(R) then 5286 fixedpoint := c[i][2]/(c[i][3]-c[i][1]); 5287 if fixedpoint in R and fixedpoint mod m = residues[i] 5288 then Add(fixedpoints,fixedpoint); fi; 5289 fi; 5290 od; 5291 elif IsZxZ(R) then 5292 for i in indices do 5293 if c[i]{[1,3]} <> [[[1,0],[0,1]],1] then 5294 A := c[i][1]; b := c[i][2]; d := c[i][3]; 5295 mat := A - [[d,0],[0,d]]; 5296 if DeterminantMat(mat) <> 0 then 5297 fixedpoint := -b/mat; 5298 if fixedpoint in R and fixedpoint mod m = residues[i] 5299 then Add(fixedpoints,fixedpoint); fi; 5300 else 5301 fixedline := SolutionNullspaceIntMat(mat,-b); # (v,w): v+k*w 5302 if fixedline[1] <> fail then Add(fixedlines,fixedline); fi; 5303 fi; 5304 fi; 5305 od; 5306 else TryNextMethod(); fi; 5307 if fixedlines <> [] and not quiet then 5308 fixedlines := Set(fixedlines); 5309 Info(InfoWarning,1,"MovedPoints: Sorry -- Lines are not yet ", 5310 "implemented;\nthere are the following fixed lines ", 5311 "(as pairs (v,w): l = v+k*w):\n",fixedlines); 5312 fi; 5313 return ResidueClassUnion(R,m,residues{indices},[],fixedpoints); 5314 end ); 5315 5316############################################################################# 5317## 5318#M MovedPoints( <f> ) . . . . . . . . for rcwa mappings of Z in sparse rep. 5319## 5320InstallMethod( MovedPoints, 5321 "for rcwa mappings of Z in sparse rep. (RCWA)", 5322 true, [ IsRcwaMappingOfZInSparseRep ], 0, 5323 5324 function ( f ) 5325 5326 local S, classes, fixedpoints, fixedpoint, c; 5327 5328 classes := []; fixedpoints := []; 5329 for c in f!.coeffs do 5330 if c{[3..5]} <> [1,0,1] then 5331 Add(classes,c{[1,2]}); 5332 if c{[3,5]} <> [1,1] then 5333 fixedpoint := c[4]/(c[5]-c[3]); 5334 if IsInt(fixedpoint) and fixedpoint mod c[2] = c[1] 5335 then Add(fixedpoints,fixedpoint); fi; 5336 fi; 5337 fi; 5338 od; 5339 S := ResidueClassUnion(Integers,classes,[],fixedpoints); 5340 return S; 5341 end ); 5342 5343############################################################################# 5344## 5345#M NrMovedPoints( <obj> ) . . . . . . . . . . . . . . . . . . default method 5346## 5347InstallOtherMethod( NrMovedPoints, "default method (RCWA)", true, 5348 [ IsObject ], 0, obj -> Size( MovedPoints( obj ) ) ); 5349 5350############################################################################# 5351## 5352#M Support( <g> ) . . . . . . . . . . . . . . . . . . . . for rcwa mappings 5353## 5354InstallMethod( Support, "for rcwa mappings (RCWA)", true, 5355 [ IsRcwaMapping ], 0, MovedPoints ); 5356 5357############################################################################# 5358## 5359#S Restricting an rcwa mapping to a residue class union. /////////////////// 5360## 5361############################################################################# 5362 5363############################################################################# 5364## 5365#M RestrictedMapping( <f>, <S> ) for an rcwa mapping and a res.- class union 5366## 5367InstallMethod( RestrictedMapping, 5368 "for an rcwa mapping and a residue class union (RCWA)", 5369 ReturnTrue, [ IsRcwaMapping, IsResidueClassUnion ], 0, 5370 5371 function ( f, S ) 5372 5373 local R, mf, mS, m, resf, resS, resm, cf, cfS, fS, r, pos, idcoeff; 5374 5375 if not IsRcwaMappingStandardRep(f) then f := StandardRep(f); fi; 5376 5377 R := Source(f); 5378 if UnderlyingRing(FamilyObj(S)) <> R 5379 or IncludedElements(S) <> [] or ExcludedElements(S) <> [] 5380 or not IsSubset(S,S^f) 5381 then TryNextMethod(); fi; 5382 mf := Modulus(f); mS := Modulus(S); m := Lcm(mf,mS); 5383 resf := AllResidues(R,mf); resS := Residues(S); resm := AllResidues(R,m); 5384 if IsRing(R) then idcoeff := [1,0,1]*One(R); 5385 elif IsZxZ(R) then idcoeff := [[[1,0],[0,1]],[0,0],1]; 5386 else TryNextMethod(); fi; 5387 cf := Coefficients(f); 5388 cfS := ListWithIdenticalEntries(Length(resm),idcoeff); 5389 for pos in [1..Length(resm)] do 5390 r := resm[pos]; 5391 if r mod mS in resS then 5392 cfS[pos] := cf[Position(resf,r mod mf)]; 5393 fi; 5394 od; 5395 fS := RcwaMapping(R,m,cfS); 5396 return fS; 5397 end ); 5398 5399############################################################################# 5400## 5401#M RestrictedMapping( <f>, <R> ) . . for an rcwa mapping and its full source 5402## 5403InstallMethod( RestrictedMapping, 5404 "for an rcwa mapping and its full source (RCWA)", 5405 ReturnTrue, [ IsRcwaMapping, IsDomain ], 0, 5406 5407 function ( f, R ) 5408 if R = Source(f) then return f; else TryNextMethod(); fi; 5409 end ); 5410 5411############################################################################# 5412## 5413#M RestrictedPerm( <g>, <S> ) . . . . . . for an rcwa permutation and a set 5414## 5415InstallMethod( RestrictedPerm, 5416 "for an rcwa permutation and a set (RCWA)", 5417 ReturnTrue, [ IsRcwaMapping, IsListOrCollection ], 0, 5418 RestrictedMapping ); 5419 5420############################################################################# 5421## 5422#S Computing images under rcwa mappings. /////////////////////////////////// 5423## 5424############################################################################# 5425 5426############################################################################# 5427## 5428#M ImageElm( <f>, <n> ) . . . . . . for an rcwa mapping of Z and an integer 5429## 5430## Returns the image of the integer <n> under the rcwa mapping <f>. 5431## 5432InstallMethod( ImageElm, 5433 "for rcwa mapping of Z in standard rep. and integer (RCWA)", 5434 true, [ IsRcwaMappingOfZInStandardRep, IsInt ], 0, 5435 5436 function ( f, n ) 5437 5438 local m, c; 5439 5440 m := f!.modulus; c := f!.coeffs[n mod m + 1]; 5441 return (c[1] * n + c[2]) / c[3]; 5442 end ); 5443 5444############################################################################# 5445## 5446#M ImageElm( <f>, <n> ) . . . . . . for an rcwa mapping of Z and an integer 5447## 5448InstallMethod( ImageElm, 5449 "for rcwa mapping of Z in sparse rep. and integer (RCWA)", 5450 true, [ IsRcwaMappingOfZInSparseRep, IsInt ], 0, 5451 5452 function ( f, n ) 5453 5454 local m, c; 5455 5456 m := f!.modulus; 5457 c := First(f!.coeffs,c->n mod c[2] = c[1]); 5458 return (c[3] * n + c[4]) / c[5]; 5459 end ); 5460 5461############################################################################# 5462## 5463#M ImageElm( <f>, <v> ) . . . . for an rcwa mapping of Z^2 and a row vector 5464## 5465## Returns the image of the vector <v> in Z^2 under the rcwa mapping <f>. 5466## 5467InstallMethod( ImageElm, 5468 "for an rcwa mapping of Z^2 and a row vector (RCWA)", true, 5469 [ IsRcwaMappingOfZxZInStandardRep, IsRowVector ], 10, 5470 5471 function ( f, v ) 5472 5473 local R, m, c; 5474 5475 R := Source(f); if not v in R then TryNextMethod(); fi; 5476 m := f!.modulus; 5477 c := f!.coeffs[PositionSorted(AllResidues(R,m),v mod m)]; 5478 return (v * c[1] + c[2]) / c[3]; 5479 end ); 5480 5481############################################################################# 5482## 5483#M ImageElm( <f>, <n> ) . for an rcwa mapping of Z_(pi) and an el. of Z_(pi) 5484## 5485## Returns the image of the element <n> of the ring Z_(pi) for suitable <pi> 5486## under the rcwa mapping <f>. 5487## 5488InstallMethod( ImageElm, 5489 "for rcwa mapping of Z_(pi) and element of Z_(pi) (RCWA)", 5490 true, [ IsRcwaMappingOfZ_piInStandardRep, IsRat ], 0, 5491 5492 function ( f, n ) 5493 5494 local m, c; 5495 5496 if not n in Source(f) then TryNextMethod(); fi; 5497 m := f!.modulus; c := f!.coeffs[n mod m + 1]; 5498 return (c[1] * n + c[2]) / c[3]; 5499 end ); 5500 5501############################################################################# 5502## 5503#M ImageElm( <f>, <p> ) for rcwa mapping of GF(q)[x] and element of GF(q)[x] 5504## 5505## Returns the image of the polynomial <p> under the rcwa mapping <f>. 5506## 5507InstallMethod( ImageElm, 5508 "for rcwa mapping of GF(q)[x] and element of GF(q)[x] (RCWA)", 5509 true, [ IsRcwaMappingOfGFqxInStandardRep, IsPolynomial ], 0, 5510 5511 function ( f, p ) 5512 5513 local R, m, c, r; 5514 5515 R := Source(f); if not p in R then TryNextMethod(); fi; 5516 m := f!.modulus; r := p mod m; 5517 c := f!.coeffs[PositionSorted(AllResidues(R,m),r)]; 5518 return (c[1] * p + c[2]) / c[3]; 5519 end ); 5520 5521############################################################################# 5522## 5523#M \^( <n>, <f> ) . . . . . . . . . . for a ring element and an rcwa mapping 5524## 5525## Returns the image of the ring element <n> under the rcwa mapping <f>. 5526## 5527InstallMethod( \^, "for a ring element and an rcwa mapping (RCWA)", 5528 ReturnTrue, [ IsRingElement, IsRcwaMapping ], 0, 5529 function ( n, f ) return ImageElm( f, n ); end ); 5530InstallMethod( \^, "for a row vector and an rcwa mapping of Z^2 (RCWA)", 5531 ReturnTrue, [ IsRowVector, IsRcwaMappingOfZxZ ], 0, 5532 function ( v, f ) return ImageElm( f, v ); end ); 5533InstallMethod( \^, "for list of row vectors and rcwa mapping of Z^2 (RCWA)", 5534 ReturnTrue, [ IsList, IsRcwaMappingOfZxZ ], 10, 5535 5536 function ( l, f ) 5537 if not IsSubset( Source( f ), l ) then TryNextMethod( ); fi; 5538 return List( l, v -> ImageElm( f, v ) ); 5539 end ); 5540 5541############################################################################# 5542## 5543#M ImagesElm( <f>, <n> ) . . . . . . for an rcwa mapping and a ring element 5544## 5545## Returns the images of the ring element <n> under the rcwa mapping <f>. 5546## For technical purposes, only. 5547## 5548InstallMethod( ImagesElm, "for an rcwa mapping and a ring element (RCWA)", 5549 true, [ IsRcwaMapping, IsRingElement ], 0, 5550 function ( f, n ) return [ ImageElm( f, n ) ]; end ); 5551InstallMethod( ImagesElm, "for rcwa mapping of Z^2 and row vector (RCWA)", 5552 true, [ IsRcwaMappingOfZxZ, IsRowVector ], 0, 5553 function ( f, n ) return [ ImageElm( f, n ) ]; end ); 5554 5555############################################################################# 5556## 5557#M ImagesSet( <f>, <S> ) . . . for an rcwa mapping and a residue class union 5558## 5559## Returns the image of the set <S> under the rcwa mapping <f>. 5560## 5561## The method rank offset SUM_FLAGS is to ensure that this method also gets 5562## called for rcwa zero mappings, instead of a Library method which returns 5563## the zero module. 5564## 5565InstallMethod( ImagesSet, 5566 "for an rcwa mapping and a residue class union (RCWA)", 5567 ReturnTrue, [ IsRcwaMappingInStandardRep, 5568 IsCollection ], SUM_FLAGS, 5569 5570 function ( f, S ) 5571 5572 local R, c, m, cls, i; 5573 5574 R := Source(f); if not IsSubset(R,S) then TryNextMethod(); fi; 5575 if IsList(S) then return Set(List(S,n->n^f)); fi; 5576 c := Coefficients(f); m := Modulus(f); 5577 cls := AllResidueClassesModulo(R,m); 5578 return Union(List([1..Length(cls)], 5579 i->(Intersection(S,cls[i])*c[i][1]+c[i][2])/c[i][3])); 5580 end ); 5581 5582############################################################################# 5583## 5584#M ImagesSet( <f>, <S> ) for an rcwa mapping of Z and a residue class union 5585## 5586## Returns the image of the set <S> under the rcwa mapping <f> of Z which is 5587## assumed to be in "sparse" representation. 5588## 5589## For the reason of the method rank offset SUM_FLAGS, see above. 5590## 5591InstallMethod( ImagesSet, 5592 "for an rcwa mapping of Z and a residue class union (RCWA)", 5593 ReturnTrue, [ IsRcwaMappingOfZInSparseRep, 5594 IsCollection ], SUM_FLAGS, 5595 5596 function ( f, S ) 5597 if not IsSubset(Integers,S) then TryNextMethod(); fi; 5598 if IsList(S) then return Set(List(S,n->n^f)); fi; 5599 return Union(List(f!.coeffs, 5600 c->(Intersection(S,ResidueClass(c[1],c[2]))*c[3]+c[4])/c[5])); 5601 end ); 5602 5603############################################################################# 5604## 5605#M ImagesSet( <f>, <cl> ) . . . for an rcwa mapping of Z and a residue class 5606## 5607## Returns the image of the residue class <cl> under the rcwa mapping <f>. 5608## It is required that <f> is injective and in standard representation, and 5609## that the modulus of <f> divides the modulus of <cl>. 5610## 5611## The rank offset SUM_FLAGS is needed to override the default method. 5612## 5613InstallMethod( ImagesSet, 5614 "for an rcwa mapping of Z and a residue class (RCWA)", 5615 ReturnTrue, [ IsRcwaMappingOfZInStandardRep and IsInjective, 5616 IsResidueClassUnionOfZ and IsResidueClass ], 5617 SUM_FLAGS, 5618 5619 function ( f, cl ) 5620 5621 local c; 5622 5623 if IsResidueClassUnionOfZInClassListRep(cl) then 5624 if cl!.m mod f!.modulus <> 0 then TryNextMethod(); fi; 5625 c := f!.coeffs[(cl!.cls[1][1]) mod f!.modulus + 1]; 5626 return ResidueClass(Integers,c[1]*cl!.m/c[3], 5627 (c[1]*cl!.cls[1][1]+c[2])/c[3]); 5628 elif IsResidueClassUnionInResidueListRep(cl) then 5629 if cl!.m mod f!.modulus <> 0 then TryNextMethod(); fi; 5630 c := f!.coeffs[(cl!.r[1]) mod f!.modulus + 1]; 5631 return ResidueClass(Integers,c[1]*cl!.m/c[3], 5632 (c[1]*cl!.r[1]+c[2])/c[3]); 5633 else TryNextMethod(); fi; 5634 end ); 5635 5636############################################################################# 5637## 5638#M ImagesSet( <f>, <cl> ) . . . for an rcwa mapping of Z and a residue class 5639## 5640## Returns the image of the residue class <cl> under the rcwa mapping <f> 5641## of Z. It is required that <f> is injective and in sparse representation, 5642## and that <cl> lies in the source of one affine partial mapping of <f>. 5643## 5644## The rank offset SUM_FLAGS is needed to override the default method. 5645## 5646InstallMethod( ImagesSet, 5647 "for an rcwa mapping of Z and a residue class (RCWA)", 5648 ReturnTrue, [ IsRcwaMappingOfZInSparseRep and IsInjective, 5649 IsResidueClassUnionOfZ and IsResidueClass ], 5650 SUM_FLAGS, 5651 5652 function ( f, cl ) 5653 5654 local c; 5655 5656 if IsResidueClassUnionOfZInClassListRep(cl) then 5657 c := First(f!.coeffs, 5658 c->cl!.cls[1][1] mod c[2] = c[1] and cl!.m mod c[2] = 0); 5659 if c = fail then TryNextMethod(); fi; 5660 return ResidueClass(Integers,c[3]*cl!.m/c[5], 5661 (c[3]*cl!.cls[1][1]+c[4])/c[5]); 5662 elif IsResidueClassUnionInResidueListRep(cl) then 5663 c := First(f!.coeffs, 5664 c->cl!.r[1] mod c[2] = c[1] and cl!.m mod c[2] = 0); 5665 if c = fail then TryNextMethod(); fi; 5666 return ResidueClass(Integers,c[3]*cl!.m/c[5], 5667 (c[3]*cl!.r[1]+c[4])/c[5]); 5668 else TryNextMethod(); fi; 5669 end ); 5670 5671############################################################################# 5672## 5673#M ImagesSource( <f> ) . . . . . . . . . . . . . . . . . for an rcwa mapping 5674## 5675## Returns the image of the rcwa mapping <f>. 5676## 5677InstallMethod( ImagesSource, 5678 "for an rcwa mapping and a residue class union (RCWA)", 5679 true, [ IsRcwaMapping ], 2 * SUM_FLAGS, 5680 f -> ImagesSet( f, Source( f ) ) ); 5681 5682############################################################################# 5683## 5684#M \^( <S>, <f> ) . . . . . for a set or class partition and an rcwa mapping 5685## 5686## Returns the image of the set or class partition <S> under the 5687## rcwa mapping <f>. 5688## 5689## The argument <S> can be: 5690## 5691## - A finite set of elements of the source of <f>. 5692## - A residue class union of the source of <f>. 5693## - A partition of the source of <f> into (unions of) residue classes. 5694## In this case the <i>th element of the result is the image of <S>[<i>]. 5695## 5696InstallMethod( \^, 5697 "for a set / class partition and an rcwa mapping (RCWA)", 5698 ReturnTrue, [ IsListOrCollection, IsRcwaMapping ], 20, 5699 5700 function ( S, f ) 5701 if S in Source(f) 5702 then return ImageElm(f,S); 5703 elif IsSubset(Source(f),S) 5704 then return ImagesSet(f,S); 5705 elif IsList(S) and ForAll(S,set->IsSubset(Source(f),set)) 5706 then return List(S,set->set^f); 5707 else TryNextMethod(); fi; 5708 end ); 5709 5710############################################################################# 5711## 5712#M \^( <U>, <f> ) . for union of res.-cl. with fixed rep's and rcwa mapping 5713## 5714## Returns the image of the union <U> of residue classes of Z with fixed 5715## representatives under the rcwa mapping <f>. 5716## 5717InstallMethod( \^, 5718 Concatenation("for a union of residue classes with fixed ", 5719 "rep's and an rcwa mapping (RCWA)"), ReturnTrue, 5720 [ IsUnionOfResidueClassesOfZWithFixedRepresentatives, 5721 IsRcwaMappingOfZ ], 0, 5722 5723 function ( U, f ) 5724 5725 local cls, abc, m, c, k, l; 5726 5727 if not IsRcwaMappingStandardRep(f) then f := StandardRep(f); fi; 5728 m := Modulus(f); c := Coefficients(f); 5729 k := List(Classes(U),cl->m/Gcd(m,cl[1])); l := Length(k); 5730 cls := AsListOfClasses(U); 5731 cls := List([1..l],i->RepresentativeStabilizingRefinement(cls[i],k[i])); 5732 cls := Flat(List(cls,cl->AsListOfClasses(cl))); 5733 abc := List(cls,cl->c[1 + Classes(cl)[1][2] mod m]); 5734 cls := List([1..Length(cls)],i->(abc[i][1]*cls[i]+abc[i][2])/abc[i][3]); 5735 return RepresentativeStabilizingRefinement(Union(cls),0); 5736 end ); 5737 5738############################################################################# 5739## 5740#S Computing preimages under rcwa mappings. //////////////////////////////// 5741## 5742############################################################################# 5743 5744############################################################################# 5745## 5746#M PreImageElm( <f>, <n> ) . for a bijective rcwa mapping and a ring element 5747## 5748## Returns the preimage of the ring element <n> under the bijective 5749## rcwa mapping <f>. 5750## 5751InstallMethod( PreImageElm, 5752 "for a bijective rcwa mapping and a ring element (RCWA)", 5753 true, [ IsRcwaMapping and IsBijective, IsRingElement ], 0, 5754 5755 function ( f, n ) 5756 return n^Inverse( f ); 5757 end ); 5758 5759############################################################################# 5760## 5761#M PreImagesElm( <f>, <n> ) . . . . . for an rcwa mapping and a ring element 5762## 5763## Returns the preimages of <n> under the rcwa mapping <f>. 5764## 5765InstallMethod( PreImagesElm, 5766 "for an rcwa mapping and a ring element (RCWA)", ReturnTrue, 5767 [ IsRcwaMappingInStandardRep, IsRingElement ], 0, 5768 5769 function ( f, n ) 5770 5771 local R, c, m, preimage, singletons, residues, n1, pre; 5772 5773 R := Source(f); if not n in R then TryNextMethod(); fi; 5774 c := f!.coeffs; m := f!.modulus; 5775 preimage := []; singletons := []; 5776 residues := AllResidues(R,m); 5777 for n1 in [1..Length(residues)] do 5778 if not IsZero(c[n1][1]) then 5779 pre := (c[n1][3] * n - c[n1][2])/c[n1][1]; 5780 if pre in R and pre mod m = residues[n1] 5781 then Add(singletons,pre); fi; 5782 else 5783 if c[n1][2] = n then 5784 if IsOne(m) then return R; 5785 else preimage := Union(preimage,ResidueClass(R,m,residues[n1])); fi; 5786 fi; 5787 fi; 5788 od; 5789 preimage := Union(preimage,singletons); 5790 return preimage; 5791 end ); 5792 5793############################################################################# 5794## 5795#M PreImagesElm( <f>, <n> ) . . . . for an rcwa mapping of Z and an integer 5796## 5797InstallMethod( PreImagesElm, 5798 "for an rcwa mapping of Z and an integer (RCWA)", 5799 ReturnTrue, [ IsRcwaMappingOfZInSparseRep, IsInt ], 0, 5800 5801 function ( f, n ) 5802 5803 local coeffs, preimage, singletons, c, pre; 5804 5805 coeffs := f!.coeffs; 5806 preimage := []; singletons := []; 5807 for c in coeffs do 5808 if c[3] <> 0 then 5809 pre := (c[5] * n - c[4])/c[3]; 5810 if IsInt(pre) and pre mod c[2] = c[1] 5811 then Add(singletons,pre); fi; 5812 else 5813 if c[4] = n then 5814 if c[2] = 1 then return Integers; 5815 else preimage := Union(preimage,ResidueClass(c[1],c[2])); fi; 5816 fi; 5817 fi; 5818 od; 5819 preimage := Union(preimage,singletons); 5820 return preimage; 5821 end ); 5822 5823############################################################################# 5824## 5825#M PreImagesRepresentative( <f>, <n> ) . . for rcwa mapping and ring element 5826## 5827## Returns a representative of the set of preimages of the integer <n> under 5828## the rcwa mapping <f>. 5829## 5830InstallMethod( PreImagesRepresentative, 5831 "for an rcwa mapping and a ring element (RCWA)", 5832 ReturnTrue, [ IsRcwaMappingInStandardRep, IsRingElement ], 0, 5833 5834 function ( f, n ) 5835 5836 local R, c, m, residues, n1, pre; 5837 5838 R := Source(f); if not n in R then return fail; fi; 5839 c := f!.coeffs; m := f!.modulus; 5840 residues := AllResidues(R,m); 5841 for n1 in [1..Length(residues)] do 5842 if not IsZero(c[n1][1]) then 5843 pre := (n * c[n1][3] - c[n1][2])/c[n1][1]; 5844 if pre in R and pre mod m = residues[n1] then return pre; fi; 5845 else 5846 if c[n1][2] = n then return residues[n1]; fi; 5847 fi; 5848 od; 5849 return fail; 5850 end ); 5851 5852############################################################################# 5853## 5854#M PreImagesRepresentative( <f>, <n> ) . . for rcwa mapping of Z and integer 5855## 5856InstallMethod( PreImagesRepresentative, 5857 "for an rcwa mapping of Z and an integer (RCWA)", 5858 ReturnTrue, [ IsRcwaMappingOfZInSparseRep, IsInt ], 0, 5859 5860 function ( f, n ) 5861 5862 local coeffs, c, pre; 5863 5864 coeffs := f!.coeffs; 5865 for c in coeffs do 5866 if c[3] <> 0 then 5867 pre := (n * c[5] - c[4])/c[3]; 5868 if IsInt(pre) and pre mod c[2] = c[1] then return pre; fi; 5869 else 5870 if c[4] = n then return c[1]; fi; 5871 fi; 5872 od; 5873 return fail; 5874 end ); 5875 5876############################################################################# 5877## 5878#M PreImagesSet( <f>, <R> ) . . for an rcwa mapping and its underlying ring 5879## 5880## Returns the source of the rcwa mapping <f>. 5881## For technical purposes, only. 5882## 5883InstallMethod( PreImagesSet, 5884 "for an rcwa mapping and its underlying ring (RCWA)", true, 5885 [ IsRcwaMapping, IsRing ], 0, 5886 5887 function ( f, R ) 5888 if R = UnderlyingRing( FamilyObj( f ) ) 5889 then return R; else TryNextMethod( ); fi; 5890 end ); 5891 5892############################################################################# 5893## 5894#M PreImagesSet( <f>, <l> ) . . . . . . for an rcwa mapping and a finite set 5895## 5896## Returns the preimage of the finite set <l> under the rcwa mapping <f>. 5897## 5898InstallMethod( PreImagesSet, 5899 "for an rcwa mapping and a finite set (RCWA)", 5900 true, [ IsRcwaMapping, IsList ], 0, 5901 5902 function ( f, l ) 5903 return Union( List( Set( l ), n -> PreImagesElm( f, n ) ) ); 5904 end ); 5905 5906############################################################################# 5907## 5908#M PreImagesSet( <f>, <S> ) . for an rcwa mapping and a residue class union 5909## 5910## Returns the preimage of the residue class union <S> under the 5911## rcwa mapping <f>. 5912## 5913InstallMethod( PreImagesSet, 5914 "for an rcwa mapping and a residue class union (RCWA)", 5915 ReturnTrue, [ IsRcwaMapping, IsResidueClassUnion ], 0, 5916 5917 function ( f, S ) 5918 5919 local R, preimage, parts, premod, preres, rump, 5920 pre, pre2, im, diff, excluded, n; 5921 5922 R := Source(f); if not IsSubset(R,S) then TryNextMethod(); fi; 5923 rump := ResidueClassUnion( R, Modulus(S), Residues(S) ); 5924 premod := Modulus(f) * Divisor(f) * Modulus(S); 5925 preres := Filtered( AllResidues( R, premod ), n -> n^f in rump ); 5926 parts := [ ResidueClassUnion( R, premod, preres ) ]; 5927 Append( parts, List( IncludedElements(S), n -> PreImagesElm( f, n ) ) ); 5928 preimage := Union( parts ); 5929 excluded := ExcludedElements(S); 5930 for n in excluded do 5931 pre := PreImagesElm( f, n ); 5932 im := ImagesSet( f, pre ); 5933 pre2 := PreImagesSet( f, Difference( im, excluded ) ); 5934 diff := Difference( pre, pre2 ); 5935 if not IsEmpty( diff ) 5936 then preimage := Difference( preimage, diff ); fi; 5937 od; 5938 return preimage; 5939 end ); 5940 5941############################################################################# 5942## 5943#M PreImagesSet( <f>, <S> ) . for rcwa mapping of Z and residue class union 5944## 5945InstallMethod( PreImagesSet, 5946 "for an rcwa mapping of Z and a residue class union (RCWA)", 5947 ReturnTrue, [ IsRcwaMappingOfZInSparseRep, 5948 IsResidueClassUnionOfZ ], 0, 5949 5950 function ( f, S ) 5951 5952 local coeffs, c, preimage, img, pre; 5953 5954 coeffs := f!.coeffs; 5955 preimage := []; 5956 5957 for c in coeffs do 5958 if c[3] <> 0 then 5959 img := ResidueClass(Integers,c[3]*c[2]/c[5],(c[3]*c[1]+c[4])/c[5]); 5960 img := Intersection(img,S); 5961 pre := (c[5]*img-c[4])/c[3]; 5962 else 5963 if c[4] in S then pre := ResidueClass(c[1],c[2]); else pre := []; fi; 5964 fi; 5965 preimage := Union(preimage,pre); 5966 od; 5967 5968 return preimage; 5969 end ); 5970 5971############################################################################# 5972## 5973#M PreImagesSet( <f>, <U> ) . . . . as above, but with fixed representatives 5974## 5975## Returns the preimage of the union <U> of residue classes of Z with fixed 5976## representatives under the rcwa mapping <f>. 5977## 5978InstallMethod( PreImagesSet, 5979 Concatenation("for an rcwa mapping of Z and a union of ", 5980 "residue classes with fixed rep's (RCWA)"), 5981 ReturnTrue, 5982 [ IsRcwaMappingOfZ, 5983 IsUnionOfResidueClassesOfZWithFixedRepresentatives ], 0, 5984 5985 function ( f, U ) 5986 5987 local preimage, cls, rep, m, minv, clm, k, l; 5988 5989 if not IsRcwaMappingStandardRep(f) then f := StandardRep(f); fi; 5990 5991 m := Modulus(f); minv := Multiplier(f) * m; 5992 k := List(Classes(U),cl->minv/Gcd(minv,cl[1])); l := Length(k); 5993 cls := AsListOfClasses(U); 5994 cls := List([1..l],i->RepresentativeStabilizingRefinement(cls[i],k[i])); 5995 cls := Flat(List(cls,cl->AsListOfClasses(cl))); 5996 rep := List(cls,cl->PreImagesElm(f,Classes(cl)[1][2])); 5997 cls := List(cls,cl->PreImagesSet(f,AsOrdinaryUnionOfResidueClasses(cl))); 5998 clm := AllResidueClassesModulo(Integers,m); 5999 cls := List(cls,cl1->List(clm,cl2->Intersection(cl1,cl2))); 6000 cls := List(cls,list->Filtered(list,cl->cl<>[])); 6001 cls := List([1..Length(cls)], 6002 i->List(cls[i],cl->[Modulus(cl), 6003 Intersection(rep[i],cl)[1]])); 6004 cls := Concatenation(cls); 6005 preimage := UnionOfResidueClassesWithFixedRepresentatives(Integers,cls); 6006 6007 return RepresentativeStabilizingRefinement(preimage,0); 6008 end ); 6009 6010############################################################################# 6011## 6012#S Testing an rcwa mapping for injectivity and surjectivity. /////////////// 6013## 6014############################################################################# 6015 6016############################################################################# 6017## 6018#M IsInjective( <f> ) . . . . . . . . . . . for rcwa mappings of Z or Z_(pi) 6019## 6020InstallMethod( IsInjective, 6021 "for rcwa mappings of Z or Z_(pi) (RCWA)", true, 6022 [ IsRcwaMappingOfZOrZ_piInStandardRep ], 0, 6023 6024 function ( f ) 6025 6026 local c, cInv, m, mInv, n, t, tm, tn, Classes, cl; 6027 6028 if IsZero(Multiplier(f)) then return false; fi; 6029 if Product(PrimeSet(f)) > 30 then 6030 if Length(Set(List([-100..100],n->n^f))) < 201 6031 then return false; fi; 6032 if Length(Set(List([-1000..1000],n->n^f))) < 2001 6033 then return false; fi; 6034 fi; 6035 c := f!.coeffs; m := f!.modulus; 6036 cInv := []; 6037 mInv := Multiplier( f ) * m / Gcd( m, Gcd( List( c, t -> t[3] ) ) ); 6038 for n in [ 1 .. m ] do 6039 t := [c[n][3], -c[n][2], c[n][1]]; if t[3] = 0 then return false; fi; 6040 tm := StandardAssociate(Source(f),c[n][1]) * m / Gcd(m,c[n][3]); 6041 tn := ((n - 1) * c[n][1] + c[n][2]) / c[n][3] mod tm; 6042 Classes := List([1 .. mInv/tm], i -> (i - 1) * tm + tn); 6043 for cl in Classes do 6044 if IsBound(cInv[cl + 1]) and cInv[cl + 1] <> t then return false; fi; 6045 cInv[cl + 1] := t; 6046 od; 6047 od; 6048 return true; 6049 end ); 6050 6051############################################################################# 6052## 6053#M IsInjective( <f> ) . . . . . . . . for rcwa mappings of Z in sparse rep. 6054## 6055InstallMethod( IsInjective, 6056 "for rcwa mappings of Z in sparse rep. (RCWA)", true, 6057 [ IsRcwaMappingOfZInSparseRep ], 0, 6058 6059 function ( f ) 6060 6061 local coeffs, imgs, c; 6062 6063 if Multiplier(f) = 0 then return false; fi; 6064 6065 coeffs := f!.coeffs; 6066 imgs := List(coeffs,c->[(c[3]*c[1]+c[4])/c[5],c[3]*c[2]/c[5]]); 6067 return ForAll(Combinations(imgs,2), 6068 c->(c[1][1]-c[2][1]) mod Gcd(c[1][2],c[2][2]) <> 0); 6069 end ); 6070 6071############################################################################# 6072## 6073#M IsInjective( <f> ) . . . . . . . . . . . . for rcwa mappings of GF(q)[x] 6074## 6075InstallMethod( IsInjective, 6076 "for rcwa mappings of GF(q)[x] (RCWA)", true, 6077 [ IsRcwaMappingOfGFqxInStandardRep ], 0, 6078 6079 function ( f ) 6080 6081 local c, cInv, m, mInv, d, dInv, R, q, x, respols, res, resInv, r, n, 6082 t, tm, tr, tn, Classes, cl, pos; 6083 6084 if IsZero(Multiplier(f)) then return false; fi; 6085 R := UnderlyingRing(FamilyObj(f)); 6086 q := Size(CoefficientsRing(R)); 6087 x := IndeterminatesOfPolynomialRing(R)[1]; 6088 c := f!.coeffs; m := f!.modulus; 6089 cInv := []; 6090 mInv := StandardAssociate( R, 6091 Multiplier( f ) * m / Gcd( m, Gcd( List( c, t -> t[3] ) ) ) ); 6092 if mInv = 0 then return false; fi; 6093 d := DegreeOfLaurentPolynomial(m); 6094 dInv := DegreeOfLaurentPolynomial(mInv); 6095 res := AllGFqPolynomialsModDegree(q,d,x); 6096 respols := List([0..dInv], d -> AllGFqPolynomialsModDegree(q,d,x)); 6097 resInv := respols[dInv + 1]; 6098 for n in [ 1 .. Length(res) ] do 6099 r := res[n]; 6100 t := [c[n][3], -c[n][2], c[n][1]]; 6101 if IsZero(t[3]) then return false; fi; 6102 tm := StandardAssociate(Source(f),c[n][1]) * m / Gcd(m,c[n][3]); 6103 tr := (r * c[n][1] + c[n][2]) / c[n][3] mod tm; 6104 Classes := List(respols[DegreeOfLaurentPolynomial(mInv/tm) + 1], 6105 p -> p * tm + tr); 6106 for cl in Classes do 6107 pos := Position(resInv,cl); 6108 if IsBound(cInv[pos]) and cInv[pos] <> t then return false; fi; 6109 cInv[pos] := t; 6110 od; 6111 od; 6112 return true; 6113 end ); 6114 6115############################################################################# 6116## 6117#M IsInjective( <f> ) . . . . . . . . . . . . . . . for rcwa mappings of Z^2 6118## 6119InstallMethod( IsInjective, 6120 "for rcwa mappings of Z^2 (RCWA)", true, 6121 [ IsRcwaMappingOfZxZ ], 0, 6122 6123 function ( f ) 6124 6125 local R, c, m, det, imgs; 6126 6127 R := Source(f); c := Coefficients(f); m := Modulus(f); 6128 6129 if DeterminantMat(Multiplier(f)) = 0 or ImageDensity(f) > 1 6130 then return false; fi; 6131 6132 det := DeterminantMat(m); 6133 if Length(Cartesian([0..RootInt(det,2)-1],[0..RootInt(det,2)-1])^f) 6134 < RootInt(det,2)^2 6135 then return false; fi; 6136 6137 if ImageDensity(f) = 1 and IsSurjective(f) then return true; fi; 6138 6139 imgs := LargestSourcesOfAffineMappings(f)^f; 6140 return ForAll( Combinations(imgs,2), pair -> Intersection(pair) = [] ); 6141 6142 return true; 6143 end ); 6144 6145############################################################################# 6146## 6147#M IsSurjective( <f> ) . . . . . . . . . . for rcwa mappings of Z or Z_(pi) 6148## 6149InstallMethod( IsSurjective, 6150 "for rcwa mappings of Z or Z_(pi) (RCWA)", true, 6151 [ IsRcwaMappingOfZOrZ_piInStandardRep ], 0, 6152 6153 function ( f ) 6154 6155 local c, cInv, m, mInv, n, t, tm, tn, Classes, cl; 6156 6157 c := f!.coeffs; m := f!.modulus; 6158 cInv := []; 6159 if ForAll(c, t -> t[1] = 0) then return false; fi; 6160 mInv := AbsInt(Lcm(Filtered(List(c,t->StandardAssociate(Source(f),t[1])), 6161 k -> k <> 0 ))) 6162 * m / Gcd(m,Gcd(List(c,t->t[3]))); 6163 for n in [1 .. m] do 6164 t := [c[n][3], -c[n][2], c[n][1]]; 6165 if t[3] <> 0 then 6166 tm := StandardAssociate(Source(f),c[n][1]) * m / Gcd(m,c[n][3]); 6167 tn := ((n - 1) * c[n][1] + c[n][2]) / c[n][3] mod tm; 6168 Classes := List([1 .. mInv/tm], i -> (i - 1) * tm + tn); 6169 for cl in Classes do cInv[cl + 1] := t; od; 6170 fi; 6171 od; 6172 return ForAll([1..mInv], i -> IsBound(cInv[i])); 6173 end ); 6174 6175############################################################################# 6176## 6177#M IsSurjective( <f> ) . . . . . . . . for rcwa mappings of Z in sparse rep. 6178## 6179InstallMethod( IsSurjective, 6180 "for rcwa mappings of Z in sparse rep. (RCWA)", true, 6181 [ IsRcwaMappingOfZInSparseRep ], 0, 6182 6183 function ( f ) 6184 6185 local coeffs, imgs; 6186 6187 coeffs := f!.coeffs; 6188 if IsInjective(f) then 6189 return Sum(List(coeffs,c->c[5]/(c[2]*AbsInt(c[3])))) = 1; 6190 else 6191 imgs := List(Filtered(coeffs,c->c[3]<>0), 6192 c->ResidueClass((c[3]*c[1]+c[4])/c[5],(c[3]*c[2])/c[5])); 6193 return IsIntegers(Union(imgs)); 6194 fi; 6195 end ); 6196 6197############################################################################# 6198## 6199#M IsSurjective( <f> ) . . . . . . . . . . . . for rcwa mappings of GF(q)[x] 6200## 6201InstallMethod( IsSurjective, 6202 "for rcwa mappings of GF(q)[x] (RCWA)", true, 6203 [ IsRcwaMappingOfGFqxInStandardRep ], 0, 6204 6205 function ( f ) 6206 6207 local c, cInv, m, mInv, d, dInv, R, q, x, 6208 respols, res, resInv, r, n, t, tm, tr, tn, Classes, cl, pos; 6209 6210 R := UnderlyingRing(FamilyObj(f)); 6211 q := Size(CoefficientsRing(R)); 6212 x := IndeterminatesOfPolynomialRing(R)[1]; 6213 c := f!.coeffs; m := f!.modulus; 6214 cInv := []; 6215 if ForAll( c, t -> IsZero(t[1]) ) then return false; fi; 6216 mInv := Lcm(Filtered(List(c, t -> StandardAssociate(Source(f),t[1])), 6217 k -> not IsZero(k) )) 6218 * m / Gcd(m,Gcd(List(c,t->t[3]))); 6219 d := DegreeOfLaurentPolynomial(m); 6220 dInv := DegreeOfLaurentPolynomial(mInv); 6221 res := AllGFqPolynomialsModDegree(q,d,x); 6222 respols := List([0..dInv], d -> AllGFqPolynomialsModDegree(q,d,x)); 6223 resInv := respols[dInv + 1]; 6224 for n in [ 1 .. Length(res) ] do 6225 r := res[n]; 6226 t := [c[n][3], -c[n][2], c[n][1]]; 6227 if not IsZero(t[3]) then 6228 tm := StandardAssociate(Source(f),c[n][1]) * m / Gcd(m,c[n][3]); 6229 tr := (r * c[n][1] + c[n][2]) / c[n][3] mod tm; 6230 Classes := List(respols[DegreeOfLaurentPolynomial(mInv/tm) + 1], 6231 p -> p * tm + tr); 6232 for cl in Classes do cInv[Position(resInv,cl)] := t; od; 6233 fi; 6234 od; 6235 return ForAll([1..Length(resInv)], i -> IsBound(cInv[i])); 6236 end ); 6237 6238############################################################################ 6239## 6240#F InjectiveAsMappingFrom( <f> ) . . . . some set on which <f> is injective 6241## 6242InstallGlobalFunction( InjectiveAsMappingFrom, 6243 6244 function ( f ) 6245 6246 local R, m, base, pre, im, cl, imcl, overlap; 6247 6248 if not IsRcwaMappingStandardRep(f) then f := StandardRep(f); fi; 6249 R := Source(f); if IsBijective(f) then return R; fi; 6250 m := Modulus(f); base := AllResidueClassesModulo(R,m); 6251 pre := R; im := []; 6252 for cl in base do 6253 imcl := cl^f; 6254 overlap := Intersection(im,imcl); 6255 im := Union(im,imcl); 6256 pre := Difference(pre,Intersection(PreImagesSet(f,overlap),cl)); 6257 od; 6258 return pre; 6259 end ); 6260 6261############################################################################# 6262## 6263#M IsUnit( <f> ) . . . . . . . . . . . . . . . . . . . . . for rcwa mappings 6264## 6265InstallOtherMethod( IsUnit, 6266 "for rcwa mappings (RCWA)", 6267 true, [ IsRcwaMapping ], 0, IsBijective ); 6268 6269############################################################################# 6270## 6271#S Computing pointwise sums of rcwa mappings. ////////////////////////////// 6272## 6273############################################################################# 6274 6275############################################################################# 6276## 6277#M \+( <f>, <g> ) . . . . . . . . . . . for two rcwa mappings of Z or Z_(pi) 6278## 6279## Returns the pointwise sum of the rcwa mappings <f> and <g>. 6280## 6281InstallMethod( \+, 6282 "for two rcwa mappings of Z or Z_(pi) (RCWA)", 6283 IsIdenticalObj, 6284 [ IsRcwaMappingOfZOrZ_piInStandardRep, 6285 IsRcwaMappingOfZOrZ_piInStandardRep ], 0, 6286 6287 function ( f, g ) 6288 6289 local c1, c2, c3, m1, m2, m3, n, n1, n2, pi; 6290 6291 c1 := f!.coeffs; c2 := g!.coeffs; 6292 m1 := f!.modulus; m2 := g!.modulus; 6293 m3 := Lcm(m1, m2); 6294 6295 c3 := []; 6296 for n in [0 .. m3 - 1] do 6297 n1 := n mod m1 + 1; 6298 n2 := n mod m2 + 1; 6299 Add(c3, [ c1[n1][1] * c2[n2][3] + c1[n1][3] * c2[n2][1], 6300 c1[n1][2] * c2[n2][3] + c1[n1][3] * c2[n2][2], 6301 c1[n1][3] * c2[n2][3] ]); 6302 od; 6303 6304 if IsRcwaMappingOfZ( f ) 6305 then return RcwaMappingNC( c3 ); 6306 else pi := NoninvertiblePrimes( Source( f ) ); 6307 return RcwaMappingNC( pi, c3 ); 6308 fi; 6309 end ); 6310 6311############################################################################# 6312## 6313#M \+( <f>, <g> ) . . . . . . . . for two rcwa mappings of Z in sparse rep. 6314## 6315## Returns the pointwise sum of the rcwa mappings <f> and <g>. 6316## 6317InstallMethod( \+, 6318 "for two rcwa mappings of Z in sparse rep. (RCWA)", 6319 IsIdenticalObj, 6320 [ IsRcwaMappingOfZInSparseRep, 6321 IsRcwaMappingOfZInSparseRep ], 0, 6322 6323 function ( f, g ) 6324 6325 local coeffs1, coeffs2, coeffs3, c1, c2, c3, r; 6326 6327 coeffs1 := f!.coeffs; coeffs2 := g!.coeffs; coeffs3 := []; 6328 for c1 in coeffs1 do 6329 for c2 in coeffs2 do 6330 if (c1[1] - c2[1]) mod Gcd(c1[2],c2[2]) = 0 then 6331 r := ChineseRem([c1[2],c2[2]],[c1[1],c2[1]]); 6332 c3 := [ r, Lcm(c1[2],c2[2]), 6333 c1[3]*c2[5] + c1[5]*c2[3], 6334 c1[4]*c2[5] + c1[5]*c2[4], 6335 c1[5]*c2[5] ]; 6336 Add(coeffs3,c3); 6337 fi; 6338 od; 6339 od; 6340 6341 return RcwaMappingNC( coeffs3 ); 6342 end ); 6343 6344############################################################################# 6345## 6346#M \+( <f>, <g> ) . . . for rcwa mappings of Z: sparse rep. + standard rep. 6347#M \+( <f>, <g> ) . . . for rcwa mappings of Z: standard rep. + sparse rep. 6348## 6349## Returns the pointwise sum of the rcwa mappings <f> and <g>. 6350## 6351InstallMethod( \+, 6352 "for rcwa mappings of Z: sparse rep. + standard rep. (RCWA)", 6353 IsIdenticalObj, [ IsRcwaMappingOfZInSparseRep, 6354 IsRcwaMappingOfZInStandardRep ], 0, 6355 function ( f, g ) return StandardRepresentation(f) + g; end ); 6356 6357InstallMethod( \+, 6358 "for rcwa mappings of Z: standard rep. + sparse rep. (RCWA)", 6359 IsIdenticalObj, [ IsRcwaMappingOfZInStandardRep, 6360 IsRcwaMappingOfZInSparseRep ], 0, 6361 function ( f, g ) return f + StandardRepresentation(g); end ); 6362 6363############################################################################# 6364## 6365#M \+( <f>, <g> ) . . . . . . . . . . . . for two rcwa mappings of GF(q)[x] 6366## 6367## Returns the pointwise sum of the rcwa mappings <f> and <g>. 6368## 6369InstallMethod( \+, 6370 "for two rcwa mappings of GF(q)[x] (RCWA)", 6371 IsIdenticalObj, 6372 [ IsRcwaMappingOfGFqxInStandardRep, 6373 IsRcwaMappingOfGFqxInStandardRep ], 0, 6374 6375 function ( f, g ) 6376 6377 local c, m, d, R, q, x, res, r, n1, n2; 6378 6379 c := [f!.coeffs, g!.coeffs, []]; 6380 m := [f!.modulus, g!.modulus, Lcm(f!.modulus,g!.modulus)]; 6381 d := List(m, DegreeOfLaurentPolynomial); 6382 R := UnderlyingRing(FamilyObj(f)); 6383 q := Size(CoefficientsRing(R)); 6384 x := IndeterminatesOfPolynomialRing(R)[1]; 6385 res := List(d, deg -> AllGFqPolynomialsModDegree(q,deg,x)); 6386 6387 for r in res[3] do 6388 n1 := Position(res[1], r mod m[1]); 6389 n2 := Position(res[2], r mod m[2]); 6390 Add(c[3], [ c[1][n1][1] * c[2][n2][3] + c[1][n1][3] * c[2][n2][1], 6391 c[1][n1][2] * c[2][n2][3] + c[1][n1][3] * c[2][n2][2], 6392 c[1][n1][3] * c[2][n2][3] ]); 6393 od; 6394 6395 return RcwaMappingNC( q, m[3], c[3] ); 6396 end ); 6397 6398############################################################################# 6399## 6400#M AdditiveInverseOp( <f> ) . . . . . . . . . . . . . . . for rcwa mappings 6401#M AdditiveInverseOp( <f> ) . . . . . for rcwa mappings of Z in sparse rep. 6402## 6403## Returns the pointwise additive inverse of rcwa mapping <f>. 6404## 6405InstallMethod( AdditiveInverseOp, 6406 "for rcwa mappings (RCWA)", true, [ IsRcwaMapping ], 0, 6407 f -> f * RcwaMappingNC( Source(f), One(Source(f)), 6408 [[-1,0,1]] * One(Source(f)) ) ); 6409 6410InstallMethod( AdditiveInverseOp, 6411 "for rcwa mappings of Z in sparse rep. (RCWA)", true, 6412 [ IsRcwaMappingOfZInSparseRep ], 0, 6413 f -> RcwaMappingNC(List(f!.coeffs, 6414 c->[c[1],c[2],-c[3],-c[4],c[5]])) ); 6415 6416############################################################################# 6417## 6418#M \+( <f>, <n> ) . . . . . . . . . . for an rcwa mapping and a ring element 6419#M \+( <f>, <n> ) . . for an rcwa mapping of Z in sparse rep. and an integer 6420#M \+( <n>, <f> ) . . . . . . . . . . for a ring element and an rcwa mapping 6421## 6422## Returns the pointwise sum of the rcwa mapping <f> and the constant 6423## rcwa mapping with value <n>. 6424## 6425InstallMethod( \+, 6426 "for an rcwa mapping and a ring element (RCWA)", 6427 ReturnTrue, [ IsRcwaMapping, IsRingElement ], 0, 6428 6429 function ( f, n ) 6430 6431 local R; 6432 6433 R := Source(f); 6434 if not n in R then TryNextMethod(); fi; 6435 return f + RcwaMapping(R,One(R),[[0,n,1]]*One(R)); 6436 end ); 6437 6438InstallMethod( \+, 6439 "for rcwa mapping of Z in sparse rep. and integer (RCWA)", 6440 ReturnTrue, [ IsRcwaMappingOfZInSparseRep, IsInt ], 0, 6441 6442 function ( f, n ) 6443 return RcwaMappingNC(List(f!.coeffs, 6444 c->[c[1],c[2],c[3],c[4]+n*c[5],c[5]])); 6445 end ); 6446 6447InstallMethod( \+, "for a ring element and an rcwa mapping (RCWA)", 6448 ReturnTrue, [ IsRingElement, IsRcwaMapping ], 0, 6449 function ( n, f ) return f + n; end ); 6450 6451############################################################################# 6452## 6453#M \+( <f>, <v> ) . . . . . for rcwa mappings of Z^2, addition of a constant 6454## 6455InstallMethod( \+, "for an rcwa mappings of Z^2 and a row vector (RCWA)", 6456 ReturnTrue, [ IsRcwaMappingOfZxZ, IsRowVector ], 0, 6457 6458 function ( f, v ) 6459 6460 local coeffs, sum; 6461 6462 if not v in Source(f) then TryNextMethod(); fi; 6463 6464 coeffs := List(Coefficients(f),c->[c[1],c[2]+c[3]*v,c[3]]); 6465 sum := RcwaMapping(Source(f),Modulus(f),coeffs); 6466 6467 if HasIsInjective(f) and IsInjective(f) 6468 then SetIsInjective(sum,true); fi; 6469 if HasIsSurjective(f) and IsSurjective(f) 6470 then SetIsSurjective(sum,true); fi; 6471 6472 return sum; 6473 end ); 6474 6475InstallMethod( \+, "for a row vector and an rcwa mapping (RCWA)", 6476 ReturnTrue, [ IsRowVector, IsRcwaMappingOfZxZ ], 0, 6477 function ( v, f ) return f + v; end ); 6478 6479############################################################################# 6480## 6481#S Multiplying rcwa mappings. ////////////////////////////////////////////// 6482## 6483############################################################################# 6484 6485############################################################################# 6486## 6487#M CompositionMapping2( <g>, <f> ) . . for two rcwa mappings of Z or Z_(pi) 6488## 6489## Returns the product (composition) of the rcwa mappings <f> and <g>. 6490## The mapping <f> is applied first. 6491## 6492InstallMethod( CompositionMapping2, 6493 "for two rcwa mappings of Z or Z_(pi) (RCWA)", 6494 IsIdenticalObj, 6495 [ IsRcwaMappingOfZOrZ_piInStandardRep, 6496 IsRcwaMappingOfZOrZ_piInStandardRep ], SUM_FLAGS, 6497 6498 function ( g, f ) 6499 6500 local fg, c1, c2, c3, m1, m2, m3, n, n1, n2, pi; 6501 6502 if ValueOption( "sparse" ) = true and Multiplier( f ) <> 0 6503 then TryNextMethod(); fi; 6504 6505 c1 := f!.coeffs; c2 := g!.coeffs; 6506 m1 := f!.modulus; m2 := g!.modulus; 6507 m3 := Gcd( Lcm( m1, m2 ) * Divisor( f ), m1 * m2 ); 6508 6509 if ValueOption("RMPROD_NO_EXPANSION") = true 6510 then m3 := Maximum(m1,m2); fi; 6511 6512 c3 := []; 6513 for n in [0 .. m3 - 1] do 6514 n1 := n mod m1 + 1; 6515 n2 := (c1[n1][1] * n + c1[n1][2])/c1[n1][3] mod m2 + 1; 6516 Add(c3, [ c1[n1][1] * c2[n2][1], 6517 c1[n1][2] * c2[n2][1] + c1[n1][3] * c2[n2][2], 6518 c1[n1][3] * c2[n2][3] ]); 6519 od; 6520 6521 if IsRcwaMappingOfZ(f) 6522 then fg := RcwaMappingNC(c3); 6523 else pi := NoninvertiblePrimes(Source(f)); 6524 fg := RcwaMappingNC(pi,c3); 6525 fi; 6526 6527 if HasIsInjective(f) and IsInjective(f) 6528 and HasIsInjective(g) and IsInjective(g) 6529 then SetIsInjective(fg,true); fi; 6530 6531 if HasIsSurjective(f) and IsSurjective(f) 6532 and HasIsSurjective(g) and IsSurjective(g) 6533 then SetIsSurjective(fg,true); fi; 6534 6535 return fg; 6536 end ); 6537 6538############################################################################# 6539## 6540#M CompositionMapping2( <g>, <f> ) . for two rcwa mappings of Z, sparse rep. 6541## 6542## Returns the product (composition) of the rcwa mappings <f> and <g>. 6543## The mapping <f> is applied first. 6544## 6545InstallMethod( CompositionMapping2, 6546 "for two rcwa mappings of Z, sparse rep. (RCWA)", 6547 IsIdenticalObj, 6548 [ IsRcwaMappingOfZInSparseRep, 6549 IsRcwaMappingOfZInSparseRep ], SUM_FLAGS, 6550 6551 function ( g, f ) 6552 6553 local fg, coeffs, c1, c2, c, img, int, pre; 6554 6555 coeffs := []; 6556 for c1 in f!.coeffs do 6557 img := [ (c1[3]*c1[1] + c1[4])/c1[5], c1[3]*c1[2]/c1[5] ]; 6558 for c2 in g!.coeffs do 6559 if img[2] <> 0 then 6560 if ( c2[1] - img[1] ) mod Gcd( c2[2], img[2] ) = 0 then 6561 int := [ ChineseRem( [ c2[2], img[2] ], [ c2[1], img[1] ] ), 6562 Lcm( c2[2], img[2] ) ]; 6563 pre := [ (int[1]*c1[5] - c1[4])/c1[3], int[2]*c1[5]/c1[3] ]; 6564 c := [ pre[1], pre[2], c1[3]*c2[3], 6565 c1[4]*c2[3] + c1[5]*c2[4], 6566 c1[5]*c2[5] ]; 6567 Add(coeffs,c); 6568 fi; 6569 elif img[1] mod c2[2] = c2[1] then 6570 pre := [ c1[1], c1[2] ]; 6571 c := [ pre[1], pre[2], c1[3]*c2[3], 6572 c1[4]*c2[3] + c1[5]*c2[4], 6573 c1[5]*c2[5] ]; 6574 Add(coeffs,c); 6575 fi; 6576 od; 6577 od; 6578 6579 fg := RcwaMappingNC(coeffs); 6580 6581 if HasIsInjective(f) and IsInjective(f) 6582 and HasIsInjective(g) and IsInjective(g) 6583 then SetIsInjective(fg,true); fi; 6584 6585 if HasIsSurjective(f) and IsSurjective(f) 6586 and HasIsSurjective(g) and IsSurjective(g) 6587 then SetIsSurjective(fg,true); fi; 6588 6589 return fg; 6590 end ); 6591 6592############################################################################# 6593## 6594#M CompositionMapping2( <g>, <f> ) . . . . . . . sparse rep. * standard rep. 6595#M CompositionMapping2( <g>, <f> ) . . . . . . . standard rep. * sparse rep. 6596## 6597## Returns the product (composition) of the rcwa mappings <f> and <g>. 6598## The mapping <f> is applied first. 6599## 6600InstallMethod( CompositionMapping2, 6601 "for rcwa mappings of Z, sparse rep. * standard rep. (RCWA)", 6602 IsIdenticalObj, 6603 [ IsRcwaMappingOfZInStandardRep, 6604 IsRcwaMappingOfZInSparseRep ], SUM_FLAGS, 6605 function ( g, f ) 6606 return CompositionMapping2(g,StandardRepresentation(f)); 6607 end ); 6608 6609InstallMethod( CompositionMapping2, 6610 "for rcwa mappings of Z, standard rep. * sparse rep. (RCWA)", 6611 IsIdenticalObj, 6612 [ IsRcwaMappingOfZInSparseRep, 6613 IsRcwaMappingOfZInStandardRep ], SUM_FLAGS, 6614 function ( g, f ) 6615 return CompositionMapping2(StandardRepresentation(g),f); 6616 end ); 6617 6618############################################################################# 6619## 6620#M CompositionMapping2( <g>, <f> ) . . . . . . for two rcwa mappings of Z^2 6621## 6622## Returns the product (composition) of the rcwa mappings <f> and <g>. 6623## The mapping <f> is applied first. 6624## 6625InstallMethod( CompositionMapping2, 6626 "for two rcwa mappings of Z^2 (RCWA)", 6627 IsIdenticalObj, 6628 [ IsRcwaMappingOfZxZInStandardRep, 6629 IsRcwaMappingOfZxZInStandardRep ], SUM_FLAGS, 6630 6631 function ( g, f ) 6632 6633 local R, fg, c1, c2, c, m1, m2, m, 6634 res1, res2, res, r1, r2, r, i1, i2, i; 6635 6636 if ValueOption( "sparse" ) = true and not IsZero( Multiplier( f ) ) 6637 then TryNextMethod(); fi; 6638 6639 R := Source(f); 6640 6641 c1 := Coefficients(f); c2 := Coefficients(g); 6642 m1 := Modulus(f); m2 := Modulus(g); 6643 6644 m := List(c1,t->m2*t[1]^-1); 6645 for i in [1..Length(m)] do 6646 m[i] := m[i] * Lcm(List(Flat(m[i]),DenominatorRat)); 6647 od; 6648 m := Lcm(m1,Lcm(m)) * Divisor(f); 6649 6650 res1 := AllResidues(R,m1); 6651 res2 := AllResidues(R,m2); 6652 res := AllResidues(R,m); 6653 6654 c := []; 6655 for r in res do 6656 r1 := r mod m1; 6657 i1 := Position(res1,r1); 6658 r2 := (r * c1[i1][1] + c1[i1][2])/c1[i1][3] mod m2; 6659 i2 := Position(res2,r2); 6660 Add(c, [ c1[i1][1] * c2[i2][1], 6661 c1[i1][2] * c2[i2][1] + c1[i1][3] * c2[i2][2], 6662 c1[i1][3] * c2[i2][3] ]); 6663 od; 6664 6665 fg := RcwaMapping(R,m,c); # ... NC, once tested 6666 6667 if HasIsInjective(f) and IsInjective(f) 6668 and HasIsInjective(g) and IsInjective(g) 6669 then SetIsInjective(fg,true); fi; 6670 6671 if HasIsSurjective(f) and IsSurjective(f) 6672 and HasIsSurjective(g) and IsSurjective(g) 6673 then SetIsSurjective(fg,true); fi; 6674 6675 return fg; 6676 end ); 6677 6678############################################################################# 6679## 6680#M CompositionMapping2( <g>, <f> ) . . . . for two rcwa mappings of GF(q)[x] 6681## 6682## Returns the product (composition) of the rcwa mappings <f> and <g>. 6683## The mapping <f> is applied first. 6684## 6685InstallMethod( CompositionMapping2, 6686 "for two rcwa mappings of GF(q)[x] (RCWA)", 6687 IsIdenticalObj, 6688 [ IsRcwaMappingOfGFqxInStandardRep, 6689 IsRcwaMappingOfGFqxInStandardRep ], SUM_FLAGS, 6690 6691 function ( g, f ) 6692 6693 local fg, c, m, d, R, q, x, res, r, n1, n2; 6694 6695 if ValueOption( "sparse" ) = true and not IsZero( Multiplier( f ) ) 6696 then TryNextMethod(); fi; 6697 6698 c := [f!.coeffs, g!.coeffs, []]; 6699 m := [f!.modulus, g!.modulus]; 6700 m[3] := Minimum( Lcm( m[1], m[2] ) * Divisor( f ), m[1] * m[2] ); 6701 d := List(m, DegreeOfLaurentPolynomial); 6702 R := UnderlyingRing(FamilyObj(f)); 6703 q := Size(CoefficientsRing(R)); 6704 x := IndeterminatesOfPolynomialRing(R)[1]; 6705 res := List(d, deg -> AllGFqPolynomialsModDegree(q,deg,x)); 6706 6707 for r in res[3] do 6708 n1 := Position(res[1], r mod m[1]); 6709 n2 := Position(res[2], 6710 (c[1][n1][1] * r + c[1][n1][2])/c[1][n1][3] mod m[2]); 6711 Add(c[3], [ c[1][n1][1] * c[2][n2][1], 6712 c[1][n1][2] * c[2][n2][1] + c[1][n1][3] * c[2][n2][2], 6713 c[1][n1][3] * c[2][n2][3] ]); 6714 od; 6715 6716 fg := RcwaMappingNC( q, m[3], c[3] ); 6717 6718 if HasIsInjective(f) and IsInjective(f) 6719 and HasIsInjective(g) and IsInjective(g) 6720 then SetIsInjective(fg,true); fi; 6721 6722 if HasIsSurjective(f) and IsSurjective(f) 6723 and HasIsSurjective(g) and IsSurjective(g) 6724 then SetIsSurjective(fg,true); fi; 6725 6726 return fg; 6727 end ); 6728 6729############################################################################# 6730## 6731#M CompositionMapping2( <g>, <f> ) . . . . . for two rcwa mappings of a ring 6732## 6733## Returns the product (composition) of the rcwa mappings <f> and <g>. 6734## The mapping <f> is applied first. The multiplier of <f> must not be zero. 6735## 6736## This method performs better than the standard methods above if <f> and 6737## <g> have only few different affine partial mappings. It is used in place 6738## of the standard methods if the option "sparse" is set. 6739## 6740## This method presently does not work for Z^2, thus for this case there is 6741## a separate "sparse" method (see below). 6742## 6743InstallMethod( CompositionMapping2, 6744 "for two rcwa mappings of a ring (sparse case method) (RCWA)", 6745 IsIdenticalObj, [ IsRcwaMappingInStandardRep, 6746 IsRcwaMappingInStandardRep ], 0, 6747 6748 function ( g, f ) 6749 6750 local fg, R, mf, mg, m, resf, resg, res, cf, cg, c, 6751 affs_f, affs_g, affs, Pf, Pg, Pf_img, P, cl, cl1, cl2, 6752 aff, pre, img, rj, mj, rjpre, mjpre, rjimg, mjimg, pos, i, j, k; 6753 6754 if IsZero(Multiplier(f)) then TryNextMethod(); fi; 6755 6756 R := Source(f); 6757 if not IsRing(R) then TryNextMethod(); fi; 6758 6759 mf := Modulus(f); mg := Modulus(g); 6760 resf := AllResidues(R,mf); resg := AllResidues(R,mg); 6761 cf := Coefficients(f); cg := Coefficients(g); 6762 6763 Pf := LargestSourcesOfAffineMappings(f); 6764 Pg := LargestSourcesOfAffineMappings(g); 6765 6766 affs_f := List(Pf,S->cf[First([1..Length(resf)],i->resf[i] in S)]); 6767 affs_g := List(Pg,S->cg[First([1..Length(resg)],i->resg[i] in S)]); 6768 6769 Pf := List(Pf,AsUnionOfFewClasses); Pg := List(Pg,AsUnionOfFewClasses); 6770 6771 Pf_img := []; 6772 for i in [1..Length(Pf)] do 6773 Pf_img[i] := []; 6774 for cl in Pf[i] do 6775 rj := Residue(cl); mj := Modulus(cl); 6776 rjimg := (rj*affs_f[i][1]+affs_f[i][2])/affs_f[i][3]; 6777 mjimg := affs_f[i][1]*mj/affs_f[i][3]; 6778 img := ResidueClass(R,mjimg,rjimg); 6779 Add(Pf_img[i],img); 6780 od; 6781 od; 6782 6783 P := []; affs := []; 6784 for i in [1..Length(Pf_img)] do 6785 for cl1 in Pf_img[i] do 6786 for j in [1..Length(Pg)] do 6787 for cl2 in Pg[j] do 6788 cl := Intersection(cl1,cl2); 6789 if cl = [] then continue; fi; 6790 aff := [affs_f[i][1]*affs_g[j][1], 6791 affs_f[i][2]*affs_g[j][1]+affs_f[i][3]*affs_g[j][2], 6792 affs_f[i][3]*affs_g[j][3]]; 6793 pos := Position(affs,aff); 6794 if pos = fail then 6795 Add(affs,aff); Add(P,[]); 6796 pos := Length(affs); 6797 fi; 6798 rj := Residue(cl); mj := Modulus(cl); 6799 rjpre := (rj*affs_f[i][3]-affs_f[i][2])/affs_f[i][1]; 6800 mjpre := affs_f[i][3]*mj/affs_f[i][1]; 6801 pre := ResidueClass(R,mjpre,rjpre); 6802 Add(P[pos],pre); 6803 od; 6804 od; 6805 od; 6806 od; 6807 6808 m := Lcm(List(Flat(P),Modulus)); 6809 res := AllResidues(R,m); 6810 c := ListWithIdenticalEntries(Length(res),[1,0,1]*One(R)); 6811 6812 for i in [1..Length(P)] do 6813 aff := affs[i]; 6814 for cl in P[i] do 6815 rj := Residue(cl); mj := Modulus(cl); 6816 for k in [1..Length(res)] do 6817 if res[k] mod mj = rj then c[k] := aff; fi; 6818 od; 6819 od; 6820 od; 6821 6822 fg := RcwaMappingNC(R,m,c); 6823 6824 if HasIsInjective(f) and IsInjective(f) 6825 and HasIsInjective(g) and IsInjective(g) 6826 then SetIsInjective(fg,true); fi; 6827 6828 if HasIsSurjective(f) and IsSurjective(f) 6829 and HasIsSurjective(g) and IsSurjective(g) 6830 then SetIsSurjective(fg,true); fi; 6831 6832 return fg; 6833 end ); 6834 6835############################################################################# 6836## 6837#M CompositionMapping2( <g>, <f> ) . . . . . . for two rcwa mappings of Z^2 6838## 6839## Returns the product (composition) of the rcwa mappings <f> and <g>. 6840## The mapping <f> is applied first. The multiplier of <f> must not be zero. 6841## 6842## This is the equivalent for rcwa mappings of Z^2 of the "sparse" method 6843## above. 6844## 6845InstallMethod( CompositionMapping2, 6846 "for two rcwa mappings of a ring (sparse case method) (RCWA)", 6847 IsIdenticalObj, [ IsRcwaMappingOfZxZInStandardRep, 6848 IsRcwaMappingOfZxZInStandardRep ], 0, 6849 6850 function ( g, f ) 6851 6852 local fg, R, mf, mg, m, resf, resg, res, cf, cg, c, 6853 affs_f, affs_g, affs, Pf, Pg, Pf_img, P, S1, S2, I, 6854 aff, pre, ri, mi, pos, i, j; 6855 6856 if IsZero(Multiplier(f)) then TryNextMethod(); fi; 6857 6858 R := Source(f); 6859 6860 mf := Modulus(f); mg := Modulus(g); 6861 resf := AllResidues(R,mf); resg := AllResidues(R,mg); 6862 cf := Coefficients(f); cg := Coefficients(g); 6863 6864 Pf := LargestSourcesOfAffineMappings(f); 6865 Pg := LargestSourcesOfAffineMappings(g); 6866 6867 affs_f := List(Pf,S->cf[First([1..Length(resf)],i->resf[i] in S)]); 6868 affs_g := List(Pg,S->cg[First([1..Length(resg)],i->resg[i] in S)]); 6869 6870 Pf_img := List(Pf,S->S^f); 6871 6872 P := []; affs := []; 6873 for i in [1..Length(Pf_img)] do 6874 S1 := Pf_img[i]; 6875 for j in [1..Length(Pg)] do 6876 S2 := Pg[j]; 6877 I := Intersection(S1,S2); 6878 if IsEmpty(I) then continue; fi; 6879 aff := [affs_f[i][1]*affs_g[j][1], 6880 affs_f[i][2]*affs_g[j][1]+affs_f[i][3]*affs_g[j][2], 6881 affs_f[i][3]*affs_g[j][3]]; 6882 pos := Position(affs,aff); 6883 if pos = fail then 6884 Add(affs,aff); Add(P,[]); 6885 pos := Length(affs); 6886 fi; 6887 pre := (I*affs_f[i][3]-affs_f[i][2])*affs_f[i][1]^-1; 6888 P[pos] := Union(P[pos],pre); 6889 od; 6890 od; 6891 6892 m := Lcm(List(P,Modulus)); 6893 res := AllResidues(R,m); 6894 c := ListWithIdenticalEntries(Length(res),Zero(R)); 6895 6896 for i in [1..Length(P)] do 6897 aff := affs[i]; mi := Modulus(P[i]); 6898 for ri in Residues(P[i]) do 6899 for j in [1..Length(res)] do 6900 if res[j] mod mi = ri then c[j] := aff; fi; 6901 od; 6902 od; 6903 od; 6904 6905 fg := RcwaMappingNC(R,m,c); 6906 6907 if HasIsInjective(f) and IsInjective(f) 6908 and HasIsInjective(g) and IsInjective(g) 6909 then SetIsInjective(fg,true); fi; 6910 6911 if HasIsSurjective(f) and IsSurjective(f) 6912 and HasIsSurjective(g) and IsSurjective(g) 6913 then SetIsSurjective(fg,true); fi; 6914 6915 return fg; 6916 end ); 6917 6918############################################################################# 6919## 6920#M \*( <f>, <g> ) . . . . . . . . . . . . . . . . . . for two rcwa mappings 6921## 6922## Product (composition) of the rcwa mappings <f> and <g>. 6923## The mapping <f> is applied first. 6924## 6925InstallMethod( \*, 6926 "for two rcwa mappings (RCWA)", 6927 IsIdenticalObj, [ IsRcwaMapping, IsRcwaMapping ], 0, 6928 6929 function ( f, g ) 6930 return CompositionMapping( g, f ); 6931 end ); 6932 6933############################################################################# 6934## 6935#M \*( <n>, <f> ) . . . . . . . . . . for a ring element and an rcwa mapping 6936#M \*( <n>, <f> ) . . for an integer and an rcwa mapping of Z in sparse rep. 6937#M \*( <f>, <n> ) . . . . . . . . . . for an rcwa mapping and a ring element 6938## 6939InstallMethod( \*, 6940 "for rcwa mappings, multiplication by a constant (RCWA)", 6941 ReturnTrue, [ IsRingElement, IsRcwaMappingInStandardRep ], 0, 6942 6943 function ( n, f ) 6944 if not n in Source(f) then TryNextMethod(); fi; 6945 return RcwaMapping(Source(f),Modulus(f), 6946 List(Coefficients(f),c->[n*c[1],n*c[2],c[3]])); 6947 end ); 6948 6949InstallMethod( \*, 6950 "for an rcwa mapping of Z in sparse rep. & a constant (RCWA)", 6951 ReturnTrue, [ IsInt, IsRcwaMappingOfZInSparseRep ], 0, 6952 6953 function ( n, f ) 6954 if not n in Source(f) then TryNextMethod(); fi; 6955 return RcwaMapping(List(f!.coeffs,c->[c[1],c[2],n*c[3],n*c[4],c[5]])); 6956 end ); 6957 6958InstallMethod( \*, "for rcwa mappings, multiplication by a constant (RCWA)", 6959 ReturnTrue, [ IsRcwaMapping, IsRingElement ], 0, 6960 6961 function ( f, n ) 6962 if not n in Source(f) then TryNextMethod(); fi; 6963 return n * f; 6964 end ); 6965 6966############################################################################# 6967## 6968#M \*( <f>, <mat> ) . . for rcwa mappings of Z^2, multiplication by a matrix 6969## 6970InstallMethod( \*, 6971 "for rcwa mappings of Z^2, multiplication by a matrix (RCWA)", 6972 ReturnTrue, [ IsRcwaMappingOfZxZ, IsMatrix ], 0, 6973 6974 function ( f, mat ) 6975 6976 local coeffs, product; 6977 6978 if DimensionsMat(mat) <> [2,2] or not ForAll(Flat(mat),IsInt) 6979 then TryNextMethod(); fi; 6980 6981 coeffs := List(Coefficients(f),c->[c[1]*mat,c[2]*mat,c[3]]); 6982 product := RcwaMapping(Source(f),Modulus(f),coeffs); 6983 6984 if DeterminantMat(mat) <> 0 and HasIsInjective(f) and IsInjective(f) 6985 then SetIsInjective(product,true); fi; 6986 6987 return product; 6988 end ); 6989 6990############################################################################# 6991## 6992#M \*( <n>, <f> ) . . for rcwa mappings of Z^2, multiplication by an integer 6993## 6994InstallMethod( \*, 6995 "for rcwa mappings of Z^2, multiplication by integer (RCWA)", 6996 ReturnTrue, [ IsInt, IsRcwaMappingOfZxZ ], 0, 6997 function ( n, f ) return f * [ [ n, 0 ], [ 0, n ] ]; end ); 6998 6999############################################################################# 7000## 7001#S Technical functions for deriving names of powers from names of bases. /// 7002## 7003############################################################################# 7004 7005############################################################################# 7006## 7007#F NAME_OF_POWER_BY_NAME_EXPONENT_AND_ORDER( <name>, <n>, <order> ) 7008## 7009## Appends ^<n> to <name>, or multiplies an existing exponent by <n>. 7010## Reduces the exponent modulo <order>, if known (i.e. <> fail). 7011## 7012BindGlobal( "NAME_OF_POWER_BY_NAME_EXPONENT_AND_ORDER", 7013 7014 function ( name, n, order ) 7015 7016 local strings, e; 7017 7018 strings := SplitString(name,"^"); 7019 if not IsSubset("-0123456789",strings[Length(strings)]) then 7020 e := n; 7021 else 7022 e := Int(strings[Length(strings)]) * n; 7023 name := JoinStringsWithSeparator(strings{[1..Length(strings)-1]},"^"); 7024 fi; 7025 if order = fail or order = infinity then 7026 return Concatenation(name,"^",String(e)); 7027 elif e mod order = 1 then 7028 return name; 7029 elif e mod order = 0 then 7030 return fail; 7031 else 7032 return Concatenation(name,"^",String(e mod order)); 7033 fi; 7034 end ); 7035 7036############################################################################# 7037## 7038#F LATEXNAME_OF_POWER_BY_NAME_EXPONENT_AND_ORDER( <name>, <n>, <order> ) 7039## 7040## Appends ^{<n>} to <name>, if <name> does not already include an exponent. 7041## Reduces the exponent <n> modulo <order>, if known (i.e. <> fail). 7042## 7043BindGlobal( "LATEXNAME_OF_POWER_BY_NAME_EXPONENT_AND_ORDER", 7044 7045 function ( name, n, order ) 7046 7047 local strings, e; 7048 7049 strings := SplitString(name,"^"); 7050 if not IsSubset("-0123456789{}",strings[Length(strings)]) then 7051 e := n; 7052 else 7053 e := Int(Filtered(strings[Length(strings)], 7054 ch->ch in "-0123456789")) * n; 7055 name := JoinStringsWithSeparator(strings{[1..Length(strings)-1]},"^"); 7056 fi; 7057 if Position(name,'_') <> fail and name[1] <> '{' 7058 then name := Concatenation("{",name,"}"); fi; 7059 if order = fail or order = infinity then 7060 if e in [2..9] then return Concatenation(name,"^",String(e)); 7061 else return Concatenation(name,"^{",String(e),"}"); fi; 7062 elif e mod order = 1 then 7063 return name; 7064 elif e mod order = 0 then 7065 return fail; 7066 else 7067 e := e mod order; 7068 if e in [2..9] then return Concatenation(name,"^",String(e)); 7069 else return Concatenation(name,"^{",String(e),"}"); fi; 7070 fi; 7071 end ); 7072 7073############################################################################# 7074## 7075#S Computing inverses of rcwa permutations. //////////////////////////////// 7076## 7077############################################################################# 7078 7079############################################################################# 7080## 7081#M InverseOp( <f> ) . . . . . . . . . . . . for rcwa mappings of Z or Z_(pi) 7082## 7083## Returns the inverse mapping of the bijective rcwa mapping <f>. 7084## 7085InstallMethod( InverseOp, 7086 "for rcwa mappings of Z or Z_(pi) (RCWA)", 7087 true, [ IsRcwaMappingOfZOrZ_piInStandardRep ], 0, 7088 7089 function ( f ) 7090 7091 local Result, order, c, cInv, m, mInv, n, t, tm, tn, Classes, cl, pi; 7092 7093 if HasOrder(f) and Order(f) = 2 then return f; fi; 7094 7095 c := f!.coeffs; m := f!.modulus; 7096 cInv := []; 7097 mInv := Multiplier( f ) * m / Gcd( List( c, t -> t[3] ) ); 7098 for n in [ 1 .. m ] do 7099 t := [c[n][3], -c[n][2], c[n][1]]; if t[3] = 0 then return fail; fi; 7100 tm := StandardAssociate(Source(f),c[n][1]) * m / c[n][3]; 7101 tn := ((n - 1) * c[n][1] + c[n][2]) / c[n][3] mod tm; 7102 Classes := List([1 .. mInv/tm], i -> (i - 1) * tm + tn); 7103 for cl in Classes do 7104 if IsBound(cInv[cl + 1]) and cInv[cl + 1] <> t then return fail; fi; 7105 cInv[cl + 1] := t; 7106 od; 7107 od; 7108 7109 if not ForAll([1..mInv], i -> IsBound(cInv[i])) then return fail; fi; 7110 7111 if IsRcwaMappingOfZ( f ) 7112 then Result := RcwaMappingNC( cInv ); 7113 else pi := NoninvertiblePrimes( Source( f ) ); 7114 Result := RcwaMappingNC( pi, cInv ); 7115 fi; 7116 7117 SetInverse(f,Result); SetInverse(Result,f); 7118 SetIsBijective(f,true); SetIsBijective(Result,true); 7119 7120 if HasOrder(f) then SetOrder(Result,Order(f)); order := Order(f); 7121 else order := fail; fi; 7122 if HasBaseRoot(f) then 7123 SetBaseRoot(Result,BaseRoot(f)); 7124 SetPowerOverBaseRoot(Result,-PowerOverBaseRoot(f)); 7125 fi; 7126 if HasSmallestRoot(f) then 7127 SetSmallestRoot(Result,SmallestRoot(f)); 7128 SetPowerOverSmallestRoot(Result,-PowerOverSmallestRoot(f)); 7129 fi; 7130 if HasName(f) then 7131 SetName(Result,NAME_OF_POWER_BY_NAME_EXPONENT_AND_ORDER( 7132 Name(f),-1,order)); 7133 fi; 7134 if HasLaTeXString(f) then 7135 SetLaTeXString(Result,LATEXNAME_OF_POWER_BY_NAME_EXPONENT_AND_ORDER( 7136 LaTeXString(f),-1,order)); 7137 fi; 7138 7139 return Result; 7140 end ); 7141 7142############################################################################# 7143## 7144#M InverseOp( <f> ) . . . . . . . . . for rcwa mappings of Z in sparse rep. 7145## 7146## Returns the inverse mapping of the bijective rcwa mapping <f>. 7147## 7148InstallMethod( InverseOp, 7149 "for rcwa mappings of Z in sparse rep. (RCWA)", 7150 true, [ IsRcwaMappingOfZInSparseRep ], 0, 7151 7152 function ( f ) 7153 7154 local inverse, order; 7155 7156 if not IsBijective(f) then return fail; fi; 7157 if HasOrder(f) and Order(f) = 2 then return f; fi; 7158 7159 inverse := RcwaMappingNC(List(f!.coeffs,c-> 7160 [(c[3]*c[1]+c[4])/c[5],c[3]*c[2]/c[5],c[5],-c[4],c[3]])); 7161 7162 SetInverse(f,inverse); SetInverse(inverse,f); 7163 SetIsBijective(f,true); SetIsBijective(inverse,true); 7164 7165 if HasOrder(f) then SetOrder(inverse,Order(f)); order := Order(f); 7166 else order := fail; fi; 7167 if HasBaseRoot(f) then 7168 SetBaseRoot(inverse,BaseRoot(f)); 7169 SetPowerOverBaseRoot(inverse,-PowerOverBaseRoot(f)); 7170 fi; 7171 if HasSmallestRoot(f) then 7172 SetSmallestRoot(inverse,SmallestRoot(f)); 7173 SetPowerOverSmallestRoot(inverse,-PowerOverSmallestRoot(f)); 7174 fi; 7175 if HasName(f) then 7176 SetName(inverse,NAME_OF_POWER_BY_NAME_EXPONENT_AND_ORDER( 7177 Name(f),-1,order)); 7178 fi; 7179 if HasLaTeXString(f) then 7180 SetLaTeXString(inverse,LATEXNAME_OF_POWER_BY_NAME_EXPONENT_AND_ORDER( 7181 LaTeXString(f),-1,order)); 7182 fi; 7183 7184 return inverse; 7185 end ); 7186 7187############################################################################# 7188## 7189#M InverseOp( <f> ) . . . . . . . . . . . . . . . . for rcwa mappings of Z^2 7190## 7191## Returns the inverse mapping of the bijective rcwa mapping <f>. 7192## 7193InstallMethod( InverseOp, 7194 "for rcwa mappings of Z^2 (RCWA)", true, 7195 [ IsRcwaMappingOfZxZInStandardRep ], 0, 7196 7197 function ( f ) 7198 7199 local R, result, m, c, mInv, cInv, res, clsimg, indimg, t, order, i, j; 7200 7201 if HasOrder(f) and Order(f) = 2 then return f; fi; 7202 if not IsBijective(f) then return fail; fi; 7203 7204 R := Source(f); m := Modulus(f); c := Coefficients(f); 7205 7206 clsimg := AllResidueClassesModulo(R,m)^f; 7207 mInv := Lcm(List(clsimg,Modulus)); 7208 res := AllResidues(R,mInv); 7209 cInv := []; 7210 7211 for i in [1..Length(clsimg)] do 7212 t := [c[i][3]*c[i][1]^-1,-c[i][2]*c[i][1]^-1,1]; 7213 t := t * Lcm(List(Flat(t),DenominatorRat)); 7214 indimg := Filtered([1..Length(res)],j->res[j] in clsimg[i]); 7215 for j in indimg do cInv[j] := t; od; 7216 od; 7217 7218 result := RcwaMapping(R,mInv,cInv); # ... NC, once tested 7219 7220 SetInverse(f,result); SetInverse(result,f); 7221 SetIsBijective(f,true); SetIsBijective(result,true); 7222 7223 if HasOrder(f) then SetOrder(result,Order(f)); order := Order(f); 7224 else order := fail; fi; 7225 if HasName(f) then 7226 SetName(result,NAME_OF_POWER_BY_NAME_EXPONENT_AND_ORDER( 7227 Name(f),-1,order)); 7228 fi; 7229 if HasLaTeXString(f) then 7230 SetLaTeXString(result,LATEXNAME_OF_POWER_BY_NAME_EXPONENT_AND_ORDER( 7231 LaTeXString(f),-1,order)); 7232 fi; 7233 7234 return result; 7235 end ); 7236 7237############################################################################# 7238## 7239#M InverseOp( <f> ) . . . . . . . . . . . . . for rcwa mappings of GF(q)[x] 7240## 7241## Returns the inverse mapping of the bijective rcwa mapping <f>. 7242## 7243InstallMethod( InverseOp, 7244 "for rcwa mappings of GF(q)[x] (RCWA)", true, 7245 [ IsRcwaMappingOfGFqxInStandardRep ], 0, 7246 7247 function ( f ) 7248 7249 local Result, order, c, cInv, m, mInv, d, dInv, R, q, x, 7250 respols, res, resInv, r, n, t, tm, tr, tn, Classes, cl, pos; 7251 7252 if HasOrder(f) and Order(f) = 2 then return f; fi; 7253 7254 R := UnderlyingRing(FamilyObj(f)); 7255 q := Size(CoefficientsRing(R)); 7256 x := IndeterminatesOfPolynomialRing(R)[1]; 7257 c := f!.coeffs; m := f!.modulus; 7258 cInv := []; 7259 mInv := StandardAssociate( R, 7260 Multiplier( f ) * m / Gcd( m, Gcd( List( c, t -> t[3] ) ) ) ); 7261 d := DegreeOfLaurentPolynomial(m); 7262 dInv := DegreeOfLaurentPolynomial(mInv); 7263 res := AllGFqPolynomialsModDegree(q,d,x); 7264 respols := List([0..dInv], d -> AllGFqPolynomialsModDegree(q,d,x)); 7265 resInv := respols[dInv + 1]; 7266 7267 for n in [ 1 .. Length(res) ] do 7268 r := res[n]; 7269 t := [c[n][3], -c[n][2], c[n][1]]; 7270 if IsZero(t[3]) then return fail; fi; 7271 tm := StandardAssociate(Source(f),c[n][1]) * m / c[n][3]; 7272 tr := (r * c[n][1] + c[n][2]) / c[n][3] mod tm; 7273 Classes := List(respols[DegreeOfLaurentPolynomial(mInv/tm) + 1], 7274 p -> p * tm + tr); 7275 for cl in Classes do 7276 pos := Position(resInv,cl); 7277 if IsBound(cInv[pos]) and cInv[pos] <> t then return fail; fi; 7278 cInv[pos] := t; 7279 od; 7280 od; 7281 7282 if not ForAll([1..Length(resInv)], i -> IsBound(cInv[i])) 7283 then return fail; fi; 7284 7285 Result := RcwaMappingNC( q, mInv, cInv ); 7286 7287 SetInverse(f,Result); SetInverse(Result,f); 7288 SetIsBijective(f,true); SetIsBijective(Result,true); 7289 7290 if HasOrder(f) then SetOrder(Result,Order(f)); order := Order(f); 7291 else order := fail; fi; 7292 if HasName(f) then 7293 SetName(Result,NAME_OF_POWER_BY_NAME_EXPONENT_AND_ORDER( 7294 Name(f),-1,order)); 7295 fi; 7296 if HasLaTeXString(f) then 7297 SetLaTeXString(Result,LATEXNAME_OF_POWER_BY_NAME_EXPONENT_AND_ORDER( 7298 LaTeXString(f),n,order)); 7299 fi; 7300 7301 return Result; 7302 end ); 7303 7304############################################################################# 7305## 7306#M InverseGeneralMapping( <f> ) . . . . . . . . . . . . . for rcwa mappings 7307## 7308## Returns the inverse mapping of the bijective rcwa mapping <f>. 7309## 7310InstallMethod( InverseGeneralMapping, 7311 "for rcwa mappings (RCWA)", 7312 true, [ IsRcwaMapping ], 0, 7313 7314 function ( f ) 7315 if IsBijective(f) then return Inverse(f); else TryNextMethod(); fi; 7316 end ); 7317 7318############################################################################# 7319## 7320#S Computing right inverses of injective rcwa mappings. //////////////////// 7321## 7322############################################################################# 7323 7324############################################################################# 7325## 7326#M RightInverse( <f> ) . . . . . . . . . . . . . for injective rcwa mappings 7327## 7328InstallMethod( RightInverse, 7329 "for injective rcwa mappings (RCWA)", 7330 true, [ IsRcwaMapping ], 0, 7331 7332 function ( f ) 7333 7334 local R, mf, cf, resf, inv, minv, cinv, resinv, imgs, 7335 r1, r2, pos1, pos2, idcoeff; 7336 7337 if not IsInjective(f) then return fail; fi; 7338 if not IsRcwaMappingStandardRep(f) then f := StandardRep(f); fi; 7339 7340 R := Source(f); 7341 if IsRing(R) then idcoeff := [1,0,1] * One(R); 7342 elif IsZxZ(R) then idcoeff := [[[1,0],[0,1]],[0,0],1]; 7343 else TryNextMethod(); fi; 7344 mf := Modulus(f); cf := Coefficients(f); 7345 imgs := AllResidueClassesModulo(R,mf)^f; 7346 minv := Lcm(List(imgs,Modulus)); 7347 cinv := ListWithIdenticalEntries(NumberOfResidues(R,minv),idcoeff); 7348 resf := AllResidues(R,mf); resinv := AllResidues(R,minv); 7349 for r1 in resf do 7350 pos1 := PositionSorted(resf,r1); 7351 for r2 in AsList(Intersection(resinv,imgs[pos1])) do 7352 pos2 := PositionSorted(resinv,r2); 7353 if IsRing(R) 7354 then cinv[pos2] := [cf[pos1][3],-cf[pos1][2],cf[pos1][1]]; 7355 else cinv[pos2] := [cf[pos1][3]*cf[pos1][1]^-1, 7356 -cf[pos1][2]*cf[pos1][1]^-1,1]; 7357 cinv[pos2] := cinv[pos2] * Lcm(List(Flat(cinv[pos2]), 7358 DenominatorRat)); 7359 fi; 7360 od; 7361 od; 7362 inv := RcwaMapping(R,minv,cinv); 7363 return inv; 7364 end ); 7365 7366############################################################################# 7367## 7368#M RightInverse( <f> ) . . . . . . . . . . for injective rcwa mappings of Z 7369## 7370InstallMethod( RightInverse, 7371 "for injective rcwa mappings of Z (RCWA)", 7372 true, [ IsRcwaMappingOfZ ], 0, 7373 7374 function ( f ) 7375 7376 local inv, mf, cf, minv, cinv, imgs, r1, r2; 7377 7378 if not IsInjective(f) then return fail; fi; 7379 if not IsRcwaMappingStandardRep(f) then f := StandardRep(f); fi; 7380 7381 mf := Modulus(f); cf := Coefficients(f); 7382 imgs := AllResidueClassesModulo(mf)^f; 7383 minv := Lcm(List(imgs,Modulus)); 7384 cinv := List([1..minv],r->[1,0,1]); 7385 for r1 in [1..mf] do 7386 for r2 in Intersection([0..minv-1],imgs[r1]) do 7387 cinv[r2+1] := [cf[r1][3],-cf[r1][2],cf[r1][1]]; 7388 od; 7389 od; 7390 inv := RcwaMapping(cinv); 7391 return inv; 7392 end ); 7393 7394############################################################################# 7395## 7396#M CommonRightInverse( <l>, <r> ) . . . . . . . . for two rcwa mappings of Z 7397## 7398InstallMethod( CommonRightInverse, 7399 "for two rcwa mappings of Z (RCWA)", true, 7400 [ IsRcwaMappingOfZ, IsRcwaMappingOfZ ], 0, 7401 7402 function ( l, r ) 7403 7404 local d, imgl, imgr, coeffs, m, c, r1, r2; 7405 7406 if not ForAll([l,r],IsInjective) or Intersection(Image(l),Image(r)) <> [] 7407 or Union(Image(l),Image(r)) <> Integers 7408 then return fail; fi; 7409 7410 if not IsRcwaMappingStandardRep(l) then l := StandardRep(l); fi; 7411 if not IsRcwaMappingStandardRep(l) then r := StandardRep(r); fi; 7412 7413 imgl := AllResidueClassesModulo(Modulus(l))^l; 7414 imgr := AllResidueClassesModulo(Modulus(r))^r; 7415 7416 m := Lcm(List(Concatenation(imgl,imgr),Modulus)); 7417 7418 coeffs := List([0..m-1],r1->[1,0,1]); 7419 7420 for r1 in [0..Length(imgl)-1] do 7421 c := Coefficients(l)[r1+1]; 7422 for r2 in Intersection(imgl[r1+1],[0..m-1]) do 7423 coeffs[r2+1] := [ c[3], -c[2], c[1] ]; 7424 od; 7425 od; 7426 7427 for r1 in [0..Length(imgr)-1] do 7428 c := Coefficients(r)[r1+1]; 7429 for r2 in Intersection(imgr[r1+1],[0..m-1]) do 7430 coeffs[r2+1] := [ c[3], -c[2], c[1] ]; 7431 od; 7432 od; 7433 7434 d := RcwaMapping(coeffs); 7435 return d; 7436 7437 end ); 7438 7439############################################################################# 7440## 7441#S Computing conjugates and powers of rcwa mappings. /////////////////////// 7442## 7443############################################################################# 7444 7445############################################################################# 7446## 7447#M \^( <g>, <h> ) . . . . . . . . . . . . . . . . . . for two rcwa mappings 7448## 7449## Returns the conjugate of the rcwa mapping <g> under <h>, 7450## i.e. <h>^-1*<g>*<h>. 7451## 7452InstallMethod( \^, 7453 "for two rcwa mappings (RCWA)", 7454 IsIdenticalObj, [ IsRcwaMapping, IsRcwaMapping ], 0, 7455 7456 function ( g, h ) 7457 7458 local f; 7459 7460 if IsOne(h) then return g; fi; 7461 f := h^-1 * g * h; 7462 if f = g then return g; fi; 7463 if HasOrder (g) then SetOrder (f,Order (g)); fi; 7464 if HasIsTame(g) then SetIsTame(f,IsTame(g)); fi; 7465 if HasStandardConjugate(g) 7466 then SetStandardConjugate(f,StandardConjugate(g)); fi; 7467 if HasStandardizingConjugator(g) 7468 then SetStandardizingConjugator(f,h^-1*StandardizingConjugator(g)); fi; 7469 if HasSmallestRoot(g) and AbsInt(PowerOverSmallestRoot(g)) > 1 then 7470 SetSmallestRoot(f,SmallestRoot(g)^h); 7471 SetPowerOverSmallestRoot(f,PowerOverSmallestRoot(g)); 7472 fi; 7473 return f; 7474 end ); 7475 7476############################################################################# 7477## 7478#M IsCommuting( <g>, <h> ) . . . . . . . . . . . . . . . . for rcwa mappings 7479## 7480InstallMethod( IsCommuting, 7481 "for rcwa mappings (RCWA)", IsIdenticalObj, 7482 [ IsRcwaMapping, IsRcwaMapping ], 0, 7483 7484 function ( g, h ) 7485 7486 local R, a, b; 7487 7488 if g = h then return true; fi; 7489 if HasInverse(g) and h = Inverse(g) then return true; fi; 7490 7491 R := Source(g); 7492 if NumberOfResidues(R,Mod(h)) > NumberOfResidues(R,Mod(g)) 7493 then a := g; b := h; else a := h; b := g; fi; 7494 if not ForAll(AllResidues(R,Mod(a)),r->(r^a)^b=(r^b)^a) 7495 then return false; fi; 7496 7497 return g*h = h*g; 7498 end ); 7499 7500############################################################################# 7501## 7502#M \^( <perm>, <g> ) . . . . . . for a permutation and an rcwa mapping of Z 7503## 7504## Returns the conjugate of the GAP permutation <perm> under the 7505## rcwa permutation <g>. The rcwa permutation <g> must not move any point 7506## in the support of <perm> to a negative integer. 7507## 7508InstallMethod( \^, 7509 "for a permutation and an rcwa mapping of Z (RCWA)", 7510 ReturnTrue, [ IsPerm, IsRcwaMappingOfZ ], 0, 7511 7512 function ( perm, g ) 7513 7514 local cycs, cyc, h, i; 7515 7516 if not IsBijective(g) then 7517 Error("<g> must be bijective.\n"); 7518 return fail; 7519 fi; 7520 if not ForAll(MovedPoints(perm)^g,IsPosInt) then 7521 Info(InfoWarning,1, 7522 "Warning: GAP permutations can only move positive integers!"); 7523 TryNextMethod(); 7524 fi; 7525 cycs := List(Cycles(perm,MovedPoints(perm)),cyc->OnTuples(cyc,g)); 7526 h := (); 7527 for cyc in cycs do 7528 for i in [2..Length(cyc)] do h := h * (cyc[1],cyc[i]); od; 7529 od; 7530 return h; 7531 end ); 7532 7533############################################################################# 7534## 7535#M \^( <f>, <n> ) . . . . . . . . . . . . for an rcwa mapping and an integer 7536## 7537## Returns the <n>-th power of the rcwa mapping <f>. 7538## 7539InstallMethod( \^, 7540 "for an rcwa mapping and an integer (RCWA)", 7541 ReturnTrue, [ IsRcwaMapping, IsInt ], 0, 7542 7543 function ( f, n ) 7544 7545 local pow, e, name, latex; 7546 7547 if ValueOption("UseKernelPOW") = true then TryNextMethod(); fi; 7548 7549 if HasOrder(f) and Order(f) <> infinity then n := n mod Order(f); fi; 7550 7551 if n = 0 then return One(f); 7552 elif n = 1 then return f; 7553 else if n > 1 then pow := POW(f,n:UseKernelPOW); 7554 else pow := POW(Inverse(f),-n:UseKernelPOW); fi; 7555 fi; 7556 7557 if HasIsTame(f) then SetIsTame(pow,IsTame(f)); fi; 7558 7559 if HasBaseRoot(f) then 7560 SetBaseRoot(pow,BaseRoot(f)); 7561 SetPowerOverBaseRoot(pow,PowerOverBaseRoot(f)*n); 7562 fi; 7563 7564 if HasSmallestRoot(f) then 7565 SetSmallestRoot(pow,SmallestRoot(f)); 7566 SetPowerOverSmallestRoot(pow,PowerOverSmallestRoot(f)*n); 7567 fi; 7568 7569 if HasOrder(f) then 7570 if Order(f) = infinity then SetOrder(pow,infinity); else 7571 SetOrder(pow,Order(f)/Gcd(Order(f),n)); 7572 fi; 7573 if HasName(f) and HasIsTame(f) and IsTame(f) then 7574 name := NAME_OF_POWER_BY_NAME_EXPONENT_AND_ORDER(Name(f),n,Order(f)); 7575 if name <> fail then SetName(pow,name); fi; 7576 fi; 7577 if HasLaTeXString(f) then 7578 latex := LATEXNAME_OF_POWER_BY_NAME_EXPONENT_AND_ORDER( 7579 LaTeXString(f),n,Order(f)); 7580 if latex <> fail then SetLaTeXString(pow,latex); fi; 7581 fi; 7582 fi; 7583 7584 if HasIsClassShift(f) and IsClassShift(f) and not IsOne(pow) 7585 then SetIsPowerOfClassShift(pow,true); fi; 7586 7587 return pow; 7588 end ); 7589 7590############################################################################# 7591## 7592#S Testing an rcwa mapping for tameness, and respected partitions. ///////// 7593## 7594############################################################################# 7595 7596############################################################################# 7597## 7598#M IsTame( <f> ) . . . . . . . . . . . . . . . . . . . . . for rcwa mappings 7599## 7600InstallMethod( IsTame, 7601 "for rcwa mappings (RCWA)", true, [ IsRcwaMapping ], 0, 7602 7603 function ( f ) 7604 7605 local gamma, delta, C, r, m, coeffs, cl, img, 7606 starttime, k, pow, exp, e; 7607 7608 Info(InfoRCWA,3,"`IsTame' for an rcwa mapping <f> of ", 7609 RingToString(Source(f)),"."); 7610 7611 if IsBijective(f) and HasOrder(f) and Order(f) <> infinity then 7612 Info(InfoRCWA,3,"IsTame: <f> has finite order, hence is tame."); 7613 return true; 7614 fi; 7615 7616 if IsIntegral(f) then 7617 Info(InfoRCWA,3,"IsTame: <f> is integral, hence tame."); 7618 return true; 7619 fi; 7620 7621 if IsRing(Source(f)) 7622 and not IsSubset(Factors(Multiplier(f)),Factors(Divisor(f))) 7623 then 7624 Info(InfoRCWA,3,"IsTame: <f> is wild, by balancedness criterion."); 7625 if IsBijective(f) then SetOrder(f,infinity); fi; 7626 return false; 7627 fi; 7628 7629 if IsBijective(f) and not IsBalanced(f) then 7630 Info(InfoRCWA,3,"IsTame: <f> is wild, by balancedness criterion."); 7631 SetOrder(f,infinity); return false; 7632 fi; 7633 7634 if IsSurjective(f) and not IsInjective(f) then 7635 Info(InfoRCWA,3,"IsTame: <f> is surjective and not ", 7636 "injective, hence wild."); 7637 return false; 7638 fi; 7639 7640 if IsRcwaMappingOfZOrZ_pi(f) and IsBijective(f) then 7641 Info(InfoRCWA,3,"IsTame: sources-and-sinks criterion."); 7642 gamma := TransitionGraph(f,Modulus(f)); 7643 for r in [1..Modulus(f)] do RemoveSet(gamma.adjacencies[r],r); od; 7644 delta := UnderlyingGraph(gamma); 7645 C := ConnectedComponents(delta); 7646 if Position(List(C,V->Diameter(InducedSubgraph(gamma,V))),-1) <> fail 7647 then 7648 Info(InfoRCWA,3,"IsTame: <f> is wild, ", 7649 "by sources-and-sinks criterion."); 7650 SetOrder(f,infinity); return false; 7651 fi; 7652 fi; 7653 7654 if IsBijective(f) then 7655 Info(InfoRCWA,3,"IsTame: loop criterion."); 7656 m := Modulus(f); 7657 if IsRcwaMappingOfZ(f) then 7658 starttime := Runtime(); 7659 k := 1; pow := f; 7660 repeat 7661 if Loops(pow) <> [] then 7662 Info(InfoRCWA,3,"IsTame: <f>^",k," has loops, thus <f> ", 7663 "is wild by loop criterion."); 7664 SetOrder(f,infinity); return false; 7665 fi; 7666 if IsIntegral(pow) then 7667 Info(InfoRCWA,3,"IsTame: <f>^",k," is integral, ", 7668 "thus <f> is tame."); 7669 return true; 7670 fi; 7671 if Mod(pow) < m or LogInt(Int(Mod(pow)/m),2) < k/6 - 1 7672 then break; fi; 7673 if Runtime() - starttime > 10 * m then break; fi; 7674 starttime := Runtime(); 7675 k := k + 1; pow := pow * f; 7676 until false; 7677 else 7678 for cl in AllResidueClassesModulo(Source(f),m) do 7679 img := cl^f; 7680 if img <> cl and Intersection(cl,img) <> [] then 7681 Info(InfoRCWA,3,"IsTame: <f> is wild, by loop criterion."); 7682 SetOrder(f,infinity); return false; 7683 fi; 7684 od; 7685 fi; 7686 fi; 7687 7688 Info(InfoRCWA,3,"IsTame: `finite order or integral power' criterion."); 7689 pow := f; 7690 exp := [2,2,3,5,2,7,3,2,11,13,5,3,17,2,19,2,2,3,5,7,11,2,23]; e := 1; 7691 for e in exp do 7692 pow := pow^e; 7693 if IsIntegral(pow) then 7694 Info(InfoRCWA,3,"IsTame: <f> has a power which is integral, ", 7695 "hence is tame."); 7696 return true; 7697 fi; 7698 if IsRcwaMappingOfZOrZ_pi(f) 7699 and Modulus(pow) > Minimum(Modulus(f)^2,2^16) 7700 or IsRcwaMappingOfGFqx(f) 7701 and DegreeOfLaurentPolynomial(Modulus(pow)) 7702 > DegreeOfLaurentPolynomial(Modulus(f)) + 2 7703 then break; fi; 7704 od; 7705 7706 if IsBijective(f) and Order(f) <> infinity then 7707 Info(InfoRCWA,3,"IsTame: <f> has finite order, hence is tame."); 7708 return true; 7709 fi; 7710 7711 if HasIsTame(f) then return IsTame(f); fi; 7712 7713 Info(InfoRCWA,3,"IsTame: Giving up."); 7714 TryNextMethod(); 7715 7716 end ); 7717 7718############################################################################# 7719## 7720#M RespectedPartition( <sigma> ) . . . . . for tame bijective rcwa mappings 7721## 7722InstallMethod( RespectedPartition, 7723 "for tame bijective rcwa mappings (RCWA)", true, 7724 [ IsRcwaMapping ], 0, 7725 7726 function ( sigma ) 7727 if not IsBijective(sigma) then return fail; fi; 7728 return RespectedPartition( Group( sigma ) ); 7729 end ); 7730 7731############################################################################# 7732## 7733#M RespectsPartition( <sigma>, <P> ) . . for rcwa mappings in standard rep. 7734## 7735InstallMethod( RespectsPartition, 7736 "for rcwa mappings in standard rep. (RCWA)", 7737 ReturnTrue, [ IsRcwaMappingInStandardRep, IsList ], 0, 7738 7739 function ( sigma, P ) 7740 7741 local R, cl, c, c_rest, pos, res, r, m; 7742 7743 R := Source(sigma); 7744 if not ForAll(P,cl->IsResidueClass(cl) and IsSubset(R,cl)) 7745 or Union(P) <> R or Sum(List(P,Density)) <> 1 7746 then TryNextMethod(); fi; 7747 if Permutation(sigma,P) = fail then return false; fi; 7748 c := Coefficients(sigma); 7749 res := AllResidues(R,Modulus(sigma)); 7750 for cl in P do 7751 r := Residue(cl); 7752 m := Modulus(cl); 7753 pos := Filtered([1..Length(res)],i->res[i] mod m = r); 7754 c_rest := c{pos}; 7755 if Length(Set(c_rest)) > 1 then return false; fi; 7756 od; 7757 return true; 7758 end ); 7759 7760############################################################################# 7761## 7762#M RespectsPartition( <sigma>, <P> ) . for rcwa mappings of Z in sparse rep. 7763## 7764InstallMethod( RespectsPartition, 7765 "for rcwa mappings of Z in sparse rep. (RCWA)", 7766 ReturnTrue, [ IsRcwaMappingOfZInSparseRep, IsList ], 0, 7767 7768 function ( sigma, P ) 7769 7770 if not ForAll(P,cl->IsResidueClass(cl) and IsSubset(Integers,cl)) 7771 or Union(P) <> Integers or Sum(List(P,Density)) <> 1 7772 then TryNextMethod(); fi; 7773 7774 if Permutation(sigma,P) = fail then return false; fi; 7775 7776 return ForAll(P,cl->Length(Set(Filtered(sigma!.coeffs, 7777 c -> (c[1]-Residue(cl)) mod Gcd(c[2],Modulus(cl)) = 0), 7778 d -> d{[3..5]})) = 1); 7779 end ); 7780 7781############################################################################# 7782## 7783#M PermutationOpNC( <sigma>, <P>, <act> ) . . for rcwa map. and resp. part. 7784## 7785## This method serves only as a placeholder for something better. 7786## 7787InstallMethod( PermutationOpNC, 7788 "for an rcwa mapping and a respected partition (RCWA)", 7789 ReturnTrue, [ IsRcwaMapping, IsList, IsFunction ], 0, 7790 7791 function ( sigma, P, act ) 7792 return PermutationOp(sigma,P,act); 7793 end ); 7794 7795############################################################################# 7796## 7797#M PermutationOpNC( <sigma>, <P>, <act> ) for rcwa map. of Z and resp. part. 7798## 7799InstallMethod( PermutationOpNC, 7800 "for an rcwa mapping of Z and a respected partition (RCWA)", 7801 ReturnTrue, [ IsRcwaMappingOfZInSparseRep, 7802 IsList, IsFunction ], 0, 7803 7804 function ( sigma, P, act ) 7805 7806 local cls, imgs, coeffs, conj, cl, img, c, i; 7807 7808 if Length(P) = 1 then TryNextMethod(); fi; 7809 cls := List(P,cl->[cl!.r[1],cl!.m]); 7810 coeffs := sigma!.coeffs; 7811 conj := SortingPerm(cls)^-1; 7812 cls := Set(cls); 7813 imgs := []; 7814 for i in [1..Length(cls)] do 7815 cl := cls[i]; 7816 c := First(coeffs,c->cl[1] mod c[2] = c[1]); 7817 img := [(c[3]*cl[1]+c[4])/c[5],c[3]*cl[2]/c[5]]; 7818 img[1] := img[1] mod img[2]; 7819 imgs[i] := PositionSorted(cls,img); 7820 od; 7821 return PermList(imgs)^conj; 7822 end ); 7823 7824############################################################################# 7825## 7826#M PermutationOpNC( <sigma>, <P>, <act> ) for rcwa map. of Z and resp. part. 7827## 7828InstallMethod( PermutationOpNC, 7829 "for an rcwa mapping of Z and a respected partition (RCWA)", 7830 ReturnTrue, [ IsRcwaMappingOfZInStandardRep, 7831 IsList, IsFunction ], 0, 7832 7833 function ( sigma, P, act ) 7834 7835 local cls, imgs, m, coeffs, conj, cl, img, c, i; 7836 7837 if Length(P) = 1 then TryNextMethod(); fi; 7838 cls := List(P,cl->[cl!.r[1],cl!.m]); 7839 m := sigma!.modulus; 7840 coeffs := sigma!.coeffs; 7841 conj := SortingPerm(cls)^-1; 7842 cls := Set(cls); 7843 imgs := []; 7844 for i in [1..Length(cls)] do 7845 cl := cls[i]; 7846 c := coeffs[cl[1] mod m + 1]; 7847 img := [(c[1]*cl[1]+c[2])/c[3],c[1]*cl[2]/c[3]]; 7848 img[1] := img[1] mod img[2]; 7849 imgs[i] := PositionSorted(cls,img); 7850 od; 7851 return PermList(imgs)^conj; 7852 end ); 7853 7854############################################################################# 7855## 7856#M Permuted( <l>, <perm> ) . . . . . . . . . . . . . . . . . fallback method 7857## 7858## This method is used in particular in the case that <perm> is an rcwa 7859## permutation and <l> is a respected partition of <perm>. 7860## 7861InstallOtherMethod( Permuted, 7862 "fallback method (RCWA)", ReturnTrue, 7863 [ IsList, IsMapping ], 0, 7864 7865 function ( l, perm ) 7866 return Permuted( l, Permutation( perm, l ) ); 7867 end ); 7868 7869############################################################################# 7870## 7871#M CompatibleConjugate( <g>, <h> ) . . . . . . . for two rcwa mappings of Z 7872## 7873InstallMethod( CompatibleConjugate, 7874 "for two rcwa mappings of Z (RCWA)", true, 7875 [ IsRcwaMappingOfZ, IsRcwaMappingOfZ ], 0, 7876 7877 function ( g, h ) 7878 7879 local DividedPartition, Pg, Ph, PgNew, PhNew, lg, lh, l, tg, th, 7880 remg, remh, cycg, cych, sigma, c, m, i, r; 7881 7882 DividedPartition := function ( P, g, t ) 7883 7884 local PNew, rem, cyc, m, r; 7885 7886 PNew := []; rem := P; 7887 while rem <> [] do 7888 cyc := Cycle(g,rem[1]); 7889 rem := Difference(rem,cyc); 7890 m := Modulus(cyc[1]); r := Residues(cyc[1])[1]; 7891 PNew := Union(PNew, 7892 Flat(List([0..t-1], 7893 k->Cycle(g,ResidueClass(Integers, 7894 t*m,k*m+r))))); 7895 od; 7896 return PNew; 7897 end; 7898 7899 if not ForAll([g,h],f->IsBijective(f) and IsTame(f)) 7900 then return fail; fi; 7901 Pg := RespectedPartition(g); Ph := RespectedPartition(h); 7902 lg := Length(Pg); lh := Length(Ph); 7903 l := Lcm(lg,lh); tg := l/lg; th := l/lh; 7904 PgNew := DividedPartition(Pg,g,tg); PhNew := DividedPartition(Ph,h,th); 7905 c := []; m := Lcm(List(PhNew,Modulus)); 7906 for i in [1..l] do 7907 for r in Filtered([0..m-1],s->s mod Modulus(PhNew[i]) 7908 = Residues(PhNew[i])[1]) do 7909 c[r+1] := [ Modulus(PgNew[i]), 7910 Modulus(PhNew[i])*Residues(PgNew[i])[1] 7911 - Modulus(PgNew[i])*Residues(PhNew[i])[1], 7912 Modulus(PhNew[i]) ]; 7913 od; 7914 od; 7915 sigma := RcwaMapping(c); 7916 if IsRcwaMappingSparseRep(g) and IsRcwaMappingSparseRep(h) 7917 then sigma := SparseRep(sigma); fi; 7918 return h^sigma; 7919 end ); 7920 7921############################################################################# 7922## 7923#S Computing the order of an rcwa permutation. ///////////////////////////// 7924## 7925############################################################################# 7926 7927############################################################################# 7928## 7929#M Order( <g> ) . . . . . . . . . . . . . . . . for bijective rcwa mappings 7930## 7931InstallMethod( Order, 7932 "for bijective rcwa mappings (RCWA)", 7933 true, [ IsRcwaMapping ], 0, 7934 7935 function ( g ) 7936 7937 local P, k, p, gtilde, e, e_old, e_max, l, l_max, stabiter, 7938 loopcheckbound, n0, n, b1, b2, m1, m2, r, cycs, pow, exp, c, i; 7939 7940 if not IsBijective(g) 7941 then Error("Order: <rcwa mapping> must be bijective"); fi; 7942 7943 Info(InfoRCWA,3,"`Order' for an rcwa permutation <g> of ", 7944 RingToString(Source(g)),"."); 7945 7946 if IsOne(g) then return 1; fi; 7947 7948 if HasIsTame(g) and not IsTame(g) then 7949 Info(InfoRCWA,3,"Order: <g> is wild, hence has infinite order."); 7950 return infinity; 7951 fi; 7952 7953 if IsRcwaMappingOfZ(g) then 7954 if IsClassWiseOrderPreserving(g) and Determinant(g) <> 0 then 7955 Info(InfoRCWA,3,"Order: <g> is class-wise order-preserving, ", 7956 "but not in ker det."); 7957 Info(InfoRCWA,3," Hence <g> has infinite order."); 7958 return infinity; 7959 fi; 7960 if not IsIntegral(g) then 7961 loopcheckbound := ValueOption("loopcheckbound"); 7962 if loopcheckbound = fail then 7963 loopcheckbound := RootInt(Mod(g),2) + 5; # necessary AT LEAST 7964 fi; 7965 pow := g; 7966 for k in [1..loopcheckbound] do 7967 if Loops(pow) <> [] then 7968 Info(InfoRCWA,3,"Order: <g>^",k," has loops, hence <g> ", 7969 "has infinite order."); 7970 SetIsTame(g,false); 7971 return infinity; 7972 fi; 7973 if k < loopcheckbound then pow := pow * g; fi; 7974 if IsIntegral(pow) then break; fi; 7975 od; 7976 fi; 7977 fi; 7978 7979 if not IsBalanced(g) then 7980 Info(InfoRCWA,3,"Order: <g> has infinite order ", 7981 "by the balancedness criterion."); 7982 SetIsTame(g,false); return infinity; 7983 fi; 7984 7985 if IsRcwaMappingOfZOrZ_piInStandardRep(g) then 7986 7987 m1 := Mod(g); pow := g; 7988 exp := [2,2,3,5,2,7,3,2,11,13,5,3,17,19,2]; 7989 for e in exp do 7990 c := Coefficients(pow); m2 := Modulus(pow); 7991 if m2 > 6 * m1 then break; fi; 7992 r := First([1..m2],i -> c[i] <> [1,0,1] and c[i]{[1,3]} = [1,1] 7993 and c[i][2] mod m2 = 0); 7994 if r <> fail then 7995 Info(InfoRCWA,3,"Order: <g> has infinite order ", 7996 "by the arithmetic progression criterion."); 7997 return infinity; 7998 fi; 7999 pow := pow^e; if IsOne(pow) then break; fi; 8000 if Loops(pow) <> [] then 8001 Info(InfoRCWA,3,"Order: <g>^",e," has loops, ", 8002 "thus <g> has infinite order."); 8003 SetIsTame(g,false); 8004 return infinity; 8005 fi; 8006 od; 8007 8008 Info(InfoRCWA,3,"Order: Looking for finite cycles ... "); 8009 8010 e := 1; l_max := 2 * Mod(g)^2; e_max := 2^Mod(g); stabiter := 0; 8011 b1 := 2^64-1; b2 := b1^2; 8012 repeat 8013 n0 := Random(-b1,b1); n := n0; l := 0; 8014 repeat 8015 n := n^g; 8016 l := l + 1; 8017 until n = n0 or AbsInt(n) > b2 or l > l_max; 8018 if n = n0 then 8019 e_old := e; e := Lcm(e,l); 8020 if e > e_old then stabiter := 0; else stabiter := stabiter + 1; fi; 8021 else break; fi; 8022 until stabiter = 64 or e > e_max; 8023 8024 if e <= e_max and stabiter = 64 then 8025 c := Reversed(CoefficientsQadic(e,2)); pow := g; 8026 for i in [2..Length(c)] do 8027 pow := pow^2; 8028 if Mod(pow) > Mod(g)^2 then break; fi; 8029 if c[i] = 1 then pow := pow * g; fi; 8030 if Mod(pow) > Mod(g)^2 then break; fi; 8031 od; 8032 if IsOne(pow) then SetIsTame(g,true); return e; fi; 8033 fi; 8034 8035 else # for rcwa permutations of rings other than Z or Z_(pi) 8036 8037 cycs := ShortCycles(g,AllResidues(Source(g),Modulus(g)), 8038 NumberOfResidues(Source(g),Modulus(g))); 8039 if cycs <> [] then 8040 e := Lcm(List(cycs,Length)); 8041 pow := g^e; 8042 if IsIntegral(pow) then SetIsTame(g,true); fi; 8043 if IsOne(pow) then SetIsTame(g,true); return e; fi; 8044 fi; 8045 8046 fi; 8047 8048 if IsRcwaMappingOfZxZ(g) then TryNextMethod(); fi; 8049 8050 if not IsRcwaMappingOfZ(g) and not IsTame(g) then 8051 Info(InfoRCWA,3,"Order: <g> is wild, thus has infinite order."); 8052 return infinity; 8053 fi; 8054 8055 Info(InfoRCWA,3,"Order: determine a respected partition <P> of <g>,"); 8056 Info(InfoRCWA,3," and compute the order <k> of the permutation"); 8057 Info(InfoRCWA,3," induced by <g> on <P> as well as the order"); 8058 Info(InfoRCWA,3," of <g>^<k>."); 8059 8060 P := RespectedPartition(g); 8061 8062 k := Order(Permutation(g,P)); 8063 gtilde := g^k; 8064 8065 if IsOne(gtilde) then return k; fi; 8066 8067 if IsRcwaMappingOfZOrZ_pi(g) then 8068 if not IsClassWiseOrderPreserving(gtilde) and IsOne(gtilde^2) 8069 then return 2*k; else return infinity; fi; 8070 fi; 8071 8072 if IsRcwaMappingOfGFqxInStandardRep(g) then 8073 e := Lcm(List(Coefficients(gtilde),c->Order(c[1]))); 8074 gtilde := gtilde^e; 8075 if IsOne(gtilde) then return k * e; fi; 8076 p := Characteristic(Source(g)); 8077 gtilde := gtilde^p; 8078 if IsOne(gtilde) then return k * e * p; fi; 8079 fi; 8080 8081 if IsRcwaMappingOfGFqxInSparseRep(g) then 8082 e := Lcm(List(Coefficients(gtilde),c->Order(c[3]))); 8083 gtilde := gtilde^e; 8084 if IsOne(gtilde) then return k * e; fi; 8085 p := Characteristic(Source(g)); 8086 gtilde := gtilde^p; 8087 if IsOne(gtilde) then return k * e * p; fi; 8088 fi; 8089 8090 if IsRcwaMappingOfZxZInStandardRep(g) then 8091 if ForAny(Coefficients(gtilde),c->Order(c[1])=infinity) then 8092 return infinity; 8093 else 8094 e := Lcm(List(Coefficients(gtilde),c->Order(c[1]))); 8095 gtilde := gtilde^e; 8096 if IsOne(gtilde) then return k * e; else return infinity; fi; 8097 fi; 8098 fi; 8099 8100 Info(InfoRCWA,3,"Order: Giving up."); 8101 TryNextMethod(); 8102 8103 end ); 8104 8105############################################################################# 8106## 8107#M Order( <g> ) . . . . . . . . . . . . . . . . . . . for elements of CT(Z) 8108## 8109InstallMethod( Order, 8110 "for elements of CT(Z) (RCWA)", true, [ IsRcwaMappingOfZ ], 5, 8111 8112 function ( g ) 8113 8114 local cycs, density, lastdensity, pow, partsbound, modbound, lngbound, n; 8115 8116 if not IsRcwaMappingOfZ(g) or not IsBijective(g) 8117 or not IsSignPreserving(g) or ValueOption("new_order") <> true 8118 then TryNextMethod(); fi; 8119 8120 if IsOne(g) then return 1; fi; 8121 if IsIntegral(g) then 8122 SetIsTame(g,true); 8123 return Lcm(List(Cycles(g,[0..Mod(g)-1]),Length)); 8124 fi; 8125 if Loops(g) <> [] then 8126 SetIsTame(g,false); return infinity; 8127 fi; 8128 8129 if not IsRcwaMappingInSparseRep(g) then g := SparseRep(g); fi; 8130 8131 n := 1; pow := g; lastdensity := 0; 8132 partsbound := 16; modbound := 32; lngbound := 16; 8133 repeat 8134 n := n + 1; 8135 pow := pow * g; 8136 if IsOne(pow) then SetIsTame(g,true); return n; fi; 8137 if Loops(pow) <> [] then SetIsTame(g,false); return infinity; fi; 8138 if Length(Coefficients(pow)) > partsbound 8139 or n mod (RootInt(Mod(g),2) + 5) = 0 8140 then 8141 cycs := ShortResidueClassCycles(g,modbound,lngbound); 8142 density := Sum(Flat(cycs),Density); 8143 if density = 1 then 8144 SetIsTame(g,true); 8145 return Lcm(List(cycs,Length)); 8146 fi; 8147 if density > lastdensity then 8148 partsbound := partsbound * 2; 8149 modbound := modbound * Maximum(PrimeSet(g)); 8150 else 8151 partsbound := 4 * Length(Coefficients(pow)); 8152 modbound := modbound * Minimum(PrimeSet(g)); 8153 fi; 8154 lngbound := lngbound * 2; 8155 lastdensity := density; 8156 fi; 8157 until false; 8158 8159 end ); 8160 8161############################################################################# 8162## 8163#S Transition matrices and transition graphs. ////////////////////////////// 8164## 8165############################################################################# 8166 8167############################################################################# 8168## 8169#M TransitionMatrix( <f>, <m> ) . for rcwa mapping and nonzero ring element 8170## 8171InstallMethod( TransitionMatrix, 8172 "for an rcwa mapping and an element<>0 of its source (RCWA)", 8173 ReturnTrue, [ IsRcwaMapping, IsRingElement ], 0, 8174 8175 function ( f, m ) 8176 8177 local T, R, mTest, Resm, ResmTest, n, i, j; 8178 8179 if IsZero(m) or not m in Source(f) then 8180 Error("usage: TransitionMatrix( <f>, <m> ),\nwhere <f> is an ", 8181 "rcwa mapping and <m> <> 0 lies in the source of <f>.\n"); 8182 fi; 8183 R := Source(f); Resm := AllResidues(R,m); 8184 mTest := Modulus(f) * Lcm(m,Divisor(f)); 8185 ResmTest := AllResidues(R,mTest); 8186 T := NullMat(Length(Resm),Length(Resm)); 8187 for n in ResmTest do 8188 i := Position(Resm,n mod m); 8189 j := Position(Resm,n^f mod m); 8190 T[i][j] := T[i][j] + 1; 8191 od; 8192 return List(T,l->l/Sum(l)); 8193 end ); 8194 8195############################################################################# 8196## 8197#M TransitionMatrix( <g> ) . for rcwa permutations of Z, single-arg. method 8198## 8199InstallMethod( TransitionMatrix, 8200 "for rcwa permutations of Z, single-argument method (RCWA)", 8201 true, [ IsRcwaMappingOfZ and IsBijective ], 0, 8202 8203 function ( g ) 8204 8205 local cls, img, pre, int, M, d, i, j; 8206 8207 if not IsRcwaMappingOfZInSparseRep(g) then g := SparseRep(g); fi; 8208 cls := List(Filtered(Coefficients(g),c->c{[3..5]}<>[1,0,1]), 8209 c->ResidueClass(c[1],c[2])); 8210 d := Length(cls); 8211 M := NullMat(d,d); 8212 for i in [1..d] do 8213 img := cls[i]^g; 8214 for j in [1..d] do 8215 int := Intersection(img,cls[j]); 8216 if int <> [] then 8217 pre := int^(g^-1); 8218 M[i][j] := Density(pre)/Density(cls[i]); 8219 fi; 8220 od; 8221 od; 8222 return M; 8223 end ); 8224 8225############################################################################# 8226## 8227#F TransitionSets( <f>, <m> ) . . . . . . . . . . . . set transition matrix 8228## 8229InstallGlobalFunction( TransitionSets, 8230 8231 function ( f, m ) 8232 8233 local M, R, res, cl, im, r, i, j; 8234 8235 R := Source(f); 8236 res := AllResidues(R,m); 8237 cl := List(res,r->ResidueClass(R,m,r)); 8238 M := []; 8239 for i in [1..Length(res)] do 8240 im := cl[i]^f; 8241 M[i] := List([1..Length(res)],j->Intersection(im,cl[j])); 8242 od; 8243 return M; 8244 end ); 8245 8246############################################################################# 8247## 8248#M TransitionGraph( <f>, <m> ) . . . . . . for rcwa mappings of Z or Z_(pi) 8249## 8250## Returns the transition graph of <f> for modulus <m> as a GRAPE graph. 8251## 8252## The vertices are labelled by 1..<m> instead of 0..<m>-1 (0 is identified 8253## with 1, etc.) because in {\GAP}, permutations cannot move 0. 8254## 8255InstallMethod( TransitionGraph, 8256 "for rcwa mappings of Z or Z_(pi) (RCWA)", 8257 true, [ IsRcwaMappingOfZOrZ_pi, IsPosInt ], 0, 8258 8259 function ( f, m ) 8260 8261 local M; 8262 8263 M := TransitionMatrix(f,m); 8264 return Graph(Group(()), [1..m], OnPoints, 8265 function(i,j) return M[i][j] <> 0; end, true); 8266 end ); 8267 8268############################################################################# 8269## 8270#M TransitionGraph( <f> ) . for rcwa mappings of Z, single-argument method 8271## 8272InstallMethod( TransitionGraph, 8273 "for rcwa mappings of Z, single-argument method (RCWA)", 8274 true, [ IsRcwaMappingOfZ ], 0, 8275 8276 function ( f ) 8277 8278 local M, m; 8279 8280 M := TransitionMatrix(f); m := Length(M); 8281 return Graph(Group(()), [1..m], OnPoints, 8282 function(i,j) return M[i][j] <> 0; end, true); 8283 end ); 8284 8285############################################################################# 8286## 8287#M OrbitsModulo( <f>, <m> ) . . . . . . . . for rcwa mappings of Z or Z_(pi) 8288## 8289InstallMethod( OrbitsModulo, 8290 "for rcwa mappings of Z or Z_(pi) (RCWA)", true, 8291 [ IsRcwaMappingOfZOrZ_pi, IsPosInt ], 0, 8292 8293 function ( f, m ) 8294 8295 local gamma, delta, C, r; 8296 8297 gamma := TransitionGraph(f,m); 8298 for r in [1..m] do RemoveSet(gamma.adjacencies[r],r); od; 8299 delta := UnderlyingGraph(gamma); 8300 C := ConnectedComponents(delta); 8301 return Set(List(C,c->List(c,r->r-1))); 8302 end ); 8303 8304############################################################################# 8305## 8306#M FactorizationOnConnectedComponents( <f>, <m> ) 8307## 8308InstallMethod( FactorizationOnConnectedComponents, 8309 "for rcwa mappings of Z or Z_(pi) (RCWA)", true, 8310 [ IsRcwaMappingOfZOrZ_pi, IsPosInt ], 0, 8311 8312 function ( f, m ) 8313 8314 local factors, c, comps, comp, coeff, m_f, m_res, r; 8315 8316 if not IsRcwaMappingStandardRep(f) then f := StandardRep(f); fi; 8317 c := Coefficients(f); 8318 comps := OrbitsModulo(f,m); 8319 m_f := Modulus(f); m_res := Lcm(m,m_f); 8320 factors := []; 8321 for comp in comps do 8322 coeff := List([1..m_res],i->[1,0,1]); 8323 for r in [0..m_res-1] do 8324 if r mod m in comp then coeff[r+1] := c[r mod m_f + 1]; fi; 8325 od; 8326 Add(factors,RcwaMapping(coeff)); 8327 od; 8328 return Set(Filtered(factors,f->not IsOne(f))); 8329 end ); 8330 8331############################################################################ 8332## 8333#M Sources( <f> ) . . . . . . . . . . . . . . . . . . . . for rcwa mappings 8334## 8335InstallMethod( Sources, 8336 "for rcwa mappings (RCWA)", true, [ IsRcwaMapping ], 0, 8337 8338 function ( f ) 8339 8340 local sources, comps, adj, res; 8341 8342 res := AllResidues(Source(f),Modulus(f)); 8343 adj := TransitionGraph(f,Modulus(f)).adjacencies; 8344 comps := List(STRONGLY_CONNECTED_COMPONENTS_DIGRAPH(adj), 8345 comp->ResidueClassUnion(Source(f),Modulus(f),res{comp})); 8346 sources := Filtered(comps,comp -> IsSubset(comp,PreImagesSet(f,comp)) 8347 and IsSubset(comp^f,comp) 8348 and comp^f <> comp); 8349 return sources; 8350 end ); 8351 8352############################################################################ 8353## 8354#M Sinks( <f> ) . . . . . . . . . . . . . . . . . . . . . for rcwa mappings 8355## 8356InstallMethod( Sinks, 8357 "for rcwa mappings (RCWA)", true, [ IsRcwaMapping ], 0, 8358 8359 function ( f ) 8360 8361 local sinks, comps, adj, res; 8362 8363 res := AllResidues(Source(f),Modulus(f)); 8364 adj := TransitionGraph(f,Modulus(f)).adjacencies; 8365 comps := List(STRONGLY_CONNECTED_COMPONENTS_DIGRAPH(adj), 8366 comp->ResidueClassUnion(Source(f),Modulus(f),res{comp})); 8367 sinks := Filtered(comps,comp -> IsSubset(PreImagesSet(f,comp),comp) 8368 and IsSubset(comp,comp^f) 8369 and comp <> comp^f); 8370 return sinks; 8371 end ); 8372 8373############################################################################ 8374## 8375#M Loops( <f> ) . . . . . . . . . . . . . . . . . . . . . for rcwa mappings 8376## 8377InstallMethod( Loops, 8378 "for rcwa mappings (RCWA)", true, [ IsRcwaMapping ], 0, 8379 8380 function ( f ) 8381 8382 local cls, cl, img, loops; 8383 8384 cls := AllResidueClassesModulo(Source(f),Modulus(f)); 8385 loops := []; 8386 for cl in cls do 8387 img := cl^f; 8388 if img <> cl and Intersection(img,cl) <> [] then Add(loops,cl); fi; 8389 od; 8390 return loops; 8391 end ); 8392 8393############################################################################ 8394## 8395#M Loops( <f> ) . . . . . for bijective rcwa mappings of Z in standard rep. 8396## 8397InstallMethod( Loops, 8398 "for bijective rcwa mappings of Z in standard rep. (RCWA)", 8399 true, [ IsRcwaMappingOfZInStandardRep and IsBijective ], 0, 8400 8401 function ( f ) 8402 8403 local c, i, r, m, r_img, m_img, loops; 8404 8405 m := Mod(f); 8406 c := Coefficients(f); 8407 loops := []; 8408 for r in [0..Mod(f)-1] do 8409 m_img := AbsInt(c[r+1][1]/c[r+1][3])*m; 8410 r_img := ((c[r+1][1]*r+c[r+1][2])/c[r+1][3]) mod m_img; 8411 if [r_img,m_img] <> [r,m] and (r_img - r) mod Gcd(m,m_img) = 0 8412 then Add(loops,ResidueClass(r,m)); fi; 8413 od; 8414 if loops <> [] then SetIsTame(f,false); fi; 8415 return loops; 8416 end ); 8417 8418############################################################################ 8419## 8420#M Loops( <f> ) . . . . . . for bijective rcwa mappings of Z in sparse rep. 8421## 8422InstallMethod( Loops, 8423 "for bijective rcwa mappings of Z in standard rep. (RCWA)", 8424 true, [ IsRcwaMappingOfZInSparseRep and IsBijective ], 0, 8425 8426 function ( f ) 8427 8428 local coeffs, modulus, c, r, m, r_img, m_img, loops; 8429 8430 modulus := Mod(f); 8431 coeffs := f!.coeffs; 8432 loops := []; 8433 for c in coeffs do 8434 r := c[1]; m := c[2]; 8435 m_img := AbsInt(c[3]*c[2]/c[5]); 8436 r_img := ((c[3]*r+c[4])/c[5]) mod m_img; 8437 if [r_img,m_img] <> [r,m] 8438 and (r_img - r) mod Gcd(m,m_img) = 0 8439 then Add(loops,ResidueClass(r,m)); fi; 8440 od; 8441 if loops <> [] then SetIsTame(f,false); fi; 8442 return loops; 8443 end ); 8444 8445############################################################################ 8446## 8447#M Loops( <f> ) . . . . . . . . . . for bijective rcwa mappings of GF(q)[x] 8448## 8449InstallMethod( Loops, 8450 "for bijective rcwa mappings of GF(q)[x] (RCWA)", true, 8451 [ IsRcwaMappingOfGFqxInStandardRep and IsBijective ], 0, 8452 8453 function ( f ) 8454 8455 local R, m, c, res, r, r_img, m_img, loops, i; 8456 8457 R := Source(f); 8458 m := Mod(f); 8459 c := Coefficients(f); 8460 res := AllResidues(R,m); 8461 loops := []; 8462 for i in [1..Length(res)] do 8463 r := res[i]; 8464 m_img := (c[i][1]/c[i][3])*m; 8465 r_img := ((c[i][1]*r+c[i][2])/c[i][3]) mod m_img; 8466 if [r_img,m_img] <> [r,m] and IsZero((r_img - r) mod Gcd(R,m,m_img)) 8467 then Add(loops,ResidueClass(R,m,r)); fi; 8468 od; 8469 if loops <> [] then SetIsTame(f,false); fi; 8470 return loops; 8471 end ); 8472 8473############################################################################# 8474## 8475#S Trajectories. /////////////////////////////////////////////////////////// 8476## 8477############################################################################# 8478 8479############################################################################# 8480## 8481#M Trajectory( <f>, <n>, <length> ) 8482## 8483InstallOtherMethod( Trajectory, 8484 "for function, start point and length (RCWA)", 8485 ReturnTrue, [ IsFunction, IsObject, IsPosInt ], 0, 8486 8487 function ( f, n, length ) 8488 8489 local l, i; 8490 8491 l := [n]; 8492 for i in [2..length] do 8493 n := f(n); 8494 Add(l,n); 8495 od; 8496 return l; 8497 end ); 8498 8499############################################################################# 8500## 8501#M Trajectory( <f>, <n>, <terminal> ) 8502## 8503InstallOtherMethod( Trajectory, 8504 "for function, start point and terminal set (RCWA)", 8505 ReturnTrue, [ IsFunction, IsObject, IsListOrCollection ], 8506 0, 8507 8508 function ( f, n, terminal ) 8509 8510 local l, i; 8511 8512 l := [n]; 8513 while not n in terminal do 8514 n := f(n); 8515 Add(l,n); 8516 od; 8517 return l; 8518 end ); 8519 8520############################################################################# 8521## 8522#M Trajectory( <f>, <n>, <halt> ) 8523## 8524InstallOtherMethod( Trajectory, 8525 "for function, start point and halting criterion (RCWA)", 8526 ReturnTrue, [ IsFunction, IsObject, IsFunction ], 0, 8527 8528 function ( f, n, halt ) 8529 8530 local l, i; 8531 8532 l := [n]; 8533 while not halt(n) do 8534 n := f(n); 8535 Add(l,n); 8536 od; 8537 return l; 8538 end ); 8539 8540############################################################################# 8541## 8542#M Trajectory( <f>, <n>, <length> ) . . . . . . . . . for rcwa mappings, (1) 8543## 8544InstallMethod( Trajectory, 8545 "for an rcwa mapping, given number of iterates (RCWA)", 8546 ReturnTrue, [ IsRcwaMapping, IsObject, IsPosInt ], 0, 8547 8548 function ( f, n, length ) 8549 8550 local seq, step, action; 8551 8552 if not (n in Source(f) or IsSubset(Source(f),n)) 8553 then TryNextMethod(); fi; 8554 action := GetOption("Action",OnPoints,IsFunction); 8555 seq := [n]; 8556 for step in [1..length-1] do 8557 n := action(n,f); 8558 Add(seq,n); 8559 od; 8560 return seq; 8561 end ); 8562 8563############################################################################# 8564## 8565#M Trajectory( <f>, <n>, <length>, <m> ) . . . . . . for rcwa mappings, (2) 8566## 8567InstallMethod( Trajectory, 8568 Concatenation("for an rcwa mapping, given number of ", 8569 "iterates (mod <m>) (RCWA)"), ReturnTrue, 8570 [ IsRcwaMapping, IsObject, IsPosInt, IsRingElement ], 0, 8571 8572 function ( f, n, length, m ) 8573 8574 local seq, step, action; 8575 8576 if not (n in Source(f) or IsSubset(Source(f),n)) or IsZero(m) 8577 then TryNextMethod(); fi; 8578 action := GetOption("Action",OnPoints,IsFunction); 8579 seq := [n mod m]; 8580 for step in [1..length-1] do 8581 n := action(n,f); 8582 Add(seq,n mod m); 8583 od; 8584 return seq; 8585 end ); 8586 8587############################################################################# 8588## 8589#M Trajectory( <f>, <n>, <terminal> ) . . . . . . . . for rcwa mappings, (3) 8590## 8591InstallMethod( Trajectory, 8592 "for an rcwa mapping, until a given set is entered (RCWA)", 8593 ReturnTrue, 8594 [ IsRcwaMapping, IsObject, IsListOrCollection ], 0, 8595 8596 function ( f, n, terminal ) 8597 8598 local seq, action; 8599 8600 if not (n in Source(f) or IsSubset(Source(f),n)) 8601 then TryNextMethod(); fi; 8602 action := GetOption("Action",OnPoints,IsFunction); 8603 seq := [n]; 8604 if IsListOrCollection(n) or not IsListOrCollection(terminal) 8605 then terminal := [terminal]; fi; 8606 while not n in terminal do 8607 n := action(n,f); 8608 Add(seq,n); 8609 od; 8610 return seq; 8611 end ); 8612 8613############################################################################# 8614## 8615#M Trajectory( <f>, <n>, <terminal>, <m> ) . . . . . for rcwa mappings, (4) 8616## 8617InstallMethod( Trajectory, 8618 Concatenation("for an rcwa mapping, until a given set i", 8619 "s entered, (mod <m>) (RCWA)"), ReturnTrue, 8620 [ IsRcwaMapping, IsObject, 8621 IsListOrCollection, IsRingElement ], 0, 8622 8623 function ( f, n, terminal, m ) 8624 8625 local seq, action; 8626 8627 if not (n in Source(f) or IsSubset(Source(f),n)) or IsZero(m) 8628 then TryNextMethod(); fi; 8629 action := GetOption("Action",OnPoints,IsFunction); 8630 seq := [n mod m]; 8631 if IsListOrCollection(n) or not IsListOrCollection(terminal) 8632 then terminal := [terminal]; fi; 8633 while not n in terminal do 8634 n := action(n,f); 8635 Add(seq,n mod m); 8636 od; 8637 return seq; 8638 end ); 8639 8640############################################################################ 8641## 8642#M Trajectory( <f>, <n>, <length>, <whichcoeffs> ) for rcwa mappings, (5) 8643#M Trajectory( <f>, <n>, <terminal>, <whichcoeffs> ) for rcwa mappings, (6) 8644## 8645InstallMethod( Trajectory, 8646 "for an rcwa mapping, coefficients (RCWA)", ReturnTrue, 8647 [ IsRcwaMapping, IsRingElement, IsObject, IsString ], 0, 8648 8649 function ( f, n, lngterm, whichcoeffs ) 8650 8651 local coeffs, triple, traj, length, terminal, 8652 c, m, d, pos, res, r, deg, R, q, x; 8653 8654 if not IsRcwaMappingStandardRep(f) then f := StandardRep(f); fi; 8655 if IsPosInt(lngterm) then length := lngterm; 8656 elif IsListOrCollection(lngterm) then terminal := lngterm; 8657 else TryNextMethod(); fi; 8658 if not n in Source(f) or not whichcoeffs in ["AllCoeffs","LastCoeffs"] 8659 then TryNextMethod(); fi; 8660 c := Coefficients(f); m := Modulus(f); 8661 traj := [n mod m]; 8662 if IsBound(length) 8663 then for pos in [2..length] do n := n^f; Add(traj,n mod m); od; 8664 else while not n in terminal do n := n^f; Add(traj,n mod m); od; fi; 8665 if IsRcwaMappingOfGFqx(f) then 8666 deg := DegreeOfLaurentPolynomial(m); 8667 R := Source(f); 8668 q := Size(CoefficientsRing(R)); 8669 x := IndeterminatesOfPolynomialRing(R)[1]; 8670 res := AllGFqPolynomialsModDegree(q,deg,x); 8671 else res := [0..m-1]; fi; 8672 triple := [1,0,1] * One(Source(f)); coeffs := [triple]; 8673 for pos in [1..Length(traj)-1] do 8674 r := Position(res,traj[pos]); 8675 triple := [ c[r][1] * triple[1], 8676 c[r][1] * triple[2] + c[r][2] * triple[3], 8677 c[r][3] * triple[3] ]; 8678 triple := triple/Gcd(triple); 8679 if whichcoeffs = "AllCoeffs" then Add(coeffs,triple); fi; 8680 od; 8681 if whichcoeffs = "AllCoeffs" then return coeffs; else return triple; fi; 8682 end ); 8683 8684############################################################################# 8685## 8686#F GluckTaylorInvariant( <l> ) . . Gluck-Taylor invariant of trajectory <l> 8687## 8688InstallGlobalFunction( GluckTaylorInvariant, 8689 8690 function ( l ) 8691 if not IsList(l) or not ForAll(l,IsInt) then return fail; fi; 8692 return Sum([1..Length(l)],i->l[i]*l[i mod Length(l) + 1])/(l*l); 8693 end ); 8694 8695############################################################################# 8696## 8697#F TraceTrajectoriesOfClasses( <f>, <S>, <maxlength> ) 8698## 8699InstallGlobalFunction( TraceTrajectoriesOfClasses, 8700 8701 function ( f, S, maxlength ) 8702 8703 local l, k, starttime, timeout; 8704 8705 l := [[S]]; k := 1; 8706 starttime := Runtime(); 8707 timeout := GetOption("timeout",infinity,IsPosInt); 8708 repeat 8709 Add(l,Flat(List(l[k],cl->AsUnionOfFewClasses(cl^f)))); 8710 k := k + 1; 8711 Info(InfoRCWA,2,"k = ",k,": ",ViewString(l[k])); 8712 until Length(l) >= maxlength or Runtime() - starttime >= timeout 8713 or l[k] in l{[1..k-1]}; 8714 return l; 8715 end ); 8716 8717############################################################################# 8718## 8719#S Probabilistic guesses concerning the behaviour of trajectories. ///////// 8720## 8721############################################################################# 8722 8723############################################################################# 8724## 8725#M GuessedDivergence( <f> ) . . . . . . . . . . . . . . . for rcwa mappings 8726## 8727InstallMethod( GuessedDivergence, 8728 "for rcwa mappings (RCWA)", true, [ IsRcwaMapping ], 0, 8729 8730 function ( f ) 8731 8732 local R, pow, m, c, M, approx, prev, facts, p, NrRes, exp, eps, prec; 8733 8734 Info(InfoWarning,1,"Warning: GuessedDivergence: no particular return ", 8735 "value is guaranteed."); 8736 if not IsRcwaMappingStandardRep(f) then f := StandardRep(f); fi; 8737 R := Source(f); 8738 prec := 10^8; eps := Float(1/prec); 8739 pow := f; exp := 1; approx := Float(0); 8740 repeat 8741 m := Modulus(pow); NrRes := Length(AllResidues(R,m)); 8742 c := Coefficients(pow); 8743 facts := List(c,t->Float(Length(AllResidues(R,t[1]))/ 8744 Length(AllResidues(R,t[3])))); 8745 Info(InfoRCWA,4,"Factors = ",facts); 8746 M := TransitionMatrix(pow,m); 8747 p := List(TransposedMat(M),l->Float(Sum(l)/NrRes)); 8748 Info(InfoRCWA,4,"p = ",p); 8749 prev := approx; 8750 approx := Product(List([1..NrRes],i->facts[i]^p[i]))^Float(1/exp); 8751 Info(InfoRCWA,2,"Approximation = ",approx); 8752 pow := pow * f; exp := exp + 1; 8753 until AbsoluteValue(approx-prev) < eps; 8754 return approx; 8755 end ); 8756 8757############################################################################# 8758## 8759#M LikelyContractionCentre( <f>, <maxn>, <bound> ) . for rcwa mappings of Z 8760## 8761InstallMethod( LikelyContractionCentre, 8762 "for rcwa mapping of Z and two positive integers (RCWA)", 8763 true, [ IsRcwaMappingOfZ, IsPosInt, IsPosInt ], 0, 8764 8765 function ( f, maxn, bound ) 8766 8767 local ReducedSetOfStartingValues, S0, S, n, n_i, i, seq; 8768 8769 ReducedSetOfStartingValues := function ( S, f, lng ) 8770 8771 local n, min, max, traj; 8772 8773 min := Minimum(S); max := Maximum(S); 8774 for n in [min..max] do 8775 if n in S then 8776 traj := Set(Trajectory(f,n,lng){[2..lng]}); 8777 if not n in traj then S := Difference(S,traj); fi; 8778 fi; 8779 od; 8780 return S; 8781 end; 8782 8783 Info(InfoWarning,1,"Warning: `LikelyContractionCentre' is highly ", 8784 "probabilistic.\nThe returned result can only be ", 8785 "regarded as a rough guess.\n", 8786 "See ?LikelyContractionCentre for more information."); 8787 if IsBijective(f) then return fail; fi; 8788 S := ReducedSetOfStartingValues([-maxn..maxn],f,8); 8789 Info(InfoRCWA,1,"#Remaining values to be examined after first ", 8790 "reduction step: ",Length(S)); 8791 S := ReducedSetOfStartingValues(S,f,64); 8792 Info(InfoRCWA,1,"#Remaining values to be examined after second ", 8793 "reduction step: ",Length(S)); 8794 S0 := []; 8795 for n in S do 8796 seq := []; n_i := n; 8797 while AbsInt(n_i) <= bound do 8798 if n_i in S0 then break; fi; 8799 if n_i in seq then 8800 S0 := Union(S0,Cycle(f,n_i)); 8801 Info(InfoRCWA,1,"|S0| = ",Length(S0)); 8802 break; 8803 fi; 8804 AddSet(seq,n_i); 8805 n_i := n_i^f; 8806 if AbsInt(n_i) > bound 8807 then Info(InfoRCWA,3,"Given bound exceeded, start value ",n); fi; 8808 od; 8809 if n >= maxn then break; fi; 8810 od; 8811 return S0; 8812 end ); 8813 8814############################################################################# 8815## 8816#S Finite cycles of an rcwa permutation. /////////////////////////////////// 8817## 8818############################################################################# 8819 8820############################################################################# 8821## 8822#M ShortCycles( <sigma>, <S>, <maxlng> ) for bij. rcwa map., set & pos. int. 8823## 8824InstallMethod( ShortCycles, 8825 Concatenation("for a bijective rcwa mapping, a set and ", 8826 "a positive integer (RCWA)"), 8827 ReturnTrue, 8828 [ IsRcwaMapping, IsListOrCollection, IsPosInt ], 0, 8829 8830 function ( sigma, S, maxlng ) 8831 8832 local cycs, absvals, minpos, i; 8833 8834 if not IsBijective(sigma) or not IsSubset(Source(sigma),S) 8835 then TryNextMethod(); fi; 8836 cycs := List(ShortOrbits(Group(sigma),S,maxlng), 8837 orb->Cycle(sigma,Minimum(orb))); 8838 if IsRcwaMappingOfZ(sigma) then 8839 SortParallel(List(cycs,cyc->AbsInt(cyc[1])),cycs); 8840 for i in [1..Length(cycs)] do 8841 if not ForAll(cycs[i],IsPosInt) then 8842 absvals := List(cycs[i],AbsInt); 8843 minpos := Position(absvals,Minimum(absvals)); 8844 cycs[i] := Concatenation(cycs[i]{[minpos..Length(cycs[i])]}, 8845 cycs[i]{[1..minpos-1]}); 8846 fi; 8847 od; 8848 fi; 8849 return cycs; 8850 end ); 8851 8852############################################################################# 8853## 8854#M ShortCycles( <sigma>, <S>, <maxlng>, <maxn> ) 8855## 8856InstallMethod( ShortCycles, 8857 Concatenation("for a bijective rcwa mapping of Z, ", 8858 "a set and two positive integers (RCWA)"), 8859 ReturnTrue, [ IsRcwaMappingOfZ, IsListOrCollection, 8860 IsPosInt, IsPosInt ], 0, 8861 8862 function ( sigma, S, maxlng, maxn ) 8863 8864 local cycs, cyc, done, min, max, lng, absvals, minpos, n, m, i, j; 8865 8866 if not IsBijective(sigma) or not ForAll(S,IsInt) 8867 then TryNextMethod(); fi; 8868 8869 min := Minimum(S); max := Maximum(S); 8870 8871 cycs := []; 8872 done := List(S,n->false); 8873 while false in done do 8874 i := Position(done,false); done[i] := true; 8875 n := S[i]; m := n; cyc := []; lng := 0; 8876 repeat 8877 Add(cyc,m); m := m^sigma; lng := lng + 1; 8878 if m >= min and m <= max then 8879 j := PositionSorted(S,m); 8880 if j <> fail then done[j] := true; fi; 8881 fi; 8882 until m = n or lng >= maxlng or AbsInt(m) > maxn; 8883 if m = n then Add(cycs,cyc); fi; 8884 od; 8885 8886 SortParallel(List(cycs,cyc->AbsInt(cyc[1])),cycs); 8887 if min < 0 then 8888 for i in [1..Length(cycs)] do 8889 if not ForAll(cycs[i],IsPosInt) then 8890 absvals := List(cycs[i],AbsInt); 8891 minpos := Position(absvals,Minimum(absvals)); 8892 cycs[i] := Concatenation(cycs[i]{[minpos..Length(cycs[i])]}, 8893 cycs[i]{[1..minpos-1]}); 8894 fi; 8895 od; 8896 fi; 8897 return cycs; 8898 end ); 8899 8900############################################################################# 8901## 8902#M ShortCycles( <f>, <maxlng> ) for rcwa mapping of Z or Z_(pi) & pos. int. 8903## 8904InstallMethod( ShortCycles, 8905 Concatenation("for an rcwa mapping of Z or Z_(pi) and ", 8906 "a positive integer (RCWA)"), 8907 ReturnTrue, [ IsRcwaMappingOfZOrZ_pi, IsPosInt ], 0, 8908 8909 function ( f, maxlng ) 8910 8911 local R, cycles, cyclesbuf, cycs, cyc, fp, pow, exp, 8912 m, min, minshift, l, i; 8913 8914 R := Source(f); cycles := []; pow := One(f); 8915 for exp in [1..maxlng] do 8916 pow := pow * f; 8917 m := Modulus(pow); 8918 fp := FixedPointsOfAffinePartialMappings(pow); 8919 cycs := List(Filtered(TransposedMat([AllResidueClassesModulo(R,m),fp]), 8920 s->IsSubset(s[1],s[2]) and not IsEmpty(s[2])), 8921 t->t[2]); 8922 cycs := List(cycs,ShallowCopy); 8923 for cyc in cycs do 8924 for i in [1..exp-1] do Add(cyc,cyc[i]^f); od; 8925 od; 8926 cycles := Concatenation(cycles,cycs); 8927 od; 8928 cycles := Filtered(cycles,cyc->Length(Set(cyc))=Length(cyc)); 8929 cyclesbuf := ShallowCopy(cycles); cycles := []; 8930 for i in [1..Length(cyclesbuf)] do 8931 if not Set(cyclesbuf[i]) in List(cyclesbuf{[1..i-1]},AsSet) then 8932 cyc := cyclesbuf[i]; l := Length(cyc); 8933 min := Minimum(cyc); minshift := l - Position(cyc,min) + 1; 8934 cyc := Permuted(cyc,SortingPerm(Concatenation([2..l],[1]))^minshift); 8935 Add(cycles,cyc); 8936 fi; 8937 od; 8938 return cycles; 8939 end ); 8940 8941############################################################################# 8942## 8943#M CycleRepresentativesAndLengths( <g>, <S> ) . . . . . . . . default method 8944## 8945InstallMethod( CycleRepresentativesAndLengths, 8946 "default method (RCWA)", 8947 ReturnTrue, [ IsRcwaMapping, IsListOrCollection ], 0, 8948 8949 function ( g, S ) 8950 8951 local replng, rem, cyc, rep, n, i, j; 8952 8953 replng := []; 8954 rem := List(S,n->n^g<>n); 8955 for i in [1..Length(S)] do 8956 if rem[i] = false then continue; fi; 8957 rep := S[i]; 8958 cyc := ComputeCycleLength(g,rep:small:=S); 8959 if not cyc.aborted then Add(replng,[rep,cyc.length]); 8960 else Add(replng,[rep,fail]); fi; 8961 for n in cyc.smallpoints do rem[PositionSorted(S,n)] := false; od; 8962 od; 8963 return replng; 8964 end ); 8965 8966############################################################################# 8967## 8968#F ComputeCycleLength( <g>, <n> ) 8969## 8970InstallGlobalFunction( ComputeCycleLength, 8971 8972 function ( g, n0 ) 8973 8974 local n, steps, max, maxpos, smallpoints, result, 8975 notify, small, abortat, aborted, quiet; 8976 8977 n := n0; steps := 0; max := n; maxpos := 1; smallpoints := [n0]; 8978 notify := ValueOption("notify"); 8979 small := ValueOption("small"); 8980 abortat := ValueOption("abortat"); 8981 quiet := ValueOption("quiet") = true; 8982 if not IsPosInt(notify) and not notify in [0,infinity] 8983 then notify := 10000; fi; 8984 aborted := false; 8985 repeat 8986 n := n^g; 8987 steps := steps + 1; 8988 if n > max then 8989 max := n; 8990 maxpos := steps; 8991 fi; 8992 if IsList(small) and n in small then Add(smallpoints,n); fi; 8993 if not quiet and not notify in [0,infinity] 8994 and steps mod notify = 0 8995 then 8996 Print("n = ",n0,": after ",steps," steps, the iterate has ", 8997 LogInt(AbsInt(n),2)+1," binary digits.\n"); 8998 fi; 8999 if IsPosInt(abortat) and steps >= abortat then 9000 aborted := true; break; 9001 fi; 9002 until n = n0; 9003 result := rec( g := g, 9004 n := n0, 9005 length := steps, 9006 maximum := max, 9007 maxpos := maxpos, 9008 aborted := aborted ); 9009 if IsList(small) then result.smallpoints := Set(smallpoints); fi; 9010 return result; 9011 end ); 9012 9013############################################################################# 9014## 9015#M ShortResidueClassCycles( <g>, <modbound>, <maxlng> ) 9016## 9017## Probably now obsolete; superseded by method below. 9018## 9019InstallMethod( ShortResidueClassCycles, 9020 "for an rcwa permutation of Z and 2 positive integers (RCWA)", 9021 ReturnTrue, [ IsRcwaMappingOfZ, IsPosInt, IsPosInt ], 0, 9022 9023 function ( g, modbound, maxlng ) 9024 9025 local cycles, cycle, cycs, lngs, lng, startpts, cycbound, 9026 cl, S, affsrc, divs, c, m, r; 9027 9028 if not IsRcwaMappingStandardRep(g) then g := StandardRep(g); fi; 9029 9030 affsrc := LargestSourcesOfAffineMappings(g); 9031 divs := Difference(DivisorsInt(modbound),[1]); 9032 9033 S := Intersection([0..modbound-1],Support(g)); 9034 cycbound := ValueOption("cycbound"); 9035 if cycbound = fail 9036 then Info(InfoRCWA,2,"ShortResidueClassCycles: option cycbound not set"); 9037 cycs := ShortCycles(g,S,maxlng); 9038 else cycs := ShortCycles(g,S,maxlng,cycbound); fi; 9039 lngs := Set(List(cycs,Length)); 9040 9041 cycles := List(AsUnionOfFewClasses(Difference(Integers,Support(g))), 9042 cl->[cl]); 9043 9044 for lng in lngs do 9045 Info(InfoRCWA,2,"ShortResidueClassCycles: checking cycle length ",lng); 9046 startpts := List(Filtered(cycs,cyc->Length(cyc)=lng),l->l[1]); 9047 for m in divs do 9048 for r in Filtered(startpts,s->s<m) do 9049 if IsSubset(startpts,[r,r+m..modbound-m+r]) and 9050 not ForAny(cycles, 9051 cyc->ForAny(cyc,cl->(r-cl!.r[1]) mod Gcd(m,cl!.m)=0)) 9052 then 9053 cycle := []; cl := ResidueClass(r,m); 9054 if m mod Mod(g) <> 0 9055 and Number(affsrc,src->Intersection(src,cl)<>[]) > 1 9056 then continue; fi; 9057 repeat 9058 Add(cycle,cl); 9059 if cl!.m mod g!.modulus <> 0 then cl := cl^g; else 9060 c := g!.coeffs[cl!.r[1] mod g!.modulus + 1]; 9061 cl := ResidueClassUnionNC(Integers,cl!.m*c[1]/c[3], 9062 [(cl!.r[1]*c[1]+c[2])/c[3]]); 9063 fi; 9064 until not IsResidueClass(cl) or cl = cycle[1] 9065 or Length(cycle) > maxlng; 9066 if cl = cycle[1] then 9067 Add(cycles,cycle); 9068 fi; 9069 fi; 9070 od; 9071 od; 9072 od; 9073 9074 return cycles; 9075 end ); 9076 9077############################################################################# 9078## 9079#M ShortResidueClassCycles( <g>, <modbound>, <maxlng> ) 9080## 9081InstallMethod( ShortResidueClassCycles, 9082 "for an rcwa permutation of Z and 2 positive integers (RCWA)", 9083 ReturnTrue, [ IsRcwaMappingOfZ, IsPosInt, IsPosInt ], 5, 9084 9085 function ( g, modbound, maxlng ) 9086 9087 local cycles, orbits; 9088 9089 orbits := ShortResidueClassOrbits(Group(g),modbound,maxlng); 9090 cycles := Set(List(orbits,orb->Cycle(g,orb[1]))); 9091 return cycles; 9092 end ); 9093 9094############################################################################# 9095## 9096#M FixedResidueClasses( <g>, <maxmod> ) 9097## 9098InstallMethod( FixedResidueClasses, 9099 "for an rcwa mapping of Z and a positive integer (RCWA)", 9100 ReturnTrue, [ IsRcwaMappingOfZ, IsPosInt ], 0, 9101 9102 function ( g, maxmod ) 9103 9104 local cls, fixed, cl, r, m; 9105 9106 cls := Concatenation(List([2..maxmod], 9107 m->AllResidueClassesModulo(Integers,m))); 9108 fixed := []; 9109 for cl in cls do 9110 r := Residue(cl); m := Modulus(cl); 9111 if ForAny([r,r+m..r+15*m],n->n^g mod m <> r) then continue; fi; 9112 if cl^g = cl then Add(fixed,cl); fi; 9113 od; 9114 return fixed; 9115 end ); 9116 9117############################################################################# 9118## 9119#S Restriction monomorphisms and induction epimorphisms. /////////////////// 9120## 9121############################################################################# 9122 9123############################################################################# 9124## 9125#M Restriction( <g>, <f> ) . . . . . . . . . . . . . . . . for rcwa mappings 9126## 9127InstallMethod( Restriction, "for rcwa mappings (RCWA)", IsIdenticalObj, 9128 [ IsRcwaMapping, IsRcwaMapping ], 0, 9129 9130 function ( g, f ) 9131 9132 local gf; 9133 9134 if not IsInjective(f) then return fail; fi; 9135 9136 gf := RestrictedPerm( RightInverse(f) * g * f, Image(f) ); 9137 9138 Assert(4,g*f=f*gf,"Restriction: Diagram does not commute.\n"); 9139 9140 if HasIsInjective(g) then SetIsInjective(gf,IsInjective(g)); fi; 9141 if HasIsSurjective(g) then SetIsSurjective(gf,IsSurjective(g)); fi; 9142 if HasIsTame(g) then SetIsTame(gf,IsTame(g)); fi; 9143 if HasOrder(g) then SetOrder(gf,Order(g)); fi; 9144 9145 return gf; 9146 end ); 9147 9148############################################################################# 9149## 9150#M Induction( <g>, <f> ) . . . . . . . . . . . . . . . . . for rcwa mappings 9151## 9152InstallMethod( Induction, "for rcwa mappings (RCWA)", IsIdenticalObj, 9153 [ IsRcwaMapping, IsRcwaMapping ], 0, 9154 9155 function ( g, f ) 9156 9157 local gf; 9158 9159 if not IsInjective(f) or not IsSubset(Image(f),MovedPoints(g)) 9160 or not IsSubset(Image(f),MovedPoints(g)^g) then return fail; fi; 9161 9162 gf := f * g * RightInverse(f); 9163 9164 Assert(4,gf*f=f*g,"Induction: Diagram does not commute.\n"); 9165 9166 if HasIsInjective(g) then SetIsInjective(gf,IsInjective(g)); fi; 9167 if HasIsSurjective(g) then SetIsSurjective(gf,IsSurjective(g)); fi; 9168 if HasIsTame(g) then SetIsTame(gf,IsTame(g)); fi; 9169 if HasOrder(g) then SetOrder(gf,Order(g)); fi; 9170 9171 return gf; 9172 end ); 9173 9174############################################################################# 9175## 9176#S Extracting roots of rcwa permutations. ////////////////////////////////// 9177## 9178############################################################################# 9179 9180############################################################################# 9181## 9182#M Root( <sigma>, <k> ) . . . . . . for an element of CT(Z) of finite order 9183## 9184InstallMethod( Root, 9185 "for an element of CT(Z) of finite order (RCWA)", 9186 ReturnTrue, [ IsRcwaMappingOfZ, IsPosInt ], 10, 9187 9188 function ( sigma, k ) 9189 9190 local root, regroot, k_reg, k_sing, order, P, remaining, cycle, l, i, j; 9191 9192 if k = 1 then return sigma; fi; 9193 if not IsClassWiseOrderPreserving(sigma) or not IsTame(sigma) 9194 or Order(sigma) = infinity 9195 or not ForAll(Factorization(sigma),IsClassTransposition) 9196 then TryNextMethod(); fi; 9197 order := Order(sigma); 9198 k_sing := Product(Filtered(Factors(k),p->order mod p = 0)); 9199 k_reg := k/k_sing; 9200 regroot := sigma^(1/k_reg mod order); 9201 if k_sing = 1 then return regroot; fi; 9202 P := RespectedPartition(regroot); 9203 remaining := ShallowCopy(P); 9204 root := One(sigma); 9205 repeat 9206 cycle := Cycle(regroot,remaining[1]); 9207 l := Length(cycle); 9208 remaining := Difference(remaining,cycle); 9209 cycle := List(cycle,cl->SplittedClass(cl,k_sing)); 9210 for i in [1..l] do 9211 for j in [1..k_sing] do 9212 if [i,j] <> [1,1] then 9213 root := root * ClassTransposition(cycle[1][1],cycle[i][j]); 9214 fi; 9215 od; 9216 od; 9217 until IsEmpty(remaining); 9218 return root; 9219 end ); 9220 9221############################################################################# 9222## 9223#M Root( <sigma>, <k> ) . . . for a cwop. rcwa mapping of Z of finite order 9224## 9225InstallMethod( Root, 9226 "for a cwop. rcwa mapping of Z of finite order (RCWA)", 9227 ReturnTrue, [ IsRcwaMappingOfZ, IsPosInt ], 0, 9228 9229 function ( sigma, k ) 9230 9231 local root, g, x; 9232 9233 if k = 1 then return sigma; fi; 9234 if IsOne(sigma) then 9235 root := Product([1..k-1],r->ClassTransposition(0,k,r,k)); 9236 SetOrder(root,k); return root; 9237 fi; 9238 if not IsClassWiseOrderPreserving(sigma) or not IsTame(sigma) 9239 or Order(sigma) = infinity 9240 then TryNextMethod(); fi; 9241 g := Product(Filtered(Factorization(sigma),IsClassTransposition)); 9242 x := RepresentativeAction(RCWA(Integers),g,sigma); 9243 root := Root(g,k)^x; 9244 return root; 9245 end ); 9246 9247############################################################################# 9248## 9249#S Factoring an rcwa permutation into class shifts, //////////////////////// 9250#S class reflections and class transpositions. ///////////////////////////// 9251## 9252############################################################################# 9253 9254############################################################################# 9255## 9256#M CTCSCRSplit( <g> ) . . . . . . . . . . . . . . for rcwa permutations of Z 9257## 9258InstallMethod( CTCSCRSplit, 9259 "for bijective rcwa mappings of Z (RCWA)", true, 9260 [ IsRcwaMappingOfZ ], 0, 9261 9262 function ( g ) 9263 9264 local coeffs, rev, reverts, revert, shifts, shift, 9265 cl, img, c, r, m, e, stdrep, listfactors; 9266 9267 if not IsBijective(g) then TryNextMethod(); fi; 9268 listfactors := ValueOption("ListFactors"); 9269 stdrep := IsRcwaMappingOfZInStandardRep(g); 9270 g := SparseRep(g); 9271 if not IsClassWiseOrderPreserving(g) then 9272 rev := ClassWiseOrderReversingOn(g); 9273 reverts := List(AsUnionOfFewClasses(rev^g), 9274 cl->SparseRep(ClassReflection(cl))); 9275 revert := Product(reverts); 9276 g := g * revert^-1; 9277 else reverts := []; revert := One(g); fi; 9278 shifts := []; 9279 coeffs := Coefficients(g); 9280 for c in coeffs do 9281 cl := ResidueClassWithFixedRep(c[2],c[1]); 9282 img := Classes(cl^g)[1]; 9283 m := img[1]; r := img[2]; 9284 e := (r - r mod m)/m; 9285 if e <> 0 then Add(shifts,SparseRep(ClassShift(r,m)^e)); fi; 9286 od; 9287 if shifts <> [] then 9288 shift := Product(shifts); 9289 else 9290 shift := One(g); 9291 fi; 9292 g := g * shift^-1; 9293 if stdrep then 9294 g := StandardRep(g); 9295 shift := StandardRep(shift); 9296 revert := StandardRep(revert); 9297 if listfactors = true then 9298 reverts := List(reverts,StandardRep); 9299 shifts := List(shifts,StandardRep); 9300 fi; 9301 fi; 9302 if listfactors <> true then 9303 return [ g, shift, revert ]; 9304 else 9305 return [ g, shifts, reverts ]; 9306 fi; 9307 end ); 9308 9309############################################################################# 9310## 9311#M FactorizationIntoCSCRCT( <g> ) . . . . . for bijective rcwa mappings of Z 9312## 9313InstallMethod( FactorizationIntoCSCRCT, 9314 "for bijective rcwa mappings of Z (RCWA)", true, 9315 [ IsRcwaMappingOfZ ], 0, 9316 9317 function ( g ) 9318 9319 local DivideBy, SaveState, RevertDirectionAndJumpBack, StateInfo, 9320 facts, gbuf, leftfacts, leftfactsbuf, rightfacts, rightfactsbuf, 9321 elm, direction, sgn, log, loop, rev, revert, affsrc, P, oldP, 9322 newP, parts, block, h, cycs, cyc, gfixP, cl, rest, c, m, r, 9323 multfacts, divfacts, p, q, Smult, Sdiv, clSmult, clSdiv, 9324 pairs, pair, diffs, largeprimes, splitpair, splittedpairs, 9325 splittedpair, d, dpos, disjoint, ctchunk, 9326 multswitches, divswitches, kmult, kdiv, i, j, k; 9327 9328 StateInfo := function ( ) 9329 Info(InfoRCWA,1,"Modulus(<g>) = ",Modulus(g), 9330 ", Multiplier(<g>) = ",Multiplier(g), 9331 ", Divisor(<g>) = ",Divisor(g)); 9332 Info(InfoRCWA,2,"MappedPartitions(<g>) = ",MappedPartitions(g)); 9333 end; 9334 9335 SaveState := function ( ) 9336 gbuf := g; 9337 leftfactsbuf := ShallowCopy(leftfacts); 9338 rightfactsbuf := ShallowCopy(rightfacts); 9339 end; 9340 9341 RevertDirectionAndJumpBack := function ( ) 9342 if direction = "from the right" 9343 then direction := "from the left"; 9344 else direction := "from the right"; fi; 9345 Info(InfoRCWA,1,"Jumping back and retrying with divisions ", 9346 direction,"."); 9347 g := gbuf; leftfacts := leftfactsbuf; rightfacts := rightfactsbuf; 9348 k[Maximum(p,q)] := k[Maximum(p,q)] + 1; 9349 end; 9350 9351 DivideBy := function ( l ) 9352 9353 local fact, prod, areCTs; 9354 9355 areCTs := ValueOption("ct") = true; 9356 if not IsList(l) then l := [l]; fi; 9357 for fact in l do # Factors in divisors list must commute. 9358 Info(InfoRCWA,1,"Dividing by ",ViewString(fact)," ",direction,"."); 9359 od; 9360 if direction = "from the right" then 9361 if areCTs 9362 then prod := Product(l); 9363 else prod := Product(Reversed(l))^-1; fi; 9364 g := g * prod; 9365 rightfacts := Concatenation(Reversed(l),rightfacts); 9366 else 9367 if areCTs 9368 then prod := Product(Reversed(l)); 9369 else prod := Product(l)^-1; fi; 9370 g := prod * g; 9371 leftfacts := Concatenation(leftfacts,l); 9372 fi; 9373 StateInfo(); 9374 Assert(4,IsBijective(RcwaMapping(ShallowCopy(Coefficients(g))))); 9375 end; 9376 9377 if not IsBijective(g) then return fail; fi; 9378 if IsOne(g) then return [g]; fi; 9379 9380 if not IsRcwaMappingStandardRep(g) then g := StandardRep(g); fi; 9381 9382 leftfacts := []; rightfacts := []; facts := []; elm := g; 9383 direction := ValueOption("Direction"); 9384 if direction <> "from the left" then direction := "from the right"; fi; 9385 multswitches := []; divswitches := []; log := []; loop := false; 9386 9387 if not IsClassWiseOrderPreserving(g) then 9388 9389 Info(InfoRCWA,1,"Making the mapping class-wise order-preserving."); 9390 9391 rev := ClassWiseOrderReversingOn(g); 9392 revert := [List(AsUnionOfFewClasses(rev ),ClassReflection), 9393 List(AsUnionOfFewClasses(rev^g),ClassReflection)]; 9394 if Length(revert[1]) <= Length(revert[2]) 9395 then g := Product(revert[1])^-1 * g; 9396 else g := g * Product(revert[2])^-1; fi; 9397 9398 else revert := [[],[]]; fi; 9399 9400 if IsIntegral(g) then 9401 9402 Info(InfoRCWA,1,"Determining largest sources of affine mappings."); 9403 9404 affsrc := Union(List(LargestSourcesOfAffineMappings(g), 9405 AsUnionOfFewClasses)); 9406 m := Modulus(g); 9407 9408 Info(InfoRCWA,1,"Computing respected partition."); 9409 9410 if ValueOption("ShortenPartition") <> false then 9411 h := PermList(List([0..m-1],i->i^g mod m + 1)); 9412 P := Set(List(affsrc,S->Intersection(S,[0..m-1]))) + 1; 9413 repeat 9414 oldP := ShallowCopy(P); newP := []; 9415 P := List(P,block->OnSets(block,h)); 9416 for i in [1..Length(P)] do 9417 if P[i] in oldP then Add(newP,P[i]); else # split 9418 parts := List([1..Length(oldP)],j->Intersection(P[i],oldP[j])); 9419 parts := Filtered(parts,block->not IsEmpty(block)); 9420 newP := Concatenation(newP,parts); 9421 fi; 9422 od; 9423 P := Set(newP); 9424 until P = oldP; 9425 P := Set(P,res->ResidueClassUnion(Integers,m,res-1)); 9426 Assert(4,Union(P)=Integers); 9427 if not ForAll(P,IsResidueClass) 9428 then P := AllResidueClassesModulo(Modulus(g)); fi; 9429 else P := AllResidueClassesModulo(Modulus(g)); fi; 9430 9431 if InfoLevel(InfoRCWA) >= 1 then 9432 Print("#I Computing induced permutation on respected partition "); 9433 View(P); Print(".\n"); 9434 fi; 9435 9436 if ValueOption("ShortenPartition") <> false 9437 then h := PermutationOpNC(g,P,OnPoints); 9438 else h := PermList(List([0..Modulus(g)-1],i->i^g mod Modulus(g) + 1)); 9439 fi; 9440 cycs := Orbits(Group(h),MovedPoints(h)); 9441 cycs := List(cycs,cyc->Cycle(h,Minimum(cyc))); 9442 for cyc in cycs do 9443 for i in [2..Length(cyc)] do 9444 Add(facts,ClassTransposition(P[cyc[1]],P[cyc[i]])); 9445 od; 9446 od; 9447 9448 Info(InfoRCWA,1,"Factoring the rest into class shifts."); 9449 9450 gfixP := g/Product(facts); # gfixP stabilizes the partition P. 9451 for cl in P do 9452 rest := RestrictedPerm(gfixP,cl); 9453 if IsOne(rest) then continue; fi; 9454 m := Modulus(rest); r := Residue(cl); 9455 c := Coefficients(rest)[r+1]; 9456 facts := Concatenation([ClassShift(r,m)^(c[2]/m)],facts); 9457 od; 9458 9459 else 9460 9461 StateInfo(); 9462 9463 repeat 9464 9465 k := ListWithIdenticalEntries(Maximum(Union(Factors(Multiplier(g)), 9466 Factors(Divisor(g)))),1); 9467 while not IsBalanced(g) do 9468 9469 p := 1; q := 1; 9470 multfacts := Set(Factors(Multiplier(g))); 9471 divfacts := Set(Factors(Divisor(g))); 9472 if not IsSubset(divfacts,multfacts) 9473 then p := Maximum(Difference(multfacts,divfacts)); fi; 9474 if not IsSubset(multfacts,divfacts) 9475 then q := Maximum(Difference(divfacts,multfacts)); fi; 9476 9477 if Maximum(p,q) < Maximum(Union(multfacts,divfacts)) 9478 then break; fi; 9479 9480 if Maximum(p,q) >= 3 then 9481 if p > q then # Additional prime p in multiplier. 9482 if p in multswitches then RevertDirectionAndJumpBack(); fi; 9483 Add(divswitches,p); SaveState(); 9484 DivideBy(PrimeSwitch(p,k[p])); 9485 else # Additional prime q in divisor. 9486 if q in divswitches then RevertDirectionAndJumpBack(); fi; 9487 Add(multswitches,q); SaveState(); 9488 DivideBy(PrimeSwitch(q,k[q])^-1); 9489 fi; 9490 elif 2 in [p,q] 9491 then DivideBy(ClassTransposition(0,2,1,4):ct); fi; 9492 9493 od; 9494 9495 if IsOne(g) then break; fi; 9496 9497 p := Maximum(Factors(Multiplier(g)*Divisor(g))); 9498 kmult := Number(Factors(Multiplier(g)),q->q=p); 9499 kdiv := Number(Factors(Divisor(g)),q->q=p); 9500 k := Maximum(kmult,kdiv); 9501 Smult := Multpk(g,p,kmult); 9502 Sdiv := Multpk(g,p,-kdiv); 9503 if direction = "from the right" 9504 then Smult := Smult^g; Sdiv := Sdiv^g; fi; 9505 9506 Info(InfoRCWA,1,"p = ",p,", kmult = ",kmult,", kdiv = ",kdiv); 9507 9508 # Search residue classes r1(m1) in Smult, r2(m2) in Sdiv 9509 # with m1/m2 = p^k. 9510 9511 clSmult := AsUnionOfFewClasses(Smult); 9512 clSdiv := AsUnionOfFewClasses(Sdiv); 9513 9514 if InfoLevel(InfoRCWA) >= 1 then 9515 if direction = "from the right" 9516 then Print("#I Images of c"); else Print("#I C"); fi; 9517 Print("lasses being multiplied by q*p^kmult:\n#I "); 9518 ViewObj(clSmult); 9519 if direction = "from the right" 9520 then Print("\n#I Images of c"); else Print("\n#I C"); fi; 9521 Print("lasses being divided by q*p^kdiv:\n#I "); 9522 ViewObj(clSdiv); Print("\n"); 9523 fi; 9524 9525 if not [p,kmult,kdiv,clSmult,clSdiv,direction] in log then 9526 9527 Add(log,[p,kmult,kdiv,clSmult,clSdiv,direction]); 9528 9529 repeat 9530 if direction = "from the right" 9531 then sgn := 1; else sgn := -1; fi; 9532 pairs := Filtered(Cartesian(clSmult,clSdiv), 9533 pair->PadicValuation(Mod(pair[1])/Mod(pair[2]),p) 9534 = sgn * k); 9535 pairs := Set(pairs); 9536 if pairs = [] then 9537 diffs := List(Cartesian(clSmult,clSdiv), 9538 pair->PadicValuation(Mod(pair[1])/Mod(pair[2]),p)); 9539 if Maximum(diffs) < sgn * k then 9540 Info(InfoRCWA,2,"Splitting classes being multiplied by ", 9541 "q*p^kmult."); 9542 clSmult := Flat(List(clSmult,cl->SplittedClass(cl,p))); 9543 fi; 9544 if Maximum(diffs) > sgn * k then 9545 Info(InfoRCWA,2,"Splitting classes being divided by ", 9546 "q*p^kdiv."); 9547 clSdiv := Flat(List(clSdiv,cl->SplittedClass(cl,p))); 9548 fi; 9549 fi; 9550 until pairs <> []; 9551 9552 Info(InfoRCWA,1,"Found ",Length(pairs)," pairs."); 9553 9554 splittedpairs := []; 9555 for i in [1..Length(pairs)] do 9556 largeprimes := List(pairs[i], 9557 cl->Filtered(Factors(Modulus(cl)),q->q>p)); 9558 largeprimes := List(largeprimes,Product); 9559 splitpair := largeprimes/Gcd(largeprimes); 9560 if 1 in splitpair then # Omit non-disjoint split. 9561 if splitpair = [1,1] then Add(splittedpairs,pairs[i]); else 9562 d := Maximum(splitpair); dpos := 3-Position(splitpair,d); 9563 if dpos = 1 then 9564 splittedpair := List(SplittedClass(pairs[i][1],d), 9565 cl->[cl,pairs[i][2]]); 9566 else 9567 splittedpair := List(SplittedClass(pairs[i][2],d), 9568 cl->[pairs[i][1],cl]); 9569 fi; 9570 splittedpairs := Concatenation(splittedpairs,splittedpair); 9571 fi; 9572 fi; 9573 od; 9574 9575 pairs := splittedpairs; 9576 Info(InfoRCWA,1,"After filtering and splitting: ", 9577 Length(pairs)," pairs."); 9578 9579 repeat 9580 disjoint := [pairs[1]]; i := 1; 9581 while i < Length(pairs) 9582 and Sum(List(Flat(disjoint),Density)) 9583 = Density(Union(Flat(disjoint))) 9584 do 9585 i := i + 1; 9586 Add(disjoint,pairs[i]); 9587 od; 9588 if Sum(List(Flat(disjoint),Density)) 9589 > Density(Union(Flat(disjoint))) 9590 then disjoint := disjoint{[1..Length(disjoint)-1]}; fi; 9591 DivideBy(List(disjoint,ClassTransposition):ct); 9592 pairs := Difference(pairs,disjoint); 9593 until pairs = []; 9594 9595 else 9596 if ValueOption("Slave") = true then 9597 Info(InfoRCWA,1,"A loop has been detected. Attempt failed."); 9598 return fail; 9599 else 9600 Info(InfoRCWA,1,"A loop has been detected. Trying to ", 9601 "factor the inverse instead."); 9602 facts := FactorizationIntoCSCRCT(elm^-1:Slave); 9603 if facts = fail then 9604 Info(InfoRCWA,1,"Factorization of the inverse failed also. ", 9605 "Giving up."); 9606 return fail; 9607 else return Reversed(List(facts,Inverse)); fi; 9608 fi; 9609 fi; 9610 9611 until IsIntegral(g); 9612 9613 facts := Concatenation(leftfacts, 9614 FactorizationIntoCSCRCT(g:Slave), 9615 rightfacts); 9616 9617 if ValueOption("ExpandPrimeSwitches") = true then 9618 facts := Flat(List(facts,FactorizationIntoCSCRCT)); 9619 fi; 9620 9621 fi; 9622 9623 if Length(revert[1]) <= Length(revert[2]) 9624 then facts := Concatenation(revert[1],facts); 9625 else facts := Concatenation(facts,revert[2]); fi; 9626 9627 facts := Filtered(facts,fact->not IsOne(fact)); 9628 9629 if ValueOption("Slave") <> true and ValueOption("NC") <> true then 9630 Info(InfoRCWA,1,"Checking the result."); 9631 if Product(facts) <> elm 9632 then Error("FactorizationIntoCSCRCT: Internal error!"); fi; 9633 fi; 9634 9635 return facts; 9636 9637 end ); 9638 9639############################################################################# 9640## 9641#M FactorizationIntoCSCRCT( <g> ) . . . . . . . . . for the identity mapping 9642## 9643InstallMethod( FactorizationIntoCSCRCT, 9644 "for the identity mapping (RCWA)", 9645 true, [ IsRcwaMapping and IsOne ], 0, one -> [ one ] ); 9646 9647############################################################################# 9648## 9649#M Factorization( <g> ) . . . for bijective rcwa mappings, into cs / cr / ct 9650## 9651InstallMethod( Factorization, 9652 "into class shifts / reflections / transpositions (RCWA)", 9653 true, [ IsRcwaMapping ], 0, FactorizationIntoCSCRCT ); 9654 9655############################################################################# 9656## 9657#F ReducingConjugatorCT3Z( <tau> ) 9658## 9659BindGlobal( "ReducingConjugatorCT3Z", 9660 9661 function ( tau ) 9662 9663 local w, ct, cls, cls4, cls6, cl, cl1, cl2, cl3, cl4; 9664 9665 w := []; 9666 cls := Union(List([2,3,4,6,8,9,12,18],AllResidueClassesModulo)); 9667 cls4 := AllResidueClassesModulo(4); 9668 cls6 := AllResidueClassesModulo(6); 9669 9670 repeat 9671 9672 repeat 9673 9674 cl := First(cls4,cl->IsSubset(cl,Support(tau))); 9675 if cl = fail then break; fi; 9676 9677 ct := ClassTransposition((Residue(cl)+1) mod 2,2,Residue(cl),4); 9678 tau := tau^ct; 9679 Add(w,ct); 9680 9681 until cl = fail; 9682 9683 repeat 9684 9685 cl := First(cls6,cl->IsSubset(cl,Support(tau))); 9686 if cl = fail then break; fi; 9687 9688 ct := ClassTransposition((Residue(cl)+1) mod 2,2,Residue(cl),6); 9689 tau := tau^ct; 9690 Add(w,ct); 9691 9692 until cl = fail; 9693 9694 cl1 := TransposedClasses(tau)[1]; cl2 := TransposedClasses(tau)[2]; 9695 9696 cl3 := First(cls,cl->Intersection(cl,Support(tau)) = []); 9697 9698 if cl3 = fail then break; fi; 9699 9700 cl4 := First(cls,cl->Intersection(cl,cl1) = [] 9701 and Intersection(cl,cl3) = [] 9702 and IsSubset(cl,cl2) and Modulus(cl) > Modulus(cl3)); 9703 9704 if cl4 = fail then break; fi; 9705 9706 ct := ClassTransposition(cl3,cl4); 9707 tau := tau^ct; 9708 Add(w,ct); 9709 9710 until cl4 = fail; 9711 9712 return [ tau, w ]; 9713 end ); 9714 9715############################################################################# 9716## 9717#M FactorizationIntoElementaryCSCRCT( <g> ) 9718## 9719InstallMethod( FactorizationIntoElementaryCSCRCT, 9720 "for elements of CT_{3}(Z) (RCWA)", true, 9721 [ IsRcwaMappingOfZ ], 0, 9722 9723 function ( g ) 9724 9725 local CT3Zgens, facts, elementaryfacts, ct, ct1, 9726 elems, elemsold, t; 9727 9728 if not IsBijective(g) then 9729 Error("usage: FactorizationIntoElementaryCSCRCT( <g> ), ", 9730 "where <g> is an rcwa permutation\n"); 9731 fi; 9732 9733 if not IsSubset([2,3],PrimeSet(g)) or not IsSignPreserving(g) 9734 then TryNextMethod(); fi; 9735 9736 CT3Zgens := List([ [0,2,1,2], [1,2,2,4], [0,2,1,4], [1,4,2,4], 9737 [0,3,1,3], [1,3,2,3], [0,3,1,9], [0,3,4,9], 9738 [0,3,7,9], [0,2,1,6], [0,3,1,6] ], 9739 ClassTransposition); 9740 9741 facts := Flat(List(Factorization(g),Factorization)); 9742 elementaryfacts := []; 9743 9744 for ct in facts do 9745 elems := [ct]; 9746 while not ForAll(elems, 9747 ct->IsSubset([2,3,4,6,8,9], 9748 List(TransposedClasses(ct),Modulus))) do 9749 elemsold := ShallowCopy(elems); 9750 elems := []; 9751 for ct1 in elemsold do 9752 t := ReducingConjugatorCT3Z(ct1); 9753 Append(elems,Concatenation(t[2],[t[1]],Reversed(t[2]))); 9754 od; 9755 od; 9756 if Product(elems) <> ct 9757 then Error("ElementaryFactorization: internal error!\n"); fi; 9758 Append(elementaryfacts,elems); 9759 od; 9760 9761 return elementaryfacts; 9762 end ); 9763 9764############################################################################# 9765## 9766#E rcwamap.gi . . . . . . . . . . . . . . . . . . . . . . . . . . ends here 9767