micropython: add micropython component

This commit is contained in:
KY-zhang-X
2022-09-29 12:10:37 +08:00
parent 1514f1cb9b
commit dd76146324
2679 changed files with 354110 additions and 0 deletions

View File

@@ -0,0 +1,13 @@
# test construction of array from array with float type
try:
from uarray import array
except ImportError:
try:
from array import array
except ImportError:
print("SKIP")
raise SystemExit
print(array("f", array("h", [1, 2])))
print(array("d", array("f", [1, 2])))

View File

@@ -0,0 +1,13 @@
# test builtin abs function with float args
for val in (
"1.0",
"-1.0",
"0.0",
"-0.0",
"nan",
"-nan",
"inf",
"-inf",
):
print(val, abs(float(val)))

View File

@@ -0,0 +1,25 @@
# test builtin hash function with float args
# these should hash to an integer with a specific value
for val in (
"0.0",
"-0.0",
"1.0",
"2.0",
"-12.0",
"12345.0",
):
print(val, hash(float(val)))
# just check that these values are hashable
for val in (
"0.1",
"-0.1",
"10.3",
"0.4e3",
"1e16",
"inf",
"-inf",
"nan",
):
print(val, type(hash(float(val))))

View File

@@ -0,0 +1,31 @@
# test builtin min and max functions with float args
try:
min
max
except:
print("SKIP")
raise SystemExit
print(min(0, 1.0))
print(min(1.0, 0))
print(min(0, -1.0))
print(min(-1.0, 0))
print(max(0, 1.0))
print(max(1.0, 0))
print(max(0, -1.0))
print(max(-1.0, 0))
print(min(1.5, -1.5))
print(min(-1.5, 1.5))
print(max(1.5, -1.5))
print(max(-1.5, 1.5))
print(min([1, 2.9, 4, 0, -1, 2]))
print(max([1, 2.9, 4, 0, -1, 2]))
print(min([1, 2.9, 4, 6.5, -1, 2]))
print(max([1, 2.9, 4, 6.5, -1, 2]))
print(min([1, 2.9, 4, -6.5, -1, 2]))
print(max([1, 2.9, 4, -6.5, -1, 2]))

View File

@@ -0,0 +1,11 @@
# test builtin pow function with float args
print(pow(0.0, 0.0))
print(pow(0, 1.0))
print(pow(1.0, 1))
print(pow(2.0, 3.0))
print(pow(2.0, -4.0))
print(pow(0.0, float("inf")))
print(pow(0.0, float("-inf")))
print(pow(0.0, float("nan")))

View File

@@ -0,0 +1,34 @@
# test round() with floats
# check basic cases
tests = [
[0.0],
[1.0],
[0.1],
[-0.1],
[123.4],
[123.6],
[-123.4],
[-123.6],
[1.234567, 5],
[1.23456, 1],
[1.23456, 0],
[1234.56, -2],
]
for t in tests:
print(round(*t))
# check .5 cases
for i in range(11):
print(round((i - 5) / 2))
# test second arg
for i in range(-1, 3):
print(round(1.47, i))
# test inf and nan
for val in (float("inf"), float("nan")):
try:
round(val)
except (ValueError, OverflowError) as e:
print(type(e))

View File

@@ -0,0 +1,4 @@
# test round() with floats that return large integers
for x in (-1e25, 1e25):
print("%.3g" % round(x))

View File

@@ -0,0 +1,12 @@
# test construction of bytearray from array with float type
try:
from uarray import array
except ImportError:
try:
from array import array
except ImportError:
print("SKIP")
raise SystemExit
print(bytearray(array("f", [1, 2.5])))

View File

@@ -0,0 +1,12 @@
# test construction of bytes from array with float type
try:
from uarray import array
except ImportError:
try:
from array import array
except ImportError:
print("SKIP")
raise SystemExit
print(bytes(array("f", [1, 2.5])))

View File

@@ -0,0 +1,65 @@
# test the functions imported from cmath
try:
from cmath import *
except ImportError:
print("SKIP")
raise SystemExit
# make sure these constants exist in cmath
print("%.5g" % e)
print("%.5g" % pi)
test_values_non_zero = []
base_values = (0.0, 0.5, 1.2345, 10.0)
for r in base_values:
for i in base_values:
if r != 0.0 or i != 0.0:
test_values_non_zero.append(complex(r, i))
if r != 0.0:
test_values_non_zero.append(complex(-r, i))
if i != 0.0:
test_values_non_zero.append(complex(r, -i))
if r != 0.0 and i != 0.0:
test_values_non_zero.append(complex(-r, -i))
test_values = [complex(0.0, 0.0)] + test_values_non_zero
print(test_values)
functions = [
("phase", phase, test_values),
("polar", polar, test_values),
(
"rect",
rect,
((0, 0), (0, 1), (0, -1), (1, 0), (-1, 0), (1, 1), (-1, 1), (1, -1), (123.0, -456.0)),
),
("exp", exp, test_values),
("log", log, test_values_non_zero),
("sqrt", sqrt, test_values),
("cos", cos, test_values),
("sin", sin, test_values),
]
for f_name, f, test_vals in functions:
print(f_name)
for val in test_vals:
if type(val) == tuple:
ret = f(*val)
else:
ret = f(val)
if type(ret) == float:
print("%.5g" % ret)
elif type(ret) == tuple:
print("%.5g %.5g" % ret)
else:
# some test (eg cmath.sqrt(-0.5)) disagree with CPython with tiny real part
real = ret.real
if abs(real) < 1e-6:
real = 0.0
print("complex(%.5g, %.5g)" % (real, ret.imag))
# test invalid type passed to cmath function
try:
log([])
except TypeError:
print("TypeError")

View File

@@ -0,0 +1,32 @@
# test the special functions imported from cmath
try:
from cmath import *
log10
except (ImportError, NameError):
print("SKIP")
raise SystemExit
test_values_non_zero = []
base_values = (0.0, 0.5, 1.2345, 10.0)
for r in base_values:
for i in base_values:
if r != 0.0 or i != 0.0:
test_values_non_zero.append(complex(r, i))
if r != 0.0:
test_values_non_zero.append(complex(-r, i))
if i != 0.0:
test_values_non_zero.append(complex(r, -i))
if r != 0.0 and i != 0.0:
test_values_non_zero.append(complex(-r, -i))
functions = [
("log10", log10, test_values_non_zero),
]
for f_name, f, test_vals in functions:
print(f_name)
for val in test_vals:
ret = f(val)
print("complex(%.4g, %.4g)" % (ret.real, ret.imag))

View File

