6
6
.. currentmodule:: arraycontext
7
7
8
8
.. autofunction:: with_container_arithmetic
9
+
10
+ .. autoclass:: BcastUntilActxArray
9
11
"""
10
12
11
13
34
36
"""
35
37
36
38
import enum
39
+ import operator
37
40
from collections .abc import Callable
41
+ from dataclasses import dataclass
42
+ from functools import partialmethod
38
43
from typing import Any , TypeVar
39
44
from warnings import warn
40
45
41
46
import numpy as np
42
47
48
+ from arraycontext .container import (
49
+ NotAnArrayContainerError ,
50
+ deserialize_container ,
51
+ serialize_container ,
52
+ )
53
+ from arraycontext .context import ArrayContext , ArrayOrArithContainer
54
+
43
55
44
56
# {{{ with_container_arithmetic
45
57
@@ -402,8 +414,9 @@ def wrap(cls: Any) -> Any:
402
414
warn (
403
415
f"Broadcasting array context array types across { cls } "
404
416
"has been explicitly "
405
- "enabled. As of 2025, this will stop working. "
406
- "There is no replacement as of right now. "
417
+ "enabled. As of 2026, this will stop working. "
418
+ "Use the arraycontext.Bcast* object wrappers for "
419
+ "roughly equivalent functionality. "
407
420
"See the discussion in "
408
421
"https://github.com/inducer/arraycontext/pull/190. "
409
422
"To opt out now (and avoid this warning), "
@@ -413,8 +426,9 @@ def wrap(cls: Any) -> Any:
413
426
warn (
414
427
f"Broadcasting array context array types across { cls } "
415
428
"has been implicitly "
416
- "enabled. As of 2025, this will no longer work. "
417
- "There is no replacement as of right now. "
429
+ "enabled. As of 2026, this will no longer work. "
430
+ "Use the arraycontext.Bcast* object wrappers for "
431
+ "roughly equivalent functionality. "
418
432
"See the discussion in "
419
433
"https://github.com/inducer/arraycontext/pull/190. "
420
434
"To opt out now (and avoid this warning), "
@@ -603,8 +617,9 @@ def {fname}(arg1):
603
617
if isinstance(arg2, { tup_str (bcast_actx_ary_types )} ):
604
618
warn("Broadcasting { cls } over array "
605
619
f"context array type {{type(arg2)}} is deprecated "
606
- "and will no longer work in 2025. "
607
- "There is no replacement as of right now. "
620
+ "and will no longer work in 2026. "
621
+ "Use the arraycontext.Bcast* object wrappers for "
622
+ "roughly equivalent functionality. "
608
623
"See the discussion in "
609
624
"https://github.com/inducer/arraycontext/"
610
625
"pull/190. ",
@@ -654,8 +669,10 @@ def {fname}(arg2, arg1):
654
669
warn("Broadcasting { cls } over array "
655
670
f"context array type {{type(arg1)}} "
656
671
"is deprecated "
657
- "and will no longer work in 2025."
658
- "There is no replacement as of right now. "
672
+ "and will no longer work in 2026."
673
+ "Use the arraycontext.Bcast* object "
674
+ "rappers for roughly equivalent "
675
+ "functionality. "
659
676
"See the discussion in "
660
677
"https://github.com/inducer/arraycontext/"
661
678
"pull/190. ",
@@ -687,4 +704,71 @@ def {fname}(arg2, arg1):
687
704
# }}}
688
705
689
706
707
+ @dataclass (frozen = True )
708
+ class BcastUntilActxArray :
709
+ array_context : ArrayContext
710
+ broadcastee : ArrayOrArithContainer
711
+
712
+ def _binary_op (self ,
713
+ op : Callable [
714
+ [ArrayOrArithContainer , ArrayOrArithContainer ],
715
+ ArrayOrArithContainer
716
+ ],
717
+ right : ArrayOrArithContainer
718
+ ) -> ArrayOrArithContainer :
719
+ try :
720
+ serialized = serialize_container (right )
721
+ except NotAnArrayContainerError :
722
+ return op (self .broadcastee , right )
723
+
724
+ return deserialize_container (right , [
725
+ (k , op (self .broadcastee , right_v )
726
+ if isinstance (right_v , self .array_context .array_types ) else
727
+ self ._binary_op (op , right_v )
728
+ )
729
+ for k , right_v in serialized ])
730
+
731
+ def _rev_binary_op (self ,
732
+ op : Callable [
733
+ [ArrayOrArithContainer , ArrayOrArithContainer ],
734
+ ArrayOrArithContainer
735
+ ],
736
+ left : ArrayOrArithContainer
737
+ ) -> ArrayOrArithContainer :
738
+ try :
739
+ serialized = serialize_container (left )
740
+ except NotAnArrayContainerError :
741
+ return op (left , self .broadcastee )
742
+
743
+ return deserialize_container (left , [
744
+ (k , op (left_v , self .broadcastee )
745
+ if isinstance (left_v , self .array_context .array_types ) else
746
+ self ._rev_binary_op (op , left_v )
747
+ )
748
+ for k , left_v in serialized ])
749
+
750
+ __add__ = partialmethod (_binary_op , operator .add )
751
+ __radd__ = partialmethod (_rev_binary_op , operator .add )
752
+ __sub__ = partialmethod (_binary_op , operator .sub )
753
+ __rsub__ = partialmethod (_rev_binary_op , operator .sub )
754
+ __mul__ = partialmethod (_binary_op , operator .mul )
755
+ __rmul__ = partialmethod (_rev_binary_op , operator .mul )
756
+ __truediv__ = partialmethod (_binary_op , operator .truediv )
757
+ __rtruediv__ = partialmethod (_rev_binary_op , operator .truediv )
758
+ __floordiv__ = partialmethod (_binary_op , operator .floordiv )
759
+ __rfloordiv__ = partialmethod (_rev_binary_op , operator .floordiv )
760
+ __mod__ = partialmethod (_binary_op , operator .mod )
761
+ __rmod__ = partialmethod (_rev_binary_op , operator .mod )
762
+ __pow__ = partialmethod (_binary_op , operator .pow )
763
+ __rpow__ = partialmethod (_rev_binary_op , operator .pow )
764
+
765
+ __lshift__ = partialmethod (_binary_op , operator .lshift )
766
+ __rlshift__ = partialmethod (_rev_binary_op , operator .lshift )
767
+ __rshift__ = partialmethod (_binary_op , operator .rshift )
768
+ __rrshift__ = partialmethod (_rev_binary_op , operator .rshift )
769
+ __and__ = partialmethod (_binary_op , operator .and_ )
770
+ __rand__ = partialmethod (_rev_binary_op , operator .and_ )
771
+ __or__ = partialmethod (_binary_op , operator .or_ )
772
+ __ror__ = partialmethod (_rev_binary_op , operator .or_ )
773
+
690
774
# vim: foldmethod=marker
0 commit comments