mirror of
https://github.com/pocketpy/pocketpy
synced 2026-02-26 17:30:17 +00:00
Compare commits
9 Commits
657e54d2f7
...
223e469668
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
223e469668 | ||
|
|
0c965d8c5b | ||
|
|
ef2481b8a5 | ||
|
|
9e4636b619 | ||
|
|
e82b2b98cf | ||
|
|
08f39b8444 | ||
|
|
2d1d61d9ca | ||
|
|
c32a97084b | ||
|
|
c048ec9faf |
@ -1 +1 @@
|
|||||||
Subproject commit 2d9e04701ddac77eb33eb7f9dcb24cab5bb10412
|
Subproject commit cc7cdccae657b0f81a1e234eb9d4ed4c458bda0f
|
||||||
76
docs/gsoc2026/guide.md
Normal file
76
docs/gsoc2026/guide.md
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
---
|
||||||
|
icon: rocket
|
||||||
|
order: 10
|
||||||
|
label: "Application Guide"
|
||||||
|
---
|
||||||
|
|
||||||
|
Welcome to the Google Summer of Code 2026 application guide for pocketpy.
|
||||||
|
We are recruiting a student who is passionate about vibe coding and mobile game development.
|
||||||
|
|
||||||
|
See [Project Ideas (TBA)](./ideas.md) for more details about the project.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
To apply for this project, you need to satisfy the following prerequisites:
|
||||||
|
|
||||||
|
+ You are a student enrolled in an accredited institution (university, college, etc.) pursuing a degree in computer science or a related field. And this is your first time participating in Google Summer of Code.
|
||||||
|
+ You have interest in vibe coding and mobile game development.
|
||||||
|
+ You are experienced in [Python](https://www.python.org/) and backend technologies, such as [FastAPI](https://fastapi.tiangolo.com/) or [Flask](https://flask.palletsprojects.com/).
|
||||||
|
+ You are glad to learn mobile app development using frameworks like [Flutter](https://flutter.dev/).
|
||||||
|
|
||||||
|
## Application steps
|
||||||
|
|
||||||
|
### Step 1
|
||||||
|
|
||||||
|
If you think you meet the prerequisites,
|
||||||
|
send an email to `blueloveth@foxmail.com` with the following information.
|
||||||
|
|
||||||
|
1. A brief introduction about yourself, including the most related open sourced project you have worked on before. It is highly recommended to attach your Github profile link.
|
||||||
|
2. Your understanding of this project and why you are capable of completing it.
|
||||||
|
3. Your free time during the whole GSoC period (From 2026-03-01 to 2026-08-31).
|
||||||
|
|
||||||
|
### Step 2
|
||||||
|
|
||||||
|
After you get a positive reply from us,
|
||||||
|
you need to complete 1~2 pull requests to pocketpy's repository on GitHub.
|
||||||
|
This is mandatory as it demonstrates your coding skills and commitment to the project.
|
||||||
|
We will provide you a few good first issues to work on.
|
||||||
|
|
||||||
|
### Step 3
|
||||||
|
|
||||||
|
Once your pull requests are merged,
|
||||||
|
we will guide you to write a full proposal
|
||||||
|
for the project you are going to work on during GSoC 2026.
|
||||||
|
This proposal will be submitted to Google for review.
|
||||||
|
|
||||||
|
## Build guide for pocketpy
|
||||||
|
|
||||||
|
First, you need to install these tools:
|
||||||
|
|
||||||
|
1. Python(>= 3.8), I am sure you already have it.
|
||||||
|
2. A C11 compiler, such as GCC, Clang or MSVC. If you are on Linux, `gcc` is already installed. If you are on Windows, you can install Visual Studio with C/C++ development tools.
|
||||||
|
3. CMake(>= 3.10), a cross-platform build tool. You can use `pip install cmake` to install it.
|
||||||
|
|
||||||
|
Then, clone pocketpy sources from github and try to build:
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/pocketpy/pocketpy
|
||||||
|
cd pocketpy
|
||||||
|
|
||||||
|
python cmake_build.py
|
||||||
|
```
|
||||||
|
|
||||||
|
If everything goes well, you will get a `main` executable (`main.exe` on Windows) in the root directory of pocketpy.
|
||||||
|
Simply run it and you will enter pocketpy's REPL.
|
||||||
|
```txt
|
||||||
|
pocketpy 2.1.7 (Jan 7 2026, 16:42:45) [64 bit] on darwin
|
||||||
|
https://github.com/pocketpy/pocketpy
|
||||||
|
Type "exit()" to exit.
|
||||||
|
>>>
|
||||||
|
>>> "Hello, world"
|
||||||
|
'Hello, world'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Coding style guide
|
||||||
|
|
||||||
|
See [Coding Style Guide](../coding-style-guide.md).
|
||||||
|
|
||||||
2
docs/gsoc2026/index.yml
Normal file
2
docs/gsoc2026/index.yml
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
order: 1
|
||||||
|
label: "GSoC 2026"
|
||||||
@ -2758,6 +2758,8 @@ static Error* compile_stmt(Compiler* self) {
|
|||||||
case TK_WITH: {
|
case TK_WITH: {
|
||||||
check(EXPR(self)); // [ <expr> ]
|
check(EXPR(self)); // [ <expr> ]
|
||||||
Ctx__s_emit_top(ctx());
|
Ctx__s_emit_top(ctx());
|
||||||
|
// Save context manager for later __exit__ call
|
||||||
|
Ctx__emit_(ctx(), OP_DUP_TOP, BC_NOARG, prev()->line);
|
||||||
Ctx__enter_block(ctx(), CodeBlockType_WITH);
|
Ctx__enter_block(ctx(), CodeBlockType_WITH);
|
||||||
NameExpr* as_name = NULL;
|
NameExpr* as_name = NULL;
|
||||||
if(match(TK_AS)) {
|
if(match(TK_AS)) {
|
||||||
@ -2766,17 +2768,33 @@ static Error* compile_stmt(Compiler* self) {
|
|||||||
as_name = NameExpr__new(prev()->line, name, name_scope(self));
|
as_name = NameExpr__new(prev()->line, name, name_scope(self));
|
||||||
}
|
}
|
||||||
Ctx__emit_(ctx(), OP_WITH_ENTER, BC_NOARG, prev()->line);
|
Ctx__emit_(ctx(), OP_WITH_ENTER, BC_NOARG, prev()->line);
|
||||||
// [ <expr> <expr>.__enter__() ]
|
|
||||||
if(as_name) {
|
if(as_name) {
|
||||||
bool ok = vtemit_store((Expr*)as_name, ctx());
|
bool ok = vtemit_store((Expr*)as_name, ctx());
|
||||||
vtdelete((Expr*)as_name);
|
vtdelete((Expr*)as_name);
|
||||||
if(!ok) return SyntaxError(self, "invalid syntax");
|
if(!ok) return SyntaxError(self, "invalid syntax");
|
||||||
} else {
|
} else {
|
||||||
// discard `__enter__()`'s return value
|
|
||||||
Ctx__emit_(ctx(), OP_POP_TOP, BC_NOARG, BC_KEEPLINE);
|
Ctx__emit_(ctx(), OP_POP_TOP, BC_NOARG, BC_KEEPLINE);
|
||||||
}
|
}
|
||||||
|
// Wrap body in try-except to ensure __exit__ is called even on exception
|
||||||
|
Ctx__enter_block(ctx(), CodeBlockType_TRY);
|
||||||
|
Ctx__emit_(ctx(), OP_BEGIN_TRY, BC_NOARG, prev()->line);
|
||||||
check(compile_block_body(self));
|
check(compile_block_body(self));
|
||||||
|
Ctx__emit_(ctx(), OP_END_TRY, BC_NOARG, BC_KEEPLINE);
|
||||||
|
// Normal exit: call __exit__(None, None, None)
|
||||||
|
Ctx__emit_(ctx(), OP_LOAD_NONE, BC_NOARG, prev()->line);
|
||||||
|
Ctx__emit_(ctx(), OP_LOAD_NONE, BC_NOARG, prev()->line);
|
||||||
|
Ctx__emit_(ctx(), OP_LOAD_NONE, BC_NOARG, prev()->line);
|
||||||
Ctx__emit_(ctx(), OP_WITH_EXIT, BC_NOARG, prev()->line);
|
Ctx__emit_(ctx(), OP_WITH_EXIT, BC_NOARG, prev()->line);
|
||||||
|
int jump_patch = Ctx__emit_(ctx(), OP_JUMP_FORWARD, BC_NOARG, BC_KEEPLINE);
|
||||||
|
Ctx__exit_block(ctx());
|
||||||
|
// Exception handler: call __exit__ with exception info, then re-raise
|
||||||
|
Ctx__emit_(ctx(), OP_PUSH_EXCEPTION, BC_NOARG, BC_KEEPLINE);
|
||||||
|
Ctx__emit_(ctx(), OP_LOAD_NONE, BC_NOARG, BC_KEEPLINE); // exc_type
|
||||||
|
Ctx__emit_(ctx(), OP_ROT_TWO, BC_NOARG, BC_KEEPLINE); // reorder: [cm, None, exc]
|
||||||
|
Ctx__emit_(ctx(), OP_LOAD_NONE, BC_NOARG, BC_KEEPLINE); // exc_tb
|
||||||
|
Ctx__emit_(ctx(), OP_WITH_EXIT, BC_NOARG, prev()->line);
|
||||||
|
Ctx__emit_(ctx(), OP_RE_RAISE, BC_NOARG, BC_KEEPLINE);
|
||||||
|
Ctx__patch_jump(ctx(), jump_patch);
|
||||||
Ctx__exit_block(ctx());
|
Ctx__exit_block(ctx());
|
||||||
} break;
|
} break;
|
||||||
/*************************************************/
|
/*************************************************/
|
||||||
|
|||||||
@ -1122,14 +1122,35 @@ __NEXT_STEP:
|
|||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
case OP_WITH_EXIT: {
|
case OP_WITH_EXIT: {
|
||||||
// [expr]
|
// Stack: [cm, exc_type, exc_val, exc_tb]
|
||||||
py_push(TOP());
|
// Call cm.__exit__(exc_type, exc_val, exc_tb)
|
||||||
|
py_Ref exc_tb = TOP();
|
||||||
|
py_Ref exc_val = SECOND();
|
||||||
|
py_Ref exc_type = THIRD();
|
||||||
|
py_Ref cm = FOURTH();
|
||||||
|
|
||||||
|
// Save all values from stack
|
||||||
|
py_TValue saved_cm = *cm;
|
||||||
|
py_TValue saved_exc_type = *exc_type;
|
||||||
|
py_TValue saved_exc_val = *exc_val;
|
||||||
|
py_TValue saved_exc_tb = *exc_tb;
|
||||||
|
self->stack.sp -= 4;
|
||||||
|
|
||||||
|
// Push cm and get __exit__ method
|
||||||
|
py_push(&saved_cm);
|
||||||
if(!py_pushmethod(__exit__)) {
|
if(!py_pushmethod(__exit__)) {
|
||||||
TypeError("'%t' object does not support the context manager protocol", TOP()->type);
|
TypeError("'%t' object does not support the context manager protocol", saved_cm.type);
|
||||||
goto __ERROR;
|
goto __ERROR;
|
||||||
}
|
}
|
||||||
if(!py_vectorcall(0, 0)) goto __ERROR;
|
|
||||||
POP();
|
// Push arguments: exc_type, exc_val, exc_tb
|
||||||
|
PUSH(&saved_exc_type);
|
||||||
|
PUSH(&saved_exc_val);
|
||||||
|
PUSH(&saved_exc_tb);
|
||||||
|
|
||||||
|
// Call __exit__(exc_type, exc_val, exc_tb)
|
||||||
|
if(!py_vectorcall(3, 0)) goto __ERROR;
|
||||||
|
py_pop(); // discard return value
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
///////////
|
///////////
|
||||||
|
|||||||
@ -18,6 +18,15 @@
|
|||||||
return true; \
|
return true; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define ONE_ARG_BOOL_FUNC(name, func) \
|
||||||
|
static bool math_##name(int argc, py_Ref argv) { \
|
||||||
|
PY_CHECK_ARGC(1); \
|
||||||
|
double x; \
|
||||||
|
if(!py_castfloat(py_arg(0), &x)) return false; \
|
||||||
|
py_newbool(py_retval(), func(x)); \
|
||||||
|
return true; \
|
||||||
|
}
|
||||||
|
|
||||||
#define TWO_ARG_FUNC(name, func) \
|
#define TWO_ARG_FUNC(name, func) \
|
||||||
static bool math_##name(int argc, py_Ref argv) { \
|
static bool math_##name(int argc, py_Ref argv) { \
|
||||||
PY_CHECK_ARGC(2); \
|
PY_CHECK_ARGC(2); \
|
||||||
@ -69,9 +78,9 @@ static bool math_gcd(int argc, py_Ref argv) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ONE_ARG_FUNC(isfinite, isfinite)
|
ONE_ARG_BOOL_FUNC(isfinite, isfinite)
|
||||||
ONE_ARG_FUNC(isinf, isinf)
|
ONE_ARG_BOOL_FUNC(isinf, isinf)
|
||||||
ONE_ARG_FUNC(isnan, isnan)
|
ONE_ARG_BOOL_FUNC(isnan, isnan)
|
||||||
|
|
||||||
static bool math_isclose(int argc, py_Ref argv) {
|
static bool math_isclose(int argc, py_Ref argv) {
|
||||||
PY_CHECK_ARGC(2);
|
PY_CHECK_ARGC(2);
|
||||||
@ -206,4 +215,5 @@ void pk__add_module_math() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#undef ONE_ARG_FUNC
|
#undef ONE_ARG_FUNC
|
||||||
#undef TWO_ARG_FUNC
|
#undef ONE_ARG_BOOL_FUNC
|
||||||
|
#undef TWO_ARG_FUNC
|
||||||
|
|||||||
@ -27,4 +27,29 @@ assert path == ['enter', 'in', 'exit']
|
|||||||
|
|
||||||
path.clear()
|
path.clear()
|
||||||
|
|
||||||
|
# Test that __exit__ is called even when an exception occurs
|
||||||
|
class B:
|
||||||
|
def __init__(self):
|
||||||
|
self.path = []
|
||||||
|
|
||||||
|
def __enter__(self):
|
||||||
|
path.append('enter')
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||||
|
path.append('exit')
|
||||||
|
if exc_type is not None:
|
||||||
|
path.append('exception')
|
||||||
|
return False # propagate exception
|
||||||
|
|
||||||
|
try:
|
||||||
|
with B():
|
||||||
|
path.append('before_raise')
|
||||||
|
raise ValueError('test')
|
||||||
|
path.append('after_raise') # should not be reached
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
assert path == ['enter', 'before_raise', 'exit', 'exception'], f"Expected ['enter', 'before_raise', 'exit', 'exception'], got {path}"
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,64 +1,259 @@
|
|||||||
from math import log, log10, log2, sin, cos, tan, e, pi, isnan, isinf, fabs, floor, ceil, sqrt
|
import math
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# Helper function for floating point comparison
|
||||||
|
# ============================================================
|
||||||
|
|
||||||
def isclose(a, b):
|
def isclose(a, b):
|
||||||
return abs(a-b) < 0.000001
|
return abs(a-b) < 0.000001
|
||||||
|
|
||||||
assert isclose(e, 2.718281828459045), e
|
# ============================================================
|
||||||
assert isclose(pi, 3.141592653589793), pi
|
# Constants: pi, e, inf, nan
|
||||||
assert isclose(log(10), 2.302585092994046), log(10)
|
# ============================================================
|
||||||
assert isclose(log10(10), 1.0), log10(10)
|
|
||||||
assert isclose(log2(10), 3.321928094887362), log2(10)
|
|
||||||
assert isclose(sin(0), 0.0), sin(0)
|
|
||||||
assert isclose(cos(0), 1.0), cos(0)
|
|
||||||
assert isclose(tan(0), 0.0), tan(0)
|
|
||||||
|
|
||||||
a = -0.1
|
assert isclose(math.pi, 3.141592653589793)
|
||||||
a = a**a
|
assert isclose(math.e, 2.718281828459045)
|
||||||
assert isnan(a)
|
assert math.isinf(math.inf)
|
||||||
assert not isinf(a)
|
assert math.isnan(math.nan)
|
||||||
assert isinf(float("inf"))
|
|
||||||
|
|
||||||
assert isclose(fabs(-1.2), 1.2)
|
# ============================================================
|
||||||
|
# Rounding functions: ceil, floor, trunc, fabs
|
||||||
|
# ============================================================
|
||||||
|
|
||||||
assert floor(1.2) == 1
|
# ceil - round up to nearest integer
|
||||||
assert floor(-1.2) == -2
|
assert math.ceil(1.2) == 2
|
||||||
assert ceil(1.2) == 2
|
assert math.ceil(-1.2) == -1
|
||||||
assert ceil(-1.2) == -1
|
assert math.ceil(2.0) == 2
|
||||||
|
assert math.ceil(0) == 0
|
||||||
|
|
||||||
assert isclose(sqrt(4), 2.0)
|
# floor - round down to nearest integer
|
||||||
|
assert math.floor(1.2) == 1
|
||||||
|
assert math.floor(-1.2) == -2
|
||||||
|
assert math.floor(2.0) == 2
|
||||||
|
assert math.floor(0) == 0
|
||||||
|
|
||||||
import math
|
# trunc - truncate towards zero
|
||||||
|
assert math.trunc(1.7) == 1
|
||||||
|
assert math.trunc(-1.7) == -1
|
||||||
|
assert math.trunc(2.0) == 2
|
||||||
|
assert math.trunc(0) == 0
|
||||||
|
|
||||||
# test fsum
|
# fabs - absolute value (returns float)
|
||||||
|
assert isclose(math.fabs(-1.2), 1.2)
|
||||||
|
assert isclose(math.fabs(1.2), 1.2)
|
||||||
|
assert isclose(math.fabs(0), 0.0)
|
||||||
|
assert isclose(math.fabs(-0.0), 0.0)
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# Classification functions: isnan, isinf, isfinite, isclose
|
||||||
|
# ============================================================
|
||||||
|
|
||||||
|
# isnan - check if value is NaN
|
||||||
|
assert math.isnan(float('nan'))
|
||||||
|
assert math.isnan(math.nan)
|
||||||
|
assert not math.isnan(1.0)
|
||||||
|
assert not math.isnan(math.inf)
|
||||||
|
|
||||||
|
# isinf - check if value is infinity
|
||||||
|
assert math.isinf(float('inf'))
|
||||||
|
assert math.isinf(float('-inf'))
|
||||||
|
assert math.isinf(math.inf)
|
||||||
|
assert not math.isinf(1.0)
|
||||||
|
assert not math.isinf(math.nan)
|
||||||
|
|
||||||
|
# isfinite - check if value is finite (not inf or nan)
|
||||||
|
assert math.isfinite(1.0)
|
||||||
|
assert math.isfinite(0.0)
|
||||||
|
assert math.isfinite(-1.0)
|
||||||
|
assert not math.isfinite(math.inf)
|
||||||
|
assert not math.isfinite(-math.inf)
|
||||||
|
assert not math.isfinite(math.nan)
|
||||||
|
|
||||||
|
# isclose - check if two values are close
|
||||||
|
assert math.isclose(1.0, 1.0)
|
||||||
|
assert math.isclose(1.0, 1.0 + 1e-10)
|
||||||
|
assert not math.isclose(1.0, 1.1)
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# Power and logarithmic functions: exp, log, log2, log10, pow, sqrt
|
||||||
|
# ============================================================
|
||||||
|
|
||||||
|
# exp - e raised to the power x
|
||||||
|
assert isclose(math.exp(0), 1.0)
|
||||||
|
assert isclose(math.exp(1), math.e)
|
||||||
|
assert isclose(math.exp(2), math.e * math.e)
|
||||||
|
|
||||||
|
# log - natural logarithm (base e) or logarithm with custom base
|
||||||
|
assert isclose(math.log(1), 0.0)
|
||||||
|
assert isclose(math.log(math.e), 1.0)
|
||||||
|
assert isclose(math.log(10), 2.302585092994046)
|
||||||
|
assert isclose(math.log(100, 10), 2.0) # log base 10
|
||||||
|
assert isclose(math.log(8, 2), 3.0) # log base 2
|
||||||
|
|
||||||
|
# log2 - logarithm base 2
|
||||||
|
assert isclose(math.log2(1), 0.0)
|
||||||
|
assert isclose(math.log2(2), 1.0)
|
||||||
|
assert isclose(math.log2(8), 3.0)
|
||||||
|
assert isclose(math.log2(10), 3.321928094887362)
|
||||||
|
|
||||||
|
# log10 - logarithm base 10
|
||||||
|
assert isclose(math.log10(1), 0.0)
|
||||||
|
assert isclose(math.log10(10), 1.0)
|
||||||
|
assert isclose(math.log10(100), 2.0)
|
||||||
|
assert isclose(math.log10(1000), 3.0)
|
||||||
|
|
||||||
|
# pow - x raised to the power y
|
||||||
|
assert isclose(math.pow(2, 3), 8.0)
|
||||||
|
assert isclose(math.pow(2, 0), 1.0)
|
||||||
|
assert isclose(math.pow(2, -1), 0.5)
|
||||||
|
assert isclose(math.pow(4, 0.5), 2.0)
|
||||||
|
assert isclose(math.pow(0, 0), 1.0)
|
||||||
|
|
||||||
|
# sqrt - square root
|
||||||
|
assert isclose(math.sqrt(4), 2.0)
|
||||||
|
assert isclose(math.sqrt(2), 1.4142135623730951)
|
||||||
|
assert isclose(math.sqrt(0), 0.0)
|
||||||
|
assert isclose(math.sqrt(1), 1.0)
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# Trigonometric functions: sin, cos, tan, asin, acos, atan, atan2
|
||||||
|
# ============================================================
|
||||||
|
|
||||||
|
# sin - sine
|
||||||
|
assert isclose(math.sin(0), 0.0)
|
||||||
|
assert isclose(math.sin(math.pi / 2), 1.0)
|
||||||
|
assert isclose(math.sin(math.pi), 0.0)
|
||||||
|
assert isclose(math.sin(-math.pi / 2), -1.0)
|
||||||
|
|
||||||
|
# cos - cosine
|
||||||
|
assert isclose(math.cos(0), 1.0)
|
||||||
|
assert isclose(math.cos(math.pi / 2), 0.0)
|
||||||
|
assert isclose(math.cos(math.pi), -1.0)
|
||||||
|
assert isclose(math.cos(-math.pi), -1.0)
|
||||||
|
|
||||||
|
# tan - tangent
|
||||||
|
assert isclose(math.tan(0), 0.0)
|
||||||
|
assert isclose(math.tan(math.pi / 4), 1.0)
|
||||||
|
assert isclose(math.tan(-math.pi / 4), -1.0)
|
||||||
|
|
||||||
|
# asin - arc sine (inverse sine)
|
||||||
|
assert isclose(math.asin(0), 0.0)
|
||||||
|
assert isclose(math.asin(1), math.pi / 2)
|
||||||
|
assert isclose(math.asin(-1), -math.pi / 2)
|
||||||
|
assert isclose(math.asin(0.5), math.pi / 6)
|
||||||
|
|
||||||
|
# acos - arc cosine (inverse cosine)
|
||||||
|
assert isclose(math.acos(1), 0.0)
|
||||||
|
assert isclose(math.acos(0), math.pi / 2)
|
||||||
|
assert isclose(math.acos(-1), math.pi)
|
||||||
|
assert isclose(math.acos(0.5), math.pi / 3)
|
||||||
|
|
||||||
|
# atan - arc tangent (inverse tangent)
|
||||||
|
assert isclose(math.atan(0), 0.0)
|
||||||
|
assert isclose(math.atan(1), math.pi / 4)
|
||||||
|
assert isclose(math.atan(-1), -math.pi / 4)
|
||||||
|
|
||||||
|
# atan2 - arc tangent of y/x (handles quadrants correctly)
|
||||||
|
assert isclose(math.atan2(0, 1), 0.0)
|
||||||
|
assert isclose(math.atan2(1, 0), math.pi / 2)
|
||||||
|
assert isclose(math.atan2(0, -1), math.pi)
|
||||||
|
assert isclose(math.atan2(-1, 0), -math.pi / 2)
|
||||||
|
assert isclose(math.atan2(1, 1), math.pi / 4)
|
||||||
|
assert isclose(math.atan2(-1, -1), -3 * math.pi / 4)
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# Angle conversion functions: degrees, radians
|
||||||
|
# ============================================================
|
||||||
|
|
||||||
|
# degrees - convert radians to degrees
|
||||||
|
assert isclose(math.degrees(0), 0.0)
|
||||||
|
assert isclose(math.degrees(math.pi), 180.0)
|
||||||
|
assert isclose(math.degrees(math.pi / 2), 90.0)
|
||||||
|
assert isclose(math.degrees(2 * math.pi), 360.0)
|
||||||
|
|
||||||
|
# radians - convert degrees to radians
|
||||||
|
assert isclose(math.radians(0), 0.0)
|
||||||
|
assert isclose(math.radians(180), math.pi)
|
||||||
|
assert isclose(math.radians(90), math.pi / 2)
|
||||||
|
assert isclose(math.radians(360), 2 * math.pi)
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# Arithmetic functions: fmod, modf, copysign, fsum, gcd, factorial
|
||||||
|
# ============================================================
|
||||||
|
|
||||||
|
# fmod - floating point modulo
|
||||||
|
assert isclose(math.fmod(5.0, 3.0), 2.0)
|
||||||
|
assert isclose(math.fmod(-5.0, 3.0), -2.0)
|
||||||
|
assert isclose(math.fmod(5.0, -3.0), 2.0)
|
||||||
|
assert isclose(math.fmod(-5.0, -3.0), -2.0)
|
||||||
|
assert isclose(math.fmod(4.0, 3.0), 1.0)
|
||||||
|
assert isclose(math.fmod(-4.0, 3.0), -1.0)
|
||||||
|
assert isclose(math.fmod(-2.0, 3.0), -2.0)
|
||||||
|
assert isclose(math.fmod(2.0, 3.0), 2.0)
|
||||||
|
|
||||||
|
# modf - split into fractional and integer parts
|
||||||
|
frac, integer = math.modf(1.5)
|
||||||
|
assert isclose(frac, 0.5)
|
||||||
|
assert isclose(integer, 1.0)
|
||||||
|
|
||||||
|
frac, integer = math.modf(-1.5)
|
||||||
|
assert isclose(frac, -0.5)
|
||||||
|
assert isclose(integer, -1.0)
|
||||||
|
|
||||||
|
frac, integer = math.modf(2.0)
|
||||||
|
assert isclose(frac, 0.0)
|
||||||
|
assert isclose(integer, 2.0)
|
||||||
|
|
||||||
|
frac, integer = math.modf(0.0)
|
||||||
|
assert isclose(frac, 0.0)
|
||||||
|
assert isclose(integer, 0.0)
|
||||||
|
|
||||||
|
# copysign - return x with the sign of y
|
||||||
|
assert isclose(math.copysign(1.0, -1.0), -1.0)
|
||||||
|
assert isclose(math.copysign(-1.0, 1.0), 1.0)
|
||||||
|
assert isclose(math.copysign(1.0, 1.0), 1.0)
|
||||||
|
assert isclose(math.copysign(-1.0, -1.0), -1.0)
|
||||||
|
assert isclose(math.copysign(5.0, -0.0), -5.0)
|
||||||
|
assert isclose(math.copysign(0.0, -1.0), 0.0) # sign of zero may vary
|
||||||
|
|
||||||
|
# fsum - accurate floating point sum
|
||||||
assert math.fsum([0.1] * 10) == 1.0
|
assert math.fsum([0.1] * 10) == 1.0
|
||||||
|
assert math.fsum([]) == 0.0
|
||||||
|
assert math.fsum([1.0, 2.0, 3.0]) == 6.0
|
||||||
|
assert math.fsum([0.1, 0.2, 0.3]) == 0.6
|
||||||
|
|
||||||
# test gcd
|
# gcd - greatest common divisor
|
||||||
assert math.gcd(10, 5) == 5
|
assert math.gcd(10, 5) == 5
|
||||||
assert math.gcd(10, 6) == 2
|
assert math.gcd(10, 6) == 2
|
||||||
assert math.gcd(10, 7) == 1
|
assert math.gcd(10, 7) == 1
|
||||||
assert math.gcd(10, 10) == 10
|
assert math.gcd(10, 10) == 10
|
||||||
assert math.gcd(-10, 10) == 10
|
assert math.gcd(-10, 10) == 10
|
||||||
|
assert math.gcd(10, -10) == 10
|
||||||
|
assert math.gcd(-10, -10) == 10
|
||||||
|
assert math.gcd(0, 5) == 5
|
||||||
|
assert math.gcd(5, 0) == 5
|
||||||
|
assert math.gcd(0, 0) == 0
|
||||||
|
|
||||||
# test fmod
|
# factorial - n!
|
||||||
assert math.fmod(-2.0, 3.0) == -2.0
|
|
||||||
assert math.fmod(2.0, 3.0) == 2.0
|
|
||||||
assert math.fmod(4.0, 3.0) == 1.0
|
|
||||||
assert math.fmod(-4.0, 3.0) == -1.0
|
|
||||||
|
|
||||||
# test modf
|
|
||||||
x, y = math.modf(1.5)
|
|
||||||
assert isclose(x, 0.5)
|
|
||||||
assert isclose(y, 1.0)
|
|
||||||
|
|
||||||
x, y = math.modf(-1.5)
|
|
||||||
assert isclose(x, -0.5)
|
|
||||||
assert isclose(y, -1.0)
|
|
||||||
|
|
||||||
# test factorial
|
|
||||||
assert math.factorial(0) == 1
|
assert math.factorial(0) == 1
|
||||||
assert math.factorial(1) == 1
|
assert math.factorial(1) == 1
|
||||||
assert math.factorial(2) == 2
|
assert math.factorial(2) == 2
|
||||||
assert math.factorial(3) == 6
|
assert math.factorial(3) == 6
|
||||||
assert math.factorial(4) == 24
|
assert math.factorial(4) == 24
|
||||||
assert math.factorial(5) == 120
|
assert math.factorial(5) == 120
|
||||||
|
assert math.factorial(10) == 3628800
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# Special value tests
|
||||||
|
# ============================================================
|
||||||
|
|
||||||
|
# Test NaN generation from invalid operations
|
||||||
|
a = -0.1
|
||||||
|
a = a ** a
|
||||||
|
assert math.isnan(a)
|
||||||
|
assert not math.isinf(a)
|
||||||
|
|
||||||
|
# Test infinity
|
||||||
|
assert math.isinf(float("inf"))
|
||||||
|
assert math.isinf(float("-inf"))
|
||||||
|
assert not math.isnan(float("inf"))
|
||||||
@ -41,15 +41,15 @@ assertEqual(math.gcd(10, 10), 10)
|
|||||||
assertEqual(math.gcd(-10, 10), 10)
|
assertEqual(math.gcd(-10, 10), 10)
|
||||||
|
|
||||||
# test isfinite, isinf, isnan
|
# test isfinite, isinf, isnan
|
||||||
assertEqual(math.isfinite(math.pi), 1)
|
assertEqual(math.isfinite(math.pi), True)
|
||||||
assertEqual(math.isfinite(math.inf), 0)
|
assertEqual(math.isfinite(math.inf), False)
|
||||||
assertEqual(math.isfinite(math.nan), 0)
|
assertEqual(math.isfinite(math.nan), False)
|
||||||
assertEqual(math.isinf(math.pi), 0)
|
assertEqual(math.isinf(math.pi), False)
|
||||||
assertEqual(math.isinf(math.inf), 1)
|
assertEqual(math.isinf(math.inf), True)
|
||||||
assertEqual(math.isinf(math.nan), 0)
|
assertEqual(math.isinf(math.nan), False)
|
||||||
assertEqual(math.isnan(math.pi), 0)
|
assertEqual(math.isnan(math.pi), False)
|
||||||
assertEqual(math.isnan(math.inf), 0)
|
assertEqual(math.isnan(math.inf), False)
|
||||||
assertEqual(math.isnan(math.nan), 1)
|
assertEqual(math.isnan(math.nan), True)
|
||||||
|
|
||||||
# test exp
|
# test exp
|
||||||
assertEqual(math.exp(0), 1.0)
|
assertEqual(math.exp(0), 1.0)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user