@@ -0,0 +1,125 @@
# test basic complex number functionality
# constructor
print(complex(1))
print(complex(1.2))
print(complex(1.2j))
print(complex("1"))
print(complex("1.2"))
print(complex("1.2j"))
print(complex(1, 2))
print(complex(1j, 2j))
# unary ops
print(bool(1j))
print(+(1j))
print(-(1 + 2j))
# binary ops
print(1j + False)
print(1j + True)
print(1j + 2)
print(1j + 2j)
print(1j - 2)
print(1j - 2j)
print(1j * 2)
print(1j * 2j)
print(1j / 2)
print((1j / 2j).real)
print(1j / (1 + 2j))
ans = 0j**0
print("%.5g %.5g" % (ans.real, ans.imag))
ans = 0j**1
print("%.5g %.5g" % (ans.real, ans.imag))
ans = 0j**0j
print("%.5g %.5g" % (ans.real, ans.imag))
ans = 1j**2.5
print("%.5g %.5g" % (ans.real, ans.imag))
ans = 1j**2.5j
print("%.5g %.5g" % (ans.real, ans.imag))
# comparison
print(1j == 1)
print(1j == 1j)
print(0 + 0j == False, 1 + 0j == True)
print(False == 0 + 0j, True == 1 + 0j)
# comparison of nan is special
nan = float("nan") * 1j
print(nan == 1j)
print(nan == nan)
# builtin abs
print(abs(1j))
print("%.5g" % abs(1j + 2))
# builtin hash
print(hash(1 + 0j))
print(type(hash(1j)))
# float on lhs should delegate to complex
print(1.2 + 3j)
# negative base and fractional power should create a complex
ans = (-1) ** 2.3
print("%.5g %.5g" % (ans.real, ans.imag))
ans = (-1.2) ** -3.4
print("%.5g %.5g" % (ans.real, ans.imag))
# check printing of inf/nan
print(float("nan") * 1j)
print(float("-nan") * 1j)
print(float("inf") * (1 + 1j))
print(float("-inf") * (1 + 1j))
# can't assign to attributes
try:
(1j).imag = 0
except AttributeError:
print("AttributeError")
# can't convert rhs to complex
try:
1j + []
except TypeError:
print("TypeError")
# unsupported unary op
try:
~(1j)
except TypeError:
print("TypeError")
# unsupported binary op
try:
1j // 2
except TypeError:
print("TypeError")
# unsupported binary op
try:
1j < 2j
except TypeError:
print("TypeError")
# small int on LHS, complex on RHS, unsupported op
try:
print(1 | 1j)
except TypeError:
print("TypeError")
# zero division
try:
1j / 0
except ZeroDivisionError:
print("ZeroDivisionError")
# zero division via power
try:
0j**-1
except ZeroDivisionError:
print("ZeroDivisionError")
try:
0j**1j
except ZeroDivisionError:
print("ZeroDivisionError")

View File

@@ -0,0 +1,5 @@
# test basic complex number functionality
# convert bignum to complex on rhs
ans = 1j + (1 << 70)
print("%.5g %.5g" % (ans.real, ans.imag))

View File

@@ -0,0 +1,10 @@
# test complex interacting with special reverse methods
class A:
def __radd__(self, x):
print("__radd__")
return 2
print(1j + A())

View File

@@ -0,0 +1,10 @@
# test complex interacting with special methods
class A:
def __add__(self, x):
print("__add__")
return 1
print(A() + 1j)

View File

