chiark / gitweb /
ec.c, field.c, group.c, mp.c: Fix conversions in `pow' and scalar mul.
[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)
6311e4f7 54 for bad in [C.GF, k, kk, 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))
6311e4f7 79 for bad in [k, kk, 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))
6311e4f7 82 for bad in [C.MP, k, kk, 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))
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
f5427c20 109 me.assertRaises(TypeError, T.add, k(3), 3.0)
553d59fe
MW
110 me.assertRaises(TypeError, T.add, k(3), kk(3))
111 me.assertRaises(TypeError, T.add, kk(3), k(3))
f5427c20
MW
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))
553d59fe
MW
117
118###----- That's all, folks --------------------------------------------------
119
120if __name__ == "__main__": U.main()