GCC Code Coverage Report


Directory: src/athena/
File: src/athena/athena_orthogonal_nop_block.f90
Date: 2026-04-15 16:08:59
Exec Total Coverage
Lines: 289 316 91.5%
Functions: 0 0 -%
Branches: 955 1918 49.8%

Line Branch Exec Source
1 module athena__orthogonal_nop_block
2 !! Module containing implementation of an Orthogonal Neural Operator layer
3 !!
4 !! This module implements the Orthogonal Neural Operator (ONO) from
5 !! "Improved Operator Learning by Orthogonal Attention" (Luo et al., 2024).
6 !!
7 !! The ONO layer uses an orthogonal attention kernel to approximate the
8 !! integral operator. It combines:
9 !! 1. A learned orthogonal basis for efficient attention (k << N)
10 !! 2. A spectral pathway through the orthogonal basis
11 !! 3. A local affine bypass
12 !!
13 !! The layer computes:
14 !! \[
15 !! \mathbf{v} = \sigma\!\bigl(
16 !! \mathbf{W}_V\,\mathbf{\Phi}\,(\mathbf{\Phi}^T\,\mathbf{u})
17 !! + \mathbf{W}\,\mathbf{u}
18 !! + \mathbf{b}\bigr)
19 !! \]
20 !!
21 !! where \(\mathbf{\Phi} \in \mathbb{R}^{n_{in} \times k}\) is obtained
22 !! by QR/Gram-Schmidt orthogonalisation of learnable basis weights
23 !! \(\mathbf{B}\).
24 !!
25 !! Parameters (learnable):
26 !! - \(\mathbf{R} \in \mathbb{R}^{k \times k}\) spectral mixing
27 !! - \(\mathbf{B} \in \mathbb{R}^{n_{in} \times k}\) basis (orthogonalised)
28 !! - \(\mathbf{W} \in \mathbb{R}^{n_{out} \times n_{in}}\) bypass
29 !! - \(\mathbf{b} \in \mathbb{R}^{n_{out}}\) bias (optional)
30 !!
31 !! The spectral path is: decode( R * encode(u) )
32 !! encode = Phi^T @ u [k, batch]
33 !! mix = R @ encoded [k, batch]
34 !! decode = Phi @ mix [n_in, batch]
35 !!
36 !! Then a linear projection to the output: W_out @ decode -> [n_out, batch]
37 !! Plus bypass: W @ u -> [n_out, batch]
38 use coreutils, only: real32, stop_program
39 use athena__base_layer, only: learnable_layer_type, base_layer_type
40 use athena__misc_types, only: base_actv_type, base_init_type, &
41 onnx_attribute_type
42 use diffstruc, only: array_type, matmul, operator(+)
43 use athena__diffstruc_extd, only: ono_encode, ono_decode
44 implicit none
45 public :: read_orthogonal_nop_block
46
47
48 type, extends(learnable_layer_type) :: orthogonal_nop_block_type
49 !! Type for an Orthogonal Neural Operator layer
50 integer :: num_inputs = 0
51 !! Number of inputs (discretisation points)
52 integer :: num_outputs = 0
53 !! Number of outputs (discretisation points)
54 integer :: num_basis = 0
55 !! Number of orthogonal basis functions (k)
56 type(array_type), dimension(1) :: z
57 !! Temporary array for pre-activation values
58 contains
59 procedure, pass(this) :: get_num_params => get_num_params_ono
60 procedure, pass(this) :: set_hyperparams => set_hyperparams_ono
61 procedure, pass(this) :: init => init_ono
62 procedure, pass(this) :: print_to_unit => print_to_unit_ono
63 procedure, pass(this) :: read => read_ono
64
65 procedure, pass(this) :: forward => forward_ono
66 procedure, pass(this) :: get_bases => get_bases_ono
67 procedure, pass(this) :: get_orthogonality_metric
68 procedure, pass(this) :: get_attributes => get_attributes_ono
69
70 final :: finalise_ono
71 end type orthogonal_nop_block_type
72
73 interface orthogonal_nop_block_type
74 module function layer_setup( &
75 num_outputs, num_basis, &
76 num_inputs, use_bias, &
77 activation, &
78 kernel_initialiser, bias_initialiser, verbose &
79 ) result(layer)
80 integer, intent(in) :: num_outputs
81 integer, intent(in) :: num_basis
82 integer, optional, intent(in) :: num_inputs
83 logical, optional, intent(in) :: use_bias
84 class(*), optional, intent(in) :: activation
85 class(*), optional, intent(in) :: kernel_initialiser, bias_initialiser
86 integer, optional, intent(in) :: verbose
87 type(orthogonal_nop_block_type) :: layer
88 end function layer_setup
89 end interface orthogonal_nop_block_type
90
91
92
93 contains
94
95 !###############################################################################
96 16 subroutine finalise_ono(this)
97 !! Finalise the orthogonal neural operator block
98 implicit none
99
100 ! Arguments
101 type(orthogonal_nop_block_type), intent(inout) :: this
102 !! Layer instance to release
103
104
3/4
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 15 times.
16 if(allocated(this%input_shape)) deallocate(this%input_shape)
105
4/6
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 15 times.
✓ Branch 5 taken 15 times.
✗ Branch 6 not taken.
16 if(allocated(this%output)) deallocate(this%output)
106
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 13 times.
16 if(this%z(1)%allocated) call this%z(1)%deallocate()
107
108 16 end subroutine finalise_ono
109 !###############################################################################
110
111
112 !###############################################################################
113 11 pure function get_num_params_ono(this) result(num_params)
114 !! Return the number of learnable parameters for the block
115 implicit none
116
117 ! Arguments
118 class(orthogonal_nop_block_type), intent(in) :: this
119 !! Layer instance
120 integer :: num_params
121 !! Total number of learnable parameters
122
123 ! R: num_basis^2 (spectral mixing)
124 ! B: num_inputs * num_basis (basis weights)
125 ! W_out: num_outputs * num_inputs (output projection / bypass)
126 ! b: num_outputs (optional)
127 num_params = this%num_basis * this%num_basis + &
128 this%num_inputs * this%num_basis + &
129 11 this%num_outputs * this%num_inputs
130
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 2 times.
11 if(this%use_bias) num_params = num_params + this%num_outputs
131
132 11 end function get_num_params_ono
133 !###############################################################################
134
135
136 !###############################################################################
137 11 module function layer_setup( &
138 num_outputs, num_basis, &
139 num_inputs, use_bias, &
140 activation, &
141 kernel_initialiser, bias_initialiser, verbose &
142
9/16
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 11 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 11 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 11 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 11 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 11 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 11 times.
22 ) result(layer)
143 use athena__activation, only: activation_setup
144 use athena__initialiser, only: initialiser_setup
145 implicit none
146
147 ! Arguments
148 integer, intent(in) :: num_outputs
149 !! Number of output features
150 integer, intent(in) :: num_basis
151 !! Number of orthogonal basis vectors
152 integer, optional, intent(in) :: num_inputs
153 !! Number of input features when known at construction time
154 logical, optional, intent(in) :: use_bias
155 !! Whether to allocate a bias term
156 class(*), optional, intent(in) :: activation
157 !! Activation function specification
158 class(*), optional, intent(in) :: kernel_initialiser, bias_initialiser
159 !! Kernel and bias initialiser specifications
160 integer, optional, intent(in) :: verbose
161 !! Verbosity level
162
163 type(orthogonal_nop_block_type) :: layer
164 !! Constructed orthogonal neural operator block
165
166 ! Local variables
167 integer :: verbose_ = 0
168 !! Effective verbosity level
169 logical :: use_bias_ = .true.
170 !! Effective bias flag
171 33 class(base_actv_type), allocatable :: activation_
172 !! Materialised activation object
173 11 class(base_init_type), allocatable :: kernel_initialiser_, bias_initialiser_
174 !! Materialised kernel and bias initialisers
175
176
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if(present(verbose)) verbose_ = verbose
177
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 5 times.
11 if(present(use_bias)) use_bias_ = use_bias
178
179
3/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
11 if(present(activation))then
180
5/14
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 6 taken 7 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 7 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 7 times.
✓ Branch 17 taken 7 times.
✗ Branch 18 not taken.
7 activation_ = activation_setup(activation)
181 else
182
5/14
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 4 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 4 times.
✓ Branch 17 taken 4 times.
✗ Branch 18 not taken.
4 activation_ = activation_setup("none")
183 end if
184
185
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
11 if(present(kernel_initialiser))then
186 kernel_initialiser_ = initialiser_setup(kernel_initialiser)
187 end if
188
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
11 if(present(bias_initialiser))then
189 bias_initialiser_ = initialiser_setup(bias_initialiser)
190 end if
191
192 call layer%set_hyperparams( &
193 num_outputs = num_outputs, &
194 num_basis = num_basis, &
195 use_bias = use_bias_, &
196 activation = activation_, &
197 kernel_initialiser = kernel_initialiser_, &
198 bias_initialiser = bias_initialiser_, &
199 verbose = verbose_ &
200 11 )
201
202
4/4
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 9 times.
20 if(present(num_inputs)) call layer%init(input_shape=[num_inputs])
203
204
13/28
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 11 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 11 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 11 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 11 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 11 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 11 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 11 times.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 21 not taken.
✓ Branch 22 taken 11 times.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✓ Branch 26 taken 11 times.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✓ Branch 29 taken 11 times.
33 end function layer_setup
205 !###############################################################################
206
207
208 !###############################################################################
209 12 subroutine set_hyperparams_ono( &
210 this, num_outputs, num_basis, &
211 use_bias, &
212 activation, &
213 kernel_initialiser, bias_initialiser, &
214 verbose &
215 )
216 use athena__activation, only: activation_setup
217 use athena__initialiser, only: get_default_initialiser, initialiser_setup
218 implicit none
219
220 ! Arguments
221 class(orthogonal_nop_block_type), intent(inout) :: this
222 !! Layer instance to configure
223 integer, intent(in) :: num_outputs
224 !! Number of output features
225 integer, intent(in) :: num_basis
226 !! Number of orthogonal basis vectors
227 logical, intent(in) :: use_bias
228 !! Whether to use a bias term
229 class(base_actv_type), allocatable, intent(in) :: activation
230 !! Activation function object
231 class(base_init_type), allocatable, intent(in) :: &
232 kernel_initialiser, bias_initialiser
233 !! Kernel and bias initialiser objects
234 integer, optional, intent(in) :: verbose
235 !! Verbosity level
236
237 ! Local variables
238 character(len=256) :: buffer
239 !! Buffer for default initialiser lookup
240
241
5/8
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 12 times.
12 this%name = "orthogonal_nop"
242 12 this%type = "nop"
243 12 this%input_rank = 1
244 12 this%output_rank = 1
245 12 this%use_bias = use_bias
246 12 this%num_outputs = num_outputs
247 12 this%num_basis = num_basis
248
249
4/6
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
12 if(allocated(this%activation)) deallocate(this%activation)
250
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if(.not.allocated(activation))then
251 this%activation = activation_setup("none")
252 else
253
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
12 allocate(this%activation, source=activation)
254 end if
255
4/6
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
12 if(allocated(this%kernel_init)) deallocate(this%kernel_init)
256
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 1 times.
12 if(.not.allocated(kernel_initialiser))then
257
1/2
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
11 buffer = get_default_initialiser(this%activation%name)
258
5/14
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 6 taken 11 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 11 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 11 times.
✓ Branch 17 taken 11 times.
✗ Branch 18 not taken.
11 this%kernel_init = initialiser_setup(buffer)
259 else
260
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 allocate(this%kernel_init, source=kernel_initialiser)
261 end if
262
4/6
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
12 if(allocated(this%bias_init)) deallocate(this%bias_init)
263
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 1 times.
12 if(.not.allocated(bias_initialiser))then
264 buffer = get_default_initialiser( &
265 this%activation%name, &
266 is_bias=.true. &
267
1/2
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
11 )
268
5/14
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 6 taken 11 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 11 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 11 times.
✓ Branch 17 taken 11 times.
✗ Branch 18 not taken.
11 this%bias_init = initialiser_setup(buffer)
269 else
270
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 allocate(this%bias_init, source=bias_initialiser)
271 end if
272
273
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if(present(verbose))then
274
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if(abs(verbose).gt.0)then
275 write(*,'("ORTHOGONAL_NOP activation: ",A)') &
276 trim(this%activation%name)
277 end if
278 end if
279
280 12 end subroutine set_hyperparams_ono
281 !###############################################################################
282
283
284 !###############################################################################
285
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 subroutine init_ono(this, input_shape, verbose)
286 !! Initialise parameter storage and output buffers for the block
287 implicit none
288
289 ! Arguments
290 class(orthogonal_nop_block_type), intent(inout) :: this
291 !! Layer instance to initialise
292 integer, dimension(:), intent(in) :: input_shape
293 !! Input shape used to infer num_inputs
294 integer, optional, intent(in) :: verbose
295 !! Verbosity level
296
297 ! Local variables
298 integer :: num_inputs
299 !! Effective fan-in size used for initialisation
300 integer :: verbose_ = 0
301 !! Effective verbosity level
302
303
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if(present(verbose)) verbose_ = verbose
304
305
306 !---------------------------------------------------------------------------
307 ! Set shapes
308 !---------------------------------------------------------------------------
309
4/8
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 11 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 11 times.
11 if(.not.allocated(this%input_shape)) call this%set_shape(input_shape)
310
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
11 this%num_inputs = this%input_shape(1)
311
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 11 times.
✓ Branch 7 taken 11 times.
22 this%output_shape = [this%num_outputs]
312 11 this%num_params = this%get_num_params()
313
314
315 !---------------------------------------------------------------------------
316 ! Allocate learnable parameters
317 !
318 ! params(1): R spectral mixing [num_basis x num_basis]
319 ! params(2): B basis weights [num_inputs x num_basis]
320 ! params(3): W bypass/output weights [num_outputs x num_inputs]
321 ! params(4): b bias [num_outputs] (optional)
322 !---------------------------------------------------------------------------
323
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 11 times.
11 allocate(this%weight_shape(2,3))
324
9/16
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 11 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 11 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 11 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 11 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 11 times.
✓ Branch 21 taken 22 times.
✓ Branch 22 taken 11 times.
33 this%weight_shape(:,1) = [ this%num_basis, this%num_basis ]
325
9/16
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 11 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 11 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 11 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 11 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 11 times.
✓ Branch 21 taken 22 times.
✓ Branch 22 taken 11 times.
33 this%weight_shape(:,2) = [ this%num_inputs, this%num_basis ]
326
9/16
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 11 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 11 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 11 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 11 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 11 times.
✓ Branch 21 taken 22 times.
✓ Branch 22 taken 11 times.
33 this%weight_shape(:,3) = [ this%num_outputs, this%num_inputs ]
327
328
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 2 times.
11 if(this%use_bias)then
329
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 9 times.
✓ Branch 7 taken 9 times.
18 this%bias_shape = [ this%num_outputs ]
330
16/30
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 9 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 9 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 9 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 9 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 9 times.
✓ Branch 21 taken 36 times.
✓ Branch 22 taken 9 times.
✓ Branch 23 taken 36 times.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✓ Branch 26 taken 36 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 36 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 36 times.
✗ Branch 31 not taken.
✓ Branch 32 taken 36 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 36 times.
✗ Branch 35 not taken.
✓ Branch 36 taken 36 times.
45 allocate(this%params(4))
331 else
332
16/30
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 2 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 2 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 2 times.
✓ Branch 21 taken 6 times.
✓ Branch 22 taken 2 times.
✓ Branch 23 taken 6 times.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✓ Branch 26 taken 6 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 6 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 6 times.
✗ Branch 31 not taken.
✓ Branch 32 taken 6 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 6 times.
✗ Branch 35 not taken.
✓ Branch 36 taken 6 times.
8 allocate(this%params(3))
333 end if
334
335 11 num_inputs = this%num_inputs
336
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 2 times.
11 if(this%use_bias) num_inputs = this%num_inputs + 1
337
338 ! R: spectral mixing weights
339
4/6
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
✓ Branch 6 taken 33 times.
✓ Branch 7 taken 11 times.
44 call this%params(1)%allocate([this%num_basis, this%num_basis, 1])
340
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
11 call this%params(1)%set_requires_grad(.true.)
341
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
11 this%params(1)%fix_pointer = .true.
342
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
11 this%params(1)%is_sample_dependent = .false.
343
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
11 this%params(1)%is_temporary = .false.
344
345 ! B: basis weights (stored flat for Gram-Schmidt, but allocated shaped)
346
4/6
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
✓ Branch 6 taken 33 times.
✓ Branch 7 taken 11 times.
44 call this%params(2)%allocate([this%num_inputs, this%num_basis, 1])
347
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
11 call this%params(2)%set_requires_grad(.true.)
348
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
11 this%params(2)%fix_pointer = .true.
349
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
11 this%params(2)%is_sample_dependent = .false.
350
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
11 this%params(2)%is_temporary = .false.
351
352 ! W: bypass/output weights
353
4/6
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
✓ Branch 6 taken 33 times.
✓ Branch 7 taken 11 times.
44 call this%params(3)%allocate([this%num_outputs, this%num_inputs, 1])
354
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
11 call this%params(3)%set_requires_grad(.true.)
355
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
11 this%params(3)%fix_pointer = .true.
356
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
11 this%params(3)%is_sample_dependent = .false.
357
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
11 this%params(3)%is_temporary = .false.
358
359
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 2 times.
11 if(this%use_bias)then
360
12/20
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 9 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 9 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 9 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 9 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 9 times.
✓ Branch 21 taken 9 times.
✓ Branch 22 taken 9 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 9 times.
✓ Branch 25 taken 18 times.
✓ Branch 26 taken 9 times.
36 call this%params(4)%allocate([this%bias_shape, 1])
361
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9 times.
9 call this%params(4)%set_requires_grad(.true.)
362
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9 times.
9 this%params(4)%fix_pointer = .true.
363
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9 times.
9 this%params(4)%is_sample_dependent = .false.
364
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9 times.
9 this%params(4)%is_temporary = .false.
365 end if
366
367
368 !---------------------------------------------------------------------------
369 ! Initialise learnable parameters
370 !---------------------------------------------------------------------------
371 call this%kernel_init%initialise( &
372 110 this%params(1)%val(:,1), &
373 fan_in = this%num_basis, fan_out = this%num_basis, &
374 spacing = [ this%num_basis ] &
375
12/22
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 11 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 11 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 11 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 11 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 11 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 11 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 11 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 11 times.
✓ Branch 30 taken 11 times.
✓ Branch 31 taken 11 times.
22 )
376 call this%kernel_init%initialise( &
377 110 this%params(2)%val(:,1), &
378 fan_in = this%num_inputs, fan_out = this%num_basis, &
379 spacing = [ this%num_inputs ] &
380
12/22
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 11 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 11 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 11 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 11 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 11 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 11 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 11 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 11 times.
✓ Branch 30 taken 11 times.
✓ Branch 31 taken 11 times.
22 )
381 call this%kernel_init%initialise( &
382 110 this%params(3)%val(:,1), &
383 fan_in = num_inputs, fan_out = this%num_outputs, &
384 spacing = [ this%num_outputs ] &
385
12/22
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 11 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 11 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 11 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 11 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 11 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 11 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 11 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 11 times.
✓ Branch 30 taken 11 times.
✓ Branch 31 taken 11 times.
22 )
386
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 2 times.
11 if(this%use_bias)then
387 call this%bias_init%initialise( &
388 90 this%params(4)%val(:,1), &
389 fan_in = num_inputs, fan_out = this%num_outputs &
390
10/20
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 9 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 9 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 9 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 9 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 9 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 9 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 9 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 9 times.
9 )
391 end if
392
393
394 !---------------------------------------------------------------------------
395 ! Allocate output arrays
396 !---------------------------------------------------------------------------
397
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
11 if(allocated(this%output)) deallocate(this%output)
398
15/26
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 11 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 11 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 11 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 11 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 11 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 11 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 11 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 11 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 11 times.
✓ Branch 33 taken 11 times.
✓ Branch 34 taken 11 times.
✓ Branch 35 taken 11 times.
✓ Branch 36 taken 11 times.
33 allocate(this%output(1,1))
399
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if(this%z(1)%allocated) call this%z(1)%deallocate()
400
401 11 end subroutine init_ono
402 !###############################################################################
403
404
405 !###############################################################################
406 1 function get_bases_ono(this) result(phi)
407 !! Orthogonalise the basis matrix B using modified Gram-Schmidt
408 implicit none
409
410 ! Arguments
411 class(orthogonal_nop_block_type), intent(in) :: this
412 !! Layer instance providing basis parameters
413 type(array_type) :: phi
414 !! Orthogonalised basis matrix packed in an array_type
415
416 ! Local variables
417 integer :: n, k, i, j
418 !! Basis dimensions and Gram-Schmidt loop indices
419 1 real(real32), allocatable :: B(:,:), Q(:,:)
420 !! Raw basis matrix and orthogonalised copy
421 real(real32) :: norm_val, proj
422 !! Gram-Schmidt norm and projection scalars
423
424 1 n = this%num_inputs
425 1 k = this%num_basis
426
427
17/34
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 1 times.
✓ Branch 19 taken 1 times.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✓ Branch 22 taken 1 times.
✓ Branch 23 taken 1 times.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✓ Branch 26 taken 1 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 1 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 1 times.
✗ Branch 31 not taken.
✓ Branch 32 taken 1 times.
✗ Branch 34 not taken.
✓ Branch 35 taken 1 times.
✗ Branch 37 not taken.
✓ Branch 38 taken 1 times.
1 allocate(B(n, k), Q(n, k))
428
429 ! Reshape B from flat params(2) into [n, k]
430
15/28
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 1 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 1 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 1 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 1 times.
✓ Branch 30 taken 2 times.
✓ Branch 31 taken 1 times.
✓ Branch 33 taken 1 times.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✓ Branch 36 taken 1 times.
✗ Branch 37 not taken.
✓ Branch 38 taken 1 times.
3 B = reshape(this%params(2)%val(:,1), [n, k])
431
432 ! Modified Gram-Schmidt orthogonalisation
433
15/36
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 1 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 1 times.
✓ Branch 24 taken 1 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 1 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 1 times.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✓ Branch 40 taken 3 times.
✓ Branch 41 taken 1 times.
✓ Branch 42 taken 24 times.
✓ Branch 43 taken 3 times.
28 Q = B
434
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
4 do j = 1, k
435
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 do i = 1, j - 1
436
15/28
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 3 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 3 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 3 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 3 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 3 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 3 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 3 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 3 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 3 times.
✓ Branch 39 taken 24 times.
✓ Branch 40 taken 3 times.
27 proj = dot_product(Q(:,i), Q(:,j))
437
22/42
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 3 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 3 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 3 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 3 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 3 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 3 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 3 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 3 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 3 times.
✗ Branch 39 not taken.
✓ Branch 40 taken 3 times.
✗ Branch 42 not taken.
✓ Branch 43 taken 3 times.
✗ Branch 45 not taken.
✓ Branch 46 taken 3 times.
✗ Branch 48 not taken.
✓ Branch 49 taken 3 times.
✗ Branch 51 not taken.
✓ Branch 52 taken 3 times.
✗ Branch 54 not taken.
✓ Branch 55 taken 3 times.
✗ Branch 57 not taken.
✓ Branch 58 taken 3 times.
✓ Branch 60 taken 24 times.
✓ Branch 61 taken 3 times.
30 Q(:,j) = Q(:,j) - proj * Q(:,i)
438 end do
439
15/28
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 3 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 3 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 3 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 3 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 3 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 3 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 3 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 3 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 3 times.
✓ Branch 39 taken 24 times.
✓ Branch 40 taken 3 times.
27 norm_val = sqrt(dot_product(Q(:,j), Q(:,j)))
440
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
4 if(norm_val .gt. 1.0e-12_real32)then
441
15/28
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 3 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 3 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 3 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 3 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 3 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 3 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 3 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 3 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 3 times.
✓ Branch 39 taken 24 times.
✓ Branch 40 taken 3 times.
27 Q(:,j) = Q(:,j) / norm_val
442 else
443 Q(:,j) = 0.0_real32
444 end if
445 end do
446
447 ! Store phi [n x k]
448
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
4 call phi%allocate([n, k, 1])
449 1 phi%is_sample_dependent = .false.
450 1 phi%requires_grad = .false.
451 1 phi%fix_pointer = .true.
452 1 phi%is_temporary = .false.
453
10/16
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✓ Branch 12 taken 1 times.
✓ Branch 13 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 1 times.
✓ Branch 21 taken 24 times.
✓ Branch 22 taken 1 times.
26 phi%val(:,1) = reshape(Q, [n * k])
454
455
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 deallocate(B, Q)
456
457
3/6
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
2 end function get_bases_ono
458 !###############################################################################
459
460
461 !###############################################################################
462 1 function get_orthogonality_metric(this) result(metric)
463 !! Compute max(|Phi^T @ Phi - I|) as a measure of basis orthogonality
464 implicit none
465
466 ! Arguments
467 class(orthogonal_nop_block_type), intent(in) :: this
468 !! Layer instance providing basis parameters
469 real(real32) :: metric
470 !! Maximum absolute deviation from orthogonality
471
472 ! Local variables
473 integer :: n, k, i, j
474 !! Matrix dimensions and traversal indices
475 1 real(real32), allocatable :: basis_matrix(:,:), orthogonal_basis(:,:)
476 !! Raw basis weights and orthogonalised basis matrix
477 real(real32) :: norm_val, projection, val
478 !! Gram-Schmidt scalars and current absolute deviation entry
479
480 1 n = this%num_inputs
481 1 k = this%num_basis
482
483
18/36
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 1 times.
✓ Branch 21 taken 1 times.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✓ Branch 24 taken 1 times.
✓ Branch 25 taken 1 times.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✓ Branch 28 taken 1 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 1 times.
✗ Branch 31 not taken.
✓ Branch 32 taken 1 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 1 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 1 times.
✗ Branch 39 not taken.
✓ Branch 40 taken 1 times.
1 allocate(basis_matrix(n, k), orthogonal_basis(n, k))
484
15/28
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 1 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 1 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 1 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 1 times.
✓ Branch 30 taken 2 times.
✓ Branch 31 taken 1 times.
✓ Branch 33 taken 1 times.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✓ Branch 36 taken 1 times.
✗ Branch 37 not taken.
✓ Branch 38 taken 1 times.
3 basis_matrix = reshape(this%params(2)%val(:,1), [n, k])
485
15/36
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 1 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 1 times.
✓ Branch 24 taken 1 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 1 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 1 times.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✓ Branch 40 taken 3 times.
✓ Branch 41 taken 1 times.
✓ Branch 42 taken 24 times.
✓ Branch 43 taken 3 times.
28 orthogonal_basis = basis_matrix
486
487
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
4 do j = 1, k
488
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 do i = 1, j - 1
489
15/28
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 3 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 3 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 3 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 3 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 3 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 3 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 3 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 3 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 3 times.
✓ Branch 39 taken 24 times.
✓ Branch 40 taken 3 times.
27 projection = dot_product(orthogonal_basis(:,i), orthogonal_basis(:,j))
490 orthogonal_basis(:,j) = orthogonal_basis(:,j) - &
491
22/42
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 3 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 3 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 3 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 3 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 3 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 3 times.
✗ Branch 25 not taken.
✓ Branch 26 taken 3 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 3 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 3 times.
✗ Branch 31 not taken.
✓ Branch 32 taken 3 times.
✗ Branch 34 not taken.
✓ Branch 35 taken 3 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 3 times.
✗ Branch 38 not taken.
✓ Branch 39 taken 3 times.
✗ Branch 41 not taken.
✓ Branch 42 taken 3 times.
✗ Branch 44 not taken.
✓ Branch 45 taken 3 times.
✗ Branch 46 not taken.
✓ Branch 47 taken 3 times.
✓ Branch 48 taken 24 times.
✓ Branch 49 taken 3 times.
30 projection * orthogonal_basis(:,i)
492 end do
493 norm_val = sqrt(dot_product( &
494
15/28
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 3 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 3 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 3 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 3 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 3 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 3 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 3 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 3 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 3 times.
✓ Branch 39 taken 24 times.
✓ Branch 40 taken 3 times.
27 orthogonal_basis(:,j), orthogonal_basis(:,j)))
495
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
4 if(norm_val .gt. 1.0e-12_real32)then
496
15/28
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 3 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 3 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 3 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 3 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 3 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 3 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 3 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 3 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 3 times.
✓ Branch 39 taken 24 times.
✓ Branch 40 taken 3 times.
27 orthogonal_basis(:,j) = orthogonal_basis(:,j) / norm_val
497 else
498 orthogonal_basis(:,j) = 0.0_real32
499 end if
500 end do
501
502 ! max(|Q^T Q - I|)
503 1 metric = 0.0_real32
504
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
4 do j = 1, k
505
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 3 times.
13 do i = 1, k
506
15/28
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 9 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 9 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 9 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 9 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 9 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 9 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 9 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 9 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 9 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 9 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 9 times.
✓ Branch 39 taken 72 times.
✓ Branch 40 taken 9 times.
81 val = dot_product(orthogonal_basis(:,i), orthogonal_basis(:,j))
507
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 6 times.
9 if(i .eq. j)then
508 3 val = abs(val - 1.0_real32)
509 else
510 6 val = abs(val)
511 end if
512
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 7 times.
12 if(val .gt. metric) metric = val
513 end do
514 end do
515
516
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 deallocate(basis_matrix, orthogonal_basis)
517
518
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 end function get_orthogonality_metric
519 !###############################################################################
520
521
522 !###############################################################################
523 1 subroutine print_to_unit_ono(this, unit)
524 !! Print orthogonal neural operator settings and parameters to a unit
525 use coreutils, only: to_upper
526 implicit none
527
528 ! Arguments
529 class(orthogonal_nop_block_type), intent(in) :: this
530 !! Layer instance to print
531 integer, intent(in) :: unit
532 !! Output unit number
533
534 1 write(unit,'(3X,"NUM_INPUTS = ",I0)') this%num_inputs
535 1 write(unit,'(3X,"NUM_OUTPUTS = ",I0)') this%num_outputs
536 1 write(unit,'(3X,"NUM_BASIS = ",I0)') this%num_basis
537 1 write(unit,'(3X,"USE_BIAS = ",L1)') this%use_bias
538
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(this%activation%name .ne. 'none')then
539 1 call this%activation%print_to_unit(unit)
540 end if
541
542 1 write(unit,'("WEIGHTS")')
543
10/18
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 1 times.
✓ Branch 25 taken 4 times.
✓ Branch 26 taken 1 times.
5 write(unit,'(5(E16.8E2))') this%params(1)%val(:,1) ! R
544
10/18
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 1 times.
✓ Branch 25 taken 10 times.
✓ Branch 26 taken 1 times.
11 write(unit,'(5(E16.8E2))') this%params(2)%val(:,1) ! B
545
10/18
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 1 times.
✓ Branch 25 taken 15 times.
✓ Branch 26 taken 1 times.
16 write(unit,'(5(E16.8E2))') this%params(3)%val(:,1) ! W
546
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(this%use_bias)then
547
10/18
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 1 times.
✓ Branch 25 taken 3 times.
✓ Branch 26 taken 1 times.
4 write(unit,'(5(E16.8E2))') this%params(4)%val(:,1) ! b
548 end if
549 1 write(unit,'("END WEIGHTS")')
550
551 1 end subroutine print_to_unit_ono
552 !###############################################################################
553
554
555 !###############################################################################
556 1 subroutine read_ono(this, unit, verbose)
557 use athena__tools_infile, only: assign_val, assign_vec, move
558 use coreutils, only: to_lower, to_upper, icount
559 use athena__activation, only: read_activation
560 use athena__initialiser, only: initialiser_setup
561 implicit none
562
563 ! Arguments
564 class(orthogonal_nop_block_type), intent(inout) :: this
565 !! Layer instance to populate from file data
566 integer, intent(in) :: unit
567 !! Input unit number
568 integer, optional, intent(in) :: verbose
569 !! Verbosity level
570
571 ! Local variables
572 integer :: stat, verbose_ = 0
573 !! I/O status and effective verbosity level
574 integer :: j, k, c, itmp1, iline
575 !! Loop counters and parser scratch integers
576 integer :: num_inputs, num_outputs, num_basis
577 !! Parsed layer dimensions
578 logical :: use_bias = .true.
579 !! Parsed bias flag
580 character(14) :: kernel_initialiser_name='', bias_initialiser_name=''
581 !! Parsed initialiser names
582 3 class(base_actv_type), allocatable :: activation
583 !! Parsed activation object
584 5 class(base_init_type), allocatable :: kernel_initialiser, bias_initialiser
585 !! Parsed initialiser objects
586 character(256) :: buffer, tag, err_msg
587 !! Input buffer, parsed tag and formatted error message
588 1 real(real32), allocatable, dimension(:) :: data_list
589 !! Temporary storage for flattened parameter blocks
590 integer :: param_line, final_line, num_vals
591 !! Weights-section line markers and current block size
592
593
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(present(verbose)) verbose_ = verbose
594
595 1 iline = 0
596 1 param_line = 0
597 1 final_line = 0
598 14 tag_loop: do
599 15 read(unit,'(A)',iostat=stat) buffer
600
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if(stat.ne.0)then
601 write(err_msg,'("file encountered error (EoF?) before END ",A)') &
602 to_upper(this%name)
603 call stop_program(err_msg)
604 return
605 end if
606
2/4
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 15 times.
15 if(trim(adjustl(buffer)).eq."") cycle tag_loop
607
608
4/6
✓ Branch 3 taken 15 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 15 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 14 times.
30 if(trim(adjustl(buffer)).eq."END "//to_upper(trim(this%name)))then
609 1 final_line = iline
610 1 backspace(unit)
611 15 exit tag_loop
612 end if
613 14 iline = iline + 1
614
615
2/4
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 14 times.
✗ Branch 5 not taken.
14 tag=trim(adjustl(buffer))
616
6/10
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 4 times.
✓ Branch 8 taken 4 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 4 times.
✗ Branch 11 not taken.
14 if(scan(buffer,"=").ne.0) tag=trim(tag(:scan(tag,"=")-1))
617
618 28 select case(trim(tag))
619 case("NUM_INPUTS")
620 2 call assign_val(buffer, num_inputs, itmp1)
621 case("NUM_OUTPUTS")
622 2 call assign_val(buffer, num_outputs, itmp1)
623 case("NUM_BASIS")
624 2 call assign_val(buffer, num_basis, itmp1)
625 case("USE_BIAS")
626 2 call assign_val(buffer, use_bias, itmp1)
627 case("ACTIVATION")
628 1 iline = iline - 1
629 1 backspace(unit)
630
5/14
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
✓ Branch 17 taken 1 times.
✗ Branch 18 not taken.
1 activation = read_activation(unit, iline)
631 case("KERNEL_INITIALISER", "KERNEL_INIT", "KERNEL_INITIALIZER")
632 call assign_val(buffer, kernel_initialiser_name, itmp1)
633 case("BIAS_INITIALISER", "BIAS_INIT", "BIAS_INITIALIZER")
634 call assign_val(buffer, bias_initialiser_name, itmp1)
635 case("WEIGHTS")
636 1 kernel_initialiser_name = 'zeros'
637 1 bias_initialiser_name = 'zeros'
638 1 param_line = iline
639 case default
640
3/4
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
✓ Branch 5 taken 1 times.
16 if(scan(to_lower(trim(adjustl(buffer))),&
641 'abcdfghijklmnopqrstuvwxyz').eq.0)then
642 8 cycle tag_loop
643
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 elseif(tag(:3).eq.'END')then
644 8 cycle tag_loop
645 end if
646 write(err_msg,'("Unrecognised line in input file: ",A)') &
647 trim(adjustl(buffer))
648 call stop_program(err_msg)
649
8/11
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
✓ Branch 10 taken 8 times.
28 return
650 end select
651 end do tag_loop
652
5/14
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
✓ Branch 17 taken 1 times.
✗ Branch 18 not taken.
1 kernel_initialiser = initialiser_setup(kernel_initialiser_name)
653
5/14
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
✓ Branch 17 taken 1 times.
✗ Branch 18 not taken.
1 bias_initialiser = initialiser_setup(bias_initialiser_name)
654
655 call this%set_hyperparams( &
656 num_outputs = num_outputs, &
657 num_basis = num_basis, &
658 use_bias = use_bias, &
659 activation = activation, &
660 kernel_initialiser = kernel_initialiser, &
661 bias_initialiser = bias_initialiser, &
662 verbose = verbose_ &
663 1 )
664
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 call this%init(input_shape=[num_inputs])
665
666
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(param_line.eq.0)then
667 write(0,*) "WARNING: WEIGHTS card in " // trim(this%name) // " not found"
668 else
669 1 call move(unit, param_line - iline, iostat=stat)
670
671 ! Read R (num_basis^2)
672 1 num_vals = num_basis * num_basis
673
7/14
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
1 allocate(data_list(num_vals), source=0._real32)
674 1 c = 1; k = 1
675
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 do while(c.le.num_vals)
676 1 read(unit,'(A)',iostat=stat) buffer
677
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(stat.ne.0) exit
678 1 k = icount(buffer)
679
5/8
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 4 times.
5 read(buffer,*,iostat=stat) (data_list(j),j=c,c+k-1)
680 1 c = c + k
681 end do
682
15/28
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 1 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 1 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 1 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 1 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 1 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 1 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 1 times.
✓ Branch 39 taken 4 times.
✓ Branch 40 taken 1 times.
5 this%params(1)%val(:,1) = data_list
683
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 deallocate(data_list)
684
685 ! Read B (num_inputs * num_basis)
686 1 num_vals = num_inputs * num_basis
687
7/14
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
1 allocate(data_list(num_vals), source=0._real32)
688 1 c = 1; k = 1
689
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 do while(c.le.num_vals)
690 2 read(unit,'(A)',iostat=stat) buffer
691
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if(stat.ne.0) exit
692 2 k = icount(buffer)
693
5/8
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 10 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 10 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 10 times.
12 read(buffer,*,iostat=stat) (data_list(j),j=c,c+k-1)
694 2 c = c + k
695 end do
696
15/28
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 1 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 1 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 1 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 1 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 1 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 1 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 1 times.
✓ Branch 39 taken 10 times.
✓ Branch 40 taken 1 times.
11 this%params(2)%val(:,1) = data_list
697
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 deallocate(data_list)
698
699 ! Read W (num_outputs * num_inputs)
700 1 num_vals = num_outputs * num_inputs
701
7/14
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
1 allocate(data_list(num_vals), source=0._real32)
702 1 c = 1; k = 1
703
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 do while(c.le.num_vals)
704 3 read(unit,'(A)',iostat=stat) buffer
705
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if(stat.ne.0) exit
706 3 k = icount(buffer)
707
5/8
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 15 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 15 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 15 times.
18 read(buffer,*,iostat=stat) (data_list(j),j=c,c+k-1)
708 3 c = c + k
709 end do
710
15/28
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 1 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 1 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 1 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 1 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 1 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 1 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 1 times.
✓ Branch 39 taken 15 times.
✓ Branch 40 taken 1 times.
16 this%params(3)%val(:,1) = data_list
711
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 deallocate(data_list)
712
713 ! Read b if use_bias
714
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(use_bias)then
715
7/14
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
1 allocate(data_list(num_outputs), source=0._real32)
716 1 c = 1; k = 1
717
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 do while(c.le.num_outputs)
718 1 read(unit,'(A)',iostat=stat) buffer
719
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(stat.ne.0) exit
720 1 k = icount(buffer)
721
5/8
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 3 times.
4 read(buffer,*,iostat=stat) (data_list(j),j=c,c+k-1)
722 1 c = c + k
723 end do
724
15/28
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 1 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 1 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 1 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 1 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 1 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 1 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 1 times.
✓ Branch 39 taken 3 times.
✓ Branch 40 taken 1 times.
4 this%params(4)%val(:,1) = data_list(1:num_outputs)
725
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 deallocate(data_list)
726 end if
727
728 1 read(unit,'(A)') buffer
729
2/4
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
1 if(trim(adjustl(buffer)).ne."END WEIGHTS")then
730 call stop_program("END WEIGHTS not where expected")
731 return
732 end if
733 end if
734
735 1 call move(unit, final_line - iline, iostat=stat)
736 1 read(unit,'(A)') buffer
737
3/6
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
2 if(trim(adjustl(buffer)).ne."END "//to_upper(trim(this%name)))then
738 write(err_msg,'("END ",A," not where expected")') to_upper(this%name)
739 call stop_program(err_msg)
740 1 return
741 end if
742
743
7/14
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
1 end subroutine read_ono
744 !###############################################################################
745
746
747 !###############################################################################
748 1 function read_orthogonal_nop_block(unit, verbose) result(layer)
749 !! Read an orthogonal neural operator block from file and return it
750 implicit none
751
752 ! Arguments
753 integer, intent(in) :: unit
754 !! Input unit number
755 integer, optional, intent(in) :: verbose
756 !! Verbosity level
757 class(base_layer_type), allocatable :: layer
758 !! Allocated base-layer instance containing the result
759
760 ! Local variables
761 integer :: verbose_ = 0
762 !! Effective verbosity level
763
764
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(present(verbose)) verbose_ = verbose
765 allocate(layer, source=orthogonal_nop_block_type( &
766
21/78
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✓ Branch 47 taken 1 times.
✗ Branch 49 not taken.
✓ Branch 50 taken 1 times.
✗ Branch 51 not taken.
✓ Branch 52 taken 1 times.
✗ Branch 53 not taken.
✓ Branch 54 taken 1 times.
✗ Branch 55 not taken.
✓ Branch 56 taken 1 times.
✗ Branch 57 not taken.
✓ Branch 58 taken 1 times.
✗ Branch 59 not taken.
✓ Branch 60 taken 1 times.
✗ Branch 62 not taken.
✓ Branch 63 taken 1 times.
✓ Branch 64 taken 1 times.
✗ Branch 65 not taken.
✗ Branch 66 not taken.
✓ Branch 67 taken 1 times.
✓ Branch 69 taken 1 times.
✗ Branch 70 not taken.
✓ Branch 71 taken 1 times.
✗ Branch 72 not taken.
✗ Branch 73 not taken.
✓ Branch 74 taken 1 times.
✓ Branch 76 taken 1 times.
✗ Branch 77 not taken.
✓ Branch 78 taken 1 times.
✗ Branch 79 not taken.
✗ Branch 80 not taken.
✓ Branch 81 taken 1 times.
✓ Branch 83 taken 1 times.
✗ Branch 84 not taken.
2 num_outputs=0, num_basis=1))
767 1 call layer%read(unit, verbose=verbose_)
768
769 2 end function read_orthogonal_nop_block
770 !###############################################################################
771
772
773 !###############################################################################
774
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 subroutine forward_ono(this, input)
775 !! Forward propagation for the Orthogonal Neural Operator layer
776 !!
777 !! Computes:
778 !! encoded = Phi^T @ u [k, batch]
779 !! mixed = R @ encoded [k, batch]
780 !! decoded = Phi @ mixed [n_in, batch]
781 !! spectral= W @ decoded [n_out, batch] (reuse W for output proj)
782 !!
783 !! bypass = W @ u [n_out, batch]
784 !!
785 !! v = sigma( spectral + bypass + b )
786 !!
787 !! Actually, we separate the spectral and bypass paths clearly:
788 !! spectral path uses the orthogonal basis + R mixing
789 !! bypass path uses W directly on input
790 !! Both project to [n_out] via W (shared) or separate matrices.
791 !!
792 !! Here we implement:
793 !! spectral = W @ Phi @ R @ Phi^T @ u
794 !! bypass = W @ u
795 !! v = sigma( spectral + bypass + b )
796 !!
797 !! Note: W is params(3) [n_out x n_in], shared for both paths
798 !! This means: v = sigma( W @ (Phi @ R @ Phi^T @ u + u) + b )
799 !! = sigma( W @ ((Phi @ R @ Phi^T + I) @ u) + b )
800 implicit none
801
802 ! Arguments
803 class(orthogonal_nop_block_type), intent(inout) :: this
804 !! Layer instance to execute
805 class(array_type), dimension(:,:), intent(in) :: input
806 !! Input batch tensor collection
807
808 ! Local variables
809 type(array_type), pointer :: ptr, ptr_spec, ptr_bypass
810 !! Combined output, spectral-path output and bypass-path output
811 type(array_type), pointer :: ptr_encoded, ptr_mixed, ptr_decoded
812 !! Encoded spectrum, mixed spectrum and decoded tensor
813
814
815 ! Spectral pathway: Phi @ R @ Phi^T @ u
816 ! Uses autodiff-tracked ono_encode/ono_decode for basis gradients
817 !---------------------------------------------------------------------------
818
819 ! Encode: Q(B)^T @ u -> [k, batch]
820 ptr_encoded => ono_encode(input(1,1), this%params(2), &
821
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 5 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5 times.
5 this%num_inputs, this%num_basis)
822
823 ! Mix: R @ encoded -> [k, batch]
824
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
5 ptr_mixed => matmul(this%params(1), ptr_encoded)
825
826 ! Decode: Q(B) @ mixed -> [n_in, batch]
827 10 ptr_decoded => ono_decode(ptr_mixed, this%params(2), &
828
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
5 this%num_inputs, this%num_basis)
829
830 ! Spectral projection: W @ decoded -> [n_out, batch]
831
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
5 ptr_spec => matmul(this%params(3), ptr_decoded)
832
833 ! Bypass: W @ u -> [n_out, batch]
834
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 5 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 5 times.
5 ptr_bypass => matmul(this%params(3), input(1,1))
835
836 ! Combine
837 5 ptr => ptr_spec + ptr_bypass
838
839 ! Add bias
840
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if(this%use_bias)then
841
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
5 ptr => ptr + this%params(4)
842 end if
843
844 ! Apply activation
845
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 5 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 5 times.
5 call this%output(1,1)%zero_grad()
846
3/4
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 3 times.
5 if(trim(this%activation%name) .eq. "none")then
847
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
2 call this%output(1,1)%assign_and_deallocate_source(ptr)
848 else
849 3 call this%z(1)%zero_grad()
850 3 call this%z(1)%assign_and_deallocate_source(ptr)
851 3 this%z(1)%is_temporary = .false.
852 3 ptr => this%activation%apply(this%z(1))
853
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
3 call this%output(1,1)%assign_and_deallocate_source(ptr)
854 end if
855
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 5 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 5 times.
5 this%output(1,1)%is_temporary = .false.
856
857 5 end subroutine forward_ono
858 !###############################################################################
859
860
861 !###############################################################################
862 2 function get_attributes_ono(this) result(attributes)
863 !! Return list of ONO attributes for ONNX export
864 implicit none
865
866 ! Arguments
867 class(orthogonal_nop_block_type), intent(in) :: this
868 !! Instance of the ONO block
869 type(onnx_attribute_type), allocatable, dimension(:) :: attributes
870 !! List of attributes for ONNX export
871
872 ! Local variables
873 character(32) :: buffer
874 !! Buffer for formatting
875
876
13/24
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 2 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 2 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 2 times.
✓ Branch 21 taken 10 times.
✓ Branch 22 taken 2 times.
✓ Branch 23 taken 10 times.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✓ Branch 26 taken 10 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 10 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 10 times.
12 allocate(attributes(5))
877
878 2 write(buffer, '(I0)') this%num_inputs
879 attributes(1) = onnx_attribute_type( &
880
6/12
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✓ Branch 11 taken 2 times.
✗ Branch 12 not taken.
2 name='num_inputs', type='int', val=trim(buffer))
881 2 write(buffer, '(I0)') this%num_outputs
882 attributes(2) = onnx_attribute_type( &
883
6/12
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✓ Branch 11 taken 2 times.
✗ Branch 12 not taken.
2 name='num_outputs', type='int', val=trim(buffer))
884 2 write(buffer, '(I0)') this%num_basis
885 attributes(3) = onnx_attribute_type( &
886
6/12
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✓ Branch 11 taken 2 times.
✗ Branch 12 not taken.
2 name='num_basis', type='int', val=trim(buffer))
887
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if(this%use_bias)then
888 2 buffer = '1'
889 else
890 buffer = '0'
891 end if
892 attributes(4) = onnx_attribute_type( &
893
6/12
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✓ Branch 11 taken 2 times.
✗ Branch 12 not taken.
2 name='use_bias', type='int', val=trim(buffer))
894 attributes(5) = onnx_attribute_type( &
895
6/12
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✓ Branch 11 taken 2 times.
✗ Branch 12 not taken.
2 name='activation', type='string', val=trim(this%activation%name))
896
897 2 end function get_attributes_ono
898 !###############################################################################
899
900
42/91
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 16 times.
✓ Branch 5 taken 17 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✓ Branch 36 taken 15 times.
✓ Branch 37 taken 2 times.
✗ Branch 38 not taken.
✓ Branch 39 taken 15 times.
✓ Branch 40 taken 16 times.
✗ Branch 41 not taken.
✓ Branch 42 taken 15 times.
✓ Branch 43 taken 16 times.
✓ Branch 44 taken 15 times.
✓ Branch 45 taken 31 times.
✗ Branch 46 not taken.
✓ Branch 47 taken 15 times.
✓ Branch 48 taken 18 times.
✓ Branch 49 taken 31 times.
✓ Branch 50 taken 2 times.
✓ Branch 51 taken 31 times.
✓ Branch 52 taken 2 times.
✓ Branch 53 taken 13 times.
✓ Branch 54 taken 4 times.
✓ Branch 55 taken 15 times.
✓ Branch 56 taken 2 times.
✓ Branch 57 taken 58 times.
✓ Branch 58 taken 15 times.
✓ Branch 59 taken 58 times.
✗ Branch 60 not taken.
✓ Branch 61 taken 58 times.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✓ Branch 64 taken 58 times.
✗ Branch 65 not taken.
✓ Branch 66 taken 58 times.
✗ Branch 67 not taken.
✓ Branch 68 taken 58 times.
✗ Branch 69 not taken.
✓ Branch 70 taken 58 times.
✓ Branch 71 taken 17 times.
✗ Branch 72 not taken.
✓ Branch 74 taken 17 times.
✗ Branch 75 not taken.
✓ Branch 77 taken 17 times.
✗ Branch 78 not taken.
✓ Branch 80 taken 17 times.
✓ Branch 81 taken 17 times.
✗ Branch 82 not taken.
✓ Branch 83 taken 17 times.
✗ Branch 84 not taken.
✓ Branch 85 taken 17 times.
✗ Branch 86 not taken.
✓ Branch 87 taken 17 times.
✗ Branch 88 not taken.
✓ Branch 89 taken 17 times.
✗ Branch 90 not taken.
✓ Branch 91 taken 17 times.
✗ Branch 92 not taken.
✓ Branch 93 taken 17 times.
338 end module athena__orthogonal_nop_block
901