galois.FieldArray.log(base: ElementLike | ArrayLike | None = None) int | ndarray

Computes the discrete logarithm of the array \(x\) base \(\beta\).

Parameters:
base: ElementLike | ArrayLike | None = None

A primitive element or elements \(\beta\) of the finite field that is the base of the logarithm. The default is None which uses primitive_element.

Slower performance

If the FieldArray is configured to use lookup tables (ufunc_mode == "jit-lookup") and this method is invoked with a base different from primitive_element, then explicit calculation will be used (which is slower than using lookup tables).

Returns:

An integer array \(i\) of powers of \(\beta\) such that \(\beta^i = x\). The return array shape obeys NumPy broadcasting rules.

Examples

Compute the logarithm of \(x\) with default base \(\alpha\), which is the specified primitive element of the field.

In [1]: GF = galois.GF(3**5)

In [2]: alpha = GF.primitive_element; alpha
Out[2]: GF(3, order=3^5)

In [3]: x = GF.Random(10, low=1); x
Out[3]: GF([ 30, 187,  98, 219, 190,   1, 100, 164, 229,  90], order=3^5)

In [4]: i = x.log(); i
Out[4]: array([ 47, 108,  35, 110, 188,   0,  92,  68, 163,  48])

In [5]: assert np.array_equal(alpha ** i, x)
In [6]: GF = galois.GF(3**5, repr="poly")

In [7]: alpha = GF.primitive_element; alpha
Out[7]: GF(α, order=3^5)

In [8]: x = GF.Random(10, low=1); x
Out[8]: 
GF([            α^4 + α^3 + 2α,  2α^4 + α^3 + 2α^2 + α + 2,
            2α^4 + α^3 + α + 1,      α^4 + 2α^3 + 2α^2 + α,
                2α^4 + α^2 + α,                   2α^3 + α,
                      2α^4 + 2, 2α^4 + α^3 + 2α^2 + 2α + 1,
             α^4 + α^2 + α + 2,                    α^4 + 1], order=3^5)

In [9]: i = x.log(); i
Out[9]: array([231,  53, 147,  80,  29, 196,  68, 153, 229, 189])

In [10]: assert np.array_equal(alpha ** i, x)
In [11]: GF = galois.GF(3**5, repr="power")

In [12]: alpha = GF.primitive_element; alpha
Out[12]: GF(α, order=3^5)

In [13]: x = GF.Random(10, low=1); x
Out[13]: 
GF([ α^18, α^140,  α^53,  α^95, α^110, α^232, α^129, α^216,  α^36, α^108],
   order=3^5)

In [14]: i = x.log(); i
Out[14]: array([ 18, 140,  53,  95, 110, 232, 129, 216,  36, 108])

In [15]: assert np.array_equal(alpha ** i, x)

With the default argument, numpy.log() and log() are equivalent.

In [16]: assert np.array_equal(np.log(x), x.log())

Compute the logarithm of \(x\) with a different base \(\beta\), which is another primitive element of the field.

In [17]: beta = GF.primitive_elements[-1]; beta
Out[17]: GF(242, order=3^5)

In [18]: i = x.log(beta); i
Out[18]: array([178,  40,  67,  79,  66, 170, 227, 200, 114, 100])

In [19]: assert np.array_equal(beta ** i, x)
In [20]: beta = GF.primitive_elements[-1]; beta
Out[20]: GF(2α^4 + 2α^3 + 2α^2 + 2α + 2, order=3^5)

In [21]: i = x.log(beta); i
Out[21]: array([178,  40,  67,  79,  66, 170, 227, 200, 114, 100])

In [22]: assert np.array_equal(beta ** i, x)
In [23]: beta = GF.primitive_elements[-1]; beta
Out[23]: GF(α^185, order=3^5)

In [24]: i = x.log(beta); i
Out[24]: array([178,  40,  67,  79,  66, 170, 227, 200, 114, 100])

In [25]: assert np.array_equal(beta ** i, x)

Compute the logarithm of a single finite field element base all of the primitive elements of the field.

In [26]: x = GF.Random(low=1); x
Out[26]: GF(220, order=3^5)

In [27]: bases = GF.primitive_elements

In [28]: i = x.log(bases); i
Out[28]: 
array([205,  17,  41, 163, 181, 207, 135, 141,  69, 219,  81, 149, 167,
       175,  61,  19,  35,   3, 129,  67, 107, 133,  45,  47,  23, 193,
       119, 239,  83,  31, 179, 235,  73,  27, 155, 229, 117,  89,  91,
       189,  85,  75, 159,  29, 195, 109,  25,  79,  53, 157, 221, 137,
         5,  59,   9, 105, 233, 227, 171,  65, 241,  39, 191,  97, 213,
       185, 111,  63,  21,  37, 217, 139, 211, 147, 103,  43, 199, 161,
       153, 127, 151, 113, 125,  71,  87, 101, 215, 197, 203, 237,  49,
       225,  13, 177, 169,  15, 223,   1, 173, 115,  95,  51, 123, 131,
        57, 183,   7,  93, 201, 145])

In [29]: assert np.all(bases ** i == x)
In [30]: x = GF.Random(low=1); x
Out[30]: GF(2α^4 + α^3 + 2α^2 + 2α + 1, order=3^5)

In [31]: bases = GF.primitive_elements

In [32]: i = x.log(bases); i
Out[32]: 
array([153, 139,  79, 137, 213,  27, 207,  71,   9, 239, 221,  51, 127,
       107,  29,  13, 215,  53, 101, 135,  35,  91,  69, 185,   3, 183,
         5, 189,  95, 225,  97, 199, 241, 235, 157,  93, 131, 201,  75,
       193, 211, 115, 147, 109,  57, 151, 119, 105,  49,  31, 113,  81,
       169, 155, 159, 161,  83, 219, 117,  19,  63, 205,  67, 181, 133,
       203,  25, 145, 129,  89, 123, 197,  17, 177,  45, 195,  47,  21,
        41, 227, 167, 141, 111, 125,  85, 171,   7, 173,  37,  73,  59,
       103, 149, 223,   1,  23, 229, 179, 233,  15,  65, 175, 237, 217,
        39,  87,  43, 191, 163,  61])

In [33]: assert np.all(bases ** i == x)
In [34]: x = GF.Random(low=1); x
Out[34]: GF(α^10, order=3^5)

In [35]: bases = GF.primitive_elements

In [36]: i = x.log(bases); i
Out[36]: 
array([ 10, 172,   2, 126, 180,  16,  42,  60,  86,  52, 122,  84, 138,
       162,  62, 178, 226, 130,  24,  80, 200,  36,  14,  20, 190, 216,
       236, 112, 128, 214, 174, 100,  98, 202, 102,  82, 230, 146, 152,
       204, 134, 104, 114, 208, 222, 206, 196, 116,  38, 108,  58,  48,
       136,  56, 148, 194,  94,  76, 150,  74, 118, 238, 210, 170,  34,
       192, 212,  68, 184, 232,  46,  54,  28,  78, 188,   8, 234, 120,
        96,  18,  90, 218,  12,  92, 140, 182,  40, 228,   4, 106,  26,
        70, 160, 168, 144, 166,  64, 124, 156, 224, 164,  32,   6,  30,
        50, 186, 142, 158, 240,  72])

In [37]: assert np.all(bases ** i == x)