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

  1. #############################################################################
  2. ##
  3. #A  gaussian.g                  GAP library                  Martin Schoenert
  4. ##
  5. #A  @(#)$Id: gaussian.g,v 3.8 1993/01/29 15:21:32 sam Rel $
  6. ##
  7. #Y  Copyright 1990-1992,  Lehrstuhl D fuer Mathematik,  RWTH Aachen,  Germany
  8. ##
  9. ##  This file contains those functions that  deal  with  Gaussian  rationals.
  10. ##
  11. ##  Gaussian rationals are elements of the form $a + b * I$ where  $I$ is the
  12. ##  square root of -1 and $a,b$  are rationals.  Note that  $I$ is written as
  13. ##  'E(4)', i.e., as a  fourth root of unity in  GAP.  Gauss was the first to
  14. ##  investigate such numbers, and already proved that the ring of integers of
  15. ##  this field, i.e.,  the elements of the  form $a +  b * I$ where $a,b$ are
  16. ##  integers, forms a Euclidean Ring.  It follows that  this ring is a Unique
  17. ##  Factorization Domain.
  18. ##
  19. #H  $Log: gaussian.g,v $
  20. #H  Revision 3.8  1993/01/29  15:21:32  sam
  21. #H  GaussianRationals now behaves like CF(4) (hopefully!)
  22. #H
  23. #H  Revision 3.7  1992/12/16  19:47:27  martin
  24. #H  replaced quoted record names with escaped ones
  25. #H
  26. #H  Revision 3.6  1992/06/23  14:02:29  sam
  27. #H  added 'Coefficients' in 'GaussianRationalsOps'
  28. #H
  29. #H  Revision 3.5  1992/06/23  13:46:19  sam
  30. #H  added some components to 'GaussianRationals' in order to achieve that
  31. #H  'GaussianRationals' and 'CF(4)' are aquivalent
  32. #H
  33. #H  Revision 3.4  1992/02/06  11:47:31  martin
  34. #H  removed 'InverseMod' and added 'QuotientMod'
  35. #H
  36. #H  Revision 3.3  1991/12/04  10:53:51  martin
  37. #H  changed 'CoeffsCyc' to 'COEFFSCYC'
  38. #H
  39. #H  Revision 3.2  1991/12/04  10:52:30  martin
  40. #H  added 'Ring' and 'DefaultRing' functions to 'GaussianRationals'
  41. #H
  42. #H  Revision 3.1  1991/10/24  11:33:29  martin
  43. #H  changed package for new domain concept with inheritance
  44. #H
  45. #H  Revision 3.0  1991/08/08  15:31:10  martin
  46. #H  initial revision under RCS
  47. #H
  48. ##
  49.  
  50.  
  51. #############################################################################
  52. ##
  53. #F  IsGaussInt(<x>) . . . . . . . . . test if an object is a Gaussian integer
  54. ##
  55. ##  'IsGaussInt' returns 'true' if the  object <x> is  a Gaussian integer and
  56. ##  'false' otherwise.  Gaussian integers are of the form  '<a> + <b>\*E(4)',
  57. ##  where <a> and <b> are integers.
  58. ##
  59. IsGaussInt := function ( x )
  60.     return IsCycInt( x ) and (NofCyc( x ) = 1 or NofCyc( x ) = 4);
  61. end;
  62.  
  63.  
  64. #############################################################################
  65. ##
  66. #V  GaussianIntegers  . . . . . . . . . . . . . . domain of Gaussian integers
  67. #V  GaussianIntegersOps . . . . . . .  operation record for Gaussian integers
  68. ##
  69. GaussianIntegersOps := Copy( RingOps );
  70.  
  71. GaussianIntegers := rec(
  72.     isDomain                    := true,
  73.     isRing                      := true,
  74.  
  75.     generators                  := [ 1, E(4) ],
  76.     zero                        := 0,
  77.     one                         := 1,
  78.     name                        := "GaussianIntegers",
  79.  
  80.     size                        := "infinity",
  81.     isFinite                    := false,
  82.     isCommutativeRing           := true,
  83.     isIntegralRing              := true,
  84.     isUniqueFactorizationRing   := true,
  85.     isEuclideanRing             := true,
  86.     units                       := [ 1, -1, E(4), -E(4) ],
  87.  
  88.     operations                  := GaussianIntegersOps
  89. );
  90.  
  91.  
  92. #############################################################################
  93. ##
  94. #F  GaussianIntegersOps.Ring(<elms>) ring generated by some Gaussian Integers
  95. ##
  96. GaussianIntegersOps.Ring := function ( elms )
  97.     if ForAll( elms, IsInt )  then
  98.         return Integers;
  99.     else
  100.         return GaussianIntegers;
  101.     fi;
  102. end;
  103.  
  104.  
  105. #############################################################################
  106. ##
  107. #F  GaussianIntegersOps.DefaultRing(<elms>) . . default ring of some Gaussian
  108. #F                                                                   integers
  109. ##
  110. GaussianIntegersOps.DefaultRing := function ( elms )
  111.     return GaussianIntegers;
  112. end;
  113.  
  114.  
  115. #############################################################################
  116. ##
  117. #F  GaussianIntegersOps.\in(<g>,<GaussInt>)  . . . . . . membership test for
  118. #F                                                          Gaussian integers
  119. ##
  120. ##  'GaussianIntegersOps.in' returns 'true' if the object  <g>  is a Gaussian
  121. ##  integer and 'false' otherwise.  Gaussian integers are of the form  '<a> +
  122. ##  <b>\*E(4)', where <a>  and   <b> are   integers.
  123. ##
  124. GaussianIntegersOps.\in := function ( x, GaussInt )
  125.     return IsCycInt( x ) and (NofCyc( x ) = 1 or NofCyc( x ) = 4);
  126. end;
  127.  
  128.  
  129. #############################################################################
  130. ##
  131. #F  GaussianIntegersOps.Random(<GaussInt>)  . . . . . random Gaussian integer
  132. ##
  133. ##  'GaussianIntegersOps.Random' returns a  random  Gaussian  integer,  i.e.,
  134. ##  $a + b E(4)$, where $a$ and $b$ are  random integers,  selected  with the
  135. ##  generator 'Random( Integers )' (see "Random", "RandomInt").
  136. ##
  137. GaussianIntegersOps.Random := function ( GaussInt )
  138.     return Random( Integers ) + Random( Integers ) * E(4);
  139. end;
  140.  
  141.  
  142. #############################################################################
  143. ##
  144. #F  GaussianIntegersOps.Quotient(<GaussInt>,<x>,<y>)  . . . . quotient of two
  145. #F                                                          Gaussian integers
  146. ##
  147. GaussianIntegersOps.Quotient := function ( GaussInt, x, y )
  148.     local   q;
  149.     q := x / y;
  150.     if not IsCycInt( q )  then
  151.         q := false;
  152.     fi;
  153.     return q;
  154. end;
  155.  
  156.  
  157. #############################################################################
  158. ##
  159. #F  GaussianIntegersOps.IsAssociated(<GaussInt>,<x>,<y>)  . . . . test if two
  160. #F                                            Gaussian integers are associate
  161. ##
  162. ##  'GaussianIntegersOps.IsAssociated'  returns  'true'   if   the   Gaussian
  163. ##  integers <x> and <y> are assocaited and 'false' otherwise.
  164. ##
  165. GaussianIntegersOps.IsAssociated := function ( GaussInt, x, y )
  166.     return x = y  or x = -y  or x = E(4)*y  or x = -E(4)*y;
  167. end;
  168.  
  169.  
  170. #############################################################################
  171. ##
  172. #F  GaussianIntegersOps.StandardAssociate(<GaussInt>,<x>)  standard associate
  173. #F                                                      of a Gaussian integer
  174. ##
  175. ##  'GaussianIntegersOps.StandardAssociate' returns the standard associate of
  176. ##  the Gaussian integer <x>.  The standard associate of <x> is an associated
  177. ##  element <y> of <x> that lies in the  first quadrant of the complex plain.
  178. ##  That  is <y>  is  that element   from '<x> * [1,-1,E(4),-E(4)]' that  has
  179. ##  positive real part and nonnegative imaginary part.
  180. ##
  181. ##  'GaussianIntegersOps.StandardAssociate' is the  generalization  of  'Abs'
  182. ##  (see "Abs") for Gaussian integers.
  183. ##
  184. GaussianIntegersOps.StandardAssociate := function ( GaussInt, x )
  185.     if   IsRat(x)  and 0 <= x  then
  186.         return x;
  187.     elif IsRat(x)  then
  188.         return -x;
  189.     elif 0 <  COEFFSCYC(x)[1]       and 0 <= COEFFSCYC(x)[2]       then
  190.         return x;
  191.     elif      COEFFSCYC(x)[1] <= 0  and 0 <  COEFFSCYC(x)[2]       then
  192.         return - E(4) * x;
  193.     elif      COEFFSCYC(x)[1] <  0  and      COEFFSCYC(x)[2] <= 0  then
  194.         return - x;
  195.     else
  196.         return E(4) * x;
  197.     fi;
  198. end;
  199.  
  200.  
  201. #############################################################################
  202. ##
  203. #F  GaussianIntegersOps.EuclideanDegree(<GaussInt>,<x>) . .  Euclidean degree
  204. #F                                                      of a Gaussian integer
  205. ##
  206. GaussianIntegersOps.EuclideanDegree := function ( GaussInt, x )
  207.     return x * GaloisCyc( x, -1 );
  208. end;
  209.  
  210.  
  211. #############################################################################
  212. ##
  213. #F  GaussianIntegersOps.Mod(<GaussInt>,<x>,<y>) . . . . . .  remainder of two
  214. #F                                                          Gaussian integers
  215. ##
  216. GaussianIntegersOps.Mod := function ( GaussInt, x, y )
  217.     return x - RoundCyc( x/y ) * y;
  218. end;
  219.  
  220.  
  221. #############################################################################
  222. ##
  223. #F  GaussianIntegersOps.IsPrime(<GaussInt>,<x>) . . . test whether a Gaussian
  224. #F                                                         integer is a prime
  225. ##
  226. GaussianIntegersOps.IsPrime := function ( GaussInt, x )
  227.     if IsInt( x )  then
  228.         return x mod 4 = 3  and IsPrimeInt( x );
  229.     else
  230.         return IsPrimeInt( x * GaloisCyc( x, -1 ) );
  231.     fi;
  232. end;
  233.  
  234.  
  235. #############################################################################
  236. ##
  237. #F  TwoSquares(<n>) . .  representation of an integer as a sum of two squares
  238. ##
  239. ##  'TwoSquares' returns a list of two integers $x\<=y$ such that  the sum of
  240. ##  the squares of $x$ and $y$ is equal to the nonnegative integer <n>, i.e.,
  241. ##  $n = x^2+y^2$.  If no such representation exists 'TwoSquares' will return
  242. ##  'false'.  'TwoSquares' will return a representation for which the  gcd of
  243. ##  $x$  and   $y$ is  as  small  as  possible.    It is not  specified which
  244. ##  representation 'TwoSquares' returns, if there are more than one.
  245. ##
  246. ##  Let $a$ be the product of all maximal powers of primes of the form $4k+3$
  247. ##  dividing $n$.  A representation of $n$ as a sum of two squares  exists if
  248. ##  and only if $a$ is a perfect square.  Let $b$ be the maximal power of $2$
  249. ##  dividing $n$ or its half, whichever is a perfect square.  Then the minmal
  250. ##  possible gcd of $x$ and $y$ is the square root $c$ of $a b$.  The  number
  251. ##  of different minimal representation with $x\<=y$ is $2^{l-1}$, where  $l$
  252. ##  is the number of different prime factors of the form $4k+1$ of $n$.
  253. ##
  254. ##  The algorithm first finds a square root $r$ of $-1$  modulo  $n / (a b)$,
  255. ##  which must exist, and applies the Euclidean algorithm  to  $r$  and  $n$.
  256. ##  The first residues in the sequence that are smaller than $\root{n/(a b)}$
  257. ##  times $c$ are a possible pair $x$ and $y$.
  258. ##
  259. ##  Better descriptions of the algorithm and related topics can be found  in:
  260. ##  S. Wagon,  The Euclidean Algorithm Strikes Again, AMMon 97, 1990, 125-129
  261. ##  D. Zagier, A One-Sentence Proof that Every Pri.., AMMon 97, 1990, 144-144
  262. ##
  263. TwoSquares := function ( n )
  264.     local  c, d, p, q, l, x, y;
  265.  
  266.     # check arguments and handle special cases
  267.     if   n < 0  then Error("<n> must be positive");
  268.     elif n = 0  then return [ 0, 0 ];
  269.     elif n = 1  then return [ 0, 1 ];
  270.     fi;
  271.  
  272.     # write $n = c^2 d$, where $c$ has only  prime factors  $2$  and  $4k+3$,
  273.     # and $d$ has at most one  $2$ and otherwise only  prime factors  $4k+1$.
  274.     c := 1;  d := 1;
  275.     for p  in Set( FactorsInt( n ) )  do
  276.         q := p;  l := 1;
  277.         while n mod (q * p) = 0  do q := q * p;  l := l + 1;  od;
  278.         if p = 2  and l mod 2 = 0  then
  279.             c := c * 2 ^ (l/2);
  280.         elif p = 2  and l mod 2 = 1  then
  281.             c := c * 2 ^ ((l-1)/2);
  282.             d := d * 2;
  283.         elif p mod 4 = 1  then
  284.             d := d * q;
  285.         elif p mod 4 = 3  and l mod 2 = 0  then
  286.             c := c * p ^ (l/2);
  287.         else # p mod 4 = 3  and l mod 2 = 1
  288.             return false;
  289.         fi;
  290.     od;
  291.  
  292.     # handle special cases
  293.     if   d = 1  then return [ 0, c ];
  294.     elif d = 2  then return [ c, c ];
  295.     fi;
  296.  
  297.     # compute a square root $x$ of $-1$ mod $d$,  which must exist  since  it
  298.     # exists modulo all prime powers that divide $d$
  299.     x := RootMod( -1, d );
  300.  
  301.     # and now the Euclidean Algorithm strikes again
  302.     y := d;
  303.     while d < y^2  do
  304.         p := x;
  305.         x := y mod x;
  306.         y := p;
  307.     od;
  308.  
  309.     # return the representation
  310.     return [ c * x, c * y ];
  311. end;
  312.  
  313.  
  314. #############################################################################
  315. ##
  316. #F  GaussianIntegersOps.Factors(<GaussInt>,<x>) . . . . .  factorization of a
  317. #F                                                           Gaussian integer
  318. ##
  319. GaussianIntegersOps.Factors := function ( GaussInt, x )
  320.     local   facs,       # factors (result)
  321.             prm,        # prime factors of the norm
  322.             tsq;        # representation of prm as $x^2 + y^2$
  323.  
  324.     # handle trivial cases
  325.     if x in [ 0, 1, -1, E(4), -E(4) ]  then
  326.         return [ x ];
  327.     fi;
  328.  
  329.     # loop over all factors of the norm of x
  330.     facs := [];
  331.     for prm  in Set( FactorsInt( EuclideanDegree( x ) ) )  do
  332.  
  333.         # $p = 2$ and primes $p = 1$ mod 4 split according to $p = x^2 + y^2$
  334.         if prm = 2  or prm mod 4 = 1  then
  335.             tsq := TwoSquares( prm );
  336.             while IsCycInt( x / (tsq[1]+tsq[2]*E(4)) )  do
  337.                 Add( facs, (tsq[1]+tsq[2]*E(4)) );
  338.                 x := x / (tsq[1]+tsq[2]*E(4));
  339.             od;
  340.             while IsCycInt( x / (tsq[2]+tsq[1]*E(4)) )  do
  341.                 Add( facs, (tsq[2]+tsq[1]*E(4)) );
  342.                 x := x / (tsq[2]+tsq[1]*E(4));
  343.             od;
  344.  
  345.         # primes $p = 3$ mod 4 stay prime
  346.         else
  347.             while IsCycInt( x / prm )  do
  348.                 Add( facs, prm );
  349.                 x := x / prm;
  350.             od;
  351.         fi;
  352.  
  353.     od;
  354.  
  355.     # the first factor takes the unit
  356.     if not x in [ 1, -1, E(4), -E(4) ]  then
  357.         Error("Panic: 'GaussianIntegersOps.Factors' cofactor is not a unit");
  358.     fi;
  359.     facs[1] := x * facs[1];
  360.  
  361.     # return the result
  362.     return facs;
  363. end;
  364.  
  365.  
  366. #############################################################################
  367. ##
  368. #F  GaussianIntegersOps.AsGroup(<GaussInt>) . . .  Gaussian integers as group
  369. ##
  370. GaussianIntegersOps.AsGroup := function ( GaussInt )
  371.     Error("sorry, Z[I] is not finitely generated as multiplicative group");
  372. end;
  373.  
  374.  
  375. #############################################################################
  376. ##
  377. #F  GaussianIntegersOps.AsAdditiveGroup(<GaussInt>) . . . . Gaussian integers
  378. #F                                                          as additive group
  379. ##
  380. #N  14-Oct-91 martin this should be
  381. #N  GaussianIntegersAsAddtiveGroupOps := Copy( AdditveGroupOps );
  382. ##
  383. GaussianIntegersAsAdditiveGroupOps := Copy( DomainOps );
  384.  
  385. GaussianIntegersOps.AsAdditiveGroup := function ( GaussInt )
  386.  
  387.     return rec(
  388.         isDoman                 := true,
  389.         isAdditiveGroup         := true,
  390.  
  391.         generators              := [ 1, E(4) ],
  392.         zero                    := 0,
  393.  
  394.         size                    := "infinity",
  395.         isFinite                := true,
  396.  
  397.         operations              := GaussianIntegersAsAdditiveGroupOps
  398.     );
  399.  
  400. end;
  401.  
  402.  
  403. #############################################################################
  404. ##
  405. #F  IsGaussRat( <x> ) . . . . . . .  test if an object is a Gaussian rational
  406. ##
  407. ##  'IsGaussRat' returns 'true' if the  object <x> is a Gaussian rational and
  408. ##  'false' otherwise.  Gaussian rationals are of the form '<a> + <b>\*E(4)',
  409. ##  where <a> and <b> are rationals.
  410. ##
  411. IsGaussRat := function ( x )
  412.     return IsCyc( x ) and (NofCyc( x ) = 1 or NofCyc( x ) = 4);
  413. end;
  414.  
  415.  
  416. #############################################################################
  417. ##
  418. #V  GaussianRationals . . . . . . . . . . . . . . field of Gaussian rationals
  419. #V  GaussianRationalsOps  . . . . .  operations record for Gaussian rationals
  420. ##
  421. GaussianRationalsOps := Copy( CyclotomicFieldOps );
  422.  
  423. GaussianRationals := rec(
  424.     isDomain                    := true,
  425.     isField                     := true,
  426.     isCyclotomicField           := true,
  427.  
  428.     char                        := 0,
  429.     generators                  := [ 1, E(4) ],
  430.     zero                        := 0,
  431.     one                         := 1,
  432.     name                        := "GaussianRationals",
  433.     stabilizer                  := [ 1 ],
  434.  
  435.     size                        := "infinity",
  436.     isFinite                    := false,
  437.     degree                      := 2,
  438.  
  439.     field                       := Rationals,
  440.     dimension                   := 2,
  441.     base                        := [ 1, E(4) ],
  442.     isIntegralBase              := true,
  443.     zumbroichbase               := [ 0, 1 ],
  444.     automorphisms               := [ x -> x, x -> GaloisCyc(x,-1) ],
  445.  
  446.     operations                  := GaussianRationalsOps
  447. );
  448.  
  449.  
  450. #############################################################################
  451. ##
  452. #F  GaussianRationalsOps.Ring(<elms>) . . . . . . . .  ring generated by some
  453. #F                                                         Gaussian rationals
  454. ##
  455. GaussianRationalsOps.Ring := function ( elms )
  456.     if ForAll( elms, IsInt )  then
  457.         return Integers;
  458.     elif ForAll( elms, IsCycInt )  then
  459.         return GaussianIntegers;
  460.     else
  461.         return AsRing( GaussianRationals );
  462.     fi;
  463. end;
  464.  
  465.  
  466. #############################################################################
  467. ##
  468. #F  GaussianRationalsOps.DefaultRing(<elms>)   default ring generated by some
  469. #F                                                         Gaussian rationals
  470. ##
  471. GaussianRationalsOps.DefaultRing := function ( elms )
  472.     if ForAll( elms, IsInt )  then
  473.         return Integers;
  474.     elif ForAll( elms, IsCycInt )  then
  475.         return GaussianIntegers;
  476.     else
  477.         return AsRing( GaussianRationals );
  478.     fi;
  479. end;
  480.  
  481.  
  482. #############################################################################
  483. ##
  484. #F  GaussianRationalsOps.Random(<GaussRat>) . . . .  random Gaussian rational
  485. ##
  486. ##  'GaussianRationalsOps.Random'  returns a random Gaussian rational.
  487. ##
  488. GaussianRationalsOps.Random := function ( GaussRat )
  489.     return Random(Rationals) + Random(Rationals) * E(4);
  490. end;
  491.  
  492.  
  493. #############################################################################
  494. ##
  495. #F  GaussianRationalsOps.Automorphisms(<GaussRat>)  . . . . . . automorphisms
  496. #F                                                  of the Gaussian rationals
  497. ##
  498. GaussianRationalsOps.Automorphisms := function ( GaussRat )
  499.     return [ x -> x, x -> GaloisCyc( x, -1 ) ];
  500. end;
  501.  
  502.  
  503. #############################################################################
  504. ##
  505. #F  GaussianRationalsOps.Conjugates(<GaussRat>,<x>) . . . . . . .  conjugates
  506. #F                                                     of a Gaussian rational
  507. ##
  508. ##  'GaussianRationals.Conjugates' returns  the  list of  conjugates   of the
  509. ##  Gaussian      rational   <x>.  I.e.,   if    '<x> =   <a> +   <b>\*E(4)',
  510. ##  'GaussianRationals.Conjugates' returns the list '[ <a> + <b>\*E(4), <a> -
  511. ##  <b>\*E(4) ]'.   Note that  the list will contain  <x>  twice if <x>  is a
  512. ##  rational.
  513. ##
  514. GaussianRationalsOps.Conjugates := function ( GaussRat, x )
  515.     return [ x, GaloisCyc( x, -1 ) ];
  516. end;
  517.  
  518.  
  519. #############################################################################
  520. ##
  521. #F  GaussianRationalsOps.Norm(<GaussRat>,<x>) . . norm of a Gaussian rational
  522. ##
  523. ##  'GaussianRationalsOps.Norm' returns  the  norm  of the  Gaussian rational
  524. ##  <x>.  The norm is the product of <x> with its  conjugate, i.e., if '<x> =
  525. ##  <a> + <b>\*E(4)', the norm is $a^2 + b^2$.  The  norm is rational, and is
  526. ##  an integer if <x> is a Gaussian integer.
  527. ##
  528. GaussianRationalsOps.Norm := function ( GaussRat, x )
  529.     return x * GaloisCyc( x, -1 );
  530. end;
  531.  
  532.  
  533. #############################################################################
  534. ##
  535. #F  GaussianRationalsOps.Trace(<GaussRat>,<x>) . trace of a Gaussian rational
  536. ##
  537. ##  'GaussianRationalsOps.Trace' returns the  trace of  the Gaussian rational
  538. ##  <x>.  The trace is the sum of <x> with its conjugate, i.e., if '<x> = <a>
  539. ##  +   <b>\*E(4)', the trace is  $2a$.   The trace  is  rational, and  is an
  540. ##  integer if <x> is a Gaussian integer.
  541. ##
  542. GaussianRationalsOps.Trace := function ( GaussRat, x )
  543.     return x + GaloisCyc( x, -1 );
  544. end;
  545.  
  546.  
  547. #############################################################################
  548. ##
  549. #F  GaussianRationalsOps.CharPol(<GaussRat>,<x>)  . .  characteristic polynom
  550. #F                                                     of a Gaussian rational
  551. ##
  552. GaussianRationalsOps.CharPol := function ( GaussRat, x )
  553.     return [ x * GaloisCyc(x,-1), -x-GaloisCyc(x,-1), 1 ];
  554. end;
  555.  
  556.  
  557. #############################################################################
  558. ##
  559. #F  GaussianRationalsOps.MinPol(<GaussRat>,<x>) . . . . . . . minimal polynom
  560. #F                                                     of a Gaussian rational
  561. ##
  562. GaussianRationalsOps.MinPol := function ( GaussRat, x )
  563.     if IsRat( x )  then
  564.         return [ -x, 1 ];
  565.     else
  566.         return [ x * GaloisCyc(x,-1), -x-GaloisCyc(x,-1), 1 ];
  567.     fi;
  568. end;
  569.  
  570.  
  571. #############################################################################
  572. ##
  573. #F  GaussianRationalsOps.AsGroup(<GaussRat>)  . . view the Gaussian rationals
  574. #F                                                    as multiplicative group
  575. ##
  576. GaussianRationalsOps.AsGroup := function ( GaussRat )
  577.     Error("sorry, Q[I] is not finitely generated as multiplicative group");
  578. end;
  579.  
  580.  
  581. #############################################################################
  582. ##
  583. #F  GaussianRationalsOps.AsAdditiveGroup(<GaussRat>)  . . . view the Gaussian
  584. #F                                                rationals as additive group
  585. ##
  586. GaussianRationalsOps.AsAdditiveGroup := function ( GaussRat )
  587.     Error("sorry, Q[I] is not finitely generated as additive group");
  588. end;
  589.  
  590.  
  591. #############################################################################
  592. ##
  593. #F  GaussianRationalsOps.AsRing(<GaussRat>) . . . view the Gaussian rationals
  594. #F                                                                    as ring
  595. ##
  596. #N  23-Oct-91 martin this should be 'FieldOps.AsRing'
  597. ##
  598. GaussianRationalsAsRingOps := Copy( RingOps );
  599.  
  600. GaussianRationalsAsRingOps.\in := GaussianRationalsOps.\in;
  601.  
  602. GaussianRationalsAsRingOps.Random := GaussianRationalsOps.Random;
  603.  
  604. GaussianRationalsAsRingOps.Quotient := function ( R, r, s )
  605.     return r/s;
  606. end;
  607.  
  608. GaussianRationalsAsRingOps.IsUnit := function ( R, r )
  609.     return r <> R.zero;
  610. end;
  611.  
  612. GaussianRationalsAsRingOps.Units := function ( R )
  613.     return AsGroup( R.field );
  614. end;
  615.  
  616. GaussianRationalsAsRingOps.IsAssociated := function ( R, r, s )
  617.     return (r = R.zero) = (s = R.zero);
  618. end;
  619.  
  620. GaussianRationalsAsRingOps.StandardAssociate := function ( R, r )
  621.     if r = R.zero  then
  622.         return R.zero;
  623.     else
  624.         return R.zero;
  625.     fi;
  626. end;
  627.  
  628. GaussianRationalsOps.AsRing := function ( GaussRat )
  629.  
  630.     return rec(
  631.         isDomain                := true,
  632.         isRing                  := true,
  633.  
  634.         zero                    := 0,
  635.         one                     := 1,
  636.  
  637.         isFinite                := false,
  638.         size                    := "infinity",
  639.         isCommutativeRing       := true,
  640.         isIntegralRing          := true,
  641.         field                   := GaussRat,
  642.  
  643.         operations              := GaussianRationalsAsRingOps
  644.     );
  645. end;
  646.  
  647.  
  648. #############################################################################
  649. ##
  650. #E  Emacs . . . . . . . . . . . . . . . . . . . . . . . local emacs variables
  651. ##
  652. ##  Local Variables:
  653. ##  mode:               outline
  654. ##  outline-regexp:     "#F\\|#V\\|#E"
  655. ##  fill-column:        73
  656. ##  fill-prefix:        "##  "
  657. ##  eval:               (hide-body)
  658. ##  End:
  659. ##
  660.  
  661.  
  662.  
  663.