Efficient calculation of difference sets from finite fields

A while ago I wrote a program to generate, amongst other things, difference sets from finite fields. Generating these sets is rather slow. Is there some theorem or construction I could use to speed it up?

I basically use the method shown in Singer(1938). Starting with an $$a$$ dimensional monic primitive polynomial $$g_d$$ over $$\mathbb{F}_{p^b} = \mathbb{F}_p(k)$$. If $$v$$ is a root of $$g_d$$ then non-zero elements of $$\mathbb{F}_p(v)$$ can be expressed as a power of $$v$$ or as a max degree $$a-1$$ polynomial over $$v$$ with coefficients $$c_n \in \mathbb{F}_p(k)$$.

$$v^n=\sum_{i = 0}^{a-1} c_i\:v^i$$

To find the difference set, I iteratively raised the power of $$v$$ up to $$v^{\frac{p^{ab}-1}{p^b-1}-1}$$, recording which powers of $$v$$ produced polynomials where $$c_{a-1} = 0$$.

Of course, I also have to get $$g_d$$, but even when I find all valid and distinct $$g_d$$ polynomials, calculating the difference sets is by far the slowest part. For $$p = 5, a = 3, b = 2$$, finding the difference sets slows the program down by an order of magnitude.

An observation I did make is that it is the parent degree $$ab$$ polynomial over $$\mathbb{F}_p$$, $$f_m$$, not $$g_d$$, that determines what specific difference set we get, since $$0$$ is a fixed point of $$r \mapsto r^p$$. I thought about directly starting from the vector space representation, but that involves finding the discrete log of complicated polynomials over $$k$$ and $$v$$ versus simple shift and carry operations.

• Just checking one thing for I'm anything but sure what you are looking for. Presumably you know the minimal polynomial of $v$ over the smaller field, say $$v^a=\sum_{j=1}^aA_jv^{a-j},\ A_j\in\Bbb{F}_{p^b}.$$ Because the trace is linear over the smaller field, the same recurrence relation holds between the traces of consecutive powers of $v$. If $s(i)=tr(v^i)$ we have, for all $i$. $$s(i+a)=\sum_{j=}^a A_j s(i+a-j).\qquad(*)$$ If I correctly looked up the definition of Singer difference sets, then it consists of those indices $i$ such that $s(i)=0$. – Jyrki Lahtonen Apr 24 at 4:07
• (cont'd) So you need to calculate the traces of the low powers $s(j)=tr(v^j),j=0,1,\ldots,a-1$, and then apply $(*)$ ever after until we start scaled repetitions at $j=(p^{ab}-1)/(p^b-1)$. – Jyrki Lahtonen Apr 24 at 4:09
• A catch is that I'm not sure trace always matches with the coefficient of degree $a-1$ term of $v^j$ written as a low degree polynomial of $v$. But, because that is another linear function (and those are all gotten as scaled traces), you get a translate of the Singer difference set. Heck, you can also simply forget about the trace, and simply check for that coefficient of degree $a-1$ term. For it, too, satisfies the recurrence $(*)$, and you are given that the sequence begins with $0,0,0,\ldots,1$ ($a-1$ zeros followed by a single $1$). – Jyrki Lahtonen Apr 24 at 4:14
• (cont'd) You still end up needeing to cycle through it. So, if you are looking for something faster, this did not help at all. May be you were actually doing exactly this, I'm not sure. Anyway, as you observed, the alternative of calculating discrete logs is a non-starter, – Jyrki Lahtonen Apr 24 at 4:17
• I edited my question to make it more clear what I was doing. I did some thinking and coding and I think I made the poly-log route viable. – del42z Apr 24 at 13:55

Assume you have the following things:

• Log tables for $$u$$, an arbitrary primitive element of $$\Bbb{F}_p(v)$$
• The log $$u$$ values of $$k$$ and $$v$$

You are likely to have these on hand from when you generated $$g_d$$ in the first place. Then we can generate the desired logs base $$v$$ easily.

We want to generate the logs of all non-zero $$k$$-$$v$$ polynomials with $$v$$-degree less than $$a-1$$ up to multiplication by $$r \in \Bbb{F}_p(k)^{\times}$$. If we were fully efficient in iteration we'd only have to iterate over $$\frac{p^{(a-1)b}-1}{p^b-1}$$ polynomials, a saving of nearly $$p^b$$-fold iterations. Here's how you can efficiently iterate over the desired polynomials

#pre-defined functions/lists/etc. needed
logu(x): finds logs base u
alogu(y): finds antlogs base u
modinv(z, period): finds the modular inverse.

#constants
p, a, b: given parameters
per, kper: (p^(ab) - 1) and (p^b - 1) respectively
beat = per/kper

d = logu(v)
lk = logu(k)
dinv = modinv(d, per)

let plog_list be an empty list

for i from 0 to a-2:
let temp_list be an empty list

for cof from 0 to kper-1:
ucof = cof*lk
term = ucof + d*i
np = (alogu(term mod per) + alogu(plog)) mod p
nplog = logu(np)

put d*i into temp_list
put all elements of temp_list into plog_list

let diff_set = {(x*dinv) mod beat | x in plog_list}


The basic idea for this iteration is as follows:

The $$i$$th step starts with all non-zero polynomials with $$v$$-degree at most $$i-1$$ whose lowest non-zero term has coefficient $$1$$. For each polynomial $$t$$ we start with and for each coefficient $$r \in \Bbb{F}_p(k)^{\times}$$, we put $$rv^i + t$$ in our working set. After all of this, we add $$v^i$$ to out working set, then merge our working and starting sets together and pass it to the $$i+1$$th step.

The other advantage here is that you're nearly always working with integers, while the shift-and-carry method almost certainly uses bulkier data types more often.