@@ -1241,21 +1241,24 @@ end );
12411241# #
12421242# F ShortestVectors( <mat>, <bound> [, \"positive\" ] )
12431243# #
1244- InstallGlobalFunction( ShortestVectors, function ( arg )
1244+ InstallGlobalFunction( ShortestVectors, function ( a, m, arg... )
12451245 local
12461246 # variables
1247- n, checkpositiv, a, llg, nullv, m, c, con , b, v,
1247+ n, positiveOnly, llg, zeroCoeffs, c, continueSearch , b, v, i, j ,
12481248 # procedures
1249- srt, vschr ;
1249+ search, emitVector ;
12501250
1251- # search for shortest vectors
1252- srt := function ( d, dam )
1253- local i, j, x, k, k1, q;
1251+ # Enumerate coefficient vectors recursively in the LLL-reduced basis,
1252+ # starting near the nearest integer to keep the search tree small.
1253+ search := function ( d, norm )
1254+ local i, j, x, k, nextnorm, q;
12541255 if d = 0 then
1255- if v = nullv then
1256- con := false ;
1256+ # Once the zero coefficient vector is reached, the remaining branch
1257+ # would only enumerate the already covered opposite vectors.
1258+ if v = zeroCoeffs then
1259+ continueSearch := false ;
12571260 else
1258- vschr( dam );
1261+ emitVector( norm );
12591262 fi ;
12601263 else
12611264 x := 0 ;
@@ -1267,27 +1270,27 @@ InstallGlobalFunction( ShortestVectors, function( arg )
12671270 i := i - SignInt( x );
12681271 fi ;
12691272 k := i + x;
1270- q := ( m + 1 / 1000 - dam ) / llg.B[ d] ;
1273+ q := ( m + 1 / 1000 - norm ) / llg.B[ d] ;
12711274 if k * k < q then
12721275 repeat
12731276 i := i + 1 ;
12741277 k := k + 1 ;
12751278 until k * k >= q and k > 0 ;
12761279 i := i - 1 ;
12771280 k := k - 1 ;
1278- while k * k < q and con do
1281+ while k * k < q and continueSearch do
12791282 v[ d] := i;
1280- k1 := llg.B[ d] * k * k + dam ;
1281- srt ( d- 1 , k1 );
1283+ nextnorm := llg.B[ d] * k * k + norm ;
1284+ search ( d- 1 , nextnorm );
12821285 i := i - 1 ;
12831286 k := k - 1 ;
12841287 od ;
12851288 fi ;
12861289 fi ;
12871290 end ;
12881291
1289- # output of vector
1290- vschr := function ( dam )
1292+ # Convert coefficients back to the original basis before storing them.
1293+ emitVector := function ( norm )
12911294 local newvec, i, j, w, haspos, hasneg;
12921295 newvec := [] ;
12931296 haspos := false ;
@@ -1304,55 +1307,55 @@ InstallGlobalFunction( ShortestVectors, function( arg )
13041307 fi ;
13051308 newvec[ i] := w;
13061309 od ;
1307- if checkpositiv then
1310+ if positiveOnly then
13081311 if haspos and hasneg then
13091312 return ;
13101313 elif hasneg then
13111314 newvec := - newvec;
13121315 fi ;
13131316 fi ;
13141317 Add(c.vectors, newvec);
1315- Add(c.norms, dam );
1318+ Add(c.norms, norm );
13161319 end ;
13171320
13181321 # main program
13191322 # check input
1320- if not IsBound ( arg[ 1 ] )
1321- or not IsList( arg[ 1 ] ) or not IsList( arg[ 1 ][ 1 ] ) then
1322- Error ( " first argument must be Gram matrix\n " ,
1323+ if not IsMatrixOrMatrixObj( a ) or NrRows( a ) <> NrCols( a ) then
1324+ Error ( " first argument must be a square Gram matrix\n " ,
13231325 " usage: ShortestVectors( <mat>, <integer> [,<\" positive\" >] )" );
1324- elif not IsBound ( arg [ 2 ] ) or not IsInt( arg [ 2 ] ) then
1325- Error ( " second argument must be integer\n " ,
1326+ elif not IsInt( m ) or m < 0 then
1327+ Error ( " second argument must be a nonnegative integer\n " ,
13261328 " usage: ShortestVectors( <mat>, <integer> [,<\" positive\" >] )" );
1327- elif IsBound ( arg[ 3 ] ) then
1328- if IsString( arg[ 3 ] ) then
1329- if arg[ 3 ] = " positive" then
1330- checkpositiv := true ;
1331- else
1332- checkpositiv := false ;
1333- fi ;
1329+ elif IsBound ( arg[ 1 ] ) then
1330+ if arg[ 1 ] = " positive" then
1331+ positiveOnly := true ;
13341332 else
1335- Error ( " third argument must be string \n " ,
1333+ Error ( " third argument, if given, must be \" positive \" \n" ,
13361334 " usage: ShortestVectors( <mat>, <integer> [,<\" positive\" >] )" );
13371335 fi ;
13381336 else
1339- checkpositiv := false ;
1337+ positiveOnly := false ;
13401338 fi ;
13411339
1342- a := arg[ 1 ] ;
1343- m := arg[ 2 ] ;
1344- n := Length( a );
1345- b := List( a, ShallowCopy );
1340+ if not IsSymmetricMatrix(a) then
1341+ Error ( " first argument must be a symmetric Gram matrix\n " ,
1342+ " usage: ShortestVectors( <mat>, <integer> [,<\" positive\" >] )" );
1343+ fi ;
1344+ n := NrRows( a );
1345+ b := MutableCopyMatrix( a );
13461346 c := rec ( vectors:= [] , norms:= [] );
13471347 v := ListWithIdenticalEntries( n, 0 );
1348- nullv := ListWithIdenticalEntries( n, 0 );
1348+ zeroCoeffs := ListWithIdenticalEntries( n, 0 );
13491349
13501350 llg:= LLLReducedGramMat( b );
1351- # T here check that the matrix is really regular
1352- # T (empty relations component)
1351+ if Length( llg.relations ) <> 0 then
1352+ Error ( " first argument must be a regular Gram matrix\n " ,
1353+ " usage: ShortestVectors( <mat>, <integer> [,<\" positive\" >] )" );
1354+ fi ;
13531355
1354- con := true ;
1355- srt( n, 0 );
1356+ # The small offset avoids missing vectors on the exact norm boundary.
1357+ continueSearch := true ;
1358+ search( n, 0 );
13561359
13571360 Info ( InfoZLattice, 2 ,
13581361 " ShortestVectors: " , Length( c.vectors ), " vectors found" );
@@ -1703,14 +1706,14 @@ l := deca( l-1 );
17031706 Error( " first argument must be symmetric Gram matrix\n " ,
17041707 " usage : Orthog... ( < gram-matrix > \n " ,
17051708 " [, <\" positive\" > ] [, < integer > ] )" );
1706- elif Length ( arg[ 1 ] ) <> Length ( arg[ 1 ] [1 ] ) then
1709+ elif NrRows ( arg[ 1 ] ) <> NrCols ( arg[ 1 ] ) then
17071710 Error( " Gram matrix must be quadratic\n " ,
17081711 " usage : Orthog... ( < gram-matrix >\n " ,
17091712 " [, <\" positive\" > ] [, < integer > ] )" );
17101713 fi ;
17111714 g := List( arg[ 1 ] , ShallowCopy );
17121715 checkdim := false ;
1713- chpo := " xxx " ;
1716+ chpo := fail ;
17141717 if IsBound ( arg[ 2 ] ) then
17151718 if IsString( arg[ 2 ] ) then
17161719 chpo := arg[ 2 ] ;
@@ -1755,7 +1758,11 @@ l := deca( l-1 );
17551758 invg := Symmatinv( g );
17561759 m := invg.enuminator;
17571760 invg := invg.inverse;
1758- x := ShortestVectors( invg, m, chpo );
1761+ if chpo = " positive" then
1762+ x := ShortestVectors( invg, m, chpo );
1763+ else
1764+ x := ShortestVectors( invg, m );
1765+ fi ;
17591766 t := Length(x.vectors);
17601767 for i in [ 1 .. t] do
17611768 x.vectors[ i][ n+ 1 ] := x.norms[ i] ;
0 commit comments