Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 19 additions & 5 deletions src/vec8bit.c
Original file line number Diff line number Diff line change
Expand Up @@ -2482,6 +2482,7 @@ static UInt CosetLeadersInner8Bits(Obj veclis,
UInt elts;
UInt1 * ptr, *ptrw;
const UInt1 * gettab;
const Obj * gapseq;
const UInt1 * feltffe;
Obj x;
Obj vp;
Expand All @@ -2491,20 +2492,29 @@ static UInt CosetLeadersInner8Bits(Obj veclis,
elts = ELS_BYTE_FIELDINFO_8BIT(info);
settab = SETELT_FIELDINFO_8BIT(info);
gettab = GETELT_FIELDINFO_8BIT(info);
gapseq = GAPSEQ_FELT_FIELDINFO_8BIT(info);
ptrw = BYTES_VEC8BIT(w);
if (weight == 1) {
for (i = pos; i <= len; i++) {
vp = ELM_PLIST(veclis, i);
u = ELM_PLIST(vp, 1);
AddVec8BitVec8BitInner(w, w, u, 1, lenw);
ptr = BYTES_VEC8BIT(v) + (i - 1) / elts;
*ptr = settab[*ptr + 256 * (elts + ((i - 1) % elts))];
// Keep the coefficient vector in the same sorted field-element
// order that NumberFFVector uses for list indices.
feltffe = FELT_FFE_FIELDINFO_8BIT(info);
x = ELM_PLIST(felts, 2);
*ptr = settab[*ptr + 256 * (elts * feltffe[VAL_FFE(x)] +
((i - 1) % elts))];
sy = 0;
for (j = 0; j < lenw; j++) {
UInt xxxx;
sy *= q;
xxxx = gettab[ptrw[j / elts] + 256 * (j % elts)];
sy += xxxx;
// The packed 8-bit representation uses a different internal
// field ordering, so translate back to GAP's sequence before
// using the syndrome number as a plain-list position.
sy += INT_INTOBJ(gapseq[xxxx]);
}
if ((Obj)0 == ELM_PLIST(leaders, sy + 1)) {
UInt k;
Expand All @@ -2517,22 +2527,26 @@ static UInt CosetLeadersInner8Bits(Obj veclis,
wc = ZeroVec8Bit(q, lenw, 1);
settab = SETELT_FIELDINFO_8BIT(info);
gettab = GETELT_FIELDINFO_8BIT(info);
gapseq = GAPSEQ_FELT_FIELDINFO_8BIT(info);
ptr = BYTES_VEC8BIT(v) + (i - 1) / elts;
ptrw = BYTES_VEC8BIT(w);
for (k = 2; k < q; k++) {
qk = FFE_FELT_FIELDINFO_8BIT(info, k);
for (k = 3; k <= q; k++) {
// Record scalar multiples in the same order as the GAP
// fallback, namely the sorted field elements in 'felts'.
qk = ELM_PLIST(felts, k);
MultVec8BitFFEInner(wc, w, qk, 1, lenw);
ptrw = BYTES_VEC8BIT(wc);
sy = 0;
for (j = 0; j < lenw; j++) {
UInt xxxx;
sy *= q;
xxxx = gettab[ptrw[j / elts] + 256 * (j % elts)];
sy += xxxx;
sy += INT_INTOBJ(gapseq[xxxx]);
}
vc = ZeroVec8Bit(q, len, 0);
settab = SETELT_FIELDINFO_8BIT(info);
gettab = GETELT_FIELDINFO_8BIT(info);
gapseq = GAPSEQ_FELT_FIELDINFO_8BIT(info);
ptr = BYTES_VEC8BIT(v) + (i - 1) / elts;
ptrw = BYTES_VEC8BIT(w);
MultVec8BitFFEInner(vc, v, qk, 1, len);
Expand Down
33 changes: 33 additions & 0 deletions tst/testbugfix/2026-04-15-issue-5923.tst
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Regression test for issue #5923: the 8-bit kernel path for
# CosetLeadersMatFFE must not leave holes in the result list.
gap> F := GF(4);;
gap> M := One(F)*[[1,0,Z(4)],[0,1,Z(4)^2]];;
gap> L := CosetLeadersMatFFE(M, F);;
gap> Length(L) = Size(F)^2;
true
gap> ForAll([1..Length(L)], i -> IsBound(L[i]));
true
gap> List(L, v -> NumberFFVector(M * v, Size(F))) = [0..Length(L)-1];
true

# some additional tests "because we can" for other cases
gap> F := GF(2);;
gap> M := One(F)*[[1,0,1,0,1,0],[1,1,1,0,0,0]];;
gap> L := CosetLeadersMatFFE(M, F);;
gap> Length(L) = Size(F)^2;
true
gap> ForAll([1..Length(L)], i -> IsBound(L[i]));
true
gap> List(L, v -> NumberFFVector(M * v, Size(F))) = [0..Length(L)-1];
true

# some additional tests "because we can" for other cases
gap> F := GF(257);;
gap> M := One(F)*[[1,0,1,0,1,0],[1,1,1,0,0,0]];;
gap> L := CosetLeadersMatFFE(M, F);;
gap> Length(L) = Size(F)^2;
true
gap> ForAll([1..Length(L)], i -> IsBound(L[i]));
true
gap> List(L, v -> NumberFFVector(M * v, Size(F))) = [0..Length(L)-1];
true
Loading