src/autograd/broadcast_pointwise_LAWS.bend
bendtorch-core@0.1.0.0 · 112 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/storage/LAWS.bend as StorageLaws
4import bendtorch-core@0.1.0.0/src/tensor/core.bend as Core
5import bendtorch-core@0.1.0.0/src/tensor/lifecycle.bend as Lifecycle
6import bendtorch-core@0.1.0.0/src/tensor/contracts/LAWS.bend as Contracts
7import bendtorch-core@0.1.0.0/src/tensor/contracts/replayed.bend as Replayed
8import bendtorch-core@0.1.0.0/src/tensor/contracts/broadcast.bend as PointwiseBroadcast
9import bendtorch-core@0.1.0.0/src/autograd/broadcast.bend as Broadcast
10
11def succeeded(result: Core.Dynamic & Result<&2, &1, Broadcast.Error, Core.Dynamic>) -> Bool:
12 (input, outcome) = result
13 Result.is_done(&2, &1, Broadcast.Error, Core.Dynamic, outcome)
14
15def output_dimensions(result: Core.Dynamic & Result<&2, &1, Broadcast.Error, Core.Dynamic>) -> Maybe<&2, List<&2, U32>>:
16 (input, outcome) = result
17 match outcome:
18 case Fail{error}:
19 None{}
20 case Done{Core.Packed{shape, tensor}}:
21 Some{Shape.dimensions(shape)}
22
23def output_point(result: Core.Dynamic & Result<&2, &1, Broadcast.Error, Core.Dynamic>, +index: U32) -> Maybe<&2, F32>:
24 (input, outcome) = result
25 match outcome:
26 case Fail{error}:
27 None{}
28 case Done{output}:
29 Core.dynamic_read_value(Core.read_dynamic(output, index))
30
31def input_point(result: Core.Dynamic & Result<&2, &1, Broadcast.Error, Core.Dynamic>, +index: U32) -> Maybe<&2, F32>:
32 (input, outcome) = result
33 Core.dynamic_read_value(Core.read_dynamic(input, index))
34
35
36
37
38type BroadcastToContract<-target: Shape.Shape, -input: Shape.Shape, -cell: Nat -> F32, -word: U32 -> F32,
39 -result: Core.Dynamic & Result<&2, &1, Broadcast.Error, Core.Dynamic>> is Type:
40 BroadcastToContract{
41 successful: {succeeded(result) == True{} : Bool},
42 dimensions: {output_dimensions(result) == Some{Shape.dimensions(target)} : Maybe<&2, List<&2, U32>>},
43 value: @+index: U32 -> @inside: {Nat.is_lt(U32.to_nat(index), Shape.logical_numel(Shape.dimensions(target))) == True{} : Bool} ->
44 {output_point(result, index) == Some{cell(U32.to_nat(index))} : Maybe<&2, F32>},
45 kept: @+other: U32 -> @inside: {Nat.is_lt(U32.to_nat(other), Shape.logical_numel(Shape.dimensions(input))) == True{} : Bool} ->
46 {input_point(result, other) == Some{word(other)} : Maybe<&2, F32>}}
47
48
49
50def cells(+plan: Shape.BroadcastPlan, +shape: Shape.Shape, +fill: F32, +ops: List<&2, StorageLaws.Op>, +count: Nat) -> List<&2, F32>:
51 match count:
52 case 0n:
53 Nil{}
54 case 1n+previous:
55 List.append(&2, F32, cells(plan, shape, fill, ops, previous),
56 [Replayed.value(shape, fill, ops, U32.from_nat(PointwiseBroadcast.left_map(plan, previous)))])
57
58
59
60
61
62def BroadcastWith(+plan: Shape.BroadcastPlan, +shape: Shape.Shape, +fill: F32, +ops: List<&2, StorageLaws.Op>,
63 -P: Core.Dynamic & Result<&2, &1, Broadcast.Error, Core.Dynamic> -> Type) -> Type:
64 @+kept: List<&2, StorageLaws.Op> ->
65 @kept_words: {Contracts.words(shape, fill, kept, Shape.logical_numel(Shape.dimensions(shape))) ==
66 Contracts.words(shape, fill, ops, Shape.logical_numel(Shape.dimensions(shape))) : List<&2, F32>} ->
67 @-input_fits: {Lifecycle.logical_length(Replayed.storage(shape, fill, kept)) == Shape.logical_numel(Shape.dimensions(shape)) : Nat} ->
68 @+output_ops: List<&2, StorageLaws.Op> ->
69 @values: {Contracts.words(Shape.output_shape(plan), 0.0, output_ops, Shape.logical_numel(Shape.dimensions(Shape.output_shape(plan)))) ==
70 cells(plan, shape, fill, ops, Shape.logical_numel(Shape.dimensions(Shape.output_shape(plan)))) : List<&2, F32>} ->
71 @-output_fits: {Lifecycle.logical_length(Replayed.storage(Shape.output_shape(plan), 0.0, output_ops)) ==
72 Shape.logical_numel(Shape.dimensions(Shape.output_shape(plan))) : Nat} ->
73 P((Core.Packed{shape, Core.TTensor{Replayed.storage(shape, fill, kept), input_fits}},
74 Done{Core.Packed{Shape.output_shape(plan), Core.TTensor{Replayed.storage(Shape.output_shape(plan), 0.0, output_ops), output_fits}}}))
75
76
77
78
79
80law broadcast_to_pointwise:
81 for +shape: Shape.Shape
82 for +target: Shape.Shape
83 for +plan: Shape.BroadcastPlan
84 for planned: {Shape.broadcast_checked(shape, target) == Done{plan} : Result<&2, &2, Shape.Error, Shape.BroadcastPlan>}
85 for same: {Shape.dimensions(Shape.output_shape(plan)) == Shape.dimensions(target) : List<&2, U32>}
86 for +fill: F32
87 for +ops: List<&2, StorageLaws.Op>
88 for -fits: {Lifecycle.logical_length(Replayed.storage(shape, fill, ops)) == Shape.logical_numel(Shape.dimensions(shape)) : Nat}
89 BroadcastToContract<target, shape,
90 index => Replayed.value(shape, fill, ops, U32.from_nat(PointwiseBroadcast.left_map(plan, index))),
91 other => Replayed.value(shape, fill, ops, other),
92 Broadcast.broadcast_to(Core.Packed{shape, Core.TTensor{Replayed.storage(shape, fill, ops), fits}}, target)>
93
94
95
96
97
98
99
100
101law broadcast_to_replayed:
102 for +shape: Shape.Shape
103 for +target: Shape.Shape
104 for +plan: Shape.BroadcastPlan
105 for planned: {Shape.broadcast_checked(shape, target) == Done{plan} : Result<&2, &2, Shape.Error, Shape.BroadcastPlan>}
106 for same: {Shape.dimensions(Shape.output_shape(plan)) == Shape.dimensions(target) : List<&2, U32>}
107 for +fill: F32
108 for +ops: List<&2, StorageLaws.Op>
109 for -fits: {Lifecycle.logical_length(Replayed.storage(shape, fill, ops)) == Shape.logical_numel(Shape.dimensions(shape)) : Nat}
110 for -P: Core.Dynamic & Result<&2, &1, Broadcast.Error, Core.Dynamic> -> Type
111 for h: BroadcastWith(plan, shape, fill, ops, P)
112 P(Broadcast.broadcast_to(Core.Packed{shape, Core.TTensor{Replayed.storage(shape, fill, ops), fits}}, target))