1 /*===========================================================================
2 *
3 * PUBLIC DOMAIN NOTICE
4 * National Center for Biotechnology Information
5 *
6 * This software/database is a "United States Government Work" under the
7 * terms of the United States Copyright Act. It was written as part of
8 * the author's official duties as a United States Government employee and
9 * thus cannot be copyrighted. This software/database is freely available
10 * to the public for use. The National Library of Medicine and the U.S.
11 * Government have not placed any restriction on its use or reproduction.
12 *
13 * Although all reasonable efforts have been taken to ensure the accuracy
14 * and reliability of the software and data, the NLM and the U.S.
15 * Government do not and cannot warrant the performance or results that
16 * may be obtained by using this software or data. The NLM and the U.S.
17 * Government disclaim all warranties, express or implied, including
18 * warranties of performance, merchantability or fitness for any particular
19 * purpose.
20 *
21 * Please cite the author in any work or product based on this material.
22 *
23 * ===========================================================================
24 *
25 */
26
27 #include <vdb/extern.h>
28
29 #include <vdb/xform.h>
30 #include <klib/rc.h>
31
32 #include "xform-priv.h"
33 #include "blob-priv.h"
34 #include "blob.h"
35 #include "page-map.h"
36
37 #include <assert.h>
38
39
40 /* Create
41 *
42 * Create a new blob. A new data buffer is sized to
43 * 'element_count' * sizeof datatype; its contents are
44 * uninitialized.
45 */
46 static
VBlobCreate(VBlob ** blobp,const VBlob * in)47 rc_t VBlobCreate ( VBlob **blobp, const VBlob *in )
48 {
49 rc_t rc = VBlobNew ( blobp, in -> start_id, in -> stop_id, "transpose" );
50 if ( rc == 0 )
51 {
52 VBlob *blob = * blobp;
53 rc = KDataBufferMake ( & blob -> data,
54 in -> data . elem_bits, in -> data . elem_count );
55 if ( rc != 0 )
56 {
57 VBlobRelease ( blob );
58 * blobp = NULL;
59 }
60 else
61 {
62 blob -> byte_order = in -> byte_order;
63 }
64 }
65 return rc;
66 }
67
68
69 /* detranspose
70 * pardoning the awful name, apply a transposition on the result
71 * of "transpose" to produce the original blob. "transpose"
72 * itself cannot be reused because of its signature.
73 *
74 * see "transpose" below for an explanation
75 */
76 static
transpose_formatted8(void * self,const VXformInfo * info,int64_t row_id,VBlob ** rslt,uint32_t argc,const VBlob * argv[])77 rc_t CC transpose_formatted8 ( void *self, const VXformInfo *info, int64_t row_id,
78 VBlob **rslt, uint32_t argc, const VBlob *argv [] )
79 {
80 /* input blob - schema assures us that it is ready to go */
81 const VBlob *in = argv [ 0 ];
82
83 /* allocate output blob of same size */
84 rc_t rc = VBlobCreate ( rslt, in );
85 if ( rc != 0 )
86 rc = ResetRCContext ( rc, rcVDB, rcFunction, rcExecuting );
87 else
88 {
89 VBlob *out = * rslt;
90
91 /* page-map iterator */
92 PageMapIterator it;
93 rc = PageMapNewIterator ( in -> pm, & it, 0, -1 );
94
95 /* create a new reference to the page map */
96 if ( rc == 0 )
97 rc = PageMapAddRef ( in -> pm );
98
99 /* last chance for failure */
100 if ( rc != 0 )
101 {
102 rc = ResetRCContext ( rc, rcVDB, rcFunction, rcExecuting );
103 VBlobRelease ( out );
104 * rslt = NULL;
105 }
106 else
107 {
108 uint32_t j, k;
109 elem_count_t i, max_row_len, row_len, rpt_cnt;
110
111 /* get source and destination pointers */
112 uint8_t *dst = out -> data . base;
113 const uint8_t *src = in -> data . base;
114
115 /* set page-map on out */
116 out -> pm = in -> pm;
117
118 /* perform the transformation
119 the first pass will determine maximum row length */
120 for ( max_row_len = 0, j = k = 0; ; k += row_len )
121 {
122 row_len = PageMapIteratorDataLength ( & it );
123 if ( row_len > max_row_len )
124 max_row_len = row_len;
125
126 if ( row_len != 0 )
127 {
128 dst [ k ] = src [ j ];
129 ++ j;
130 }
131
132 rpt_cnt = PageMapIteratorRepeatCount ( & it );
133 if ( ! PageMapIteratorAdvance ( & it, rpt_cnt ) )
134 break;
135 }
136
137 /* perform transformation on the remainder */
138 for ( i = 1; i < max_row_len; ++ i )
139 {
140 it . cur_row = 0;
141 for ( k = i; ; k += row_len )
142 {
143 row_len = PageMapIteratorDataLength ( & it );
144 if ( row_len > i )
145 {
146 dst [ k ] = src [ j ];
147 ++ j;
148 }
149
150 rpt_cnt = PageMapIteratorRepeatCount ( & it );
151 if ( ! PageMapIteratorAdvance ( & it, rpt_cnt ) )
152 break;
153 }
154 }
155 }
156 }
157
158 return rc;
159 }
160
161 static
transpose_formatted16(void * self,const VXformInfo * info,int64_t row_id,VBlob ** rslt,uint32_t argc,const VBlob * argv[])162 rc_t CC transpose_formatted16 ( void *self, const VXformInfo *info, int64_t row_id,
163 VBlob **rslt, uint32_t argc, const VBlob *argv [] )
164 {
165 const VBlob *in = argv [ 0 ];
166 rc_t rc = VBlobCreate ( rslt, in );
167 if ( rc != 0 )
168 rc = ResetRCContext ( rc, rcVDB, rcFunction, rcExecuting );
169 else
170 {
171 VBlob *out = * rslt;
172 PageMapIterator it;
173 rc = PageMapNewIterator ( in -> pm, & it, 0, -1 );
174 if ( rc == 0 )
175 rc = PageMapAddRef ( in -> pm );
176 if ( rc != 0 )
177 {
178 rc = ResetRCContext ( rc, rcVDB, rcFunction, rcExecuting );
179 VBlobRelease ( out );
180 * rslt = NULL;
181 }
182 else
183 {
184 uint32_t j, k;
185 elem_count_t i, max_row_len, row_len, rpt_cnt;
186 uint16_t *dst = out -> data . base;
187 const uint16_t *src = in -> data . base;
188 out -> pm = in -> pm;
189 for ( max_row_len = 0, j = k = 0; ; k += row_len )
190 {
191 row_len = PageMapIteratorDataLength ( & it );
192 if ( row_len > max_row_len )
193 max_row_len = row_len;
194 if ( row_len != 0 )
195 {
196 dst [ k ] = src [ j ];
197 ++ j;
198 }
199 rpt_cnt = PageMapIteratorRepeatCount ( & it );
200 if ( ! PageMapIteratorAdvance ( & it, rpt_cnt ) )
201 break;
202 }
203 for ( i = 1; i < max_row_len; ++ i )
204 {
205 it . cur_row = 0;
206 for ( k = i; ; k += row_len )
207 {
208 row_len = PageMapIteratorDataLength ( & it );
209 if ( row_len > i )
210 {
211 dst [ k ] = src [ j ];
212 ++ j;
213 }
214 rpt_cnt = PageMapIteratorRepeatCount ( & it );
215 if ( ! PageMapIteratorAdvance ( & it, rpt_cnt ) )
216 break;
217 }
218 }
219 }
220 }
221
222 return rc;
223 }
224
225 static
transpose_formatted32(void * self,const VXformInfo * info,int64_t row_id,VBlob ** rslt,uint32_t argc,const VBlob * argv[])226 rc_t CC transpose_formatted32 ( void *self, const VXformInfo *info, int64_t row_id,
227 VBlob **rslt, uint32_t argc, const VBlob *argv [] )
228 {
229 const VBlob *in = argv [ 0 ];
230 rc_t rc = VBlobCreate ( rslt, in );
231 if ( rc != 0 )
232 rc = ResetRCContext ( rc, rcVDB, rcFunction, rcExecuting );
233 else
234 {
235 VBlob *out = * rslt;
236 PageMapIterator it;
237 rc = PageMapNewIterator ( in -> pm, & it, 0, -1 );
238 if ( rc == 0 )
239 rc = PageMapAddRef ( in -> pm );
240 if ( rc != 0 )
241 {
242 rc = ResetRCContext ( rc, rcVDB, rcFunction, rcExecuting );
243 VBlobRelease ( out );
244 * rslt = NULL;
245 }
246 else
247 {
248 uint32_t j, k;
249 elem_count_t i, max_row_len, row_len, rpt_cnt;
250 uint32_t *dst = out -> data . base;
251 const uint32_t *src = in -> data . base;
252 out -> pm = in -> pm;
253 for ( max_row_len = 0, j = k = 0; ; k += row_len )
254 {
255 row_len = PageMapIteratorDataLength ( & it );
256 if ( row_len > max_row_len )
257 max_row_len = row_len;
258 if ( row_len != 0 )
259 {
260 dst [ k ] = src [ j ];
261 ++ j;
262 }
263 rpt_cnt = PageMapIteratorRepeatCount ( & it );
264 if ( ! PageMapIteratorAdvance ( & it, rpt_cnt ) )
265 break;
266 }
267 for ( i = 1; i < max_row_len; ++ i )
268 {
269 it . cur_row = 0;
270 for ( k = i; ; k += row_len )
271 {
272 row_len = PageMapIteratorDataLength ( & it );
273 if ( row_len > i )
274 {
275 dst [ k ] = src [ j ];
276 ++ j;
277 }
278 rpt_cnt = PageMapIteratorRepeatCount ( & it );
279 if ( ! PageMapIteratorAdvance ( & it, rpt_cnt ) )
280 break;
281 }
282 }
283 }
284 }
285
286 return rc;
287 }
288
289 static
transpose_formatted64(void * self,const VXformInfo * info,int64_t row_id,VBlob ** rslt,uint32_t argc,const VBlob * argv[])290 rc_t CC transpose_formatted64 ( void *self, const VXformInfo *info, int64_t row_id,
291 VBlob **rslt, uint32_t argc, const VBlob *argv [] )
292 {
293 const VBlob *in = argv [ 0 ];
294 rc_t rc = VBlobCreate ( rslt, in );
295 if ( rc != 0 )
296 rc = ResetRCContext ( rc, rcVDB, rcFunction, rcExecuting );
297 else
298 {
299 VBlob *out = * rslt;
300 PageMapIterator it;
301 rc = PageMapNewIterator ( in -> pm, & it, 0, -1 );
302 if ( rc == 0 )
303 rc = PageMapAddRef ( in -> pm );
304 if ( rc != 0 )
305 {
306 rc = ResetRCContext ( rc, rcVDB, rcFunction, rcExecuting );
307 VBlobRelease ( out );
308 * rslt = NULL;
309 }
310 else
311 {
312 uint32_t j, k;
313 elem_count_t i, max_row_len, row_len, rpt_cnt;
314 uint64_t *dst = out -> data . base;
315 const uint64_t *src = in -> data . base;
316 out -> pm = in -> pm;
317 for ( max_row_len = 0, j = k = 0; ; k += row_len )
318 {
319 row_len = PageMapIteratorDataLength ( & it );
320 if ( row_len > max_row_len )
321 max_row_len = row_len;
322 if ( row_len != 0 )
323 {
324 dst [ k ] = src [ j ];
325 ++ j;
326 }
327 rpt_cnt = PageMapIteratorRepeatCount ( & it );
328 if ( ! PageMapIteratorAdvance ( & it, rpt_cnt ) )
329 break;
330 }
331 for ( i = 1; i < max_row_len; ++ i )
332 {
333 it . cur_row = 0;
334 for ( k = i; ; k += row_len )
335 {
336 row_len = PageMapIteratorDataLength ( & it );
337 if ( row_len > i )
338 {
339 dst [ k ] = src [ j ];
340 ++ j;
341 }
342 rpt_cnt = PageMapIteratorRepeatCount ( & it );
343 if ( ! PageMapIteratorAdvance ( & it, rpt_cnt ) )
344 break;
345 }
346 }
347 }
348 }
349
350 return rc;
351 }
352
353 VTRANSFACT_BUILTIN_IMPL ( vdb_detranspose, 1, 0, 0 )
354 ( const void *self, const VXfactInfo *info, VFuncDesc *rslt,
355 const VFactoryParams *cp, const VFunctionParams *dp )
356 {
357 switch ( VTypedescSizeof ( & info -> fdesc . desc ) )
358 {
359 case 8:
360 VFUNCDESC_INTERNAL_FUNCS ( rslt ) -> bfN = transpose_formatted8;
361 break;
362 case 16:
363 VFUNCDESC_INTERNAL_FUNCS ( rslt ) -> bfN = transpose_formatted16;
364 break;
365 case 32:
366 VFUNCDESC_INTERNAL_FUNCS ( rslt ) -> bfN = transpose_formatted32;
367 break;
368 case 64:
369 VFUNCDESC_INTERNAL_FUNCS ( rslt ) -> bfN = transpose_formatted64;
370 break;
371 }
372
373 rslt -> variant = vftBlobN;
374 return 0;
375 }
376
377 /* transpose
378 * transpose a page of unformatted data
379 *
380 * for example - convert a simple page of values,
381 * where vertical scale is row id and horizontal element index:
382 *
383 * 1 2 3
384 * +---+---+---+
385 * 1 | a | b | c |
386 * +---+---+---+
387 * 2 | d | e |
388 * +---+---+
389 * 3 | f |
390 * +---+---+---+
391 * 4 | g | h | i |
392 * +---+---+---+
393 *
394 * into:
395 *
396 * 1 2 3 4
397 * +---+---+---+---+
398 * 1 | a | d | f | g |
399 * +---+---+---+---+
400 * 2 | b | e | | h |
401 * +---+---+ +---+
402 * 3 | c | | i |
403 * +---+ +---+
404 *
405 * or:
406 *
407 * +---+---+---+---+---+---+---+---+---+
408 * | a | d | f | g | b | e | h | c | i |
409 * +---+---+---+---+---+---+---+---+---+
410 *
411 * variable row-lengths are supported. The output blob is
412 * formatted, meaning that the result can no longer be addressed
413 * as a matrix, but the transposition has be applied to data.
414 *
415 * "in" [ DATA ] - unformatted data to be transposed
416 */
417 static
transpose_unformatted8(void * self,const VXformInfo * info,int64_t row_id,VBlob ** rslt,uint32_t argc,const VBlob * argv[])418 rc_t CC transpose_unformatted8 ( void *self, const VXformInfo *info, int64_t row_id,
419 VBlob **rslt, uint32_t argc, const VBlob *argv [] )
420 {
421 /* input blob - schema assures us that it is ready to go */
422 const VBlob *in = argv [ 0 ];
423
424 /* allocate output blob of same size */
425 rc_t rc = VBlobCreate ( rslt, in );
426 if ( rc != 0 )
427 rc = ResetRCContext ( rc, rcVDB, rcFunction, rcExecuting );
428 else
429 {
430 VBlob *out = * rslt;
431
432 /* page-map iterator */
433 PageMapIterator it;
434 rc = PageMapNewIterator ( in -> pm, & it, 0, -1 );
435
436 /* create a new reference to the page map */
437 if ( rc == 0 )
438 rc = PageMapAddRef ( in -> pm );
439
440 /* last chance for failure */
441 if ( rc != 0 )
442 {
443 rc = ResetRCContext ( rc, rcVDB, rcFunction, rcExecuting );
444 VBlobRelease ( out );
445 * rslt = NULL;
446 }
447 else
448 {
449 uint32_t j, k;
450 elem_count_t i, max_row_len, row_len, rpt_cnt;
451
452 /* get source and destination pointers */
453 uint8_t *dst = out -> data . base;
454 const uint8_t *src = in -> data . base;
455
456 /* set page-map on out */
457 out -> pm = in -> pm;
458
459 /* perform the transformation
460 the first pass will determine maximum row length */
461 for ( max_row_len = 0, j = k = 0; ; k += row_len )
462 {
463 row_len = PageMapIteratorDataLength ( & it );
464 if ( row_len > max_row_len )
465 max_row_len = row_len;
466
467 if ( row_len != 0 )
468 {
469 dst [ j ] = src [ k ];
470 ++ j;
471 }
472
473 rpt_cnt = PageMapIteratorRepeatCount ( & it );
474 if ( ! PageMapIteratorAdvance ( & it, rpt_cnt ) )
475 break;
476 }
477
478 /* perform transformation on the remainder */
479 for ( i = 1; i < max_row_len; ++ i )
480 {
481 it . cur_row = 0;
482 for ( k = i; ; k += row_len )
483 {
484 row_len = PageMapIteratorDataLength ( & it );
485 if ( row_len > i )
486 {
487 dst [ j ] = src [ k ];
488 ++ j;
489 }
490
491 rpt_cnt = PageMapIteratorRepeatCount ( & it );
492 if ( ! PageMapIteratorAdvance ( & it, rpt_cnt ) )
493 break;
494 }
495 }
496 }
497 }
498
499 return rc;
500 }
501
502 static
transpose_unformatted16(void * self,const VXformInfo * info,int64_t row_id,VBlob ** rslt,uint32_t argc,const VBlob * argv[])503 rc_t CC transpose_unformatted16 ( void *self, const VXformInfo *info, int64_t row_id,
504 VBlob **rslt, uint32_t argc, const VBlob *argv [] )
505 {
506 const VBlob *in = argv [ 0 ];
507 rc_t rc = VBlobCreate ( rslt, in );
508 if ( rc != 0 )
509 rc = ResetRCContext ( rc, rcVDB, rcFunction, rcExecuting );
510 else
511 {
512 VBlob *out = * rslt;
513 PageMapIterator it;
514 rc = PageMapNewIterator ( in -> pm, & it, 0, -1 );
515 if ( rc == 0 )
516 rc = PageMapAddRef ( in -> pm );
517 if ( rc != 0 )
518 {
519 rc = ResetRCContext ( rc, rcVDB, rcFunction, rcExecuting );
520 VBlobRelease ( out );
521 * rslt = NULL;
522 }
523 else
524 {
525 uint32_t j, k;
526 elem_count_t i, max_row_len, row_len, rpt_cnt;
527 uint16_t *dst = out -> data . base;
528 const uint16_t *src = in -> data . base;
529 out -> pm = in -> pm;
530 for ( max_row_len = 0, j = k = 0; ; k += row_len )
531 {
532 row_len = PageMapIteratorDataLength ( & it );
533 if ( row_len > max_row_len )
534 max_row_len = row_len;
535 if ( row_len != 0 )
536 {
537 dst [ j ] = src [ k ];
538 ++ j;
539 }
540 rpt_cnt = PageMapIteratorRepeatCount ( & it );
541 if ( ! PageMapIteratorAdvance ( & it, rpt_cnt ) )
542 break;
543 }
544 for ( i = 1; i < max_row_len; ++ i )
545 {
546 it . cur_row = 0;
547 for ( k = i; ; k += row_len )
548 {
549 row_len = PageMapIteratorDataLength ( & it );
550 if ( row_len > i )
551 {
552 dst [ j ] = src [ k ];
553 ++ j;
554 }
555 rpt_cnt = PageMapIteratorRepeatCount ( & it );
556 if ( ! PageMapIteratorAdvance ( & it, rpt_cnt ) )
557 break;
558 }
559 }
560 }
561 }
562
563 return rc;
564 }
565
566 static
transpose_unformatted32(void * self,const VXformInfo * info,int64_t row_id,VBlob ** rslt,uint32_t argc,const VBlob * argv[])567 rc_t CC transpose_unformatted32 ( void *self, const VXformInfo *info, int64_t row_id,
568 VBlob **rslt, uint32_t argc, const VBlob *argv [] )
569 {
570 const VBlob *in = argv [ 0 ];
571 rc_t rc = VBlobCreate ( rslt, in );
572 if ( rc != 0 )
573 rc = ResetRCContext ( rc, rcVDB, rcFunction, rcExecuting );
574 else
575 {
576 VBlob *out = * rslt;
577 PageMapIterator it;
578 rc = PageMapNewIterator ( in -> pm, & it, 0, -1 );
579 if ( rc == 0 )
580 rc = PageMapAddRef ( in -> pm );
581 if ( rc != 0 )
582 {
583 rc = ResetRCContext ( rc, rcVDB, rcFunction, rcExecuting );
584 VBlobRelease ( out );
585 * rslt = NULL;
586 }
587 else
588 {
589 uint32_t j, k;
590 elem_count_t i, max_row_len, row_len, rpt_cnt;
591 uint32_t *dst = out -> data . base;
592 const uint32_t *src = in -> data . base;
593 out -> pm = in -> pm;
594 for ( max_row_len = 0, j = k = 0; ; k += row_len )
595 {
596 row_len = PageMapIteratorDataLength ( & it );
597 if ( row_len > max_row_len )
598 max_row_len = row_len;
599 if ( row_len != 0 )
600 {
601 dst [ j ] = src [ k ];
602 ++ j;
603 }
604 rpt_cnt = PageMapIteratorRepeatCount ( & it );
605 if ( ! PageMapIteratorAdvance ( & it, rpt_cnt ) )
606 break;
607 }
608 for ( i = 1; i < max_row_len; ++ i )
609 {
610 it . cur_row = 0;
611 for ( k = i; ; k += row_len )
612 {
613 row_len = PageMapIteratorDataLength ( & it );
614 if ( row_len > i )
615 {
616 dst [ j ] = src [ k ];
617 ++ j;
618 }
619 rpt_cnt = PageMapIteratorRepeatCount ( & it );
620 if ( ! PageMapIteratorAdvance ( & it, rpt_cnt ) )
621 break;
622 }
623 }
624 }
625 }
626
627 return rc;
628 }
629
630 static
transpose_unformatted64(void * self,const VXformInfo * info,int64_t row_id,VBlob ** rslt,uint32_t argc,const VBlob * argv[])631 rc_t CC transpose_unformatted64 ( void *self, const VXformInfo *info, int64_t row_id,
632 VBlob **rslt, uint32_t argc, const VBlob *argv [] )
633 {
634 const VBlob *in = argv [ 0 ];
635 rc_t rc = VBlobCreate ( rslt, in );
636 if ( rc != 0 )
637 rc = ResetRCContext ( rc, rcVDB, rcFunction, rcExecuting );
638 else
639 {
640 VBlob *out = * rslt;
641 PageMapIterator it;
642 rc = PageMapNewIterator ( in -> pm, & it, 0, -1 );
643 if ( rc == 0 )
644 rc = PageMapAddRef ( in -> pm );
645 if ( rc != 0 )
646 {
647 rc = ResetRCContext ( rc, rcVDB, rcFunction, rcExecuting );
648 VBlobRelease ( out );
649 * rslt = NULL;
650 }
651 else
652 {
653 uint32_t j, k;
654 elem_count_t i, max_row_len, row_len, rpt_cnt;
655 uint64_t *dst = out -> data . base;
656 const uint64_t *src = in -> data . base;
657 out -> pm = in -> pm;
658 for ( max_row_len = 0, j = k = 0; ; k += row_len )
659 {
660 row_len = PageMapIteratorDataLength ( & it );
661 if ( row_len > max_row_len )
662 max_row_len = row_len;
663 if ( row_len != 0 )
664 {
665 dst [ j ] = src [ k ];
666 ++ j;
667 }
668 rpt_cnt = PageMapIteratorRepeatCount ( & it );
669 if ( ! PageMapIteratorAdvance ( & it, rpt_cnt ) )
670 break;
671 }
672 for ( i = 1; i < max_row_len; ++ i )
673 {
674 it . cur_row = 0;
675 for ( k = i; ; k += row_len )
676 {
677 row_len = PageMapIteratorDataLength ( & it );
678 if ( row_len > i )
679 {
680 dst [ j ] = src [ k ];
681 ++ j;
682 }
683 rpt_cnt = PageMapIteratorRepeatCount ( & it );
684 if ( ! PageMapIteratorAdvance ( & it, rpt_cnt ) )
685 break;
686 }
687 }
688 }
689 }
690
691 return rc;
692 }
693
694
695 VTRANSFACT_BUILTIN_IMPL ( vdb_transpose, 1, 0, 0 )
696 ( const void *self, const VXfactInfo *info, VFuncDesc *rslt,
697 const VFactoryParams *cp, const VFunctionParams *dp )
698 {
699 /* the TYPE of input has been validated by schema, but not the dimension */
700 switch ( VTypedescSizeof ( & dp -> argv [ 0 ] . desc ) )
701 {
702 case 8:
703 VFUNCDESC_INTERNAL_FUNCS ( rslt ) -> bfN = transpose_unformatted8;
704 break;
705 case 16:
706 VFUNCDESC_INTERNAL_FUNCS ( rslt ) -> bfN = transpose_unformatted16;
707 break;
708 case 32:
709 VFUNCDESC_INTERNAL_FUNCS ( rslt ) -> bfN = transpose_unformatted32;
710 break;
711 case 64:
712 VFUNCDESC_INTERNAL_FUNCS ( rslt ) -> bfN = transpose_unformatted64;
713 break;
714 default:
715 return RC ( rcVDB, rcFunction, rcConstructing, rcType, rcUnsupported );
716 }
717
718 rslt -> variant = vftBlobN;
719 return 0;
720 }
721