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([ 43, 174, 123, 208, 133, 217,  40,  19,   4, 238], order=3^5)

In [4]: i = x.log(); i
Out[4]: array([ 30,  29, 217,  98, 202, 240, 115, 195,  69, 186])

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 + α + 1,                      2α^3,
    2α^4 + α^3 + 2α^2 + α + 1,      2α^4 + 2α^2 + 2α + 2,
         2α^4 + 2α^3 + 2α + 1,       2α^4 + 2α^3 + α + 1,
               α^4 + 2α^3 + 2,        2α^4 + α^2 + α + 2,
                   2α^4 + α^3,        2α^4 + α^3 + α + 2], order=3^5)

In [9]: i = x.log(); i
Out[9]: array([221, 124, 178,  21, 134, 205,  67, 114, 129, 141])

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([α^161, α^147, α^196,  α^23, α^181,  α^54, α^153, α^190, α^115, α^236],
   order=3^5)

In [14]: i = x.log(); i
Out[14]: array([161, 147, 196,  23, 181,  54, 153, 190, 115, 236])

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([167, 163,  56,  93,  69,  50,  61, 158, 223, 102])

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([167, 163,  56,  93,  69,  50,  61, 158, 223, 102])

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([167, 163,  56,  93,  69,  50,  61, 158, 223, 102])

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(106, order=3^5)

In [27]: bases = GF.primitive_elements

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

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

In [31]: bases = GF.primitive_elements

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

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

In [35]: bases = GF.primitive_elements

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

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