1############################################################################# 2## 3#W matdisp.g GAP 4 package `browse' Thomas Breuer 4## 5#Y Copyright (C) 2011, Lehrstuhl D für Mathematik, RWTH Aachen, Germany 6## 7 8 9############################################################################# 10## 11#F NCurses.BrowseDenseList( <list>, <arec> ) 12#M Browse( <list> ) 13## 14## <#GAPDoc Label="Matrix_section"> 15## <Section Label="sec:matrixdisp"> 16## <Heading>Matrix Display</Heading> 17## 18## The &GAP; library provides several <Ref Oper="Display" BookName="ref"/> 19## methods for matrices. 20## In order to cover the functionality of these methods, 21## &Browse; provides the function <Ref Func="NCurses.BrowseDenseList"/> 22## that uses the standard facilities of the function 23## <Ref Func="NCurses.BrowseGeneric"/>, i. e., 24## one can scroll in the matrix, searching and sorting are provided etc. 25## <P/> 26## The idea is to customize this function for different special cases, 27## and to install corresponding <Ref Oper="Browse"/> methods. 28## Examples are methods for matrices over finite fields and residue 29## class rings of the rational integers, 30## see <Ref Meth="Browse" Label="for a list of lists"/>. 31## <P/> 32## The code can be found in the file <F>app/matdisp.g</F> of the package. 33## 34## <ManSection> 35## <Func Name="NCurses.BrowseDenseList" Arg="list, arec"/> 36## 37## <Returns> 38## nothing. 39## </Returns> 40## 41## <Description> 42## Let <A>list</A> be a dense list whose entries are lists, 43## for example a matrix, and let <A>arec</A> be a record. 44## This function displays <A>list</A> in a window, as a two-dimensional 45## array with row and column positions as row and column labels, 46## respectively. 47## <P/> 48## The following components of <A>arec</A> are supported. 49## <List> 50## <Mark><C>header</C></Mark> 51## <Item> 52## If bound, the value must be a valid value of the <C>work.header</C> 53## component of a browse table, 54## see <Ref Func="BrowseData.IsBrowseTable"/>; 55## for example, the value can be a list of strings. 56## If this component is not bound then the browse table has no header. 57## </Item> 58## <Mark><C>convertEntry</C></Mark> 59## <Item> 60## If bound, the value must be a unary function that returns a string 61## describing its argument. 62## The default is the operation <Ref Func="String" BookName="ref"/>. 63## Another possible value is <C>NCurses.ReplaceZeroByDot</C>, which 64## returns the string <C>"."</C> if the argument is a zero element 65## in the sense of <Ref Func="IsZero" BookName="ref"/>, 66## and returns the <Ref Func="String" BookName="ref"/> value otherwise. 67## For each entry in a row of <A>list</A>, the <C>convertEntry</C> value 68## is shown in the browse table. 69## </Item> 70## <Mark><C>labelsRow</C></Mark> 71## <Item> 72## If bound, the value must be a list of row label rows for 73## <A>list</A>, as described in Section 74## <Ref Func="BrowseData.IsBrowseTable"/>. 75## The default is <C>[ [ "1" ], [ "2" ], ... ]</C>. 76## </Item> 77## <Mark><C>labelsCol</C></Mark> 78## <Item> 79## If bound, the value must be a list of column label rows for 80## <A>list</A>, as described in Section 81## <Ref Func="BrowseData.IsBrowseTable"/>. 82## The default is <C>[ [ "1", "2", ... ] ]</C>. 83## </Item> 84## </List> 85## <P/> 86## The full functionality of the function 87## <Ref Func="NCurses.BrowseGeneric"/> is available. 88## </Description> 89## </ManSection> 90## 91## <ManSection> 92## <Meth Name="Browse" Arg="list" Label="for a list of lists"/> 93## 94## <Returns> 95## nothing. 96## </Returns> 97## 98## <Description> 99## Several methods for the operation <Ref Oper="Browse"/> are installed for 100## the case that the argument is a list of lists. 101## These methods cover a default method for lists of lists and the 102## <Ref Oper="Display" BookName="ref"/> methods for matrices over 103## finite fields and residue class rings of the rational integers. 104## Note that matrices over finite prime fields, small extension fields, and 105## large extension fields are displayed differently, 106## and the same holds for the corresponding <Ref Oper="Browse"/> methods. 107## <P/> 108## <Example><![CDATA[ 109## gap> n:= [ 14, 14, 14, 14 ];; 110## gap> input:= Concatenation( n, n, n, "Q" );; # ``do nothing and quit'' 111## gap> BrowseData.SetReplay( input ); 112## gap> Browse( RandomMat( 10, 10, Integers ) ); 113## gap> BrowseData.SetReplay( input ); 114## gap> Browse( RandomMat( 10, 10, GF(3) ) ); 115## gap> BrowseData.SetReplay( input ); 116## gap> Browse( RandomMat( 10, 10, GF(4) ) ); 117## gap> BrowseData.SetReplay( input ); 118## gap> Browse( RandomMat( 10, 10, Integers mod 6 ) ); 119## gap> BrowseData.SetReplay( input ); 120## gap> Browse( RandomMat( 10, 10, GF( NextPrimeInt( 2^16 ) ) ) ); 121## gap> BrowseData.SetReplay( input ); 122## gap> Browse( RandomMat( 10, 10, GF( 2^20 ) ) ); 123## gap> BrowseData.SetReplay( false ); 124## ]]></Example> 125## </Description> 126## </ManSection> 127## </Section> 128## <#/GAPDoc> 129## 130NCurses.ReplaceZeroByDot:= function( val ) 131 if IsZero( val ) then 132 return "."; 133 else 134 return String( val ); 135 fi; 136 end; 137 138NCurses.BrowseDenseList:= function( list, arec ) 139 local m, n, r; 140 141 if IsEmpty( list ) or not ForAll( list, IsList ) then 142 TryNextMethod(); 143 fi; 144 145 m:= Length( list ); 146 n:= Maximum( List( list, Length ) ); 147 148 # Create the default table. 149 r:= rec( 150 work:= rec( 151 align:= "c", 152 153 # Avoid computing strings for all entries in advance. 154 main:= [], 155 Main:= function( t, i, j ) 156 if IsBound( list[i][j] ) then 157 return r.work.convertEntry( list[i][j] ); 158 else 159 return ""; 160 fi; 161 end, 162 m:= m, 163 n:= n, 164 165 labelsRow:= List( [ 1 .. m ], i -> [ String( i ) ] ), 166 labelsCol:= [ List( [ 1 .. n ], String ) ], 167 sepLabelsCol:= [ "", "-" ], 168 sepLabelsRow:= [ "", " |" ], 169 sepCol:= Concatenation( List( [ 1 .. n ], x -> " " ), [ "" ] ), 170 SpecialGrid:= BrowseData.SpecialGridLineDrawPlus, 171 ), 172 ); 173 174 # Customize the browse table. 175 if IsBound( arec.header ) then 176 r.work.header:= arec.header; 177 fi; 178 if IsBound( arec.labelsRow ) then 179 r.work.labelsRow:= arec.labelsRow; 180 fi; 181 if IsBound( arec.labelsCol ) then 182 r.work.labelsCol:= arec.labelsCol; 183 fi; 184 if IsBound( arec.convertEntry ) then 185 r.work.convertEntry:= arec.convertEntry; 186 else 187 r.work.convertEntry:= String; 188#T support a user default 189 fi; 190 191 NCurses.BrowseGeneric( r ); 192 end; 193 194 195########################################################################## 196## 197#M Browse( <list> ) 198## 199## The default just shows row and column labels. 200## The table has no header, and `String' is used to convert entries. 201## 202InstallMethod( Browse, 203 [ "IsDenseList" ], 204 function( list ) 205 NCurses.BrowseDenseList( list, rec() ); 206 end ); 207 208 209########################################################################## 210## 211#M Browse( <ffe-mat> ) 212## 213## This method corresponds to the `Display' method from `lib/matrix.gi' 214## that is installed with the condition "IsFFECollColl and IsMatrix". 215## 216InstallMethod( Browse, 217 [ "IsFFECollColl and IsMatrix" ], 218 function( m ) 219 local deg, chr, q, z; 220 221 if Length( m[1] ) = 0 then 222 TryNextMethod(); 223 fi; 224 225 if IsZmodnZObj( m[1][1] ) then 226 NCurses.BrowseDenseList( List( m, r -> List( r, i -> i![1] ) ), 227 rec( header:= [ Concatenation( "matrix over Integers mod ", 228 String( Characteristic( m[1][1] ) ) ), 229 "" ], 230 convertEntry:= NCurses.ReplaceZeroByDot, 231 ) ); 232 else 233 # get the degree and characteristic 234 deg:= Lcm( List( m, DegreeFFE ) ); 235 chr:= Characteristic( m[1][1] ); 236 237 if deg = 1 then 238 # if it is a finite prime field, use integers for display 239 NCurses.BrowseDenseList( m, 240 rec( header:= [ Concatenation( "matrix over prime field GF(", 241 String( chr ), ")" ), "" ], 242 convertEntry:= function( val ) 243 val:= IntFFE( val ); 244 if val = 0 then 245 return "."; 246 else 247 return String( val ); 248 fi; 249 end, 250 ) ); 251 else 252 # if it is a finite extension field, use mixed integers/z notation 253 q:= chr^deg; 254 z:= Z(q); 255 256 NCurses.BrowseDenseList( m, 257 rec( header:= [ Concatenation( "finite field matrix, z = Z(", 258 String( q ), ")" ), "" ], 259 convertEntry:= function( val ) 260 if DegreeFFE( val ) = 1 then 261 val:= IntFFE( val ); 262 if val = 0 then 263 return "."; 264 else 265 return String( val ); 266 fi; 267 else 268 return Concatenation( "z^", String( LogFFE( val, z ) ) ); 269 fi; 270 end, 271 ) ); 272 fi; 273 fi; 274 end ); 275 276 277########################################################################## 278## 279#M Browse( <ZmodnZ-mat> ) 280## 281## This method corresponds to the `Display' method from `lib/matrix.gi' 282## that is installed with the condition 283## "IsZmodnZObjNonprimeCollColl and IsMatrix". 284## 285InstallMethod( Browse, 286 [ "IsZmodnZObjNonprimeCollColl and IsMatrix" ], 287 function( m ) 288 local deg, chr, q, z; 289 290 if Length( m[1] ) = 0 then 291 TryNextMethod(); 292 fi; 293 294 NCurses.BrowseDenseList( List( m, r -> List( r, i -> i![1] ) ), 295 rec( header:= [ Concatenation( "matrix over Integers mod ", 296 String( Characteristic( m[1][1] ) ) ), 297 "" ], 298 convertEntry:= NCurses.ReplaceZeroByDot, 299 ) ); 300 end ); 301 302 303########################################################################## 304## 305#M Browse( <ffe-mat> ) 306## 307## This method corresponds to the `Display' method from `lib/ffeconway.gi' 308## that is installed with the condition "IsFFECollColl and IsMatrix". 309## 310InstallMethod( Browse, 311 [ "IsFFECollColl and IsMatrix" ], 10, # prefer this to existing method 312 function(m) 313 local deg, chr; 314 315 if Length( m ) = 0 or Length( m[1] ) = 0 then 316 TryNextMethod(); 317 fi; 318 319 deg:= Lcm( List( m, DegreeFFE ) ); 320 chr:= Characteristic( m[1][1] ); 321 if deg = 1 or chr^deg <= MAXSIZE_GF_INTERNAL then 322 TryNextMethod(); 323 fi; 324 325 NCurses.BrowseDenseList( m, 326 rec( header:= [ Concatenation( "finite field matrix, z = Z(", 327 String( chr ), ", ", String( deg ), 328 "); z2 = z^2, etc." ), "" ], 329 convertEntry:= function( val ) 330 local s, y, j, a; 331 332 if IsZero( val ) then 333 return "."; 334 else 335 s:= ""; 336 y:= FFECONWAY.WriteOverLargerField( val, deg ); 337 for j in [ 0 .. deg-1 ] do 338 a:= IntFFE( y![1][j+1] ); 339 if a <> 0 then 340 if Length( s ) <> 0 then 341 Append( s, "+" ); 342 fi; 343 if a <> 1 then 344 Append( s, String( a ) ); 345 fi; 346 if j <> 0 then 347 Append( s, "z" ); 348 if j <> 1 then 349 Append( s, String( j ) ); 350 fi; 351 fi; 352 fi; 353 od; 354 return s; 355 fi; 356 end ) ); 357 end ); 358 359 360############################################################################# 361## 362#E 363 364