mirror of
https://github.com/Sei-Lisa/LSL-PyOptimizer
synced 2025-07-01 15:48:21 +00:00
Implement llListFindListNext and llListFindStrided
This commit is contained in:
parent
914b57f603
commit
5ee290deff
5 changed files with 188 additions and 53 deletions
|
@ -688,6 +688,86 @@ def InternalGetDeleteSubSequence(val, start, end, isGet):
|
||||||
return val[:end+1] + val[start:] if isGet else val[end+1:start]
|
return val[:end+1] + val[start:] if isGet else val[end+1:start]
|
||||||
return val[start:end+1] if isGet else val[:start] + val[end+1:]
|
return val[start:end+1] if isGet else val[:start] + val[end+1:]
|
||||||
|
|
||||||
|
def InternalCompareElems(e1, e2):
|
||||||
|
"""Compares two list elements according to llListFindList rules."""
|
||||||
|
# NaN is found in floats, but not in vectors
|
||||||
|
if type(e1) == type(e2) == float:
|
||||||
|
if e1 == e2:
|
||||||
|
return True
|
||||||
|
# Exceptionally, NaN equals NaN
|
||||||
|
if math.isnan(e1) and math.isnan(e2):
|
||||||
|
return True
|
||||||
|
# Mismatch
|
||||||
|
return False
|
||||||
|
elif type(e1) == type(e2) in (Vector, Quaternion):
|
||||||
|
# Act as if the list's vector/quat was all floats, even if not
|
||||||
|
if type(e1) == Vector:
|
||||||
|
e1 = v2f(e1)
|
||||||
|
e2 = v2f(e2)
|
||||||
|
else:
|
||||||
|
e1 = q2f(e1)
|
||||||
|
e2 = q2f(e2)
|
||||||
|
# Unfortunately, Python fails to consider (NaN,) != (NaN,) sometimes
|
||||||
|
# so we need to implement our own test
|
||||||
|
for e1e,e2e in zip(e1,e2):
|
||||||
|
# NaNs are considered different to themselves here as normal
|
||||||
|
if e1e != e2e:
|
||||||
|
# Mismatch in vector/quaternion component
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
# No mismatch in any component
|
||||||
|
return True
|
||||||
|
# Mismatch
|
||||||
|
return False
|
||||||
|
elif type(e1) != type(e2) or e1 != e2:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def InternalListFindList(lst, elems, start, end, stride, instance):
|
||||||
|
"""Generalizes llListFindList with start/end, stride and instance args."""
|
||||||
|
L1 = len(lst)
|
||||||
|
L2 = len(elems)
|
||||||
|
if L1 == L2 == 0:
|
||||||
|
return 0 # an empty list is always found in an empty list
|
||||||
|
if L2 > L1:
|
||||||
|
return -1 # can't find a sublist longer than the original list
|
||||||
|
if start < 0:
|
||||||
|
start += L1
|
||||||
|
if end < 0:
|
||||||
|
end += L1
|
||||||
|
if end >= L1:
|
||||||
|
end = L1 - 1
|
||||||
|
if start < 0 or start >= L1 or end < 0 or end >= L1 or start > end:
|
||||||
|
return -1
|
||||||
|
if L2 == 0:
|
||||||
|
# empty list is always found at position 0
|
||||||
|
return 0
|
||||||
|
if stride < 1:
|
||||||
|
return -1 # stride 0 or negative returns -1
|
||||||
|
if instance >= 0:
|
||||||
|
# Forward search
|
||||||
|
for i in xrange(start, end+2-L2, stride):
|
||||||
|
for j in xrange(L2):
|
||||||
|
if not InternalCompareElems(lst[i+j], elems[j]):
|
||||||
|
break # mismatch
|
||||||
|
else:
|
||||||
|
# no mismatch
|
||||||
|
if instance == 0:
|
||||||
|
return i
|
||||||
|
instance -= 1
|
||||||
|
else:
|
||||||
|
# Backward search
|
||||||
|
for i in xrange(end+1-L2, start-1, -stride):
|
||||||
|
for j in xrange(L2):
|
||||||
|
if not InternalCompareElems(lst[i+j], elems[j]):
|
||||||
|
break # mismatch
|
||||||
|
else:
|
||||||
|
# no mismatch
|
||||||
|
instance += 1
|
||||||
|
if instance == 0:
|
||||||
|
return i
|
||||||
|
return -1
|
||||||
|
|
||||||
def reduce(t):
|
def reduce(t):
|
||||||
t = F32(t)
|
t = F32(t)
|
||||||
if not t.is_integer():
|
if not t.is_integer():
|
||||||
|
@ -1516,64 +1596,21 @@ def llList2Vector(lst, pos):
|
||||||
def llListFindList(lst, elems):
|
def llListFindList(lst, elems):
|
||||||
lst = fl(lst)
|
lst = fl(lst)
|
||||||
elems = fl(elems)
|
elems = fl(elems)
|
||||||
# NaN is found in floats, but not in vectors
|
return InternalListFindList(lst, elems, 0, -1, 1, 0)
|
||||||
L1 = len(lst)
|
|
||||||
L2 = len(elems)
|
|
||||||
if L2 > L1:
|
|
||||||
return -1 # can't find a sublist longer than the original list
|
|
||||||
if L2 == 0:
|
|
||||||
# empty list is always found at position 0
|
|
||||||
return 0
|
|
||||||
for i in xrange(L1-L2+1):
|
|
||||||
for j in xrange(L2):
|
|
||||||
e1 = lst[i+j]
|
|
||||||
e2 = elems[j]
|
|
||||||
if type(e1) == type(e2) == float:
|
|
||||||
if e1 == e2:
|
|
||||||
continue
|
|
||||||
# Exceptionally, NaN equals NaN
|
|
||||||
if math.isnan(e1) and math.isnan(e2):
|
|
||||||
continue
|
|
||||||
# Mismatch
|
|
||||||
break
|
|
||||||
elif type(e1) == type(e2) in (Vector, Quaternion):
|
|
||||||
# Act as if the list's vector/quat was all floats, even if not
|
|
||||||
if type(e1) == Vector:
|
|
||||||
e1 = v2f(e1)
|
|
||||||
e2 = v2f(e2)
|
|
||||||
else:
|
|
||||||
e1 = q2f(e1)
|
|
||||||
e2 = q2f(e2)
|
|
||||||
# Unfortunately, Python fails to consider (NaN,) != (NaN,) sometimes
|
|
||||||
# so we need to implement our own test
|
|
||||||
for e1e,e2e in zip(e1,e2):
|
|
||||||
if e1e != e2e: # NaNs are considered different to themselves here as normal
|
|
||||||
# Mismatch in vector/quaternion sub-element
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
# No mismatch in any sub-element, try next list element
|
|
||||||
continue
|
|
||||||
break # discrepancy found
|
|
||||||
elif type(e1) != type(e2) or e1 != e2:
|
|
||||||
break # mismatch
|
|
||||||
else:
|
|
||||||
# no mismatch
|
|
||||||
return i
|
|
||||||
return -1
|
|
||||||
|
|
||||||
def llListFindListNext(src, test, n):
|
def llListFindListNext(lst, elems, instance):
|
||||||
src = fl(src)
|
lst = fl(lst)
|
||||||
test = fl(test)
|
elems = fl(elems)
|
||||||
n = fi(n)
|
instance = fi(instance)
|
||||||
raise eLSLCantCompute # TODO: Implement llListFindListNext
|
return InternalListFindList(lst, elems, 0, -1, 1, instance)
|
||||||
|
|
||||||
def llListFindStrided(src, test, start, end, stride):
|
def llListFindStrided(lst, elems, start, end, stride):
|
||||||
src = fl(src)
|
lst = fl(lst)
|
||||||
test = fl(test)
|
elems = fl(elems)
|
||||||
start = fi(start)
|
start = fi(start)
|
||||||
end = fi(end)
|
end = fi(end)
|
||||||
stride = fi(stride)
|
stride = fi(stride)
|
||||||
raise ELSLCantCompute # TODO: Implement llListFindStrided
|
return InternalListFindList(lst, elems, start, end, stride, 0)
|
||||||
|
|
||||||
def llListInsertList(lst, elems, pos):
|
def llListInsertList(lst, elems, pos):
|
||||||
lst = fl(lst)
|
lst = fl(lst)
|
||||||
|
|
34
unit_tests/expr.suite/list-funcs-5.lsl
Normal file
34
unit_tests/expr.suite/list-funcs-5.lsl
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
[ llListFindStrided(["a",0,"b",1,"c",2,"b",1], ["b"], 0, -1, 1)
|
||||||
|
, llListFindStrided(["a",0,"b",1,"c",2,"b",1], ["b",1], 2, -1, 1)
|
||||||
|
, llListFindStrided(["a",0,"b",1,"c",2,"b",1], ["b"], 3, -1, 1)
|
||||||
|
, llListFindStrided(["a",0,"b",1,"c",2,"b",1], ["b",1], 2, -1, 1)
|
||||||
|
, llListFindStrided(["a",0,"b",1,"c",2,"b",1], ["b",1], 3, -1, 1)
|
||||||
|
, llListFindStrided(["a",0,"b",1,"c",2,"b",1], ["b",1], 3, -2, 1)
|
||||||
|
, llListFindStrided(["a",0,"b",1,"c",2,"b",1], ["b",2], 0, -1, 1)
|
||||||
|
, llListFindStrided(["a",0,"b",1,"c",2,"b",1], ["c"], 0, -1, 2)
|
||||||
|
, llListFindStrided(["a",0,"b",1,"c",2,"b",1], ["c"], 0, -1, 3)
|
||||||
|
, llListFindStrided(["a",0,"b",1,"c",2,"b",1], ["c"], 0, -1, 4)
|
||||||
|
, llListFindStrided(["a",0,"b",1,"c",2,"b",1], ["c"], 1, -1, 2)
|
||||||
|
, llListFindStrided(["a",0,"b",1,"c",2,"b",1], ["b",1], 3, -1, 2)
|
||||||
|
, llListFindStrided(["a",0,"b",1,"c",2,"b",1], ["b",1], 4, -1, 2)
|
||||||
|
, llListFindStrided(["a",0,"b",1,"c",2,"b",1], ["b",1], 4, -2, 2)
|
||||||
|
, llListFindStrided([0,1,2,3,4,5,6], [4], 4, 0, 2)
|
||||||
|
, llListFindStrided([], [], 3, 1, 2)
|
||||||
|
, llListFindStrided([], [], 3, 1, 0)
|
||||||
|
, llListFindStrided([], [], 0, 0, 0)
|
||||||
|
, llListFindStrided([1], [], 3, 1, 2)
|
||||||
|
, llListFindStrided([1], [], 3, 1, 1)
|
||||||
|
, llListFindStrided([1], [], 0, 1, 1)
|
||||||
|
, llListFindStrided([1], [], 0, 0, 0)
|
||||||
|
, llListFindStrided(["a",0,"b",1,"c",2,"b",1], ["b",1], 3, 6, 1)
|
||||||
|
, llListFindStrided(["a",0,"b",1,"c",2,"b",1], ["b"], 2, -1, 3)
|
||||||
|
, llListFindStrided(["a",0,"b",1,"c",2,"b",1], ["b"], 3, -1, 3)
|
||||||
|
, llListFindStrided(["a",0,"b",1,"c",2,"b",1], ["b"], 4, -1, 3)
|
||||||
|
, llListFindStrided(["a",0,"b",1,"c",2,"b",1], ["b",1], 2, -1, 3)
|
||||||
|
, llListFindStrided(["a",0,"b",1,"c",2,"b",1], ["b",1], 3, -1, 3)
|
||||||
|
, llListFindStrided(["a",0,"b",1,"c",2,"b",1], ["b",1], 4, -1, 3)
|
||||||
|
, llListFindStrided(["a",0,"b",1,"c",2,"b",1], ["b",1], -99999, 7, 3)
|
||||||
|
, llListFindStrided(["a",0,"b",1,"c",2,"b",1], ["b",1], -99999, 7, 1)
|
||||||
|
, llListFindStrided(["a",0,"b",1,"c",2,"b",1], ["b",1], 3, 99999, 3)
|
||||||
|
, llListFindStrided(["a",0,"b",1,"c",2,"b",1], ["b",1], 0, 99999, 1)
|
||||||
|
]
|
34
unit_tests/expr.suite/list-funcs-5.out
Normal file
34
unit_tests/expr.suite/list-funcs-5.out
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
[ 2
|
||||||
|
, 2
|
||||||
|
, 6
|
||||||
|
, 2
|
||||||
|
, 6
|
||||||
|
, -1
|
||||||
|
, -1
|
||||||
|
, 4
|
||||||
|
, -1
|
||||||
|
, 4
|
||||||
|
, -1
|
||||||
|
, -1
|
||||||
|
, 6
|
||||||
|
, -1
|
||||||
|
, -1
|
||||||
|
, 0
|
||||||
|
, 0
|
||||||
|
, 0
|
||||||
|
, -1
|
||||||
|
, -1
|
||||||
|
, 0
|
||||||
|
, 0
|
||||||
|
, -1
|
||||||
|
, 2
|
||||||
|
, 6
|
||||||
|
, -1
|
||||||
|
, 2
|
||||||
|
, 6
|
||||||
|
, -1
|
||||||
|
, -1
|
||||||
|
, -1
|
||||||
|
, 6
|
||||||
|
, 2
|
||||||
|
]
|
15
unit_tests/expr.suite/list-funcs-6.lsl
Normal file
15
unit_tests/expr.suite/list-funcs-6.lsl
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
[ llListFindListNext(["A", 0, "B", 1, "C", 2, "A", 0, "A", 1, "A", "A", 0, <1,2,3>, "c"], ["A", 0], 0)
|
||||||
|
, llListFindListNext(["A", 0, "B", 1, "C", 2, "A", 0, "A", 1, "A", "A", 0, <1,2,3>, "c"], ["A", 0], 1)
|
||||||
|
, llListFindListNext(["A", 0, "B", 1, "C", 2, "A", 0, "A", 1, "A", "A", 0, <1,2,3>, "c"], ["A", 0], 2)
|
||||||
|
, llListFindListNext(["A", 0, "B", 1, "C", 2, "A", 0, "A", 1, "A", "A", 0, <1,2,3>, "c"], ["A", 0], 3)
|
||||||
|
, llListFindListNext(["A", 0, "B", 1, "C", 2, "A", 0, "A", 1, "A", "A", 0, <1,2,3>, "c"], ["A", 0], -1)
|
||||||
|
, llListFindListNext(["A", 0, "B", 1, "C", 2, "A", 0, "A", 1, "A", "A", 0, <1,2,3>, "c"], ["A", 0], -2)
|
||||||
|
, llListFindListNext(["A", 0, "B", 1, "C", 2, "A", 0, "A", 1, "A", "A", 0, <1,2,3>, "c"], ["A", 0], -3)
|
||||||
|
, llListFindListNext(["A", 0, "B", 1, "C", 2, "A", 0, "A", 1, "A", "A", 0, <1,2,3>, "c"], ["A", 0], -4)
|
||||||
|
, llListFindListNext(["A", 0, "B", 1, "C", 2, "A", 0, "A", 1, "A", "A", 0, <1,2,3>, "c"], [3], 0)
|
||||||
|
, llListFindListNext(["A", 0, "B", 1, "C", 2, "A", 0, "A", 1, "A", "A", 0, <1,2,3>, "c"], [<1,2,3>], -1)
|
||||||
|
, llListFindListNext(["A", 0, "B", 1, "C", 2, "A", 0, "A", 1, "A", "A", 0, <1,2,3>, "c"], [<1,2,3>, "c"], -1)
|
||||||
|
, llListFindListNext(["A", 0, "B", 1, "C", 2, "A", 0, "A", 1, "A", "A", 0, <1,2,3>, "c"], ["c"], -1)
|
||||||
|
, llListFindListNext(["A", 0, "B", 1, "C", 2, "A", 0, "A", 1, "A", "A", 0, <1,2,3>, "c"], ["c"], 0)
|
||||||
|
, llListFindList(["A", 0, "B", 1, "C", 2, "A", 0, "A", 1, "A", "A", 0, <1,2,3>, "c"], ["c"])
|
||||||
|
]
|
15
unit_tests/expr.suite/list-funcs-6.out
Normal file
15
unit_tests/expr.suite/list-funcs-6.out
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
[ 0
|
||||||
|
, 6
|
||||||
|
, 11
|
||||||
|
, -1
|
||||||
|
, 11
|
||||||
|
, 6
|
||||||
|
, 0
|
||||||
|
, -1
|
||||||
|
, -1
|
||||||
|
, 13
|
||||||
|
, 13
|
||||||
|
, 14
|
||||||
|
, 14
|
||||||
|
, 14
|
||||||
|
]
|
Loading…
Add table
Add a link
Reference in a new issue