94 lines
3.6 KiB
Python
94 lines
3.6 KiB
Python
from mcp_calculator.ops.context import MathError
|
|
from mcp_calculator.ops.number_theory import number_theory
|
|
from mcp_calculator.ops.units import convert_units
|
|
from tests.support import MathTestCase
|
|
|
|
|
|
class NumberTheoryTest(MathTestCase):
|
|
def test_operations(self):
|
|
cases = [
|
|
("gcd", [48, 180], 12),
|
|
("lcm", [4, 6, 10], 60),
|
|
("is_prime", [97], True),
|
|
("is_prime", ["2305843009213693951"], True),
|
|
("next_prime", [100], 101),
|
|
("previous_prime", [100], 97),
|
|
("nth_prime", [10], 29),
|
|
("totient", [36], 12),
|
|
("mod", [-7, 3], 2),
|
|
("mod_pow", [2, 100, 97], 16),
|
|
("mod_inverse", [3, 11], 4),
|
|
("binomial", [49, 6], 13983816),
|
|
("permutations", [5, 2], 20),
|
|
("fibonacci", [50], 12586269025),
|
|
("factorial", [10], 3628800),
|
|
]
|
|
for operation, values, expected in cases:
|
|
with self.subTest(operation=operation, values=values):
|
|
self.assertEqual(number_theory(operation, values)["result"], expected)
|
|
|
|
def test_big_results_are_strings(self):
|
|
r = number_theory("factorial", [30])
|
|
self.assertEqual(r["result"], "265252859812191058636308480000000")
|
|
self.assertEqual(r["digits"], 33)
|
|
|
|
def test_factorize(self):
|
|
r = number_theory("factorize", [360])
|
|
self.assertEqual(r["result"], {"2": 3, "3": 2, "5": 1})
|
|
self.assertEqual(r["product_form"], "2^3 * 3^2 * 5")
|
|
|
|
def test_crt(self):
|
|
self.assertEqual(number_theory("crt", [2, 3, 2], moduli=[3, 5, 7])["result"], 23)
|
|
|
|
def test_base_convert(self):
|
|
self.assertEqual(number_theory("base_convert", ["ff"], from_base=16, to_base=2)["result"], "11111111")
|
|
self.assertEqual(number_theory("base_convert", ["0x1F"], from_base=16, to_base=10)["result"], "31")
|
|
self.assertEqual(number_theory("base_convert", ["-10"], to_base=2)["result"], "-1010")
|
|
|
|
def test_continued_fraction(self):
|
|
self.assertEqual(number_theory("continued_fraction", ["415/93"])["result"], [4, 2, 6, 7])
|
|
|
|
def test_primes_in_range(self):
|
|
self.assertEqual(number_theory("primes_in_range", [10, 30])["result"], [11, 13, 17, 19, 23, 29])
|
|
|
|
def test_arity_errors(self):
|
|
with self.assertRaisesRegex(MathError, "values"):
|
|
number_theory("mod_pow", [2, 3])
|
|
|
|
def test_no_inverse(self):
|
|
with self.assertRaisesRegex(MathError, "no inverse"):
|
|
number_theory("mod_inverse", [2, 4])
|
|
|
|
def test_non_integer(self):
|
|
with self.assertRaisesRegex(MathError, "not an integer"):
|
|
number_theory("gcd", ["1.5", 3])
|
|
|
|
|
|
class UnitsTest(MathTestCase):
|
|
def test_speed(self):
|
|
self.assertApprox(convert_units("100 km/h", "m/s")["magnitude"], 27.7777777778)
|
|
|
|
def test_temperature(self):
|
|
self.assertApprox(convert_units("25 degC", "degF")["magnitude"], 77)
|
|
|
|
def test_quantity_arithmetic(self):
|
|
self.assertApprox(convert_units("5 km/h * 2 h", "m")["magnitude"], 10000)
|
|
|
|
def test_force(self):
|
|
self.assertApprox(convert_units("1.5 kg * 9.81 m/s^2", "N")["magnitude"], 14.715)
|
|
|
|
def test_base_units(self):
|
|
r = convert_units("3 kWh")
|
|
self.assertApprox(r["magnitude"], 10_800_000)
|
|
self.assertIn("note", r)
|
|
|
|
def test_data_units(self):
|
|
self.assertApprox(convert_units("1 GiB", "MB")["magnitude"], 1073.741824)
|
|
|
|
def test_incompatible(self):
|
|
with self.assertRaisesRegex(MathError, "incompatible"):
|
|
convert_units("5 kg", "m")
|
|
|
|
def test_unknown_unit(self):
|
|
with self.assertRaisesRegex(MathError, "unknown"):
|
|
convert_units("5 flurbs", "m")
|