chiark / gitweb /
ec.c, field.c, group.c, mp.c: Fix conversions in `pow' and scalar mul.
[catacomb-python] / t / t-convert.py
... / ...
CommitLineData
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)
54 for bad in [C.GF, k, kk, float, lambda x: [x]]:
55 me.assertRaises(TypeError, pow, C.MP(5), bad(2))
56 me.assertRaises(TypeError, pow, C.MP(5), bad(2), 7)
57 if not (T.PY2 and T.DEBUGP):
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))
79 for bad in [k, kk, float, lambda x: [x]]:
80 me.assertRaises(TypeError, pow, C.GF(5), bad(2))
81 me.assertRaises(TypeError, T.lsl, C.GF(5), bad(2))
82 for bad in [C.MP, k, kk, float, lambda x: [x]]:
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))
87 if not (T.PY2 and T.DEBUGP):
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))
94
95 me.assertEqual(C.MP(5) + 3, 8)
96 me.assertEqual(3 + C.MP(5), 8)
97 me.assertRaises(TypeError, T.add, C.MP(5), C.GF(3))
98 me.assertRaises(TypeError, T.add, C.GF(3), C.MP(5))
99
100 ## Field elements.
101 me.assertEqual(k(3) + 4, 7)
102 me.assertEqual(4 + k(3), 7)
103 me.assertEqual(k(3) + C.MP(4), 7)
104 me.assertEqual(C.MP(4) + k(3), 7)
105 me.assertEqual(k(3) + 4, 7)
106 me.assertEqual(C.GF(7) + kk(3), C.GF(4))
107 me.assertEqual(kk(3) + C.GF(7), C.GF(4))
108
109 me.assertRaises(TypeError, T.add, k(3), 3.0)
110 me.assertRaises(TypeError, T.add, k(3), kk(3))
111 me.assertRaises(TypeError, T.add, kk(3), k(3))
112 me.assertRaises(TypeError, T.add, k(3), C.GF(7))
113 me.assertRaises(TypeError, T.add, C.GF(7), k(3))
114 me.assertRaises(TypeError, T.add, kk(3), 7.0)
115 me.assertRaises(TypeError, T.add, kk(3), C.MP(7))
116 me.assertRaises(TypeError, T.add, C.MP(7), kk(3))
117
118###----- That's all, folks --------------------------------------------------
119
120if __name__ == "__main__": U.main()