mirror of
https://github.com/Sei-Lisa/LSL-PyOptimizer
synced 2025-07-01 15:48:21 +00:00
lslbasefuncs: Rewrite some things in a different way.
Also some formatting changes. No functionality changes.
This commit is contained in:
parent
ea28e13e4a
commit
028b244a9e
1 changed files with 98 additions and 112 deletions
|
@ -78,7 +78,7 @@ TOUCH_INVALID_TEXCOORD = Vector((-1.0, -1.0, 0.0))
|
|||
|
||||
Infinity = float('inf')
|
||||
Indet = Infinity * 0
|
||||
NaN = -Indet # Don't use float("nan") - Windows gets upset.
|
||||
NaN = -Indet # Don't use float("nan") - Windows gets upset.
|
||||
|
||||
class ELSLTypeMismatch(Exception):
|
||||
def __init__(self):
|
||||
|
@ -110,13 +110,13 @@ class ELSONotSupported(Exception):
|
|||
# * LSL list -> Python list
|
||||
|
||||
Types = {
|
||||
int: 1, # TYPE_INTEGER
|
||||
float: 2, # TYPE_FLOAT
|
||||
unicode: 3, # TYPE_STRING
|
||||
Key: 4, # TYPE_KEY
|
||||
Vector: 5, # TYPE_VECTOR
|
||||
Quaternion: 6, # TYPE_ROTATION
|
||||
list: 0, # TYPE_INVALID
|
||||
int: 1, # TYPE_INTEGER
|
||||
float: 2, # TYPE_FLOAT
|
||||
unicode: 3, # TYPE_STRING
|
||||
Key: 4, # TYPE_KEY
|
||||
Vector: 5, # TYPE_VECTOR
|
||||
Quaternion: 6, # TYPE_ROTATION
|
||||
list: 0, # TYPE_INVALID
|
||||
}
|
||||
|
||||
# Utility functions
|
||||
|
@ -124,10 +124,10 @@ Types = {
|
|||
def F32(f, f32=True):
|
||||
"""Truncate a float to have a precision equivalent to IEEE single"""
|
||||
|
||||
if not f32: # don't truncate
|
||||
if not f32: # don't truncate
|
||||
return f
|
||||
|
||||
if isinstance(f, tuple): # vector, quaternion
|
||||
if isinstance(f, tuple): # vector, quaternion
|
||||
return f.__class__(F32(i) for i in f)
|
||||
|
||||
# Alternative to the big blurb below. This relies on the machine using IEEE-754, though.
|
||||
|
@ -221,7 +221,7 @@ def F32(f, f32=True):
|
|||
# if f < 0.000000000000000000000000000000000000011754943508222875079687365372222456778186655567720875215087517062784172594547271728515625:
|
||||
# # Denormal range
|
||||
# f *= 713623846352979940529142984724747568191373312.0
|
||||
# e = 0.00000000000000000000000000000000000000000000140129846432481707092372958328991613128026194187651577175706828388979108268586060148663818836212158203125 # 2^-149
|
||||
# e = 0.00000000000000000000000000000000000000000000140129846432481707092372958328991613128026194187651577175706828388979108268586060148663818836212158203125 # 2^-149
|
||||
# else:
|
||||
# e = 1.0
|
||||
# # This first loop is an optimization to get closer to the destination faster for very small numbers
|
||||
|
@ -335,13 +335,13 @@ def f2s(val, DP=6):
|
|||
if math.isnan(val):
|
||||
return u'NaN'
|
||||
if lslcommon.LSO or val == 0.:
|
||||
return u'%.*f' % (DP, val) # deals with -0.0 too
|
||||
return u'%.*f' % (DP, val) # deals with -0.0 too
|
||||
|
||||
# Format according to Mono rules (7 decimals after the DP, found experimentally)
|
||||
s = u'%.*f' % (DP+7, val)
|
||||
|
||||
if s[:DP+3] == u'-0.' + '0'*DP and s[DP+3] < u'5':
|
||||
return u'0.' + '0'*DP # underflown negatives return 0.0 except for -0.0 dealt with above
|
||||
return u'0.' + '0'*DP # underflown negatives return 0.0 except for -0.0 dealt with above
|
||||
|
||||
# Separate the sign
|
||||
sgn = u'-' if s[0] == u'-' else u''
|
||||
|
@ -368,42 +368,38 @@ def f2s(val, DP=6):
|
|||
if s[i if i != dot else i+1] >= u'5':
|
||||
# Rounding - increment s[:i] storing result into new_s
|
||||
new_s = u''
|
||||
ci = i-1 # carry index
|
||||
ci = i-1 # carry index
|
||||
while ci >= 0 and s[ci] == u'9':
|
||||
new_s = u'0' + new_s
|
||||
ci -= 1
|
||||
if ci == dot:
|
||||
ci -= 1 # skip over the dot
|
||||
new_s = u'.' + new_s # but add it to new_s
|
||||
ci -= 1 # skip over the dot
|
||||
new_s = u'.' + new_s # but add it to new_s
|
||||
if ci < 0:
|
||||
new_s = u'1' + new_s # 9...9 -> 10...0
|
||||
new_s = u'1' + new_s # 9...9 -> 10...0
|
||||
else:
|
||||
# increment s[ci] e.g. 43999 -> 44000
|
||||
new_s = s[:ci] + chr(ord(s[ci])+1) + new_s
|
||||
new_s = s[:ci] + chr(ord(s[ci]) + 1) + new_s
|
||||
else:
|
||||
new_s = s[:i]
|
||||
|
||||
if i <= dot:
|
||||
return sgn + new_s + u'0'*(dot-i) + u'.' + u'0'*DP
|
||||
return sgn + new_s + u'0'*(dot+1+DP-i)
|
||||
return sgn + new_s + u'0' * (dot - i) + u'.' + u'0' * DP
|
||||
return sgn + new_s + u'0' * (dot + 1 + DP - i)
|
||||
|
||||
def vr2s(v, DP=6):
|
||||
if type(v) == Vector:
|
||||
return u'<'+f2s(v[0],DP)+u', '+f2s(v[1],DP)+u', '+f2s(v[2],DP)+u'>'
|
||||
return u'<'+f2s(v[0],DP)+u', '+f2s(v[1],DP)+u', '+f2s(v[2],DP)+u', '+f2s(v[3],DP)+u'>'
|
||||
|
||||
assert len(v) == (3 if type(v) == Vector else 4)
|
||||
return u'<' + ', '.join(f2s(x, DP) for x in v) + u'>'
|
||||
|
||||
def qnz(q):
|
||||
if all(x == 0. for x in q):
|
||||
return Quaternion((0.,0.,0.,1.))
|
||||
return q
|
||||
return Quaternion((0.,0.,0.,1.)) if all(x == 0. for x in q) else q
|
||||
|
||||
def qnorm(q):
|
||||
q = qnz(q)
|
||||
mag2 = math.fsum((q[0]*q[0], q[1]*q[1], q[2]*q[2], q[3]*q[3]))
|
||||
# Threshold for renormalization
|
||||
eps_h = 1.0000021457672119140625 #float.fromhex('0x1.000024p0')
|
||||
eps_l = 0.99999797344207763671875 # float.fromhex('0x1.FFFFBCp-1')
|
||||
eps_h = 1.0000021457672119140625 # float.fromhex('0x1.000024p0')
|
||||
eps_l = 0.99999797344207763671875 # float.fromhex('0x1.FFFFBCp-1')
|
||||
if mag2 >= eps_h or mag2 <= eps_l:
|
||||
# Renormalize
|
||||
mag2 = math.sqrt(mag2)
|
||||
|
@ -421,7 +417,7 @@ def InternalTypecast(val, out, InList, f32):
|
|||
if out == list:
|
||||
return [val]
|
||||
|
||||
if tval == int: # integer
|
||||
if tval == int: # integer
|
||||
val = S32(val)
|
||||
if out == int: return val
|
||||
if out == float: return F32(val, f32)
|
||||
|
@ -445,7 +441,7 @@ def InternalTypecast(val, out, InList, f32):
|
|||
if out == Quaternion: return val
|
||||
if out == unicode: return vr2s(val, 6 if InList else 5)
|
||||
raise ELSLTypeMismatch
|
||||
if tval == Key: # key
|
||||
if tval == Key: # key
|
||||
if out == Key: return zstr(val)
|
||||
if out == unicode: return zstr(unicode(val))
|
||||
raise ELSLTypeMismatch
|
||||
|
@ -505,10 +501,10 @@ def InternalTypecast(val, out, InList, f32):
|
|||
if val[i:i+1] != u',':
|
||||
return Z
|
||||
val = val[i+1:]
|
||||
return out(ret) # convert type
|
||||
return out(ret) # convert type
|
||||
|
||||
# To avoid mutual recursion, this was moved:
|
||||
#if tval == list: # etc.
|
||||
#if tval == list: # etc.
|
||||
|
||||
raise ELSLInvalidType
|
||||
|
||||
|
@ -590,12 +586,8 @@ def InternalGetDeleteSubSequence(val, start, end, isGet):
|
|||
if end == -1: end += L
|
||||
if (start+L if start < 0 else start) > (end+L if end < 0 else end):
|
||||
# Exclusion range - get/delete from end and start
|
||||
if isGet:
|
||||
return val[:end+1] + val[start:]
|
||||
return val[end+1:start]
|
||||
if isGet:
|
||||
return val[start:end+1]
|
||||
return val[:start] + val[end+1:]
|
||||
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:]
|
||||
|
||||
def typecast(val, out, InList=False, f32=True):
|
||||
"""Type cast an item. Calls InternalList2Strings for lists and
|
||||
|
@ -603,7 +595,7 @@ def typecast(val, out, InList=False, f32=True):
|
|||
"""
|
||||
if type(val) == list:
|
||||
if out == list:
|
||||
return val # NOTE: We're not duplicating it here.
|
||||
return val # NOTE: We're not duplicating it here.
|
||||
if out == unicode:
|
||||
return u''.join(InternalList2Strings(val))
|
||||
raise ELSLTypeMismatch
|
||||
|
@ -680,8 +672,10 @@ def mul(a, b, f32=True):
|
|||
if tb in (int, float):
|
||||
if ta == tb == int:
|
||||
return S32(a*b)
|
||||
if math.isnan(a) and math.isnan(b) and math.copysign(1, a) != math.copysign(1, b):
|
||||
return NaN
|
||||
if math.isnan(a) and math.isnan(b):
|
||||
return (-NaN
|
||||
if math.copysign(1, a) == math.copysign(1, b) == -1
|
||||
else NaN)
|
||||
return F32(ff(a)*ff(b), f32)
|
||||
if tb != Vector:
|
||||
# scalar * quat is not defined
|
||||
|
@ -702,7 +696,7 @@ def mul(a, b, f32=True):
|
|||
a[3] * b[3] - a[0] * b[0] - a[1] * b[1] - a[2] * b[2]), f32))
|
||||
|
||||
if ta != Vector:
|
||||
raise ELSLInvalidType # Should never happen at this point
|
||||
raise ELSLInvalidType # Should never happen at this point
|
||||
|
||||
if tb in (int, float):
|
||||
a = v2f(a)
|
||||
|
@ -716,7 +710,7 @@ def mul(a, b, f32=True):
|
|||
return F32(math.fsum((a[0]*b[0], a[1]*b[1], a[2]*b[2])), f32)
|
||||
|
||||
if tb != Quaternion:
|
||||
raise ELSLInvalidType # Should never happen at this point
|
||||
raise ELSLInvalidType # Should never happen at this point
|
||||
|
||||
# vector * quaternion: perform conjugation
|
||||
#v = mul(Quaternion((-b[0], -b[1], -b[2], b[3])), mul(Quaternion((a[0], a[1], a[2], 0.0)), b, f32=False))
|
||||
|
@ -729,11 +723,11 @@ def mul(a, b, f32=True):
|
|||
a[1]*2*(b[0]*b[1]-b[2]*b[3]),
|
||||
a[2]*2*(b[0]*b[2]+b[1]*b[3]))),
|
||||
math.fsum(( a[0]*2*(b[0]*b[1]+b[2]*b[3]),
|
||||
-a[1]*(b[0]*b[0]-b[1]*b[1]+b[2]*b[2]-b[3]*b[3]), # notice minus sign
|
||||
-a[1]*(b[0]*b[0]-b[1]*b[1]+b[2]*b[2]-b[3]*b[3]), # notice minus sign
|
||||
a[2]*2*(b[1]*b[2]-b[0]*b[3]))),
|
||||
math.fsum(( a[0]*2*(b[0]*b[2]-b[1]*b[3]),
|
||||
a[1]*2*(b[1]*b[2]+b[0]*b[3]),
|
||||
-a[2]*(b[0]*b[0]+b[1]*b[1]-b[2]*b[2]-b[3]*b[3]))) # notice minus sign
|
||||
-a[2]*(b[0]*b[0]+b[1]*b[1]-b[2]*b[2]-b[3]*b[3]))) # notice minus sign
|
||||
), f32))
|
||||
|
||||
def div(a, b, f32=True):
|
||||
|
@ -751,13 +745,13 @@ def div(a, b, f32=True):
|
|||
if ta == int and tb == int:
|
||||
# special case
|
||||
if a == -2147483648 and b == -1:
|
||||
return a # this could be handled by using S32 but it's probably faster this way
|
||||
return a # this could be handled by using S32 but it's probably faster this way
|
||||
if (a < 0) ^ (b < 0):
|
||||
# signs differ - Python rounds towards -inf, we need rounding towards 0
|
||||
return -(a//-b)
|
||||
return a//b
|
||||
ret = F32(ff(a)/ff(b), f32)
|
||||
if math.isnan(ret): # A NaN result gives a math error.
|
||||
if math.isnan(ret): # A NaN result gives a math error.
|
||||
raise ELSLMathError
|
||||
return ret
|
||||
if ta == Vector:
|
||||
|
@ -803,15 +797,13 @@ def compare(a, b, Eq = True):
|
|||
ret = a == b
|
||||
else:
|
||||
ret = ff(a) == ff(b)
|
||||
return int(ret) if Eq else 1-ret
|
||||
return int(ret == Eq)
|
||||
if ta in (unicode, Key) and tb in (unicode, Key):
|
||||
ret = 0 if a == b else 1 if a > b or not lslcommon.LSO else -1
|
||||
ret = 0 if a == b else 1 if not lslcommon.LSO or a > b else -1
|
||||
return int(not ret) if Eq else ret
|
||||
if ta == tb in (Vector, Quaternion):
|
||||
for ae,be in zip(a,b):
|
||||
if ae != be:
|
||||
return int(not Eq)
|
||||
return int(Eq)
|
||||
ret = not any(ae != be for ae, be in zip(a, b))
|
||||
return int(ret == Eq)
|
||||
if ta == tb == list:
|
||||
ret = len(a) - len(b)
|
||||
return int(not ret) if Eq else ret
|
||||
|
@ -843,12 +835,12 @@ def cond(x):
|
|||
if lslcommon.LSO and tx == list:
|
||||
# SVC-689: lists of 1 element count as false
|
||||
return len(x) > 1
|
||||
return bool(x) # works fine for int, float, string, list
|
||||
return bool(x) # works fine for int, float, string, list
|
||||
|
||||
def reduce(t):
|
||||
t = F32(t)
|
||||
if not t.is_integer():
|
||||
return t # Accurate-ish until big numbers come into play
|
||||
return t # Accurate-ish until big numbers come into play
|
||||
return int(t * 18446744073709551616) % 115904311329233965478 / 18446744073709551616.
|
||||
|
||||
#
|
||||
|
@ -887,12 +879,10 @@ def llAtan2(y, x):
|
|||
y = ff(y)
|
||||
x = ff(x)
|
||||
if math.isnan(x) and math.isnan(y):
|
||||
if math.copysign(1, x) == -1 and math.copysign(1, y) == -1:
|
||||
return -NaN
|
||||
return NaN
|
||||
elif math.isnan(x):
|
||||
return mul(x, y)
|
||||
if math.isnan(x):
|
||||
return x
|
||||
elif math.isnan(y):
|
||||
if math.isnan(y):
|
||||
return y
|
||||
return F32(math.atan2(y, x))
|
||||
|
||||
|
@ -904,7 +894,7 @@ def llAxes2Rot(fwd, left, up):
|
|||
# One of the hardest.
|
||||
|
||||
t = math.fsum((fwd[0], left[1], up[2]))
|
||||
if t > 0.: # no danger of division by zero or negative roots
|
||||
if t > 0.: # no danger of division by zero or negative roots
|
||||
r = math.sqrt(1. + t)
|
||||
s = 0.5/r
|
||||
|
||||
|
@ -913,12 +903,12 @@ def llAxes2Rot(fwd, left, up):
|
|||
|
||||
# Find a positive combo. LSL normalizes the result in these cases only, so we do the same.
|
||||
|
||||
if left[1] <= fwd[0] >= up[2]: # is fwd[0] the greatest?
|
||||
if left[1] <= fwd[0] >= up[2]: # is fwd[0] the greatest?
|
||||
r = math.sqrt(1. + fwd[0] - left[1] - up[2])
|
||||
s = 0.5/r
|
||||
q = (r*0.5, s*(fwd[1]+left[0]), s*(up[0]+fwd[2]), s*(left[2]-up[1]))
|
||||
|
||||
elif fwd[0] <= left[1] >= up[2]: # is left[1] the greatest?
|
||||
elif fwd[0] <= left[1] >= up[2]: # is left[1] the greatest?
|
||||
r = math.sqrt(1. - fwd[0] + left[1] - up[2])
|
||||
s = 0.5/r
|
||||
q = (s*(fwd[1]+left[0]), r*0.5, s*(left[2]+up[1]), s*(up[0]-fwd[2]))
|
||||
|
@ -934,7 +924,6 @@ def llAxes2Rot(fwd, left, up):
|
|||
mag = math.sqrt(math.fsum((q[0]*q[0], q[1]*q[1], q[2]*q[2], q[3]*q[3])))
|
||||
return Quaternion(F32((q[0]/mag, q[1]/mag, q[2]/mag, q[3]/mag)))
|
||||
|
||||
|
||||
def llAxisAngle2Rot(axis, angle):
|
||||
axis = v2f(axis)
|
||||
angle = ff(angle)
|
||||
|
@ -964,7 +953,7 @@ def llBase64ToInteger(s):
|
|||
b64tos_re = re.compile(
|
||||
b'('
|
||||
# Those pass through and are caught by InternalUTF8toString:
|
||||
b'\x00$' # NUL at last position (zstr removes it)
|
||||
b'\x00$' # NUL at last position (zstr removes it)
|
||||
b'|[\x09\x0A\x0F\x1F-\x7F\xFE\xFF]|[\xC2-\xDF][\x80-\xBF]'
|
||||
b'|(?:\xE0[\xA0-\xBF]|[\xE1-\xEF][\x80-\xBF])[\x80-\xBF]'
|
||||
b'|(?:\xF0[\x90-\xBF]|[\xF1-\xF7][\x80-\xBF])[\x80-\xBF]{2}'
|
||||
|
@ -979,7 +968,7 @@ b64tos_re = re.compile(
|
|||
b'|[\xF0-\xF7][\x80-\xBF]{0,3}'
|
||||
b'|[\xF8-\xFB][\x80-\xBF]{0,4}'
|
||||
b'|[\xFC-\xFD][\x80-\xBF]{0,5}'
|
||||
b')|(.)' # should never be reached
|
||||
b')|(.)' # should never be reached
|
||||
)
|
||||
|
||||
def llBase64ToString(s):
|
||||
|
@ -1033,7 +1022,7 @@ def llCSV2List(s):
|
|||
bracketlevel += 1
|
||||
elif c == u'>':
|
||||
bracketlevel -= 1
|
||||
elif lastwascomma and c == u' ': # eat space after comma
|
||||
elif lastwascomma and c == u' ': # eat space after comma
|
||||
lastwascomma = False
|
||||
lastidx = i+1
|
||||
else:
|
||||
|
@ -1079,7 +1068,7 @@ def llDumpList2String(lst, sep):
|
|||
|
||||
def llEscapeURL(s):
|
||||
s = fs(s)
|
||||
s = s.encode('utf8') # get bytes
|
||||
s = s.encode('utf8') # get bytes
|
||||
ret = u''
|
||||
for c in s:
|
||||
if b'A' <= c <= b'Z' or b'a' <= c <= b'z' or b'0' <= c <= b'9':
|
||||
|
@ -1123,7 +1112,7 @@ def llEuler2Rot(v):
|
|||
|
||||
def llFabs(f):
|
||||
f = ff(f)
|
||||
if f == 0.0 or math.isnan(f): # llFabs(-0.0) is -0.0; llFabs(-nan) is -nan
|
||||
if f == 0.0 or math.isnan(f): # llFabs(-0.0) is -0.0; llFabs(-nan) is -nan
|
||||
return f
|
||||
return math.fabs(f)
|
||||
|
||||
|
@ -1151,7 +1140,7 @@ def llFrand(lim):
|
|||
if val == lim:
|
||||
# this should never happen
|
||||
# (it can happen on denormals, but these cause output of 0.0)
|
||||
val = 0. # pragma: no cover
|
||||
val = 0. # pragma: no cover
|
||||
return val
|
||||
|
||||
# Can't give a concrete value
|
||||
|
@ -1165,8 +1154,7 @@ def llGenerateKey():
|
|||
s = hashlib.md5((u'%.17g %f %f' % (time.time(), random.random(),
|
||||
random.random())).encode('utf8')
|
||||
).hexdigest()
|
||||
return Key(s[:8] + '-' + s[8:12] + '-' + s[12:16] + '-' + s[16:20]
|
||||
+ '-' + s[20:32])
|
||||
return Key('-'.join((s[:8], s[8:12], s[12:16], s[16:20], s[20:32])))
|
||||
|
||||
# Can't give a concrete value
|
||||
raise ELSLCantCompute
|
||||
|
@ -1178,7 +1166,7 @@ def llGetListEntryType(lst, pos):
|
|||
return Types[type(lst[pos])]
|
||||
except IndexError:
|
||||
# list index out of bounds
|
||||
return 0 # TYPE_INVALID
|
||||
return 0 # TYPE_INVALID
|
||||
except KeyError:
|
||||
# type of element not in Types
|
||||
raise ELSLInvalidType
|
||||
|
@ -1195,12 +1183,13 @@ def llInsertString(s, pos, src):
|
|||
s = fs(s)
|
||||
pos = fi(pos)
|
||||
src = fs(src)
|
||||
if pos < 0: pos = 0 # llInsertString does not support negative indices
|
||||
if pos < 0: pos = 0 # llInsertString does not support negative indices
|
||||
return s[:pos] + src + s[pos:]
|
||||
|
||||
def llIntegerToBase64(x):
|
||||
x = fi(x)
|
||||
return b64encode(chr((x>>24)&255) + chr((x>>16)&255) + chr((x>>8)&255) + chr(x&255)).decode('utf8')
|
||||
return b64encode(chr((x>>24)&255) + chr((x>>16)&255) + chr((x>>8)&255)
|
||||
+ chr(x&255)).decode('utf8')
|
||||
|
||||
def llList2CSV(lst):
|
||||
lst = fl(lst)
|
||||
|
@ -1329,7 +1318,7 @@ def llListFindList(lst, elems):
|
|||
L1 = len(lst)
|
||||
L2 = len(elems)
|
||||
if L2 > L1:
|
||||
return -1 # can't find a sublist longer than the original list
|
||||
return -1 # can't find a sublist longer than the original list
|
||||
if L2 == 0:
|
||||
# empty list is always found at position 0 in Mono,
|
||||
# and in LSO if the first list isn't empty
|
||||
|
@ -1357,15 +1346,15 @@ def llListFindList(lst, elems):
|
|||
# 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
|
||||
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
|
||||
break # discrepancy found
|
||||
elif type(e1) != type(e2) or e1 != e2:
|
||||
break # mismatch
|
||||
break # mismatch
|
||||
else:
|
||||
# no mismatch
|
||||
return i
|
||||
|
@ -1403,9 +1392,9 @@ def llListSort(lst, stride, asc):
|
|||
lst = fl(lst)
|
||||
stride = fi(stride)
|
||||
asc = fi(asc)
|
||||
lst = lst[:] # make a copy
|
||||
lst = lst[:] # make a copy
|
||||
L = len(lst)
|
||||
broken = u'\ufb1a' > u'\U0001d41a' # that happens on Windows
|
||||
broken = u'\ufb1a' > u'\U0001d41a' # that happens on Windows
|
||||
if stride < 1: stride = 1
|
||||
if L % stride:
|
||||
return lst
|
||||
|
@ -1414,12 +1403,12 @@ def llListSort(lst, stride, asc):
|
|||
a = lst[i]
|
||||
ta = type(a)
|
||||
if ta == Vector:
|
||||
a = v2f(a) # list should contain vectors made only of floats
|
||||
a = v2f(a) # list should contain vectors made only of floats
|
||||
a = a[0]*a[0] + a[1]*a[1] + a[2]*a[2]
|
||||
if broken and ta in (unicode, Key):
|
||||
# Note this breaks type consistency between a and ta!
|
||||
# It should be OK because only equal types are compared.
|
||||
a = a.encode('utf-32-be') # pragma: no cover
|
||||
a = a.encode('utf-32-be') # pragma: no cover
|
||||
for j in xrange(i+stride, L, stride):
|
||||
b = lst[j]
|
||||
tb = type(b)
|
||||
|
@ -1431,8 +1420,8 @@ def llListSort(lst, stride, asc):
|
|||
# (note NaNs compare as > thus the reversed condition!)
|
||||
elif tb != Quaternion:
|
||||
if broken and tb in (unicode, Key):
|
||||
b = b.encode('utf-32-be') # pragma: no cover
|
||||
gt = not (a <= b) # float, integer, string, key all take this branch
|
||||
b = b.encode('utf-32-be') # pragma: no cover
|
||||
gt = not (a <= b) # float, integer, string, key all take this branch
|
||||
# (note NaNs compare as > thus the reversed condition!)
|
||||
if gt ^ (asc != 1):
|
||||
# swap
|
||||
|
@ -1444,7 +1433,7 @@ def llListSort(lst, stride, asc):
|
|||
a = v2f(a)
|
||||
a = a[0]*a[0] + a[1]*a[1] + a[2]*a[2]
|
||||
if broken and ta in (unicode, Key):
|
||||
a = a.encode('utf-32-be') # pragma: no cover
|
||||
a = a.encode('utf-32-be') # pragma: no cover
|
||||
return lst
|
||||
|
||||
def llListStatistics(op, lst):
|
||||
|
@ -1460,10 +1449,10 @@ def llListStatistics(op, lst):
|
|||
if nums == []:
|
||||
return 0.0
|
||||
|
||||
if op == 8: # LIST_STAT_NUM_COUNT
|
||||
if op == 8: # LIST_STAT_NUM_COUNT
|
||||
return float(len(nums))
|
||||
|
||||
if op in (0, 1, 2) : # LIST_STAT_RANGE, LIST_STAT_MIN, LIST_STAT_MAX
|
||||
if op in (0, 1, 2): # LIST_STAT_RANGE, LIST_STAT_MIN, LIST_STAT_MAX
|
||||
min = None
|
||||
for elem in nums:
|
||||
if min is None:
|
||||
|
@ -1475,7 +1464,7 @@ def llListStatistics(op, lst):
|
|||
max = elem
|
||||
return F32(max - min if op == 0 else min if op == 1 else max)
|
||||
|
||||
if op == 4: # LIST_STAT_MEDIAN requires special treatment
|
||||
if op == 4: # LIST_STAT_MEDIAN requires special treatment
|
||||
# The function behaves very strangely with NaNs. This seems to reproduce it:
|
||||
|
||||
# llListSort seems to do the right thing with NaNs as needed by the median.
|
||||
|
@ -1485,7 +1474,7 @@ def llListStatistics(op, lst):
|
|||
return F32(nums[L>>1])
|
||||
return F32((nums[(L>>1)-1] + nums[L>>1])*0.5)
|
||||
|
||||
if op in (3, 5, 6, 7): # LIST_STAT_MEAN, STD_DEV, SUM, SUM_SQUARES
|
||||
if op in (3, 5, 6, 7): # LIST_STAT_MEAN, STD_DEV, SUM, SUM_SQUARES
|
||||
sum = 0.
|
||||
sumsq = 0.
|
||||
mean = 0.
|
||||
|
@ -1499,15 +1488,15 @@ def llListStatistics(op, lst):
|
|||
mean += delta/N
|
||||
M2 += delta*(elem-mean)
|
||||
|
||||
if op == 5: # LIST_STAT_STD_DEV
|
||||
if op == 5: # LIST_STAT_STD_DEV
|
||||
return 0. if N == 1. else F32(math.sqrt(M2/(N-1.)))
|
||||
if op == 6: # LIST_STAT_SUM
|
||||
if op == 6: # LIST_STAT_SUM
|
||||
return F32(sum)
|
||||
if op == 7: # LIST_STAT_SUM_SQUARES
|
||||
if op == 7: # LIST_STAT_SUM_SQUARES
|
||||
return F32(sumsq)
|
||||
return F32(mean)
|
||||
|
||||
if op == 9: # LIST_STAT_GEOMETRIC_MEAN
|
||||
if op == 9: # LIST_STAT_GEOMETRIC_MEAN
|
||||
N = 0.
|
||||
GMlog = 0.
|
||||
for elem in nums:
|
||||
|
@ -1551,12 +1540,9 @@ def llModPow(base, exp, mod):
|
|||
if exp == 0:
|
||||
return 1
|
||||
# Convert all numbers to unsigned
|
||||
if base < 0:
|
||||
base += 4294967296
|
||||
if exp < 0:
|
||||
exp += 4294967296
|
||||
if mod < 0:
|
||||
mod += 4294967296
|
||||
base &= 0xFFFFFFFF
|
||||
exp &= 0xFFFFFFFF
|
||||
mod &= 0xFFFFFFFF
|
||||
prod = base
|
||||
ret = 1
|
||||
while True:
|
||||
|
@ -1606,22 +1592,22 @@ def llPow(base, exp):
|
|||
if exp == 0.0:
|
||||
return 1.0
|
||||
|
||||
if base == 0.0: # Python gives exception on these, LSL returns stuff
|
||||
if base == 0.0: # Python gives exception on these, LSL returns stuff
|
||||
if math.isinf(exp) and exp < 0:
|
||||
return Infinity # llPow(0.0, -inf) = inf
|
||||
return Infinity # llPow(0.0, -inf) = inf
|
||||
|
||||
if exp < 0.0:
|
||||
# Negative finite exponent cases
|
||||
if math.copysign(1, base) < 0 and exp.is_integer() and not (exp/2.).is_integer():
|
||||
return -Infinity # llPow(-0.0, -odd_integer) = -inf
|
||||
return -Infinity # llPow(-0.0, -odd_integer) = -inf
|
||||
return Infinity
|
||||
|
||||
elif abs(base) == 1.0 and math.isinf(exp):
|
||||
return NaN # Python says 1.0
|
||||
return NaN # Python says 1.0
|
||||
|
||||
f = F32(math.pow(base, exp))
|
||||
return 0.0 if f == 0.0 else f # don't return -0.0
|
||||
except ValueError: # should happen only with negative base and noninteger exponent
|
||||
return 0.0 if f == 0.0 else f # don't return -0.0
|
||||
except ValueError: # should happen only with negative base and noninteger exponent
|
||||
return Indet
|
||||
|
||||
def llRot2Angle(r):
|
||||
|
@ -1701,7 +1687,7 @@ def llRotBetween(v1, v2):
|
|||
# which will be perpendicular to both. But matching the SL results requires
|
||||
# another cross product of the input with the result, so we do that.
|
||||
ortho = mod(mod(v1, Vector((1., 0., 0.))), v1)
|
||||
ortho = Vector((0. if f == 0. else f for f in ortho)) # remove minus zero
|
||||
ortho = Vector((0. if f == 0. else f for f in ortho)) # remove minus zero
|
||||
m = mul(ortho, ortho)
|
||||
if m < float.fromhex('0x1.b7cdfep-34'):
|
||||
# The input vectors were aligned with <1,0,0>, so this was not a
|
||||
|
@ -1749,10 +1735,10 @@ def llStringTrim(s, mode):
|
|||
head = 0
|
||||
length = len(s)
|
||||
tail = length-1
|
||||
if mode & 1: # STRING_TRIM_HEAD
|
||||
if mode & 1: # STRING_TRIM_HEAD
|
||||
while head < length and s[head] in u'\x09\x0a\x0b\x0c\x0d\x20':
|
||||
head += 1
|
||||
if mode & 2: # STRING_TRIM_TAIL
|
||||
if mode & 2: # STRING_TRIM_TAIL
|
||||
while tail >= head and s[tail] in u'\x09\x0a\x0b\x0c\x0d\x20':
|
||||
tail -= 1
|
||||
return s[head:tail+1]
|
||||
|
@ -1795,14 +1781,14 @@ def llUnescapeURL(s):
|
|||
continue
|
||||
if i >= L:
|
||||
break
|
||||
c = s[i] # First digit
|
||||
c = s[i] # First digit
|
||||
i += 1
|
||||
if i >= L:
|
||||
break
|
||||
v = 0
|
||||
if u'0' <= c <= u'9' or u'A' <= c <= u'F' or u'a' <= c <= u'f':
|
||||
v = int(c, 16)<<4
|
||||
c = s[i] # Second digit
|
||||
c = s[i] # Second digit
|
||||
if c == u'%':
|
||||
ret += chr(v)
|
||||
i += 1
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue