fips-collection 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Aditya Pratap Singh
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,114 @@
1
+ Metadata-Version: 2.4
2
+ Name: fips-collection
3
+ Version: 1.0.0
4
+ Summary: Educational implementations of NIST FIPS cryptographic standard.
5
+ Author: Aditya Pratap Singh
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/kyuuaditya/fips-collection-python
8
+ Project-URL: Documentation, https://kyuuaditya.github.io/fips-collection-python/
9
+ Project-URL: Repository, https://github.com/kyuuaditya/fips-collection-python
10
+ Keywords: cryptography,fips,nist,ml-dsa,mldsa,post-quantum,pqc
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Topic :: Security :: Cryptography
14
+ Requires-Python: >=3.11
15
+ Description-Content-Type: text/markdown
16
+ License-File: LICENSE
17
+ Dynamic: license-file
18
+
19
+ [![License MIT](https://img.shields.io/badge/License-MIT-brightgreen.svg)](https://github.com/kyuuaditya/fips-collection-python/blob/main/LICENSE)
20
+
21
+ # FIPS Standards Implementations
22
+
23
+ > [!CAUTION]
24
+ > :warning: **Under no circumstances should this be used for cryptographic
25
+ applications.** :warning:
26
+ >
27
+ > This is an educational resource and has not been designed to be secure against any form of side-channel attack. The intended use of this project is for learning and experimenting with FIPS Algorithms.
28
+
29
+ This repository contains a **python** implementation of:
30
+
31
+ 1. **ML-DSA** the NIST Module-Lattice-Based Digital Signature Standard following
32
+ the [FIPS 204](https://csrc.nist.gov/pubs/fips/204/final).
33
+
34
+ ## Licenses
35
+
36
+ This project is licensed under the [License MIT](https://github.com/kyuuaditya/fips-collection-python/blob/main/LICENSE).
37
+
38
+ ## Disclaimer
39
+
40
+ This implementation follows instructions given in FIPS 204 as it is for all algorithms.
41
+
42
+ With sole exception of Algorithm 43 BitRev as zeta values are precomputed and hardcoded.
43
+
44
+ ## Documentation
45
+
46
+ Complete documentation of this repository is available at https://kyuuaditya.github.io/fips-collection-python/
47
+
48
+ ## Using fips
49
+
50
+ ### FIPS 204 - MLDSA
51
+
52
+ The `MLDSA` class contains 3 main functions:
53
+
54
+ - `MLDSAKeyGen()`: generates a public-private keypair `(public_key, secret_key)`
55
+ - `MLDSASign(secret_key, Message, ctx)`: generates an MLDSA signature `sigature`
56
+ from the message `message` and bit-packed secret key `secret_key`.
57
+ - `MLDSAVerify(public_key, message, signature)`: verifies a `signature` rho for a `message` M.
58
+
59
+ To use `FIPS 204 - MLDSA` simply import as follows:
60
+
61
+ ```python
62
+ from fips import MLDSA_44, MLDSA_65, MLDSA_87
63
+ ```
64
+
65
+ #### Example Use Case
66
+
67
+ ```python
68
+ from fips import MLDSA_44
69
+
70
+ mldsa128 = MLDSA_44
71
+
72
+ # Generate the public-private key pair.
73
+ public_key, secret_key = mldsa128.MLDSAKeyGen()
74
+
75
+ context = b'ab'
76
+ message = "du bis gut"
77
+ message_spoof = "you are good"
78
+
79
+ # Generate the signature.
80
+ signature = mldsa128.MLDSASign(secret_key, mldsa128.auxilary.BytesToBits(message.encode()), context)
81
+
82
+ # Verification will only pass with the correct corresponding public key.
83
+ assert mldsa128.MLDSAVerify(public_key, mldsa128.auxilary.BytesToBits(message.encode()), signature, context)
84
+
85
+ # Verification will fail with an altered message.
86
+ assert not MLDSA_44.MLDSAVerify(public_key, MLDSA_44.auxilary.BytesToBits(message_spoof.encode()), signature, context)
87
+
88
+ # Verification will fail with any other public key.
89
+ public_key_new, secret_key_new = MLDSA_44.MLDSAKeyGen()
90
+ assert not MLDSA_44.MLDSAVerify(public_key_new, MLDSA_44.auxilary.BytesToBits(message.encode()), signature, context)
91
+ ```
92
+
93
+ The above example would also work with the other NIST levels
94
+ `MLDSA_65` and `MLDSA_87`.
95
+
96
+ #### Hash ML-DSA
97
+
98
+ Algorithm 4 and 5 of FIPS 204 are not yet added to this implementation.
99
+
100
+ ## Benchmarks
101
+
102
+ `FIPS 204 - MLDSA` Performance:
103
+
104
+ | | `MLDSA_44` | `MLDSA_65` | `MLDSA_87` |
105
+ |--------------------------|------------|------------|------------|
106
+ | `KeyGen()` Average Time | 8.4 ms | 14.1 ms | 22.3 ms |
107
+ | `Sign()` Average Time | 78.0 ms | 127.1 ms | 144.3 ms |
108
+ | `Verify()` Average Time | 20.9 ms | 29.9 ms | 43.6 ms |
109
+
110
+ Data recorded using a Ryzen 7 4800H CPU averaged over 1000 calls.
111
+
112
+ ## Colaborations
113
+
114
+ Feel free to modify and share improvements.
@@ -0,0 +1,96 @@
1
+ [![License MIT](https://img.shields.io/badge/License-MIT-brightgreen.svg)](https://github.com/kyuuaditya/fips-collection-python/blob/main/LICENSE)
2
+
3
+ # FIPS Standards Implementations
4
+
5
+ > [!CAUTION]
6
+ > :warning: **Under no circumstances should this be used for cryptographic
7
+ applications.** :warning:
8
+ >
9
+ > This is an educational resource and has not been designed to be secure against any form of side-channel attack. The intended use of this project is for learning and experimenting with FIPS Algorithms.
10
+
11
+ This repository contains a **python** implementation of:
12
+
13
+ 1. **ML-DSA** the NIST Module-Lattice-Based Digital Signature Standard following
14
+ the [FIPS 204](https://csrc.nist.gov/pubs/fips/204/final).
15
+
16
+ ## Licenses
17
+
18
+ This project is licensed under the [License MIT](https://github.com/kyuuaditya/fips-collection-python/blob/main/LICENSE).
19
+
20
+ ## Disclaimer
21
+
22
+ This implementation follows instructions given in FIPS 204 as it is for all algorithms.
23
+
24
+ With sole exception of Algorithm 43 BitRev as zeta values are precomputed and hardcoded.
25
+
26
+ ## Documentation
27
+
28
+ Complete documentation of this repository is available at https://kyuuaditya.github.io/fips-collection-python/
29
+
30
+ ## Using fips
31
+
32
+ ### FIPS 204 - MLDSA
33
+
34
+ The `MLDSA` class contains 3 main functions:
35
+
36
+ - `MLDSAKeyGen()`: generates a public-private keypair `(public_key, secret_key)`
37
+ - `MLDSASign(secret_key, Message, ctx)`: generates an MLDSA signature `sigature`
38
+ from the message `message` and bit-packed secret key `secret_key`.
39
+ - `MLDSAVerify(public_key, message, signature)`: verifies a `signature` rho for a `message` M.
40
+
41
+ To use `FIPS 204 - MLDSA` simply import as follows:
42
+
43
+ ```python
44
+ from fips import MLDSA_44, MLDSA_65, MLDSA_87
45
+ ```
46
+
47
+ #### Example Use Case
48
+
49
+ ```python
50
+ from fips import MLDSA_44
51
+
52
+ mldsa128 = MLDSA_44
53
+
54
+ # Generate the public-private key pair.
55
+ public_key, secret_key = mldsa128.MLDSAKeyGen()
56
+
57
+ context = b'ab'
58
+ message = "du bis gut"
59
+ message_spoof = "you are good"
60
+
61
+ # Generate the signature.
62
+ signature = mldsa128.MLDSASign(secret_key, mldsa128.auxilary.BytesToBits(message.encode()), context)
63
+
64
+ # Verification will only pass with the correct corresponding public key.
65
+ assert mldsa128.MLDSAVerify(public_key, mldsa128.auxilary.BytesToBits(message.encode()), signature, context)
66
+
67
+ # Verification will fail with an altered message.
68
+ assert not MLDSA_44.MLDSAVerify(public_key, MLDSA_44.auxilary.BytesToBits(message_spoof.encode()), signature, context)
69
+
70
+ # Verification will fail with any other public key.
71
+ public_key_new, secret_key_new = MLDSA_44.MLDSAKeyGen()
72
+ assert not MLDSA_44.MLDSAVerify(public_key_new, MLDSA_44.auxilary.BytesToBits(message.encode()), signature, context)
73
+ ```
74
+
75
+ The above example would also work with the other NIST levels
76
+ `MLDSA_65` and `MLDSA_87`.
77
+
78
+ #### Hash ML-DSA
79
+
80
+ Algorithm 4 and 5 of FIPS 204 are not yet added to this implementation.
81
+
82
+ ## Benchmarks
83
+
84
+ `FIPS 204 - MLDSA` Performance:
85
+
86
+ | | `MLDSA_44` | `MLDSA_65` | `MLDSA_87` |
87
+ |--------------------------|------------|------------|------------|
88
+ | `KeyGen()` Average Time | 8.4 ms | 14.1 ms | 22.3 ms |
89
+ | `Sign()` Average Time | 78.0 ms | 127.1 ms | 144.3 ms |
90
+ | `Verify()` Average Time | 20.9 ms | 29.9 ms | 43.6 ms |
91
+
92
+ Data recorded using a Ryzen 7 4800H CPU averaged over 1000 calls.
93
+
94
+ ## Colaborations
95
+
96
+ Feel free to modify and share improvements.
@@ -0,0 +1,46 @@
1
+ [build-system]
2
+ requires = ["setuptools>=69", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "fips-collection"
7
+ version = "1.0.0"
8
+ description = "Educational implementations of NIST FIPS cryptographic standard."
9
+ readme = "README.md"
10
+ requires-python = ">=3.11"
11
+
12
+ license = "MIT"
13
+ license-files = ["LICENSE"]
14
+
15
+ authors = [
16
+ {name = "Aditya Pratap Singh"}
17
+ ]
18
+
19
+ keywords = [
20
+ "cryptography",
21
+ "fips",
22
+ "nist",
23
+ "ml-dsa",
24
+ "mldsa",
25
+ "post-quantum",
26
+ "pqc"
27
+ ]
28
+
29
+ classifiers = [
30
+ "Programming Language :: Python :: 3",
31
+ "Operating System :: OS Independent",
32
+ "Topic :: Security :: Cryptography",
33
+ ]
34
+
35
+ dependencies = []
36
+
37
+ [project.urls]
38
+ Homepage = "https://github.com/kyuuaditya/fips-collection-python"
39
+ Documentation = "https://kyuuaditya.github.io/fips-collection-python/"
40
+ Repository = "https://github.com/kyuuaditya/fips-collection-python"
41
+
42
+ [tool.setuptools]
43
+ package-dir = {"" = "src"}
44
+
45
+ [tool.setuptools.packages.find]
46
+ where = ["src"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,10 @@
1
+ from .parameter import(
2
+ MLDSA_44, MLDSA_65, MLDSA_87
3
+ )
4
+
5
+
6
+ __all__ = [
7
+ "MLDSA_44",
8
+ "MLDSA_65",
9
+ "MLDSA_87",
10
+ ]
@@ -0,0 +1,369 @@
1
+ class AUXILARY:
2
+ """
3
+ This class provides subroutines utilized by MLDSA, including function for data-type converstions and arithmetic.
4
+ """
5
+
6
+ def __init__(self, parameter: dict[str, int]):
7
+ self.q = parameter["q"]
8
+ self.N = parameter["N"]
9
+ self.eta = parameter["eta"]
10
+
11
+ def IntegerToBits(self, x: int, alpha: int):
12
+ """
13
+ Algorithm 9
14
+
15
+ Computes the base-2 representation of x mod 2^alpha in ``little-endian`` order.
16
+
17
+ Args:
18
+ x (``int``): A ``non-negative`` integer.
19
+ alpha (``int``): Number of ``bits`` to represent.
20
+
21
+ Returns:
22
+ str (``bits``): ``Bitstring`` of length ``alpha`` in ``little-endian`` order.
23
+
24
+ Raises:
25
+ ValueError: If x is ``negative`` or alpha is not a positive integer.
26
+ ValueError: If x is ``too big`` to be represented in alpha bits.
27
+ TypeError: If x or alpha is ``not an integer``.
28
+ """
29
+
30
+ if x < 0:
31
+ raise ValueError("x must be non-negative.")
32
+ if alpha <= 0:
33
+ raise ValueError("alpha must be a positive integer.")
34
+ if x >= 2 ** alpha:
35
+ raise ValueError(f"x = {x} cannot be represented in {alpha} bits.")
36
+
37
+ x_mod = x
38
+ bits:list[str] = []
39
+ for _ in range(alpha):
40
+ bits.append(str(x_mod % 2))
41
+ x_mod //= 2
42
+
43
+ return ''.join(bits)
44
+
45
+ def BitsToInteger(self, y: str, alpha: int) -> int:
46
+ """
47
+ Algorithm 10
48
+
49
+ Computes the ``integer`` value expressed by a bit string using ``little-endian`` order.
50
+
51
+ Args:
52
+ y (``bitstring``): ``Bitstring`` to convert to an integer.
53
+ alpha (``int``): Number of ``bits`` to consider.
54
+
55
+ Returns:
56
+ integer (``int``): The ``integer`` value represented by the ``bitstring``.
57
+
58
+ Raises:
59
+ ValueError: If the length of ``y`` does not match alpha or if ``y`` contains invalid characters.
60
+ TypeError: If ``y`` is not a ``string`` or alpha is not an ``integer``.
61
+ """
62
+ if alpha <= 0:
63
+ raise ValueError("alpha must be a positive integer.")
64
+ if len(y) != alpha:
65
+ raise ValueError(f"Bit string y must have exactly {alpha} bits.")
66
+ if any(bit not in "01" for bit in y):
67
+ raise ValueError("Bit string y must contain only '0' and '1' characters.")
68
+
69
+ x = 0
70
+ for i in range(1, alpha + 1):
71
+ bit = int(y[alpha - i])
72
+ x = 2 * x + bit
73
+ return x
74
+
75
+ def IntegerToBytes(self, x: int, alpha: int) -> bytes:
76
+ """
77
+ Algorithm 11
78
+
79
+ Computes a base-256 representation of x mod 256^alpha in ``little-endian`` order.
80
+
81
+ Args:
82
+ x (``int``): A ``non-negative`` integer.
83
+ alpha (``int``): Number of ``bytes`` in the output.
84
+
85
+ Returns:
86
+ bytes (``bytes``): ``Bytestring`` of length alpha in ``little-endian`` order.
87
+
88
+ Raises:
89
+ ValueError: x = _ cannot be represented in _ bytes.
90
+ """
91
+ try:
92
+ return x.to_bytes(alpha, byteorder = "little")
93
+ except OverflowError:
94
+ raise ValueError(f"x = {x} cannot be represented in {alpha} bytes.")
95
+
96
+ def BitsToBytes(self, y: str) -> bytes:
97
+ """
98
+ Algorithm 12
99
+
100
+ Converts a ``bitstring`` y into a ``bytestring`` using ``little-endian`` order.
101
+
102
+ Args:
103
+ y (``str``): ``Bitstring`` consisting of ``0`` and ``1``.
104
+
105
+ Returns:
106
+ bytes (``bytes``): ``Bytestring`` of length ceil ``(len(y) / 8)``.
107
+
108
+ Raises:
109
+ TypeError: If y is ``not a string``.
110
+ ValueError: If y contains characters other than ``0`` or ``1``.
111
+ """
112
+ if any(bit not in "01" for bit in y):
113
+ raise ValueError("Bit string y must contain only '0' and '1'.")
114
+
115
+ alpha = len(y)
116
+ byte_len = (alpha + 7) // 8 # Equivalent to ceil(alpha / 8)
117
+ z = [0] * byte_len
118
+
119
+ for i in range(alpha):
120
+ byte_index = i // 8
121
+ bit_index = i % 8
122
+ z[byte_index] |= int(y[i]) << bit_index
123
+
124
+ return bytes(z)
125
+
126
+ def BytesToBits(self, z: bytes) -> str:
127
+ """
128
+ Algorithm 13
129
+
130
+ Converts a ``bytestring`` ``z`` into a ``bitstring`` in ``little-endian`` order.
131
+
132
+ Args:
133
+ z (``bytes``): A ``bytestring``.
134
+
135
+ Returns:
136
+ str (bit string): A ``bitstring`` of length ``8 * len(z)``, in ``little-endian`` order.
137
+
138
+ Raises:
139
+ TypeError: If ``z`` is not a ``bytes`` object.
140
+ """
141
+ if not isinstance(z, (bytes, bytearray)):
142
+ raise TypeError("Input z must be a bytes or bytearray object.")
143
+
144
+ bits: list[str] = []
145
+ for byte in z:
146
+ for i in range(8):
147
+ bits.append(str((byte >> i) & 1)) # Little-endian bit order
148
+
149
+ return ''.join(bits)
150
+
151
+ def CoeffFromThreeBytes(self, b0: int, b1: int, b2:int) -> int | None:
152
+ """
153
+ Algorithm 14
154
+
155
+ Generates an element of {``0``, ``1``, ``2``, ... , ``q - 1``} U { ``None`` }
156
+
157
+ Args:
158
+ b0 (``int``): first byte
159
+ b1 (``int``): second byte
160
+ b2 (``int``): third byte
161
+
162
+ Returns:
163
+ z (``int``): sampled coefficient or ``None`` if rejected.
164
+
165
+ Raises:
166
+ TypeError: if any of ``b0``, ``b1``, ``b2`` is ``not an integer``.
167
+ """
168
+ # checks for validity of inputs.
169
+ for i, b in enumerate((b0, b1, b2), start = 0):
170
+ if not (0 <= b <= 255):
171
+ raise ValueError (f"b{i} must be in the range 0 - 255.")
172
+
173
+ # line 1: make a copy of b2.
174
+ b2_prime = b2
175
+
176
+ # line 2 to 4: making sure b2_prime is 7 bits, not 8.
177
+ if b2_prime > 127:
178
+ b2_prime = b2_prime - 128
179
+
180
+ # line 5: evaluate z for sampling.
181
+ z = (b2_prime << 16) + (b1 << 8) + b0
182
+
183
+ # line 6 to 8: reject the sample z if it's greater than q.
184
+ if z < self.q:
185
+ return z # accept sample
186
+ else:
187
+ return None # reject sample
188
+
189
+ def CoeffFromHalfByte(self, b: int) -> int | None:
190
+ """
191
+ Algorithm 15
192
+
193
+ Let ``eta`` ∈ {2, 4}.
194
+
195
+ Generates an element of {``-eta``, ``-eta + 1``, ... , ``eta``} U { ``None`` }
196
+
197
+ Args:
198
+ b (``int``): an integer in the range ``0 - 15``.
199
+
200
+ Returns:
201
+ z (``int``): sampled coefficient or ``None`` if rejected.
202
+
203
+ Raises:
204
+ TypeError: if b is ``not an integer``.
205
+ ValueError: if b is ``not`` in the range ``0 - 15``.
206
+ """
207
+ if not (0 <= b <= 15):
208
+ raise ValueError (f"{b} must be in the range 0 - 15.")
209
+
210
+ # line 1 and 2: rejection sampline from {-2, ... , 2 }
211
+ if self.eta == 2 and b < 15:
212
+ return 2 - (b % 5)
213
+
214
+ # line 3: rejection sampline from {-4, ... , 4 }
215
+ elif self.eta == 4 and b < 9:
216
+ return 4 - b
217
+
218
+ # line 4: sample is just rejected.
219
+ else:
220
+ return None
221
+
222
+ def CenteredModulus(self, z: int) -> int:
223
+ """
224
+ Additional Helper Function 1
225
+
226
+ Computes the centered modulus ``z mod± q``.
227
+
228
+ Maps each integer ``x`` to the unique ``r`` in ::
229
+
230
+ [-(q-1)/2, (q-1)/2]
231
+
232
+ such that ::
233
+
234
+ x ≡ r (mod q).
235
+
236
+ Args:
237
+ z(``int``): An integer
238
+
239
+ Returns:
240
+ CenteredModulus(``int``)
241
+
242
+ Raises:
243
+ TypeError: If ``z`` is ``not an integer``.
244
+ """
245
+ half_q = (self.q - 1) // 2
246
+
247
+ return (z + half_q) % self.q - half_q
248
+
249
+ def CenteredModulusList(self, z: list[int]) -> list[int]:
250
+ """
251
+ Additional Helper Function 2
252
+
253
+ Computes the centered modulus ``z mod± q`` for a ``list`` of ``Integers``.
254
+
255
+ Maps each integer ``x`` to the unique ``r`` in ::
256
+
257
+ [-(q-1)/2, (q-1)/2]
258
+
259
+ such that ::
260
+
261
+ x ≡ r (mod q).
262
+
263
+ Args:
264
+ z(``list[int]``): A list of ``integers``.
265
+
266
+ Returns:
267
+ CenteredModulus(``list[int]``)
268
+
269
+ Raises:
270
+ TypeError: If ``z`` is not a ``list[int]``.
271
+ """
272
+ half_q = (self.q - 1) // 2
273
+
274
+ return [(x + half_q) % self.q - half_q for x in z]
275
+
276
+ def CenteredModulusMatrix(self, z: list[list[int]]) -> list[list[int]]:
277
+ """
278
+ Additional Helper Function 3
279
+
280
+ Computes the centered modulus ``z mod± q`` for a ``matrix`` of ``Integers``.
281
+
282
+ Maps each integer ``x`` to the unique ``r`` in ::
283
+
284
+ [-(q-1)/2, (q-1)/2]
285
+
286
+ such that ::
287
+
288
+ x ≡ r (mod q).
289
+
290
+ Args:
291
+ z(``list[list[int]]``): A matrix of ``integers``.
292
+
293
+ Returns:
294
+ CenteredModulus(``list[list[int]]``)
295
+
296
+ Raises:
297
+ TypeError: If ``z`` is not a ``list[list[int]]``.
298
+ """
299
+
300
+ half_q = (self.q - 1) // 2
301
+
302
+ return [[(x + half_q) % self.q - half_q for x in z[k]] for k in range(len(z))]
303
+
304
+ def abs_for_list (self, z: list[int]) -> list[int]:
305
+ """
306
+ Additional Helper Function 4
307
+
308
+ Computes the absolute values of a ``list`` of integers.
309
+
310
+ Args:
311
+ z (``list[int]``): A ``list`` of integers.
312
+
313
+ Returns:
314
+ |z| (``list[int]``): A ``list`` containing the ``absolute`` values of the input ``integers``.
315
+ """
316
+ for p in range (len(z)):
317
+ z[p] = abs(z[p])
318
+
319
+ return z
320
+
321
+ def InfinityNorm(self, z: list[list[int]]) -> int:
322
+ """
323
+ Additional Helper Function 5
324
+
325
+ Compute the ``L-Infinity Norm`` of a ``Matrix``.
326
+
327
+ Args:
328
+ z (``list[list[int]]``): A ``Matrix`` of integers.
329
+
330
+ Returns:
331
+ infinity_norm (``int``): The infinity norm (``maximum`` absolute value) among all lists.
332
+
333
+ Raises:
334
+ TypeError: If ``z`` is not a list of lists of ``integers``.
335
+ TypeError: If any element in the sublists is ``not an integer``.
336
+ TypeError: If elements of ``z[x]`` are not lists.
337
+ """
338
+ max_value = 0
339
+
340
+ for i in range (len(z)):
341
+ if max_value < max(self.abs_for_list(self.CenteredModulusList(z[i]))):
342
+ max_value = max(self.abs_for_list(self.CenteredModulusList(z[i])))
343
+
344
+ return max_value # returns the max value among all lists.
345
+
346
+ def CalcOnes(self, h: list[list[int]]) -> int:
347
+ """
348
+ Additional Helper Function 6
349
+
350
+ Compute the number of ``1`` s inside a ``list[list[int]]`` .
351
+
352
+ Args:
353
+ h (``list[list[int]]``): A ``matrix`` containing ``0`` s and ``1`` s.
354
+
355
+ Returns:
356
+ Count(``int``): The count of ``1`` s in the ``matrix``.
357
+
358
+ Raises:
359
+ TypeError: If ``h`` is not a ``matrix`` of integers.
360
+ TypeError: If any element in the sublists is not an integer .
361
+ TypeError: If elements of ``h[x]`` are not ``0`` or ``1``.
362
+ """
363
+ count = 0
364
+ for i in range(len(h)):
365
+ for j in range(len(h[i])):
366
+ if h[i][j] == 1:
367
+ count = count + 1
368
+
369
+ return count