mirror of
https://github.com/Sei-Lisa/LSL-PyOptimizer
synced 2025-07-03 00:18:20 +00:00
Improve llFrand.
- Remove it from lslextrafuncs, and move all the code to lslbasefuncs. - Make it behave like SL's more accurately. Denormals return 0 always in SL. - Use int() for truncation rather then floor/ceil. - Add test cases.
This commit is contained in:
parent
fc97ce42df
commit
159fae90bf
3 changed files with 40 additions and 28 deletions
|
@ -20,8 +20,8 @@
|
||||||
# The functions it implements are all functions that always return the same
|
# The functions it implements are all functions that always return the same
|
||||||
# result when given the same input, and that have no side effects.
|
# result when given the same input, and that have no side effects.
|
||||||
#
|
#
|
||||||
# For example, llAbs() is here, but llFrand() is not, because it doesn't always
|
# For example, llAbs() is here, but llGetPos() is not, because it doesn't
|
||||||
# return the same result.
|
# always return the same result.
|
||||||
#
|
#
|
||||||
# This implies that functions present in this module can be precomputed if
|
# This implies that functions present in this module can be precomputed if
|
||||||
# their arguments are constants.
|
# their arguments are constants.
|
||||||
|
@ -1053,36 +1053,41 @@ def llFloor(f):
|
||||||
return -2147483648
|
return -2147483648
|
||||||
return int(math.floor(f))
|
return int(math.floor(f))
|
||||||
|
|
||||||
if lslcommon.IsCalc:
|
def llFrand(lim):
|
||||||
import time
|
assert isfloat(lim)
|
||||||
import random
|
if math.isinf(lim) or abs(lim) < 1.1754943508222875e-38:
|
||||||
def llFrand(lim):
|
return 0.
|
||||||
assert isfloat(lim)
|
if math.isnan(lim):
|
||||||
if math.isinf(lim):
|
return lim
|
||||||
return 0.
|
|
||||||
if math.isnan(lim):
|
|
||||||
return lim
|
|
||||||
|
|
||||||
lim = F32(lim) # apply constraints
|
if lslcommon.IsCalc:
|
||||||
|
import random
|
||||||
val = random.random() * lim
|
val = random.random() * lim
|
||||||
# Truncate, rather than rounding
|
# Truncate, rather than rounding
|
||||||
m, e = math.frexp(val)
|
m, e = math.frexp(val)
|
||||||
m = m * 16777216.0
|
val = F32(math.ldexp(int(m * 16777216.) * .000000059604644775390625, e))
|
||||||
m = math.floor(m) if m > 0 else math.ceil(m) # don't invoke __trunc__
|
|
||||||
val = F32(math.ldexp(m * 0.000000059604644775390625, e))
|
|
||||||
if val == lim:
|
if val == lim:
|
||||||
|
# this should never happen
|
||||||
|
# (it can happen on denormals, but these cause output of 0.0)
|
||||||
val = 0.
|
val = 0.
|
||||||
return val
|
return val
|
||||||
|
|
||||||
def llGenerateKey():
|
# Can't give a concrete value
|
||||||
|
raise ELSLCantCompute
|
||||||
|
|
||||||
|
def llGenerateKey():
|
||||||
|
if lslcommon.IsCalc:
|
||||||
|
import time
|
||||||
|
import random
|
||||||
|
|
||||||
s = hashlib.md5((u'%.17g %f %f' % (time.time(), random.random(),
|
s = hashlib.md5((u'%.17g %f %f' % (time.time(), random.random(),
|
||||||
random.random())).encode('utf8')
|
random.random())).encode('utf8')
|
||||||
).hexdigest()
|
).hexdigest()
|
||||||
return Key(s[:8] + '-' + s[8:12] + '-' + s[12:16] + '-' + s[16:20]
|
return Key(s[:8] + '-' + s[8:12] + '-' + s[12:16] + '-' + s[16:20]
|
||||||
+ '-' + s[20:32])
|
+ '-' + s[20:32])
|
||||||
|
|
||||||
# Otherwise they're not implemented, as they don't give the same output for
|
# Can't give a concrete value
|
||||||
# the same input.
|
raise ELSLCantCompute
|
||||||
|
|
||||||
def llGetListEntryType(lst, pos):
|
def llGetListEntryType(lst, pos):
|
||||||
assert islist(lst)
|
assert islist(lst)
|
||||||
|
|
|
@ -17,11 +17,10 @@
|
||||||
|
|
||||||
# Extra functions that have predictable return values for certain arguments.
|
# Extra functions that have predictable return values for certain arguments.
|
||||||
|
|
||||||
import lslcommon
|
|
||||||
from lslcommon import Key #, Vector, Quaternion
|
from lslcommon import Key #, Vector, Quaternion
|
||||||
from lslbasefuncs import ELSLCantCompute, isinteger, iskey, islist, \
|
from lslbasefuncs import ELSLCantCompute, isinteger, iskey, islist, \
|
||||||
isfloat, isvector, isstring, NULL_KEY, ZERO_VECTOR, ZERO_ROTATION, cond
|
isvector, isstring, NULL_KEY, ZERO_VECTOR, ZERO_ROTATION, cond
|
||||||
#isrotation
|
#isfloat, isrotation
|
||||||
|
|
||||||
TouchEvents = ('touch', 'touch_start', 'touch_end')
|
TouchEvents = ('touch', 'touch_start', 'touch_end')
|
||||||
DetectionEvents = ('touch', 'touch_start', 'touch_end',
|
DetectionEvents = ('touch', 'touch_start', 'touch_end',
|
||||||
|
@ -147,13 +146,6 @@ def llEdgeOfWorld(v1, v2):
|
||||||
return 1
|
return 1
|
||||||
raise ELSLCantCompute
|
raise ELSLCantCompute
|
||||||
|
|
||||||
if not lslcommon.IsCalc:
|
|
||||||
def llFrand(f):
|
|
||||||
assert isfloat(f)
|
|
||||||
if f == 0:
|
|
||||||
return 0.
|
|
||||||
raise ELSLCantCompute
|
|
||||||
|
|
||||||
def llGetAgentInfo(id):
|
def llGetAgentInfo(id):
|
||||||
assert iskey(id)
|
assert iskey(id)
|
||||||
if not cond(id):
|
if not cond(id):
|
||||||
|
|
15
testfuncs.py
15
testfuncs.py
|
@ -890,6 +890,21 @@ def do_tests():
|
||||||
test('llList2CSV([llPow(nan,F32(1.3))])', u'nan')
|
test('llList2CSV([llPow(nan,F32(1.3))])', u'nan')
|
||||||
test('llList2CSV([Vector((-nan,nan,-inf))])', u'<-nan, nan, -inf>')
|
test('llList2CSV([Vector((-nan,nan,-inf))])', u'<-nan, nan, -inf>')
|
||||||
|
|
||||||
|
test('llFrand(0.0)', 0.0)
|
||||||
|
test('llFrand(-0.0)', 0.0)
|
||||||
|
test('llFrand(Infinity)', 0.0)
|
||||||
|
test('llFrand(-Infinity)', 0.0)
|
||||||
|
test('llFrand(-NaN)', -NaN)
|
||||||
|
test('llFrand(NaN)', NaN)
|
||||||
|
for i in range(10):
|
||||||
|
test('llFrand(F32(1.4e-45))', 0.0)
|
||||||
|
test('llFrand(F32(1.1754943508222875e-38))', 0.0)
|
||||||
|
|
||||||
|
lslcommon.IsCalc = True
|
||||||
|
test('cond(llGenerateKey())', True)
|
||||||
|
lslcommon.IsCalc = False
|
||||||
|
shouldexcept('llGenerateKey()', ELSLCantCompute)
|
||||||
|
|
||||||
testXB64S("", "", "")
|
testXB64S("", "", "")
|
||||||
testXB64S(u"Hello, World!", u"", u"Hello, World!")
|
testXB64S(u"Hello, World!", u"", u"Hello, World!")
|
||||||
testXB64S("AAAAA==AAAAA=", "_X", "/X/X/==X/X/X=")
|
testXB64S("AAAAA==AAAAA=", "_X", "/X/X/==X/X/X=")
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue