# select_nth.ludic - :nth-child's formulas # :nth-child(odd), (even), (3), (2n+1), (n+2), (-n+3): is the k-th child one of them. The a and b of # an + b are read once per argument (matched per element per frame, a read made text every time) const MM_NTH: int = -16 # n1 a, n2 b function sel_nth(ui_st: mut UiState, arg: string, k: int) -> bool { if arg == "odd" { return k % 2 == 1 } if arg == "even" { return k % 2 == 0 } let m = mm_of(ui_st) let i = mm_find(m, MM_NTH, arg) if i >= 0 { ui_st.nth_a = int(m.n1[i]) ui_st.nth_b = int(m.n2[i]) } else { sel_nth_read(ui_st, m, arg) } let a = ui_st.nth_a let b = ui_st.nth_b if a == 0 { return k == b } let d = k - b return d % a == 0 and d / a >= 0 } @alloc_ok("a memo miss: once per :nth-child argument, bounded by MM_CAP") function sel_nth_read(ui_st: mut UiState, m: UiMemo, arg: string) -> void { var npos = -1 for i in 0 .. len(arg) { if arg[i] == 110 { npos = i } } var a = 0 var b = 0 if npos < 0 { b = int(el_num(arg)) } else { a = 1 let head: string = arg[0..npos] if head == "-" { a = -1 } else if len(head) > 0 { a = int(el_num(head)) } var tail = tpl_words(arg[npos + 1..len(arg)]) if len(tail) > 0 and tail[0] == 43 { tail = tpl_words(tail[1..len(tail)]) } if len(tail) > 0 { b = int(el_num(tail)) } } ui_st.nth_a = a ui_st.nth_b = b let j = mm_add(m, MM_NTH, arg) if j >= 0 { m.n1[j] = float(a) m.n2[j] = float(b) } }