russell_tensor 3.2.1

Tensor analysis, calculus, and functions for continuum mechanics
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
use crate::{ADD, SQRT_2};
use crate::{Tensor2, Tensor4};

/// Performs the underbar dyadic product between two Tensor2 resulting in a (general) Tensor4
///
/// Computes:
///
/// ```text
/// ADD: D += s A ⊗ B  or  SET: D = s A ⊗ B
///               ‾                     ‾
/// ```
///
/// With Cartesian components (example with SET):
///
/// ```text
/// Dᵢⱼₖₗ = s Aᵢₗ Bⱼₖ
/// ```
///
/// **Important:** The result is **not** necessarily minor-symmetric; therefore `D` is general.
///
/// # Output
///
/// * `dd` -- the tensor `D`
///
/// # Input
///
/// * `op` -- operation: ADD or SET
/// * `s` -- the multiplier
/// * `aa` -- first tensor
/// * `bb` -- second tensor
pub fn t2_udyad_t2<const N: usize>(dd: &mut Tensor4<9>, op: u8, s: f64, aa: &Tensor2<N>, bb: &Tensor2<N>) {
    t2_udyad_t2_vec::<N>(dd, op, s, aa.as_vec(), bb.as_vec());
}

/// Internal (unrolled) underbar dyadic product on raw Kelvin-Mandel vectors.
#[rustfmt::skip]
#[inline]
pub(crate) fn t2_udyad_t2_vec<const N:usize>(dd: &mut Tensor4<9>, op: u8, s: f64, a: &[f64; N], b: &[f64; N]) {
    let tsq2 = 2.0 * SQRT_2;
    if op == ADD {
        if N == 4 {
            dd.add(0, 0, s*a[0]*b[0]);
            dd.add(0, 1, s*(a[3]*b[3])/2.0);
            dd.add(0, 2, 0.0);
            dd.add(0, 3, s*(a[3]*b[0] + a[0]*b[3])/2.0);
            dd.add(0, 4, 0.0);
            dd.add(0, 5, 0.0);
            dd.add(0, 6, s*(a[3]*b[0] - a[0]*b[3])/2.0);
            dd.add(0, 7, 0.0);
            dd.add(0, 8, 0.0);

            dd.add(1, 0, s*(a[3]*b[3])/2.0);
            dd.add(1, 1, s*a[1]*b[1]);
            dd.add(1, 2, 0.0);
            dd.add(1, 3, s*(a[3]*b[1] + a[1]*b[3])/2.0);
            dd.add(1, 4, 0.0);
            dd.add(1, 5, 0.0);
            dd.add(1, 6, s*(-(a[3]*b[1]) + a[1]*b[3])/2.0);
            dd.add(1, 7, 0.0);
            dd.add(1, 8, 0.0);

            dd.add(2, 0, 0.0);
            dd.add(2, 1, 0.0);
            dd.add(2, 2, s*a[2]*b[2]);
            dd.add(2, 3, 0.0);
            dd.add(2, 4, 0.0);
            dd.add(2, 5, 0.0);
            dd.add(2, 6, 0.0);
            dd.add(2, 7, 0.0);
            dd.add(2, 8, 0.0);

            dd.add(3, 0, s*(a[3]*b[0] + a[0]*b[3])/2.0);
            dd.add(3, 1, s*(a[3]*b[1] + a[1]*b[3])/2.0);
            dd.add(3, 2, 0.0);
            dd.add(3, 3, s*(a[1]*b[0] + a[0]*b[1] + a[3]*b[3])/2.0);
            dd.add(3, 4, 0.0);
            dd.add(3, 5, 0.0);
            dd.add(3, 6, s*(a[1]*b[0] - a[0]*b[1])/2.0);
            dd.add(3, 7, 0.0);
            dd.add(3, 8, 0.0);

            dd.add(4, 0, 0.0);
            dd.add(4, 1, 0.0);
            dd.add(4, 2, 0.0);
            dd.add(4, 3, 0.0);
            dd.add(4, 4, s*(a[2]*b[1] + a[1]*b[2])/2.0);
            dd.add(4, 5, s*(a[3]*b[2] + a[2]*b[3])/tsq2);
            dd.add(4, 6, 0.0);
            dd.add(4, 7, s*(a[2]*b[1] - a[1]*b[2])/2.0);
            dd.add(4, 8, s*(-(a[3]*b[2]) + a[2]*b[3])/tsq2);

            dd.add(5, 0, 0.0);
            dd.add(5, 1, 0.0);
            dd.add(5, 2, 0.0);
            dd.add(5, 3, 0.0);
            dd.add(5, 4, s*(a[3]*b[2] + a[2]*b[3])/tsq2);
            dd.add(5, 5, s*(a[2]*b[0] + a[0]*b[2])/2.0);
            dd.add(5, 6, 0.0);
            dd.add(5, 7, s*(-(a[3]*b[2]) + a[2]*b[3])/tsq2);
            dd.add(5, 8, s*(a[2]*b[0] - a[0]*b[2])/2.0);

            dd.add(6, 0, s*(-(a[3]*b[0]) + a[0]*b[3])/2.0);
            dd.add(6, 1, s*(a[3]*b[1] - a[1]*b[3])/2.0);
            dd.add(6, 2, 0.0);
            dd.add(6, 3, s*(-(a[1]*b[0]) + a[0]*b[1])/2.0);
            dd.add(6, 4, 0.0);
            dd.add(6, 5, 0.0);
            dd.add(6, 6, s*(-(a[1]*b[0]) - a[0]*b[1] + a[3]*b[3])/2.0);
            dd.add(6, 7, 0.0);
            dd.add(6, 8, 0.0);

            dd.add(7, 0, 0.0);
            dd.add(7, 1, 0.0);
            dd.add(7, 2, 0.0);
            dd.add(7, 3, 0.0);
            dd.add(7, 4, s*(-(a[2]*b[1]) + a[1]*b[2])/2.0);
            dd.add(7, 5, s*(a[3]*b[2] - a[2]*b[3])/tsq2);
            dd.add(7, 6, 0.0);
            dd.add(7, 7, s*(-(a[2]*b[1]) - a[1]*b[2])/2.0);
            dd.add(7, 8, s*(-(a[3]*b[2] + a[2]*b[3])/tsq2));

            dd.add(8, 0, 0.0);
            dd.add(8, 1, 0.0);
            dd.add(8, 2, 0.0);
            dd.add(8, 3, 0.0);
            dd.add(8, 4, s*(a[3]*b[2] - a[2]*b[3])/tsq2);
            dd.add(8, 5, s*(-(a[2]*b[0]) + a[0]*b[2])/2.0);
            dd.add(8, 6, 0.0);
            dd.add(8, 7, s*(-(a[3]*b[2] + a[2]*b[3])/tsq2));
            dd.add(8, 8, s*(-(a[2]*b[0]) - a[0]*b[2])/2.0);
        } else if N == 6 {
            dd.add(0, 0, s*a[0]*b[0]);
            dd.add(0, 1, s*(a[3]*b[3])/2.0);
            dd.add(0, 2, s*(a[5]*b[5])/2.0);
            dd.add(0, 3, s*(a[3]*b[0] + a[0]*b[3])/2.0);
            dd.add(0, 4, s*(a[5]*b[3] + a[3]*b[5])/tsq2);
            dd.add(0, 5, s*(a[5]*b[0] + a[0]*b[5])/2.0);
            dd.add(0, 6, s*(a[3]*b[0] - a[0]*b[3])/2.0);
            dd.add(0, 7, s*(a[5]*b[3] - a[3]*b[5])/tsq2);
            dd.add(0, 8, s*(a[5]*b[0] - a[0]*b[5])/2.0);

            dd.add(1, 0, s*(a[3]*b[3])/2.0);
            dd.add(1, 1, s*a[1]*b[1]);
            dd.add(1, 2, s*(a[4]*b[4])/2.0);
            dd.add(1, 3, s*(a[3]*b[1] + a[1]*b[3])/2.0);
            dd.add(1, 4, s*(a[4]*b[1] + a[1]*b[4])/2.0);
            dd.add(1, 5, s*(a[4]*b[3] + a[3]*b[4])/tsq2);
            dd.add(1, 6, s*(-(a[3]*b[1]) + a[1]*b[3])/2.0);
            dd.add(1, 7, s*(a[4]*b[1] - a[1]*b[4])/2.0);
            dd.add(1, 8, s*(a[4]*b[3] - a[3]*b[4])/tsq2);

            dd.add(2, 0, s*(a[5]*b[5])/2.0);
            dd.add(2, 1, s*(a[4]*b[4])/2.0);
            dd.add(2, 2, s*a[2]*b[2]);
            dd.add(2, 3, s*(a[ 5]*b[4] + a[4]*b[5])/tsq2);
            dd.add(2, 4, s*(a[4]*b[2] + a[2]*b[4])/2.0);
            dd.add(2, 5, s*(a[5]*b[2] + a[2]*b[5])/2.0);
            dd.add(2, 6, s*(-(a[5]*b[4]) + a[4]*b[5])/tsq2);
            dd.add(2, 7, s*(-(a[4]*b[2]) + a[2]*b[4])/2.0);
            dd.add(2, 8, s*(-(a[5]*b[2]) + a[2]*b[5])/2.0);

            dd.add(3, 0, s*(a[3]*b[0] + a[0]*b[3])/2.0);
            dd.add(3, 1, s*(a[3]*b[1] + a[1]*b[3])/2.0);
            dd.add(3, 2, s*(a[5]*b[4] + a[4]*b[5])/tsq2);
            dd.add(3, 3, s*(a[1]*b[0] + a[0]*b[1] + a[3]*b[3])/2.0);
            dd.add(3, 4, s*(SQRT_2*a[5]*b[1] + a[4]*b[3] + a[3]*b[4] + SQRT_2*a[1]*b[5])/4.0);
            dd.add(3, 5, s*(SQRT_2*a[4]*b[0] + a[5]*b[3] + SQRT_2*a[0]*b[4] + a[3]*b[5])/4.0);
            dd.add(3, 6, s*(a[1]*b[0] - a[0]*b[1])/2.0);
            dd.add(3, 7, s*(SQRT_2*a[5]*b[1] + a[4]*b[3] - a[3]*b[4] - SQRT_2*a[1]*b[5])/4.0);
            dd.add(3, 8, s*(SQRT_2*a[4]*b[0] + a[5]*b[3] - SQRT_2*a[0]*b[4] - a[3]*b[5])/4.0);

            dd.add(4, 0, s*(a[5]*b[3] + a[3]*b[5])/tsq2);
            dd.add(4, 1, s*(a[4]*b[1] + a[1]*b[4])/2.0);
            dd.add(4, 2, s*(a[4]*b[2] + a[2]*b[4])/2.0);
            dd.add(4, 3, s*(SQRT_2*a[5]*b[1] + a[4]*b[3] + a[3]*b[4] + SQRT_2*a[1]*b[5])/4.0);
            dd.add(4, 4, s*(a[2]*b[1] + a[1]*b[2] + a[4]*b[4])/2.0);
            dd.add(4, 5, s*(SQRT_2*a[3]*b[2] + SQRT_2*a[2]*b[3] + a[5]*b[4] + a[4]*b[5])/4.0);
            dd.add(4, 6, s*(-(SQRT_2*a[5]*b[1]) + a[4]*b[3] - a[3]*b[4] + SQRT_2*a[1]*b[5])/4.0);
            dd.add(4, 7, s*(a[2]*b[1] - a[1]*b[2])/2.0);
            dd.add(4, 8, s*(-(SQRT_2*a[3]*b[2]) + SQRT_2*a[2]*b[3] - a[5]*b[4] + a[4]*b[5])/4.0);

            dd.add(5, 0, s*(a[5]*b[0] + a[0]*b[5])/2.0);
            dd.add(5, 1, s*(a[4]*b[3] + a[3]*b[4])/tsq2);
            dd.add(5, 2, s*(a[5]*b[2] + a[2]*b[5])/2.0);
            dd.add(5, 3, s*(SQRT_2*a[4]*b[0] + a[5]*b[3] + SQRT_2*a[0]*b[4] + a[3]*b[5])/4.0);
            dd.add(5, 4, s*(SQRT_2*a[3]*b[2] + SQRT_2*a[2]*b[3] + a[5]*b[4] + a[4]*b[5])/4.0);
            dd.add(5, 5, s*(a[2]*b[0] + a[0]*b[2] + a[5]*b[5])/2.0);
            dd.add(5, 6, s*(SQRT_2*a[4]*b[0] - a[5]*b[3] - SQRT_2*a[0]*b[4] + a[3]*b[5])/4.0);
            dd.add(5, 7, s*(-(SQRT_2*a[3]*b[2]) + SQRT_2*a[2]*b[3] + a[5]*b[4] - a[4]*b[5])/4.0);
            dd.add(5, 8, s*(a[2]*b[0] - a[0]*b[2])/2.0);

            dd.add(6, 0, s*(-(a[3]*b[0]) + a[0]*b[3])/2.0);
            dd.add(6, 1, s*(a[3]*b[1] - a[1]*b[3])/2.0);
            dd.add(6, 2, s*(a[5]*b[4] - a[4]*b[5])/tsq2);
            dd.add(6, 3, s*(-(a[1]*b[0]) + a[0]*b[1])/2.0);
            dd.add(6, 4, s*(SQRT_2*a[5]*b[1] - a[4]*b[3] + a[3]*b[4] - SQRT_2*a[1]*b[5])/4.0);
            dd.add(6, 5, s*(-(SQRT_2*a[4]*b[0]) + a[5]*b[3] + SQRT_2*a[0]*b[4] - a[3]*b[5])/4.0);
            dd.add(6, 6, s*(-(a[1]*b[0]) - a[0]*b[1] + a[3]*b[3])/2.0);
            dd.add(6, 7, s*(SQRT_2*a[5]*b[1] - a[4]*b[3] - a[3]*b[4] + SQRT_2*a[1]*b[5])/4.0);
            dd.add(6, 8, s*(-(SQRT_2*a[4]*b[0]) + a[5]*b[3] - SQRT_2*a[0]*b[4] + a[3]*b[5])/4.0);

            dd.add(7, 0, s*(-(a[5]*b[3]) + a[3]*b[5])/tsq2);
            dd.add(7, 1, s*(-(a[4]*b[1]) + a[1]*b[4])/2.0);
            dd.add(7, 2, s*(a[4]*b[2] - a[2]*b[4])/2.0);
            dd.add(7, 3, s*(-(SQRT_2*a[5]*b[1]) - a[4]*b[3] + a[3]*b[4] + SQRT_2*a[1]*b[5])/4.0);
            dd.add(7, 4, s*(-(a[2]*b[1]) + a[1]*b[2])/2.0);
            dd.add(7, 5, s*(SQRT_2*a[3]*b[2] - SQRT_2*a[2]*b[3] - a[5]*b[4] + a[4]*b[5])/4.0);
            dd.add(7, 6, s*(SQRT_2*a[5]*b[1] - a[4]*b[3] - a[3]*b[4] + SQRT_2*a[1]*b[5])/4.0);
            dd.add(7, 7, s*(-(a[2]*b[1]) - a[1]*b[2] + a[4]*b[4])/2.0);
            dd.add(7, 8, s*(-(SQRT_2*a[3]*b[2]) - SQRT_2*a[2]*b[3] + a[5]*b[4] + a[4]*b[5])/4.0);

            dd.add(8, 0, s*(-(a[5]*b[0]) + a[0]*b[5])/2.0);
            dd.add(8, 1, s*(-(a[4]*b[3]) + a[3]*b[4])/tsq2);
            dd.add(8, 2, s*(a[5]*b[2] - a[2]*b[5])/2.0);
            dd.add(8, 3, s*(-(SQRT_2*a[4]*b[0]) - a[5]*b[3] + SQRT_2*a[0]*b[4] + a[3]*b[5])/4.0);
            dd.add(8, 4, s*(SQRT_2*a[3]*b[2] - SQRT_2*a[2]*b[3] + a[5]*b[4] - a[4]*b[5])/4.0);
            dd.add(8, 5, s*(-(a[2]*b[0]) + a[0]*b[2])/2.0);
            dd.add(8, 6, s*(-(SQRT_2*a[4]*b[0]) + a[5]*b[3] - SQRT_2*a[0]*b[4] + a[3]*b[5])/4.0);
            dd.add(8, 7, s*(-(SQRT_2*a[3]*b[2]) - SQRT_2*a[2]*b[3] + a[5]*b[4] + a[4]*b[5])/4.0);
            dd.add(8, 8, s*(-(a[2]*b[0]) - a[0]*b[2] + a[5]*b[5])/2.0);
        } else {
            debug_assert!(N == 9);

            dd.add(0, 0, s*a[0]*b[0]);
            dd.add(0, 1, s*((a[3] + a[6])*(b[3] + b[6]))/2.0);
            dd.add(0, 2, s*((a[5] + a[8])*(b[5] + b[8]))/2.0);
            dd.add(0, 3, s*(a[3]*b[0] + a[6]*b[0] + a[0]*(b[3] + b[6]))/2.0);
            dd.add(0, 4, s*((a[5] + a[8])*(b[3] + b[6]) + (a[3] + a[6])*(b[5] + b[8]))/tsq2);
            dd.add(0, 5, s*(a[5]*b[0] + a[8]*b[0] + a[0]*(b[5] + b[8]))/2.0);
            dd.add(0, 6, s*(a[3]*b[0] + a[6]*b[0] - a[0]*(b[3] + b[6]))/2.0);
            dd.add(0, 7, s*((a[5] + a[8])*(b[3] + b[6]) - (a[3] + a[6])*(b[5] + b[8]))/tsq2);
            dd.add(0, 8, s*(a[5]*b[0] + a[8]*b[0] - a[0]*(b[5] + b[8]))/2.0);

            dd.add(1, 0, s*((a[3] - a[6])*(b[3] - b[6]))/2.0);
            dd.add(1, 1, s*a[1]*b[1]);
            dd.add(1, 2, s*((a[4] + a[7])*(b[4] + b[7]))/2.0);
            dd.add(1, 3, s*(a[3]*b[1] - a[6]*b[1] + a[1]*(b[3] - b[6]))/2.0);
            dd.add(1, 4, s*(a[4]*b[1] + a[7]*b[1] + a[1]*(b[4] + b[7]))/2.0);
            dd.add(1, 5, s*((a[4] + a[7])*(b[3] - b[6]) + (a[3] - a[6])*(b[4] + b[7]))/tsq2);
            dd.add(1, 6, s*(-(a[3]*b[1]) + a[6]*b[1] + a[1]*(b[3] - b[6]))/2.0);
            dd.add(1, 7, s*(a[4]*b[1] + a[7]*b[1] - a[1]*(b[4] + b[7]))/2.0);
            dd.add(1, 8, s*((a[4] + a[7])*(b[3] - b[6]) - (a[3] - a[6])*(b[4] + b[7]))/tsq2);

            dd.add(2, 0, s*((a[5] - a[8])*(b[5] - b[8]))/2.0);
            dd.add(2, 1, s*((a[4] - a[7])*(b[4] - b[7]))/2.0);
            dd.add(2, 2, s*a[2]*b[2]);
            dd.add(2, 3, s*((a[5] - a[8])*(b[4] - b[7]) + (a[4] - a[7])*(b[5] - b[8]))/tsq2);
            dd.add(2, 4, s*(a[4]*b[2] - a[7]*b[2] + a[2]*(b[4] - b[7]))/2.0);
            dd.add(2, 5, s*(a[5]*b[2] - a[8]*b[2] + a[2]*(b[5] - b[8]))/2.0);
            dd.add(2, 6, s*(-((a[5] - a[8])*(b[4] - b[7])) + (a[4] - a[7])*(b[5] - b[8]))/tsq2);
            dd.add(2, 7, s*(-(a[4]*b[2]) + a[7]*b[2] + a[2]*(b[4] - b[7]))/2.0);
            dd.add(2, 8, s*(-(a[5]*b[2]) + a[8]*b[2] + a[2]*(b[5] - b[8]))/2.0);

            dd.add(3, 0, s*(a[3]*b[0] - a[6]*b[0] + a[0]*(b[3] - b[6]))/2.0);
            dd.add(3, 1, s*(a[3]*b[1] + a[6]*b[1] + a[1]*(b[3] + b[6]))/2.0);
            dd.add(3, 2, s*((a[5] + a[8])*(b[4] + b[7]) + (a[4] + a[7])*(b[5] + b[8]))/tsq2);
            dd.add(3, 3, s*(a[1]*b[0] + a[0]*b[1] + a[3]*b[3] - a[6]*b[6])/2.0);
            dd.add(3, 4, s*(SQRT_2*(a[5] + a[8])*b[1] + (a[4] + a[7])*(b[3] + b[6]) + (a[3] + a[6])*(b[4] + b[7]) + SQRT_2*a[1]*(b[5] + b[8]))/4.0);
            dd.add(3, 5, s*(SQRT_2*(a[4] + a[7])*b[0] + (a[5] + a[8])*(b[3] - b[6]) + SQRT_2*a[0]*(b[4] + b[7]) + (a[3] - a[6])*(b[5] + b[8]))/4.0);
            dd.add(3, 6, s*(a[1]*b[0] - a[0]*b[1] + a[6]*b[3] - a[3]*b[6])/2.0);
            dd.add(3, 7, s*(SQRT_2*(a[5] + a[8])*b[1] + (a[4] + a[7])*(b[3] + b[6]) - (a[3] + a[6])*(b[4] + b[7]) - SQRT_2*a[1]*(b[5] + b[8]))/4.0);
            dd.add(3, 8, s*(SQRT_2*(a[4] + a[7])*b[0] + (a[5] + a[8])*(b[3] - b[6]) - SQRT_2*a[0]*(b[4] + b[7]) - (a[3] - a[6])*(b[5] + b[8]))/4.0);

            dd.add(4, 0, s*((a[5] - a[8])*(b[3] - b[6]) + (a[3] - a[6])*(b[5] - b[8]))/tsq2);
            dd.add(4, 1, s*(a[4]*b[1] - a[7]*b[1] + a[1]*(b[4] - b[7]))/2.0);
            dd.add(4, 2, s*(a[4]*b[2] + a[7]*b[2] + a[2]*(b[4] + b[7]))/2.0);
            dd.add(4, 3, s*(SQRT_2*(a[5] - a[8])*b[1] + (a[4] - a[7])*(b[3] - b[6]) + (a[3] - a[6])*(b[4] - b[7]) + SQRT_2*a[1]*(b[5] - b[8]))/4.0);
            dd.add(4, 4, s*(a[2]*b[1] + a[1]*b[2] + a[4]*b[4] - a[7]*b[7])/2.0);
            dd.add(4, 5, s*(SQRT_2*(a[3] - a[6])*b[2] + SQRT_2*a[2]*(b[3] - b[6]) + (a[5] - a[8])*(b[4] + b[7]) + (a[4] + a[7])*(b[5] - b[8]))/4.0);
            dd.add(4, 6, s*(-(SQRT_2*(a[5] - a[8])*b[1]) + (a[4] - a[7])*(b[3] - b[6]) - (a[3] - a[6])*(b[4] - b[7]) + SQRT_2*a[1]*(b[5] - b[8]))/4.0);
            dd.add(4, 7, s*(a[2]*b[1] - a[1]*b[2] + a[7]*b[4] - a[4]*b[7])/2.0);
            dd.add(4, 8, s*(-(SQRT_2*(a[3] - a[6])*b[2]) + SQRT_2*a[2]*(b[3] - b[6]) - (a[5] - a[8])*(b[4] + b[7]) + (a[4] + a[7])*(b[5] - b[8]))/4.0);

            dd.add(5, 0, s*(a[5]*b[0] - a[8]*b[0] + a[0]*(b[5] - b[8]))/2.0);
            dd.add(5, 1, s*((a[4] - a[7])*(b[3] + b[6]) + (a[3] + a[6])*(b[4] - b[7]))/tsq2);
            dd.add(5, 2, s*(a[5]*b[2] + a[8]*b[2] + a[2]*(b[5] + b[8]))/2.0);
            dd.add(5, 3, s*(SQRT_2*(a[4] - a[7])*b[0] + (a[5] - a[8])*(b[3] + b[6]) + SQRT_2*a[0]*(b[4] - b[7]) + (a[3] + a[6])*(b[5] - b[8]))/4.0);
            dd.add(5, 4, s*(SQRT_2*(a[3] + a[6])*b[2] + SQRT_2*a[2]*(b[3] + b[6]) + (a[5] + a[8])*(b[4] - b[7]) + (a[4] - a[7])*(b[5] + b[8]))/4.0);
            dd.add(5, 5, s*(a[2]*b[0] + a[0]*b[2] + a[5]*b[5] - a[8]*b[8])/2.0);
            dd.add(5, 6, s*(SQRT_2*(a[4] - a[7])*b[0] - (a[5] - a[8])*(b[3] + b[6]) - SQRT_2*a[0]*(b[4] - b[7]) + (a[3] + a[6])*(b[5] - b[8]))/4.0);
            dd.add(5, 7, s*(-(SQRT_2*(a[3] + a[6])*b[2]) + SQRT_2*a[2]*(b[3] + b[6]) + (a[5] + a[8])*(b[4] - b[7]) - (a[4] - a[7])*(b[5] + b[8]))/4.0);
            dd.add(5, 8, s*(a[2]*b[0] - a[0]*b[2] + a[8]*b[5] - a[5]*b[8])/2.0);

            dd.add(6, 0, s*(-(a[3]*b[0]) + a[6]*b[0] + a[0]*(b[3] - b[6]))/2.0);
            dd.add(6, 1, s*(a[3]*b[1] + a[6]*b[1] - a[1]*(b[3] + b[6]))/2.0);
            dd.add(6, 2, s*((a[5] + a[8])*(b[4] + b[7]) - (a[4] + a[7])*(b[5] + b[8]))/tsq2);
            dd.add(6, 3, s*(-(a[1]*b[0]) + a[0]*b[1] + a[6]*b[3] - a[3]*b[6])/2.0);
            dd.add(6, 4, s*(SQRT_2*(a[5] + a[8])*b[1] - (a[4] + a[7])*(b[3] + b[6]) + (a[3] + a[6])*(b[4] + b[7]) - SQRT_2*a[1]*(b[5] + b[8]))/4.0);
            dd.add(6, 5, s*(-(SQRT_2*(a[4] + a[7])*b[0]) + (a[5] + a[8])*(b[3] - b[6]) + SQRT_2*a[0]*(b[4] + b[7]) - (a[3] - a[6])*(b[5] + b[8]))/4.0);
            dd.add(6, 6, s*(-(a[1]*b[0]) - a[0]*b[1] + a[3]*b[3] - a[6]*b[6])/2.0);
            dd.add(6, 7, s*(SQRT_2*(a[5] + a[8])*b[1] - (a[4] + a[7])*(b[3] + b[6]) - (a[3] + a[6])*(b[4] + b[7]) + SQRT_2*a[1]*(b[5] + b[8]))/4.0);
            dd.add(6, 8, s*(-(SQRT_2*(a[4] + a[7])*b[0]) + (a[5] + a[8])*(b[3] - b[6]) - SQRT_2*a[0]*(b[4] + b[7]) + (a[3] - a[6])*(b[5] + b[8]))/4.0);

            dd.add(7, 0, s*(-((a[5] - a[8])*(b[3] - b[6])) + (a[3] - a[6])*(b[5] - b[8]))/tsq2);
            dd.add(7, 1, s*(-(a[4]*b[1]) + a[7]*b[1] + a[1]*(b[4] - b[7]))/2.0);
            dd.add(7, 2, s*(a[4]*b[2] + a[7]*b[2] - a[2]*(b[4] + b[7]))/2.0);
            dd.add(7, 3, s*(-(SQRT_2*(a[5] - a[8])*b[1]) - (a[4] - a[7])*(b[3] - b[6]) + (a[3] - a[6])*(b[4] - b[7]) + SQRT_2*a[1]*(b[5] - b[8]))/4.0);
            dd.add(7, 4, s*(-(a[2]*b[1]) + a[1]*b[2] + a[7]*b[4] - a[4]*b[7])/2.0);
            dd.add(7, 5, s*(SQRT_2*(a[3] - a[6])*b[2] - SQRT_2*a[2]*(b[3] - b[6]) - (a[5] - a[8])*(b[4] + b[7]) + (a[4] + a[7])*(b[5] - b[8]))/4.0);
            dd.add(7, 6, s*(SQRT_2*(a[5] - a[8])*b[1] - (a[4] - a[7])*(b[3] - b[6]) - (a[3] - a[6])*(b[4] - b[7]) + SQRT_2*a[1]*(b[5] - b[8]))/4.0);
            dd.add(7, 7, s*(-(a[2]*b[1]) - a[1]*b[2] + a[4]*b[4] - a[7]*b[7])/2.0);
            dd.add(7, 8, s*(-(SQRT_2*(a[3] - a[6])*b[2]) - SQRT_2*a[2]*(b[3] - b[6]) + (a[5] - a[8])*(b[4] + b[7]) + (a[4] + a[7])*(b[5] - b[8]))/4.0);

            dd.add(8, 0, s*(-(a[5]*b[0]) + a[8]*b[0] + a[0]*(b[5] - b[8]))/2.0);
            dd.add(8, 1, s*(-((a[4] - a[7])*(b[3] + b[6])) + (a[3] + a[6])*(b[4] - b[7]))/tsq2);
            dd.add(8, 2, s*(a[5]*b[2] + a[8]*b[2] - a[2]*(b[5] + b[8]))/2.0);
            dd.add(8, 3, s*(-(SQRT_2*(a[4] - a[7])*b[0]) - (a[5] - a[8])*(b[3] + b[6]) + SQRT_2*a[0]*(b[4] - b[7]) + (a[3] + a[6])*(b[5] - b[8]))/4.0);
            dd.add(8, 4, s*(SQRT_2*(a[3] + a[6])*b[2] - SQRT_2*a[2]*(b[3] + b[6]) + (a[5] + a[8])*(b[4] - b[7]) - (a[4] - a[7])*(b[5] + b[8]))/4.0);
            dd.add(8, 5, s*(-(a[2]*b[0]) + a[0]*b[2] + a[8]*b[5] - a[5]*b[8])/2.0);
            dd.add(8, 6, s*(-(SQRT_2*(a[4] - a[7])*b[0]) + (a[5] - a[8])*(b[3] + b[6]) - SQRT_2*a[0]*(b[4] - b[7]) + (a[3] + a[6])*(b[5] - b[8]))/4.0);
            dd.add(8, 7, s*(-(SQRT_2*(a[3] + a[6])*b[2]) - SQRT_2*a[2]*(b[3] + b[6]) + (a[5] + a[8])*(b[4] - b[7]) + (a[4] - a[7])*(b[5] + b[8]))/4.0);
            dd.add(8, 8, s*(-(a[2]*b[0]) - a[0]*b[2] + a[5]*b[5] - a[8]*b[8])/2.0);
        }
    } else {
        if N == 4 {
            dd.set(0, 0, s*a[0]*b[0]);
            dd.set(0, 1, s*(a[3]*b[3])/2.0);
            dd.set(0, 2, 0.0);
            dd.set(0, 3, s*(a[3]*b[0] + a[0]*b[3])/2.0);
            dd.set(0, 4, 0.0);
            dd.set(0, 5, 0.0);
            dd.set(0, 6, s*(a[3]*b[0] - a[0]*b[3])/2.0);
            dd.set(0, 7, 0.0);
            dd.set(0, 8, 0.0);

            dd.set(1, 0, s*(a[3]*b[3])/2.0);
            dd.set(1, 1, s*a[1]*b[1]);
            dd.set(1, 2, 0.0);
            dd.set(1, 3, s*(a[3]*b[1] + a[1]*b[3])/2.0);
            dd.set(1, 4, 0.0);
            dd.set(1, 5, 0.0);
            dd.set(1, 6, s*(-(a[3]*b[1]) + a[1]*b[3])/2.0);
            dd.set(1, 7, 0.0);
            dd.set(1, 8, 0.0);

            dd.set(2, 0, 0.0);
            dd.set(2, 1, 0.0);
            dd.set(2, 2, s*a[2]*b[2]);
            dd.set(2, 3, 0.0);
            dd.set(2, 4, 0.0);
            dd.set(2, 5, 0.0);
            dd.set(2, 6, 0.0);
            dd.set(2, 7, 0.0);
            dd.set(2, 8, 0.0);

            dd.set(3, 0, s*(a[3]*b[0] + a[0]*b[3])/2.0);
            dd.set(3, 1, s*(a[3]*b[1] + a[1]*b[3])/2.0);
            dd.set(3, 2, 0.0);
            dd.set(3, 3, s*(a[1]*b[0] + a[0]*b[1] + a[3]*b[3])/2.0);
            dd.set(3, 4, 0.0);
            dd.set(3, 5, 0.0);
            dd.set(3, 6, s*(a[1]*b[0] - a[0]*b[1])/2.0);
            dd.set(3, 7, 0.0);
            dd.set(3, 8, 0.0);

            dd.set(4, 0, 0.0);
            dd.set(4, 1, 0.0);
            dd.set(4, 2, 0.0);
            dd.set(4, 3, 0.0);
            dd.set(4, 4, s*(a[2]*b[1] + a[1]*b[2])/2.0);
            dd.set(4, 5, s*(a[3]*b[2] + a[2]*b[3])/tsq2);
            dd.set(4, 6, 0.0);
            dd.set(4, 7, s*(a[2]*b[1] - a[1]*b[2])/2.0);
            dd.set(4, 8, s*(-(a[3]*b[2]) + a[2]*b[3])/tsq2);

            dd.set(5, 0, 0.0);
            dd.set(5, 1, 0.0);
            dd.set(5, 2, 0.0);
            dd.set(5, 3, 0.0);
            dd.set(5, 4, s*(a[3]*b[2] + a[2]*b[3])/tsq2);
            dd.set(5, 5, s*(a[2]*b[0] + a[0]*b[2])/2.0);
            dd.set(5, 6, 0.0);
            dd.set(5, 7, s*(-(a[3]*b[2]) + a[2]*b[3])/tsq2);
            dd.set(5, 8, s*(a[2]*b[0] - a[0]*b[2])/2.0);

            dd.set(6, 0, s*(-(a[3]*b[0]) + a[0]*b[3])/2.0);
            dd.set(6, 1, s*(a[3]*b[1] - a[1]*b[3])/2.0);
            dd.set(6, 2, 0.0);
            dd.set(6, 3, s*(-(a[1]*b[0]) + a[0]*b[1])/2.0);
            dd.set(6, 4, 0.0);
            dd.set(6, 5, 0.0);
            dd.set(6, 6, s*(-(a[1]*b[0]) - a[0]*b[1] + a[3]*b[3])/2.0);
            dd.set(6, 7, 0.0);
            dd.set(6, 8, 0.0);

            dd.set(7, 0, 0.0);
            dd.set(7, 1, 0.0);
            dd.set(7, 2, 0.0);
            dd.set(7, 3, 0.0);
            dd.set(7, 4, s*(-(a[2]*b[1]) + a[1]*b[2])/2.0);
            dd.set(7, 5, s*(a[3]*b[2] - a[2]*b[3])/tsq2);
            dd.set(7, 6, 0.0);
            dd.set(7, 7, s*(-(a[2]*b[1]) - a[1]*b[2])/2.0);
            dd.set(7, 8, s*(-(a[3]*b[2] + a[2]*b[3])/tsq2));

            dd.set(8, 0, 0.0);
            dd.set(8, 1, 0.0);
            dd.set(8, 2, 0.0);
            dd.set(8, 3, 0.0);
            dd.set(8, 4, s*(a[3]*b[2] - a[2]*b[3])/tsq2);
            dd.set(8, 5, s*(-(a[2]*b[0]) + a[0]*b[2])/2.0);
            dd.set(8, 6, 0.0);
            dd.set(8, 7, s*(-(a[3]*b[2] + a[2]*b[3])/tsq2));
            dd.set(8, 8, s*(-(a[2]*b[0]) - a[0]*b[2])/2.0);
        } else if N == 6 {
            dd.set(0, 0, s*a[0]*b[0]);
            dd.set(0, 1, s*(a[3]*b[3])/2.0);
            dd.set(0, 2, s*(a[5]*b[5])/2.0);
            dd.set(0, 3, s*(a[3]*b[0] + a[0]*b[3])/2.0);
            dd.set(0, 4, s*(a[5]*b[3] + a[3]*b[5])/tsq2);
            dd.set(0, 5, s*(a[5]*b[0] + a[0]*b[5])/2.0);
            dd.set(0, 6, s*(a[3]*b[0] - a[0]*b[3])/2.0);
            dd.set(0, 7, s*(a[5]*b[3] - a[3]*b[5])/tsq2);
            dd.set(0, 8, s*(a[5]*b[0] - a[0]*b[5])/2.0);

            dd.set(1, 0, s*(a[3]*b[3])/2.0);
            dd.set(1, 1, s*a[1]*b[1]);
            dd.set(1, 2, s*(a[4]*b[4])/2.0);
            dd.set(1, 3, s*(a[3]*b[1] + a[1]*b[3])/2.0);
            dd.set(1, 4, s*(a[4]*b[1] + a[1]*b[4])/2.0);
            dd.set(1, 5, s*(a[4]*b[3] + a[3]*b[4])/tsq2);
            dd.set(1, 6, s*(-(a[3]*b[1]) + a[1]*b[3])/2.0);
            dd.set(1, 7, s*(a[4]*b[1] - a[1]*b[4])/2.0);
            dd.set(1, 8, s*(a[4]*b[3] - a[3]*b[4])/tsq2);

            dd.set(2, 0, s*(a[5]*b[5])/2.0);
            dd.set(2, 1, s*(a[4]*b[4])/2.0);
            dd.set(2, 2, s*a[2]*b[2]);
            dd.set(2, 3, s*(a[ 5]*b[4] + a[4]*b[5])/tsq2);
            dd.set(2, 4, s*(a[4]*b[2] + a[2]*b[4])/2.0);
            dd.set(2, 5, s*(a[5]*b[2] + a[2]*b[5])/2.0);
            dd.set(2, 6, s*(-(a[5]*b[4]) + a[4]*b[5])/tsq2);
            dd.set(2, 7, s*(-(a[4]*b[2]) + a[2]*b[4])/2.0);
            dd.set(2, 8, s*(-(a[5]*b[2]) + a[2]*b[5])/2.0);

            dd.set(3, 0, s*(a[3]*b[0] + a[0]*b[3])/2.0);
            dd.set(3, 1, s*(a[3]*b[1] + a[1]*b[3])/2.0);
            dd.set(3, 2, s*(a[5]*b[4] + a[4]*b[5])/tsq2);
            dd.set(3, 3, s*(a[1]*b[0] + a[0]*b[1] + a[3]*b[3])/2.0);
            dd.set(3, 4, s*(SQRT_2*a[5]*b[1] + a[4]*b[3] + a[3]*b[4] + SQRT_2*a[1]*b[5])/4.0);
            dd.set(3, 5, s*(SQRT_2*a[4]*b[0] + a[5]*b[3] + SQRT_2*a[0]*b[4] + a[3]*b[5])/4.0);
            dd.set(3, 6, s*(a[1]*b[0] - a[0]*b[1])/2.0);
            dd.set(3, 7, s*(SQRT_2*a[5]*b[1] + a[4]*b[3] - a[3]*b[4] - SQRT_2*a[1]*b[5])/4.0);
            dd.set(3, 8, s*(SQRT_2*a[4]*b[0] + a[5]*b[3] - SQRT_2*a[0]*b[4] - a[3]*b[5])/4.0);

            dd.set(4, 0, s*(a[5]*b[3] + a[3]*b[5])/tsq2);
            dd.set(4, 1, s*(a[4]*b[1] + a[1]*b[4])/2.0);
            dd.set(4, 2, s*(a[4]*b[2] + a[2]*b[4])/2.0);
            dd.set(4, 3, s*(SQRT_2*a[5]*b[1] + a[4]*b[3] + a[3]*b[4] + SQRT_2*a[1]*b[5])/4.0);
            dd.set(4, 4, s*(a[2]*b[1] + a[1]*b[2] + a[4]*b[4])/2.0);
            dd.set(4, 5, s*(SQRT_2*a[3]*b[2] + SQRT_2*a[2]*b[3] + a[5]*b[4] + a[4]*b[5])/4.0);
            dd.set(4, 6, s*(-(SQRT_2*a[5]*b[1]) + a[4]*b[3] - a[3]*b[4] + SQRT_2*a[1]*b[5])/4.0);
            dd.set(4, 7, s*(a[2]*b[1] - a[1]*b[2])/2.0);
            dd.set(4, 8, s*(-(SQRT_2*a[3]*b[2]) + SQRT_2*a[2]*b[3] - a[5]*b[4] + a[4]*b[5])/4.0);

            dd.set(5, 0, s*(a[5]*b[0] + a[0]*b[5])/2.0);
            dd.set(5, 1, s*(a[4]*b[3] + a[3]*b[4])/tsq2);
            dd.set(5, 2, s*(a[5]*b[2] + a[2]*b[5])/2.0);
            dd.set(5, 3, s*(SQRT_2*a[4]*b[0] + a[5]*b[3] + SQRT_2*a[0]*b[4] + a[3]*b[5])/4.0);
            dd.set(5, 4, s*(SQRT_2*a[3]*b[2] + SQRT_2*a[2]*b[3] + a[5]*b[4] + a[4]*b[5])/4.0);
            dd.set(5, 5, s*(a[2]*b[0] + a[0]*b[2] + a[5]*b[5])/2.0);
            dd.set(5, 6, s*(SQRT_2*a[4]*b[0] - a[5]*b[3] - SQRT_2*a[0]*b[4] + a[3]*b[5])/4.0);
            dd.set(5, 7, s*(-(SQRT_2*a[3]*b[2]) + SQRT_2*a[2]*b[3] + a[5]*b[4] - a[4]*b[5])/4.0);
            dd.set(5, 8, s*(a[2]*b[0] - a[0]*b[2])/2.0);

            dd.set(6, 0, s*(-(a[3]*b[0]) + a[0]*b[3])/2.0);
            dd.set(6, 1, s*(a[3]*b[1] - a[1]*b[3])/2.0);
            dd.set(6, 2, s*(a[5]*b[4] - a[4]*b[5])/tsq2);
            dd.set(6, 3, s*(-(a[1]*b[0]) + a[0]*b[1])/2.0);
            dd.set(6, 4, s*(SQRT_2*a[5]*b[1] - a[4]*b[3] + a[3]*b[4] - SQRT_2*a[1]*b[5])/4.0);
            dd.set(6, 5, s*(-(SQRT_2*a[4]*b[0]) + a[5]*b[3] + SQRT_2*a[0]*b[4] - a[3]*b[5])/4.0);
            dd.set(6, 6, s*(-(a[1]*b[0]) - a[0]*b[1] + a[3]*b[3])/2.0);
            dd.set(6, 7, s*(SQRT_2*a[5]*b[1] - a[4]*b[3] - a[3]*b[4] + SQRT_2*a[1]*b[5])/4.0);
            dd.set(6, 8, s*(-(SQRT_2*a[4]*b[0]) + a[5]*b[3] - SQRT_2*a[0]*b[4] + a[3]*b[5])/4.0);

            dd.set(7, 0, s*(-(a[5]*b[3]) + a[3]*b[5])/tsq2);
            dd.set(7, 1, s*(-(a[4]*b[1]) + a[1]*b[4])/2.0);
            dd.set(7, 2, s*(a[4]*b[2] - a[2]*b[4])/2.0);
            dd.set(7, 3, s*(-(SQRT_2*a[5]*b[1]) - a[4]*b[3] + a[3]*b[4] + SQRT_2*a[1]*b[5])/4.0);
            dd.set(7, 4, s*(-(a[2]*b[1]) + a[1]*b[2])/2.0);
            dd.set(7, 5, s*(SQRT_2*a[3]*b[2] - SQRT_2*a[2]*b[3] - a[5]*b[4] + a[4]*b[5])/4.0);
            dd.set(7, 6, s*(SQRT_2*a[5]*b[1] - a[4]*b[3] - a[3]*b[4] + SQRT_2*a[1]*b[5])/4.0);
            dd.set(7, 7, s*(-(a[2]*b[1]) - a[1]*b[2] + a[4]*b[4])/2.0);
            dd.set(7, 8, s*(-(SQRT_2*a[3]*b[2]) - SQRT_2*a[2]*b[3] + a[5]*b[4] + a[4]*b[5])/4.0);

            dd.set(8, 0, s*(-(a[5]*b[0]) + a[0]*b[5])/2.0);
            dd.set(8, 1, s*(-(a[4]*b[3]) + a[3]*b[4])/tsq2);
            dd.set(8, 2, s*(a[5]*b[2] - a[2]*b[5])/2.0);
            dd.set(8, 3, s*(-(SQRT_2*a[4]*b[0]) - a[5]*b[3] + SQRT_2*a[0]*b[4] + a[3]*b[5])/4.0);
            dd.set(8, 4, s*(SQRT_2*a[3]*b[2] - SQRT_2*a[2]*b[3] + a[5]*b[4] - a[4]*b[5])/4.0);
            dd.set(8, 5, s*(-(a[2]*b[0]) + a[0]*b[2])/2.0);
            dd.set(8, 6, s*(-(SQRT_2*a[4]*b[0]) + a[5]*b[3] - SQRT_2*a[0]*b[4] + a[3]*b[5])/4.0);
            dd.set(8, 7, s*(-(SQRT_2*a[3]*b[2]) - SQRT_2*a[2]*b[3] + a[5]*b[4] + a[4]*b[5])/4.0);
            dd.set(8, 8, s*(-(a[2]*b[0]) - a[0]*b[2] + a[5]*b[5])/2.0);
        } else {
            debug_assert!(N == 9);

            dd.set(0, 0, s*a[0]*b[0]);
            dd.set(0, 1, s*((a[3] + a[6])*(b[3] + b[6]))/2.0);
            dd.set(0, 2, s*((a[5] + a[8])*(b[5] + b[8]))/2.0);
            dd.set(0, 3, s*(a[3]*b[0] + a[6]*b[0] + a[0]*(b[3] + b[6]))/2.0);
            dd.set(0, 4, s*((a[5] + a[8])*(b[3] + b[6]) + (a[3] + a[6])*(b[5] + b[8]))/tsq2);
            dd.set(0, 5, s*(a[5]*b[0] + a[8]*b[0] + a[0]*(b[5] + b[8]))/2.0);
            dd.set(0, 6, s*(a[3]*b[0] + a[6]*b[0] - a[0]*(b[3] + b[6]))/2.0);
            dd.set(0, 7, s*((a[5] + a[8])*(b[3] + b[6]) - (a[3] + a[6])*(b[5] + b[8]))/tsq2);
            dd.set(0, 8, s*(a[5]*b[0] + a[8]*b[0] - a[0]*(b[5] + b[8]))/2.0);

            dd.set(1, 0, s*((a[3] - a[6])*(b[3] - b[6]))/2.0);
            dd.set(1, 1, s*a[1]*b[1]);
            dd.set(1, 2, s*((a[4] + a[7])*(b[4] + b[7]))/2.0);
            dd.set(1, 3, s*(a[3]*b[1] - a[6]*b[1] + a[1]*(b[3] - b[6]))/2.0);
            dd.set(1, 4, s*(a[4]*b[1] + a[7]*b[1] + a[1]*(b[4] + b[7]))/2.0);
            dd.set(1, 5, s*((a[4] + a[7])*(b[3] - b[6]) + (a[3] - a[6])*(b[4] + b[7]))/tsq2);
            dd.set(1, 6, s*(-(a[3]*b[1]) + a[6]*b[1] + a[1]*(b[3] - b[6]))/2.0);
            dd.set(1, 7, s*(a[4]*b[1] + a[7]*b[1] - a[1]*(b[4] + b[7]))/2.0);
            dd.set(1, 8, s*((a[4] + a[7])*(b[3] - b[6]) - (a[3] - a[6])*(b[4] + b[7]))/tsq2);

            dd.set(2, 0, s*((a[5] - a[8])*(b[5] - b[8]))/2.0);
            dd.set(2, 1, s*((a[4] - a[7])*(b[4] - b[7]))/2.0);
            dd.set(2, 2, s*a[2]*b[2]);
            dd.set(2, 3, s*((a[5] - a[8])*(b[4] - b[7]) + (a[4] - a[7])*(b[5] - b[8]))/tsq2);
            dd.set(2, 4, s*(a[4]*b[2] - a[7]*b[2] + a[2]*(b[4] - b[7]))/2.0);
            dd.set(2, 5, s*(a[5]*b[2] - a[8]*b[2] + a[2]*(b[5] - b[8]))/2.0);
            dd.set(2, 6, s*(-((a[5] - a[8])*(b[4] - b[7])) + (a[4] - a[7])*(b[5] - b[8]))/tsq2);
            dd.set(2, 7, s*(-(a[4]*b[2]) + a[7]*b[2] + a[2]*(b[4] - b[7]))/2.0);
            dd.set(2, 8, s*(-(a[5]*b[2]) + a[8]*b[2] + a[2]*(b[5] - b[8]))/2.0);

            dd.set(3, 0, s*(a[3]*b[0] - a[6]*b[0] + a[0]*(b[3] - b[6]))/2.0);
            dd.set(3, 1, s*(a[3]*b[1] + a[6]*b[1] + a[1]*(b[3] + b[6]))/2.0);
            dd.set(3, 2, s*((a[5] + a[8])*(b[4] + b[7]) + (a[4] + a[7])*(b[5] + b[8]))/tsq2);
            dd.set(3, 3, s*(a[1]*b[0] + a[0]*b[1] + a[3]*b[3] - a[6]*b[6])/2.0);
            dd.set(3, 4, s*(SQRT_2*(a[5] + a[8])*b[1] + (a[4] + a[7])*(b[3] + b[6]) + (a[3] + a[6])*(b[4] + b[7]) + SQRT_2*a[1]*(b[5] + b[8]))/4.0);
            dd.set(3, 5, s*(SQRT_2*(a[4] + a[7])*b[0] + (a[5] + a[8])*(b[3] - b[6]) + SQRT_2*a[0]*(b[4] + b[7]) + (a[3] - a[6])*(b[5] + b[8]))/4.0);
            dd.set(3, 6, s*(a[1]*b[0] - a[0]*b[1] + a[6]*b[3] - a[3]*b[6])/2.0);
            dd.set(3, 7, s*(SQRT_2*(a[5] + a[8])*b[1] + (a[4] + a[7])*(b[3] + b[6]) - (a[3] + a[6])*(b[4] + b[7]) - SQRT_2*a[1]*(b[5] + b[8]))/4.0);
            dd.set(3, 8, s*(SQRT_2*(a[4] + a[7])*b[0] + (a[5] + a[8])*(b[3] - b[6]) - SQRT_2*a[0]*(b[4] + b[7]) - (a[3] - a[6])*(b[5] + b[8]))/4.0);

            dd.set(4, 0, s*((a[5] - a[8])*(b[3] - b[6]) + (a[3] - a[6])*(b[5] - b[8]))/tsq2);
            dd.set(4, 1, s*(a[4]*b[1] - a[7]*b[1] + a[1]*(b[4] - b[7]))/2.0);
            dd.set(4, 2, s*(a[4]*b[2] + a[7]*b[2] + a[2]*(b[4] + b[7]))/2.0);
            dd.set(4, 3, s*(SQRT_2*(a[5] - a[8])*b[1] + (a[4] - a[7])*(b[3] - b[6]) + (a[3] - a[6])*(b[4] - b[7]) + SQRT_2*a[1]*(b[5] - b[8]))/4.0);
            dd.set(4, 4, s*(a[2]*b[1] + a[1]*b[2] + a[4]*b[4] - a[7]*b[7])/2.0);
            dd.set(4, 5, s*(SQRT_2*(a[3] - a[6])*b[2] + SQRT_2*a[2]*(b[3] - b[6]) + (a[5] - a[8])*(b[4] + b[7]) + (a[4] + a[7])*(b[5] - b[8]))/4.0);
            dd.set(4, 6, s*(-(SQRT_2*(a[5] - a[8])*b[1]) + (a[4] - a[7])*(b[3] - b[6]) - (a[3] - a[6])*(b[4] - b[7]) + SQRT_2*a[1]*(b[5] - b[8]))/4.0);
            dd.set(4, 7, s*(a[2]*b[1] - a[1]*b[2] + a[7]*b[4] - a[4]*b[7])/2.0);
            dd.set(4, 8, s*(-(SQRT_2*(a[3] - a[6])*b[2]) + SQRT_2*a[2]*(b[3] - b[6]) - (a[5] - a[8])*(b[4] + b[7]) + (a[4] + a[7])*(b[5] - b[8]))/4.0);

            dd.set(5, 0, s*(a[5]*b[0] - a[8]*b[0] + a[0]*(b[5] - b[8]))/2.0);
            dd.set(5, 1, s*((a[4] - a[7])*(b[3] + b[6]) + (a[3] + a[6])*(b[4] - b[7]))/tsq2);
            dd.set(5, 2, s*(a[5]*b[2] + a[8]*b[2] + a[2]*(b[5] + b[8]))/2.0);
            dd.set(5, 3, s*(SQRT_2*(a[4] - a[7])*b[0] + (a[5] - a[8])*(b[3] + b[6]) + SQRT_2*a[0]*(b[4] - b[7]) + (a[3] + a[6])*(b[5] - b[8]))/4.0);
            dd.set(5, 4, s*(SQRT_2*(a[3] + a[6])*b[2] + SQRT_2*a[2]*(b[3] + b[6]) + (a[5] + a[8])*(b[4] - b[7]) + (a[4] - a[7])*(b[5] + b[8]))/4.0);
            dd.set(5, 5, s*(a[2]*b[0] + a[0]*b[2] + a[5]*b[5] - a[8]*b[8])/2.0);
            dd.set(5, 6, s*(SQRT_2*(a[4] - a[7])*b[0] - (a[5] - a[8])*(b[3] + b[6]) - SQRT_2*a[0]*(b[4] - b[7]) + (a[3] + a[6])*(b[5] - b[8]))/4.0);
            dd.set(5, 7, s*(-(SQRT_2*(a[3] + a[6])*b[2]) + SQRT_2*a[2]*(b[3] + b[6]) + (a[5] + a[8])*(b[4] - b[7]) - (a[4] - a[7])*(b[5] + b[8]))/4.0);
            dd.set(5, 8, s*(a[2]*b[0] - a[0]*b[2] + a[8]*b[5] - a[5]*b[8])/2.0);

            dd.set(6, 0, s*(-(a[3]*b[0]) + a[6]*b[0] + a[0]*(b[3] - b[6]))/2.0);
            dd.set(6, 1, s*(a[3]*b[1] + a[6]*b[1] - a[1]*(b[3] + b[6]))/2.0);
            dd.set(6, 2, s*((a[5] + a[8])*(b[4] + b[7]) - (a[4] + a[7])*(b[5] + b[8]))/tsq2);
            dd.set(6, 3, s*(-(a[1]*b[0]) + a[0]*b[1] + a[6]*b[3] - a[3]*b[6])/2.0);
            dd.set(6, 4, s*(SQRT_2*(a[5] + a[8])*b[1] - (a[4] + a[7])*(b[3] + b[6]) + (a[3] + a[6])*(b[4] + b[7]) - SQRT_2*a[1]*(b[5] + b[8]))/4.0);
            dd.set(6, 5, s*(-(SQRT_2*(a[4] + a[7])*b[0]) + (a[5] + a[8])*(b[3] - b[6]) + SQRT_2*a[0]*(b[4] + b[7]) - (a[3] - a[6])*(b[5] + b[8]))/4.0);
            dd.set(6, 6, s*(-(a[1]*b[0]) - a[0]*b[1] + a[3]*b[3] - a[6]*b[6])/2.0);
            dd.set(6, 7, s*(SQRT_2*(a[5] + a[8])*b[1] - (a[4] + a[7])*(b[3] + b[6]) - (a[3] + a[6])*(b[4] + b[7]) + SQRT_2*a[1]*(b[5] + b[8]))/4.0);
            dd.set(6, 8, s*(-(SQRT_2*(a[4] + a[7])*b[0]) + (a[5] + a[8])*(b[3] - b[6]) - SQRT_2*a[0]*(b[4] + b[7]) + (a[3] - a[6])*(b[5] + b[8]))/4.0);

            dd.set(7, 0, s*(-((a[5] - a[8])*(b[3] - b[6])) + (a[3] - a[6])*(b[5] - b[8]))/tsq2);
            dd.set(7, 1, s*(-(a[4]*b[1]) + a[7]*b[1] + a[1]*(b[4] - b[7]))/2.0);
            dd.set(7, 2, s*(a[4]*b[2] + a[7]*b[2] - a[2]*(b[4] + b[7]))/2.0);
            dd.set(7, 3, s*(-(SQRT_2*(a[5] - a[8])*b[1]) - (a[4] - a[7])*(b[3] - b[6]) + (a[3] - a[6])*(b[4] - b[7]) + SQRT_2*a[1]*(b[5] - b[8]))/4.0);
            dd.set(7, 4, s*(-(a[2]*b[1]) + a[1]*b[2] + a[7]*b[4] - a[4]*b[7])/2.0);
            dd.set(7, 5, s*(SQRT_2*(a[3] - a[6])*b[2] - SQRT_2*a[2]*(b[3] - b[6]) - (a[5] - a[8])*(b[4] + b[7]) + (a[4] + a[7])*(b[5] - b[8]))/4.0);
            dd.set(7, 6, s*(SQRT_2*(a[5] - a[8])*b[1] - (a[4] - a[7])*(b[3] - b[6]) - (a[3] - a[6])*(b[4] - b[7]) + SQRT_2*a[1]*(b[5] - b[8]))/4.0);
            dd.set(7, 7, s*(-(a[2]*b[1]) - a[1]*b[2] + a[4]*b[4] - a[7]*b[7])/2.0);
            dd.set(7, 8, s*(-(SQRT_2*(a[3] - a[6])*b[2]) - SQRT_2*a[2]*(b[3] - b[6]) + (a[5] - a[8])*(b[4] + b[7]) + (a[4] + a[7])*(b[5] - b[8]))/4.0);

            dd.set(8, 0, s*(-(a[5]*b[0]) + a[8]*b[0] + a[0]*(b[5] - b[8]))/2.0);
            dd.set(8, 1, s*(-((a[4] - a[7])*(b[3] + b[6])) + (a[3] + a[6])*(b[4] - b[7]))/tsq2);
            dd.set(8, 2, s*(a[5]*b[2] + a[8]*b[2] - a[2]*(b[5] + b[8]))/2.0);
            dd.set(8, 3, s*(-(SQRT_2*(a[4] - a[7])*b[0]) - (a[5] - a[8])*(b[3] + b[6]) + SQRT_2*a[0]*(b[4] - b[7]) + (a[3] + a[6])*(b[5] - b[8]))/4.0);
            dd.set(8, 4, s*(SQRT_2*(a[3] + a[6])*b[2] - SQRT_2*a[2]*(b[3] + b[6]) + (a[5] + a[8])*(b[4] - b[7]) - (a[4] - a[7])*(b[5] + b[8]))/4.0);
            dd.set(8, 5, s*(-(a[2]*b[0]) + a[0]*b[2] + a[8]*b[5] - a[5]*b[8])/2.0);
            dd.set(8, 6, s*(-(SQRT_2*(a[4] - a[7])*b[0]) + (a[5] - a[8])*(b[3] + b[6]) - SQRT_2*a[0]*(b[4] - b[7]) + (a[3] + a[6])*(b[5] - b[8]))/4.0);
            dd.set(8, 7, s*(-(SQRT_2*(a[3] + a[6])*b[2]) - SQRT_2*a[2]*(b[3] + b[6]) + (a[5] + a[8])*(b[4] - b[7]) + (a[4] - a[7])*(b[5] + b[8]))/4.0);
            dd.set(8, 8, s*(-(a[2]*b[0]) - a[0]*b[2] + a[5]*b[5] - a[8]*b[8])/2.0);
        }
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#[cfg(test)]
mod tests {
    use super::t2_udyad_t2;
    use crate::{ADD, MN_TO_IJKL, SET, SQRT_2};
    use crate::{Tensor2, Tensor4};
    use russell_lab::{Matrix, mat_approx_eq};

    fn kelvin_matrix<const N: usize>(dd: &Tensor4<N>) -> Matrix {
        let mut m = Matrix::new(N, N);
        for i in 0..N {
            for j in 0..N {
                m.set(i, j, dd.get(i, j));
            }
        }
        m
    }

    fn check_udyad<const N: usize>(s: f64, a_ten: &Tensor2<N>, b_ten: &Tensor2<N>, dd_ten: &Tensor4<9>, tol: f64) {
        let a = a_ten.as_std_matrix();
        let b = b_ten.as_std_matrix();
        let dd = dd_ten.as_std_matrix();
        let mut correct = Matrix::new(9, 9); // Use 9 here due to the conversion to "STD"
        for m in 0..9 {
            for n in 0..9 {
                let (i, j, k, l) = MN_TO_IJKL[m][n];
                correct.set(m, n, s * a.get(i, l) * b.get(j, k));
            }
        }
        mat_approx_eq(&dd, &correct, tol);
    }

    #[test]
    fn t2_udyad_t2_works() {
        // general udyad general
        #[rustfmt::skip]
        let a = Tensor2::<9>::from_std_matrix(&[
            [1.0, 2.0, 3.0],
            [4.0, 5.0, 6.0],
            [7.0, 8.0, 9.0],
        ]).unwrap();
        #[rustfmt::skip]
        let b = Tensor2::<9>::from_std_matrix(&[
            [9.0, 8.0, 7.0],
            [6.0, 5.0, 4.0],
            [3.0, 2.0, 1.0],
        ]).unwrap();
        let mut dd = Tensor4::<9>::new();
        t2_udyad_t2(&mut dd, SET, 2.0, &a, &b);
        let mat = dd.as_std_matrix();
        let correct = Matrix::from(&[
            [18.0, 32.0, 42.0, 36.0, 48.0, 54.0, 16.0, 28.0, 14.0],
            [48.0, 50.0, 48.0, 60.0, 60.0, 72.0, 40.0, 40.0, 32.0],
            [42.0, 32.0, 18.0, 48.0, 36.0, 54.0, 28.0, 16.0, 14.0],
            [12.0, 20.0, 24.0, 24.0, 30.0, 36.0, 10.0, 16.0, 8.0],
            [24.0, 20.0, 12.0, 30.0, 24.0, 36.0, 16.0, 10.0, 8.0],
            [6.0, 8.0, 6.0, 12.0, 12.0, 18.0, 4.0, 4.0, 2.0],
            [72.0, 80.0, 84.0, 90.0, 96.0, 108.0, 64.0, 70.0, 56.0],
            [84.0, 80.0, 72.0, 96.0, 90.0, 108.0, 70.0, 64.0, 56.0],
            [126.0, 128.0, 126.0, 144.0, 144.0, 162.0, 112.0, 112.0, 98.0],
        ]);
        mat_approx_eq(&mat, &correct, 1e-13);
        check_udyad(2.0, &a, &b, &dd, 1e-13);

        // symmetric udyad symmetric
        #[rustfmt::skip]
        let a = Tensor2::<6>::from_std_matrix(&[
            [1.0, 4.0, 6.0],
            [4.0, 2.0, 5.0],
            [6.0, 5.0, 3.0],
        ]).unwrap();
        #[rustfmt::skip]
        let b = Tensor2::<6>::from_std_matrix(&[
            [3.0, 5.0, 6.0],
            [5.0, 2.0, 4.0],
            [6.0, 4.0, 1.0],
        ]).unwrap();
        let mut dd = Tensor4::<9>::new();
        t2_udyad_t2(&mut dd, SET, 2.0, &a, &b);
        let mat = dd.as_std_matrix();
        let correct = Matrix::from(&[
            [6.0, 40.0, 72.0, 24.0, 60.0, 36.0, 10.0, 48.0, 12.0],
            [40.0, 8.0, 40.0, 20.0, 20.0, 50.0, 16.0, 16.0, 32.0],
            [72.0, 40.0, 6.0, 60.0, 24.0, 36.0, 48.0, 10.0, 12.0],
            [10.0, 16.0, 48.0, 40.0, 24.0, 60.0, 4.0, 32.0, 8.0],
            [48.0, 16.0, 10.0, 24.0, 40.0, 60.0, 32.0, 4.0, 8.0],
            [12.0, 32.0, 12.0, 48.0, 48.0, 72.0, 8.0, 8.0, 2.0],
            [24.0, 20.0, 60.0, 12.0, 50.0, 30.0, 40.0, 24.0, 48.0],
            [60.0, 20.0, 24.0, 50.0, 12.0, 30.0, 24.0, 40.0, 48.0],
            [36.0, 50.0, 36.0, 30.0, 30.0, 18.0, 60.0, 60.0, 72.0],
        ]);
        mat_approx_eq(&mat, &correct, 1e-13);
        check_udyad(2.0, &a, &b, &dd, 1e-13);

        // symmetric generalized plane udyad symmetric generalized plane
        #[rustfmt::skip]
        let a = Tensor2::<4>::from_std_matrix(&[
            [1.0, 4.0, 0.0],
            [4.0, 2.0, 0.0],
            [0.0, 0.0, 3.0],
        ]).unwrap();
        #[rustfmt::skip]
        let b = Tensor2::<4>::from_std_matrix(&[
            [3.0, 4.0, 0.0],
            [4.0, 2.0, 0.0],
            [0.0, 0.0, 1.0],
        ]).unwrap();
        let mut dd = Tensor4::<9>::new();
        t2_udyad_t2(&mut dd, SET, 2.0, &a, &b);
        let kelvin_mat = Matrix::from(&[
            [6.0, 32.0, 0.0, 16.0 * SQRT_2, 0.0, 0.0, 8.0 * SQRT_2, 0.0, 0.0],
            [32.0, 8.0, 0.0, 16.0 * SQRT_2, 0.0, 0.0, 0.0, 0.0, 0.0],
            [0.0, 0.0, 6.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
            [16.0 * SQRT_2, 16.0 * SQRT_2, 0.0, 40.0, 0.0, 0.0, 4.0, 0.0, 0.0],
            [0.0, 0.0, 0.0, 0.0, 8.0, 16.0, 0.0, 4.0, 8.0],
            [0.0, 0.0, 0.0, 0.0, 16.0, 10.0, 0.0, 8.0, 8.0],
            [-8.0 * SQRT_2, 0.0, 0.0, -4.0, 0.0, 0.0, 24.0, 0.0, 0.0],
            [0.0, 0.0, 0.0, 0.0, -4.0, -8.0, 0.0, -8.0, -16.0],
            [0.0, 0.0, 0.0, 0.0, -8.0, -8.0, 0.0, -16.0, -10.0],
        ]);
        mat_approx_eq(&kelvin_matrix(&dd), &kelvin_mat, 1e-14);
        let mat = dd.as_std_matrix();
        let correct = Matrix::from(&[
            [6.0, 32.0, 0.0, 24.0, 0.0, 0.0, 8.0, 0.0, 0.0],
            [32.0, 8.0, 0.0, 16.0, 0.0, 0.0, 16.0, 0.0, 0.0],
            [0.0, 0.0, 6.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
            [8.0, 16.0, 0.0, 32.0, 0.0, 0.0, 4.0, 0.0, 0.0],
            [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 4.0, 8.0],
            [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 8.0, 2.0],
            [24.0, 16.0, 0.0, 12.0, 0.0, 0.0, 32.0, 0.0, 0.0],
            [0.0, 0.0, 0.0, 0.0, 12.0, 24.0, 0.0, 0.0, 0.0],
            [0.0, 0.0, 0.0, 0.0, 24.0, 18.0, 0.0, 0.0, 0.0],
        ]);
        mat_approx_eq(&mat, &correct, 1e-14);
        check_udyad(2.0, &a, &b, &dd, 1e-15);
    }

    #[test]
    fn t2_udyad_t2_add_works() {
        // general udyad general
        #[rustfmt::skip]
        let a = Tensor2::<9>::from_std_matrix(&[
            [1.0, 2.0, 3.0],
            [4.0, 5.0, 6.0],
            [7.0, 8.0, 9.0],
        ]).unwrap();
        #[rustfmt::skip]
        let b = Tensor2::<9>::from_std_matrix(&[
            [9.0, 8.0, 7.0],
            [6.0, 5.0, 4.0],
            [3.0, 2.0, 1.0],
        ]).unwrap();
        let mut dd = Tensor4::<9>::new();
        t2_udyad_t2(&mut dd, SET, 2.0, &a, &b);
        t2_udyad_t2(&mut dd, ADD, 3.0, &a, &b);
        check_udyad(5.0, &a, &b, &dd, 1e-12);

        // symmetric udyad symmetric
        #[rustfmt::skip]
        let a = Tensor2::<6>::from_std_matrix(&[
            [1.0, 4.0, 6.0],
            [4.0, 2.0, 5.0],
            [6.0, 5.0, 3.0],
        ]).unwrap();
        #[rustfmt::skip]
        let b = Tensor2::<6>::from_std_matrix(&[
            [3.0, 5.0, 6.0],
            [5.0, 2.0, 4.0],
            [6.0, 4.0, 1.0],
        ]).unwrap();
        let mut dd = Tensor4::<9>::new();
        t2_udyad_t2(&mut dd, SET, 2.0, &a, &b);
        t2_udyad_t2(&mut dd, ADD, 3.0, &a, &b);
        check_udyad(5.0, &a, &b, &dd, 1e-12);

        // symmetric generalized plane udyad symmetric generalized plane
        #[rustfmt::skip]
        let a = Tensor2::<4>::from_std_matrix(&[
            [1.0, 4.0, 0.0],
            [4.0, 2.0, 0.0],
            [0.0, 0.0, 3.0],
        ]).unwrap();
        #[rustfmt::skip]
        let b = Tensor2::<4>::from_std_matrix(&[
            [3.0, 4.0, 0.0],
            [4.0, 2.0, 0.0],
            [0.0, 0.0, 1.0],
        ]).unwrap();
        let mut dd = Tensor4::<9>::new();
        t2_udyad_t2(&mut dd, SET, 2.0, &a, &b);
        t2_udyad_t2(&mut dd, ADD, 3.0, &a, &b);
        check_udyad(5.0, &a, &b, &dd, 1e-12);
    }
}