aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/docs.yml5
-rw-r--r--pyecsca/ec/mod.py43
2 files changed, 44 insertions, 4 deletions
diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
index fcfb66c..eb87a63 100644
--- a/.github/workflows/docs.yml
+++ b/.github/workflows/docs.yml
@@ -9,6 +9,7 @@ env:
LLVM_CONFIG: /usr/bin/llvm-config-10
PS_PACKAGES: libps4000 libps5000 libps6000
GMP_PACKAGES: libgmp-dev libmpfr-dev libmpc-dev
+ FLINT_PACKAGES: libflint-dev
OTHER_PACKAGES: pandoc swig gcc libpcsclite-dev llvm-10 libllvm10 llvm-10-dev libpari-dev pari-gp pari-seadata gcc-arm-none-eabi binutils-arm-none-eabi libnewlib-arm-none-eabi
jobs:
@@ -50,7 +51,7 @@ jobs:
sudo apt-get update
- name: Install system dependencies
run: |
- sudo apt-get install -y $PS_PACKAGES $OTHER_PACKAGES $GMP_PACKAGES
+ sudo apt-get install -y $PS_PACKAGES $OTHER_PACKAGES $GMP_PACKAGES $FLINT_PACKAGES
- name: Install picoscope bindings
run: |
python -m pip install -U pip setuptools wheel
@@ -59,7 +60,7 @@ jobs:
- name: Install pyecsca
working-directory: pyecsca
run: |
- pip install -e ".[picoscope_sdk, picoscope_alt, chipwhisperer, smartcard, gmp, leia, test, dev, doc]"
+ pip install -e ".[picoscope_sdk, picoscope_alt, chipwhisperer, smartcard, gmp, flint, leia, test, dev, doc]"
- name: Install pyecsca-codegen
working-directory: pyecsca-codegen
run: |
diff --git a/pyecsca/ec/mod.py b/pyecsca/ec/mod.py
index 4221a93..7637fd4 100644
--- a/pyecsca/ec/mod.py
+++ b/pyecsca/ec/mod.py
@@ -5,7 +5,8 @@ The base class :py:class:`Mod` dynamically
dispatches to the implementation chosen by the runtime configuration of the library
(see :py:class:`pyecsca.misc.cfg.Config`). A Python integer based implementation is available under
:py:class:`RawMod`. A symbolic implementation based on sympy is available under :py:class:`SymbolicMod`. If
-`gmpy2` is installed, a GMP based implementation is available under :py:class:`GMPMod`.
+`gmpy2` is installed, a GMP based implementation is available under :py:class:`GMPMod`. If `python-flint` is
+installed, a flint based implementation is available under :py:class:`FlintMod`.
"""
import random
import secrets
@@ -162,7 +163,40 @@ _mod_order = ["gmp", "flint", "python"]
@public
class Mod:
- """An element x of ℤₙ."""
+ """
+ An element x of ℤₙ.
+
+ .. note::
+ This class dispatches to one of :py:class:`RawMod`, :py:class:`GMPMod` or :py:class:`FlintMod`
+ based on what packages are installed and what implementation is configured (see
+ :py:module:`pyecsca.misc.cfg`).
+
+ Has all the usual special methods that upcast integers automatically:
+
+ >>> a = Mod(3, 5)
+ >>> b = Mod(2, 5)
+ >>> a + b
+ 0
+ >>> a * 2
+ 1
+ >>> a == 3
+ True
+ >>> a == -2
+ True
+ >>> -a
+ 2
+
+ Plus some additional useful things:
+
+ >>> a.inverse()
+ 2
+ >>> a.is_residue()
+ False
+ >>> (a**2).is_residue()
+ True
+ >>> (a**2).sqrt() == a
+ True
+ """
x: Any
n: Any
@@ -204,6 +238,11 @@ class Mod:
return self.__class__(self.n - self.x, self.n)
def bit_length(self):
+ """
+ Compute the bit length of this element (in its positive integer representation).
+
+ :return: The bit-length.
+ """
raise NotImplementedError
def inverse(self) -> "Mod":