Finished umath, urandom, and uselect
This commit is contained in:
@@ -2,6 +2,8 @@ from pybricks.parameters import Port
|
|||||||
from uerrno import EAGAIN, EBUSY, ECANCELED, EINVAL, EIO, ENODEV, EOPNOTSUPP, EPERM, ETIMEDOUT
|
from uerrno import EAGAIN, EBUSY, ECANCELED, EINVAL, EIO, ENODEV, EOPNOTSUPP, EPERM, ETIMEDOUT
|
||||||
import uio
|
import uio
|
||||||
import ujson
|
import ujson
|
||||||
|
import urandom
|
||||||
|
from urandom import random
|
||||||
from pybricks.iodevices import UARTDevice as _UARTDevice
|
from pybricks.iodevices import UARTDevice as _UARTDevice
|
||||||
from pybricks.tools import wait, multitask, run_task
|
from pybricks.tools import wait, multitask, run_task
|
||||||
|
|
||||||
@@ -47,7 +49,7 @@ class OSDiagnostics:
|
|||||||
self.motorclass = motorclass
|
self.motorclass = motorclass
|
||||||
self.successfultests = 0
|
self.successfultests = 0
|
||||||
self.failedtests = {}
|
self.failedtests = {}
|
||||||
def testUerrno(self):
|
def testUErrno(self):
|
||||||
uerrnotestobject = UerrnoTest(self.hub, self.motorclass)
|
uerrnotestobject = UerrnoTest(self.hub, self.motorclass)
|
||||||
uerrnotestobject.testeagain()
|
uerrnotestobject.testeagain()
|
||||||
uerrnotestobject.testebusy()
|
uerrnotestobject.testebusy()
|
||||||
@@ -76,7 +78,29 @@ class OSDiagnostics:
|
|||||||
umathtestobject.print_results()
|
umathtestobject.print_results()
|
||||||
self.successfultests += umathtestobject.successfultests
|
self.successfultests += umathtestobject.successfultests
|
||||||
self.failedtests.update(umathtestobject.failedtests)
|
self.failedtests.update(umathtestobject.failedtests)
|
||||||
|
def testURandom(self):
|
||||||
|
urandtestobject = URandomTest(self.hub, self.motorclass)
|
||||||
|
urandtestobject.print_results()
|
||||||
|
self.successfultests += urandtestobject.successfultests
|
||||||
|
self.failedtests.update(urandtestobject.failedtests)
|
||||||
|
|
||||||
|
def testUSelect(self):
|
||||||
|
uselecttestobject = USelectTest(self.hub, self.motorclass)
|
||||||
|
uselecttestobject.print_results()
|
||||||
|
self.successfultests += uselecttestobject.successfultests
|
||||||
|
self.failedtests.update(uselecttestobject.failedtests)
|
||||||
|
|
||||||
|
def testUStruct(self):
|
||||||
|
ustructtestobject = UStructTest(self.hub, self.motorclass)
|
||||||
|
ustructtestobject.print_results()
|
||||||
|
self.successfultests += ustructtestobject.successfultests
|
||||||
|
self.failedtests.update(ustructtestobject.failedtests)
|
||||||
|
|
||||||
|
def testUSys(self):
|
||||||
|
usystestobject = USysTest(self.hub, self.motorclass)
|
||||||
|
usystestobject.print_results()
|
||||||
|
self.successfultests += usystestobject.successfultests
|
||||||
|
self.failedtests.update(usystestobject.failedtests)
|
||||||
|
|
||||||
|
|
||||||
class UerrnoTest:
|
class UerrnoTest:
|
||||||
@@ -431,6 +455,394 @@ class UMathTest:
|
|||||||
self.successfultests = 0
|
self.successfultests = 0
|
||||||
self.failedtests = {}
|
self.failedtests = {}
|
||||||
def test_math(self):
|
def test_math(self):
|
||||||
|
if(umath.ceil(87.21) == 88):
|
||||||
|
self.successfultests += 1
|
||||||
|
else:
|
||||||
|
self.failedtests["ceilpos"] = "Failed"
|
||||||
|
|
||||||
|
if(umath.floor(14.61) == 14):
|
||||||
|
self.successfultests += 1
|
||||||
|
else:
|
||||||
|
self.failedtests["floorpos"] = "Failed"
|
||||||
|
|
||||||
|
if(umath.ceil(-87.21) == -87):
|
||||||
|
self.successfultests += 1
|
||||||
|
else:
|
||||||
|
self.failedtests["ceilneg"] = "Failed"
|
||||||
|
|
||||||
|
if(umath.floor(-14.61) == -15):
|
||||||
|
self.successfultests += 1
|
||||||
|
else:
|
||||||
|
self.failedtests["floorneg"] = "Failed"
|
||||||
|
|
||||||
|
if(umath.trunc(33.22) == 33):
|
||||||
|
self.successfultests += 1
|
||||||
|
else:
|
||||||
|
self.failedtests["truncpos"] = "Failed"
|
||||||
|
|
||||||
|
if(umath.trunc(-33.22) == -33):
|
||||||
|
self.successfultests += 1
|
||||||
|
else:
|
||||||
|
self.failedtests["truncneg"] = "Failed"
|
||||||
|
|
||||||
|
if(umath.fmod(6040, 3) == 1):
|
||||||
|
self.successfultests += 1
|
||||||
|
else:
|
||||||
|
self.failedtests["fmod"] = "Failed"
|
||||||
|
|
||||||
|
if(umath.fabs(88273) == 88273):
|
||||||
|
self.successfultests += 1
|
||||||
|
else:
|
||||||
|
self.failedtests["fabspos"] = "Failed"
|
||||||
|
|
||||||
|
if(umath.fabs(-27482) == 27482):
|
||||||
|
self.successfultests += 1
|
||||||
|
else:
|
||||||
|
self.failedtests["fabsneg"] = "Failed"
|
||||||
|
|
||||||
|
if(umath.fabs(-2742.233) == 2742.233):
|
||||||
|
self.successfultests += 1
|
||||||
|
else:
|
||||||
|
self.failedtests["fabsflt"] = "Failed"
|
||||||
|
|
||||||
|
if(umath.copysign(3928, -182) == -3928):
|
||||||
|
self.successfultests += 1
|
||||||
|
else:
|
||||||
|
self.failedtests["copysign"] = "Failed"
|
||||||
|
|
||||||
|
if(umath.exp(umath.log(1)) == 1):
|
||||||
|
self.successfultests += 2
|
||||||
|
else:
|
||||||
|
self.failedtests["eexp"] = "Failed"
|
||||||
|
self.failedtests["ln"] = "Failed"
|
||||||
|
print(umath.e)
|
||||||
|
print("\n")
|
||||||
|
if(input("Press Y and press enter if the value displayed above is around 2.718282. Type N and press Enter if it is not:") == "Y"):
|
||||||
|
self.successfultests += 1
|
||||||
|
else:
|
||||||
|
self.failedtests["e"] = "Failed"
|
||||||
|
|
||||||
|
if(umath.pow(19, 7) == 893871739):
|
||||||
|
self.successfultests += 1
|
||||||
|
else:
|
||||||
|
self.failedtests["pow"] = "Failed"
|
||||||
|
|
||||||
|
if(umath.sqrt(242064) == 492):
|
||||||
|
self.successfultests += 1
|
||||||
|
else:
|
||||||
|
self.failedtests["sqrt"] = "Failed"
|
||||||
|
|
||||||
|
print(umath.pi)
|
||||||
|
print("\n")
|
||||||
|
if(input("Press Y and press enter if the value displayed above is around 3.14159265. Type N and press Enter if it is not:") == "Y"):
|
||||||
|
self.successfultests += 1
|
||||||
|
else:
|
||||||
|
self.failedtests["pi"] = "Failed"
|
||||||
|
|
||||||
|
EPSILON = 1e-9
|
||||||
|
if abs(umath.degrees(umath.pi * 3) - 540) < EPSILON:
|
||||||
|
self.successfultests += 1
|
||||||
|
else:
|
||||||
|
self.failedtests["degrees"] = "Failed"
|
||||||
|
|
||||||
|
if abs(umath.radians(270) - umath.pi * 1.5) < EPSILON:
|
||||||
|
self.successfultests += 1
|
||||||
|
else:
|
||||||
|
self.failedtests["radians"] = "Failed"
|
||||||
|
|
||||||
|
if(abs(umath.sin(umath.pi)) < EPSILON):
|
||||||
|
self.successfultests += 1
|
||||||
|
else:
|
||||||
|
self.failedtests["sin"] = "Failed"
|
||||||
|
|
||||||
|
if(abs(umath.asin(1) - umath.pi * 0.5) < EPSILON):
|
||||||
|
self.successfultests += 1
|
||||||
|
else:
|
||||||
|
self.failedtests["asin"] = "Failed"
|
||||||
|
|
||||||
|
if(abs(umath.cos(umath.pi) + 1) < EPSILON):
|
||||||
|
self.successfultests += 1
|
||||||
|
else:
|
||||||
|
self.failedtests["cos"] = "Failed"
|
||||||
|
|
||||||
|
if(abs(umath.acos(1)) < EPSILON):
|
||||||
|
self.successfultests += 1
|
||||||
|
else:
|
||||||
|
self.failedtests["acos"] = "Failed"
|
||||||
|
|
||||||
|
if(abs(umath.tan(umath.pi)) < EPSILON):
|
||||||
|
self.successfultests += 1
|
||||||
|
else:
|
||||||
|
self.failedtests["tan"] = "Failed"
|
||||||
|
|
||||||
|
if(abs(umath.atan(1) - umath.pi * 0.25) < EPSILON):
|
||||||
|
self.successfultests += 1
|
||||||
|
else:
|
||||||
|
self.failedtests["atan"] = "Failed"
|
||||||
|
|
||||||
|
if(abs(umath.atan2(1, -1) - umath.pi * 0.75) < EPSILON):
|
||||||
|
self.successfultests += 1
|
||||||
|
else:
|
||||||
|
self.failedtests["atan2"] = "Failed"
|
||||||
|
|
||||||
|
infinitenum = float('inf')
|
||||||
|
finitenum = 123456
|
||||||
|
if(umath.isfinite(finitenum) == True):
|
||||||
|
self.successfultests += 1
|
||||||
|
else:
|
||||||
|
self.failedtests["isfinitefinite"] = "Failed"
|
||||||
|
|
||||||
|
if(umath.isfinite(infinitenum) == False):
|
||||||
|
self.successfultests += 1
|
||||||
|
else:
|
||||||
|
self.failedtests["isfiniteinfinite"] = "Failed"
|
||||||
|
|
||||||
|
if(umath.isinfinite(finitenum) == False):
|
||||||
|
self.successfultests += 1
|
||||||
|
else:
|
||||||
|
self.failedtests["isinfinitefinite"] = "Failed"
|
||||||
|
|
||||||
|
if(umath.isinfinite(infinitenum) == True):
|
||||||
|
self.successfultests += 1
|
||||||
|
else:
|
||||||
|
self.failedtests["isinfiniteinfinite"] = "Failed"
|
||||||
|
nannum = float("nan")
|
||||||
|
|
||||||
|
if(umath.isnan(nannum) == True):
|
||||||
|
self.successfultests += 1
|
||||||
|
else:
|
||||||
|
self.failedtests["isnannan"] = "Failed"
|
||||||
|
|
||||||
|
if(umath.isnan(finitenum) == False):
|
||||||
|
self.successfultests += 1
|
||||||
|
else:
|
||||||
|
self.failedtests["isnannotnan"] = "Failed"
|
||||||
|
|
||||||
|
frac, integer = umath.modf(87.21)
|
||||||
|
if integer == 87.0 and abs(frac - 0.21) < EPSILON:
|
||||||
|
self.successfultests += 1
|
||||||
|
else:
|
||||||
|
self.failedtests["modf"] = "Failed"
|
||||||
|
|
||||||
|
mantissa, exponent = umath.frexp(64)
|
||||||
|
if mantissa == 0.5 and exponent == 7:
|
||||||
|
self.successfultests += 1
|
||||||
|
else:
|
||||||
|
self.failedtests["frexp"] = "Failed"
|
||||||
|
|
||||||
|
result = umath.ldexp(0.5, 7)
|
||||||
|
if result == 64:
|
||||||
|
self.successfultests += 1
|
||||||
|
else:
|
||||||
|
self.failedtests["ldexp"] = "Failed"
|
||||||
|
def print_results(self):
|
||||||
|
self.test_math()
|
||||||
|
print(f"\n=== Results: {self.successfultests}/34 tests passed ===")
|
||||||
|
if self.failedtests:
|
||||||
|
print("Failed tests:")
|
||||||
|
for key, value in self.failedtests.items():
|
||||||
|
print(f" {key}: {value}")
|
||||||
|
class URandomTest:
|
||||||
|
def __init__(self, hub, motorclass):
|
||||||
|
self.hub = hub
|
||||||
|
self.motorclass = motorclass
|
||||||
|
self.successfultests = 0
|
||||||
|
self.failedtests = {}
|
||||||
|
def testrandom(self):
|
||||||
|
NUM_SAMPLES = 1000000
|
||||||
|
NUM_BUCKETS = 10
|
||||||
|
CHART_WIDTH = 50
|
||||||
|
SAMPLE_PEEK = 20
|
||||||
|
|
||||||
|
samples = [random() for _ in range(NUM_SAMPLES)]
|
||||||
|
|
||||||
|
bucket_counts = [0] * NUM_BUCKETS
|
||||||
|
for x in samples:
|
||||||
|
i = int(x * NUM_BUCKETS)
|
||||||
|
if i == NUM_BUCKETS:
|
||||||
|
i -= 1
|
||||||
|
bucket_counts[i] += 1
|
||||||
|
|
||||||
|
mean = sum(samples) / NUM_SAMPLES
|
||||||
|
ideal = NUM_SAMPLES / NUM_BUCKETS
|
||||||
|
max_count = max(bucket_counts)
|
||||||
|
|
||||||
|
print("=" * 66)
|
||||||
|
print(" random() distribution test n=" + str(NUM_SAMPLES))
|
||||||
|
print("=" * 66)
|
||||||
|
print("")
|
||||||
|
print(" Range Count Bar")
|
||||||
|
print(" -------------- ----- " + "-" * CHART_WIDTH)
|
||||||
|
|
||||||
|
for i in range(NUM_BUCKETS):
|
||||||
|
lo = i / NUM_BUCKETS
|
||||||
|
hi = (i + 1) / NUM_BUCKETS
|
||||||
|
count = bucket_counts[i]
|
||||||
|
bar = round(count / max_count * CHART_WIDTH)
|
||||||
|
dev = abs(count - ideal) / ideal
|
||||||
|
if dev <= 0.10:
|
||||||
|
marker = "#"
|
||||||
|
elif dev <= 0.20:
|
||||||
|
marker = "+"
|
||||||
|
else:
|
||||||
|
marker = "."
|
||||||
|
lo_str = "{:.2f}".format(lo)
|
||||||
|
hi_str = "{:.2f}".format(hi)
|
||||||
|
count_str = str(count).rjust(10)
|
||||||
|
print(" " + lo_str + " - " + hi_str + " " + count_str + " " + marker * bar)
|
||||||
|
|
||||||
|
print("")
|
||||||
|
print(" Samples : " + str(NUM_SAMPLES))
|
||||||
|
print(" Mean : " + "{:.6f}".format(mean) + " (ideal 0.500000)")
|
||||||
|
print(" Min : " + "{:.6f}".format(min(samples)))
|
||||||
|
print(" Max : " + "{:.6f}".format(max(samples)))
|
||||||
|
print(" Legend : # within 10% + within 20% . beyond 20%")
|
||||||
|
print("")
|
||||||
|
print(" First " + str(SAMPLE_PEEK) + " raw values:")
|
||||||
|
|
||||||
|
row = " "
|
||||||
|
for idx, val in enumerate(samples[:SAMPLE_PEEK], 1):
|
||||||
|
row += "{:.4f} ".format(val)
|
||||||
|
if idx % 5 == 0:
|
||||||
|
print(row)
|
||||||
|
row = " "
|
||||||
|
if row.strip():
|
||||||
|
print(row)
|
||||||
|
|
||||||
|
print("")
|
||||||
|
if(abs(0.5 - mean) < 0.02):
|
||||||
|
print("Random Distribution Test: SUCCESSFUL")
|
||||||
|
self.successfultests += 1
|
||||||
|
else:
|
||||||
|
print("Random Distribution Test: FAILED")
|
||||||
|
self.failedtests["randomdistribution"] = "Too much error"
|
||||||
|
def test_other_rands(self):
|
||||||
|
N = 1000
|
||||||
|
choicelist = ["apple", "banana", "grape", "orange"]
|
||||||
|
|
||||||
|
randint_vals = [urandom.randint(1, 100) for _ in range(N)]
|
||||||
|
randint_mean = sum(randint_vals) / N
|
||||||
|
print("Randint mean (ideally 50.5): {:.4f}".format(randint_mean))
|
||||||
|
if abs(50.5 - randint_mean) < 1.0:
|
||||||
|
print("Randint Test: SUCCESSFUL")
|
||||||
|
self.successfultests += 1
|
||||||
|
else:
|
||||||
|
print("Randint Test: FAILED")
|
||||||
|
self.failedtests["randint"] = "Too much error"
|
||||||
|
|
||||||
|
getrandbits_vals = [urandom.getrandbits(7) for _ in range(N)]
|
||||||
|
getrandbits_mean = sum(getrandbits_vals) / N
|
||||||
|
print("Getrandbits(7) mean (ideally 63.5): {:.4f}".format(getrandbits_mean))
|
||||||
|
if abs(63.5 - getrandbits_mean) < 1.3:
|
||||||
|
print("Getrandbits Test: SUCCESSFUL")
|
||||||
|
self.successfultests += 1
|
||||||
|
else:
|
||||||
|
print("Getrandbits Test: FAILED")
|
||||||
|
self.failedtests["getrandbits"] = "Too much error"
|
||||||
|
|
||||||
|
randrange_vals = [urandom.randrange(1, 1001, 4) for _ in range(N)]
|
||||||
|
randrange_mean = sum(randrange_vals) / N
|
||||||
|
print("Randrange(1,1001,4) mean (ideally 501.0): {:.4f}".format(randrange_mean))
|
||||||
|
if abs(501.0 - randrange_mean) < 10.0:
|
||||||
|
print("Randrange Test: SUCCESSFUL")
|
||||||
|
self.successfultests += 1
|
||||||
|
else:
|
||||||
|
print("Randrange Test: FAILED")
|
||||||
|
self.failedtests["randrange"] = "Too much error"
|
||||||
|
|
||||||
|
uniform_vals = [urandom.uniform(1, 10) for _ in range(N)]
|
||||||
|
uniform_mean = sum(uniform_vals) / N
|
||||||
|
print("Uniform(1,10) mean (ideally 5.5): {:.4f}".format(uniform_mean))
|
||||||
|
if abs(5.5 - uniform_mean) < 0.09:
|
||||||
|
print("Uniform Test: SUCCESSFUL")
|
||||||
|
self.successfultests += 1
|
||||||
|
else:
|
||||||
|
print("Uniform Test: FAILED")
|
||||||
|
self.failedtests["uniform"] = "Too much error"
|
||||||
|
|
||||||
|
choice_counts = {}
|
||||||
|
for item in choicelist:
|
||||||
|
choice_counts[item] = 0
|
||||||
|
for _ in range(N):
|
||||||
|
choice_counts[urandom.choice(choicelist)] += 1
|
||||||
|
ideal_pct = 100.0 / len(choicelist)
|
||||||
|
print("Choice distribution (ideally {:.1f}% each):".format(ideal_pct))
|
||||||
|
choice_ok = True
|
||||||
|
for item in choicelist:
|
||||||
|
pct = choice_counts[item] / N * 100
|
||||||
|
print(" " + item + ": {:.1f}%".format(pct))
|
||||||
|
if abs(pct - ideal_pct) > 5.0:
|
||||||
|
choice_ok = False
|
||||||
|
if choice_ok:
|
||||||
|
print("Choice Test: SUCCESSFUL")
|
||||||
|
self.successfultests += 1
|
||||||
|
else:
|
||||||
|
print("Choice Test: FAILED")
|
||||||
|
self.failedtests["choice"] = "Too much error"
|
||||||
|
def print_results(self):
|
||||||
|
self.testrandom()
|
||||||
|
self.test_other_rands()
|
||||||
|
print(f"\n=== Results: {self.successfultests}/6 tests passed ===")
|
||||||
|
if self.failedtests:
|
||||||
|
print("Failed tests:")
|
||||||
|
for key, value in self.failedtests.items():
|
||||||
|
print(f" {key}: {value}")
|
||||||
|
|
||||||
|
class USelectTest:
|
||||||
|
def __init__(self, hub, motorclass):
|
||||||
|
self.hub = hub
|
||||||
|
self.motorclass = motorclass
|
||||||
|
self.successfultests = 0
|
||||||
|
self.failedtests = {}
|
||||||
|
|
||||||
|
def print_results(self):
|
||||||
|
# Register the standard input so we can read keyboard presses.
|
||||||
|
keyboard = poll()
|
||||||
|
keyboard.register(stdin)
|
||||||
|
print("Type a few keys, make sure you get back what characteryou typed, then press Escape.")
|
||||||
|
while True:
|
||||||
|
# Check if a key has been pressed.
|
||||||
|
if keyboard.poll(0):
|
||||||
|
|
||||||
|
# Read the key and print it.
|
||||||
|
key = stdin.read(1)
|
||||||
|
if key == '\x1b':
|
||||||
|
print("Escape key pressed. Exiting...")
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
print("Pressed:", key)
|
||||||
|
if(input("Input Y if the results were accurate:") == "Y"):
|
||||||
|
print(f"\n=== Results: 1/1 tests passed ===")
|
||||||
|
self.successfultests += 1
|
||||||
|
else:
|
||||||
|
self.failedtests["input"] = "Unsatisfied"
|
||||||
|
if self.failedtests:
|
||||||
|
print("Failed tests:")
|
||||||
|
for key, value in self.failedtests.items():
|
||||||
|
print(f" {key}: {value}")
|
||||||
|
|
||||||
|
|
||||||
|
class UStructTest:
|
||||||
|
def __init__(self, hub, motorclass):
|
||||||
|
self.hub = hub
|
||||||
|
self.motorclass = motorclass
|
||||||
|
self.successfultests = 0
|
||||||
|
self.failedtests = {}
|
||||||
|
|
||||||
|
def print_results(self):
|
||||||
|
print(f"\n=== Results: {self.successfultests}/0 tests passed ===")
|
||||||
|
if self.failedtests:
|
||||||
|
print("Failed tests:")
|
||||||
|
for key, value in self.failedtests.items():
|
||||||
|
print(f" {key}: {value}")
|
||||||
|
|
||||||
|
|
||||||
|
class USysTest:
|
||||||
|
def __init__(self, hub, motorclass):
|
||||||
|
self.hub = hub
|
||||||
|
self.motorclass = motorclass
|
||||||
|
self.successfultests = 0
|
||||||
|
self.failedtests = {}
|
||||||
|
|
||||||
def print_results(self):
|
def print_results(self):
|
||||||
print(f"\n=== Results: {self.successfultests}/0 tests passed ===")
|
print(f"\n=== Results: {self.successfultests}/0 tests passed ===")
|
||||||
|
|||||||
Reference in New Issue
Block a user