@@ -0,0 +1,121 @@
# test basic float capabilities
# literals
print(0.12)
print(1.0)
print(1.2)
print(0e0)
print(0e0)
print(0e-0)
# float construction
print(float(1.2))
print(float("1.2"))
print(float("+1"))
print(float("1e1"))
print(float("1e+1"))
print(float("1e-1"))
print(float("inf"))
print(float("-inf"))
print(float("INF"))
print(float("infinity"))
print(float("INFINITY"))
print(float("nan"))
print(float("-nan"))
print(float("NaN"))
try:
float("")
except ValueError:
print("ValueError")
try:
float("1e+")
except ValueError:
print("ValueError")
try:
float("1z")
except ValueError:
print("ValueError")
# construct from something with the buffer protocol
print(float(b"1.2"))
print(float(bytearray(b"3.4")))
# unary operators
print(bool(0.0))
print(bool(1.2))
print(+(1.2))
print(-(1.2))
# division of integers
x = 1 / 2
print(x)
# /= operator
a = 1
a /= 2
print(a)
# floor division
print(1.0 // 2)
print(2.0 // 2)
# comparison
print(1.2 <= 3.4)
print(1.2 <= -3.4)
print(1.2 >= 3.4)
print(1.2 >= -3.4)
print(0.0 == False, 1.0 == True)
print(False == 0.0, True == 1.0)
# comparison of nan is special
nan = float("nan")
print(nan == 1.2)
print(nan == nan)
try:
1.0 / 0
except ZeroDivisionError:
print("ZeroDivisionError")
try:
1.0 // 0
except ZeroDivisionError:
print("ZeroDivisionError")
try:
1.2 % 0
except ZeroDivisionError:
print("ZeroDivisionError")
try:
0.0**-1
except ZeroDivisionError:
print("ZeroDivisionError")
# unsupported unary ops
try:
~1.2
except TypeError:
print("TypeError")
try:
1.2 in 3.4
except TypeError:
print("TypeError")
# small int on LHS, float on RHS, unsupported op
try:
print(1 | 1.0)
except TypeError:
print("TypeError")
# can't convert list to float
try:
float([])
except TypeError:
print("TypeError")
# test constant float with more than 255 chars
x = 1.84728699436059052516398251149631771898472869943605905251639825114963177189847286994360590525163982511496317718984728699436059052516398251149631771898472869943605905251639825114963177189847286994360590525163982511496317718984728699436059052516398251149631771898472869943605905251639825114963177189
print("%.5f" % x)

View File

@@ -0,0 +1,104 @@
# check cases converting float to int, requiring double precision float
try:
import ustruct as struct
import usys as sys
except:
import struct
import sys
maxsize_bits = 0
maxsize = sys.maxsize
while maxsize:
maxsize >>= 1
maxsize_bits += 1
# work out configuration values
is_64bit = maxsize_bits > 32
# 0 = none, 1 = long long, 2 = mpz
ll_type = None
if is_64bit:
if maxsize_bits < 63:
ll_type = 0
else:
if maxsize_bits < 31:
ll_type = 0
if ll_type is None:
one = 1
if one << 65 < one << 62:
ll_type = 1
else:
ll_type = 2
# This case occurs with time.time() values
if ll_type != 0:
print(int(1418774543.0))
print("%d" % 1418774543.0)
if ll_type == 3:
print(int(2.0**100))
print("%d" % 2.0**100)
else:
print(int(1073741823.0))
print("%d" % 1073741823.0)
testpass = True
p2_rng = ((30, 63, 1024), (62, 63, 1024))[is_64bit][ll_type]
for i in range(0, p2_rng):
bitcnt = len(bin(int(2.0**i))) - 3
if i != bitcnt:
print("fail: 2**%u was %u bits long" % (i, bitcnt))
testpass = False
print("power of 2 test: %s" % (testpass and "passed" or "failed"))
testpass = True
p10_rng = ((9, 18, 23), (18, 18, 23))[is_64bit][ll_type]
for i in range(0, p10_rng):
digcnt = len(str(int(10.0**i))) - 1
if i != digcnt:
print("fail: 10**%u was %u digits long" % (i, digcnt))
testpass = False
print("power of 10 test: %s" % (testpass and "passed" or "failed"))
def fp2int_test(num, name, should_fail):
try:
x = int(num)
passed = ~should_fail
except:
passed = should_fail
print("%s: %s" % (name, passed and "passed" or "failed"))
if ll_type != 2:
if ll_type == 0:
if is_64bit:
neg_bad_fp = -1.00000005 * 2.0**62.0
pos_bad_fp = 2.0**62.0
neg_good_fp = -(2.0**62.0)
pos_good_fp = 0.99999993 * 2.0**62.0
else:
neg_bad_fp = -1.00000005 * 2.0**30.0
pos_bad_fp = 2.0**30.0
neg_good_fp = -(2.0**30.0)
pos_good_fp = 0.9999999499 * 2.0**30.0
else:
neg_bad_fp = -0.51 * 2.0**64.0
pos_bad_fp = 2.0**63.0
neg_good_fp = -(2.0**63.0)
pos_good_fp = 1.9999998 * 2.0**62.0
fp2int_test(neg_bad_fp, "neg bad", True)
fp2int_test(pos_bad_fp, "pos bad", True)
fp2int_test(neg_good_fp, "neg good", False)
fp2int_test(pos_good_fp, "pos good", False)
else:
fp2int_test(-1.9999999999999981 * 2.0**1023.0, "large neg", False)
fp2int_test(1.9999999999999981 * 2.0**1023.0, "large pos", False)
fp2int_test(float("inf"), "inf test", True)
fp2int_test(float("-inf"), "inf test", True)
fp2int_test(float("nan"), "NaN test", True)
# test numbers < 1 (this used to fail; see issue #1044)
fp2int_test(0.0001, "small num", False)
struct.pack("I", int(1 / 2))

View File

@@ -0,0 +1,101 @@
# check cases converting float to int, relying only on single precision float
try:
import ustruct as struct
import usys as sys
except:
import struct
import sys
maxsize_bits = 0
maxsize = sys.maxsize
while maxsize:
maxsize >>= 1
maxsize_bits += 1
# work out configuration values
is_64bit = maxsize_bits > 32
# 0 = none, 1 = long long, 2 = mpz
ll_type = None
if is_64bit:
if maxsize_bits < 63:
ll_type = 0
else:
if maxsize_bits < 31:
ll_type = 0
if ll_type is None:
one = 1
if one << 65 < one << 62:
ll_type = 1
else:
ll_type = 2
# basic conversion
print(int(14187744.0))
print("%d" % 14187744.0)
if ll_type == 2:
print(int(2.0**100))
print("%d" % 2.0**100)
testpass = True
p2_rng = ((30, 63, 127), (62, 63, 127))[is_64bit][ll_type]
for i in range(0, p2_rng):
bitcnt = len(bin(int(2.0**i))) - 3
if i != bitcnt:
print("fail: 2.**%u was %u bits long" % (i, bitcnt))
testpass = False
print("power of 2 test: %s" % (testpass and "passed" or "failed"))
# TODO why does 10**12 fail this test for single precision float?
testpass = True
p10_rng = 9
for i in range(0, p10_rng):
digcnt = len(str(int(10.0**i))) - 1
if i != digcnt:
print("fail: 10.**%u was %u digits long" % (i, digcnt))
testpass = False
print("power of 10 test: %s" % (testpass and "passed" or "failed"))
def fp2int_test(num, name, should_fail):
try:
x = int(num)
passed = ~should_fail
except:
passed = should_fail
print("%s: %s" % (name, passed and "passed" or "failed"))
if ll_type != 2:
if ll_type == 0:
if is_64bit:
neg_bad_fp = -1.00000005 * 2.0**62.0
pos_bad_fp = 2.0**62.0
neg_good_fp = -(2.0**62.0)
pos_good_fp = 0.99999993 * 2.0**62.0
else:
neg_bad_fp = -1.00000005 * 2.0**30.0
pos_bad_fp = 2.0**30.0
neg_good_fp = -(2.0**30.0)
pos_good_fp = 0.9999999499 * 2.0**30.0
else:
neg_bad_fp = -0.51 * 2.0**64.0
pos_bad_fp = 2.0**63.0
neg_good_fp = -(2.0**63.0)
pos_good_fp = 1.9999998 * 2.0**62.0
fp2int_test(neg_bad_fp, "neg bad", True)
fp2int_test(pos_bad_fp, "pos bad", True)
fp2int_test(neg_good_fp, "neg good", False)
fp2int_test(pos_good_fp, "pos good", False)
else:
fp2int_test(-1.999999879 * 2.0**126.0, "large neg", False)
fp2int_test(1.999999879 * 2.0**126.0, "large pos", False)
fp2int_test(float("inf"), "inf test", True)
fp2int_test(float("-inf"), "inf test", True)
fp2int_test(float("nan"), "NaN test", True)
# test numbers < 1 (this used to fail; see issue #1044)
fp2int_test(0.0001, "small num", False)
struct.pack("I", int(1 / 2))

View File

@@ -0,0 +1,103 @@
# check cases converting float to int, relying only on single precision float
try:
import ustruct as struct
import usys as sys
except:
import struct
import sys
maxsize_bits = 0
maxsize = sys.maxsize
while maxsize:
maxsize >>= 1
maxsize_bits += 1
# work out configuration values
is_64bit = maxsize_bits > 32
# 0 = none, 1 = long long, 2 = mpz
ll_type = None
if is_64bit:
if maxsize_bits < 63:
ll_type = 0
else:
if maxsize_bits < 31:
ll_type = 0
if ll_type is None:
one = 1
if one << 65 < one << 62:
ll_type = 1
else:
ll_type = 2
# basic conversion
# fmt: off
print(int(14187745.))
print("%d" % 14187745.)
# fmt: on
if ll_type == 2:
print(int(2.0**100))
print("%d" % 2.0**100)
testpass = True
p2_rng = ((30, 63, 127), (62, 63, 127))[is_64bit][ll_type]
for i in range(0, p2_rng):
bitcnt = len(bin(int(2.0**i))) - 3
if i != bitcnt:
print("fail: 2.**%u was %u bits long" % (i, bitcnt))
testpass = False
print("power of 2 test: %s" % (testpass and "passed" or "failed"))
# TODO why does 10**12 fail this test for single precision float?
testpass = True
p10_rng = 9 if (ll_type == 0 and ~is_64bit) else 11
for i in range(0, p10_rng):
digcnt = len(str(int(10.0**i))) - 1
if i != digcnt:
print("fail: 10.**%u was %u digits long" % (i, digcnt))
testpass = False
print("power of 10 test: %s" % (testpass and "passed" or "failed"))
def fp2int_test(num, name, should_fail):
try:
x = int(num)
passed = ~should_fail
except:
passed = should_fail
print("%s: %s" % (name, passed and "passed" or "failed"))
if ll_type != 2:
if ll_type == 0:
if is_64bit:
neg_bad_fp = -1.00000005 * 2.0**62.0
pos_bad_fp = 2.0**62.0
neg_good_fp = -(2.0**62.0)
pos_good_fp = 0.99999993 * 2.0**62.0
else:
neg_bad_fp = -1.00000005 * 2.0**30.0
pos_bad_fp = 2.0**30.0
neg_good_fp = -(2.0**30.0)
pos_good_fp = 0.9999999499 * 2.0**30.0
else:
neg_bad_fp = -0.51 * 2.0**64.0
pos_bad_fp = 2.0**63.0
neg_good_fp = -(2.0**63.0)
pos_good_fp = 1.9999998 * 2.0**62.0
fp2int_test(neg_bad_fp, "neg bad", True)
fp2int_test(pos_bad_fp, "pos bad", True)
fp2int_test(neg_good_fp, "neg good", False)
fp2int_test(pos_good_fp, "pos good", False)
else:
fp2int_test(-1.999999879 * 2.0**127.0, "large neg", False)
fp2int_test(1.999999879 * 2.0**127.0, "large pos", False)
fp2int_test(float("inf"), "inf test", True)
fp2int_test(float("nan"), "NaN test", True)
# test numbers < 1 (this used to fail; see issue #1044)
fp2int_test(0.0001, "small num", False)
struct.pack("I", int(1 / 2))

View File

@@ -0,0 +1,25 @@
try:
from uarray import array
except ImportError:
try:
from array import array
except ImportError:
print("SKIP")
raise SystemExit
def test(a):
print(a)
a.append(1.2)
print(len(a), "%.3f" % a[0])
a.append(1)
a.append(False)
print(len(a), "%.3f %.3f" % (a[1], a[2]))
a[-1] = 3.45
print("%.3f" % a[-1])
test(array("f"))
test(array("d"))
print("{:.4f}".format(array("f", bytes(array("I", [0x3DCCCCCC])))[0]))

View File

@@ -0,0 +1,24 @@
# Extended float comparisons
class Foo:
pass
foo = Foo()
print(foo == 1.0)
print(1.0 == foo)
print(1.0 == Foo)
print(1.0 == [])
print(1.0 == {})
try:
print(foo < 1.0)
except TypeError:
print("TypeError")
try:
print(1.0 < foo)
except TypeError:
print("TypeError")

View File

@@ -0,0 +1,27 @@
# test floating point floor divide and modulus
# it has some tricky corner cases
def test(x, y):
div, mod = divmod(x, y)
print("%.8f %.8f %.8f %.8f" % (x // y, x % y, div, mod))
print(div == x // y, mod == x % y, abs(div * y + mod - x) < 1e-15)
test(1.23456, 0.7)
test(-1.23456, 0.7)
test(1.23456, -0.7)
test(-1.23456, -0.7)
a = 1.23456
b = 0.7
test(a, b)
test(a, -b)
test(-a, b)
test(-a, -b)
for i in range(25):
x = (i - 12.5) / 6
for j in range(25):
y = (j - 12.5) / 6
test(x, y)

View File

@@ -0,0 +1,35 @@
# test floating point floor divide and modulus
# it has some tricky corner cases
# pyboard has 32-bit floating point and gives different (but still
# correct) answers for certain combinations of divmod arguments.
def test(x, y):
div, mod = divmod(x, y)
print(div == x // y, mod == x % y, abs(div * y + mod - x) < 1e-6)
test(1.23456, 0.7)
test(-1.23456, 0.7)
test(1.23456, -0.7)
test(-1.23456, -0.7)
a = 1.23456
b = 0.7
test(a, b)
test(a, -b)
test(-a, b)
test(-a, -b)
for i in range(25):
x = (i - 12.5) / 6
for j in range(25):
y = (j - 12.5) / 6
test(x, y)
# test division by zero error
try:
divmod(1.0, 0)
except ZeroDivisionError:
print("ZeroDivisionError")

View File

@@ -0,0 +1,19 @@
# test float formatting
# general rounding
for val in (116, 1111, 1234, 5010, 11111):
print("%.0f" % val)
print("%.1f" % val)
print("%.3f" % val)
# make sure rounding is done at the correct precision
for prec in range(8):
print(("%%.%df" % prec) % 6e-5)
# check certain cases that had a digit value of 10 render as a ":" character
print("%.2e" % float("9" * 51 + "e-39"))
print("%.2e" % float("9" * 40 + "e-21"))
# check a case that would render negative digit values, eg ")" characters
# the string is converted back to a float to check for no illegal characters
float("%.23e" % 1e-80)

View File

@@ -0,0 +1,36 @@
# test parsing of floats
inf = float("inf")
# it shouldn't matter where the decimal point is if the exponent balances the value
print(float("1234") - float("0.1234e4"))
print(float("1.015625") - float("1015625e-6"))
# very large integer part with a very negative exponent should cancel out
print("%.4e" % float("9" * 60 + "e-60"))
print("%.4e" % float("9" * 60 + "e-40"))
# many fractional digits
print(float("." + "9" * 70))
print(float("." + "9" * 70 + "e20"))
print(float("." + "9" * 70 + "e-50") == float("1e-50"))
# tiny fraction with large exponent
print(float("." + "0" * 60 + "1e10") == float("1e-51"))
print(float("." + "0" * 60 + "9e25") == float("9e-36"))
print(float("." + "0" * 60 + "9e40") == float("9e-21"))
# ensure that accuracy is retained when value is close to a subnormal
print(float("1.00000000000000000000e-37"))
print(float("10.0000000000000000000e-38"))
print(float("100.000000000000000000e-39"))
# very large exponent literal
print(float("1e4294967301"))
print(float("1e-4294967301"))
print(float("1e18446744073709551621"))
print(float("1e-18446744073709551621"))
# check small decimals are as close to their true value as possible
for n in range(1, 10):
print(float("0.%u" % n) == n / 10)

View File

@@ -0,0 +1,21 @@
# test parsing of floats, requiring double-precision
# very large integer part with a very negative exponent should cancel out
print(float("9" * 400 + "e-100"))
print(float("9" * 400 + "e-200"))
print(float("9" * 400 + "e-400"))
# many fractional digits
print(float("." + "9" * 400))
print(float("." + "9" * 400 + "e100"))
print(float("." + "9" * 400 + "e-100"))
# tiny fraction with large exponent
print("%.14e" % float("." + "0" * 400 + "9e100"))
print("%.14e" % float("." + "0" * 400 + "9e200"))
print("%.14e" % float("." + "0" * 400 + "9e400"))
# ensure that accuracy is retained when value is close to a subnormal
print(float("1.00000000000000000000e-307"))
print(float("10.0000000000000000000e-308"))
print(float("100.000000000000000000e-309"))

View File

@@ -0,0 +1,17 @@
# test struct package with floats
try:
try:
import ustruct as struct
except:
import struct
except ImportError:
print("SKIP")
raise SystemExit
i = 1.0 + 1 / 2
# TODO: it looks like '=' format modifier is not yet supported
# for fmt in ('f', 'd', '>f', '>d', '<f', '<d', '=f', '=d'):
for fmt in ("f", "d", ">f", ">d", "<f", "<d"):
x = struct.pack(fmt, i)
v = struct.unpack(fmt, x)[0]
print("%2s: %.17f - %s" % (fmt, v, (i == v) and "passed" or "failed"))

View File

@@ -0,0 +1,20 @@
# Test behaviour of inf and nan in basic float operations
inf = float("inf")
nan = float("nan")
values = (-2, -1, 0, 1, 2, inf, nan)
for x in values:
for y in values:
print(x, y)
print(" + - *", x + y, x - y, x * y)
try:
print(" /", x / y)
except ZeroDivisionError:
print(" / ZeroDivisionError")
try:
print(" ** pow", x**y, pow(x, y))
except ZeroDivisionError:
print(" ** pow ZeroDivisionError")
print(" == != < <= > >=", x == y, x != y, x < y, x <= y, x > y, x >= y)

View File

@@ -0,0 +1,28 @@
# test bignum operation with float/complex
i = 1 << 65
# convert bignum to float on rhs
print("%.5g" % (2.0 * i))
# negative bignum as float
print("%.5g" % float(-i))
# this should convert to float
print("%.5g" % (i / 5))
# these should delegate to float
print("%.5g" % (i * 1.2))
print("%.5g" % (i / 1.2))
# this should delegate to complex
print("%.5g" % (i * 1.2j).imag)
# negative power should produce float
print("%.5g" % (i**-1))
print("%.5g" % ((2 + i - i) ** -3))
try:
i / 0
except ZeroDivisionError:
print("ZeroDivisionError")

View File

@@ -0,0 +1,9 @@
try:
1 / 0
except ZeroDivisionError:
print("ZeroDivisionError")
try:
0**-1
except ZeroDivisionError:
print("ZeroDivisionError")

View File

@@ -0,0 +1,8 @@
# negative power should produce float
x = 2
print(x**-2)
x = 3
x **= -2
print("%.5f" % x)

View File

@@ -0,0 +1,6 @@
# since black code formatter does not allow leading decimal point with nothing
# before it, we need to test it explicitly
# fmt: off
print(.1)
# fmt: on

View File

@@ -0,0 +1,8 @@
x = [1, 2]
print(x[1])
try:
print(x[1.0])
except TypeError:
print("TypeError")

View File

@@ -0,0 +1,11 @@
# Tests various constants of the math module.
try:
import math
from math import exp, cos
except ImportError:
print("SKIP")
raise SystemExit
print(math.e == exp(1.0))
print(cos(math.pi))

View File

@@ -0,0 +1,17 @@
# Tests constants of the math module available only with MICROPY_PY_MATH_CONSTANTS.
try:
import math
from math import isnan
math.tau
except (ImportError, AttributeError):
print("SKIP")
raise SystemExit
print(math.tau == 2.0 * math.pi)
print(math.inf == float("inf"))
print(-math.inf == -float("inf"))
print(isnan(math.nan))
print(isnan(-math.nan))

View File

@@ -0,0 +1,51 @@
# Tests domain errors in math functions
try:
import math
except ImportError:
print("SKIP")
raise SystemExit
inf = float("inf")
nan = float("nan")
# single argument functions
for name, f, args in (
("fabs", math.fabs, ()),
("ceil", math.ceil, ()),
("floor", math.floor, ()),
("trunc", math.trunc, ()),
("sqrt", math.sqrt, (-1, 0)),
("exp", math.exp, ()),
("sin", math.sin, ()),
("cos", math.cos, ()),
("tan", math.tan, ()),
("asin", math.asin, (-1.1, 1, 1.1)),
("acos", math.acos, (-1.1, 1, 1.1)),
("atan", math.atan, ()),
("ldexp", lambda x: math.ldexp(x, 0), ()),
("radians", math.radians, ()),
("degrees", math.degrees, ()),
):
for x in args + (inf, nan):
try:
ans = f(x)
print("%.4f" % ans)
except ValueError:
print(name, "ValueError")
except OverflowError:
print(name, "OverflowError")
# double argument functions
for name, f, args in (
("pow", math.pow, ((0, 2), (-1, 2), (0, -1), (-1, 2.3), (nan, 0), (1, nan))),
("fmod", math.fmod, ((1.2, inf), (1.2, -inf), (1.2, 0), (inf, 1.2))),
("atan2", math.atan2, ((0, 0), (-inf, inf), (-inf, -inf), (inf, -inf))),
("copysign", math.copysign, ()),
):
for x in args + ((0, inf), (inf, 0), (inf, inf), (inf, nan), (nan, inf), (nan, nan)):
try:
ans = f(*x)
print("%.4f" % ans)
except ValueError:
print(name, "ValueError")

View File

@@ -0,0 +1,37 @@
# Tests domain errors in special math functions
try:
import math
math.erf
except (ImportError, AttributeError):
print("SKIP")
raise SystemExit
inf = float("inf")
nan = float("nan")
# single argument functions
for name, f, args in (
("expm1", math.exp, ()),
("log2", math.log2, (-1, 0)),
("log10", math.log10, (-1, 0)),
("sinh", math.sinh, ()),
("cosh", math.cosh, ()),
("tanh", math.tanh, ()),
("asinh", math.asinh, ()),
("acosh", math.acosh, (-1, 0.9, 1)),
("atanh", math.atanh, (-1, 1)),
("erf", math.erf, ()),
("erfc", math.erfc, ()),
("gamma", math.gamma, (-2, -1, 0, 1)),
("lgamma", math.lgamma, (-2, -1, 0, 1)),
):
for x in args + (inf, -inf, nan):
try:
ans = f(x)
print("%.4f" % ans)
except ValueError:
print(name, "ValueError")
except OverflowError:
print(name, "OverflowError")

View File

@@ -0,0 +1,15 @@
try:
import math
math.factorial
except (ImportError, AttributeError):
print("SKIP")
raise SystemExit
for fun in (math.factorial,):
for x in range(-1, 30):
try:
print("%d" % fun(x))
except ValueError as e:
print("ValueError")

View File

@@ -0,0 +1,91 @@
# Tests the functions imported from math
try:
from math import *
except ImportError:
print("SKIP")
raise SystemExit
test_values = [-100.0, -1.23456, -1, -0.5, 0.0, 0.5, 1.23456, 100.0]
test_values_small = [
-10.0,
-1.23456,
-1,
-0.5,
0.0,
0.5,
1.23456,
10.0,
] # so we don't overflow 32-bit precision
unit_range_test_values = [-1.0, -0.75, -0.5, -0.25, 0.0, 0.25, 0.5, 0.75, 1.0]
functions = [
("sqrt", sqrt, test_values),
("exp", exp, test_values_small),
("log", log, test_values),
("cos", cos, test_values),
("sin", sin, test_values),
("tan", tan, test_values),
("acos", acos, unit_range_test_values),
("asin", asin, unit_range_test_values),
("atan", atan, test_values),
("ceil", ceil, test_values),
("fabs", fabs, test_values),
("floor", floor, test_values),
("trunc", trunc, test_values),
("radians", radians, test_values),
("degrees", degrees, test_values),
]
for function_name, function, test_vals in functions:
print(function_name)
for value in test_vals:
try:
print("{:.5g}".format(function(value)))
except ValueError as e:
print(str(e))
tuple_functions = [
("frexp", frexp, test_values),
("modf", modf, test_values),
]
for function_name, function, test_vals in tuple_functions:
print(function_name)
for value in test_vals:
x, y = function(value)
print("{:.5g} {:.5g}".format(x, y))
binary_functions = [
(
"copysign",
copysign,
[(23.0, 42.0), (-23.0, 42.0), (23.0, -42.0), (-23.0, -42.0), (1.0, 0.0), (1.0, -0.0)],
),
("pow", pow, ((1.0, 0.0), (0.0, 1.0), (2.0, 0.5), (-3.0, 5.0), (-3.0, -4.0))),
("atan2", atan2, ((1.0, 0.0), (0.0, 1.0), (2.0, 0.5), (-3.0, 5.0), (-3.0, -4.0))),
("fmod", fmod, ((1.0, 1.0), (0.0, 1.0), (2.0, 0.5), (-3.0, 5.0), (-3.0, -4.0))),
("ldexp", ldexp, ((1.0, 0), (0.0, 1), (2.0, 2), (3.0, -2), (-3.0, -4))),
(
"log",
log,
(
(2.0, 2.0),
(3.0, 2.0),
(4.0, 5.0),
(0.0, 1.0),
(1.0, 0.0),
(-1.0, 1.0),
(1.0, -1.0),
(2.0, 1.0),
),
),
]
for function_name, function, test_vals in binary_functions:
print(function_name)
for value1, value2 in test_vals:
try:
print("{:.5g}".format(function(value1, value2)))
except (ValueError, ZeroDivisionError) as e:
print(type(e))

View File

@@ -0,0 +1,15 @@
# Test the bool functions from math
try:
from math import isfinite, isnan, isinf
except ImportError:
print("SKIP")
raise SystemExit
test_values = [1, 0, -1, 1.0, 0.0, -1.0, float("NaN"), float("Inf"), -float("NaN"), -float("Inf")]
functions = [isfinite, isnan, isinf]
for val in test_values:
for f in functions:
print(f(val))

View File

@@ -0,0 +1,14 @@
# test the math functions that return ints
try:
import math
except ImportError:
print("SKIP")
raise SystemExit
for fun in (math.ceil, math.floor, math.trunc):
for x in (-1.6, -0.2, 0, 0.6, 1.4, float("inf"), float("nan")):
try:
print(fun(x))
except (ValueError, OverflowError) as e:
print(type(e))

View File

@@ -0,0 +1,11 @@
# test the math functions that return ints, with very large results
try:
import math
except ImportError:
print("SKIP")
raise SystemExit
for fun in (math.ceil, math.floor, math.trunc):
for x in (-1e25, 1e25):
print("%.3g" % fun(x))

View File

@@ -0,0 +1,52 @@
# test the special functions imported from math
try:
from math import *
erf
except (ImportError, NameError):
print("SKIP")
raise SystemExit
test_values = [
-8.0,
-2.5,
-1,
-0.5,
0.0,
0.5,
2.5,
8.0,
]
pos_test_values = [
0.001,
0.1,
0.5,
1.0,
1.5,
10.0,
]
functions = [
("expm1", expm1, test_values),
("log2", log2, test_values),
("log10", log10, test_values),
("cosh", cosh, test_values),
("sinh", sinh, test_values),
("tanh", tanh, [-1e6, -100] + test_values + [100, 1e6]),
("acosh", acosh, [1.0, 5.0, 1.0]),
("asinh", asinh, test_values),
("atanh", atanh, [-0.99, -0.5, 0.0, 0.5, 0.99]),
("erf", erf, test_values),
("erfc", erfc, test_values),
("gamma", gamma, pos_test_values),
("lgamma", lgamma, pos_test_values + [50.0, 100.0]),
]
for function_name, function, test_vals in functions:
print(function_name)
for value in test_vals:
try:
print("{:.4g}".format(function(value)))
except ValueError as e:
print(str(e))

View File

@@ -0,0 +1,50 @@
# test math.isclose (appeared in Python 3.5)
try:
from math import isclose
except ImportError:
print("SKIP")
raise SystemExit
def test(a, b, **kwargs):
print(isclose(a, b, **kwargs))
def test_combinations(a, b, **kwargs):
test(a, a, **kwargs)
test(a, b, **kwargs)
test(b, a, **kwargs)
test(b, b, **kwargs)
# Special numbers
test_combinations(float("nan"), 1)
test_combinations(float("inf"), 1)
test_combinations(float("-inf"), 1)
# Equality
test(1.0, 1.0, rel_tol=0.0, abs_tol=0.0)
test(2.35e-100, 2.35e-100, rel_tol=0.0, abs_tol=0.0)
test(2.1234e100, 2.1234e100, rel_tol=0.0, abs_tol=0.0)
# Relative tolerance
test(1000.0, 1001.0, rel_tol=1e-3)
test(1000.0, 1001.0, rel_tol=1e-4)
test(1000, 1001, rel_tol=1e-3)
test(1000, 1001, rel_tol=1e-4)
test_combinations(0, 1, rel_tol=1.0)
# Absolute tolerance
test(0.0, 1e-10, abs_tol=1e-10, rel_tol=0.1)
test(0.0, 1e-10, abs_tol=0.0, rel_tol=0.1)
# Bad parameters
try:
isclose(0, 0, abs_tol=-1)
except ValueError:
print("ValueError")
try:
isclose(0, 0, rel_tol=-1)
except ValueError:
print("ValueError")

View File

@@ -0,0 +1,27 @@
False
False
False
True
True
False
False
True
True
False
False
True
True
True
True
True
False
True
False
True
True
True
True
True
False
ValueError
ValueError

View File

@@ -0,0 +1,10 @@
# tests for things that only Python 3.6 supports, needing floats
# underscores in numeric literals
print(1_000.1_8)
print("%.2g" % 1e1_2)
# underscore supported by int/float constructors
print(float("1_2_3"))
print(float("1_2_3.4"))
print("%.2g" % float("1e1_3"))

View File

@@ -0,0 +1,5 @@
1000.18
1e+12
123.0
123.4
1e+13

View File

@@ -0,0 +1,45 @@
def test(fmt, *args):
print("{:8s}".format(fmt) + ">" + fmt.format(*args) + "<")
test("{:10.4}", 123.456)
test("{:10.4e}", 123.456)
test("{:10.4e}", -123.456)
test("{:10.4f}", 123.456)
test("{:10.4f}", -123.456)
test("{:10.4g}", 123.456)
test("{:10.4g}", -123.456)
test("{:10.4n}", 123.456)
test("{:e}", 100)
test("{:f}", 200)
test("{:g}", 300)
test("{:10.4E}", 123.456)
test("{:10.4E}", -123.456)
test("{:10.4F}", 123.456)
test("{:10.4F}", -123.456)
test("{:10.4G}", 123.456)
test("{:10.4G}", -123.456)
test("{:06e}", float("inf"))
test("{:06e}", float("-inf"))
test("{:06e}", float("nan"))
test("{:f}", False)
test("{:f}", True)
# The following fails right now
# test("{:10.1}", 0.0)
print("%.0f" % (1.750000 % 0.08333333333))
# Below isn't compatible with single-precision float
# print("%.1f" % (1.750000 % 0.08333333333))
# print("%.2f" % (1.750000 % 0.08333333333))
# print("%.12f" % (1.750000 % 0.08333333333))
# tests for errors in format string
try:
"{:10.1b}".format(0.0)
except ValueError:
print("ValueError")

View File

@@ -0,0 +1,182 @@
# Change the following to True to get a much more comprehensive set of tests
# to run, albeit, which take considerably longer.
full_tests = False
def test(fmt, *args):
print("{:8s}".format(fmt) + ">" + fmt.format(*args) + "<")
def test_fmt(conv, fill, alignment, sign, prefix, width, precision, type, arg):
fmt = "{"
if conv:
fmt += "!"
fmt += conv
fmt += ":"
if alignment:
fmt += fill
fmt += alignment
fmt += sign
fmt += prefix
fmt += width
if precision:
fmt += "."
fmt += precision
fmt += type
fmt += "}"
test(fmt, arg)
if fill == "0" and alignment == "=":
fmt = "{:"
fmt += sign
fmt += prefix
fmt += width
if precision:
fmt += "."
fmt += precision
fmt += type
fmt += "}"
test(fmt, arg)
eg_nums = (
0.0,
-0.0,
0.1,
1.234,
12.3459,
1.23456789,
123456789.0,
-0.0,
-0.1,
-1.234,
-12.3459,
1e4,
1e-4,
1e5,
1e-5,
1e6,
1e-6,
1e10,
1e37,
-1e37,
1e-37,
-1e-37,
1.23456e8,
1.23456e7,
1.23456e6,
1.23456e5,
1.23456e4,
1.23456e3,
1.23456e2,
1.23456e1,
1.23456e0,
1.23456e-1,
1.23456e-2,
1.23456e-3,
1.23456e-4,
1.23456e-5,
1.23456e-6,
1.23456e-7,
1.23456e-8,
-1.23456e8,
-1.23456e7,
-1.23456e6,
-1.23456e5,
-1.23456e4,
-1.23456e3,
-1.23456e2,
-1.23456e1,
-1.23456e0,
-1.23456e-1,
-1.23456e-2,
-1.23456e-3,
-1.23456e-4,
-1.23456e-5,
-1.23456e-6,
-1.23456e-7,
-1.23456e-8,
)
if full_tests:
for type in ("e", "E", "g", "G", "n"):
for width in ("", "4", "6", "8", "10"):
for alignment in ("", "<", ">", "=", "^"):
for fill in ("", "@", "0", " "):
for sign in ("", "+", "-", " "):
for prec in ("", "1", "3", "6"):
for num in eg_nums:
test_fmt("", fill, alignment, sign, "", width, prec, type, num)
# Note: We use 1.23459 rather than 1.2345 because '{:3f}'.format(1.2345)
# rounds differently than print("%.3f", 1.2345);
f_nums = (
0.0,
-0.0,
0.0001,
0.001,
0.01,
0.1,
1.0,
10.0,
0.0012,
0.0123,
0.1234,
1.23459,
12.3456,
-0.0001,
-0.001,
-0.01,
-0.1,
-1.0,
-10.0,
-0.0012,
-0.0123,
-0.1234,
-1.23459,
-12.3456,
)
if full_tests:
for type in ("f", "F"):
for width in ("", "4", "6", "8", "10"):
for alignment in ("", "<", ">", "=", "^"):
for fill in ("", " ", "0", "@"):
for sign in ("", "+", "-", " "):
# An empty precision defaults to 6, but when uPy is
# configured to use a float, we can only use a
# precision of 6 with numbers less than 10 and still
# get results that compare to CPython (which uses
# long doubles).
for prec in ("1", "2", "3"):
for num in f_nums:
test_fmt("", fill, alignment, sign, "", width, prec, type, num)
for num in int_nums2:
test_fmt("", fill, alignment, sign, "", width, "", type, num)
pct_nums1 = (0.1, 0.58, 0.99, -0.1, -0.58, -0.99)
pct_nums2 = (True, False, 1, 0, -1)
if full_tests:
type = "%"
for width in ("", "4", "6", "8", "10"):
for alignment in ("", "<", ">", "=", "^"):
for fill in ("", " ", "0", "@"):
for sign in ("", "+", "-", " "):
# An empty precision defaults to 6, but when uPy is
# configured to use a float, we can only use a
# precision of 6 with numbers less than 10 and still
# get results that compare to CPython (which uses
# long doubles).
for prec in ("1", "2", "3"):
for num in pct_nums1:
test_fmt("", fill, alignment, sign, "", width, prec, type, num)
for num in pct_nums2:
test_fmt("", fill, alignment, sign, "", width, "", type, num)
else:
for num in pct_nums1:
test_fmt("", "", "", "", "", "", "1", "%", num)
# We don't currently test a type of '' with floats (see the detailed comment
# in objstr.c)

View File

@@ -0,0 +1,42 @@
def test(fmt, *args):
print("{:8s}".format(fmt) + ">" + fmt.format(*args) + "<")
test("{:10.4}", 123.456)
test("{:10.4e}", 123.456)
test("{:10.4e}", -123.456)
# test("{:10.4f}", 123.456)
# test("{:10.4f}", -123.456)
test("{:10.4g}", 123.456)
test("{:10.4g}", -123.456)
test("{:10.4n}", 123.456)
test("{:e}", 100)
test("{:f}", 200)
test("{:g}", 300)
test("{:10.4E}", 123.456)
test("{:10.4E}", -123.456)
# test("{:10.4F}", 123.456)
# test("{:10.4F}", -123.456)
test("{:10.4G}", 123.456)
test("{:10.4G}", -123.456)
test("{:06e}", float("inf"))
test("{:06e}", float("-inf"))
test("{:06e}", float("nan"))
# The following fails right now
# test("{:10.1}", 0.0)
print("%.0f" % (1.750000 % 0.08333333333))
# Below isn't compatible with single-precision float
# print("%.1f" % (1.750000 % 0.08333333333))
# print("%.2f" % (1.750000 % 0.08333333333))
# print("%.12f" % (1.750000 % 0.08333333333))
# tests for errors in format string
try:
"{:10.1b}".format(0.0)
except ValueError:
print("ValueError")

View File

@@ -0,0 +1,49 @@
print("%s" % 1.0)
print("%r" % 1.0)
print("%d" % 1.0)
print("%i" % 1.0)
print("%u" % 1.0)
# these 3 have different behaviour in Python 3.x versions
# uPy raises a TypeError, following Python 3.5 (earlier versions don't)
# print("%x" % 18.0)
# print("%o" % 18.0)
# print("%X" % 18.0)
print("%e" % 1.23456)
print("%E" % 1.23456)
print("%f" % 1.23456)
print("%F" % 1.23456)
print("%g" % 1.23456)
print("%G" % 1.23456)
print("%06e" % float("inf"))
print("%06e" % float("-inf"))
print("%06e" % float("nan"))
print("%02.3d" % 123) # prec > width
print("%+f %+f" % (1.23, -1.23)) # float sign
print("% f % f" % (1.23, -1.23)) # float space sign
print("%0f" % -1.23) # negative number with 0 padding
# numbers with large negative exponents
print("%f" % 1e-10)
print("%f" % 1e-20)
print("%f" % 1e-50)
print("%f" % 1e-100)
print("%f" % 1e-300)
# large decimal precision should be truncated and not overflow buffer
# the output depends on the FP calculation so only first 2 digits are printed
# (the 'g' with small e are printed using 'f' style, so need to be checked)
print(("%.40f" % 1e-300)[:2])
print(("%.40g" % 1e-1)[:2])
print(("%.40g" % 1e-2)[:2])
print(("%.40g" % 1e-3)[:2])
print(("%.40g" % 1e-4)[:2])
print("%.0g" % 1) # 0 precision 'g'
print("%.1e" % 9.99) # round up with positive exponent
print("%.1e" % 0.999) # round up with negative exponent

View File

@@ -0,0 +1,26 @@
# test formatting floats with large precision, that it doesn't overflow the buffer
def test(num, num_str):
if num == float("inf") or num == 0.0 and num_str != "0.0":
# skip numbers that overflow or underflow the FP precision
return
for kind in ("e", "f", "g"):
# check precision either side of the size of the buffer (32 bytes)
for prec in range(23, 36, 2):
fmt = "%." + "%d" % prec + kind
s = fmt % num
check = abs(float(s) - num)
if num > 1:
check /= num
if check > 1e-6:
print("FAIL", num_str, fmt, s, len(s), check)
# check pure zero
test(0.0, "0.0")
# check some powers of 10, making sure to include exponents with 3 digits
for e in range(-8, 8):
num = pow(10, e)
test(num, "1e%d" % e)

View File

@@ -0,0 +1,23 @@
# test formatting floats with large precision, that it doesn't overflow the buffer
def test(num, num_str):
if num == float("inf") or num == 0.0 and num_str != "0.0":
# skip numbers that overflow or underflow the FP precision
return
for kind in ("e", "f", "g"):
# check precision either side of the size of the buffer (32 bytes)
for prec in range(23, 36, 2):
fmt = "%." + "%d" % prec + kind
s = fmt % num
check = abs(float(s) - num)
if num > 1:
check /= num
if check > 1e-6:
print("FAIL", num_str, fmt, s, len(s), check)
# check most powers of 10, making sure to include exponents with 3 digits
for e in range(-101, 102):
num = pow(10, e)
test(num, "1e%d" % e)

View File

@@ -0,0 +1,3 @@
# uPy and CPython outputs differ for the following
print("%.1g" % -9.9) # round up 'g' with '-' sign
print("%.2g" % 99.9) # round up

View File

@@ -0,0 +1,2 @@
-10
100

View File

@@ -0,0 +1,7 @@
# Test true-ish value handling
if not 0.0:
print("float 0")
if not 0 + 0j:
print("complex 0")

View File

@@ -0,0 +1,17 @@
# float types
print(float)
print(complex)
print(type(float()) == float)
print(type(complex()) == complex)
print(type(0.0) == float)
print(type(1j) == complex)
# hashing float types
d = dict()
d[float] = complex
d[complex] = float
print(len(d))