src/autograd/broadcast.bend
bendtorch-core@0.1.0.0 · 75 lines · 9 definitions
1import Base
2import bendtorch-core@0.1.0.0/src/shape/core.bend as Shape
3import bendtorch-core@0.1.0.0/src/tensor/core.bend as Core
4import bendtorch-core@0.1.0.0/src/tensor/elementwise.bend as Elementwise
5import bendtorch-core@0.1.0.0/src/tensor/layout.bend as Layout
6
7
8
9
10
11
12
13type Error is Data:
14 TensorError{error: Core.Error}
15 NotBroadcastable{}
16
17def finish(pair: (Core.Dynamic & Core.Dynamic) & Result<&2, &1, Core.Error, Core.Dynamic>) ->
18 Core.Dynamic & Result<&2, &1, Error, Core.Dynamic>:
19 ((input, zeros), result) = pair
20 match result:
21 case Fail{error}:
22 (input, Fail{TensorError{error}})
23 case Done{output}:
24 (input, Done{output})
25
26def zeroed(input: Core.Dynamic, +target: Shape.Shape, +plan: Shape.BroadcastPlan,
27 result: Result<&2, &1, Core.Error, Core.Tensor<target>>) -> Core.Dynamic & Result<&2, &1, Error, Core.Dynamic>:
28 match result:
29 case Fail{error}:
30 (input, Fail{TensorError{error}})
31 case Done{zeros}:
32 finish(Elementwise.parallel_allocated(Elementwise.KeepLeft{}, plan, input, Core.Packed{target, zeros},
33 Core.new(Shape.output_shape(plan), 0.0)))
34
35def fitted(input: Core.Dynamic, +target: Shape.Shape, +plan: Shape.BroadcastPlan, same: Bool) ->
36 Core.Dynamic & Result<&2, &1, Error, Core.Dynamic>:
37 match same:
38 case False{}:
39 (input, Fail{NotBroadcastable{}})
40 case True{}:
41 zeroed(input, target, plan, Core.new(target, 0.0))
42
43def planned(input: Core.Dynamic, +target: Shape.Shape, result: Result<&2, &2, Shape.Error, Shape.BroadcastPlan>) ->
44 Core.Dynamic & Result<&2, &1, Error, Core.Dynamic>:
45 match result:
46 case Fail{error}:
47 (input, Fail{TensorError{Core.ShapeError{error}}})
48 case Done{+plan}:
49 fitted(input, target, plan, Layout.words_same(Shape.dimensions(Shape.output_shape(plan)), Shape.dimensions(target)))
50
51
52
53
54
55def broadcast_to(input: Core.Dynamic, +target: Shape.Shape) -> Core.Dynamic & Result<&2, &1, Error, Core.Dynamic>:
56 Core.Packed{+shape, tensor} = input
57 planned(Core.Packed{shape, tensor}, target, Shape.broadcast_checked(shape, target))
58
59def broadcast_to_dimensions_result(input: Core.Dynamic, -dimensions: List<&2, U32>, result: Shape.ConstructResult<dimensions>) ->
60 Core.Dynamic & Result<&2, &1, Error, Core.Dynamic>:
61 match result:
62 case Shape.SError{error}:
63 (input, Fail{TensorError{Core.ShapeError{error}}})
64 case Shape.SBuilt{+target, preserved}:
65 broadcast_to(input, target)
66
67def broadcast_to_dimensions(input: Core.Dynamic, +dimensions: List<&2, U32>) -> Core.Dynamic & Result<&2, &1, Error, Core.Dynamic>:
68 broadcast_to_dimensions_result(input, dimensions, Shape.construct(dimensions))
69
70def error_code(error: Error) -> U32:
71 match error:
72 case TensorError{error}:
73 Core.error_code(error)
74 case NotBroadcastable{}:
75 100