Thread: [Algorithms] Byte Swapping
Brought to you by:
vexxed72
From: Tom H. <to...@3d...> - 2000-07-16 06:31:43
|
I can do the obvious method, but I was wondering if anyone have any cool/fast code snippets for byte swapping integers and floats? Tom |
From: Charles B. <cb...@cb...> - 2000-07-17 22:42:12
|
Jumping in late : I'm sure you don't need it now, but here's a crazy ANSI C byte-swapper : let x = a 32 bit ulong , ABCD then y = DCBA y = (x = x>>16 | x<<16) ^ (x = (x^x>>8) & 0x00FF00FF) ^ (x<<8); At 11:45 PM 7/15/2000 -0700, you wrote: >I can do the obvious method, but I was wondering if anyone have any >cool/fast code snippets for byte swapping integers and floats? > >Tom > > >_______________________________________________ >GDAlgorithms-list mailing list >GDA...@li... >http://lists.sourceforge.net/mailman/listinfo/gdalgorithms-list > > -------------------------------------- Charles Bloom www.cbloom.com |
From: Pierre T. <p.t...@wa...> - 2000-07-17 23:11:47
|
Errr............ you'd better use the BSWAP instruction........ same result with one line of assembly............ Pierre ----- Original Message ----- From: Charles Bloom <cb...@cb...> To: <gda...@li...> Sent: Tuesday, July 18, 2000 12:41 AM Subject: Re: [Algorithms] Byte Swapping > > Jumping in late : I'm sure you don't need it now, but > here's a crazy ANSI C byte-swapper : > > let x = a 32 bit ulong , ABCD > then y = DCBA > > y = (x = x>>16 | x<<16) ^ (x = (x^x>>8) & 0x00FF00FF) ^ (x<<8); > > At 11:45 PM 7/15/2000 -0700, you wrote: > >I can do the obvious method, but I was wondering if anyone have any > >cool/fast code snippets for byte swapping integers and floats? > > > >Tom > > > > > >_______________________________________________ > >GDAlgorithms-list mailing list > >GDA...@li... > >http://lists.sourceforge.net/mailman/listinfo/gdalgorithms-list > > > > > -------------------------------------- > Charles Bloom www.cbloom.com > > > _______________________________________________ > GDAlgorithms-list mailing list > GDA...@li... > http://lists.sourceforge.net/mailman/listinfo/gdalgorithms-list |
From: Conor S. <cs...@tp...> - 2000-07-18 01:18:33
|
> Errr............ you'd better use the BSWAP instruction........ same result > with one line of assembly............ > BSWAP is an x86 instruction :) Not much good if you wanna swap bytes on the Mac. Possibly there is a Mac equivelent, but I think it is RISC practice to avoid such instructions. Conor Stokes |
From: brian s. <br...@hu...> - 2000-07-18 02:00:08
|
> From: Charles Bloom <cb...@cb...> > > Jumping in late : I'm sure you don't need it now, but > here's a crazy ANSI C byte-swapper : > > let x = a 32 bit ulong , ABCD > then y = DCBA > > y = (x = x>>16 | x<<16) ^ (x = (x^x>>8) & 0x00FF00FF) ^ (x<<8); > wow, I'll say that's crazy...but unfortunately non-functional. see the results of this program: #include <stdio.h> long swap1(long x) { return (x = x>>16 | x<<16) ^ (x = (x^x>>8) & 0x00FF00FF) ^ (x<<8); } long swap2(long x) { return ((x >> 24) & 0x000000FF) | ((x >> 8 ) & 0x0000FF00) | ((x << 8 ) & 0x00FF0000) | ((x << 24) & 0xFF000000) ; } int main(int argc, char **argv) { long test = 0x01020304; printf("swap1: 0x%08X 0x%08X 0x%08X \n", test, swap1(test), swap1(swap1(test))); printf("swap2: 0x%08X 0x%08X 0x%08X \n", test, swap2(test), swap2(swap2(test))); } swap1: 0x01020304 0x07000300 0x03000700 swap2: 0x01020304 0x04030201 0x01020304 anyway, in case anyone hasn't gotten their fill of this stuff, here is our comparatively lame byteswapping code that uses those fast swappers on PowerPC: #ifndef _MBSWAP_H_ #define _MBSWAP_H_ // swapping macros/inlines #include <Runtime/MBBase.h> inline MBint16 MBSwap(const MBint16 & swap) { #if defined(MB_MAC) && defined(MB_POWERPC) return __lhbrx(const_cast<MBint16 *>(&swap), 0); #else return ((swap >> 8 ) & 0x00FF) | ((swap << 8 ) & 0xFF00) ; #endif } inline MBuint16 MBSwap(const MBuint16 & swap) { #if defined(MB_MAC) && defined(MB_POWERPC) return __lhbrx(const_cast<MBuint16 *>(&swap), 0); #else return ((swap >> 8 ) & 0x00FF) | ((swap << 8 ) & 0xFF00) ; #endif } inline MBint32 MBSwap(const MBint32 & swap) { #if defined(MB_MAC) && defined(MB_POWERPC) return __lwbrx(const_cast<MBint32 *>(&swap), 0); #else return ((swap >> 24) & 0x000000FF) | ((swap >> 8 ) & 0x0000FF00) | ((swap << 8 ) & 0x00FF0000) | ((swap << 24) & 0xFF000000) ; #endif } inline MBuint32 MBSwap(const MBuint32 & swap) { #if defined(MB_MAC) && defined(MB_POWERPC) return __lwbrx(const_cast<MBuint32 *>(&swap), 0); #else return ((swap >> 24) & 0x000000FF) | ((swap >> 8 ) & 0x0000FF00) | ((swap << 8 ) & 0x00FF0000) | ((swap << 24) & 0xFF000000) ; #endif } inline MBfloat MBSwap(const MBfloat & swap) { MBuint32 temp = *(const MBuint32*)&swap; temp = MBSwap(temp); return *(const MBfloat *)&temp; } #ifdef MB_MSB #define MBSwapMSBToNative( s ) s #define MBSwapNativeToMSB( s ) s #define MBSwapLSBToNative MBSwap #define MBSwapNativeToLSB MBSwap #elif defined(MB_LSB) #define MBSwapLSBToNative( s ) s #define MBSwapNativeToLSB( s ) s #define MBSwapMSBToNative MBSwap #define MBSwapNativeToMSB MBSwap #endif #endif // header guard |
From: Matthew M. <ma...@me...> - 2000-10-02 22:27:57
|
I'm (re) building a scene graph and have made some strange choices with uncertain implications. These are partly motivated by my desire to see the benefits of a "highly OOP" approach to a scene graph, avoiding for the moment my knee-jerk tendency to overoptimize immature architectures. At any rate, I ran into a thorny (and hopefully interesting) architectural decision recently which I'd like some input on. The basic approach: A scene graph is a nodes & arcs data structure used for affecting rendering state. The screen is considered to be state. Each node in a scenegraph has any number of incoming arcs. The most basic level of node has one outgoing arc. Arcs are directed. Subgraphs may be cyclic. It is incumbent upon the node to conditionalize traversal of outgoing arcs to effect loop termination. This is where we insert culling, including portals and octree neighbors. Rendering is effected by calling "render" on the root of the graph, which then recurses on the targets of outgoing arcs. My First Weird Decision is to make arcs first-class objects. Nodes never contain pointers (in the C sense) to other nodes, but only pointers to arcs. - to provide a point of indirection for loading scenes over the network (functionality) - to allow lazy evaluation of inter-object references (performance) - to separate inter-object reference semantics from node semantics (simplicity) This brought up an interesting issue. Since the "basic" node has a single outgoing arc, how do we have a classic one parent/many children relationship. The two choices are: - a special type of node with multiple outgoing arcs (group nodes) - a special type of arc with multiple terminating nodes (multi-arcs) The advantage of multi-arcs is that nodes don't have to support "groupness," simplifying their implementation. Classes designed to support a single outgoing arc can be fitted with multiple outgoing arcs. The disadvantage of multi-arcs is that they need to be made aware of the rendering protocol, thereby conflating "rendering" with "connecting," two previously orthagonal concepts. The advantage of group nodes is that arc traversal decisions are centralized into the node. For example, imagine a cell (as in portals and cells) that's deciding which of its portal links to traverse. If the number of portals is "hidden" from the cell, the logic becomes less intuitive. For these (and other reasons,) I went with the group nodes approach, but not without some regret for the simple elegance of multi-arcs. The hard-core among us will, I'm sure, look askance at the cache-pessimizing effect of having pointers all over creation. My plan for this is a "graph-crushing" algorithm which will pack a graph into a contiguous chunk of RAM based on a more-or-less "standard" traversal. This is extremely easy to effect at load time. I will, however, still have to support fragmentation and relocation for (hopefully rare) cases of dynamic graph modification. |
From: Stefan B. <ste...@te...> - 2000-10-03 11:18:05
|
> My First Weird Decision is to make arcs first-class objects. Nodes never > contain pointers (in the C sense) to other nodes, but only > pointers to arcs. > - to provide a point of indirection for loading scenes over > the network (functionality) > - to allow lazy evaluation of inter-object references (performance) > - to separate inter-object reference semantics from node semantics > (simplicity) Interesting. I have something similar, but effectively in the reverse. In my scene graph design (inspired by XSG), the interior nodes are typically all of the same class (XInteriorNode), but can have a "core" node plugged into it (or a chain of cores, even). The core node modifies the traversal behaviour, so f.ex. instead of having a dedicated transform or switch node, we have an interior node with a "Matrix" core or "Switch" core plugged into it. Traditional: +-------+ +--------+ +------+ | Xform | |Interior|<---|Matrix| +-------+ +--------+ +------+ / | \ / | \ +----+ +----+ +----+ +----+ +----+ +----+ |Geom| |Geom| |Geom| |Geom| |Geom| |Geom| +----+ +----+ +----+ +----+ +----+ +----+ This simplifies and enables you to do a lot of things, but it's kind of hard to describe everything here. To take one example, imagine having a scene graph describing a number of different levels-of-detail of a car. During the game you will want to update the scene graph to rotate the wheels. Now if you had a graph where the interior nodes themselves stored the matrix as well as the child node list, you would have to update ALL transform nodes in each level-of-detail subgraph. Using the plug-in approach instead, you would only have one transform plugged into all LOD instances, so you would only have to poke the rotation matrix into one place, without caring which LOD subgraph is picked at traversal time. This is, I think, similar to what you have done -- only different :). The interior node objects typically only describe the topology and bounding volumes of the graph, with geometry at the leaf nodes and behaviour modifiers ("cores") plugged into the interior nodes. I don't allow cycles in my scene graphs though. I keep separate node graphs for higher-level culling and visibility purposes. I like to keep my graphs "clean" and single-purpose. Another thing you may want to look at is using a more generic dispatch system rather than having virtual functions (I'm assuming that's what you are doing now) on the nodes themselves. By separating behaviour from data you gain a lot of power. I use a Action/Node double-dispatch system similar to the one used in XSG and Inventor. In my previous scene-graph prototype I used virtual functions and it got messy real quick. I have had no such problems with the double-dispatch approach. It works incredibly well actually. Cheers, Stefan -- Stefan Boberg, R&D Manager, Team17 Software Ltd. bo...@te... |
From: Michael S. H. <mic...@ud...> - 2000-07-17 23:18:40
|
Just for good measure, here's ours /* useful macros for swapping 16 and 32 bit data types */ #define MAKE16(l, h) ((Uint16)(((Byte)(l)) | ((Uint16)((Byte)(h))) << 8)) #define MAKE32(l, h) ((Uint32)(((Uint16)(l)) | ((Uint32)((Uint16)(h))) << 16)) #define LO16(l) ((Uint16)(l)) #define HI16(l) ((Uint16)(((Uint32)(l) >> 16) & 0xFFFF)) #define LO8(w) ((Byte)(w)) #define HI8(w) ((Byte)(((Uint16)(w) >> 8) & 0xFF)) /* these assume that the swapping is from motorola to intel format */ #if __cplusplus #if NEEDBYTESWAP inline Int16 ByteSwap( Int16 &x ) { Uint16 y = (Uint16)x; y = (Uint16)(y >> 8 | (y << 8 & 0xff00)); x = (Int16 &)y; return x; } inline Uint16 ByteSwap( Uint16 &x ) { x = (Uint16)(x >> 8 | (x << 8 & 0xff00)); return x; } inline Int32 ByteSwap( Int32 &x ) { Uint32 y = (Uint32)x; y = y >> 24 | (y >> 8 & 0xff00) | (y << 8 & 0xff0000) | (y << 24 & 0xff000000); x = (Int32 &)y; return x; } inline Uint32 ByteSwap( Uint32 &x ) { x = x >> 24 | (x >> 8 & 0xff00) | (x << 8 & 0xff0000) | (x << 24 & 0xff000000); return x; } template<class T> inline T ByteSwap( T &parm ) { Uint32 x = (Uint32)parm; x = x >> 24 | (x >> 8 & 0xff00) | (x << 8 & 0xff0000) | (x << 24 & 0xff000000); parm = (T &)x; return parm; } inline float ByteSwap( float &x ) { Uint32 * pTemp = (Uint32*)&x; Uint32 y = *pTemp; y = y >> 24 | (y >> 8 & 0xff00) | (y << 8 & 0xff0000) | (y << 24 & 0xff000000); pTemp = (Uint32*)&y; x = *((float*)pTemp); return x; } inline double ByteSwap( double &x ) { Uint32 * pParm = (Uint32*)&x; Uint32 nFirst = pParm[0]; Uint32 nSecond = pParm[1]; ByteSwap( nFirst ); ByteSwap( nSecond ); pParm[0] = nSecond; pParm[1] = nFirst; return x; } #else #define ByteSwap(x) (x) #endif #endif /* __cplusplus */ At 03:41 PM 7/17/00, you wrote: >Jumping in late : I'm sure you don't need it now, but >here's a crazy ANSI C byte-swapper : > >let x = a 32 bit ulong , ABCD >then y = DCBA > >y = (x = x>>16 | x<<16) ^ (x = (x^x>>8) & 0x00FF00FF) ^ (x<<8); > >At 11:45 PM 7/15/2000 -0700, you wrote: >>I can do the obvious method, but I was wondering if anyone have any >>cool/fast code snippets for byte swapping integers and floats? >> >>Tom >> >> >>_______________________________________________ >>GDAlgorithms-list mailing list >>GDA...@li... >>http://lists.sourceforge.net/mailman/listinfo/gdalgorithms-list >> >> >-------------------------------------- >Charles Bloom www.cbloom.com > > >_______________________________________________ >GDAlgorithms-list mailing list >GDA...@li... >http://lists.sourceforge.net/mailman/listinfo/gdalgorithms-list |
From: Favnir <fa...@wi...> - 2000-07-18 07:48:57
|
----- Original Message -----=20 From: Michael S. Harrison=20 To: gda...@li...=20 Sent: Tuesday, July 18, 2000 1:17 AM Subject: Re: [Algorithms] Byte Swapping [ SNIP ] /* these assume that the swapping is from motorola to intel format */ [ SNIP ] ...or vice versa ;-)))) Are, F |
From: Michael S. H. <mic...@ud...> - 2000-07-18 12:34:14
|
hehe. True. That comment reflects the fact that all of our basic data files are in Motorola format and have to be converted when running on the PC At 10:48 AM 7/18/00, you wrote: > >----- Original Message ----- >From: <mailto:mic...@ud...>Michael S. Harrison >To: <mailto:gda...@li...>gda...@li... >Sent: Tuesday, July 18, 2000 1:17 AM >Subject: Re: [Algorithms] Byte Swapping > >[ SNIP ] >/* these assume that the swapping is from motorola to intel format */ > >[ SNIP ] > > >...or vice versa ;-)))) > >Are, >F > |
From: Eugene F. <fo...@dr...> - 2000-07-20 00:32:09
|
If you're writing to the Mac (or even just have the QuickTime SDK installed), there are some handy endian-swapping macros in Endian.h. They're of the form (using unsigned longs as an example) EndianU32_?to?(value) where the characters in the question marks are L (for little endian), B (for big endian), and N (for native format). Thus, since your data files are in big endian format you could write EndianU32_BtoN(value) which would do a conversion when compiled for Intel and compile to nothing for PPC. Endian.h uses ConditionalMacros.h to figure out whether you're compiling for big or little endian. The only problem is that they don't automatically use CodeWarrior's intrinsic functions mentioned earlier by Jens Ayton. I've found that CodeWarrior lets me get away with the following code, which is in my precompiled header: #include <Endian.h> #undef Endian32_Swap #define Endian32_Swap(value) \ ( *(uint32*)&(value) = __lwbrx( (uint32*)&(value), 0 ) ) #undef Endian16_Swap #define Endian16_Swap(value) \ ( (value) = __lhbrx( &(value), 0 ) ) -----Original Message----- From: gda...@li... [mailto:gda...@li...]On Behalf Of Michael S. Harrison Sent: Tuesday, July 18, 2000 5:30 AM To: gda...@li... Subject: Re: [Algorithms] Byte Swapping hehe. True. That comment reflects the fact that all of our basic data files are in Motorola format and have to be converted when running on the PC At 10:48 AM 7/18/00, you wrote: ----- Original Message ----- From: Michael S. Harrison To: gda...@li... Sent: Tuesday, July 18, 2000 1:17 AM Subject: Re: [Algorithms] Byte Swapping [ SNIP ] /* these assume that the swapping is from motorola to intel format */ [ SNIP ] ...or vice versa ;-)))) Are, F |