@@@ py_buffer/freebin wip
[catacomb-python] / t / t-convert.py
CommitLineData
553d59fe
MW
1### -*- mode: python, coding: utf-8 -*-
2###
3### Testing implicit conversions
4###
5### (c) 2019 Straylight/Edgeware
6###
7
8###----- Licensing notice ---------------------------------------------------
9###
10### This file is part of the Python interface to Catacomb.
11###
12### Catacomb/Python is free software: you can redistribute it and/or
13### modify it under the terms of the GNU General Public License as
14### published by the Free Software Foundation; either version 2 of the
15### License, or (at your option) any later version.
16###
17### Catacomb/Python is distributed in the hope that it will be useful, but
18### WITHOUT ANY WARRANTY; without even the implied warranty of
19### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20### General Public License for more details.
21###
22### You should have received a copy of the GNU General Public License
23### along with Catacomb/Python. If not, write to the Free Software
24### Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
25### USA.
26
27###--------------------------------------------------------------------------
28### Imported modules.
29
30import catacomb as C
31import sys as SYS
32import unittest as U
33import testutils as T
34
35###--------------------------------------------------------------------------
36class TestConvert (U.TestCase):
37 """Test implicit conversions between various mathematical types."""
38
39 def test(me):
40
41 k = C.PrimeField(17)
42 E = k.ec(-3, 4)
43 P = E(1) # order 15
44 kk = C.BinPolyField(0x13)
45 EE = kk.ec(1, 2)
46 PP = E(9) # order 16
47
48 ## `MP' asymmetric operations.
49 me.assertEqual(pow(C.MP(5), 2), 25)
50 me.assertEqual(pow(5, C.MP(2)), 25)
51 me.assertEqual(pow(C.MP(5), 2, 7), 4)
52 me.assertEqual(pow(5, C.MP(2), 7), 4)
53 me.assertEqual(pow(5, 2, C.MP(7)), 4)
e7d2e2e2 54 for bad in [C.GF, k, kk, str, float, lambda x: [x]]:
553d59fe
MW
55 me.assertRaises(TypeError, pow, C.MP(5), bad(2))
56 me.assertRaises(TypeError, pow, C.MP(5), bad(2), 7)
f7623015 57 if not (T.PY2 and T.DEBUGP):
553d59fe
MW
58 ## Debug builds of Python 2 crash here, and it's not our fault. Run
59 ##
60 ## $ python2.7-dbg -c 'pow(long(5), 2, [7])'
61 ##
62 ## to confirm. The `[7]' causes coercion to occur. The first and
63 ## second operands are coerced first, and successfully replaced by
64 ## the results: the first operand (in this case) is unchanged, but
65 ## has its refcount bumped, and the second operand is replaced by the
66 ## result of coercion, which now has a refcount of 1. Then the first
67 ## and third operands are coerced, which fails. Python decrements
68 ## the refcounts of the results of the first coercion, so the second
69 ## operand is now freed and, in debug builds, clobbered. Python then
70 ## tries to format an error message, quoting the types of the
71 ## operands, but one of them has been lost.
72 me.assertRaises(TypeError, pow, C.MP(5), 2, bad(7))
73 me.assertRaises(TypeError, T.lsl, C.MP(5), bad(2))
74
75 ## `GF' asymmetric operations.
76 me.assertEqual(pow(C.GF(0x5), 2), C.GF(0x11))
77 me.assertEqual(pow(C.GF(0x5), C.MP(2)), C.GF(0x11))
78 me.assertEqual(pow(C.GF(5), 2, C.GF(0x13)), C.GF(0x2))
e7d2e2e2 79 for bad in [k, kk, str, float, lambda x: [x]]:
553d59fe
MW
80 me.assertRaises(TypeError, pow, C.GF(5), bad(2))
81 me.assertRaises(TypeError, T.lsl, C.GF(5), bad(2))
e7d2e2e2 82 for bad in [int, C.MP, k, kk, str, float, lambda x: [x]]:
553d59fe
MW
83 me.assertRaises(TypeError, pow, bad(5), C.GF(2))
84 me.assertRaises(TypeError, pow, bad(5), C.GF(2), bad(7))
85 me.assertRaises(TypeError, pow, bad(5), bad(2), C.GF(7))
86 me.assertRaises(TypeError, pow, C.GF(5), bad(2), bad(7))
f7623015 87 if not (T.PY2 and T.DEBUGP):
553d59fe
MW
88 ## Python bug: see above.
89 me.assertRaises(TypeError, pow, C.GF(5), 2, bad(7))
90
91 ## `MP' and `GF'.
92 me.assertEqual(C.MP(5), 5)
93 me.assertEqual(5, C.MP(5))
e7d2e2e2
MW
94 me.assertNotEqual(C.GF(5), 5)
95 me.assertNotEqual(5, C.GF(5))
712ebf4b
MW
96 me.assertNotEqual(C.MP(5), C.GF(5))
97 me.assertNotEqual(C.GF(5), C.MP(5))
553d59fe
MW
98
99 me.assertEqual(C.MP(5) + 3, 8)
100 me.assertEqual(3 + C.MP(5), 8)
e7d2e2e2
MW
101 me.assertRaises(TypeError, T.add, C.GF(5), 3)
102 me.assertRaises(TypeError, T.add, 3, C.GF(5))
553d59fe
MW
103 me.assertRaises(TypeError, T.add, C.MP(5), C.GF(3))
104 me.assertRaises(TypeError, T.add, C.GF(3), C.MP(5))
e7d2e2e2 105 if T.PY3: me.assertRaises(TypeError, T.le, C.MP(4), C.GF(5))
553d59fe
MW
106
107 ## Field elements.
108 me.assertEqual(k(3) + 4, 7)
109 me.assertEqual(4 + k(3), 7)
110 me.assertEqual(k(3) + C.MP(4), 7)
111 me.assertEqual(C.MP(4) + k(3), 7)
112 me.assertEqual(k(3) + 4, 7)
113 me.assertEqual(C.GF(7) + kk(3), C.GF(4))
114 me.assertEqual(kk(3) + C.GF(7), C.GF(4))
115
f5427c20 116 me.assertRaises(TypeError, T.add, k(3), 3.0)
e7d2e2e2 117 me.assertRaises(TypeError, T.add, k(3), "3")
553d59fe
MW
118 me.assertRaises(TypeError, T.add, k(3), kk(3))
119 me.assertRaises(TypeError, T.add, kk(3), k(3))
f5427c20
MW
120 me.assertRaises(TypeError, T.add, k(3), C.GF(7))
121 me.assertRaises(TypeError, T.add, C.GF(7), k(3))
e7d2e2e2 122 me.assertRaises(TypeError, T.add, kk(3), 7)
f5427c20 123 me.assertRaises(TypeError, T.add, kk(3), 7.0)
e7d2e2e2
MW
124 me.assertRaises(TypeError, T.add, kk(3), "7")
125 me.assertRaises(TypeError, T.add, 7, kk(3))
f5427c20
MW
126 me.assertRaises(TypeError, T.add, kk(3), C.MP(7))
127 me.assertRaises(TypeError, T.add, C.MP(7), kk(3))
553d59fe
MW
128
129###----- That's all, folks --------------------------------------------------
130
131if __name__ == "__main__": U.main()