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