tensor_window.bend
stelliferous@0.0.2.0 · 120 lines · 16 definitions
1
2
3
4
5
6import Base
7import stelliferous@0.0.2.0/storage_buffer.bend as Storage
8import stelliferous@0.0.2.0/tensor_shape.bend as Shapes
9import stelliferous@0.0.2.0/tensor_access.bend as Access
10import stelliferous@0.0.2.0/tensor_operations.bend as Operations
11import stelliferous@0.0.2.0/tensor.bend as Tensors
12import stelliferous@0.0.2.0/tensor_layout.bend as Layout
13import stelliferous@0.0.2.0/tensor_band.bend as Bands
14import stelliferous@0.0.2.0/tensor_band_window.bend as BandWindow
15import stelliferous@0.0.2.0/tensor_band_pool.bend as BandPool
16
17def out_extent(+extent: U32,+kernel: U32,+stride: U32,+padding: U32) -> U32:
18 ((extent + 2 * padding - kernel : U32) / U32.max(stride,1) + 1 : U32)
19
20def geometry(+shape: List<&2,U32>,+kernel: U32,+stride: U32,+padding: U32) -> Access.Pool:
21 +rank = List.length(&2,U32,shape)
22 +height = Layout.extent_at(shape,Nat.sub(rank,2n))
23 +width = Layout.extent_at(shape,Nat.sub(rank,1n))
24 Access.Pool{height,width,kernel,stride,padding,out_extent(height,kernel,stride,padding),out_extent(width,kernel,stride,padding)}
25
26def leading(ranked: Bool,+shape: List<&2,U32>) -> Maybe<&2,U32>:
27 match ranked:
28 case True{}: Shapes.product(List.take(&2,U32,shape,Nat.sub(List.length(&2,U32,shape),2n)),Some{1})
29 case False{}: None{}
30
31
32def planes(+shape: List<&2,U32>) -> Maybe<&2,U32>:
33 leading(Nat.is_le(2n,List.length(&2,U32,shape)),shape)
34
35def pooled(~Element: Data,name: String,+shape: List<&2,U32>,+out_shape: List<&2,U32>,fill: Element,+workers: U32,
36 result: Operations.Outcome<(Storage.Buffer<Element> & Storage.Buffer<Element>)>) -> Tensors.Tensor<Element>:
37 match result:
38 case Operations.Accepted{(input,output)}: Tensors.Tensor{output,out_shape,fill,Tensors.Usable{},workers}
39 case Operations.Rejected{(input,output)}: Tensors.Tensor{output,out_shape,fill,Tensors.Failed{Tensors.Problem{name,Tensors.InvalidArgument{shape}}},workers}
40
41def pool_middle(~Element: Data,~operation: Element -> Element -> Element,name: String,+pad: Element,middle: Maybe<&2,U32>,count: U32,+channels: U32,+pool: Access.Pool,
42 storage: Storage.Buffer<Element>,+shape: List<&2,U32>,+out_shape: List<&2,U32>,+fill: Element,+workers: U32) -> Tensors.Tensor<Element>:
43 match middle:
44 case Some{middle}:
45 pooled(~Element,name,shape,out_shape,fill,workers,
46 Operations.pool(~Element,~operation,pad,storage,pool,channels,Tensors.buffer(~Element,fill,middle),Tensors.buffer(~Element,fill,count)))
47 case None{}: Tensors.failed(~Element,name,Tensors.InvalidArgument{shape},shape,fill,workers)
48
49
50
51def middle_shape(+shape: List<&2,U32>,pool: Access.Pool) -> List<&2,U32>:
52 Access.Pool{height,width,kernel,stride,padding,out_height,out_width} = pool
53 List.append(&2,U32,List.take(&2,U32,shape,Nat.sub(List.length(&2,U32,shape),2n)),[height,out_width])
54
55def pool_counts(~Element: Data,~operation: Element -> Element -> Element,name: String,+pad: Element,channels: Maybe<&2,U32>,count: Maybe<&2,U32>,+pool: Access.Pool,
56 storage: Storage.Buffer<Element>,+shape: List<&2,U32>,+out_shape: List<&2,U32>,+fill: Element,+workers: U32) -> Tensors.Tensor<Element>:
57 match channels count:
58 case Some{+channels} Some{count}:
59 pool_middle(~Element,~operation,name,pad,Tensors.count_of(middle_shape(shape,pool)),count,channels,pool,storage,shape,out_shape,fill,workers)
60 case channels count: Tensors.failed(~Element,name,Tensors.InvalidArgument{shape},shape,fill,workers)
61
62def pool_planes(~Element: Data,~operation: Element -> Element -> Element,name: String,+pad: Element,channels: Maybe<&2,U32>,+pool: Access.Pool,
63 storage: Storage.Buffer<Element>,+shape: List<&2,U32>,+fill: Element,+workers: U32) -> Tensors.Tensor<Element>:
64 Access.Pool{height,width,kernel,stride,padding,+out_height,+out_width} = pool
65 +out_shape = List.append(&2,U32,List.take(&2,U32,shape,Nat.sub(List.length(&2,U32,shape),2n)),[out_height,out_width])
66 pool_counts(~Element,~operation,name,pad,channels,Tensors.count_of(out_shape),pool,storage,shape,out_shape,fill,workers)
67
68def pool_status(~Element: Data,~operation: Element -> Element -> Element,name: String,status: Tensors.Status,+pad: Element,+kernel: U32,+stride: U32,+padding: U32,
69 storage: Storage.Buffer<Element>,+shape: List<&2,U32>,+fill: Element,+workers: U32) -> Tensors.Tensor<Element>:
70 match status:
71 case Tensors.Usable{}:
72 pool_planes(~Element,~operation,name,pad,planes(shape),geometry(shape,kernel,stride,padding),storage,shape,fill,workers)
73 case Tensors.Failed{problem}: Tensors.Tensor{storage,shape,fill,Tensors.Failed{problem},workers}
74
75
76def band_shape(shape: List<&2,U32>,geometry: Bands.Geometry) -> Bool:
77 match shape geometry:
78 case [c,h,w] Bands.Geometry{n,ci,hi,wi}: U32.is_eq(n,1) && U32.is_eq(c,ci) && U32.is_eq(h,hi) && U32.is_eq(w,wi)
79 case [n,c,h,w] Bands.Geometry{ni,ci,hi,wi}: U32.is_eq(n,ni) && U32.is_eq(c,ci) && U32.is_eq(h,hi) && U32.is_eq(w,wi)
80 case shape geometry: False{}
81
82def band_execute(~Element: Data,~operation: Element -> Element -> Element,+pad: Element,pool: Access.Pool,+geometry: Bands.Geometry,bands: Bands.Bands(~Element),
83 out_shape: List<&2,U32>,+fill: Element,+workers: U32) -> Tensors.Tensor<Element>:
84 match pool geometry:
85 case Access.Pool{height,width,kernel,stride,padding,+oh,+ow} Bands.Geometry{batch,channels,ih,iw}:
86 Tensors.Banded{BandPool.execute(~Element,~operation,BandPool.Context{BandWindow.Geometry{geometry,kernel,stride,padding,oh,ow},pad,fill,workers},bands),
87 Bands.Geometry{batch,channels,oh,ow},out_shape,fill,Tensors.Usable{},workers}
88
89
90
91def band_count(~Element: Data,~operation: Element -> Element -> Element,name: String,valid: Bool,planes: Maybe<&2,U32>,count: Maybe<&2,U32>,+pad: Element,+pool: Access.Pool,+geometry: Bands.Geometry,bands: Bands.Bands(~Element),
92 +shape: List<&2,U32>,out_shape: List<&2,U32>,+fill: Element,+workers: U32) -> Tensors.Tensor<Element>:
93 match valid planes count pool:
94 case True{} Some{planes} Some{count} pool: band_execute(~Element,~operation,pad,pool,geometry,bands,out_shape,fill,workers)
95 case valid planes count Access.Pool{height,width,kernel,stride,padding,oh,ow}:
96 Tensors.with_dense(~Element,~Tensors.Tensor<Element>,Tensors.Banded{bands,geometry,shape,fill,Tensors.Usable{},workers},storage => shape => fill => status => workers =>
97 pool_status(~Element,~operation,name,status,pad,kernel,stride,padding,storage,shape,fill,workers))
98
99def band_geometry(~Element: Data,~operation: Element -> Element -> Element,name: String,pad: Element,+pool: Access.Pool,+geometry: Bands.Geometry,bands: Bands.Bands(~Element),
100 +shape: List<&2,U32>,fill: Element,workers: U32) -> Tensors.Tensor<Element>:
101 Access.Pool{+height,+width,+kernel,+stride,+padding,+out_height,+out_width} = pool
102 +pool = {Access.Pool{height,width,kernel,stride,padding,out_height,out_width} : Access.Pool}
103 +out_shape = List.append(&2,U32,List.take(&2,U32,shape,Nat.sub(List.length(&2,U32,shape),2n)),[out_height,out_width])
104 band_count(~Element,~operation,name,band_shape(shape,geometry) && Operations.pool_geometry(pool) && U32.is_lt(0,height) && U32.is_lt(0,width) &&
105 Bool.not(Shapes.has_zero(out_shape)),Tensors.count_of(middle_shape(shape,pool)),Tensors.count_of(out_shape),pad,pool,geometry,bands,shape,out_shape,fill,workers)
106
107def band_status(~Element: Data,~operation: Element -> Element -> Element,name: String,status: Tensors.Status,pad: Element,+kernel: U32,+stride: U32,+padding: U32,
108 layout: Bands.Geometry,bands: Bands.Bands(~Element),+shape: List<&2,U32>,fill: Element,workers: U32) -> Tensors.Tensor<Element>:
109 match status:
110 case Tensors.Failed{+problem}:
111 Tensors.with_dense(~Element,~Tensors.Tensor<Element>,Tensors.Banded{bands,layout,shape,fill,Tensors.Failed{problem},workers},
112 storage => shape => fill => status => workers =>
113 pool_status(~Element,~operation,name,status,pad,kernel,stride,padding,storage,shape,fill,workers))
114 case Tensors.Usable{}: band_geometry(~Element,~operation,name,pad,geometry(shape,kernel,stride,padding),layout,bands,shape,fill,workers)
115
116def pool2d(~Element: Data,~operation: Element -> Element -> Element,name: String,+pad: Element,tensor: Tensors.Tensor<Element>,
117 +kernel: U32,+stride: U32,+padding: U32) -> Tensors.Tensor<Element>:
118 match tensor:
119 case Tensors.Tensor{storage,shape,fill,status,workers}: pool_status(~Element,~operation,name,status,pad,kernel,stride,padding,storage,shape,fill,workers)
120 case Tensors.Banded{bands,layout,shape,fill,status,workers}: band_status(~Element,~operation,name,status,pad,kernel,stride,padding,layout,bands,shape,fill,workers)