From 2287a181dabee1e0c449f8ab3c69025353646011 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Thu, 1 Jan 2026 14:57:47 +0100 Subject: [PATCH] neg() und abs() stencil added in copapy --- src/copapy/_autograd.py | 7 +++++-- src/copapy/_basic_types.py | 10 ++++------ tests/test_autograd.py | 23 ++++++++++++++++++++++- 3 files changed, 31 insertions(+), 9 deletions(-) diff --git a/src/copapy/_autograd.py b/src/copapy/_autograd.py index 3abd97e..4840805 100644 --- a/src/copapy/_autograd.py +++ b/src/copapy/_autograd.py @@ -89,8 +89,11 @@ def grad(x: Any, y: value[Any] | Sequence[value[Any]] | vector[Any] | tensor[Any elif opn == 'sqrt': add_grad(a, g * (0.5 / cp.sqrt(a))) - #elif opn == 'abs': - # add_grad(x, g * cp.sign(x)) + elif opn == 'abs': + add_grad(a, g * cp.sign(a)) + + elif opn == 'neg': + add_grad(a, -b) elif opn == 'sin': add_grad(a, g * cp.cos(a)) diff --git a/src/copapy/_basic_types.py b/src/copapy/_basic_types.py index e71077a..6a9ba6d 100644 --- a/src/copapy/_basic_types.py +++ b/src/copapy/_basic_types.py @@ -230,13 +230,11 @@ class value(Generic[TNum]): def __rfloordiv__(self, other: NumLike) -> Any: return add_op('floordiv', [other, self]) - def __abs__(self: TCPNum) -> TCPNum: - return cp.abs(self) # type: ignore + def __abs__(self: 'value[TNum]') -> 'value[TNum]': + return cp.abs(self) - def __neg__(self: TCPNum) -> TCPNum: - if self.dtype == 'float': - return cast(TCPNum, add_op('sub', [value(0.0), self])) - return cast(TCPNum, add_op('sub', [value(0), self])) + def __neg__(self: 'value[TNum]') -> 'value[TNum]': + return add_op('neg', [self]) def __gt__(self, other: TVarNumb) -> 'value[int]': return add_op('gt', [self, other], dtype='bool') diff --git a/tests/test_autograd.py b/tests/test_autograd.py index f8b113d..fb79f55 100644 --- a/tests/test_autograd.py +++ b/tests/test_autograd.py @@ -13,7 +13,7 @@ def test_autograd(): c += c + 1 c += 1 + c + (-a) d += d * 2 + cp.relu(b + a) - d += 3 * d + cp.relu(b - a) + d += 3 * d + cp.relu(-a + b) e = c - d f = e**2 g = f / 2.0 @@ -34,5 +34,26 @@ def test_autograd(): assert pytest.approx(dg[1], abs=1e-4) == 645.57725 # pyright: ignore[reportUnknownMemberType] +def test_autograd_extended(): + a = value(-4.0) + b = value(2.0) + c = a + b + d = a * b + b**3 + c += c + 1 + c += 1 + c + (-a) + d += d * 2 + cp.relu(b + a) + d += 3 * d + cp.relu(b - a) + e = c - cp.sin(-d) + f = cp.abs(e**2) + g = f / 2.0 + g += 10.0 / f + + dg = grad(g, (a, b)) + + tg = cp.Target() + tg.compile(g, dg) + tg.run() + + if __name__ == "__main__": test_autograd()