From 9afcc582e6c3068855fb48e7098ba35ce036342c Mon Sep 17 00:00:00 2001 From: preciz Date: Sat, 15 Aug 2026 21:45:52 +0200 Subject: [PATCH] Optimize functional selector matching Instead of generating an+b values until one matches, solve the formula directly with bounds and a remainder check. This turns each match from a stream scan into O(1) arithmetic. --- lib/floki/selector/pseudo_class.ex | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/floki/selector/pseudo_class.ex b/lib/floki/selector/pseudo_class.ex index 0ca506cb..15b85325 100644 --- a/lib/floki/selector/pseudo_class.ex +++ b/lib/floki/selector/pseudo_class.ex @@ -98,8 +98,14 @@ defmodule Floki.Selector.PseudoClass do "odd" -> rem(relative_position, 2) == 1 - %Functional{stream: s} -> - relative_position in s + %Functional{a: 0, b: b} -> + relative_position == b + + %Functional{a: a, b: b} when a > 0 -> + relative_position >= b and rem(relative_position - b, a) == 0 + + %Functional{a: a, b: b} when a < 0 -> + relative_position <= b and rem(relative_position - b, a) == 0 expression -> Logger.debug(fn ->