]> gitweb.michael.orlitzky.com - sage.d.git/blob - mjo/hurwitz.py
mjo/**/*.py: drop obsolete set_random_seed().
[sage.d.git] / mjo / hurwitz.py
1 from sage.misc.cachefunc import cached_method
2 from sage.combinat.free_module import CombinatorialFreeModule
3 from sage.modules.with_basis.indexed_element import IndexedFreeModuleElement
4 from sage.rings.all import AA
5
6 from mjo.matrix_algebra import MatrixAlgebra, MatrixAlgebraElement
7
8 class Octonion(IndexedFreeModuleElement):
9 def conjugate(self):
10 r"""
11 SETUP::
12
13 sage: from mjo.hurwitz import Octonions
14
15 EXAMPLES::
16
17 sage: O = Octonions()
18 sage: x = sum(O.gens())
19 sage: x.conjugate()
20 e0 - e1 - e2 - e3 - e4 - e5 - e6 - e7
21
22 TESTS::
23
24 Conjugating twice gets you the original element::
25
26 sage: O = Octonions()
27 sage: x = O.random_element()
28 sage: x.conjugate().conjugate() == x
29 True
30
31 """
32 from sage.rings.all import ZZ
33 from sage.matrix.matrix_space import MatrixSpace
34 C = MatrixSpace(ZZ,8).diagonal_matrix((1,-1,-1,-1,-1,-1,-1,-1))
35 return self.parent().from_vector(C*self.to_vector())
36
37 def real(self):
38 r"""
39 Return the real part of this octonion.
40
41 The real part of an octonion is its projection onto the span
42 of the first generator. In other words, the "first dimension"
43 is real and the others are imaginary.
44
45 SETUP::
46
47 sage: from mjo.hurwitz import Octonions
48
49 EXAMPLES::
50
51 sage: O = Octonions()
52 sage: x = sum(O.gens())
53 sage: x.real()
54 e0
55
56 TESTS:
57
58 This method is idempotent::
59
60 sage: O = Octonions()
61 sage: x = O.random_element()
62 sage: x.real().real() == x.real()
63 True
64
65 """
66 return (self + self.conjugate())/2
67
68 def imag(self):
69 r"""
70 Return the imaginary part of this octonion.
71
72 The imaginary part of an octonion is its projection onto the
73 orthogonal complement of the span of the first generator. In
74 other words, the "first dimension" is real and the others are
75 imaginary.
76
77 SETUP::
78
79 sage: from mjo.hurwitz import Octonions
80
81 EXAMPLES::
82
83 sage: O = Octonions()
84 sage: x = sum(O.gens())
85 sage: x.imag()
86 e1 + e2 + e3 + e4 + e5 + e6 + e7
87
88 TESTS:
89
90 This method is idempotent::
91
92 sage: O = Octonions()
93 sage: x = O.random_element()
94 sage: x.imag().imag() == x.imag()
95 True
96
97 """
98 return (self - self.conjugate())/2
99
100 def _norm_squared(self):
101 return (self*self.conjugate()).coefficient(0)
102
103 def norm(self):
104 r"""
105 Return the norm of this octonion.
106
107 SETUP::
108
109 sage: from mjo.hurwitz import Octonions
110
111 EXAMPLES::
112
113 sage: O = Octonions()
114 sage: O.one().norm()
115 1
116
117 TESTS:
118
119 The norm is nonnegative and belongs to the base field::
120
121 sage: O = Octonions()
122 sage: n = O.random_element().norm()
123 sage: n >= 0 and n in O.base_ring()
124 True
125
126 The norm is homogeneous::
127
128 sage: O = Octonions()
129 sage: x = O.random_element()
130 sage: alpha = O.base_ring().random_element()
131 sage: (alpha*x).norm() == alpha.abs()*x.norm()
132 True
133
134 """
135 return self._norm_squared().sqrt()
136
137 # The absolute value notation is typically used for complex numbers...
138 # and norm() isn't supported in AA, so this lets us use abs() in all
139 # of the division algebras we need.
140 abs = norm
141
142 def inverse(self):
143 r"""
144 Return the inverse of this element if it exists.
145
146 SETUP::
147
148 sage: from mjo.hurwitz import Octonions
149
150 EXAMPLES::
151
152 sage: O = Octonions()
153 sage: x = sum(O.gens())
154 sage: x*x.inverse() == O.one()
155 True
156
157 ::
158
159 sage: O = Octonions()
160 sage: O.one().inverse() == O.one()
161 True
162
163 TESTS::
164
165 sage: O = Octonions()
166 sage: x = O.random_element()
167 sage: x.is_zero() or ( x*x.inverse() == O.one() )
168 True
169
170 """
171 if self.is_zero():
172 raise ValueError("zero is not invertible")
173 return self.conjugate()/self._norm_squared()
174
175
176
177 class Octonions(CombinatorialFreeModule):
178 r"""
179 SETUP::
180
181 sage: from mjo.hurwitz import Octonions
182
183 EXAMPLES::
184
185 sage: Octonions()
186 Octonion algebra with base ring Algebraic Real Field
187 sage: Octonions(field=QQ)
188 Octonion algebra with base ring Rational Field
189
190 """
191 def __init__(self,
192 field=AA,
193 prefix="e"):
194
195 # Not associative, not commutative
196 from sage.categories.magmatic_algebras import MagmaticAlgebras
197 category = MagmaticAlgebras(field).FiniteDimensional()
198 category = category.WithBasis().Unital()
199
200 super().__init__(field,
201 range(8),
202 element_class=Octonion,
203 category=category,
204 prefix=prefix,
205 bracket=False)
206
207 # The product of each basis element is plus/minus another
208 # basis element that can simply be looked up on
209 # https://en.wikipedia.org/wiki/Octonion
210 e0, e1, e2, e3, e4, e5, e6, e7 = self.gens()
211 self._multiplication_table = (
212 (e0, e1, e2, e3, e4, e5, e6, e7),
213 (e1,-e0, e3,-e2, e5,-e4,-e7, e6),
214 (e2,-e3,-e0, e1, e6, e7,-e4,-e5),
215 (e3, e2,-e1,-e0, e7,-e6, e5,-e4),
216 (e4,-e5,-e6,-e7,-e0, e1, e2, e3),
217 (e5, e4,-e7, e6,-e1,-e0,-e3, e2),
218 (e6, e7, e4,-e5,-e2, e3,-e0,-e1),
219 (e7,-e6, e5, e4,-e3,-e2, e1,-e0),
220 )
221
222 def product_on_basis(self, i, j):
223 return self._multiplication_table[i][j]
224
225 def one_basis(self):
226 r"""
227 Return the monomial index (basis element) corresponding to the
228 octonion unit element.
229
230 SETUP::
231
232 sage: from mjo.hurwitz import Octonions
233
234 TESTS:
235
236 This gives the correct unit element::
237
238 sage: O = Octonions()
239 sage: x = O.random_element()
240 sage: x*O.one() == x and O.one()*x == x
241 True
242
243 """
244 return 0
245
246 def _repr_(self):
247 return ("Octonion algebra with base ring %s" % self.base_ring())
248
249 def multiplication_table(self):
250 """
251 Return a visual representation of this algebra's multiplication
252 table (on basis elements).
253
254 SETUP::
255
256 sage: from mjo.hurwitz import Octonions
257
258 EXAMPLES:
259
260 The multiplication table is what Wikipedia says it is::
261
262 sage: Octonions().multiplication_table()
263 +----++----+-----+-----+-----+-----+-----+-----+-----+
264 | * || e0 | e1 | e2 | e3 | e4 | e5 | e6 | e7 |
265 +====++====+=====+=====+=====+=====+=====+=====+=====+
266 | e0 || e0 | e1 | e2 | e3 | e4 | e5 | e6 | e7 |
267 +----++----+-----+-----+-----+-----+-----+-----+-----+
268 | e1 || e1 | -e0 | e3 | -e2 | e5 | -e4 | -e7 | e6 |
269 +----++----+-----+-----+-----+-----+-----+-----+-----+
270 | e2 || e2 | -e3 | -e0 | e1 | e6 | e7 | -e4 | -e5 |
271 +----++----+-----+-----+-----+-----+-----+-----+-----+
272 | e3 || e3 | e2 | -e1 | -e0 | e7 | -e6 | e5 | -e4 |
273 +----++----+-----+-----+-----+-----+-----+-----+-----+
274 | e4 || e4 | -e5 | -e6 | -e7 | -e0 | e1 | e2 | e3 |
275 +----++----+-----+-----+-----+-----+-----+-----+-----+
276 | e5 || e5 | e4 | -e7 | e6 | -e1 | -e0 | -e3 | e2 |
277 +----++----+-----+-----+-----+-----+-----+-----+-----+
278 | e6 || e6 | e7 | e4 | -e5 | -e2 | e3 | -e0 | -e1 |
279 +----++----+-----+-----+-----+-----+-----+-----+-----+
280 | e7 || e7 | -e6 | e5 | e4 | -e3 | -e2 | e1 | -e0 |
281 +----++----+-----+-----+-----+-----+-----+-----+-----+
282
283 """
284 n = self.dimension()
285 # Prepend the header row.
286 M = [["*"] + list(self.gens())]
287
288 # And to each subsequent row, prepend an entry that belongs to
289 # the left-side "header column."
290 M += [ [self.monomial(i)] + [ self.monomial(i)*self.monomial(j)
291 for j in range(n) ]
292 for i in range(n) ]
293
294 from sage.misc.table import table
295 return table(M, header_row=True, header_column=True, frame=True)
296
297
298
299
300
301 class HurwitzMatrixAlgebraElement(MatrixAlgebraElement):
302 def conjugate_transpose(self):
303 r"""
304 Return the conjugate-transpose of this matrix.
305
306 SETUP::
307
308 sage: from mjo.hurwitz import ComplexMatrixAlgebra
309
310 EXAMPLES::
311
312 sage: A = ComplexMatrixAlgebra(2, QQbar, ZZ)
313 sage: M = A([ [ I, 2*I],
314 ....: [ 3*I, 4*I] ])
315 sage: M.conjugate_transpose()
316 +------+------+
317 | -I | -3*I |
318 +------+------+
319 | -2*I | -4*I |
320 +------+------+
321 sage: M.conjugate_transpose().to_vector()
322 (0, -1, 0, -3, 0, -2, 0, -4)
323
324 """
325 entries = [ [ self[j,i].conjugate()
326 for j in range(self.ncols())]
327 for i in range(self.nrows()) ]
328 return self.parent()._element_constructor_(entries)
329
330 def is_hermitian(self):
331 r"""
332
333 SETUP::
334
335 sage: from mjo.hurwitz import (ComplexMatrixAlgebra,
336 ....: HurwitzMatrixAlgebra)
337
338 EXAMPLES::
339
340 sage: A = ComplexMatrixAlgebra(2, QQbar, ZZ)
341 sage: M = A([ [ 0,I],
342 ....: [-I,0] ])
343 sage: M.is_hermitian()
344 True
345
346 ::
347
348 sage: A = HurwitzMatrixAlgebra(2, AA, QQ)
349 sage: M = A([ [1, 1],
350 ....: [1, 1] ])
351 sage: M.is_hermitian()
352 True
353
354 """
355 # A tiny bit faster than checking equality with the conjugate
356 # transpose.
357 return all( self[i,j] == self[j,i].conjugate()
358 for i in range(self.nrows())
359 for j in range(self.ncols()) )
360
361
362 class HurwitzMatrixAlgebra(MatrixAlgebra):
363 r"""
364 A class of matrix algebras whose entries come from a Hurwitz
365 algebra.
366
367 For our purposes, we consider "a Hurwitz" algebra to be the real
368 or complex numbers, the quaternions, or the octonions. These are
369 typically also referred to as the Euclidean Hurwitz algebras, or
370 the normed division algebras.
371
372 By the Cayley-Dickson construction, each Hurwitz algebra is an
373 algebra over the real numbers, so we restrict the scalar field in
374 this case to be real. This also allows us to more accurately
375 produce the generators of the matrix algebra.
376 """
377 Element = HurwitzMatrixAlgebraElement
378
379 def __init__(self, n, entry_algebra, scalars, **kwargs):
380 from sage.rings.all import RR
381 if not scalars.is_subring(RR):
382 # Not perfect, but it's what we're using.
383 raise ValueError("scalar field is not real")
384
385 super().__init__(n, entry_algebra, scalars, **kwargs)
386
387 def entry_algebra_gens(self):
388 r"""
389 Return a tuple of the generators of (that is, a basis for) the
390 entries of this matrix algebra.
391
392 This works around the inconsistency in the ``gens()`` methods
393 of the real/complex numbers, quaternions, and octonions.
394
395 SETUP::
396
397 sage: from mjo.hurwitz import Octonions, HurwitzMatrixAlgebra
398
399 EXAMPLES:
400
401 The inclusion of the unit element is inconsistent across
402 (subalgebras of) Hurwitz algebras::
403
404 sage: AA.gens()
405 (1,)
406 sage: QQbar.gens()
407 (I,)
408 sage: QuaternionAlgebra(AA,1,-1).gens()
409 [i, j, k]
410 sage: Octonions().gens()
411 (e0, e1, e2, e3, e4, e5, e6, e7)
412
413 The unit element is always returned by this method, so the
414 sets of generators have cartinality 1,2,4, and 8 as you'd
415 expect::
416
417 sage: HurwitzMatrixAlgebra(2, AA, AA).entry_algebra_gens()
418 (1,)
419 sage: HurwitzMatrixAlgebra(2, QQbar, AA).entry_algebra_gens()
420 (1, I)
421 sage: Q = QuaternionAlgebra(AA,-1,-1)
422 sage: HurwitzMatrixAlgebra(2, Q, AA).entry_algebra_gens()
423 (1, i, j, k)
424 sage: O = Octonions()
425 sage: HurwitzMatrixAlgebra(2, O, AA).entry_algebra_gens()
426 (e0, e1, e2, e3, e4, e5, e6, e7)
427
428 """
429 gs = self.entry_algebra().gens()
430 one = self.entry_algebra().one()
431 if one in gs:
432 return gs
433 else:
434 return (one,) + tuple(gs)
435
436
437
438 class OctonionMatrixAlgebra(HurwitzMatrixAlgebra):
439 r"""
440 The algebra of ``n``-by-``n`` matrices with octonion entries over
441 (a subfield of) the real numbers.
442
443 The usual matrix spaces in SageMath don't support octonion entries
444 because they assume that the entries of the matrix come from a
445 commutative and associative ring, and the octonions are neither.
446
447 SETUP::
448
449 sage: from mjo.hurwitz import Octonions, OctonionMatrixAlgebra
450
451 EXAMPLES::
452
453 sage: OctonionMatrixAlgebra(3)
454 Module of 3 by 3 matrices with entries in Octonion algebra with base
455 ring Algebraic Real Field over the scalar ring Algebraic Real Field
456
457 ::
458
459 sage: OctonionMatrixAlgebra(3,scalars=QQ)
460 Module of 3 by 3 matrices with entries in Octonion algebra with
461 base ring Rational Field over the scalar ring Rational Field
462
463 ::
464
465 sage: O = Octonions(RR)
466 sage: A = OctonionMatrixAlgebra(1,O)
467 sage: A
468 Module of 1 by 1 matrices with entries in Octonion algebra with
469 base ring Real Field with 53 bits of precision over the scalar
470 ring Algebraic Real Field
471 sage: A.one()
472 +---------------------+
473 | 1.00000000000000*e0 |
474 +---------------------+
475 sage: A.gens()
476 (+---------------------+
477 | 1.00000000000000*e0 |
478 +---------------------+,
479 +---------------------+
480 | 1.00000000000000*e1 |
481 +---------------------+,
482 +---------------------+
483 | 1.00000000000000*e2 |
484 +---------------------+,
485 +---------------------+
486 | 1.00000000000000*e3 |
487 +---------------------+,
488 +---------------------+
489 | 1.00000000000000*e4 |
490 +---------------------+,
491 +---------------------+
492 | 1.00000000000000*e5 |
493 +---------------------+,
494 +---------------------+
495 | 1.00000000000000*e6 |
496 +---------------------+,
497 +---------------------+
498 | 1.00000000000000*e7 |
499 +---------------------+)
500
501 ::
502
503 sage: A = OctonionMatrixAlgebra(2)
504 sage: e0,e1,e2,e3,e4,e5,e6,e7 = A.entry_algebra().gens()
505 sage: A([ [e0+e4, e1+e5],
506 ....: [e2-e6, e3-e7] ])
507 +---------+---------+
508 | e0 + e4 | e1 + e5 |
509 +---------+---------+
510 | e2 - e6 | e3 - e7 |
511 +---------+---------+
512
513 ::
514
515 sage: A1 = OctonionMatrixAlgebra(1,scalars=QQ)
516 sage: A2 = OctonionMatrixAlgebra(1,scalars=QQ)
517 sage: cartesian_product([A1,A2])
518 Module of 1 by 1 matrices with entries in Octonion algebra with
519 base ring Rational Field over the scalar ring Rational Field (+)
520 Module of 1 by 1 matrices with entries in Octonion algebra with
521 base ring Rational Field over the scalar ring Rational Field
522
523 TESTS::
524
525 sage: A = OctonionMatrixAlgebra(ZZ.random_element(10))
526 sage: x = A.random_element()
527 sage: x*A.one() == x and A.one()*x == x
528 True
529
530 """
531 def __init__(self, n, entry_algebra=None, scalars=AA, **kwargs):
532 if entry_algebra is None:
533 entry_algebra = Octonions(field=scalars)
534 super().__init__(n,
535 entry_algebra,
536 scalars,
537 **kwargs)
538
539 class QuaternionMatrixAlgebra(HurwitzMatrixAlgebra):
540 r"""
541 The algebra of ``n``-by-``n`` matrices with quaternion entries over
542 (a subfield of) the real numbers.
543
544 The usual matrix spaces in SageMath don't support quaternion entries
545 because they assume that the entries of the matrix come from a
546 commutative ring, and the quaternions are not commutative.
547
548 SETUP::
549
550 sage: from mjo.hurwitz import QuaternionMatrixAlgebra
551
552 EXAMPLES::
553
554 sage: QuaternionMatrixAlgebra(3)
555 Module of 3 by 3 matrices with entries in Quaternion
556 Algebra (-1, -1) with base ring Algebraic Real Field
557 over the scalar ring Algebraic Real Field
558
559 ::
560
561 sage: QuaternionMatrixAlgebra(3,scalars=QQ)
562 Module of 3 by 3 matrices with entries in Quaternion
563 Algebra (-1, -1) with base ring Rational Field over
564 the scalar ring Rational Field
565
566 ::
567
568 sage: Q = QuaternionAlgebra(RDF, -1, -1)
569 sage: A = QuaternionMatrixAlgebra(1,Q)
570 sage: A
571 Module of 1 by 1 matrices with entries in Quaternion Algebra
572 (-1.0, -1.0) with base ring Real Double Field over the scalar
573 ring Algebraic Real Field
574 sage: A.one()
575 +-----+
576 | 1.0 |
577 +-----+
578 sage: A.gens()
579 (+-----+
580 | 1.0 |
581 +-----+,
582 +---+
583 | i |
584 +---+,
585 +---+
586 | j |
587 +---+,
588 +---+
589 | k |
590 +---+)
591
592 ::
593
594 sage: A = QuaternionMatrixAlgebra(2)
595 sage: i,j,k = A.entry_algebra().gens()
596 sage: A([ [1+i, j-2],
597 ....: [k, k+j] ])
598 +-------+--------+
599 | 1 + i | -2 + j |
600 +-------+--------+
601 | k | j + k |
602 +-------+--------+
603
604 ::
605
606 sage: A1 = QuaternionMatrixAlgebra(1,scalars=QQ)
607 sage: A2 = QuaternionMatrixAlgebra(2,scalars=QQ)
608 sage: cartesian_product([A1,A2])
609 Module of 1 by 1 matrices with entries in Quaternion Algebra
610 (-1, -1) with base ring Rational Field over the scalar ring
611 Rational Field (+) Module of 2 by 2 matrices with entries in
612 Quaternion Algebra (-1, -1) with base ring Rational Field over
613 the scalar ring Rational Field
614
615 TESTS::
616
617 sage: A = QuaternionMatrixAlgebra(ZZ.random_element(10))
618 sage: x = A.random_element()
619 sage: x*A.one() == x and A.one()*x == x
620 True
621
622 """
623 def __init__(self, n, entry_algebra=None, scalars=AA, **kwargs):
624 if entry_algebra is None:
625 # The -1,-1 gives us the "usual" definition of quaternion
626 from sage.algebras.quatalg.quaternion_algebra import (
627 QuaternionAlgebra
628 )
629 entry_algebra = QuaternionAlgebra(scalars,-1,-1)
630 super().__init__(n, entry_algebra, scalars, **kwargs)
631
632 def _entry_algebra_element_to_vector(self, entry):
633 r"""
634
635 SETUP::
636
637 sage: from mjo.hurwitz import QuaternionMatrixAlgebra
638
639 EXAMPLES::
640
641 sage: A = QuaternionMatrixAlgebra(2)
642 sage: u = A.entry_algebra().one()
643 sage: A._entry_algebra_element_to_vector(u)
644 (1, 0, 0, 0)
645 sage: i,j,k = A.entry_algebra().gens()
646 sage: A._entry_algebra_element_to_vector(i)
647 (0, 1, 0, 0)
648 sage: A._entry_algebra_element_to_vector(j)
649 (0, 0, 1, 0)
650 sage: A._entry_algebra_element_to_vector(k)
651 (0, 0, 0, 1)
652
653 """
654 from sage.modules.free_module import FreeModule
655 d = len(self.entry_algebra_gens())
656 V = FreeModule(self.entry_algebra().base_ring(), d)
657 return V(entry.coefficient_tuple())
658
659 class ComplexMatrixAlgebra(HurwitzMatrixAlgebra):
660 r"""
661 The algebra of ``n``-by-``n`` matrices with complex entries over
662 (a subfield of) the real numbers.
663
664 These differ from the usual complex matrix spaces in SageMath
665 because the scalar field is real (and not assumed to be the same
666 as the space from which the entries are drawn). The space of
667 `1`-by-`1` complex matrices will have dimension two, for example.
668
669 SETUP::
670
671 sage: from mjo.hurwitz import ComplexMatrixAlgebra
672
673 EXAMPLES::
674
675 sage: ComplexMatrixAlgebra(3)
676 Module of 3 by 3 matrices with entries in Algebraic Field
677 over the scalar ring Algebraic Real Field
678
679 ::
680
681 sage: ComplexMatrixAlgebra(3,scalars=QQ)
682 Module of 3 by 3 matrices with entries in Algebraic Field
683 over the scalar ring Rational Field
684
685 ::
686
687 sage: A = ComplexMatrixAlgebra(1,CC)
688 sage: A
689 Module of 1 by 1 matrices with entries in Complex Field with
690 53 bits of precision over the scalar ring Algebraic Real Field
691 sage: A.one()
692 +------------------+
693 | 1.00000000000000 |
694 +------------------+
695 sage: A.gens()
696 (+------------------+
697 | 1.00000000000000 |
698 +------------------+,
699 +--------------------+
700 | 1.00000000000000*I |
701 +--------------------+)
702
703 ::
704
705 sage: A = ComplexMatrixAlgebra(2)
706 sage: (I,) = A.entry_algebra().gens()
707 sage: A([ [1+I, 1],
708 ....: [-1, -I] ])
709 +---------+------+
710 | 1 + 1*I | 1 |
711 +---------+------+
712 | -1 | -1*I |
713 +---------+------+
714
715 ::
716
717 sage: A1 = ComplexMatrixAlgebra(1,scalars=QQ)
718 sage: A2 = ComplexMatrixAlgebra(2,scalars=QQ)
719 sage: cartesian_product([A1,A2])
720 Module of 1 by 1 matrices with entries in Algebraic Field over
721 the scalar ring Rational Field (+) Module of 2 by 2 matrices with
722 entries in Algebraic Field over the scalar ring Rational Field
723
724 TESTS::
725
726 sage: A = ComplexMatrixAlgebra(ZZ.random_element(10))
727 sage: x = A.random_element()
728 sage: x*A.one() == x and A.one()*x == x
729 True
730
731 """
732 def __init__(self, n, entry_algebra=None, scalars=AA, **kwargs):
733 if entry_algebra is None:
734 from sage.rings.all import QQbar
735 entry_algebra = QQbar
736 super().__init__(n, entry_algebra, scalars, **kwargs)
737
738 def _entry_algebra_element_to_vector(self, entry):
739 r"""
740
741 SETUP::
742
743 sage: from mjo.hurwitz import ComplexMatrixAlgebra
744
745 EXAMPLES::
746
747 sage: A = ComplexMatrixAlgebra(2, QQbar, QQ)
748 sage: A._entry_algebra_element_to_vector(QQbar(1))
749 (1, 0)
750 sage: A._entry_algebra_element_to_vector(QQbar(I))
751 (0, 1)
752
753 """
754 from sage.modules.free_module import FreeModule
755 d = len(self.entry_algebra_gens())
756 V = FreeModule(self.entry_algebra().base_ring(), d)
757 return V((entry.real(), entry.imag()))