public static int FindMoveIndex(MGMove[] moves, ConverterMGMoveEncodedMove.FromTo moveSquares, int startIndex, int numMovesUsed) { short fromAndTo = moveSquares.FromAndToCombined; // partially unroll the loop to improve instruction-level parallelism int i = startIndex; while (i < numMovesUsed - 3) { if (moves[i].FromAndToCombined == fromAndTo) { return(i); } if (moves[i + 1].FromAndToCombined == fromAndTo) { return(i + 1); } if (moves[i + 2].FromAndToCombined == fromAndTo) { return(i + 2); } if (moves[i + 3].FromAndToCombined == fromAndTo) { return(i + 3); } i += 4; } while (i < numMovesUsed) { if (moves[i].FromAndToCombined == fromAndTo) { return(i); } i++; } return(-1); }
// -------------------------------------------------------------------------------------------- internal unsafe static int FindMoveIndexAVX(MGMove[] moves, ConverterMGMoveEncodedMove.FromTo moveSquares, int startIndex, int numMovesUsed) { // Use non-AVX version if few move to check if (numMovesUsed - startIndex < 12) { return(MoveInMGMovesArrayLocator.FindMoveIndex(moves, moveSquares, startIndex, numMovesUsed)); } void * ptrStart = Unsafe.AsPointer(ref moves[0]); Span <int> ints = new Span <int>(ptrStart, numMovesUsed); int foundIndex = FindIndexOfShortAtEvenIndexHavingValue(ints, moveSquares.FromAndToCombined, startIndex, numMovesUsed - 1); if (foundIndex == -2) { // The AVX routine found a false pseudo-match at odd index // Fallback to non AVX version // This is expected to happen only very rarely return(MoveInMGMovesArrayLocator.FindMoveIndex(moves, moveSquares, startIndex, numMovesUsed)); } return(foundIndex); }