home *** CD-ROM | disk | FTP | other *** search
/ Math Solutions 1995 October / Math_Solutions_CD-ROM_Walnut_Creek_October_1995.iso / pc / mac / discrete / lib / vecspace.g < prev   
Encoding:
Text File  |  1993-05-05  |  22.4 KB  |  787 lines

  1. #############################################################################
  2. ##
  3. #A  vecspace.g                  GAP library                    J\"urgen Mnich
  4. ##
  5. #A  @(#)$Id: vecspace.g,v 3.10 1992/12/16 19:47:27 martin Rel $
  6. ##
  7. #Y  Copyright 1990-1992,  Lehrstuhl D fuer Mathematik,  RWTH Aachen,  Germany
  8. ##
  9. ##  This file contains all polymorph functions for vector spaces.
  10. ##
  11. ##  $Log: vecspace.g,v $
  12. #H  Revision 3.10  1992/12/16  19:47:27  martin
  13. #H  replaced quoted record names with escaped ones
  14. #H
  15. #H  Revision 3.9  1992/12/02  08:16:20  fceller
  16. #H  added 'VectorSpaceOps.Random'
  17. #H
  18. #H  Revision 3.8  1992/05/21  15:33:15  martin
  19. #H  added 'NormedVector'
  20. #H
  21. #H  Revision 3.7  1992/04/07  16:15:32  jmnich
  22. #H  adapted to changes in the finite field module
  23. #H
  24. #H  Revision 3.6  1992/03/17  12:31:20  jmnich
  25. #H  minor style changes, more bug fixes
  26. #H
  27. #H  Revision 3.5  1992/02/29  13:25:11  jmnich
  28. #H  general library review, some bug fixes
  29. #H
  30. #H  Revision 3.4  1992/01/30  12:30:46  martin
  31. #H  changed 'Order' to take two arguments, group and element
  32. #H
  33. #H  Revision 3.3  1992/01/07  12:22:55  jmnich
  34. #H  changed a lot
  35. #H
  36. #H  Revision 3.2  1991/09/24  14:41:43  fceller
  37. #H  'Coefficients' (internal) is now 'CoefficientsInt'.
  38. #H
  39. #H  Revision 3.1  1991/09/24  14:24:59  fceller
  40. #H  Initial Release under RCS
  41. #H
  42. ##
  43.  
  44.  
  45. #############################################################################
  46. ##
  47. #F  InfoVectorSpace1(...) . . . . . . . . . . . . . . . . package information
  48. #F  InfoVectorSpace2(...) . . . . . . . . . . . . . package debug information
  49. ##
  50. if not IsBound( InfoVectorSpace1 )  then  InfoVectorSpace1 := Ignore;  fi;
  51. if not IsBound( InfoVectorSpace2 )  then  InfoVectorSpace2 := Ignore;  fi;
  52.  
  53.  
  54. #############################################################################
  55. ##
  56. #F  VectorSpace( <generators>, <field>[, <zero>] )  . . create a vector space
  57. ##
  58. ##  This  is the basic function to create a vector space as a \GAP object. If
  59. ##  the  given  generators  are  in fact \GAP vectors the job will be left to
  60. ##  'RowSpace'.
  61. ##
  62. VectorSpace := function( arg )
  63.     local   gens, v, zero;
  64.  
  65.     # perform typecheck on the arguments
  66.  
  67.     if Length( arg ) < 2 or Length( arg ) > 3
  68.       or not IsList( arg[1] ) or not IsField( arg[2] ) then
  69.         Error( "usage: VectorSpace( <generators>, <field>[, <zero>] )" );
  70.     fi;
  71.  
  72.     # extract zero element from arguments
  73.  
  74.     if Length( arg ) = 3 then   zero := arg[3];
  75.     elif arg[1] <> [] then      zero := 0 * arg[1][1];
  76.     else
  77.         Error( "sorry, need at least one element" );
  78.     fi;
  79.  
  80.     # Check if the given arguments describe a row space.
  81.     # A row space, by definition, is a vector space whose generators are
  82.     # \GAP vectors which all have entries lying in the field of the
  83.     # vector space.
  84.  
  85.     if IsVector( zero )
  86.       and ForAll( arg[1], IsVector )
  87.       and ForAll( arg[1], x -> ForAll( x, y -> y in arg[2] ) ) then
  88.         return RowSpace( arg[1], arg[2], zero );
  89.     fi;
  90.  
  91.     # this will be a general vector space, so set up its generators
  92.  
  93.     gens := [];
  94.     for v in arg[1] do
  95.         if v <> zero then  Add( gens, v );  fi;
  96.     od;
  97.  
  98.     # create the vector space record
  99.  
  100.     return rec(
  101.         generators    := gens,
  102.         field         := arg[2],
  103.         zero          := zero,
  104.         isDomain      := true,
  105.         isVectorSpace := true,
  106.         isFinite      := IsFinite( arg[2] ) or gens = [],
  107.         operations    := VectorSpaceOps
  108.     );
  109. end;
  110.  
  111.  
  112. #############################################################################
  113. ##
  114. #F  IsVectorSpace( <obj> )  . . . . . . . test if an object is a vector space
  115. ##
  116. IsVectorSpace := function( obj )
  117.     return  IsRec( obj )
  118.         and IsBound( obj.isVectorSpace ) and obj.isVectorSpace;
  119. end;
  120.  
  121.  
  122. #############################################################################
  123. ##
  124. #V  VectorSpaceOps  . . . . . . . . . . . operations record for vector spaces
  125. ##
  126. VectorSpaceOps := ShallowCopy( DomainOps );
  127.  
  128.  
  129. #############################################################################
  130. ##
  131. #F  VectorSpaceOps.\=( <V>, <W> )  . . . test if two vector spaces are equal
  132. ##
  133. ##  Two vector spaces are considered to be equal if they are written over the
  134. ##  same field and if each of them contains the generators of the other.
  135. ##
  136. VectorSpaceOps.\= := function( V, W )
  137.     local   iseq;
  138.  
  139.     if IsVectorSpace( V )  and IsVectorSpace( W )  then
  140.         iseq := V.field = W.field
  141.                 and ForAll( V.generators, x -> x in W )
  142.                 and ForAll( W.generators, x -> x in V );
  143.     else
  144.         iseq := DomainOps.\=( V, W );
  145.     fi;
  146.     return iseq;
  147. end;
  148.  
  149.  
  150. #############################################################################
  151. ##
  152. #F  VectorSpaceOps.\<( <V>, <W> )  . . . . . .  test if <V> is less than <W>
  153. ##
  154. ##  As for vector spaces in general  there  is (so far) no way to determine a
  155. ##  canonical  Base  (in  this  module)  the decision is made as proposed for
  156. ##  domains in general if the vector spaces have the same field.
  157. ##
  158. VectorSpaceOps.\< := function( V, W )
  159.     local   isless;
  160.  
  161.     if IsVectorSpace( V )  and IsVectorSpace( W )  then
  162.         if V.field = W.field then
  163.             isless := DomainOps.\<( V, W );
  164.         else
  165.             isless := V.field < W.field;
  166.         fi;
  167.     else
  168.         isless := DomainOps.\<( V, W );
  169.     fi;
  170.     return isless;
  171. end;
  172.  
  173.  
  174. #############################################################################
  175. ##
  176. #F  VectorSpaceOps.Print( <V> ) . . . . . . . . . . . .  print a vector space
  177. ##
  178. VectorSpaceOps.Print := function( V )
  179.     if IsBound( V.name ) then
  180.         Print( V.name );
  181.     elif V.generators = [] then
  182.         Print( "VectorSpace( [  ], ", V.field, ", ", V.zero, " )" );
  183.     else
  184.         Print( "VectorSpace( ", V.generators, ", ", V.field, " )" );
  185.     fi;
  186. end;
  187.  
  188.  
  189. #############################################################################
  190. ##
  191. #F  VectorSpaceOps.IsFinite( <V> )  . . . .  test if a vector space is finite
  192. ##
  193. VectorSpaceOps.IsFinite := function( V )
  194.     return IsFinite( V.field ) or V.generators = [];
  195. end;
  196.  
  197.  
  198. #############################################################################
  199. ##
  200. #F  VectorSpaceOps.Size( <V> )  . . . . . . . . . . .  size of a vector space
  201. ##
  202. VectorSpaceOps.Size := function( V )
  203.     if V.generators = [] then
  204.         return 1;
  205.     elif IsFinite( V.field ) then
  206.         return Size( V.field ) ^ Dimension( V );
  207.     else
  208.         return "infinity";
  209.     fi;
  210. end;
  211.  
  212.  
  213. #############################################################################
  214. ##
  215. #F  VectorSpaceOps.Elements( <V> )  . . . . . . .  elements of a vector space
  216. ##
  217. VectorSpaceOps.Elements := function( V )
  218.     local list, new, len, gen, ord, pow, tmp, i;
  219.  
  220.     if V.generators = [] then  return [ V.zero ];  fi;
  221.  
  222.     if not IsFinite( V.field ) then
  223.         Error( "sorry, vector space is infinite" );
  224.     fi;
  225.  
  226.     # <V> is written over a finite field, so built all linear combinations
  227.     # of its generators.
  228.  
  229.     list := [ V.zero ];
  230.     ord  := Order( V.field, V.field.root );
  231.     for gen in V.generators do
  232.         if not gen in list then
  233.             new := [];
  234.             len := Length( list );
  235.             for pow in [1..ord] do
  236.                 tmp := ShallowCopy( list );
  237.                 for i in [1..len] do  tmp[i] := tmp[i] + gen;  od;
  238.                 UniteSet( new, tmp );
  239.                 gen := V.field.root * gen;
  240.             od;
  241.             UniteSet( list, new );
  242.         fi;
  243.     od;
  244.     return list;
  245. end;
  246.  
  247.  
  248. #############################################################################
  249. ##
  250. #F  VectorSpaceOps.Random( <V> )  . . . . . . . . . . . . . . . random vector
  251. ##
  252. VectorSpaceOps.Random:=function(V)
  253.     local   f,  i,  r,  v;
  254.  
  255.     f := V.field;
  256.     r := V.zero;
  257.     for v  in Base(V)  do
  258.         r := r + v * Random(f);
  259.     od;
  260.     return r;
  261.  
  262. end;
  263.  
  264.  
  265. #############################################################################
  266. ##
  267. #F  VectorSpaceOps.Intersection( <V>, <W> ) . . intersection of vector spaces
  268. ##
  269. VectorSpaceOps.Intersection := function( V, W )
  270.     local base, olist, list, new, len, gen, ord, pow, tmp, i;
  271.  
  272.     if V.zero <> W.zero or V.field <> W.field then
  273.         Error( "sorry, vector spaces are incompatible" );
  274.     fi;
  275.  
  276.     if V.generators = [] or W.generators = [] then
  277.         return VectorSpace( [], V.field, V.zero );
  278.     fi;
  279.  
  280.     if not IsFinite( V ) and not IsFinite( W ) then
  281.         Error( "sorry, vector spaces are infinite" );
  282.     fi;
  283.  
  284.     olist := Intersection( Elements( V ), Elements( W ) );
  285.     base  := [];
  286.     list  := [ V.zero ];
  287.     olist := Difference( olist, list );
  288.     ord   := Order( V.field, V.field.root );
  289.     while olist <> [] do
  290.         gen := olist[1];
  291.         Add( base, gen );
  292.         new := [];
  293.         len := Length( list );
  294.         if Length( olist ) > ord * len then
  295.             for pow in [1..ord] do
  296.                 tmp := ShallowCopy( list );
  297.                 for i in [1..len] do  tmp[i] := tmp[i] + gen;  od;
  298.                 UniteSet( new, tmp );
  299.                 gen := V.field.root * gen;
  300.             od;
  301.             SubtractSet( olist, new );
  302.             UniteSet( list, new );
  303.         else
  304.             olist := [];
  305.         fi;
  306.     od;
  307.     return VectorSpace( base, V.field. V.zero );
  308. end;
  309.  
  310.  
  311. #############################################################################
  312. ##
  313. #F  VectorSpaceOps.IsSubspace( <V>, <W> ) . .  test if <W> is a subspace of <V>
  314. ##
  315. VectorSpaceOps.IsSubspace := function( V, W )
  316.     if IsBound( W.base )  then
  317.         return ForAll( W.base, x -> x in V );
  318.     else
  319.         return ForAll( W.generators, x -> x in V );
  320.     fi;
  321. end;
  322.  
  323.  
  324. #############################################################################
  325. ##
  326. #F  IsSubspace( <V>, <W> )  . . . . . . . .  test if <W> is a subspace of <V>
  327. ##
  328. IsSubspace := function( V, W )
  329.     local   issub;
  330.  
  331.     if not IsVectorSpace( V )  then
  332.         Error( "usage: IsSubspace( <V>, <W> )" );
  333.     else
  334.         issub := V.operations.IsSubspace( V, W );
  335.     fi;
  336.     return issub;
  337. end;
  338.  
  339.  
  340. #############################################################################
  341. ##
  342. #F  VectorSpaceOps.Base( <V> )  . . . . . . . . . . .  base of a vector space
  343. ##
  344. ##  This function computes a base for a given vector space. However, although
  345. ##  it is computed, it is no canonical base, for it depends on the generating
  346. ##  vectors.
  347. ##
  348. VectorSpaceOps.Base := function( V )
  349.     local base, list, new, len, gen, ord, pow, tmp, i, j;
  350.  
  351.     if V.generators = [] then  return [];  fi;
  352.  
  353.     if not IsFinite( V ) then
  354.         Error( "sorry, vector space is infinite" );
  355.     fi;
  356.  
  357.     base := [];
  358.     list := [ V.zero ];
  359.     ord  := Order( V.field, V.field.root );
  360.     for j in [1..Length( V.generators )-1] do
  361.         gen := V.generators[j];
  362.         if not gen in list then
  363.             Add( base, gen );
  364.             new := [];
  365.             len := Length( list );
  366.             for pow in [1..ord] do
  367.                 tmp := ShallowCopy( list );
  368.                 for i in [1..len] do  tmp[i] := tmp[i] + gen;  od;
  369.                 UniteSet( new, tmp );
  370.                 gen := V.field.root * gen;
  371.             od;
  372.             UniteSet( list, new );
  373.         fi;
  374.     od;
  375.  
  376.     gen := V.generators[Length( V.generators )];
  377.     if not gen in list then
  378.         Add( base, gen );
  379.     fi;
  380.  
  381.     return base;
  382. end;
  383.  
  384.  
  385. #############################################################################
  386. ##
  387. #F  Base( <object> )  . . . . . . . . . . . . . . . . . . . base of an object
  388. ##
  389. ##  Determines  a base of an object by either returning a corresponding entry
  390. ##  in  the  domain record  or  by  calculating it, using the function in the
  391. ##  operations  record.  In the latter case the record field 'isComputedBase'
  392. ##  is set to (possibly) indicate special properties of the base.
  393. ##
  394. Base := function( obj )
  395.     local   base;
  396.  
  397.     if IsDomain( obj ) and IsBound( obj.base ) then
  398.         base := obj.base;
  399.     elif IsDomain( obj )  and IsBound( obj.operations.Base ) then
  400.         obj.base := obj.operations.Base( obj );
  401.         obj.isComputedBase := true;
  402.         base := obj.base;
  403.     else
  404.         Error( "sorry, can't compute a base for <object>" );
  405.     fi;
  406.     return base;
  407. end;
  408.  
  409.  
  410. #############################################################################
  411. ##
  412. #F  VectorSpaceOps.AddBase( <V>, <base> ) . . add base to vector space record
  413. ##
  414. ##  Adds a user calculated base to a vector space record. This will reset the
  415. ##  flag   'isComputedBase'  and  discard  the  information  record  for  the
  416. ##  vector space.
  417. ##
  418. VectorSpaceOps.AddBase := function( V, base )
  419.     V.base := base;
  420.     V.isComputedBase := false;
  421.     Unbind( V.information );
  422. end;
  423.  
  424.  
  425. #############################################################################
  426. ##
  427. #F  AddBase( <object>, <base> ) . . . . . . . . . . . add a base to an object
  428. ##
  429. AddBase := function( obj, base )
  430.     if IsDomain( obj ) and IsBound( obj.operations.AddBase ) then
  431.         obj.operations.AddBase( obj, base );
  432.     else
  433.         Error( "sorry, can't add <base> to <object>" );
  434.     fi;
  435. end;
  436.  
  437.  
  438. #############################################################################
  439. ##
  440. #F  Dimension( <object> ) . . . . . . . . . . . . . .  dimension of an object
  441. ##
  442. Dimension := function( obj )
  443.     local   dim;
  444.  
  445.     if IsDomain( obj ) and IsBound( obj.dimension ) then
  446.         dim := obj.dimension;
  447.     elif IsDomain( obj ) and IsBound( obj.operations.Dimension )  then
  448.         obj.dimension := obj.operations.Dimension( obj );
  449.         dim := obj.dimension;
  450.     elif IsDomain( obj ) then
  451.         obj.dimension := Length( Base( obj ) );
  452.         dim := obj.dimension;
  453.     else
  454.         Error( "sorry, can't compute dimension for <object>" );
  455.     fi;
  456.     return dim;
  457. end;
  458.  
  459.  
  460. #############################################################################
  461. ##
  462. #F  VectorSpaceOps.Information( <V> ) . .  information about the vector space
  463. ##
  464. VectorSpaceOps.Information := function( V )
  465.     local   base, dim, size, ord, gen, list, new, len, num, comp, pow, tmp,
  466.             info, oldbase, i;
  467.  
  468.  
  469.     # first step: general information about the vector space
  470.  
  471.     info := rec(
  472.         field    := V.field,
  473.         zero     := V.zero,
  474.         isFinite := IsFinite( V )
  475.     );
  476.  
  477.  
  478.     # second step: details about the field
  479.  
  480.     info.isFiniteField := IsFinite( V.field );
  481.     if info.isFiniteField then
  482.         info.isFinitePrimeField := V.field.degree = 1;
  483.         if info.isFinitePrimeField then
  484.             info.integers := IntegerTable( V.field );
  485.         fi;
  486.     else
  487.         info.isFinitePrimeField := false;
  488.     fi;
  489.  
  490.  
  491.     # third step: base and dimension
  492.  
  493.     if V.generators = [] then
  494.  
  495.         info.base      := [];
  496.         info.dimension := 0;
  497.  
  498.     elif info.isFiniteField then
  499.  
  500.         # find a generating set. if a base is there use this one.
  501.         # we need the base to generate all elements. to ensure a lexicographic
  502.         # order on the elements relative to a _base_ we have to reverse it.
  503.  
  504.         if IsBound( V.base ) then  oldbase := Reversed( V.base );
  505.         else                       oldbase := V.generators;
  506.         fi;
  507.  
  508.         # generate all elements and collect a base for the vector space
  509.  
  510.         base := [];
  511.         list := [ V.zero ];
  512.         ord  := Order( V.field, V.field.root );
  513.         for gen in oldbase do
  514.             if not gen in list then
  515.                 Add( base, gen );
  516.                 new := [];
  517.                 len := Length( list );
  518.                 for pow in [1..ord] do
  519.                     tmp := ShallowCopy( list );
  520.                     for i in [1..len] do  tmp[i] := tmp[i] + gen;  od;
  521.                     Append( new, tmp );
  522.                     gen := V.field.root * gen;
  523.                 od;
  524.                 Append( list, new );
  525.             fi;
  526.         od;
  527.  
  528.         base := Reversed( base );
  529.         dim  := Length( base );
  530.  
  531.         if IsBound( V.base ) then
  532.             if base <> V.base then
  533.                 V.base      := base;
  534.                 V.dimension := dim;
  535.                 Print( "#I  Information: warning, replacing bad base." );
  536.             fi;
  537.         else
  538.             V.base      := base;
  539.             V.dimension := dim;
  540.         fi;
  541.  
  542.         info.base      := base;
  543.         info.dimension := dim;
  544.  
  545.     elif IsBound( V.base ) then
  546.  
  547.         info.base      := V.base;
  548.         info.dimension := Length( info.base );
  549.  
  550.     else
  551.         Error( "sorry, no base available" );
  552.     fi;
  553.  
  554.     # fourth step: enumeration and coefficients information
  555.     #              only applicable if the field is finite
  556.  
  557.     if info.isFiniteField then
  558.  
  559.         # recall the data of the last step
  560.  
  561.         comp := function( a, b )  return list[a] < list[b];  end;
  562.         num  := [1..Length( list )];
  563.         Sort( num, comp );
  564.  
  565.         size := Size( V.field );
  566.  
  567.         info.elements  := Set( list );
  568.         info.numbers   := num;
  569.         info.exponents := List( base, x -> size );
  570.     fi;
  571.  
  572.     return info;
  573. end;
  574.  
  575.  
  576. #############################################################################
  577. ##
  578. #F  Information( <object> ) . . . . . . . . . . . information about an object
  579. ##
  580. Information := function( obj )
  581.     local   info;
  582.  
  583.     if IsRec( obj ) and IsBound( obj.information ) then
  584.         info := obj.information;
  585.     elif IsRec( obj ) and IsBound( obj.operations )
  586.       and IsBound( obj.operations.Information ) then
  587.         obj.information := obj.operations.Information( obj );
  588.         info := obj.information;
  589.     else
  590.         Error( "sorry, can't set up information for <object>" );
  591.     fi;
  592.     return info;
  593. end;
  594.  
  595.  
  596. #############################################################################
  597. ##
  598. #F  VectorSpaceOps.Coefficients( <V>, <v> ) . . .  coefficients of <v> in <V>
  599. ##
  600. VectorSpaceOps.Coefficients := function( V, v )
  601.     local   info, cf;
  602.  
  603.     if not IsBound( V.information ) then
  604.         Information( V );
  605.     fi;
  606.     info := V.information;
  607.  
  608.     if info.dimension = 0 then  return [];  fi;
  609.  
  610.     cf := CoefficientsInt( info.exponents,
  611.                 info.numbers[Position( info.elements, v )]-1 );
  612.  
  613.     return cf * V.field.one;
  614. end;
  615.  
  616.  
  617. #############################################################################
  618. ##
  619. #F  Coefficients( <V>, <v> )  . . . . . . . . . .  coefficients of <v> in <V>
  620. ##
  621. Coefficients := function( V, v )
  622.     local   cf;
  623.  
  624.     if IsList( V ) then
  625.         cf := CoefficientsInt( V, v );
  626.     elif IsDomain( V ) and IsBound( V.operations.Coefficients ) then
  627.         cf := V.operations.Coefficients( V, v );
  628.     else
  629.         Error( "sorry, can't compute coefficients of <v> in <V>" );
  630.     fi;
  631.     return cf;
  632. end;
  633.  
  634.  
  635. #############################################################################
  636. ##
  637. #F  VectorSpaceOps.LinearCombination( <V>, <cf> ) . linear combination in <V>
  638. ##
  639. VectorSpaceOps.LinearCombination := function( V, cf )
  640.     local   base, dim, v, i;
  641.  
  642.     if not IsBound( V.base )      then  Base( V );       fi;
  643.     if not IsBound( V.dimension ) then  Dimension( V );  fi;
  644.  
  645.     base := V.base;
  646.     dim  := V.dimension;
  647.     v    := V.zero;
  648.  
  649.     for i in [1..dim] do
  650.         if cf[i] <> V.field.zero then
  651.             v := v + cf[i] * base[i];
  652.         fi;
  653.     od;
  654.     return v;
  655. end;
  656.  
  657.  
  658. #############################################################################
  659. ##
  660. #F  LinearCombination( <V>, <cf> )  . . . . . . . . linear combination in <V>
  661. ##
  662. LinearCombination := function( V, cf )
  663.     local   lc;
  664.  
  665.     if IsDomain( V ) and IsBound( V.operations.LinearCombination ) then
  666.         lc := V.operations.LinearCombination( V, cf );
  667.     else
  668.         Error( "sorry, can't compute linear combination in <V>" );
  669.     fi;
  670.     return lc;
  671. end;
  672.  
  673.  
  674. #############################################################################
  675. ##
  676. #F  Enumeration( <object> ) . . . .  enumeration for the elements of <object>
  677. ##
  678. Enumeration := function( obj )
  679.     local   enum;
  680.  
  681.     if IsList( obj )  then
  682.         enum := rec(
  683.             elements := Set( obj ),
  684.             number   := function ( e, x ) return Position( e.elements, x ); end,
  685.             element  := function ( e, y ) return e.elements[y]; end
  686.         );
  687.     elif IsDomain( obj ) and IsBound( obj.enumeration ) then
  688.         enum := obj.enumeration;
  689.     elif IsDomain( obj ) and IsBound( obj.operations.Enumeration )  then
  690.         obj.enumeration := obj.operations.Enumeration( obj );
  691.         enum := obj.enumeration;
  692.     elif IsDomain( obj ) then
  693.         obj.enumeration := rec(
  694.             elements := Elements( obj ),
  695.             number   := function ( e, x ) return Position( e.elements, x ); end,
  696.             element  := function ( e, y ) return e.elements[y]; end
  697.         );
  698.         enum := obj.enumeration;
  699.     else
  700.         Error( "sorry, can't set up an enumeration for <object>" );
  701.     fi;
  702.     return enum;
  703. end;
  704.  
  705.  
  706. #############################################################################
  707. ##
  708. #F  LineEnumeration( <V> )  . . . . . . . enumerate one-dimensional subspaces
  709. ##
  710. LineEnumeration := function( V )
  711.     local enum, size, base, dim, range, off, ranges, offset, i;
  712.  
  713.     if not IsVectorSpace( V ) then
  714.         Error( "usage: LineEnumeration( <V> )" );
  715.     fi;
  716.  
  717.     base := Base( V );
  718.     dim  := Length( base );
  719.     enum := rec();
  720.     if dim = 0 then
  721.         enum.numberLines := 0;
  722.         enum.line := function ( num )
  723.             Error( "sorry, vector space has no lines" );
  724.         end;
  725.     elif dim = 1 then
  726.         enum.numberLines := 1;
  727.         enum.line := x -> base[1];
  728.     elif IsFinite( V ) then
  729.         enum   := Enumeration( V );
  730.         size   := Size( V.field );
  731.         range  := [1,1];
  732.         ranges := [ range ];
  733.         off    := 1;
  734.         offset := [ off + 1 ];
  735.         for i in [1..dim-1] do
  736.             range := [ range[2] + 1, range[2] * size + 1 ];
  737.             off   := off * size;
  738.             Add( ranges, range );
  739.             Add( offset, off + 1 );
  740.         od;
  741.         enum.numberLines := ((size ^ dim) - 1) / (size - 1);
  742.         enum.line := function ( num )
  743.             local i;
  744.             for i in [1..dim] do
  745.                 if ranges[i][1] <= num and num <= ranges[i][2] then
  746.                     return enum.element(  enum,
  747.                                           num - ranges[i][1] + offset[i] );
  748.                 fi;
  749.             od;
  750.             Error( "sorry, number too big" );
  751.         end;
  752.     else
  753.         Error( "sorry, vector space has an infinte number of lines" );
  754.     fi;
  755.     return enum;
  756. end;
  757.  
  758.  
  759. #############################################################################
  760. ##
  761. #F  NormedVector(<vec>) . . . . . . . . . . . . . . . . . . . . normed vector
  762. ##
  763. NormedVector := function ( vec )
  764.     local   zero, elm;
  765.     zero := vec[1] - vec[1];
  766.     for elm  in vec  do
  767.         if elm <> zero  then
  768.             return (1/elm) * vec;
  769.         fi;
  770.     od;
  771.     return vec;
  772. end;
  773.  
  774.  
  775. #############################################################################
  776. ##
  777. #E  Emacs . . . . . . . . . . . . . . . . . . . . . . . local emacs variables
  778. ##
  779. ##  Local Variables:
  780. ##  mode:               outline
  781. ##  outline-regexp:     "#F\\|#V\\|#E"
  782. ##  fill-column:        73
  783. ##  fill-prefix:        "##  "
  784. ##  eval:               (hide-body)
  785. ##  End:
  786. ##
  787.