blueloveTH 2 年 前
コミット
f650f159b4
6 ファイル変更23 行追加8 行削除
  1. 4 0
      docs/modules/math.md
  2. 2 0
      include/pocketpy/common.h
  3. 1 1
      include/pocketpy/linalg.h
  4. 5 5
      python/cmath.py
  5. 6 0
      src/pocketpy.cpp
  6. 5 2
      tests/10_cmath.py

+ 4 - 0
docs/modules/math.md

@@ -59,6 +59,10 @@ Return `True` if `x` is a positive or negative infinity, and `False` otherwise.
 
 Return `True` if `x` is a NaN (not a number), and `False` otherwise.
 
+### `math.isclose(a, b)`
+
+Return `True` if the values `a` and `b` are close to each other and `False` otherwise.
+
 ### `math.exp(x)`
 
 Return `e` raised to the power of `x`.

+ 2 - 0
include/pocketpy/common.h

@@ -78,6 +78,7 @@ struct NumberTraits<4> {
 
 	static constexpr int_t kMaxSmallInt = (1 << 28) - 1;
 	static constexpr int_t kMinSmallInt = - (1 << 28);
+	static constexpr float_t kEpsilon = 1e-4;
 };
 
 template <>
@@ -87,6 +88,7 @@ struct NumberTraits<8> {
 
 	static constexpr int_t kMaxSmallInt = (1ll << 60) - 1;
 	static constexpr int_t kMinSmallInt = - (1ll << 60);
+	static constexpr float_t kEpsilon = 1e-8;
 };
 
 using Number = NumberTraits<sizeof(void*)>;

+ 1 - 1
include/pocketpy/linalg.h

@@ -4,7 +4,7 @@
 
 namespace pkpy{
 
-inline bool isclose(float a, float b){ return fabsf(a - b) < 1e-4f; }
+inline bool isclose(float a, float b){ return std::fabsf(a - b) <= NumberTraits<4>::kEpsilon; }
 
 struct Vec2{
     float x, y;

+ 5 - 5
python/cmath.py

@@ -13,14 +13,17 @@ class complex:
     def imag(self):
         return self._imag
     
+    def conjugate(self):
+        return complex(self.real, -self.imag)
+    
     def __repr__(self):
         return f"({self.real}+{self.imag}j)"
     
     def __eq__(self, other):
         if type(other) is complex:
-            return self.real == other.real and self.imag == other.imag
+            return math.isclose(self.real, other.real) and math.isclose(self.imag, other.imag)
         if type(other) in (int, float):
-            return self.real == other and self.imag == 0
+            return math.isclose(self.real, other) and self.imag == 0
         return NotImplemented
     
     def __add__(self, other):
@@ -144,9 +147,6 @@ def isinf(z: complex):
 def isnan(z: complex):
     return math.isnan(z.real) or math.isnan(z.imag)
 
-def isclose(*args, **kwargs):
-    raise NotImplementedError
-
 # Constants
 
 pi = math.pi

+ 6 - 0
src/pocketpy.cpp

@@ -1488,6 +1488,12 @@ void add_module_math(VM* vm){
     vm->bind_func<1>(mod, "isinf", PK_LAMBDA(VAR(std::isinf(CAST_F(args[0])))));
     vm->bind_func<1>(mod, "isnan", PK_LAMBDA(VAR(std::isnan(CAST_F(args[0])))));
 
+    vm->bind_func<2>(mod, "isclose", [](VM* vm, ArgsView args) {
+        f64 a = CAST_F(args[0]);
+        f64 b = CAST_F(args[1]);
+        return VAR(std::fabs(a - b) <= Number::kEpsilon);
+    });
+
     vm->bind_func<1>(mod, "exp", PK_LAMBDA(VAR(std::exp(CAST_F(args[0])))));
     vm->bind_func<1>(mod, "log", PK_LAMBDA(VAR(std::log(CAST_F(args[0])))));
     vm->bind_func<1>(mod, "log2", PK_LAMBDA(VAR(std::log2(CAST_F(args[0])))));

+ 5 - 2
tests/10_cmath.py

@@ -12,6 +12,9 @@ assert (1+2j)*3 == 3+6j
 
 import cmath
 
+assert (1+2j)**2 == -3+4j
+
+assert (1+2j).conjugate() == 1-2j
+
 res = cmath.sqrt(1+2j)
-assert round(res.real, 3) == 1.272, res.real
-assert round(res.imag, 3) == 0.786, res.imag
+assert res == 1.272019649514069+0.7861513777574233j