From cf1d93ebf41df4ca4814f53b7738f44d74e598c6 Mon Sep 17 00:00:00 2001 From: castano Date: Sun, 8 Jul 2007 08:08:52 +0000 Subject: [PATCH] Sync with perforce repository. Several bugfixes in nvcore. Add imgdiff to cmakefiles and fix compilation errors on linux. --- src/nvcore/Containers.h | 93 +- src/nvcore/StrLib.cpp | 12 + src/nvcore/StrLib.h | 6 +- src/nvcore/TextReader.cpp | 7 +- src/nvcore/poshlib/posh.c | 1932 ++++++++++++++------------- src/nvcore/poshlib/posh.h | 1996 ++++++++++++++-------------- src/nvimage/ImageIO.cpp | 111 +- src/nvimage/ImageIO.h | 3 +- src/nvimage/nvtt/CMakeLists.txt | 5 +- src/nvimage/nvtt/tools/imgdiff.cpp | 3 +- src/nvmath/Matrix.h | 1938 +++++++++++++-------------- 11 files changed, 3154 insertions(+), 2952 deletions(-) diff --git a/src/nvcore/Containers.h b/src/nvcore/Containers.h index 0e3333f..086e577 100644 --- a/src/nvcore/Containers.h +++ b/src/nvcore/Containers.h @@ -34,10 +34,10 @@ Do not use memmove in insert & remove, use copy ctors instead. #define NV_FOREACH(i, container) \ typedef typeof(container) NV_STRING_JOIN2(cont,__LINE__); \ - for(NV_STRING_JOIN2(cont,__LINE__)::PseudoIndex i((container).start()); (container).isDone(i); (container).advance(i)) + for(NV_STRING_JOIN2(cont,__LINE__)::PseudoIndex i((container).start()); !(container).isDone(i); (container).advance(i)) /* #define NV_FOREACH(i, container) \ - for(typename typeof(container)::PseudoIndex i((container).start()); (container).isDone(i); (container).advance(i)) + for(typename typeof(container)::PseudoIndex i((container).start()); !(container).isDone(i); (container).advance(i)) */ #else // If typeof not available: @@ -61,7 +61,7 @@ struct PseudoIndexWrapper { }; #define NV_FOREACH(i, container) \ - for(PseudoIndexWrapper i(container); (container).isDone(i(&(container))); (container).advance(i(&(container)))) + for(PseudoIndexWrapper i(container); !(container).isDone(i(&(container))); (container).advance(i(&(container)))) #endif @@ -145,7 +145,7 @@ namespace nv template void deleteAll(T & container) { - for(typename T::PseudoIndex i = container.start(); container.isDone(i); container.advance(i)) + for(typename T::PseudoIndex i = container.start(); !container.isDone(i); container.advance(i)) { delete container[i]; } @@ -272,14 +272,19 @@ namespace nv /// Push an element at the end of the vector. void push_back( const T & val ) { - // DO NOT pass elements of your own vector into - // push_back()! Since we're using references, - // resize() may munge the element storage! - nvDebugCheck( &val < &m_buffer[0] || &val > &m_buffer[m_size] ); - - int new_size = m_size + 1; - resize( new_size ); - m_buffer[new_size-1] = val; + uint new_size = m_size + 1; + + if (new_size > m_buffer_size) + { + const T copy(val); // create a copy in case value is inside of this array. + resize(new_size); + m_buffer[new_size-1] = copy; + } + else + { + m_size = new_size; + m_buffer[new_size-1] = val; + } } void pushBack( const T & val ) { @@ -364,7 +369,7 @@ namespace nv /// Remove the first instance of the given element. void remove(const T & element) { - for(PseudoIndex i = start(); isDone(i); advance(i)) { + for(PseudoIndex i = start(); !isDone(i); advance(i)) { removeAt(i); break; } @@ -560,8 +565,8 @@ namespace nv typedef uint PseudoIndex; PseudoIndex start() const { return 0; } - bool isDone(const PseudoIndex & i) const { return i < this->m_size; }; - void advance(PseudoIndex & i) const { i++; } + bool isDone(const PseudoIndex & i) const { nvDebugCheck(i <= this->m_size); return i == this->m_size; }; + void advance(PseudoIndex & i) const { nvDebugCheck(i <= this->m_size); i++; } #if NV_CC_MSVC T & operator[]( const PseudoIndexWrapper & i ) { @@ -642,7 +647,7 @@ namespace nv ~HashMap() { clear(); } - /** Set a new or existing value under the key, to the value. */ + /// Set a new or existing value under the key, to the value. void set(const T& key, const U& value) { int index = findIndex(key); @@ -657,7 +662,7 @@ namespace nv } - /** Add a new value to the hash table, under the specified key. */ + /// Add a new value to the hash table, under the specified key. void add(const T& key, const U& value) { nvCheck(findIndex(key) == -1); @@ -732,7 +737,7 @@ namespace nv } - /** Remove the first value under the specified key. */ + /// Remove the first value under the specified key. bool remove(const T& key) { if (table == NULL) @@ -767,7 +772,7 @@ namespace nv } - /** Remove all entries from the hash table. */ + /// Remove all entries from the hash table. void clear() { if (table != NULL) @@ -789,25 +794,24 @@ namespace nv } - /** Returns true if the hash is empty. */ + /// Returns true if the hash is empty. bool isEmpty() const { return table == NULL || entry_count == 0; } - /** - * Retrieve the value under the given key. - * - * If there's no value under the key, then return false and leave - * *value alone. - * - * If there is a value, return true, and set *value to the entry's - * value. - * - * If value == NULL, return true or false according to the - * presence of the key, but don't touch *value. - */ + /** Retrieve the value under the given key. + * + * If there's no value under the key, then return false and leave + * *value alone. + * + * If there is a value, return true, and set *value to the entry's + * value. + * + * If value == NULL, return true or false according to the + * presence of the key, but don't touch *value. + */ bool get(const T& key, U* value = NULL) const { int index = findIndex(key); @@ -821,6 +825,7 @@ namespace nv return false; } + /// Determine if the given key is contained in the hash. bool contains(const T & key) const { return get(key); @@ -856,7 +861,7 @@ namespace nv } - /** Hint the bucket count to >= n. */ + /// Hint the bucket count to >= n. void resize(int n) { // Not really sure what this means in relation to @@ -881,7 +886,7 @@ namespace nv setRawCapacity(new_raw_size); } - /** Behaves much like std::pair. */ + /// Behaves much like std::pair. struct Entry { int next_in_chain; // internal chaining for collisions @@ -910,11 +915,11 @@ namespace nv }; - /** HashMap enumerator. */ + // HashMap enumerator. typedef int PseudoIndex; PseudoIndex start() const { PseudoIndex i = 0; findNext(i); return i; } - bool isDone(const PseudoIndex & i) const { return i <= size_mask; }; - void advance(PseudoIndex & i) const { i++; findNext(i); } + bool isDone(const PseudoIndex & i) const { nvDebugCheck(i <= size_mask+1); return i == size_mask+1; }; + void advance(PseudoIndex & i) const { nvDebugCheck(i <= size_mask+1); i++; findNext(i); } #if NV_CC_GNUC Entry & operator[]( const PseudoIndex & i ) { @@ -936,7 +941,7 @@ namespace nv private: - /** Find the index of the matching entry. If no match, then return -1. */ + // Find the index of the matching entry. If no match, then return -1. int findIndex(const T& key) const { if (table == NULL) return -1; @@ -987,11 +992,11 @@ namespace nv /** - * Resize the hash table to the given size (Rehash the - * contents of the current table). The arg is the number of - * hash table entries, not the number of elements we should - * actually contain (which will be less than this). - */ + * Resize the hash table to the given size (Rehash the + * contents of the current table). The arg is the number of + * hash table entries, not the number of elements we should + * actually contain (which will be less than this). + */ void setRawCapacity(int new_size) { if (new_size <= 0) { @@ -1041,7 +1046,7 @@ namespace nv new_hash.table = NULL; } - /** Move the enumerator to the next valid element. */ + // Move the enumerator to the next valid element. void findNext(PseudoIndex & i) const { while (i <= size_mask && E(i).isEmpty()) { i++; diff --git a/src/nvcore/StrLib.cpp b/src/nvcore/StrLib.cpp index 5a238f4..bbdf2de 100644 --- a/src/nvcore/StrLib.cpp +++ b/src/nvcore/StrLib.cpp @@ -102,6 +102,18 @@ void nv::strCpy(char * dst, int size, const char * src) #endif } +void nv::strCpy(char * dst, int size, const char * src, int len) +{ + nvDebugCheck(dst != NULL); + nvDebugCheck(src != NULL); +#if NV_CC_MSVC && _MSC_VER >= 1400 + strncpy_s(dst, size, src, len); +#else + NV_UNUSED(size); + strncpy(dst, src, len); +#endif +} + void nv::strCat(char * dst, int size, const char * src) { nvDebugCheck(dst != NULL); diff --git a/src/nvcore/StrLib.h b/src/nvcore/StrLib.h index 274e095..47e66ea 100644 --- a/src/nvcore/StrLib.h +++ b/src/nvcore/StrLib.h @@ -32,6 +32,7 @@ namespace nv NVCORE_API int strCaseCmp(const char * s1, const char * s2) NV_PURE; NVCORE_API int strCmp(const char * s1, const char * s2) NV_PURE; NVCORE_API void strCpy(char * dst, int size, const char * src); + NVCORE_API void strCpy(char * dst, int size, const char * src, int len); NVCORE_API void strCat(char * dst, int size, const char * src); NVCORE_API bool strMatch(const char * str, const char * pat) NV_PURE; @@ -327,7 +328,10 @@ namespace nv setRefCount( 0 ); // Copy string. - strCpy(const_cast(data), len + 1, str); + strCpy(const_cast(data), len+1, str, len); + + // Add terminating character. + const_cast(data)[len] = '\0'; } NVCORE_API void setString(const char * str); diff --git a/src/nvcore/TextReader.cpp b/src/nvcore/TextReader.cpp index 4bf0a5a..8eb7461 100644 --- a/src/nvcore/TextReader.cpp +++ b/src/nvcore/TextReader.cpp @@ -27,12 +27,13 @@ char TextReader::read() { nvDebugCheck(m_stream != NULL); + char c; + m_stream->serialize(&c, 1); + if( m_stream->isAtEnd() ) { return 0; } - - char c; - m_stream->serialize(&c, 1); + return c; } diff --git a/src/nvcore/poshlib/posh.c b/src/nvcore/poshlib/posh.c index 860922a..431948c 100644 --- a/src/nvcore/poshlib/posh.c +++ b/src/nvcore/poshlib/posh.c @@ -1,926 +1,1006 @@ -/* -LICENSE: - -Copyright (c) 2004, Brian Hook -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - - * The names of this package'ss contributors contributors may not - be used to endorse or promote products derived from this - software without specific prior written permission. - - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -/** - @file posh.c - @author Brian Hook - @date 2002 - @brief Portable Open Source Harness primary source file -*/ -#include "posh.h" - -#if !defined FORCE_DOXYGEN - -#if !defined POSH_NO_FLOAT -# define POSH_FLOAT_STRING "enabled" -#else -# define POSH_FLOAT_STRING "disabled" -#endif - -#if defined POSH_64BIT_INTEGER -# define POSH_64BIT_INTEGER_STRING "yes" -#else -# define POSH_64BIT_INTEGER_STRING "no" -#endif - -#if defined POSH_64BIT_POINTER -# define POSH_POINTER_STRING "64-bits" -#else -# define POSH_POINTER_STRING "32-bits" -#endif - -#if defined POSH_LITTLE_ENDIAN -# define IS_BIG_ENDIAN 0 - -# define NATIVE16 POSH_LittleU16 -# define NATIVE32 POSH_LittleU32 -# define NATIVE64 POSH_LittleU64 -# define FOREIGN16 POSH_BigU16 -# define FOREIGN32 POSH_BigU32 -# define FOREIGN64 POSH_BigU64 -#else -# define IS_BIG_ENDIAN 1 - -# define NATIVE16 POSH_BigU16 -# define NATIVE32 POSH_BigU32 -# define NATIVE64 POSH_BigU64 -# define FOREIGN16 POSH_LittleU16 -# define FOREIGN32 POSH_LittleU32 -# define FOREIGN64 POSH_LittleU64 -#endif /* POSH_LITTLE_ENDIAN */ - -static -int -s_testBigEndian( void ) -{ - union - { - posh_byte_t c[ 4 ]; - posh_u32_t i; - } u; - - u.i= 1; - - if ( u.c[ 0 ] == 1 ) - { - return 0; - } - return 1; -} - -static -const char * -s_testSerialization( void ) -{ - posh_byte_t serbuf[ 8 ]; - posh_u16_t tmp16; - posh_u32_t tmp32; - - /* 16-bit serialization */ - POSH_WriteU16ToLittle( serbuf, 0xABCD ); - if ( ( tmp16 = POSH_ReadU16FromLittle( serbuf ) ) != 0xABCD ) - { - return "*ERROR: failed little-endian 16-bit serialization test"; - } - - POSH_WriteU16ToBig( serbuf, 0xABCD ); - if ( ( tmp16 = POSH_ReadU16FromBig( serbuf ) ) != 0xABCD ) - { - return "*ERROR: failed big-endian 16-bit serialization test"; - } - - /* 32-bit serialization */ - POSH_WriteU32ToLittle( serbuf, 0xABCD1234L ); - if ( ( tmp32 = POSH_ReadU32FromLittle( serbuf ) ) != 0xABCD1234 ) - { - return "*ERROR: failed little-endian 32-bit serialization test"; - } - - POSH_WriteU32ToBig( serbuf, 0xABCD1234L ); - if ( ( tmp32 = POSH_ReadU32FromBig( serbuf ) ) != 0xABCD1234 ) - { - return "*ERROR: failed big-endian 32-bit serialization test"; - } - -#if defined POSH_64BIT_INTEGER - { -#define REF64 POSH_U64(0xFEDCBA9876543210) - - posh_u64_t tmp64; - - POSH_WriteU64ToLittle( serbuf, REF64 ); - - if ( ( tmp64 = POSH_ReadU64FromLittle( serbuf ) ) != REF64 ) - { - return "*ERROR: failed little-endian 64-bit serialization test"; - } - - POSH_WriteU64ToBig( serbuf, REF64 ); - - if ( ( tmp64 = POSH_ReadU64FromBig( serbuf ) ) != REF64 ) - { - return "*ERROR: failed big-endian 64-bit serialization test"; - } - } -#endif - - return 0; -} - -#if !defined POSH_NO_FLOAT -static -const char * -s_testFloatingPoint( void ) -{ - float fRef = 10.0f/30.0f; - double dRef = 10.0/30.0; - posh_byte_t dbuf[ 8 ]; - float fTmp; - double dTmp; - - fTmp = POSH_FloatFromLittleBits( POSH_LittleFloatBits( fRef ) ); - - if ( fTmp != fRef ) - { - return "*ERROR: POSH little endian floating point conversion failed. Please report this to poshlib@poshlib.org!\n"; - } - - fTmp = POSH_FloatFromBigBits( POSH_BigFloatBits( fRef ) ); - if ( fTmp != fRef ) - { - return "*ERROR: POSH big endian floating point conversion failed. Please report this to poshlib@poshlib.org!\n"; - } - - POSH_DoubleBits( dRef, dbuf ); - - dTmp = POSH_DoubleFromBits( dbuf ); - - if ( dTmp != dRef ) - { - return "*ERROR: POSH double precision floating point serialization failed. Please report this to poshlib@poshlib.org!\n"; - } - - return 0; -} -#endif /* !defined POSH_NO_FLOAT */ - -static -const char * -s_testEndianess( void ) -{ - /* check endianess */ - if ( s_testBigEndian() != IS_BIG_ENDIAN ) - { - return "*ERROR: POSH compile time endianess does not match run-time endianess verification. Please report this to poshlib@poshlib.org!\n"; - } - - /* make sure our endian swap routines work */ - if ( ( NATIVE32( 0x11223344L ) != 0x11223344L ) || - ( FOREIGN32( 0x11223344L ) != 0x44332211L ) || - ( NATIVE16( 0x1234 ) != 0x1234 ) || - ( FOREIGN16( 0x1234 ) != 0x3412 ) ) - { - return "*ERROR: POSH endianess macro selection failed. Please report this to poshlib@poshlib.org!\n"; - } - - /* test serialization routines */ - - return 0; -} -#endif /* !defined FORCE_DOXYGEN */ - -/** - Returns a string describing this platform's basic attributes. - - POSH_GetArchString() reports on an architecture's statically determined - attributes. In addition, it will perform run-time verification checks - to make sure the various platform specific functions work. If an error - occurs, please contact me at poshlib@poshlib.org so we can try to resolve - what the specific failure case is. - @returns a string describing this platform on success, or a string in the - form "*ERROR: [text]" on failure. You can simply check to see if - the first character returned is '*' to verify an error condition. -*/ -const char * -POSH_GetArchString( void ) -{ - const char *err; - const char *s = "OS:.............."POSH_OS_STRING"\n" - "CPU:............."POSH_CPU_STRING"\n" - "endian:.........."POSH_ENDIAN_STRING"\n" - "ptr size:........"POSH_POINTER_STRING"\n" - "64-bit ints......"POSH_64BIT_INTEGER_STRING"\n" - "floating point..."POSH_FLOAT_STRING"\n" - "compiler........."POSH_COMPILER_STRING"\n"; - - /* test endianess */ - err = s_testEndianess(); - - if ( err != 0 ) - { - return err; - } - - /* test serialization */ - err = s_testSerialization(); - - if ( err != 0 ) - { - return err; - } - -#if !defined POSH_NO_FLOAT - /* check that our floating point support is correct */ - err = s_testFloatingPoint(); - - if ( err != 0 ) - { - return err; - } - -#endif - - return s; -} - -/* ---------------------------------------------------------------------------*/ -/* BYTE SWAPPING SUPPORT */ -/* ---------------------------------------------------------------------------*/ -/** - * Byte swaps a 16-bit unsigned value - * - @param v [in] unsigned 16-bit input value to swap - @returns a byte swapped version of v - */ -posh_u16_t -POSH_SwapU16( posh_u16_t v ) -{ - posh_u16_t swapped; - - swapped = v << 8; - swapped |= v >> 8; - - return swapped; -} - -/** - * Byte swaps a 16-bit signed value - * - @param v [in] signed 16-bit input value to swap - @returns a byte swapped version of v - @remarks This just calls back to the unsigned version, since byte swapping - is independent of sign. However, we still provide this function to - avoid signed/unsigned mismatch compiler warnings. - */ -posh_i16_t -POSH_SwapI16( posh_i16_t v ) -{ - return ( posh_i16_t ) POSH_SwapU16( v ); -} - -/** - * Byte swaps a 32-bit unsigned value - * - @param v [in] unsigned 32-bit input value to swap - @returns a byte swapped version of v - */ -posh_u32_t -POSH_SwapU32( posh_u32_t v ) -{ - posh_u32_t swapped; - - swapped = ( v & 0xFF ) << 24; - swapped |= ( v & 0xFF00 ) << 8; - swapped |= ( v >> 8 ) & 0xFF00; - swapped |= ( v >> 24 ); - - return swapped; -} - -/** - * Byte swaps a 32-bit signed value - * - @param v [in] signed 32-bit input value to swap - @returns a byte swapped version of v - @remarks This just calls back to the unsigned version, since byte swapping - is independent of sign. However, we still provide this function to - avoid signed/unsigned mismatch compiler warnings. - */ -posh_i32_t -POSH_SwapI32( posh_i32_t v ) -{ - return ( posh_i32_t ) POSH_SwapU32( ( posh_u32_t ) v ); -} - -#if defined POSH_64BIT_INTEGER -/** - * Byte swaps a 64-bit unsigned value - - @param v [in] a 64-bit input value to swap - @ingroup SixtyFourBit - @returns a byte swapped version of v -*/ -posh_u64_t -POSH_SwapU64( posh_u64_t v ) -{ - posh_byte_t tmp; - union { - posh_byte_t bytes[ 8 ]; - posh_u64_t u64; - } u; - - u.u64 = v; - - tmp = u.bytes[ 0 ]; u.bytes[ 0 ] = u.bytes[ 7 ]; u.bytes[ 7 ] = tmp; - tmp = u.bytes[ 1 ]; u.bytes[ 1 ] = u.bytes[ 6 ]; u.bytes[ 6 ] = tmp; - tmp = u.bytes[ 2 ]; u.bytes[ 2 ] = u.bytes[ 5 ]; u.bytes[ 5 ] = tmp; - tmp = u.bytes[ 3 ]; u.bytes[ 3 ] = u.bytes[ 4 ]; u.bytes[ 4 ] = tmp; - - return u.u64; -} - -/** - * Byte swaps a 64-bit signed value - - @param v [in] a 64-bit input value to swap - @ingroup SixtyFourBit - @returns a byte swapped version of v -*/ -posh_i64_t -POSH_SwapI64( posh_i64_t v ) -{ - return ( posh_i64_t ) POSH_SwapU64( ( posh_u64_t ) v ); -} - -#endif /* defined POSH_64BIT_INTEGER */ - -/* ---------------------------------------------------------------------------*/ -/* IN-MEMORY SERIALIZATION */ -/* ---------------------------------------------------------------------------*/ - -/** - * Writes an unsigned 16-bit value to a little endian buffer - - @param dst [out] pointer to the destination buffer, may not be NULL - @param value [in] host-endian unsigned 16-bit value - @returns a pointer to the location two bytes after dst - @remarks does no validation of the inputs -*/ -posh_u16_t * -POSH_WriteU16ToLittle( void *dst, posh_u16_t value ) -{ - posh_u16_t *p16 = ( posh_u16_t * ) dst; - - *p16 = POSH_LittleU16(value); - - return p16 + 1; -} - -/** - * Writes a signed 16-bit value to a little endian buffer - - @param dst [out] pointer to the destination buffer, may not be NULL - @param value [in] host-endian signed 16-bit value - @returns a pointer to the location two bytes after dst - @remarks does no validation of the inputs. This simply calls - POSH_WriteU16ToLittle() with appropriate casting. -*/ -posh_i16_t * -POSH_WriteI16ToLittle( void *dst, posh_i16_t value ) -{ - return ( posh_i16_t * ) POSH_WriteU16ToLittle( dst, ( posh_u16_t ) value ); -} - -/** - * Writes an unsigned 32-bit value to a little endian buffer - - @param dst [out] pointer to the destination buffer, may not be NULL - @param value [in] host-endian signed 32-bit value - @returns a pointer to the location four bytes after dst - @remarks does no validation of the inputs. -*/ -posh_u32_t * -POSH_WriteU32ToLittle( void *dst, posh_u32_t value ) -{ - posh_u32_t *p32 = ( posh_u32_t * ) dst; - - *p32 = POSH_LittleU32(value); - - return p32 + 1; -} - -/** - * Writes a signed 32-bit value to a little endian buffer - - @param dst [out] pointer to the destination buffer, may not be NULL - @param value [in] host-endian signed 32-bit value - @returns a pointer to the location four bytes after dst - @remarks does no validation of the inputs. This simply calls - POSH_WriteU32ToLittle() with appropriate casting. -*/ -posh_i32_t * -POSH_WriteI32ToLittle( void *dst, posh_i32_t value ) -{ - return ( posh_i32_t * ) POSH_WriteU32ToLittle( dst, ( posh_u32_t ) value ); -} - -/** - * Writes an unsigned 16-bit value to a big endian buffer - - @param dst [out] pointer to the destination buffer, may not be NULL - @param value [in] host-endian unsigned 16-bit value - @returns a pointer to the location two bytes after dst - @remarks does no validation of the inputs -*/ -posh_u16_t * -POSH_WriteU16ToBig( void *dst, posh_u16_t value ) -{ - posh_u16_t *p16 = ( posh_u16_t * ) dst; - - *p16 = POSH_BigU16(value); - - return p16 + 1; -} - -/** - * Writes a signed 16-bit value to a big endian buffer - - @param dst [out] pointer to the destination buffer, may not be NULL - @param value [in] host-endian signed 16-bit value - @returns a pointer to the location two bytes after dst - @remarks does no validation of the inputs. This simply calls - POSH_WriteU16ToLittle() with appropriate casting. -*/ -posh_i16_t * -POSH_WriteI16ToBig( void *dst, posh_i16_t value ) -{ - return ( posh_i16_t * ) POSH_WriteU16ToBig( dst, ( posh_u16_t ) value ); -} - -/** - * Writes an unsigned 32-bit value to a big endian buffer - - @param dst [out] pointer to the destination buffer, may not be NULL - @param value [in] host-endian unsigned 32-bit value - @returns a pointer to the location four bytes after dst - @remarks does no validation of the inputs. -*/ -posh_u32_t * -POSH_WriteU32ToBig( void *dst, posh_u32_t value ) -{ - posh_u32_t *p32 = ( posh_u32_t * ) dst; - - *p32 = POSH_BigU32(value); - - return p32 + 1; -} - -/** - * Writes a signed 32-bit value to a big endian buffer - - @param dst [out] pointer to the destination buffer, may not be NULL - @param value [in] host-endian signed 32-bit value - @returns a pointer to the location four bytes after dst - @remarks does no validation of the inputs. This simply calls - POSH_WriteU32ToBig() with appropriate casting. -*/ -posh_i32_t * -POSH_WriteI32ToBig( void *dst, posh_i32_t value ) -{ - return ( posh_i32_t * ) POSH_WriteU32ToBig( dst, ( posh_u32_t ) value ); -} - -#if defined POSH_64BIT_INTEGER -/** - * Writes an unsigned 64-bit value to a little-endian buffer - - @ingroup SixtyFourBit - @param dst [out] pointer to the destination buffer, may not be NULL - @param value [in] host-endian unsigned 64-bit value - @returns a pointer to the location eight bytes after dst - @remarks does no validation of the inputs. -*/ -posh_u64_t * -POSH_WriteU64ToLittle( void *dst, posh_u64_t value ) -{ - posh_u64_t *p64 = ( posh_u64_t * ) dst; - - *p64 = POSH_LittleU64(value); - - return p64 + 1; -} - -/** - * Writes a signed 64-bit value to a little-endian buffer - - @ingroup SixtyFourBit - @param dst [out] pointer to the destination buffer, may not be NULL - @param value [in] host-endian unsigned 64-bit value - @returns a pointer to the location eight bytes after dst - @remarks does no validation of the inputs. -*/ -posh_i64_t * -POSH_WriteI64ToLittle( void *dst, posh_i64_t value ) -{ - return ( posh_i64_t * ) POSH_WriteU64ToLittle( dst, ( posh_u64_t ) value ); -} - -/** - * Writes an unsigned 64-bit value to a big-endian buffer - - @ingroup SixtyFourBit - @param dst [out] pointer to the destination buffer, may not be NULL - @param value [in] host-endian unsigned 64-bit value - @returns a pointer to the location eight bytes after dst - @remarks does no validation of the inputs. -*/ -posh_u64_t * -POSH_WriteU64ToBig( void *dst, posh_u64_t value ) -{ - posh_u64_t *p64 = ( posh_u64_t * ) dst; - - *p64 = POSH_BigU64(value); - - return p64 + 8; -} - -/** - * Writes a signed 64-bit value to a big-endian buffer - - @ingroup SixtyFourBit - @param dst [out] pointer to the destination buffer, may not be NULL - @param value [in] host-endian signed 64-bit value - @returns a pointer to the location eight bytes after dst - @remarks does no validation of the inputs. -*/ -posh_i64_t * -POSH_WriteI64ToBig( void *dst, posh_i64_t value ) -{ - return ( posh_i64_t * ) POSH_WriteU64ToBig( dst, ( posh_u64_t ) value ); -} - -#endif /* POSH_64BIT_INTEGER */ - -/* ---------------------------------------------------------------------------*/ -/* IN-MEMORY DESERIALIZATION */ -/* ---------------------------------------------------------------------------*/ - -/** - * Reads an unsigned 16-bit value from a little-endian buffer - @param src [in] source buffer - @returns host-endian unsigned 16-bit value -*/ -posh_u16_t -POSH_ReadU16FromLittle( const void *src ) -{ - return POSH_LittleU16( (*(const posh_u16_t*)src) ); -} - -/** - * Reads a signed 16-bit value from a little-endian buffer - @param src [in] source buffer - @returns host-endian signed 16-bit value -*/ -posh_i16_t -POSH_ReadI16FromLittle( const void *src ) -{ - return POSH_LittleI16( (*(const posh_i16_t*)src) ); -} - -/** - * Reads an unsigned 32-bit value from a little-endian buffer - @param src [in] source buffer - @returns host-endian unsigned 32-bit value -*/ -posh_u32_t -POSH_ReadU32FromLittle( const void *src ) -{ - return POSH_LittleU32( (*(const posh_u32_t*)src) ); -} - -/** - * Reads a signed 32-bit value from a little-endian buffer - @param src [in] source buffer - @returns host-endian signed 32-bit value -*/ -posh_i32_t -POSH_ReadI32FromLittle( const void *src ) -{ - return POSH_LittleI32( (*(const posh_i32_t*)src) ); -} - - -/** - * Reads an unsigned 16-bit value from a big-endian buffer - @param src [in] source buffer - @returns host-endian unsigned 16-bit value -*/ -posh_u16_t -POSH_ReadU16FromBig( const void *src ) -{ - return POSH_BigU16( (*(const posh_u16_t*)src) ); -} - -/** - * Reads a signed 16-bit value from a big-endian buffer - @param src [in] source buffer - @returns host-endian signed 16-bit value -*/ -posh_i16_t -POSH_ReadI16FromBig( const void *src ) -{ - return POSH_BigI16( (*(const posh_i16_t*)src)); -} - -/** - * Reads an unsigned 32-bit value from a big-endian buffer - @param src [in] source buffer - @returns host-endian unsigned 32-bit value -*/ -posh_u32_t -POSH_ReadU32FromBig( const void *src ) -{ - return POSH_BigU32( (*(const posh_u32_t*)src) ); -} - -/** - * Reads a signed 32-bit value from a big-endian buffer - @param src [in] source buffer - @returns host-endian signed 32-bit value -*/ -posh_i32_t -POSH_ReadI32FromBig( const void *src ) -{ - return POSH_BigI32( (*(const posh_i32_t*)src ) ); -} - -#if defined POSH_64BIT_INTEGER - -/** - * Reads an unsigned 64-bit value from a little-endian buffer - @param src [in] source buffer - @returns host-endian unsigned 32-bit value -*/ -posh_u64_t -POSH_ReadU64FromLittle( const void *src ) -{ - return POSH_LittleU64( (*(const posh_u64_t*)src) ); -} - -/** - * Reads a signed 64-bit value from a little-endian buffer - @param src [in] source buffer - @returns host-endian signed 32-bit value -*/ -posh_i64_t -POSH_ReadI64FromLittle( const void *src ) -{ - return POSH_LittleI64( (*(const posh_i64_t*)src) ); -} - -/** - * Reads an unsigned 64-bit value from a big-endian buffer - @param src [in] source buffer - @returns host-endian unsigned 32-bit value -*/ -posh_u64_t -POSH_ReadU64FromBig( const void *src ) -{ - return POSH_BigU64( (*(const posh_u64_t*)src) ); -} - -/** - * Reads an signed 64-bit value from a big-endian buffer - @param src [in] source buffer - @returns host-endian signed 32-bit value -*/ -posh_i64_t -POSH_ReadI64FromBig( const void *src ) -{ - return POSH_BigI64( (*(const posh_i64_t*)src) ); -} - -#endif /* POSH_64BIT_INTEGER */ - -/* ---------------------------------------------------------------------------*/ -/* FLOATING POINT SUPPORT */ -/* ---------------------------------------------------------------------------*/ - -#if !defined POSH_NO_FLOAT - -/** @ingroup FloatingPoint - @param[in] f floating point value - @returns a little-endian bit representation of f - */ -posh_u32_t -POSH_LittleFloatBits( float f ) -{ - union - { - float f32; - posh_u32_t u32; - } u; - - u.f32 = f; - -#if defined POSH_LITTLE_ENDIAN - return u.u32; -#else - return POSH_SwapU32( u.u32 ); -#endif -} - -/** - * Extracts raw big-endian bits from a 32-bit floating point value - * - @ingroup FloatingPoint - @param f [in] floating point value - @returns a big-endian bit representation of f - */ -posh_u32_t -POSH_BigFloatBits( float f ) -{ - union - { - float f32; - posh_u32_t u32; - } u; - - u.f32 = f; - -#if defined POSH_LITTLE_ENDIAN - return POSH_SwapU32( u.u32 ); -#else - return u.u32; -#endif -} - -/** - * Extracts raw, little-endian bit representation from a 64-bit double. - * - @param d [in] 64-bit double precision value - @param dst [out] 8-byte storage buffer - @ingroup FloatingPoint - @returns the raw bits used to represent the value 'd', in the form dst[0]=LSB - */ -void -POSH_DoubleBits( double d, posh_byte_t dst[ 8 ] ) -{ - union - { - double d64; - posh_byte_t bytes[ 8 ]; - } u; - - u.d64 = d; - -#if defined POSH_LITTLE_ENDIAN - dst[ 0 ] = u.bytes[ 0 ]; - dst[ 1 ] = u.bytes[ 1 ]; - dst[ 2 ] = u.bytes[ 2 ]; - dst[ 3 ] = u.bytes[ 3 ]; - dst[ 4 ] = u.bytes[ 4 ]; - dst[ 5 ] = u.bytes[ 5 ]; - dst[ 6 ] = u.bytes[ 6 ]; - dst[ 7 ] = u.bytes[ 7 ]; -#else - dst[ 0 ] = u.bytes[ 7 ]; - dst[ 1 ] = u.bytes[ 6 ]; - dst[ 2 ] = u.bytes[ 5 ]; - dst[ 3 ] = u.bytes[ 4 ]; - dst[ 4 ] = u.bytes[ 3 ]; - dst[ 5 ] = u.bytes[ 2 ]; - dst[ 6 ] = u.bytes[ 1 ]; - dst[ 7 ] = u.bytes[ 0 ]; -#endif -} - -/** - * Creates a double-precision, 64-bit floating point value from a set of raw, - * little-endian bits - - @ingroup FloatingPoint - @param src [in] little-endian byte representation of 64-bit double precision - floating point value - @returns double precision floating point representation of the raw bits - @remarks No error checking is performed, so there are no guarantees that the - result is a valid number, nor is there any check to ensure that src is - non-NULL. BE CAREFUL USING THIS. - */ -double -POSH_DoubleFromBits( const posh_byte_t src[ 8 ] ) -{ - union - { - double d64; - posh_byte_t bytes[ 8 ]; - } u; - -#if defined POSH_LITTLE_ENDIAN - u.bytes[ 0 ] = src[ 0 ]; - u.bytes[ 1 ] = src[ 1 ]; - u.bytes[ 2 ] = src[ 2 ]; - u.bytes[ 3 ] = src[ 3 ]; - u.bytes[ 4 ] = src[ 4 ]; - u.bytes[ 5 ] = src[ 5 ]; - u.bytes[ 6 ] = src[ 6 ]; - u.bytes[ 7 ] = src[ 7 ]; -#else - u.bytes[ 0 ] = src[ 7 ]; - u.bytes[ 1 ] = src[ 6 ]; - u.bytes[ 2 ] = src[ 5 ]; - u.bytes[ 3 ] = src[ 4 ]; - u.bytes[ 4 ] = src[ 3 ]; - u.bytes[ 5 ] = src[ 2 ]; - u.bytes[ 6 ] = src[ 1 ]; - u.bytes[ 7 ] = src[ 0 ]; -#endif - - return u.d64; -} - -/** - * Creates a floating point number from little endian bits - * - @ingroup FloatingPoint - @param bits [in] raw floating point bits in little-endian form - @returns a floating point number based on the given bit representation - @remarks No error checking is performed, so there are no guarantees that the - result is a valid number. BE CAREFUL USING THIS. - */ -float -POSH_FloatFromLittleBits( posh_u32_t bits ) -{ - union - { - float f32; - posh_u32_t u32; - } u; - - u.u32 = bits; -#if defined POSH_BIG_ENDIAN - u.u32 = POSH_SwapU32( u.u32 ); -#endif - - return u.f32; -} - -/** - * Creates a floating point number from big-endian bits - * - @ingroup FloatingPoint - @param bits [in] raw floating point bits in big-endian form - @returns a floating point number based on the given bit representation - @remarks No error checking is performed, so there are no guarantees that the - result is a valid number. BE CAREFUL USING THIS. - */ -float -POSH_FloatFromBigBits( posh_u32_t bits ) -{ - union - { - float f32; - posh_u32_t u32; - } u; - - u.u32 = bits; -#if defined POSH_LITTLE_ENDIAN - u.u32 = POSH_SwapU32( u.u32 ); -#endif - - return u.f32; -} - -#endif /* !defined POSH_NO_FLOAT */ +/* +LICENSE: + +Copyright (c) 2004, Brian Hook +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * The names of this package'ss contributors contributors may not + be used to endorse or promote products derived from this + software without specific prior written permission. + + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/** + @file posh.c + @author Brian Hook + @date 2002 + @brief Portable Open Source Harness primary source file +*/ +#include "posh.h" + +#if !defined FORCE_DOXYGEN + +#if !defined POSH_NO_FLOAT +# define POSH_FLOAT_STRING "enabled" +#else +# define POSH_FLOAT_STRING "disabled" +#endif + +#if defined POSH_64BIT_INTEGER +# define POSH_64BIT_INTEGER_STRING "yes" +#else +# define POSH_64BIT_INTEGER_STRING "no" +#endif + +#if defined POSH_64BIT_POINTER +# define POSH_POINTER_STRING "64-bits" +#else +# define POSH_POINTER_STRING "32-bits" +#endif + +#if defined POSH_LITTLE_ENDIAN +# define IS_BIG_ENDIAN 0 + +# define NATIVE16 POSH_LittleU16 +# define NATIVE32 POSH_LittleU32 +# define NATIVE64 POSH_LittleU64 +# define FOREIGN16 POSH_BigU16 +# define FOREIGN32 POSH_BigU32 +# define FOREIGN64 POSH_BigU64 +#else +# define IS_BIG_ENDIAN 1 + +# define NATIVE16 POSH_BigU16 +# define NATIVE32 POSH_BigU32 +# define NATIVE64 POSH_BigU64 +# define FOREIGN16 POSH_LittleU16 +# define FOREIGN32 POSH_LittleU32 +# define FOREIGN64 POSH_LittleU64 +#endif /* POSH_LITTLE_ENDIAN */ + +static +int +s_testBigEndian( void ) +{ + union + { + posh_byte_t c[ 4 ]; + posh_u32_t i; + } u; + + u.i= 1; + + if ( u.c[ 0 ] == 1 ) + { + return 0; + } + return 1; +} + +static +const char * +s_testSerialization( void ) +{ + posh_byte_t serbuf[ 8 ]; + posh_u16_t tmp16; + posh_u32_t tmp32; + + /* 16-bit serialization */ + POSH_WriteU16ToLittle( serbuf, 0xABCD ); + if ( ( tmp16 = POSH_ReadU16FromLittle( serbuf ) ) != 0xABCD ) + { + return "*ERROR: failed little-endian 16-bit serialization test"; + } + + POSH_WriteU16ToBig( serbuf, 0xABCD ); + if ( ( tmp16 = POSH_ReadU16FromBig( serbuf ) ) != 0xABCD ) + { + return "*ERROR: failed big-endian 16-bit serialization test"; + } + + /* 32-bit serialization */ + POSH_WriteU32ToLittle( serbuf, 0xABCD1234L ); + if ( ( tmp32 = POSH_ReadU32FromLittle( serbuf ) ) != 0xABCD1234 ) + { + return "*ERROR: failed little-endian 32-bit serialization test"; + } + + POSH_WriteU32ToBig( serbuf, 0xABCD1234L ); + if ( ( tmp32 = POSH_ReadU32FromBig( serbuf ) ) != 0xABCD1234 ) + { + return "*ERROR: failed big-endian 32-bit serialization test"; + } + +#if defined POSH_64BIT_INTEGER + { +#define REF64 POSH_U64(0xFEDCBA9876543210) + + posh_u64_t tmp64; + + POSH_WriteU64ToLittle( serbuf, REF64 ); + + if ( ( tmp64 = POSH_ReadU64FromLittle( serbuf ) ) != REF64 ) + { + return "*ERROR: failed little-endian 64-bit serialization test"; + } + + POSH_WriteU64ToBig( serbuf, REF64 ); + + if ( ( tmp64 = POSH_ReadU64FromBig( serbuf ) ) != REF64 ) + { + return "*ERROR: failed big-endian 64-bit serialization test"; + } + } +#endif + + return 0; +} + +#if !defined POSH_NO_FLOAT +static +const char * +s_testFloatingPoint( void ) +{ + float fRef = 10.0f/30.0f; + double dRef = 10.0/30.0; + posh_byte_t dbuf[ 8 ]; + float fTmp; + double dTmp; + + fTmp = POSH_FloatFromLittleBits( POSH_LittleFloatBits( fRef ) ); + + if ( fTmp != fRef ) + { + return "*ERROR: POSH little endian floating point conversion failed. Please report this to poshlib@poshlib.org!\n"; + } + + fTmp = POSH_FloatFromBigBits( POSH_BigFloatBits( fRef ) ); + if ( fTmp != fRef ) + { + return "*ERROR: POSH big endian floating point conversion failed. Please report this to poshlib@poshlib.org!\n"; + } + + POSH_DoubleBits( dRef, dbuf ); + + dTmp = POSH_DoubleFromBits( dbuf ); + + if ( dTmp != dRef ) + { + return "*ERROR: POSH double precision floating point serialization failed. Please report this to poshlib@poshlib.org!\n"; + } + + return 0; +} +#endif /* !defined POSH_NO_FLOAT */ + +static +const char * +s_testEndianess( void ) +{ + /* check endianess */ + if ( s_testBigEndian() != IS_BIG_ENDIAN ) + { + return "*ERROR: POSH compile time endianess does not match run-time endianess verification. Please report this to poshlib@poshlib.org!\n"; + } + + /* make sure our endian swap routines work */ + if ( ( NATIVE32( 0x11223344L ) != 0x11223344L ) || + ( FOREIGN32( 0x11223344L ) != 0x44332211L ) || + ( NATIVE16( 0x1234 ) != 0x1234 ) || + ( FOREIGN16( 0x1234 ) != 0x3412 ) ) + { + return "*ERROR: POSH endianess macro selection failed. Please report this to poshlib@poshlib.org!\n"; + } + + /* test serialization routines */ + + return 0; +} +#endif /* !defined FORCE_DOXYGEN */ + +/** + Returns a string describing this platform's basic attributes. + + POSH_GetArchString() reports on an architecture's statically determined + attributes. In addition, it will perform run-time verification checks + to make sure the various platform specific functions work. If an error + occurs, please contact me at poshlib@poshlib.org so we can try to resolve + what the specific failure case is. + @returns a string describing this platform on success, or a string in the + form "*ERROR: [text]" on failure. You can simply check to see if + the first character returned is '*' to verify an error condition. +*/ +const char * +POSH_GetArchString( void ) +{ + const char *err; + const char *s = "OS:.............."POSH_OS_STRING"\n" + "CPU:............."POSH_CPU_STRING"\n" + "endian:.........."POSH_ENDIAN_STRING"\n" + "ptr size:........"POSH_POINTER_STRING"\n" + "64-bit ints......"POSH_64BIT_INTEGER_STRING"\n" + "floating point..."POSH_FLOAT_STRING"\n" + "compiler........."POSH_COMPILER_STRING"\n"; + + /* test endianess */ + err = s_testEndianess(); + + if ( err != 0 ) + { + return err; + } + + /* test serialization */ + err = s_testSerialization(); + + if ( err != 0 ) + { + return err; + } + +#if !defined POSH_NO_FLOAT + /* check that our floating point support is correct */ + err = s_testFloatingPoint(); + + if ( err != 0 ) + { + return err; + } + +#endif + + return s; +} + +/* ---------------------------------------------------------------------------*/ +/* BYTE SWAPPING SUPPORT */ +/* ---------------------------------------------------------------------------*/ +/** + * Byte swaps a 16-bit unsigned value + * + @ingroup ByteSwapFunctions + @param v [in] unsigned 16-bit input value to swap + @returns a byte swapped version of v + */ +posh_u16_t +POSH_SwapU16( posh_u16_t v ) +{ + posh_u16_t swapped; + + swapped = v << 8; + swapped |= v >> 8; + + return swapped; +} + +/** + * Byte swaps a 16-bit signed value + * + @ingroup ByteSwapFunctions + @param v [in] signed 16-bit input value to swap + @returns a byte swapped version of v + @remarks This just calls back to the unsigned version, since byte swapping + is independent of sign. However, we still provide this function to + avoid signed/unsigned mismatch compiler warnings. + */ +posh_i16_t +POSH_SwapI16( posh_i16_t v ) +{ + return ( posh_i16_t ) POSH_SwapU16( v ); +} + +/** + * Byte swaps a 32-bit unsigned value + * + @ingroup ByteSwapFunctions + @param v [in] unsigned 32-bit input value to swap + @returns a byte swapped version of v + */ +posh_u32_t +POSH_SwapU32( posh_u32_t v ) +{ + posh_u32_t swapped; + + swapped = ( v & 0xFF ) << 24; + swapped |= ( v & 0xFF00 ) << 8; + swapped |= ( v >> 8 ) & 0xFF00; + swapped |= ( v >> 24 ); + + return swapped; +} + +/** + * Byte swaps a 32-bit signed value + * + @ingroup ByteSwapFunctions + @param v [in] signed 32-bit input value to swap + @returns a byte swapped version of v + @remarks This just calls back to the unsigned version, since byte swapping + is independent of sign. However, we still provide this function to + avoid signed/unsigned mismatch compiler warnings. + */ +posh_i32_t +POSH_SwapI32( posh_i32_t v ) +{ + return ( posh_i32_t ) POSH_SwapU32( ( posh_u32_t ) v ); +} + +#if defined POSH_64BIT_INTEGER +/** + * Byte swaps a 64-bit unsigned value + + @param v [in] a 64-bit input value to swap + @ingroup SixtyFourBit + @returns a byte swapped version of v +*/ +posh_u64_t +POSH_SwapU64( posh_u64_t v ) +{ + posh_byte_t tmp; + union { + posh_byte_t bytes[ 8 ]; + posh_u64_t u64; + } u; + + u.u64 = v; + + tmp = u.bytes[ 0 ]; u.bytes[ 0 ] = u.bytes[ 7 ]; u.bytes[ 7 ] = tmp; + tmp = u.bytes[ 1 ]; u.bytes[ 1 ] = u.bytes[ 6 ]; u.bytes[ 6 ] = tmp; + tmp = u.bytes[ 2 ]; u.bytes[ 2 ] = u.bytes[ 5 ]; u.bytes[ 5 ] = tmp; + tmp = u.bytes[ 3 ]; u.bytes[ 3 ] = u.bytes[ 4 ]; u.bytes[ 4 ] = tmp; + + return u.u64; +} + +/** + * Byte swaps a 64-bit signed value + + @param v [in] a 64-bit input value to swap + @ingroup SixtyFourBit + @returns a byte swapped version of v +*/ +posh_i64_t +POSH_SwapI64( posh_i64_t v ) +{ + return ( posh_i64_t ) POSH_SwapU64( ( posh_u64_t ) v ); +} + +#endif /* defined POSH_64BIT_INTEGER */ + +/* ---------------------------------------------------------------------------*/ +/* IN-MEMORY SERIALIZATION */ +/* ---------------------------------------------------------------------------*/ + +/** + * Writes an unsigned 16-bit value to a little endian buffer + + @ingroup MemoryBuffer + @param dst [out] pointer to the destination buffer, may not be NULL. Alignment doesn't matter. + @param value [in] host-endian unsigned 16-bit value + @returns a pointer to the location two bytes after dst + @remarks does no validation of the inputs +*/ +posh_u16_t * +POSH_WriteU16ToLittle( void *dst, posh_u16_t value ) +{ + posh_u16_t *p16 = ( posh_u16_t * ) dst; + posh_byte_t *p = ( posh_byte_t * ) dst; + + p[ 0 ] = value & 0xFF; + p[ 1 ] = ( value & 0xFF00) >> 8; + + return p16 + 1; +} + +/** + * Writes a signed 16-bit value to a little endian buffer + + @ingroup MemoryBuffer + @param dst [out] pointer to the destination buffer, may not be NULL + @param value [in] host-endian signed 16-bit value + @returns a pointer to the location two bytes after dst + @remarks does no validation of the inputs. This simply calls + POSH_WriteU16ToLittle() with appropriate casting. +*/ +posh_i16_t * +POSH_WriteI16ToLittle( void *dst, posh_i16_t value ) +{ + return ( posh_i16_t * ) POSH_WriteU16ToLittle( dst, ( posh_u16_t ) value ); +} + +/** + * Writes an unsigned 32-bit value to a little endian buffer + + @ingroup MemoryBuffer + @param dst [out] pointer to the destination buffer, may not be NULL + @param value [in] host-endian signed 32-bit value + @returns a pointer to the location four bytes after dst + @remarks does no validation of the inputs. +*/ +posh_u32_t * +POSH_WriteU32ToLittle( void *dst, posh_u32_t value ) +{ + posh_u32_t *p32 = ( posh_u32_t * ) dst; + posh_byte_t *p = ( posh_byte_t * ) dst; + + p[ 0 ] = ( value & 0xFF ); + p[ 1 ] = ( value & 0xFF00 ) >> 8; + p[ 2 ] = ( value & 0xFF0000 ) >> 16; + p[ 3 ] = ( value & 0xFF000000 ) >> 24; + + return p32 + 1; +} + +/** + * Writes a signed 32-bit value to a little endian buffer + + @ingroup MemoryBuffer + @param dst [out] pointer to the destination buffer, may not be NULL + @param value [in] host-endian signed 32-bit value + @returns a pointer to the location four bytes after dst + @remarks does no validation of the inputs. This simply calls + POSH_WriteU32ToLittle() with appropriate casting. +*/ +posh_i32_t * +POSH_WriteI32ToLittle( void *dst, posh_i32_t value ) +{ + return ( posh_i32_t * ) POSH_WriteU32ToLittle( dst, ( posh_u32_t ) value ); +} + +/** + * Writes an unsigned 16-bit value to a big endian buffer + + @ingroup MemoryBuffer + @param dst [out] pointer to the destination buffer, may not be NULL + @param value [in] host-endian unsigned 16-bit value + @returns a pointer to the location two bytes after dst + @remarks does no validation of the inputs +*/ +posh_u16_t * +POSH_WriteU16ToBig( void *dst, posh_u16_t value ) +{ + posh_u16_t *p16 = ( posh_u16_t * ) dst; + posh_byte_t *p = ( posh_byte_t * ) dst; + + p[ 1 ] = ( value & 0xFF ); + p[ 0 ] = ( value & 0xFF00 ) >> 8; + + return p16 + 1; +} + +/** + * Writes a signed 16-bit value to a big endian buffer + + @ingroup MemoryBuffer + @param dst [out] pointer to the destination buffer, may not be NULL + @param value [in] host-endian signed 16-bit value + @returns a pointer to the location two bytes after dst + @remarks does no validation of the inputs. This simply calls + POSH_WriteU16ToLittle() with appropriate casting. +*/ +posh_i16_t * +POSH_WriteI16ToBig( void *dst, posh_i16_t value ) +{ + return ( posh_i16_t * ) POSH_WriteU16ToBig( dst, ( posh_u16_t ) value ); +} + +/** + * Writes an unsigned 32-bit value to a big endian buffer + + @ingroup MemoryBuffer + @param dst [out] pointer to the destination buffer, may not be NULL + @param value [in] host-endian unsigned 32-bit value + @returns a pointer to the location four bytes after dst + @remarks does no validation of the inputs. +*/ +posh_u32_t * +POSH_WriteU32ToBig( void *dst, posh_u32_t value ) +{ + posh_u32_t *p32 = ( posh_u32_t * ) dst; + posh_byte_t *p = ( posh_byte_t * ) dst; + + p[ 3 ] = ( value & 0xFF ); + p[ 2 ] = ( value & 0xFF00 ) >> 8; + p[ 1 ] = ( value & 0xFF0000 ) >> 16; + p[ 0 ] = ( value & 0xFF000000 ) >> 24; + + return p32 + 1; +} + +/** + * Writes a signed 32-bit value to a big endian buffer + + @ingroup MemoryBuffer + @param dst [out] pointer to the destination buffer, may not be NULL + @param value [in] host-endian signed 32-bit value + @returns a pointer to the location four bytes after dst + @remarks does no validation of the inputs. This simply calls + POSH_WriteU32ToBig() with appropriate casting. +*/ +posh_i32_t * +POSH_WriteI32ToBig( void *dst, posh_i32_t value ) +{ + return ( posh_i32_t * ) POSH_WriteU32ToBig( dst, ( posh_u32_t ) value ); +} + +#if defined POSH_64BIT_INTEGER +/** + * Writes an unsigned 64-bit value to a little-endian buffer + + @ingroup SixtyFourBit + @param dst [out] pointer to the destination buffer, may not be NULL + @param value [in] host-endian unsigned 64-bit value + @returns a pointer to the location eight bytes after dst + @remarks does no validation of the inputs. +*/ +posh_u64_t * +POSH_WriteU64ToLittle( void *dst, posh_u64_t value ) +{ + posh_u64_t *p64 = ( posh_u64_t * ) dst; + posh_byte_t *p = ( posh_byte_t * ) dst; + int i; + + for ( i = 0; i < 8; i++, value >>= 8 ) + { + p[ i ] = ( posh_byte_t ) ( value & 0xFF ); + } + + return p64 + 1; +} + +/** + * Writes a signed 64-bit value to a little-endian buffer + + @ingroup SixtyFourBit + @param dst [out] pointer to the destination buffer, may not be NULL + @param value [in] host-endian unsigned 64-bit value + @returns a pointer to the location eight bytes after dst + @remarks does no validation of the inputs. +*/ +posh_i64_t * +POSH_WriteI64ToLittle( void *dst, posh_i64_t value ) +{ + return ( posh_i64_t * ) POSH_WriteU64ToLittle( dst, ( posh_u64_t ) value ); +} + +/** + * Writes an unsigned 64-bit value to a big-endian buffer + + @ingroup SixtyFourBit + @param dst [out] pointer to the destination buffer, may not be NULL + @param value [in] host-endian unsigned 64-bit value + @returns a pointer to the location eight bytes after dst + @remarks does no validation of the inputs. +*/ +posh_u64_t * +POSH_WriteU64ToBig( void *dst, posh_u64_t value ) +{ + posh_u64_t *p64 = ( posh_u64_t * ) dst; + posh_byte_t *p = ( posh_byte_t * ) dst; + int i; + + for ( i = 0; i < 8; i++, value >>= 8 ) + { + p[ 7-i ] = ( posh_byte_t ) ( value & 0xFF ); + } + + return p64 + 8; +} + +/** + * Writes a signed 64-bit value to a big-endian buffer + + @ingroup SixtyFourBit + @param dst [out] pointer to the destination buffer, may not be NULL + @param value [in] host-endian signed 64-bit value + @returns a pointer to the location eight bytes after dst + @remarks does no validation of the inputs. +*/ +posh_i64_t * +POSH_WriteI64ToBig( void *dst, posh_i64_t value ) +{ + return ( posh_i64_t * ) POSH_WriteU64ToBig( dst, ( posh_u64_t ) value ); +} + +#endif /* POSH_64BIT_INTEGER */ + +/* ---------------------------------------------------------------------------*/ +/* IN-MEMORY DESERIALIZATION */ +/* ---------------------------------------------------------------------------*/ + +/** + * Reads an unsigned 16-bit value from a little-endian buffer + @ingroup MemoryBuffer + @param src [in] source buffer + @returns host-endian unsigned 16-bit value +*/ +posh_u16_t +POSH_ReadU16FromLittle( const void *src ) +{ + posh_u16_t v = 0; + posh_byte_t *p = ( posh_byte_t * ) src; + + v |= p[ 0 ]; + v |= ( ( posh_u16_t ) p[ 1 ] ) << 8; + + return v; +} + +/** + * Reads a signed 16-bit value from a little-endian buffer + @ingroup MemoryBuffer + @param src [in] source buffer + @returns host-endian signed 16-bit value +*/ +posh_i16_t +POSH_ReadI16FromLittle( const void *src ) +{ + return ( posh_i16_t ) POSH_ReadU16FromLittle( src ); +} + +/** + * Reads an unsigned 32-bit value from a little-endian buffer + @ingroup MemoryBuffer + @param src [in] source buffer + @returns host-endian unsigned 32-bit value +*/ +posh_u32_t +POSH_ReadU32FromLittle( const void *src ) +{ + posh_u32_t v = 0; + posh_byte_t *p = ( posh_byte_t * ) src; + + v |= p[ 0 ]; + v |= ( ( posh_u32_t ) p[ 1 ] ) << 8; + v |= ( ( posh_u32_t ) p[ 2 ] ) << 16; + v |= ( ( posh_u32_t ) p[ 3 ] ) << 24; + + return v; +} + +/** + * Reads a signed 32-bit value from a little-endian buffer + @ingroup MemoryBuffer + @param src [in] source buffer + @returns host-endian signed 32-bit value +*/ +posh_i32_t +POSH_ReadI32FromLittle( const void *src ) +{ + return ( posh_i32_t ) POSH_ReadU32FromLittle( src ); +} + + +/** + * Reads an unsigned 16-bit value from a big-endian buffer + @ingroup MemoryBuffer + @param src [in] source buffer + @returns host-endian unsigned 16-bit value +*/ +posh_u16_t +POSH_ReadU16FromBig( const void *src ) +{ + posh_u16_t v = 0; + posh_byte_t *p = ( posh_byte_t * ) src; + + v |= p[ 1 ]; + v |= ( ( posh_u16_t ) p[ 0 ] ) << 8; + + return v; +} + +/** + * Reads a signed 16-bit value from a big-endian buffer + @ingroup MemoryBuffer + @param src [in] source buffer + @returns host-endian signed 16-bit value +*/ +posh_i16_t +POSH_ReadI16FromBig( const void *src ) +{ + return ( posh_i16_t ) POSH_ReadU16FromBig( src ); +} + +/** + * Reads an unsigned 32-bit value from a big-endian buffer + @ingroup MemoryBuffer + @param src [in] source buffer + @returns host-endian unsigned 32-bit value +*/ +posh_u32_t +POSH_ReadU32FromBig( const void *src ) +{ + posh_u32_t v = 0; + posh_byte_t *p = ( posh_byte_t * ) src; + + v |= p[ 3 ]; + v |= ( ( posh_u32_t ) p[ 2 ] ) << 8; + v |= ( ( posh_u32_t ) p[ 1 ] ) << 16; + v |= ( ( posh_u32_t ) p[ 0 ] ) << 24; + + return v; +} + +/** + * Reads a signed 32-bit value from a big-endian buffer + @ingroup MemoryBuffer + @param src [in] source buffer + @returns host-endian signed 32-bit value +*/ +posh_i32_t +POSH_ReadI32FromBig( const void *src ) +{ + return POSH_BigI32( (*(const posh_i32_t*)src ) ); +} + +#if defined POSH_64BIT_INTEGER + +/** + * Reads an unsigned 64-bit value from a little-endian buffer + @param src [in] source buffer + @returns host-endian unsigned 32-bit value +*/ +posh_u64_t +POSH_ReadU64FromLittle( const void *src ) +{ + posh_u64_t v = 0; + posh_byte_t *p = ( posh_byte_t * ) src; + int i; + + for ( i = 0; i < 8; i++ ) + { + v |= ( ( posh_u64_t ) p[ i ] ) << (i*8); + } + + return v; +} + +/** + * Reads a signed 64-bit value from a little-endian buffer + @param src [in] source buffer + @returns host-endian signed 32-bit value +*/ +posh_i64_t +POSH_ReadI64FromLittle( const void *src ) +{ + return ( posh_i64_t ) POSH_ReadU64FromLittle( src ); +} + +/** + * Reads an unsigned 64-bit value from a big-endian buffer + @param src [in] source buffer + @returns host-endian unsigned 32-bit value +*/ +posh_u64_t +POSH_ReadU64FromBig( const void *src ) +{ + posh_u64_t v = 0; + posh_byte_t *p = ( posh_byte_t * ) src; + int i; + + for ( i = 0; i < 8; i++ ) + { + v |= ( ( posh_u64_t ) p[ 7-i ] ) << (i*8); + } + + return v; +} + +/** + * Reads an signed 64-bit value from a big-endian buffer + @param src [in] source buffer + @returns host-endian signed 32-bit value +*/ +posh_i64_t +POSH_ReadI64FromBig( const void *src ) +{ + return ( posh_i64_t ) POSH_ReadU64FromBig( src ); +} + +#endif /* POSH_64BIT_INTEGER */ + +/* ---------------------------------------------------------------------------*/ +/* FLOATING POINT SUPPORT */ +/* ---------------------------------------------------------------------------*/ + +#if !defined POSH_NO_FLOAT + +/** @ingroup FloatingPoint + @param[in] f floating point value + @returns a little-endian bit representation of f + */ +posh_u32_t +POSH_LittleFloatBits( float f ) +{ + union + { + float f32; + posh_u32_t u32; + } u; + + u.f32 = f; + + return POSH_LittleU32( u.u32 ); +} + +/** + * Extracts raw big-endian bits from a 32-bit floating point value + * + @ingroup FloatingPoint + @param f [in] floating point value + @returns a big-endian bit representation of f + */ +posh_u32_t +POSH_BigFloatBits( float f ) +{ + union + { + float f32; + posh_u32_t u32; + } u; + + u.f32 = f; + + return POSH_BigU32( u.u32 ); +} + +/** + * Extracts raw, little-endian bit representation from a 64-bit double. + * + @param d [in] 64-bit double precision value + @param dst [out] 8-byte storage buffer + @ingroup FloatingPoint + @returns the raw bits used to represent the value 'd', in the form dst[0]=LSB + */ +void +POSH_DoubleBits( double d, posh_byte_t dst[ 8 ] ) +{ + union + { + double d64; + posh_byte_t bytes[ 8 ]; + } u; + + u.d64 = d; + +#if defined POSH_LITTLE_ENDIAN + dst[ 0 ] = u.bytes[ 0 ]; + dst[ 1 ] = u.bytes[ 1 ]; + dst[ 2 ] = u.bytes[ 2 ]; + dst[ 3 ] = u.bytes[ 3 ]; + dst[ 4 ] = u.bytes[ 4 ]; + dst[ 5 ] = u.bytes[ 5 ]; + dst[ 6 ] = u.bytes[ 6 ]; + dst[ 7 ] = u.bytes[ 7 ]; +#else + dst[ 0 ] = u.bytes[ 7 ]; + dst[ 1 ] = u.bytes[ 6 ]; + dst[ 2 ] = u.bytes[ 5 ]; + dst[ 3 ] = u.bytes[ 4 ]; + dst[ 4 ] = u.bytes[ 3 ]; + dst[ 5 ] = u.bytes[ 2 ]; + dst[ 6 ] = u.bytes[ 1 ]; + dst[ 7 ] = u.bytes[ 0 ]; +#endif +} + +/** + * Creates a double-precision, 64-bit floating point value from a set of raw, + * little-endian bits + + @ingroup FloatingPoint + @param src [in] little-endian byte representation of 64-bit double precision + floating point value + @returns double precision floating point representation of the raw bits + @remarks No error checking is performed, so there are no guarantees that the + result is a valid number, nor is there any check to ensure that src is + non-NULL. BE CAREFUL USING THIS. + */ +double +POSH_DoubleFromBits( const posh_byte_t src[ 8 ] ) +{ + union + { + double d64; + posh_byte_t bytes[ 8 ]; + } u; + +#if defined POSH_LITTLE_ENDIAN + u.bytes[ 0 ] = src[ 0 ]; + u.bytes[ 1 ] = src[ 1 ]; + u.bytes[ 2 ] = src[ 2 ]; + u.bytes[ 3 ] = src[ 3 ]; + u.bytes[ 4 ] = src[ 4 ]; + u.bytes[ 5 ] = src[ 5 ]; + u.bytes[ 6 ] = src[ 6 ]; + u.bytes[ 7 ] = src[ 7 ]; +#else + u.bytes[ 0 ] = src[ 7 ]; + u.bytes[ 1 ] = src[ 6 ]; + u.bytes[ 2 ] = src[ 5 ]; + u.bytes[ 3 ] = src[ 4 ]; + u.bytes[ 4 ] = src[ 3 ]; + u.bytes[ 5 ] = src[ 2 ]; + u.bytes[ 6 ] = src[ 1 ]; + u.bytes[ 7 ] = src[ 0 ]; +#endif + + return u.d64; +} + +/** + * Creates a floating point number from little endian bits + * + @ingroup FloatingPoint + @param bits [in] raw floating point bits in little-endian form + @returns a floating point number based on the given bit representation + @remarks No error checking is performed, so there are no guarantees that the + result is a valid number. BE CAREFUL USING THIS. + */ +float +POSH_FloatFromLittleBits( posh_u32_t bits ) +{ + union + { + float f32; + posh_u32_t u32; + } u; + + u.u32 = bits; +#if defined POSH_BIG_ENDIAN + u.u32 = POSH_SwapU32( u.u32 ); +#endif + + return u.f32; +} + +/** + * Creates a floating point number from big-endian bits + * + @ingroup FloatingPoint + @param bits [in] raw floating point bits in big-endian form + @returns a floating point number based on the given bit representation + @remarks No error checking is performed, so there are no guarantees that the + result is a valid number. BE CAREFUL USING THIS. + */ +float +POSH_FloatFromBigBits( posh_u32_t bits ) +{ + union + { + float f32; + posh_u32_t u32; + } u; + + u.u32 = bits; +#if defined POSH_LITTLE_ENDIAN + u.u32 = POSH_SwapU32( u.u32 ); +#endif + + return u.f32; +} + +#endif /* !defined POSH_NO_FLOAT */ diff --git a/src/nvcore/poshlib/posh.h b/src/nvcore/poshlib/posh.h index 3ca079b..8cd5a2a 100644 --- a/src/nvcore/poshlib/posh.h +++ b/src/nvcore/poshlib/posh.h @@ -1,989 +1,1007 @@ -/** -@file posh.h -@author Brian Hook - -Header file for POSH, the Portable Open Source Harness project. - -NOTE: Unlike most header files, this one is designed to be included -multiple times, which is why it does not have the @#ifndef/@#define -preamble. - -POSH relies on environment specified preprocessor symbols in order -to infer as much as possible about the target OS/architecture and -the host compiler capabilities. - -NOTE: POSH is simple and focused. It attempts to provide basic -functionality and information, but it does NOT attempt to emulate -missing functionality. I am also not willing to make POSH dirty -and hackish to support truly ancient and/or outmoded and/or bizarre -technologies such as non-ANSI compilers, systems with non-IEEE -floating point formats, segmented 16-bit operating systems, etc. - -Please refer to the accompanying HTML documentation or visit -http://www.poshlib.org for more information on how to use POSH. - -LICENSE: - -Copyright (c) 2004, Brian Hook -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - - * The names of this package'ss contributors contributors may not - be used to endorse or promote products derived from this - software without specific prior written permission. - - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ -/* -I have yet to find an authoritative reference on preprocessor -symbols, but so far this is what I've gleaned: - -GNU GCC/G++: - - __GNUC__: GNU C version - - __GNUG__: GNU C++ compiler - - __sun__ : on Sun platforms - - __svr4__: on Solaris and other SysV R4 platforms - - __mips__: on MIPS processor platforms - - __sparc_v9__: on Sparc 64-bit CPUs - - __sparcv9: 64-bit Solaris - - __MIPSEL__: mips processor, compiled for little endian - - __MIPSEB__: mips processor, compiled for big endian - - _R5900: MIPS/Sony/Toshiba R5900 (PS2) - - mc68000: 68K - - m68000: 68K - - m68k: 68K - - __palmos__: PalmOS - -Intel C/C++ Compiler: - - __ECC : compiler version, IA64 only - - __EDG__ - - __ELF__ - - __GXX_ABI_VERSION - - __i386 : IA-32 only - - __i386__ : IA-32 only - - i386 : IA-32 only - - __ia64 : IA-64 only - - __ia64__ : IA-64 only - - ia64 : IA-64 only - - __ICC : IA-32 only - - __INTEL_COMPILER : IA-32 or IA-64, newer versions only - -Apple's C/C++ Compiler for OS X: - - __APPLE_CC__ - - __APPLE__ - - __BIG_ENDIAN__ - - __APPLE__ - - __ppc__ - - __MACH__ - -DJGPP: - - __MSDOS__ - - __unix__ - - __unix - - __GNUC__ - - __GO32 - - DJGPP - - __i386, __i386, i386 - -Cray's C compiler: - - _ADDR64: if 64-bit pointers - - _UNICOS: - - __unix: - -SGI's CC compiler predefines the following (and more) with -ansi: - - __sgi - - __unix - - __host_mips - - _SYSTYPE_SVR4 - - __mips - - _MIPSEB - - anyone know if there is a predefined symbol for the compiler?! - -MinGW: - - as GnuC but also defines _WIN32, __WIN32, WIN32, _X86_, __i386, __i386__, and several others - - __MINGW32__ - -Cygwin: - - as Gnu C, but also - - __unix__ - - __CYGWIN32__ - -Microsoft Visual Studio predefines the following: - - _MSC_VER - - _WIN32: on Win32 - - _M_IX6 (on x86 systems) - - _M_ALPHA (on DEC AXP systems) - - _SH3: WinCE, Hitachi SH-3 - - _MIPS: WinCE, MIPS - - _ARM: WinCE, ARM - -Sun's C Compiler: - - sun and _sun - - unix and _unix - - sparc and _sparc (SPARC systems only) - - i386 and _i386 (x86 systems only) - - __SVR4 (Solaris only) - - __sparcv9: 64-bit solaris - - __SUNPRO_C - - _LP64: defined in 64-bit LP64 mode, but only if is included - -Borland C/C++ predefines the following: - - __BORLANDC__: - -DEC/Compaq C/C++ on Alpha: - - __alpha - - __arch64__ - - __unix__ (on Tru64 Unix) - - __osf__ - - __DECC - - __DECCXX (C++ compilation) - - __DECC_VER - - __DECCXX_VER - -IBM's AIX compiler: - - __64BIT__ if 64-bit mode - - _AIX - - __IBMC__: C compiler version - - __IBMCPP__: C++ compiler version - - _LONG_LONG: compiler allows long long - -Watcom: - - __WATCOMC__ - - __DOS__ : if targeting DOS - - __386__ : if 32-bit support - - __WIN32__ : if targetin 32-bit Windows - -HP-UX C/C++ Compiler: - - __hpux - - __unix - - __hppa (on PA-RISC) - - __LP64__: if compiled in 64-bit mode - -Metrowerks: - - __MWERKS__ - - __powerpc__ - - _powerc - - __MC68K__ - - macintosh when compiling for MacOS - - __INTEL__ for x86 targets - - __POWERPC__ - -*/ - -#ifndef HAVE_POSH_H -#define HAVE_POSH_H - -/* -** ---------------------------------------------------------------------------- -** Include optionally -** ---------------------------------------------------------------------------- -*/ -#ifdef POSH_USE_LIMITS_H -# include -#endif - -/* -** ---------------------------------------------------------------------------- -** Determine compilation environment -** ---------------------------------------------------------------------------- -*/ -#if defined __ECC || defined __ICC || defined __INTEL_COMPILER -# define POSH_COMPILER_STRING "Intel C/C++" -# define POSH_COMPILER_INTEL 1 -#endif - -#if ( defined __host_mips || defined __sgi ) && !defined __GNUC__ -# define POSH_COMPILER_STRING "MIPSpro C/C++" -# define POSH_COMPILER_MIPSPRO 1 -#endif - -#if defined __hpux && !defined __GNUC__ -# define POSH_COMPILER_STRING "HP-UX CC" -# define POSH_COMPILER_HPCC 1 -#endif - -#if defined __GNUC__ -# define POSH_COMPILER_STRING "Gnu GCC" -# define POSH_COMPILER_GCC 1 -#endif - -#if defined __APPLE_CC__ - /* we don't define the compiler string here, let it be GNU */ -# define POSH_COMPILER_APPLECC 1 -#endif - -#if defined __IBMC__ || defined __IBMCPP__ -# define POSH_COMPILER_STRING "IBM C/C++" -# define POSH_COMPILER_IBM 1 -#endif - -#if defined _MSC_VER -# define POSH_COMPILER_STRING "Microsoft Visual C++" -# define POSH_COMPILER_MSVC 1 -#endif - -#if defined __SUNPRO_C -# define POSH_COMPILER_STRING "Sun Pro" -# define POSH_COMPILER_SUN 1 -#endif - -#if defined __BORLANDC__ -# define POSH_COMPILER_STRING "Borland C/C++" -# define POSH_COMPILER_BORLAND 1 -#endif - -#if defined __MWERKS__ -# define POSH_COMPILER_STRING "MetroWerks CodeWarrior" -# define POSH_COMPILER_METROWERKS 1 -#endif - -#if defined __DECC || defined __DECCXX -# define POSH_COMPILER_STRING "Compaq/DEC C/C++" -# define POSH_COMPILER_DEC 1 -#endif - -#if defined __WATCOMC__ -# define POSH_COMPILER_STRING "Watcom C/C++" -# define POSH_COMPILER_WATCOM 1 -#endif - -#if !defined POSH_COMPILER_STRING -# define POSH_COMPILER_STRING "Unknown compiler" -#endif - -/* -** ---------------------------------------------------------------------------- -** Determine target operating system -** ---------------------------------------------------------------------------- -*/ -#if defined linux || defined __linux__ -# define POSH_OS_LINUX 1 -# define POSH_OS_STRING "Linux" -#endif - -#if defined __CYGWIN32__ -# define POSH_OS_CYGWIN32 1 -# define POSH_OS_STRING "Cygwin" -#endif - -#if defined __MINGW32__ -# define POSH_OS_MINGW 1 -# define POSH_OS_STRING "MinGW" -#endif - -#if defined GO32 && defined DJGPP && defined __MSDOS__ -# define POSH_OS_GO32 1 -# define POSH_OS_STRING "GO32/MS-DOS" -#endif - -/* NOTE: make sure you use /bt=DOS if compiling for 32-bit DOS, - otherwise Watcom assumes host=target */ -#if defined __WATCOMC__ && defined __386__ && defined __DOS__ -# define POSH_OS_DOS32 1 -# define POSH_OS_STRING "DOS/32-bit" -#endif - -#if defined _UNICOS -# define POSH_OS_UNICOS 1 -# define POSH_OS_STRING "UNICOS" -#endif - -#if ( defined __MWERKS__ && defined __powerc && !defined macintosh ) || defined __APPLE_CC__ || defined macosx -# define POSH_OS_OSX 1 -# define POSH_OS_STRING "MacOS X" -#endif - -#if defined __sun__ || defined sun || defined __sun || defined __solaris__ -# if defined __SVR4 || defined __svr4__ || defined __solaris__ -# define POSH_OS_STRING "Solaris" -# define POSH_OS_SOLARIS 1 -# endif -# if !defined POSH_OS_STRING -# define POSH_OS_STRING "SunOS" -# define POSH_OS_SUNOS 1 -# endif -#endif - -#if defined __sgi__ || defined sgi || defined __sgi -# define POSH_OS_IRIX 1 -# define POSH_OS_STRING "Irix" -#endif - -#if defined __hpux__ || defined __hpux -# define POSH_OS_HPUX 1 -# define POSH_OS_STRING "HP-UX" -#endif - -#if defined _AIX -# define POSH_OS_AIX 1 -# define POSH_OS_STRING "AIX" -#endif - -#if ( defined __alpha && defined __osf__ ) -# define POSH_OS_TRU64 1 -# define POSH_OS_STRING "Tru64" -#endif - -#if defined __BEOS__ || defined __beos__ -# define POSH_OS_BEOS 1 -# define POSH_OS_STRING "BeOS" -#endif - -#if defined amiga || defined amigados || defined AMIGA || defined _AMIGA -# define POSH_OS_AMIGA 1 -# define POSH_OS_STRING "Amiga" -#endif - -#if defined __unix__ -# define POSH_OS_UNIX 1 -# if !defined POSH_OS_STRING -# define POSH_OS_STRING "Unix-like(generic)" -# endif -#endif - -#if defined _WIN32_WCE -# define POSH_OS_WINCE 1 -# define POSH_OS_STRING "Windows CE" -#endif - -#if defined _XBOX_VER == 200 -# define POSH_OS_XBOX360 1 -# define POSH_OS_STRING "XBOX-360" -#elif defined _XBOX -# define POSH_OS_XBOX 1 -# define POSH_OS_STRING "XBOX" -#endif - - -#if defined _WIN32 || defined WIN32 || defined __NT__ || defined __WIN32__ -# define POSH_OS_WIN32 1 -# if !defined POSH_OS_XBOX -# if defined _WIN64 -# define POSH_OS_WIN64 1 -# define POSH_OS_STRING "Win64" -# else -# if !defined POSH_OS_STRING -# define POSH_OS_STRING "Win32" -# endif -# endif -# endif -#endif - -#if defined __palmos__ -# define POSH_OS_PALM 1 -# define POSH_OS_STRING "PalmOS" -#endif - -#if defined THINK_C || defined macintosh -# define POSH_OS_MACOS 1 -# define POSH_OS_STRING "MacOS" -#endif - -/* -** ----------------------------------------------------------------------------- -** Determine target CPU -** ----------------------------------------------------------------------------- -*/ -#if defined mc68000 || defined m68k || defined __MC68K__ || defined m68000 -# define POSH_CPU_68K 1 -# define POSH_CPU_STRING "MC68000" -#endif - -#if defined __PPC__ || defined __POWERPC__ || defined powerpc || defined _POWER || defined __ppc__ || defined __powerpc__ -# define POSH_CPU_PPC 1 -# if defined __powerpc64__ -# define POSH_CPU_STRING "PowerPC64" -# else -# define POSH_CPU_STRING "PowerPC" -# endif -#endif - -#if defined _CRAYT3E || defined _CRAYMPP -# define POSH_CPU_CRAYT3E 1 /* target processor is a DEC Alpha 21164 used in a Cray T3E*/ -# define POSH_CPU_STRING "Cray T3E (Alpha 21164)" -#endif - -#if defined CRAY || defined _CRAY && !defined _CRAYT3E -# error Non-AXP Cray systems not supported -#endif - -#if defined _SH3 -# define POSH_CPU_SH3 1 -# define POSH_CPU_STRING "Hitachi SH-3" -#endif - -#if defined __sh4__ || defined __SH4__ -# define POSH_CPU_SH3 1 -# define POSH_CPU_SH4 1 -# define POSH_CPU_STRING "Hitachi SH-4" -#endif - -#if defined __sparc__ || defined __sparc -# if defined __arch64__ || defined __sparcv9 || defined __sparc_v9__ -# define POSH_CPU_SPARC64 1 -# define POSH_CPU_STRING "Sparc/64" -# else -# define POSH_CPU_STRING "Sparc/32" -# endif -# define POSH_CPU_SPARC 1 -#endif - -#if defined ARM || defined __arm__ || defined _ARM -# define POSH_CPU_STRONGARM 1 -# define POSH_CPU_STRING "ARM" -#endif - -#if defined mips || defined __mips__ || defined __MIPS__ || defined _MIPS -# define POSH_CPU_MIPS 1 -# if defined _R5900 -# define POSH_CPU_STRING "MIPS R5900 (PS2)" -# else -# define POSH_CPU_STRING "MIPS" -# endif -#endif - -#if defined __ia64 || defined _M_IA64 || defined __ia64__ -# define POSH_CPU_IA64 1 -# define POSH_CPU_STRING "IA64" -#endif - -#if defined __X86__ || defined __i386__ || defined i386 || defined _M_IX86 || defined __386__ || defined __x86_64__ || defined _M_X64 -# define POSH_CPU_X86 1 -# if defined __x86_64__ || defined _M_X64 -# define POSH_CPU_X86_64 1 -# endif -# if defined POSH_CPU_X86_64 -# define POSH_CPU_STRING "AMD x86-64" -# else -# define POSH_CPU_STRING "Intel 386+" -# endif -#endif - -#if defined __alpha || defined alpha || defined _M_ALPHA || defined __alpha__ -# define POSH_CPU_AXP 1 -# define POSH_CPU_STRING "AXP" -#endif - -#if defined __hppa || defined hppa -# define POSH_CPU_HPPA 1 -# define POSH_CPU_STRING "PA-RISC" -#endif - -#if !defined POSH_CPU_STRING -# error POSH cannot determine target CPU -# define POSH_CPU_STRING "Unknown" /* this is here for Doxygen's benefit */ -#endif - -/* -** ----------------------------------------------------------------------------- -** Attempt to autodetect building for embedded on Sony PS2 -** ----------------------------------------------------------------------------- -*/ -#if !defined POSH_OS_STRING -# if !defined FORCE_DOXYGEN -# define POSH_OS_EMBEDDED 1 -# endif -# if defined _R5900 -# define POSH_OS_STRING "Sony PS2(embedded)" -# else -# define POSH_OS_STRING "Embedded/Unknown" -# endif -#endif - -/* -** --------------------------------------------------------------------------- -** Handle cdecl, stdcall, fastcall, etc. -** --------------------------------------------------------------------------- -*/ -#if defined POSH_CPU_X86 && !defined POSH_CPU_X86_64 -# if defined __GNUC__ -# define POSH_CDECL __attribute__((cdecl)) -# define POSH_STDCALL __attribute__((stdcall)) -# define POSH_FASTCALL __attribute__((fastcall)) -# elif ( defined _MSC_VER || defined __WATCOMC__ || defined __BORLANDC__ || defined __MWERKS__ ) -# define POSH_CDECL __cdecl -# define POSH_STDCALL __stdcall -# define POSH_FASTCALL __fastcall -# endif -#else -# define POSH_CDECL -# define POSH_STDCALL -# define POSH_FASTCALL -#endif - -/* -** --------------------------------------------------------------------------- -** Define POSH_IMPORTEXPORT signature based on POSH_DLL and POSH_BUILDING_LIB -** --------------------------------------------------------------------------- -*/ - -/* -** We undefine this so that multiple inclusions will work -*/ -#if defined POSH_IMPORTEXPORT -# undef POSH_IMPORTEXPORT -#endif - -#if defined POSH_DLL -# if defined POSH_OS_WIN32 -# if defined _MSC_VER -# if ( _MSC_VER >= 800 ) -# if defined POSH_BUILDING_LIB -# define POSH_IMPORTEXPORT __declspec( dllexport ) -# else -# define POSH_IMPORTEXPORT __declspec( dllimport ) -# endif -# else -# if defined POSH_BUILDING_LIB -# define POSH_IMPORTEXPORT __export -# else -# define POSH_IMPORTEXPORT -# endif -# endif -# endif /* defined _MSC_VER */ -# if defined __BORLANDC__ -# if ( __BORLANDC__ >= 0x500 ) -# if defined POSH_BUILDING_LIB -# define POSH_IMPORTEXPORT __declspec( dllexport ) -# else -# define POSH_IMPORTEXPORT __declspec( dllimport ) -# endif -# else -# if defined POSH_BUILDING_LIB -# define POSH_IMPORTEXPORT __export -# else -# define POSH_IMPORTEXPORT -# endif -# endif -# endif /* defined __BORLANDC__ */ - /* for all other compilers, we're just making a blanket assumption */ -# if defined __GNUC__ || defined __WATCOMC__ || defined __MWERKS__ -# if defined POSH_BUILDING_LIB -# define POSH_IMPORTEXPORT __declspec( dllexport ) -# else -# define POSH_IMPORTEXPORT __declspec( dllimport ) -# endif -# endif /* all other compilers */ -# if !defined POSH_IMPORTEXPORT -# error Building DLLs not supported on this compiler (poshlib@poshlib.org if you know how) -# endif -# endif /* defined POSH_OS_WIN32 */ -#endif - -/* On pretty much everything else, we can thankfully just ignore this */ -#if !defined POSH_IMPORTEXPORT -# define POSH_IMPORTEXPORT -#endif - -#if defined FORCE_DOXYGEN -# define POSH_DLL -# define POSH_BUILDING_LIB -# undef POSH_DLL -# undef POSH_BUILDING_LIB -#endif - -/* -** ---------------------------------------------------------------------------- -** (Re)define POSH_PUBLIC_API export signature -** ---------------------------------------------------------------------------- -*/ -#ifdef POSH_PUBLIC_API -# undef POSH_PUBLIC_API -#endif - -#if ( ( defined _MSC_VER ) && ( _MSC_VER < 800 ) ) || ( defined __BORLANDC__ && ( __BORLANDC__ < 0x500 ) ) -# define POSH_PUBLIC_API(rtype) extern rtype POSH_IMPORTEXPORT -#else -# define POSH_PUBLIC_API(rtype) extern POSH_IMPORTEXPORT rtype -#endif - -/* -** ---------------------------------------------------------------------------- -** Try to infer endianess. Basically we just go through the CPUs we know are -** little endian, and assume anything that isn't one of those is big endian. -** As a sanity check, we also do this with operating systems we know are -** little endian, such as Windows. Some processors are bi-endian, such as -** the MIPS series, so we have to be careful about those. -** ---------------------------------------------------------------------------- -*/ -#if defined POSH_CPU_X86 || defined POSH_CPU_AXP || defined POSH_CPU_STRONGARM || defined POSH_OS_WIN32 || defined POSH_OS_WINCE || defined __MIPSEL__ -# define POSH_ENDIAN_STRING "little" -# define POSH_LITTLE_ENDIAN 1 -#else -# define POSH_ENDIAN_STRING "big" -# define POSH_BIG_ENDIAN 1 -#endif - -#if defined FORCE_DOXYGEN -# define POSH_LITTLE_ENDIAN -#endif - -/* -** ---------------------------------------------------------------------------- -** Cross-platform compile time assertion macro -** ---------------------------------------------------------------------------- -*/ -#define POSH_COMPILE_TIME_ASSERT(name, x) typedef int _POSH_dummy_ ## name[(x) ? 1 : -1 ] - -/* -** ---------------------------------------------------------------------------- -** 64-bit Integer -** -** We don't require 64-bit support, nor do we emulate its functionality, we -** simply export it if it's available. Since we can't count on -** for 64-bit support, we ignore the POSH_USE_LIMITS_H directive. -** ---------------------------------------------------------------------------- -*/ -#if defined ( __LP64__ ) || defined ( __powerpc64__ ) || defined POSH_CPU_SPARC64 -# define POSH_64BIT_INTEGER 1 -typedef long posh_i64_t; -typedef unsigned long posh_u64_t; -# define POSH_I64( x ) ((posh_i64_t)x) -# define POSH_U64( x ) ((posh_u64_t)x) -# define POSH_I64_PRINTF_PREFIX "l" -#elif defined _MSC_VER || defined __BORLANDC__ || defined __WATCOMC__ || ( defined __alpha && defined __DECC ) -# define POSH_64BIT_INTEGER 1 -typedef __int64 posh_i64_t; -typedef unsigned __int64 posh_u64_t; -# define POSH_I64( x ) ((posh_i64_t)x) -# define POSH_U64( x ) ((posh_u64_t)x) -# define POSH_I64_PRINTF_PREFIX "I64" -#elif defined __GNUC__ || defined __MWERKS__ || defined __SUNPRO_C || defined __SUNPRO_CC || defined __APPLE_CC__ || defined POSH_OS_IRIX || defined _LONG_LONG || defined _CRAYC -# define POSH_64BIT_INTEGER 1 -typedef long long posh_i64_t; -typedef unsigned long long posh_u64_t; -# define POSH_U64( x ) ((posh_u64_t)(x##LL)) -# define POSH_I64( x ) ((posh_i64_t)(x##LL)) -# define POSH_I64_PRINTF_PREFIX "ll" -#endif - -/* hack */ -#ifdef __MINGW32__ -# undef POSH_I64 -# undef POSH_U64 -# undef POSH_I64_PRINTF_PREFIX -# define POSH_U64( x ) ((posh_u64_t)(x##LL)) -# define POSH_I64( x ) ((posh_i64_t)(x##LL)) -# define POSH_I64_PRINTF_PREFIX "I64" -#endif - -#ifdef FORCE_DOXYGEN -typedef long long posh_i64_t; -typedef unsigned long posh_u64_t; -# define POSH_64BIT_INTEGER -# define POSH_I64_PRINTF_PREFIX -# define POSH_I64(x) -# define POSH_U64(x) -#endif - -/** Minimum value for a 64-bit signed integer */ -#define POSH_I64_MIN POSH_I64(0x8000000000000000) -/** Maximum value for a 64-bit signed integer */ -#define POSH_I64_MAX POSH_I64(0x7FFFFFFFFFFFFFFF) -/** Minimum value for a 64-bit unsigned integer */ -#define POSH_U64_MIN POSH_U64(0) -/** Maximum value for a 64-bit unsigned integer */ -#define POSH_U64_MAX POSH_U64(0xFFFFFFFFFFFFFFFF) - -/* ---------------------------------------------------------------------------- -** Basic Sized Types -** -** These types are expected to be EXACTLY sized so you can use them for -** serialization. -** ---------------------------------------------------------------------------- -*/ -#define POSH_FALSE 0 -#define POSH_TRUE 1 - -typedef int posh_bool_t; -typedef unsigned char posh_byte_t; - -/* NOTE: These assume that CHAR_BIT is 8!! */ -typedef unsigned char posh_u8_t; -typedef signed char posh_i8_t; - -#if defined POSH_USE_LIMITS_H -# if CHAR_BITS > 8 -# error This machine uses 9-bit characters. This is a warning, you can comment this out now. -# endif /* CHAR_BITS > 8 */ - -/* 16-bit */ -# if ( USHRT_MAX == 65535 ) - typedef unsigned short posh_u16_t; - typedef short posh_i16_t; -# else - /* Yes, in theory there could still be a 16-bit character type and shorts are - 32-bits in size...if you find such an architecture, let me know =P */ -# error No 16-bit type found -# endif - -/* 32-bit */ -# if ( INT_MAX == 2147483647 ) - typedef unsigned posh_u32_t; - typedef int posh_i32_t; -# elif ( LONG_MAX == 2147483647 ) - typedef unsigned long posh_u32_t; - typedef long posh_i32_t; -# else - error No 32-bit type found -# endif - -#else /* POSH_USE_LIMITS_H */ - - typedef unsigned short posh_u16_t; - typedef short posh_i16_t; - -# if !defined POSH_OS_PALM - typedef unsigned posh_u32_t; - typedef int posh_i32_t; -# else - typedef unsigned long posh_u32_t; - typedef long posh_i32_t; -# endif -#endif - -/** Minimum value for a byte */ -#define POSH_BYTE_MIN 0 -/** Maximum value for an 8-bit unsigned value */ -#define POSH_BYTE_MAX 255 -/** Minimum value for a byte */ -#define POSH_I16_MIN ( ( posh_i16_t ) 0x8000 ) -/** Maximum value for a 16-bit signed value */ -#define POSH_I16_MAX ( ( posh_i16_t ) 0x7FFF ) -/** Minimum value for a 16-bit unsigned value */ -#define POSH_U16_MIN 0 -/** Maximum value for a 16-bit unsigned value */ -#define POSH_U16_MAX ( ( posh_u16_t ) 0xFFFF ) -/** Minimum value for a 32-bit signed value */ -#define POSH_I32_MIN ( ( posh_i32_t ) 0x80000000 ) -/** Maximum value for a 32-bit signed value */ -#define POSH_I32_MAX ( ( posh_i32_t ) 0x7FFFFFFF ) -/** Minimum value for a 32-bit unsigned value */ -#define POSH_U32_MIN 0 -/** Maximum value for a 32-bit unsigned value */ -#define POSH_U32_MAX ( ( posh_u32_t ) 0xFFFFFFFF ) - -/* -** ---------------------------------------------------------------------------- -** Sanity checks on expected sizes -** ---------------------------------------------------------------------------- -*/ -#if !defined FORCE_DOXYGEN - -POSH_COMPILE_TIME_ASSERT(posh_byte_t, sizeof(posh_byte_t) == 1); -POSH_COMPILE_TIME_ASSERT(posh_u8_t, sizeof(posh_u8_t) == 1); -POSH_COMPILE_TIME_ASSERT(posh_i8_t, sizeof(posh_i8_t) == 1); -POSH_COMPILE_TIME_ASSERT(posh_u16_t, sizeof(posh_u16_t) == 2); -POSH_COMPILE_TIME_ASSERT(posh_i16_t, sizeof(posh_i16_t) == 2); -POSH_COMPILE_TIME_ASSERT(posh_u32_t, sizeof(posh_u32_t) == 4); -POSH_COMPILE_TIME_ASSERT(posh_i32_t, sizeof(posh_i32_t) == 4); - -#if !defined POSH_NO_FLOAT - POSH_COMPILE_TIME_ASSERT(posh_testfloat_t, sizeof(float)==4 ); - POSH_COMPILE_TIME_ASSERT(posh_testdouble_t, sizeof(double)==8); -#endif - -#if defined POSH_64BIT_INTEGER - POSH_COMPILE_TIME_ASSERT(posh_u64_t, sizeof(posh_u64_t) == 8); - POSH_COMPILE_TIME_ASSERT(posh_i64_t, sizeof(posh_i64_t) == 8); -#endif - -#endif - -/* -** ---------------------------------------------------------------------------- -** 64-bit pointer support -** ---------------------------------------------------------------------------- -*/ -#if defined POSH_CPU_AXP && ( defined POSH_OS_TRU64 || defined POSH_OS_LINUX ) -# define POSH_64BIT_POINTER 1 -#endif - -#if defined POSH_CPU_X86_64 && defined POSH_OS_LINUX -# define POSH_64BIT_POINTER 1 -#endif - -#if defined POSH_CPU_SPARC64 || defined POSH_OS_WIN64 || defined __64BIT__ || defined __LP64 || defined _LP64 || defined __LP64__ || defined _ADDR64 || defined _CRAYC -# define POSH_64BIT_POINTER 1 -#endif - -#if defined POSH_64BIT_POINTER - POSH_COMPILE_TIME_ASSERT( posh_64bit_pointer, sizeof( void * ) == 8 ); -#elif !defined FORCE_DOXYGEN -/* if this assertion is hit then you're on a system that either has 64-bit - addressing and we didn't catch it, or you're on a system with 16-bit - pointers. In the latter case, POSH doesn't actually care, we're just - triggering this assertion to make sure you're aware of the situation, - so feel free to delete it. - - If this assertion is triggered on a known 32 or 64-bit platform, - please let us know (poshlib@poshlib.org) */ - POSH_COMPILE_TIME_ASSERT( posh_32bit_pointer, sizeof( void * ) == 4 ); -#endif - -#if defined FORCE_DOXYGEN -# define POSH_64BIT_POINTER -#endif - -/* -** ---------------------------------------------------------------------------- -** POSH Utility Functions -** -** These are optional POSH utility functions that are not required if you don't -** need anything except static checking of your host and target environment. -** -** These functions are NOT wrapped with POSH_PUBLIC_API because I didn't want -** to enforce their export if your own library is only using them internally. -** ---------------------------------------------------------------------------- -*/ -#ifdef __cplusplus -extern "C" { -#endif - -const char *POSH_GetArchString( void ); - -#if !defined POSH_NO_FLOAT - -posh_u32_t POSH_LittleFloatBits( float f ); -posh_u32_t POSH_BigFloatBits( float f ); -float POSH_FloatFromLittleBits( posh_u32_t bits ); -float POSH_FloatFromBigBits( posh_u32_t bits ); - -void POSH_DoubleBits( double d, posh_byte_t dst[ 8 ] ); -double POSH_DoubleFromBits( const posh_byte_t src[ 8 ] ); - -/* unimplemented -float *POSH_WriteFloatToLittle( void *dst, float f ); -float *POSH_WriteFloatToBig( void *dst, float f ); -float POSH_ReadFloatFromLittle( const void *src ); -float POSH_ReadFloatFromBig( const void *src ); - -double *POSH_WriteDoubleToLittle( void *dst, double d ); -double *POSH_WriteDoubleToBig( void *dst, double d ); -double POSH_ReadDoubleFromLittle( const void *src ); -double POSH_ReadDoubleFromBig( const void *src ); -*/ -#endif /* !defined POSH_NO_FLOAT */ - -#if defined FORCE_DOXYGEN -# define POSH_NO_FLOAT -# undef POSH_NO_FLOAT -#endif - - -extern posh_u16_t POSH_SwapU16( posh_u16_t u ); -extern posh_i16_t POSH_SwapI16( posh_i16_t u ); -extern posh_u32_t POSH_SwapU32( posh_u32_t u ); -extern posh_i32_t POSH_SwapI32( posh_i32_t u ); - -#if defined POSH_64BIT_INTEGER - -extern posh_u64_t POSH_SwapU64( posh_u64_t u ); -extern posh_i64_t POSH_SwapI64( posh_i64_t u ); - -#endif /*POSH_64BIT_INTEGER */ - -extern posh_u16_t *POSH_WriteU16ToLittle( void *dst, posh_u16_t value ); -extern posh_i16_t *POSH_WriteI16ToLittle( void *dst, posh_i16_t value ); -extern posh_u32_t *POSH_WriteU32ToLittle( void *dst, posh_u32_t value ); -extern posh_i32_t *POSH_WriteI32ToLittle( void *dst, posh_i32_t value ); - -extern posh_u16_t *POSH_WriteU16ToBig( void *dst, posh_u16_t value ); -extern posh_i16_t *POSH_WriteI16ToBig( void *dst, posh_i16_t value ); -extern posh_u32_t *POSH_WriteU32ToBig( void *dst, posh_u32_t value ); -extern posh_i32_t *POSH_WriteI32ToBig( void *dst, posh_i32_t value ); - -extern posh_u16_t POSH_ReadU16FromLittle( const void *src ); -extern posh_i16_t POSH_ReadI16FromLittle( const void *src ); -extern posh_u32_t POSH_ReadU32FromLittle( const void *src ); -extern posh_i32_t POSH_ReadI32FromLittle( const void *src ); - -extern posh_u16_t POSH_ReadU16FromBig( const void *src ); -extern posh_i16_t POSH_ReadI16FromBig( const void *src ); -extern posh_u32_t POSH_ReadU32FromBig( const void *src ); -extern posh_i32_t POSH_ReadI32FromBig( const void *src ); - -#if defined POSH_64BIT_INTEGER -extern posh_u64_t *POSH_WriteU64ToLittle( void *dst, posh_u64_t value ); -extern posh_i64_t *POSH_WriteI64ToLittle( void *dst, posh_i64_t value ); -extern posh_u64_t *POSH_WriteU64ToBig( void *dst, posh_u64_t value ); -extern posh_i64_t *POSH_WriteI64ToBig( void *dst, posh_i64_t value ); - -extern posh_u64_t POSH_ReadU64FromLittle( const void *src ); -extern posh_i64_t POSH_ReadI64FromLittle( const void *src ); -extern posh_u64_t POSH_ReadU64FromBig( const void *src ); -extern posh_i64_t POSH_ReadI64FromBig( const void *src ); -#endif /* POSH_64BIT_INTEGER */ - -#if defined POSH_LITTLE_ENDIAN - -# define POSH_LittleU16(x) (x) -# define POSH_LittleU32(x) (x) -# define POSH_LittleI16(x) (x) -# define POSH_LittleI32(x) (x) -# if defined POSH_64BIT_INTEGER -# define POSH_LittleU64(x) (x) -# define POSH_LittleI64(x) (x) -# endif /* defined POSH_64BIT_INTEGER */ - -# define POSH_BigU16(x) POSH_SwapU16(x) -# define POSH_BigU32(x) POSH_SwapU32(x) -# define POSH_BigI16(x) POSH_SwapI16(x) -# define POSH_BigI32(x) POSH_SwapI32(x) -# if defined POSH_64BIT_INTEGER -# define POSH_BigU64(x) POSH_SwapU64(x) -# define POSH_BigI64(x) POSH_SwapI64(x) -# endif /* defined POSH_64BIT_INTEGER */ - -#else - -# define POSH_BigU16(x) (x) -# define POSH_BigU32(x) (x) -# define POSH_BigI16(x) (x) -# define POSH_BigI32(x) (x) - -# if defined POSH_64BIT_INTEGER -# define POSH_BigU64(x) (x) -# define POSH_BigI64(x) (x) -# endif /* POSH_64BIT_INTEGER */ - -# define POSH_LittleU16(x) POSH_SwapU16(x) -# define POSH_LittleU32(x) POSH_SwapU32(x) -# define POSH_LittleI16(x) POSH_SwapI16(x) -# define POSH_LittleI32(x) POSH_SwapI32(x) - -# if defined POSH_64BIT_INTEGER -# define POSH_LittleU64(x) POSH_SwapU64(x) -# define POSH_LittleI64(x) POSH_SwapI64(x) -# endif /* POSH_64BIT_INTEGER */ - -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* HAVE_POSH_H */ +/** +@file posh.h +@author Brian Hook +@version 1.3.001 + +Header file for POSH, the Portable Open Source Harness project. + +NOTE: Unlike most header files, this one is designed to be included +multiple times, which is why it does not have the @#ifndef/@#define +preamble. + +POSH relies on environment specified preprocessor symbols in order +to infer as much as possible about the target OS/architecture and +the host compiler capabilities. + +NOTE: POSH is simple and focused. It attempts to provide basic +functionality and information, but it does NOT attempt to emulate +missing functionality. I am also not willing to make POSH dirty +and hackish to support truly ancient and/or outmoded and/or bizarre +technologies such as non-ANSI compilers, systems with non-IEEE +floating point formats, segmented 16-bit operating systems, etc. + +Please refer to the accompanying HTML documentation or visit +http://www.poshlib.org for more information on how to use POSH. + +LICENSE: + +Copyright (c) 2004, Brian Hook +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * The names of this package'ss contributors contributors may not + be used to endorse or promote products derived from this + software without specific prior written permission. + + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +REVISION: + +I've been lax about revision histories, so this starts at, um, 1.3.001. +Sorry for any inconveniences. + +1.3.001 - 2/23/2006 - Incorporated fix for bug reported by Bill Cary, + where I was not detecting Visual Studio + compilation on x86-64 systems. Added check for + _M_X64 which should fix that. + +*/ +/* +I have yet to find an authoritative reference on preprocessor +symbols, but so far this is what I've gleaned: + +GNU GCC/G++: + - __GNUC__: GNU C version + - __GNUG__: GNU C++ compiler + - __sun__ : on Sun platforms + - __svr4__: on Solaris and other SysV R4 platforms + - __mips__: on MIPS processor platforms + - __sparc_v9__: on Sparc 64-bit CPUs + - __sparcv9: 64-bit Solaris + - __MIPSEL__: mips processor, compiled for little endian + - __MIPSEB__: mips processor, compiled for big endian + - _R5900: MIPS/Sony/Toshiba R5900 (PS2) + - mc68000: 68K + - m68000: 68K + - m68k: 68K + - __palmos__: PalmOS + +Intel C/C++ Compiler: + - __ECC : compiler version, IA64 only + - __EDG__ + - __ELF__ + - __GXX_ABI_VERSION + - __i386 : IA-32 only + - __i386__ : IA-32 only + - i386 : IA-32 only + - __ia64 : IA-64 only + - __ia64__ : IA-64 only + - ia64 : IA-64 only + - __ICC : IA-32 only + - __INTEL_COMPILER : IA-32 or IA-64, newer versions only + +Apple's C/C++ Compiler for OS X: + - __APPLE_CC__ + - __APPLE__ + - __BIG_ENDIAN__ + - __APPLE__ + - __ppc__ + - __MACH__ + +DJGPP: + - __MSDOS__ + - __unix__ + - __unix + - __GNUC__ + - __GO32 + - DJGPP + - __i386, __i386, i386 + +Cray's C compiler: + - _ADDR64: if 64-bit pointers + - _UNICOS: + - __unix: + +SGI's CC compiler predefines the following (and more) with -ansi: + - __sgi + - __unix + - __host_mips + - _SYSTYPE_SVR4 + - __mips + - _MIPSEB + - anyone know if there is a predefined symbol for the compiler?! + +MinGW: + - as GnuC but also defines _WIN32, __WIN32, WIN32, _X86_, __i386, __i386__, and several others + - __MINGW32__ + +Cygwin: + - as Gnu C, but also + - __unix__ + - __CYGWIN32__ + +Microsoft Visual Studio predefines the following: + - _MSC_VER + - _WIN32: on Win32 + - _M_IX6 (on x86 systems) + - _M_X64: on x86-64 systems + - _M_ALPHA (on DEC AXP systems) + - _SH3: WinCE, Hitachi SH-3 + - _MIPS: WinCE, MIPS + - _ARM: WinCE, ARM + +Sun's C Compiler: + - sun and _sun + - unix and _unix + - sparc and _sparc (SPARC systems only) + - i386 and _i386 (x86 systems only) + - __SVR4 (Solaris only) + - __sparcv9: 64-bit solaris + - __SUNPRO_C + - _LP64: defined in 64-bit LP64 mode, but only if is included + +Borland C/C++ predefines the following: + - __BORLANDC__: + +DEC/Compaq C/C++ on Alpha: + - __alpha + - __arch64__ + - __unix__ (on Tru64 Unix) + - __osf__ + - __DECC + - __DECCXX (C++ compilation) + - __DECC_VER + - __DECCXX_VER + +IBM's AIX compiler: + - __64BIT__ if 64-bit mode + - _AIX + - __IBMC__: C compiler version + - __IBMCPP__: C++ compiler version + - _LONG_LONG: compiler allows long long + +Watcom: + - __WATCOMC__ + - __DOS__ : if targeting DOS + - __386__ : if 32-bit support + - __WIN32__ : if targetin 32-bit Windows + +HP-UX C/C++ Compiler: + - __hpux + - __unix + - __hppa (on PA-RISC) + - __LP64__: if compiled in 64-bit mode + +Metrowerks: + - __MWERKS__ + - __powerpc__ + - _powerc + - __MC68K__ + - macintosh when compiling for MacOS + - __INTEL__ for x86 targets + - __POWERPC__ + +*/ + +/* +** ---------------------------------------------------------------------------- +** Include optionally +** ---------------------------------------------------------------------------- +*/ +#ifdef POSH_USE_LIMITS_H +# include +#endif + +/* +** ---------------------------------------------------------------------------- +** Determine compilation environment +** ---------------------------------------------------------------------------- +*/ +#if defined __ECC || defined __ICC || defined __INTEL_COMPILER +# define POSH_COMPILER_STRING "Intel C/C++" +# define POSH_COMPILER_INTEL 1 +#endif + +#if ( defined __host_mips || defined __sgi ) && !defined __GNUC__ +# define POSH_COMPILER_STRING "MIPSpro C/C++" +# define POSH_COMPILER_MIPSPRO 1 +#endif + +#if defined __hpux && !defined __GNUC__ +# define POSH_COMPILER_STRING "HP-UX CC" +# define POSH_COMPILER_HPCC 1 +#endif + +#if defined __GNUC__ +# define POSH_COMPILER_STRING "Gnu GCC" +# define POSH_COMPILER_GCC 1 +#endif + +#if defined __APPLE_CC__ + /* we don't define the compiler string here, let it be GNU */ +# define POSH_COMPILER_APPLECC 1 +#endif + +#if defined __IBMC__ || defined __IBMCPP__ +# define POSH_COMPILER_STRING "IBM C/C++" +# define POSH_COMPILER_IBM 1 +#endif + +#if defined _MSC_VER +# define POSH_COMPILER_STRING "Microsoft Visual C++" +# define POSH_COMPILER_MSVC 1 +#endif + +#if defined __SUNPRO_C +# define POSH_COMPILER_STRING "Sun Pro" +# define POSH_COMPILER_SUN 1 +#endif + +#if defined __BORLANDC__ +# define POSH_COMPILER_STRING "Borland C/C++" +# define POSH_COMPILER_BORLAND 1 +#endif + +#if defined __MWERKS__ +# define POSH_COMPILER_STRING "MetroWerks CodeWarrior" +# define POSH_COMPILER_METROWERKS 1 +#endif + +#if defined __DECC || defined __DECCXX +# define POSH_COMPILER_STRING "Compaq/DEC C/C++" +# define POSH_COMPILER_DEC 1 +#endif + +#if defined __WATCOMC__ +# define POSH_COMPILER_STRING "Watcom C/C++" +# define POSH_COMPILER_WATCOM 1 +#endif + +#if !defined POSH_COMPILER_STRING +# define POSH_COMPILER_STRING "Unknown compiler" +#endif + +/* +** ---------------------------------------------------------------------------- +** Determine target operating system +** ---------------------------------------------------------------------------- +*/ +#if defined linux || defined __linux__ +# define POSH_OS_LINUX 1 +# define POSH_OS_STRING "Linux" +#endif + +#if defined __CYGWIN32__ +# define POSH_OS_CYGWIN32 1 +# define POSH_OS_STRING "Cygwin" +#endif + +#if defined GEKKO +# define POSH_OS_GAMECUBE +# define __powerpc__ +# define POSH_OS_STRING "GameCube" +#endif + +#if defined __MINGW32__ +# define POSH_OS_MINGW 1 +# define POSH_OS_STRING "MinGW" +#endif + +#if defined GO32 && defined DJGPP && defined __MSDOS__ +# define POSH_OS_GO32 1 +# define POSH_OS_STRING "GO32/MS-DOS" +#endif + +/* NOTE: make sure you use /bt=DOS if compiling for 32-bit DOS, + otherwise Watcom assumes host=target */ +#if defined __WATCOMC__ && defined __386__ && defined __DOS__ +# define POSH_OS_DOS32 1 +# define POSH_OS_STRING "DOS/32-bit" +#endif + +#if defined _UNICOS +# define POSH_OS_UNICOS 1 +# define POSH_OS_STRING "UNICOS" +#endif + +#if ( defined __MWERKS__ && defined __powerc && !defined macintosh ) || defined __APPLE_CC__ || defined macosx +# define POSH_OS_OSX 1 +# define POSH_OS_STRING "MacOS X" +#endif + +#if defined __sun__ || defined sun || defined __sun || defined __solaris__ +# if defined __SVR4 || defined __svr4__ || defined __solaris__ +# define POSH_OS_STRING "Solaris" +# define POSH_OS_SOLARIS 1 +# endif +# if !defined POSH_OS_STRING +# define POSH_OS_STRING "SunOS" +# define POSH_OS_SUNOS 1 +# endif +#endif + +#if defined __sgi__ || defined sgi || defined __sgi +# define POSH_OS_IRIX 1 +# define POSH_OS_STRING "Irix" +#endif + +#if defined __hpux__ || defined __hpux +# define POSH_OS_HPUX 1 +# define POSH_OS_STRING "HP-UX" +#endif + +#if defined _AIX +# define POSH_OS_AIX 1 +# define POSH_OS_STRING "AIX" +#endif + +#if ( defined __alpha && defined __osf__ ) +# define POSH_OS_TRU64 1 +# define POSH_OS_STRING "Tru64" +#endif + +#if defined __BEOS__ || defined __beos__ +# define POSH_OS_BEOS 1 +# define POSH_OS_STRING "BeOS" +#endif + +#if defined amiga || defined amigados || defined AMIGA || defined _AMIGA +# define POSH_OS_AMIGA 1 +# define POSH_OS_STRING "Amiga" +#endif + +#if defined __unix__ +# define POSH_OS_UNIX 1 +# if !defined POSH_OS_STRING +# define POSH_OS_STRING "Unix-like(generic)" +# endif +#endif + +#if defined _WIN32_WCE +# define POSH_OS_WINCE 1 +# define POSH_OS_STRING "Windows CE" +#endif + +#if defined _XBOX +# define POSH_OS_XBOX 1 +# define POSH_OS_STRING "XBOX" +#endif + +#if defined _WIN32 || defined WIN32 || defined __NT__ || defined __WIN32__ +# define POSH_OS_WIN32 1 +# if !defined POSH_OS_XBOX +# if defined _WIN64 +# define POSH_OS_WIN64 1 +# define POSH_OS_STRING "Win64" +# else +# if !defined POSH_OS_STRING +# define POSH_OS_STRING "Win32" +# endif +# endif +# endif +#endif + +#if defined __palmos__ +# define POSH_OS_PALM 1 +# define POSH_OS_STRING "PalmOS" +#endif + +#if defined THINK_C || defined macintosh +# define POSH_OS_MACOS 1 +# define POSH_OS_STRING "MacOS" +#endif + +/* +** ----------------------------------------------------------------------------- +** Determine target CPU +** ----------------------------------------------------------------------------- +*/ + +#if defined GEKKO +# define POSH_CPU_PPC750 1 +# define POSH_CPU_STRING "IBM PowerPC 750 (NGC)" +#endif + +#if defined mc68000 || defined m68k || defined __MC68K__ || defined m68000 +# define POSH_CPU_68K 1 +# define POSH_CPU_STRING "MC68000" +#endif + +#if defined __PPC__ || defined __POWERPC__ || defined powerpc || defined _POWER || defined __ppc__ || defined __powerpc__ +# define POSH_CPU_PPC 1 +# if !defined POSH_CPU_STRING +# if defined __powerpc64__ +# define POSH_CPU_STRING "PowerPC64" +# else +# define POSH_CPU_STRING "PowerPC" +# endif +# endif +#endif + +#if defined _CRAYT3E || defined _CRAYMPP +# define POSH_CPU_CRAYT3E 1 /* target processor is a DEC Alpha 21164 used in a Cray T3E*/ +# define POSH_CPU_STRING "Cray T3E (Alpha 21164)" +#endif + +#if defined CRAY || defined _CRAY && !defined _CRAYT3E +# error Non-AXP Cray systems not supported +#endif + +#if defined _SH3 +# define POSH_CPU_SH3 1 +# define POSH_CPU_STRING "Hitachi SH-3" +#endif + +#if defined __sh4__ || defined __SH4__ +# define POSH_CPU_SH3 1 +# define POSH_CPU_SH4 1 +# define POSH_CPU_STRING "Hitachi SH-4" +#endif + +#if defined __sparc__ || defined __sparc +# if defined __arch64__ || defined __sparcv9 || defined __sparc_v9__ +# define POSH_CPU_SPARC64 1 +# define POSH_CPU_STRING "Sparc/64" +# else +# define POSH_CPU_STRING "Sparc/32" +# endif +# define POSH_CPU_SPARC 1 +#endif + +#if defined ARM || defined __arm__ || defined _ARM +# define POSH_CPU_STRONGARM 1 +# define POSH_CPU_STRING "ARM" +#endif + +#if defined mips || defined __mips__ || defined __MIPS__ || defined _MIPS +# define POSH_CPU_MIPS 1 +# if defined _R5900 +# define POSH_CPU_STRING "MIPS R5900 (PS2)" +# else +# define POSH_CPU_STRING "MIPS" +# endif +#endif + +#if defined __ia64 || defined _M_IA64 || defined __ia64__ +# define POSH_CPU_IA64 1 +# define POSH_CPU_STRING "IA64" +#endif + +#if defined __X86__ || defined __i386__ || defined i386 || defined _M_IX86 || defined __386__ || defined __x86_64__ || defined _M_X64 +# define POSH_CPU_X86 1 +# if defined __x86_64__ || defined _M_X64 +# define POSH_CPU_X86_64 1 +# endif +# if defined POSH_CPU_X86_64 +# define POSH_CPU_STRING "AMD x86-64" +# else +# define POSH_CPU_STRING "Intel 386+" +# endif +#endif + +#if defined __alpha || defined alpha || defined _M_ALPHA || defined __alpha__ +# define POSH_CPU_AXP 1 +# define POSH_CPU_STRING "AXP" +#endif + +#if defined __hppa || defined hppa +# define POSH_CPU_HPPA 1 +# define POSH_CPU_STRING "PA-RISC" +#endif + +#if !defined POSH_CPU_STRING +# error POSH cannot determine target CPU +# define POSH_CPU_STRING "Unknown" /* this is here for Doxygen's benefit */ +#endif + +/* +** ----------------------------------------------------------------------------- +** Attempt to autodetect building for embedded on Sony PS2 +** ----------------------------------------------------------------------------- +*/ +#if !defined POSH_OS_STRING +# if !defined FORCE_DOXYGEN +# define POSH_OS_EMBEDDED 1 +# endif +# if defined _R5900 +# define POSH_OS_STRING "Sony PS2(embedded)" +# else +# define POSH_OS_STRING "Embedded/Unknown" +# endif +#endif + +/* +** --------------------------------------------------------------------------- +** Handle cdecl, stdcall, fastcall, etc. +** --------------------------------------------------------------------------- +*/ +#if defined POSH_CPU_X86 && !defined POSH_CPU_X86_64 +# if defined __GNUC__ +# define POSH_CDECL __attribute__((cdecl)) +# define POSH_STDCALL __attribute__((stdcall)) +# define POSH_FASTCALL __attribute__((fastcall)) +# elif ( defined _MSC_VER || defined __WATCOMC__ || defined __BORLANDC__ || defined __MWERKS__ ) +# define POSH_CDECL __cdecl +# define POSH_STDCALL __stdcall +# define POSH_FASTCALL __fastcall +# endif +#else +# define POSH_CDECL +# define POSH_STDCALL +# define POSH_FASTCALL +#endif + +/* +** --------------------------------------------------------------------------- +** Define POSH_IMPORTEXPORT signature based on POSH_DLL and POSH_BUILDING_LIB +** --------------------------------------------------------------------------- +*/ + +/* +** We undefine this so that multiple inclusions will work +*/ +#if defined POSH_IMPORTEXPORT +# undef POSH_IMPORTEXPORT +#endif + +#if defined POSH_DLL +# if defined POSH_OS_WIN32 +# if defined _MSC_VER +# if ( _MSC_VER >= 800 ) +# if defined POSH_BUILDING_LIB +# define POSH_IMPORTEXPORT __declspec( dllexport ) +# else +# define POSH_IMPORTEXPORT __declspec( dllimport ) +# endif +# else +# if defined POSH_BUILDING_LIB +# define POSH_IMPORTEXPORT __export +# else +# define POSH_IMPORTEXPORT +# endif +# endif +# endif /* defined _MSC_VER */ +# if defined __BORLANDC__ +# if ( __BORLANDC__ >= 0x500 ) +# if defined POSH_BUILDING_LIB +# define POSH_IMPORTEXPORT __declspec( dllexport ) +# else +# define POSH_IMPORTEXPORT __declspec( dllimport ) +# endif +# else +# if defined POSH_BUILDING_LIB +# define POSH_IMPORTEXPORT __export +# else +# define POSH_IMPORTEXPORT +# endif +# endif +# endif /* defined __BORLANDC__ */ + /* for all other compilers, we're just making a blanket assumption */ +# if defined __GNUC__ || defined __WATCOMC__ || defined __MWERKS__ +# if defined POSH_BUILDING_LIB +# define POSH_IMPORTEXPORT __declspec( dllexport ) +# else +# define POSH_IMPORTEXPORT __declspec( dllimport ) +# endif +# endif /* all other compilers */ +# if !defined POSH_IMPORTEXPORT +# error Building DLLs not supported on this compiler (poshlib@poshlib.org if you know how) +# endif +# endif /* defined POSH_OS_WIN32 */ +#endif + +/* On pretty much everything else, we can thankfully just ignore this */ +#if !defined POSH_IMPORTEXPORT +# define POSH_IMPORTEXPORT +#endif + +#if defined FORCE_DOXYGEN +# define POSH_DLL +# define POSH_BUILDING_LIB +# undef POSH_DLL +# undef POSH_BUILDING_LIB +#endif + +/* +** ---------------------------------------------------------------------------- +** (Re)define POSH_PUBLIC_API export signature +** ---------------------------------------------------------------------------- +*/ +#ifdef POSH_PUBLIC_API +# undef POSH_PUBLIC_API +#endif + +#if ( ( defined _MSC_VER ) && ( _MSC_VER < 800 ) ) || ( defined __BORLANDC__ && ( __BORLANDC__ < 0x500 ) ) +# define POSH_PUBLIC_API(rtype) extern rtype POSH_IMPORTEXPORT +#else +# define POSH_PUBLIC_API(rtype) extern POSH_IMPORTEXPORT rtype +#endif + +/* +** ---------------------------------------------------------------------------- +** Try to infer endianess. Basically we just go through the CPUs we know are +** little endian, and assume anything that isn't one of those is big endian. +** As a sanity check, we also do this with operating systems we know are +** little endian, such as Windows. Some processors are bi-endian, such as +** the MIPS series, so we have to be careful about those. +** ---------------------------------------------------------------------------- +*/ +#if defined POSH_CPU_X86 || defined POSH_CPU_AXP || defined POSH_CPU_STRONGARM || defined POSH_OS_WIN32 || defined POSH_OS_WINCE || defined __MIPSEL__ +# define POSH_ENDIAN_STRING "little" +# define POSH_LITTLE_ENDIAN 1 +#else +# define POSH_ENDIAN_STRING "big" +# define POSH_BIG_ENDIAN 1 +#endif + +#if defined FORCE_DOXYGEN +# define POSH_LITTLE_ENDIAN +#endif + +/* +** ---------------------------------------------------------------------------- +** Cross-platform compile time assertion macro +** ---------------------------------------------------------------------------- +*/ +#define POSH_COMPILE_TIME_ASSERT(name, x) typedef int _POSH_dummy_ ## name[(x) ? 1 : -1 ] + +/* +** ---------------------------------------------------------------------------- +** 64-bit Integer +** +** We don't require 64-bit support, nor do we emulate its functionality, we +** simply export it if it's available. Since we can't count on +** for 64-bit support, we ignore the POSH_USE_LIMITS_H directive. +** ---------------------------------------------------------------------------- +*/ +#if defined ( __LP64__ ) || defined ( __powerpc64__ ) || defined POSH_CPU_SPARC64 +# define POSH_64BIT_INTEGER 1 +typedef long posh_i64_t; +typedef unsigned long posh_u64_t; +# define POSH_I64( x ) ((posh_i64_t)x) +# define POSH_U64( x ) ((posh_u64_t)x) +# define POSH_I64_PRINTF_PREFIX "l" +#elif defined _MSC_VER || defined __BORLANDC__ || defined __WATCOMC__ || ( defined __alpha && defined __DECC ) +# define POSH_64BIT_INTEGER 1 +typedef __int64 posh_i64_t; +typedef unsigned __int64 posh_u64_t; +# define POSH_I64( x ) ((posh_i64_t)x) +# define POSH_U64( x ) ((posh_u64_t)x) +# define POSH_I64_PRINTF_PREFIX "I64" +#elif defined __GNUC__ || defined __MWERKS__ || defined __SUNPRO_C || defined __SUNPRO_CC || defined __APPLE_CC__ || defined POSH_OS_IRIX || defined _LONG_LONG || defined _CRAYC +# define POSH_64BIT_INTEGER 1 +typedef long long posh_i64_t; +typedef unsigned long long posh_u64_t; +# define POSH_U64( x ) ((posh_u64_t)(x##LL)) +# define POSH_I64( x ) ((posh_i64_t)(x##LL)) +# define POSH_I64_PRINTF_PREFIX "ll" +#endif + +/* hack */ +#ifdef __MINGW32__ +#undef POSH_I64 +#undef POSH_U64 +#undef POSH_I64_PRINTF_PREFIX +#define POSH_I64( x ) ((posh_i64_t)x) +#define POSH_U64( x ) ((posh_u64_t)x) +#define POSH_I64_PRINTF_PREFIX "I64" +#endif + +#ifdef FORCE_DOXYGEN +typedef long long posh_i64_t; +typedef unsigned long posh_u64_t; +# define POSH_64BIT_INTEGER +# define POSH_I64_PRINTF_PREFIX +# define POSH_I64(x) +# define POSH_U64(x) +#endif + +/** Minimum value for a 64-bit signed integer */ +#define POSH_I64_MIN POSH_I64(0x8000000000000000) +/** Maximum value for a 64-bit signed integer */ +#define POSH_I64_MAX POSH_I64(0x7FFFFFFFFFFFFFFF) +/** Minimum value for a 64-bit unsigned integer */ +#define POSH_U64_MIN POSH_U64(0) +/** Maximum value for a 64-bit unsigned integer */ +#define POSH_U64_MAX POSH_U64(0xFFFFFFFFFFFFFFFF) + +/* ---------------------------------------------------------------------------- +** Basic Sized Types +** +** These types are expected to be EXACTLY sized so you can use them for +** serialization. +** ---------------------------------------------------------------------------- +*/ +#define POSH_FALSE 0 +#define POSH_TRUE 1 + +typedef int posh_bool_t; +typedef unsigned char posh_byte_t; + +/* NOTE: These assume that CHAR_BIT is 8!! */ +typedef unsigned char posh_u8_t; +typedef signed char posh_i8_t; + +#if defined POSH_USE_LIMITS_H +# if CHAR_BITS > 8 +# error This machine uses 9-bit characters. This is a warning, you can comment this out now. +# endif /* CHAR_BITS > 8 */ + +/* 16-bit */ +# if ( USHRT_MAX == 65535 ) + typedef unsigned short posh_u16_t; + typedef short posh_i16_t; +# else + /* Yes, in theory there could still be a 16-bit character type and shorts are + 32-bits in size...if you find such an architecture, let me know =P */ +# error No 16-bit type found +# endif + +/* 32-bit */ +# if ( INT_MAX == 2147483647 ) + typedef unsigned posh_u32_t; + typedef int posh_i32_t; +# elif ( LONG_MAX == 2147483647 ) + typedef unsigned long posh_u32_t; + typedef long posh_i32_t; +# else + error No 32-bit type found +# endif + +#else /* POSH_USE_LIMITS_H */ + + typedef unsigned short posh_u16_t; + typedef short posh_i16_t; + +# if !defined POSH_OS_PALM + typedef unsigned posh_u32_t; + typedef int posh_i32_t; +# else + typedef unsigned long posh_u32_t; + typedef long posh_i32_t; +# endif +#endif + +/** Minimum value for a byte */ +#define POSH_BYTE_MIN 0 +/** Maximum value for an 8-bit unsigned value */ +#define POSH_BYTE_MAX 255 +/** Minimum value for a byte */ +#define POSH_I16_MIN ( ( posh_i16_t ) 0x8000 ) +/** Maximum value for a 16-bit signed value */ +#define POSH_I16_MAX ( ( posh_i16_t ) 0x7FFF ) +/** Minimum value for a 16-bit unsigned value */ +#define POSH_U16_MIN 0 +/** Maximum value for a 16-bit unsigned value */ +#define POSH_U16_MAX ( ( posh_u16_t ) 0xFFFF ) +/** Minimum value for a 32-bit signed value */ +#define POSH_I32_MIN ( ( posh_i32_t ) 0x80000000 ) +/** Maximum value for a 32-bit signed value */ +#define POSH_I32_MAX ( ( posh_i32_t ) 0x7FFFFFFF ) +/** Minimum value for a 32-bit unsigned value */ +#define POSH_U32_MIN 0 +/** Maximum value for a 32-bit unsigned value */ +#define POSH_U32_MAX ( ( posh_u32_t ) 0xFFFFFFFF ) + +/* +** ---------------------------------------------------------------------------- +** Sanity checks on expected sizes +** ---------------------------------------------------------------------------- +*/ +#if !defined FORCE_DOXYGEN + +POSH_COMPILE_TIME_ASSERT(posh_byte_t, sizeof(posh_byte_t) == 1); +POSH_COMPILE_TIME_ASSERT(posh_u8_t, sizeof(posh_u8_t) == 1); +POSH_COMPILE_TIME_ASSERT(posh_i8_t, sizeof(posh_i8_t) == 1); +POSH_COMPILE_TIME_ASSERT(posh_u16_t, sizeof(posh_u16_t) == 2); +POSH_COMPILE_TIME_ASSERT(posh_i16_t, sizeof(posh_i16_t) == 2); +POSH_COMPILE_TIME_ASSERT(posh_u32_t, sizeof(posh_u32_t) == 4); +POSH_COMPILE_TIME_ASSERT(posh_i32_t, sizeof(posh_i32_t) == 4); + +#if !defined POSH_NO_FLOAT + POSH_COMPILE_TIME_ASSERT(posh_testfloat_t, sizeof(float)==4 ); + POSH_COMPILE_TIME_ASSERT(posh_testdouble_t, sizeof(double)==8); +#endif + +#if defined POSH_64BIT_INTEGER + POSH_COMPILE_TIME_ASSERT(posh_u64_t, sizeof(posh_u64_t) == 8); + POSH_COMPILE_TIME_ASSERT(posh_i64_t, sizeof(posh_i64_t) == 8); +#endif + +#endif + +/* +** ---------------------------------------------------------------------------- +** 64-bit pointer support +** ---------------------------------------------------------------------------- +*/ +#if defined POSH_CPU_AXP && ( defined POSH_OS_TRU64 || defined POSH_OS_LINUX ) +# define POSH_64BIT_POINTER 1 +#endif + +#if defined POSH_CPU_X86_64 && defined POSH_OS_LINUX +# define POSH_64BIT_POINTER 1 +#endif + +#if defined POSH_CPU_SPARC64 || defined POSH_OS_WIN64 || defined __64BIT__ || defined __LP64 || defined _LP64 || defined __LP64__ || defined _ADDR64 || defined _CRAYC +# define POSH_64BIT_POINTER 1 +#endif + +#if defined POSH_64BIT_POINTER + POSH_COMPILE_TIME_ASSERT( posh_64bit_pointer, sizeof( void * ) == 8 ); +#elif !defined FORCE_DOXYGEN +/* if this assertion is hit then you're on a system that either has 64-bit + addressing and we didn't catch it, or you're on a system with 16-bit + pointers. In the latter case, POSH doesn't actually care, we're just + triggering this assertion to make sure you're aware of the situation, + so feel free to delete it. + + If this assertion is triggered on a known 32 or 64-bit platform, + please let us know (poshlib@poshlib.org) */ + POSH_COMPILE_TIME_ASSERT( posh_32bit_pointer, sizeof( void * ) == 4 ); +#endif + +#if defined FORCE_DOXYGEN +# define POSH_64BIT_POINTER +#endif + +/* +** ---------------------------------------------------------------------------- +** POSH Utility Functions +** +** These are optional POSH utility functions that are not required if you don't +** need anything except static checking of your host and target environment. +** +** These functions are NOT wrapped with POSH_PUBLIC_API because I didn't want +** to enforce their export if your own library is only using them internally. +** ---------------------------------------------------------------------------- +*/ +#ifdef __cplusplus +extern "C" { +#endif + +const char *POSH_GetArchString( void ); + +#if !defined POSH_NO_FLOAT + +posh_u32_t POSH_LittleFloatBits( float f ); +posh_u32_t POSH_BigFloatBits( float f ); +float POSH_FloatFromLittleBits( posh_u32_t bits ); +float POSH_FloatFromBigBits( posh_u32_t bits ); + +void POSH_DoubleBits( double d, posh_byte_t dst[ 8 ] ); +double POSH_DoubleFromBits( const posh_byte_t src[ 8 ] ); + +/* unimplemented +float *POSH_WriteFloatToLittle( void *dst, float f ); +float *POSH_WriteFloatToBig( void *dst, float f ); +float POSH_ReadFloatFromLittle( const void *src ); +float POSH_ReadFloatFromBig( const void *src ); + +double *POSH_WriteDoubleToLittle( void *dst, double d ); +double *POSH_WriteDoubleToBig( void *dst, double d ); +double POSH_ReadDoubleFromLittle( const void *src ); +double POSH_ReadDoubleFromBig( const void *src ); +*/ +#endif /* !defined POSH_NO_FLOAT */ + +#if defined FORCE_DOXYGEN +# define POSH_NO_FLOAT +# undef POSH_NO_FLOAT +#endif + +extern posh_u16_t POSH_SwapU16( posh_u16_t u ); +extern posh_i16_t POSH_SwapI16( posh_i16_t u ); +extern posh_u32_t POSH_SwapU32( posh_u32_t u ); +extern posh_i32_t POSH_SwapI32( posh_i32_t u ); + +#if defined POSH_64BIT_INTEGER + +extern posh_u64_t POSH_SwapU64( posh_u64_t u ); +extern posh_i64_t POSH_SwapI64( posh_i64_t u ); + +#endif /*POSH_64BIT_INTEGER */ + +extern posh_u16_t *POSH_WriteU16ToLittle( void *dst, posh_u16_t value ); +extern posh_i16_t *POSH_WriteI16ToLittle( void *dst, posh_i16_t value ); +extern posh_u32_t *POSH_WriteU32ToLittle( void *dst, posh_u32_t value ); +extern posh_i32_t *POSH_WriteI32ToLittle( void *dst, posh_i32_t value ); + +extern posh_u16_t *POSH_WriteU16ToBig( void *dst, posh_u16_t value ); +extern posh_i16_t *POSH_WriteI16ToBig( void *dst, posh_i16_t value ); +extern posh_u32_t *POSH_WriteU32ToBig( void *dst, posh_u32_t value ); +extern posh_i32_t *POSH_WriteI32ToBig( void *dst, posh_i32_t value ); + +extern posh_u16_t POSH_ReadU16FromLittle( const void *src ); +extern posh_i16_t POSH_ReadI16FromLittle( const void *src ); +extern posh_u32_t POSH_ReadU32FromLittle( const void *src ); +extern posh_i32_t POSH_ReadI32FromLittle( const void *src ); + +extern posh_u16_t POSH_ReadU16FromBig( const void *src ); +extern posh_i16_t POSH_ReadI16FromBig( const void *src ); +extern posh_u32_t POSH_ReadU32FromBig( const void *src ); +extern posh_i32_t POSH_ReadI32FromBig( const void *src ); + +#if defined POSH_64BIT_INTEGER +extern posh_u64_t *POSH_WriteU64ToLittle( void *dst, posh_u64_t value ); +extern posh_i64_t *POSH_WriteI64ToLittle( void *dst, posh_i64_t value ); +extern posh_u64_t *POSH_WriteU64ToBig( void *dst, posh_u64_t value ); +extern posh_i64_t *POSH_WriteI64ToBig( void *dst, posh_i64_t value ); + +extern posh_u64_t POSH_ReadU64FromLittle( const void *src ); +extern posh_i64_t POSH_ReadI64FromLittle( const void *src ); +extern posh_u64_t POSH_ReadU64FromBig( const void *src ); +extern posh_i64_t POSH_ReadI64FromBig( const void *src ); +#endif /* POSH_64BIT_INTEGER */ + +#if defined POSH_LITTLE_ENDIAN + +# define POSH_LittleU16(x) (x) +# define POSH_LittleU32(x) (x) +# define POSH_LittleI16(x) (x) +# define POSH_LittleI32(x) (x) +# if defined POSH_64BIT_INTEGER +# define POSH_LittleU64(x) (x) +# define POSH_LittleI64(x) (x) +# endif /* defined POSH_64BIT_INTEGER */ + +# define POSH_BigU16(x) POSH_SwapU16(x) +# define POSH_BigU32(x) POSH_SwapU32(x) +# define POSH_BigI16(x) POSH_SwapI16(x) +# define POSH_BigI32(x) POSH_SwapI32(x) +# if defined POSH_64BIT_INTEGER +# define POSH_BigU64(x) POSH_SwapU64(x) +# define POSH_BigI64(x) POSH_SwapI64(x) +# endif /* defined POSH_64BIT_INTEGER */ + +#else + +# define POSH_BigU16(x) (x) +# define POSH_BigU32(x) (x) +# define POSH_BigI16(x) (x) +# define POSH_BigI32(x) (x) + +# if defined POSH_64BIT_INTEGER +# define POSH_BigU64(x) (x) +# define POSH_BigI64(x) (x) +# endif /* POSH_64BIT_INTEGER */ + +# define POSH_LittleU16(x) POSH_SwapU16(x) +# define POSH_LittleU32(x) POSH_SwapU32(x) +# define POSH_LittleI16(x) POSH_SwapI16(x) +# define POSH_LittleI32(x) POSH_SwapI32(x) + +# if defined POSH_64BIT_INTEGER +# define POSH_LittleU64(x) POSH_SwapU64(x) +# define POSH_LittleI64(x) POSH_SwapI64(x) +# endif /* POSH_64BIT_INTEGER */ + +#endif + +#ifdef __cplusplus +} +#endif + + diff --git a/src/nvimage/ImageIO.cpp b/src/nvimage/ImageIO.cpp index 3e6a9c0..a28e239 100644 --- a/src/nvimage/ImageIO.cpp +++ b/src/nvimage/ImageIO.cpp @@ -752,44 +752,57 @@ FloatImage * nv::ImageIO::loadFloatTIFF(const char * fileName) return NULL; } - ::uint16 spp, bpp; + ::uint16 spp, bpp, format; ::uint32 width, height; TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height); TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width); TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bpp); TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &spp); + TIFFGetField(tif, TIFFTAG_SAMPLEFORMAT, &format); - if (spp != 1 || (bpp != 8 && bpp != 16 && bpp != 32)) { + if (bpp != 8 && bpp != 16 && bpp != 32) { nvDebug("Can't load '%s', only 1 sample per pixel supported\n", fileName); TIFFClose(tif); return NULL; } - FloatImage * fimage = new FloatImage(); + AutoPtr fimage(new FloatImage()); fimage->allocate(spp, width, height); int linesize = TIFFScanlineSize(tif); tdata_t buf = (::uint8 *)nv::mem::malloc(linesize); - for (uint y = 0; y < height; y++) { + for (uint y = 0; y < height; y++) + { TIFFReadScanline(tif, buf, y, 0); - - float * dst = fimage->scanline(y, 0); - - if (bpp == 8) { - for(uint x = 0; x < width; x++) { - dst[x] = float(((::uint8 *)buf)[x]) / float(0xFF); - } - } - else if (bpp == 16) { - for(uint x = 0; x < width; x++) { - dst[x] = float(((::uint16 *)buf)[x]) / float(0xFFFF); - } - } - else /*if (bpp == 32)*/ { - // Mantissa has only 24 bits, so drop 8 bits. - for(uint x = 0; x < width; x++) { - dst[x] = float(((::uint32 *)buf)[x] >> 8) / float(0xFFFFFF); + + for (uint c=0; cscanline(y, c); + + for(uint x = 0; x < width; x++) + { + if (bpp == 8) + { + dst[x] = float(((::uint8 *)buf)[x*spp+c]) / float(0xFF); + } + else if (bpp == 16) + { + dst[x] = float(((::uint16 *)buf)[x*spp+c]) / float(0xFFFF); + } + else if (bpp == 32) + { + if (format==SAMPLEFORMAT_IEEEFP) + { + dst[x] = float(((float *)buf)[x*spp+c]); + } + else + { + dst[x] = float(((::uint32 *)buf)[x*spp+c] >> 8) / float(0xFFFFFF); + } + + } + } } } @@ -798,9 +811,63 @@ FloatImage * nv::ImageIO::loadFloatTIFF(const char * fileName) TIFFClose(tif); - return fimage; + return fimage.release(); } + +bool nv::ImageIO::saveFloatTIFF(const char * fileName, FloatImage *fimage) +{ + int iW=fimage->width(); + int iH=fimage->height(); + int iC=fimage->componentNum(); + + TIFF * image = TIFFOpen(fileName, "w"); + + // Open the TIFF file + if (image == NULL) + { + nvDebug("Could not open '%s' for writing\n", fileName); + return false; + } + + TIFFSetField(image, TIFFTAG_IMAGEWIDTH, iW); + TIFFSetField(image, TIFFTAG_IMAGELENGTH, iH); + TIFFSetField(image, TIFFTAG_SAMPLESPERPIXEL, iC); + TIFFSetField(image, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP); + TIFFSetField(image, TIFFTAG_BITSPERSAMPLE, 32); + + uint32 rowsperstrip = TIFFDefaultStripSize(image, -1); + + TIFFSetField(image, TIFFTAG_ROWSPERSTRIP, rowsperstrip); + TIFFSetField(image, TIFFTAG_COMPRESSION, COMPRESSION_PACKBITS); + TIFFSetField(image, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); + TIFFSetField(image, TIFFTAG_ROWSPERSTRIP, -1L); + + TIFFSetField(image, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); + + float *scanline = new float[iW * iC]; + for (int y=0; yscanline(y, c); + for (int x=0; x -#include - -namespace nv -{ - -// @@ Use scalar defined in Vector.h, but should use a template instead. - -/// 4x4 transformation matrix. -/// -# Matrices are stored in memory in column major order. -/// -# Points are to be though of as column vectors. -/// -# Transformation of a point p by a matrix M is: p' = M * p -class NVMATH_CLASS Matrix -{ -public: - typedef Matrix const & Arg; - - Matrix(); - Matrix(zero_t); - Matrix(identity_t); - Matrix(const Matrix & m); - - scalar get(uint row, uint col) const; - scalar operator()(uint row, uint col) const; - scalar & operator()(uint row, uint col); - const scalar * ptr() const; - - Vector4 row(uint i) const; - Vector4 column(uint i) const; - - void scale(scalar s); - void scale(Vector3::Arg s); - void translate(Vector3::Arg t); - void rotate(scalar theta, scalar v0, scalar v1, scalar v2); - Matrix inverse(); - scalar determinant(); - - void apply(Matrix::Arg m); - -private: - scalar m_data[16]; -}; - - -inline Matrix::Matrix() -{ -} - -inline Matrix::Matrix(zero_t) -{ - for(int i = 0; i < 16; i++) { - m_data[i] = 0.0f; - } -} - -inline Matrix::Matrix(identity_t) -{ - for(int i = 0; i < 4; i++) { - for(int j = 0; j < 4; j++) { - m_data[4*j+i] = (i == j) ? 1.0f : 0.0f; - } - } -} - -inline Matrix::Matrix(const Matrix & m) -{ - for(int i = 0; i < 16; i++) { - m_data[i] = m.m_data[i]; - } -} - - -// Accessors -inline scalar Matrix::get(uint row, uint col) const -{ - nvDebugCheck(row < 4 && col < 4); - return m_data[col * 4 + row]; -} -inline scalar Matrix::operator()(uint row, uint col) const -{ - nvDebugCheck(row < 4 && col < 4); - return m_data[col * 4 + row]; -} -inline scalar & Matrix::operator()(uint row, uint col) -{ - nvDebugCheck(row < 4 && col < 4); - return m_data[col * 4 + row]; -} - -inline const scalar * Matrix::ptr() const -{ - return m_data; -} - -inline Vector4 Matrix::row(uint i) const -{ - nvDebugCheck(i < 4); - return Vector4(get(i, 0), get(i, 1), get(i, 2), get(i, 3)); -} - -inline Vector4 Matrix::column(uint i) const -{ - nvDebugCheck(i < 4); - return Vector4(get(0, i), get(1, i), get(2, i), get(3, i)); -} - -/// Apply scale. -inline void Matrix::scale(scalar s) -{ - m_data[0] *= s; m_data[1] *= s; m_data[2] *= s; m_data[3] *= s; - m_data[4] *= s; m_data[5] *= s; m_data[6] *= s; m_data[7] *= s; - m_data[8] *= s; m_data[9] *= s; m_data[10] *= s; m_data[11] *= s; - m_data[12] *= s; m_data[13] *= s; m_data[14] *= s; m_data[15] *= s; -} - -/// Apply scale. -inline void Matrix::scale(Vector3::Arg s) -{ - m_data[0] *= s.x(); m_data[1] *= s.x(); m_data[2] *= s.x(); m_data[3] *= s.x(); - m_data[4] *= s.y(); m_data[5] *= s.y(); m_data[6] *= s.y(); m_data[7] *= s.y(); - m_data[8] *= s.z(); m_data[9] *= s.z(); m_data[10] *= s.z(); m_data[11] *= s.z(); -} - -/// Apply translation. -inline void Matrix::translate(Vector3::Arg t) -{ - m_data[12] = m_data[0] * t.x() + m_data[4] * t.y() + m_data[8] * t.z() + m_data[12]; - m_data[13] = m_data[1] * t.x() + m_data[5] * t.y() + m_data[9] * t.z() + m_data[13]; - m_data[14] = m_data[2] * t.x() + m_data[6] * t.y() + m_data[10] * t.z() + m_data[14]; - m_data[15] = m_data[3] * t.x() + m_data[7] * t.y() + m_data[11] * t.z() + m_data[15]; -} - -Matrix rotation(scalar theta, scalar v0, scalar v1, scalar v2); - -/// Apply rotation. -inline void Matrix::rotate(scalar theta, scalar v0, scalar v1, scalar v2) -{ - Matrix R(rotation(theta, v0, v1, v2)); - apply(R); -} - -/// Apply transform. -inline void Matrix::apply(Matrix::Arg m) -{ - nvDebugCheck(this != &m); - - for(int i = 0; i < 4; i++) { - const scalar ai0 = get(i,0), ai1 = get(i,1), ai2 = get(i,2), ai3 = get(i,3); - m_data[0 + i] = ai0 * m(0,0) + ai1 * m(1,0) + ai2 * m(2,0) + ai3 * m(3,0); - m_data[4 + i] = ai0 * m(0,1) + ai1 * m(1,1) + ai2 * m(2,1) + ai3 * m(3,1); - m_data[8 + i] = ai0 * m(0,2) + ai1 * m(1,2) + ai2 * m(2,2) + ai3 * m(3,2); - m_data[12+ i] = ai0 * m(0,3) + ai1 * m(1,3) + ai2 * m(2,3) + ai3 * m(3,3); - } -} - -/// Get scale matrix. -inline Matrix scale(Vector3::Arg s) -{ - Matrix m(identity); - m(0,0) = s.x(); - m(1,1) = s.y(); - m(2,2) = s.z(); - return m; -} - -/// Get scale matrix. -inline Matrix scale(scalar s) -{ - Matrix m(identity); - m(0,0) = m(1,1) = m(2,2) = s; - return m; -} - -/// Get translation matrix. -inline Matrix translation(Vector3::Arg t) -{ - Matrix m(identity); - m(0,3) = t.x(); - m(1,3) = t.y(); - m(2,3) = t.z(); - return m; -} - -/// Get rotation matrix. -inline Matrix rotation(scalar theta, scalar v0, scalar v1, scalar v2) -{ - scalar cost = cosf(theta); - scalar sint = sinf(theta); - - Matrix m(identity); - - if( 1 == v0 && 0 == v1 && 0 == v2 ) { - m(1,1) = cost; m(2,1) = -sint; - m(1,2) = sint; m(2,2) = cost; - } - else if( 0 == v0 && 1 == v1 && 0 == v2 ) { - m(0,0) = cost; m(2,0) = sint; - m(1,2) = -sint; m(2,2) = cost; - } - else if( 0 == v0 && 0 == v1 && 1 == v2 ) { - m(0,0) = cost; m(1,0) = -sint; - m(0,1) = sint; m(1,1) = cost; - } - else { - scalar a2, b2, c2; - a2 = v0 * v0; - b2 = v1 * v1; - c2 = v2 * v2; - - scalar iscale = 1.0f / sqrtf(a2 + b2 + c2); - v0 *= iscale; - v1 *= iscale; - v2 *= iscale; - - scalar abm, acm, bcm; - scalar mcos, asin, bsin, csin; - mcos = 1.0f - cost; - abm = v0 * v1 * mcos; - acm = v0 * v2 * mcos; - bcm = v1 * v2 * mcos; - asin = v0 * sint; - bsin = v1 * sint; - csin = v2 * sint; - m(0,0) = a2 * mcos + cost; - m(1,0) = abm - csin; - m(2,0) = acm + bsin; - m(3,0) = abm + csin; - m(1,1) = b2 * mcos + cost; - m(2,1) = bcm - asin; - m(3,1) = acm - bsin; - m(1,2) = bcm + asin; - m(2,2) = c2 * mcos + cost; - } - return m; -} - -//Matrix rotation(scalar yaw, scalar pitch, scalar roll); -//Matrix skew(scalar angle, Vector3::Arg v1, Vector3::Arg v2); - -/// Get frustum matrix. -inline Matrix frustum(scalar xmin, scalar xmax, scalar ymin, scalar ymax, scalar zNear, scalar zFar) -{ - Matrix m(zero); - - scalar doubleznear = 2.0f * zNear; - scalar one_deltax = 1.0f / (xmax - xmin); - scalar one_deltay = 1.0f / (ymax - ymin); - scalar one_deltaz = 1.0f / (zFar - zNear); - - m(0,0) = doubleznear * one_deltax; - m(1,1) = doubleznear * one_deltay; - m(0,2) = (xmax + xmin) * one_deltax; - m(1,2) = (ymax + ymin) * one_deltay; - m(2,2) = -(zFar + zNear) * one_deltaz; - m(3,2) = -1.0f; - m(2,3) = -(zFar * doubleznear) * one_deltaz; - - return m; -} - -/// Get infinite frustum matrix. -inline Matrix frustum(scalar xmin, scalar xmax, scalar ymin, scalar ymax, scalar zNear) -{ - Matrix m(zero); - - scalar doubleznear = 2.0f * zNear; - scalar one_deltax = 1.0f / (xmax - xmin); - scalar one_deltay = 1.0f / (ymax - ymin); - scalar nudge = 1.0; // 0.999; - - m(0,0) = doubleznear * one_deltax; - m(1,1) = doubleznear * one_deltay; - m(0,2) = (xmax + xmin) * one_deltax; - m(1,2) = (ymax + ymin) * one_deltay; - m(2,2) = -1.0f * nudge; - m(3,2) = -1.0f; - m(2,3) = -doubleznear * nudge; - - return m; -} - -/// Get perspective matrix. -inline Matrix perspective(scalar fovy, scalar aspect, scalar zNear, scalar zFar) -{ - scalar xmax = zNear * tan(fovy / 2); - scalar xmin = -xmax; - - scalar ymax = xmax / aspect; - scalar ymin = -ymax; - - return frustum(xmin, xmax, ymin, ymax, zNear, zFar); -} - -/// Get infinite perspective matrix. -inline Matrix perspective(scalar fovy, scalar aspect, scalar zNear) -{ - scalar x = zNear * tan(fovy / 2); - scalar y = x / aspect; - return frustum( -x, x, -y, y, zNear ); -} - -/// Get matrix determinant. -inline scalar Matrix::determinant() -{ - return m_data[3] * m_data[6] * m_data[9] * m_data[12]-m_data[2] * m_data[7] * m_data[9] * m_data[12]-m_data[3] * m_data[5] * m_data[10] * m_data[12]+m_data[1] * m_data[7] * m_data[10] * m_data[12]+ - m_data[2] * m_data[5] * m_data[11] * m_data[12]-m_data[1] * m_data[6] * m_data[11] * m_data[12]-m_data[3] * m_data[6] * m_data[8] * m_data[13]+m_data[2] * m_data[7] * m_data[8] * m_data[13]+ - m_data[3] * m_data[4] * m_data[10] * m_data[13]-m_data[0] * m_data[7] * m_data[10] * m_data[13]-m_data[2] * m_data[4] * m_data[11] * m_data[13]+m_data[0] * m_data[6] * m_data[11] * m_data[13]+ - m_data[3] * m_data[5] * m_data[8] * m_data[14]-m_data[1] * m_data[7] * m_data[8] * m_data[14]-m_data[3] * m_data[4] * m_data[9] * m_data[14]+m_data[0] * m_data[7] * m_data[9] * m_data[14]+ - m_data[1] * m_data[4] * m_data[11] * m_data[14]-m_data[0] * m_data[5] * m_data[11] * m_data[14]-m_data[2] * m_data[5] * m_data[8] * m_data[15]+m_data[1] * m_data[6] * m_data[8] * m_data[15]+ - m_data[2] * m_data[4] * m_data[9] * m_data[15]-m_data[0] * m_data[6] * m_data[9] * m_data[15]-m_data[1] * m_data[4] * m_data[10] * m_data[15]+m_data[0] * m_data[5] * m_data[10] * m_data[15]; -} - -inline Matrix transpose(Matrix::Arg m) -{ - Matrix r; - for (int i = 0; i < 4; i++) - { - for (int j = 0; j < 4; i++) - { - r(i, j) = m(j, i); - } - } - return r; -} - -inline Matrix Matrix::inverse() -{ - Matrix r; - r.m_data[ 0] = m_data[6]*m_data[11]*m_data[13] - m_data[7]*m_data[10]*m_data[13] + m_data[7]*m_data[9]*m_data[14] - m_data[5]*m_data[11]*m_data[14] - m_data[6]*m_data[9]*m_data[15] + m_data[5]*m_data[10]*m_data[15]; - r.m_data[ 1] = m_data[3]*m_data[10]*m_data[13] - m_data[2]*m_data[11]*m_data[13] - m_data[3]*m_data[9]*m_data[14] + m_data[1]*m_data[11]*m_data[14] + m_data[2]*m_data[9]*m_data[15] - m_data[1]*m_data[10]*m_data[15]; - r.m_data[ 2] = m_data[2]*m_data[7]*m_data[13] - m_data[3]*m_data[6]*m_data[13] + m_data[3]*m_data[5]*m_data[14] - m_data[1]*m_data[7]*m_data[14] - m_data[2]*m_data[5]*m_data[15] + m_data[1]*m_data[6]*m_data[15]; - r.m_data[ 3] = m_data[3]*m_data[6]*m_data[9] - m_data[2]*m_data[7]*m_data[9] - m_data[3]*m_data[5]*m_data[10] + m_data[1]*m_data[7]*m_data[10] + m_data[2]*m_data[5]*m_data[11] - m_data[1]*m_data[6]*m_data[11]; - r.m_data[ 4] = m_data[7]*m_data[10]*m_data[12] - m_data[6]*m_data[11]*m_data[12] - m_data[7]*m_data[8]*m_data[14] + m_data[4]*m_data[11]*m_data[14] + m_data[6]*m_data[8]*m_data[15] - m_data[4]*m_data[10]*m_data[15]; - r.m_data[ 5] = m_data[2]*m_data[11]*m_data[12] - m_data[3]*m_data[10]*m_data[12] + m_data[3]*m_data[8]*m_data[14] - m_data[0]*m_data[11]*m_data[14] - m_data[2]*m_data[8]*m_data[15] + m_data[0]*m_data[10]*m_data[15]; - r.m_data[ 6] = m_data[3]*m_data[6]*m_data[12] - m_data[2]*m_data[7]*m_data[12] - m_data[3]*m_data[4]*m_data[14] + m_data[0]*m_data[7]*m_data[14] + m_data[2]*m_data[4]*m_data[15] - m_data[0]*m_data[6]*m_data[15]; - r.m_data[ 7] = m_data[2]*m_data[7]*m_data[8] - m_data[3]*m_data[6]*m_data[8] + m_data[3]*m_data[4]*m_data[10] - m_data[0]*m_data[7]*m_data[10] - m_data[2]*m_data[4]*m_data[11] + m_data[0]*m_data[6]*m_data[11]; - r.m_data[ 8] = m_data[5]*m_data[11]*m_data[12] - m_data[7]*m_data[9]*m_data[12] + m_data[7]*m_data[8]*m_data[13] - m_data[4]*m_data[11]*m_data[13] - m_data[5]*m_data[8]*m_data[15] + m_data[4]*m_data[9]*m_data[15]; - r.m_data[ 9] = m_data[3]*m_data[9]*m_data[12] - m_data[1]*m_data[11]*m_data[12] - m_data[3]*m_data[8]*m_data[13] + m_data[0]*m_data[11]*m_data[13] + m_data[1]*m_data[8]*m_data[15] - m_data[0]*m_data[9]*m_data[15]; - r.m_data[10] = m_data[1]*m_data[7]*m_data[12] - m_data[3]*m_data[5]*m_data[12] + m_data[3]*m_data[4]*m_data[13] - m_data[0]*m_data[7]*m_data[13] - m_data[1]*m_data[4]*m_data[15] + m_data[0]*m_data[5]*m_data[15]; - r.m_data[11] = m_data[3]*m_data[5]*m_data[8] - m_data[1]*m_data[7]*m_data[8] - m_data[3]*m_data[4]*m_data[9] + m_data[0]*m_data[7]*m_data[9] + m_data[1]*m_data[4]*m_data[11] - m_data[0]*m_data[5]*m_data[11]; - r.m_data[12] = m_data[6]*m_data[9]*m_data[12] - m_data[5]*m_data[10]*m_data[12] - m_data[6]*m_data[8]*m_data[13] + m_data[4]*m_data[10]*m_data[13] + m_data[5]*m_data[8]*m_data[14] - m_data[4]*m_data[9]*m_data[14]; - r.m_data[13] = m_data[1]*m_data[10]*m_data[12] - m_data[2]*m_data[9]*m_data[12] + m_data[2]*m_data[8]*m_data[13] - m_data[0]*m_data[10]*m_data[13] - m_data[1]*m_data[8]*m_data[14] + m_data[0]*m_data[9]*m_data[14]; - r.m_data[14] = m_data[2]*m_data[5]*m_data[12] - m_data[1]*m_data[6]*m_data[12] - m_data[2]*m_data[4]*m_data[13] + m_data[0]*m_data[6]*m_data[13] + m_data[1]*m_data[4]*m_data[14] - m_data[0]*m_data[5]*m_data[14]; - r.m_data[15] = m_data[1]*m_data[6]*m_data[8] - m_data[2]*m_data[5]*m_data[8] + m_data[2]*m_data[4]*m_data[9] - m_data[0]*m_data[6]*m_data[9] - m_data[1]*m_data[4]*m_data[10] + m_data[0]*m_data[5]*m_data[10]; - r.scale(1./determinant()); - return r; -} - -//Matrix isometryInverse(Matrix::Arg m); -//Matrix affineInverse(Matrix::Arg m); - -/// Transform the given 3d point with the given matrix. -inline Vector3 transformPoint(Matrix::Arg m, Vector3::Arg p) -{ - return Vector3( - p.x() * m(0,0) + p.y() * m(0,1) + p.z() * m(0,2) + m(0,3), - p.x() * m(1,0) + p.y() * m(1,1) + p.z() * m(1,2) + m(1,3), - p.x() * m(2,0) + p.y() * m(2,1) + p.z() * m(2,2) + m(2,3)); -} - -/// Transform the given 3d vector with the given matrix. -inline Vector3 transformVector(Matrix::Arg m, Vector3::Arg p) -{ - return Vector3( - p.x() * m(0,0) + p.y() * m(0,1) + p.z() * m(0,2), - p.x() * m(1,0) + p.y() * m(1,1) + p.z() * m(1,2), - p.x() * m(2,0) + p.y() * m(2,1) + p.z() * m(2,2)); -} - -/// Transform the given 4d vector with the given matrix. -inline Vector4 transform(Matrix::Arg m, Vector4::Arg p) -{ - return Vector4( - p.x() * m(0,0) + p.y() * m(0,1) + p.z() * m(0,2) + p.w() * m(0,3), - p.x() * m(1,0) + p.y() * m(1,1) + p.z() * m(1,2) + p.w() * m(1,3), - p.x() * m(2,0) + p.y() * m(2,1) + p.z() * m(2,2) + p.w() * m(2,3), - p.x() * m(3,0) + p.y() * m(3,1) + p.z() * m(3,2) + p.w() * m(3,3)); -} - - -} // nv namespace - - - - -#if 0 - /** @name Special matrices. */ - //@{ - /** Generate a translation matrix. */ - void TranslationMatrix(const Vec3 & v) { - data[0] = 1; data[1] = 0; data[2] = 0; data[3] = 0; - data[4] = 0; data[5] = 1; data[6] = 0; data[7] = 0; - data[8] = 0; data[9] = 0; data[10] = 1; data[11] = 0; - data[12] = v.x; data[13] = v.y; data[14] = v.z; data[15] = 1; - } - - /** Rotate theta degrees around v. */ - void RotationMatrix( scalar theta, scalar v0, scalar v1, scalar v2 ) { - scalar cost = cos(theta); - scalar sint = sin(theta); - - if( 1 == v0 && 0 == v1 && 0 == v2 ) { - data[0] = 1.0f; data[1] = 0.0f; data[2] = 0.0f; data[3] = 0.0f; - data[4] = 0.0f; data[5] = cost; data[6] = -sint;data[7] = 0.0f; - data[8] = 0.0f; data[9] = sint; data[10] = cost;data[11] = 0.0f; - data[12] = 0.0f;data[13] = 0.0f;data[14] = 0.0f;data[15] = 1.0f; - } - else if( 0 == v0 && 1 == v1 && 0 == v2 ) { - data[0] = cost; data[1] = 0.0f; data[2] = sint; data[3] = 0.0f; - data[4] = 0.0f; data[5] = 1.0f; data[6] = 0.0f; data[7] = 0.0f; - data[8] = -sint;data[9] = 0.0f;data[10] = cost; data[11] = 0.0f; - data[12] = 0.0f;data[13] = 0.0f;data[14] = 0.0f;data[15] = 1.0f; - } - else if( 0 == v0 && 0 == v1 && 1 == v2 ) { - data[0] = cost; data[1] = -sint;data[2] = 0.0f; data[3] = 0.0f; - data[4] = sint; data[5] = cost; data[6] = 0.0f; data[7] = 0.0f; - data[8] = 0.0f; data[9] = 0.0f; data[10] = 1.0f;data[11] = 0.0f; - data[12] = 0.0f;data[13] = 0.0f;data[14] = 0.0f;data[15] = 1.0f; - } - else { - //we need scale a,b,c to unit length. - scalar a2, b2, c2; - a2 = v0 * v0; - b2 = v1 * v1; - c2 = v2 * v2; - - scalar iscale = 1.0f / sqrtf(a2 + b2 + c2); - v0 *= iscale; - v1 *= iscale; - v2 *= iscale; - - scalar abm, acm, bcm; - scalar mcos, asin, bsin, csin; - mcos = 1.0f - cost; - abm = v0 * v1 * mcos; - acm = v0 * v2 * mcos; - bcm = v1 * v2 * mcos; - asin = v0 * sint; - bsin = v1 * sint; - csin = v2 * sint; - data[0] = a2 * mcos + cost; - data[1] = abm - csin; - data[2] = acm + bsin; - data[3] = abm + csin; - data[4] = 0.0f; - data[5] = b2 * mcos + cost; - data[6] = bcm - asin; - data[7] = acm - bsin; - data[8] = 0.0f; - data[9] = bcm + asin; - data[10] = c2 * mcos + cost; - data[11] = 0.0f; - data[12] = 0.0f; - data[13] = 0.0f; - data[14] = 0.0f; - data[15] = 1.0f; - } - } - - /* - void SkewMatrix(scalar angle, const Vec3 & v1, const Vec3 & v2) { - v1.Normalize(); - v2.Normalize(); - - Vec3 v3; - v3.Cross(v1, v2); - v3.Normalize(); - - // Get skew factor. - scalar costheta = Vec3DotProduct(v1, v2); - scalar sintheta = Real.Sqrt(1 - costheta * costheta); - scalar skew = tan(Trig.DegreesToRadians(angle) + acos(sintheta)) * sintheta - costheta; - - // Build orthonormal matrix. - v1 = FXVector3.Cross(v3, v2); - v1.Normalize(); - - Matrix R = Matrix::Identity; - R[0, 0] = v3.X; // Not sure this is in the correct order... - R[1, 0] = v3.Y; - R[2, 0] = v3.Z; - R[0, 1] = v1.X; - R[1, 1] = v1.Y; - R[2, 1] = v1.Z; - R[0, 2] = v2.X; - R[1, 2] = v2.Y; - R[2, 2] = v2.Z; - - // Build skew matrix. - Matrix S = Matrix::Identity; - S[2, 1] = -skew; - - // Return skew transform. - return R * S * R.Transpose; // Not sure this is in the correct order... - } - */ - - /** - * Generate rotation matrix for the euler angles. This is the same as computing - * 3 rotation matrices and multiplying them together in our custom order. - * - * @todo Have to recompute this code for our new convention. - **/ - void RotationMatrix( scalar yaw, scalar pitch, scalar roll ) { - scalar sy = sin(yaw+ToRadian(90)); - scalar cy = cos(yaw+ToRadian(90)); - scalar sp = sin(pitch-ToRadian(90)); - scalar cp = cos(pitch-ToRadian(90)); - scalar sr = sin(roll); - scalar cr = cos(roll); - - data[0] = cr*cy + sr*sp*sy; - data[1] = cp*sy; - data[2] = -sr*cy + cr*sp*sy; - data[3] = 0; - - data[4] = -cr*sy + sr*sp*cy; - data[5] = cp*cy; - data[6] = sr*sy + cr*sp*cy; - data[7] = 0; - - data[8] = sr*cp; - data[9] = -sp; - data[10] = cr*cp; - data[11] = 0; - - data[12] = 0; - data[13] = 0; - data[14] = 0; - data[15] = 1; - } - - /** Create a frustum matrix with the far plane at the infinity. */ - void Frustum( scalar xmin, scalar xmax, scalar ymin, scalar ymax, scalar zNear, scalar zFar ) { - scalar one_deltax, one_deltay, one_deltaz, doubleznear; - - doubleznear = 2.0f * zNear; - one_deltax = 1.0f / (xmax - xmin); - one_deltay = 1.0f / (ymax - ymin); - one_deltaz = 1.0f / (zFar - zNear); - - data[0] = (scalar)(doubleznear * one_deltax); - data[1] = 0.0f; - data[2] = 0.0f; - data[3] = 0.0f; - data[4] = 0.0f; - data[5] = (scalar)(doubleznear * one_deltay); - data[6] = 0.f; - data[7] = 0.f; - data[8] = (scalar)((xmax + xmin) * one_deltax); - data[9] = (scalar)((ymax + ymin) * one_deltay); - data[10] = (scalar)(-(zFar + zNear) * one_deltaz); - data[11] = -1.f; - data[12] = 0.f; - data[13] = 0.f; - data[14] = (scalar)(-(zFar * doubleznear) * one_deltaz); - data[15] = 0.f; - } - - /** Create a frustum matrix with the far plane at the infinity. */ - void FrustumInf( scalar xmin, scalar xmax, scalar ymin, scalar ymax, scalar zNear ) { - scalar one_deltax, one_deltay, doubleznear, nudge; - - doubleznear = 2.0f * zNear; - one_deltax = 1.0f / (xmax - xmin); - one_deltay = 1.0f / (ymax - ymin); - nudge = 1.0; // 0.999; - - data[0] = doubleznear * one_deltax; - data[1] = 0.0f; - data[2] = 0.0f; - data[3] = 0.0f; - - data[4] = 0.0f; - data[5] = doubleznear * one_deltay; - data[6] = 0.f; - data[7] = 0.f; - - data[8] = (xmax + xmin) * one_deltax; - data[9] = (ymax + ymin) * one_deltay; - data[10] = -1.0f * nudge; - data[11] = -1.0f; - - data[12] = 0.f; - data[13] = 0.f; - data[14] = -doubleznear * nudge; - data[15] = 0.f; - } - - /** Create an inverse frustum matrix with the far plane at the infinity. */ - void FrustumInfInv( scalar left, scalar right, scalar bottom, scalar top, scalar zNear ) { - // this matrix is wrong (not tested scalarly) I think it should be transposed. - data[0] = (right - left) / (2 * zNear); - data[1] = 0; - data[2] = 0; - data[3] = (right + left) / (2 * zNear); - data[4] = 0; - data[5] = (top - bottom) / (2 * zNear); - data[6] = 0; - data[7] = (top + bottom) / (2 * zNear); - data[8] = 0; - data[9] = 0; - data[10] = 0; - data[11] = -1; - data[12] = 0; - data[13] = 0; - data[14] = -1 / (2 * zNear); - data[15] = 1 / (2 * zNear); - } - - /** Create an homogeneous projection matrix. */ - void Perspective( scalar fov, scalar aspect, scalar zNear, scalar zFar ) { - scalar xmin, xmax, ymin, ymax; - - xmax = zNear * tan( fov/2 ); - xmin = -xmax; - - ymax = xmax / aspect; - ymin = -ymax; - - Frustum(xmin, xmax, ymin, ymax, zNear, zFar); - } - - /** Create a projection matrix with the far plane at the infinity. */ - void PerspectiveInf( scalar fov, scalar aspect, scalar zNear ) { - scalar x = zNear * tan( fov/2 ); - scalar y = x / aspect; - FrustumInf( -x, x, -y, y, zNear ); - } - - /** Create an inverse projection matrix with far plane at the infinity. */ - void PerspectiveInfInv( scalar fov, scalar aspect, scalar zNear ) { - scalar x = zNear * tan( fov/2 ); - scalar y = x / aspect; - FrustumInfInv( -x, x, -y, y, zNear ); - } - - /** Build bone matrix from quatertion and offset. */ - void BoneMatrix(const Quat & q, const Vec3 & offset) { - scalar x2, y2, z2, xx, xy, xz, yy, yz, zz, wx, wy, wz; - - // calculate coefficients - x2 = q.x + q.x; - y2 = q.y + q.y; - z2 = q.z + q.z; - - xx = q.x * x2; xy = q.x * y2; xz = q.x * z2; - yy = q.y * y2; yz = q.y * z2; zz = q.z * z2; - wx = q.w * x2; wy = q.w * y2; wz = q.w * z2; - - data[0] = 1.0f - (yy + zz); - data[1] = xy - wz; - data[2] = xz + wy; - data[3] = 0.0f; - - data[4] = xy + wz; - data[5] = 1.0f - (xx + zz); - data[6] = yz - wx; - data[7] = 0.0f; - - data[8] = xz - wy; - data[9] = yz + wx; - data[10] = 1.0f - (xx + yy); - data[11] = 0.0f; - - data[12] = offset.x; - data[13] = offset.y; - data[14] = offset.z; - data[15] = 1.0f; - } - - //@} - - - /** @name Transformations: */ - //@{ - - /** Apply a general scale. */ - void Scale( scalar x, scalar y, scalar z ) { - data[0] *= x; data[4] *= y; data[8] *= z; - data[1] *= x; data[5] *= y; data[9] *= z; - data[2] *= x; data[6] *= y; data[10] *= z; - data[3] *= x; data[7] *= y; data[11] *= z; - } - - /** Apply a rotation of theta degrees around the axis v*/ - void Rotate( scalar theta, const Vec3 & v ) { - Matrix b; - b.RotationMatrix( theta, v[0], v[1], v[2] ); - Multiply4x3( b ); - } - - /** Apply a rotation of theta degrees around the axis v*/ - void Rotate( scalar theta, scalar v0, scalar v1, scalar v2 ) { - Matrix b; - b.RotationMatrix( theta, v0, v1, v2 ); - Multiply4x3( b ); - } - - /** - * Translate the matrix by t. This is the same as multiplying by a - * translation matrix with the given offset. - * this = T * this - */ - void Translate( const Vec3 &t ) { - data[12] = data[0] * t.x + data[4] * t.y + data[8] * t.z + data[12]; - data[13] = data[1] * t.x + data[5] * t.y + data[9] * t.z + data[13]; - data[14] = data[2] * t.x + data[6] * t.y + data[10] * t.z + data[14]; - data[15] = data[3] * t.x + data[7] * t.y + data[11] * t.z + data[15]; - } - - /** - * Translate the matrix by x, y, z. This is the same as multiplying by a - * translation matrix with the given offsets. - */ - void Translate( scalar x, scalar y, scalar z ) { - data[12] = data[0] * x + data[4] * y + data[8] * z + data[12]; - data[13] = data[1] * x + data[5] * y + data[9] * z + data[13]; - data[14] = data[2] * x + data[6] * y + data[10] * z + data[14]; - data[15] = data[3] * x + data[7] * y + data[11] * z + data[15]; - } - - /** Compute the transposed matrix. */ - void Transpose() { - piSwap(data[1], data[4]); - piSwap(data[2], data[8]); - piSwap(data[6], data[9]); - piSwap(data[3], data[12]); - piSwap(data[7], data[13]); - piSwap(data[11], data[14]); - } - - /** Compute the inverse of a rigid-body/isometry/orthonormal matrix. */ - void IsometryInverse() { - // transposed 3x3 upper left matrix - piSwap(data[1], data[4]); - piSwap(data[2], data[8]); - piSwap(data[6], data[9]); - - // translate by the negative offsets - Vec3 v(-data[12], -data[13], -data[14]); - data[12] = data[13] = data[14] = 0; - Translate(v); - } - - /** Compute the inverse of the affine portion of this matrix. */ - void AffineInverse() { - data[12] = data[13] = data[14] = 0; - Transpose(); - } - //@} - - /** @name Matrix operations: */ - //@{ - - /** Return the determinant of this matrix. */ - scalar Determinant() const { - return data[0] * data[5] * data[10] * data[15] + - data[1] * data[6] * data[11] * data[12] + - data[2] * data[7] * data[ 8] * data[13] + - data[3] * data[4] * data[ 9] * data[14] - - data[3] * data[6] * data[ 9] * data[12] - - data[2] * data[5] * data[ 8] * data[15] - - data[1] * data[4] * data[11] * data[14] - - data[0] * data[7] * data[10] * data[12]; - } - - - /** Standard matrix product: this *= B. */ - void Multiply4x4( const Matrix & restrict B ) { - Multiply4x4(*this, B); - } - - /** Standard matrix product: this = A * B. this != B*/ - void Multiply4x4( const Matrix & A, const Matrix & restrict B ) { - piDebugCheck(this != &B); - - for(int i = 0; i < 4; i++) { - const scalar ai0 = A(i,0), ai1 = A(i,1), ai2 = A(i,2), ai3 = A(i,3); - GetElem(i,0) = ai0 * B(0,0) + ai1 * B(1,0) + ai2 * B(2,0) + ai3 * B(3,0); - GetElem(i,1) = ai0 * B(0,1) + ai1 * B(1,1) + ai2 * B(2,1) + ai3 * B(3,1); - GetElem(i,2) = ai0 * B(0,2) + ai1 * B(1,2) + ai2 * B(2,2) + ai3 * B(3,2); - GetElem(i,3) = ai0 * B(0,3) + ai1 * B(1,3) + ai2 * B(2,3) + ai3 * B(3,3); - } - - /* Unrolled but does not allow this == A - data[0] = A.data[0] * B.data[0] + A.data[4] * B.data[1] + A.data[8] * B.data[2] + A.data[12] * B.data[3]; - data[1] = A.data[1] * B.data[0] + A.data[5] * B.data[1] + A.data[9] * B.data[2] + A.data[13] * B.data[3]; - data[2] = A.data[2] * B.data[0] + A.data[6] * B.data[1] + A.data[10] * B.data[2] + A.data[14] * B.data[3]; - data[3] = A.data[3] * B.data[0] + A.data[7] * B.data[1] + A.data[11] * B.data[2] + A.data[15] * B.data[3]; - data[4] = A.data[0] * B.data[4] + A.data[4] * B.data[5] + A.data[8] * B.data[6] + A.data[12] * B.data[7]; - data[5] = A.data[1] * B.data[4] + A.data[5] * B.data[5] + A.data[9] * B.data[6] + A.data[13] * B.data[7]; - data[6] = A.data[2] * B.data[4] + A.data[6] * B.data[5] + A.data[10] * B.data[6] + A.data[14] * B.data[7]; - data[7] = A.data[3] * B.data[4] + A.data[7] * B.data[5] + A.data[11] * B.data[6] + A.data[15] * B.data[7]; - data[8] = A.data[0] * B.data[8] + A.data[4] * B.data[9] + A.data[8] * B.data[10] + A.data[12] * B.data[11]; - data[9] = A.data[1] * B.data[8] + A.data[5] * B.data[9] + A.data[9] * B.data[10] + A.data[13] * B.data[11]; - data[10]= A.data[2] * B.data[8] + A.data[6] * B.data[9] + A.data[10] * B.data[10] + A.data[14] * B.data[11]; - data[11]= A.data[3] * B.data[8] + A.data[7] * B.data[9] + A.data[11] * B.data[10] + A.data[15] * B.data[11]; - data[12]= A.data[0] * B.data[12] + A.data[4] * B.data[13] + A.data[8] * B.data[14] + A.data[12] * B.data[15]; - data[13]= A.data[1] * B.data[12] + A.data[5] * B.data[13] + A.data[9] * B.data[14] + A.data[13] * B.data[15]; - data[14]= A.data[2] * B.data[12] + A.data[6] * B.data[13] + A.data[10] * B.data[14] + A.data[14] * B.data[15]; - data[15]= A.data[3] * B.data[12] + A.data[7] * B.data[13] + A.data[11] * B.data[14] + A.data[15] * B.data[15]; - */ - } - - /** Standard matrix product: this *= B. */ - void Multiply4x3( const Matrix & restrict B ) { - Multiply4x3(*this, B); - } - - /** Standard product of matrices, where the last row is [0 0 0 1]. */ - void Multiply4x3( const Matrix & A, const Matrix & restrict B ) { - piDebugCheck(this != &B); - - for(int i = 0; i < 3; i++) { - const scalar ai0 = A(i,0), ai1 = A(i,1), ai2 = A(i,2), ai3 = A(i,3); - GetElem(i,0) = ai0 * B(0,0) + ai1 * B(1,0) + ai2 * B(2,0) + ai3 * B(3,0); - GetElem(i,1) = ai0 * B(0,1) + ai1 * B(1,1) + ai2 * B(2,1) + ai3 * B(3,1); - GetElem(i,2) = ai0 * B(0,2) + ai1 * B(1,2) + ai2 * B(2,2) + ai3 * B(3,2); - GetElem(i,3) = ai0 * B(0,3) + ai1 * B(1,3) + ai2 * B(2,3) + ai3 * B(3,3); - } - data[3] = 0.0f; data[7] = 0.0f; data[11] = 0.0f; data[15] = 1.0f; - - /* Unrolled but does not allow this == A - data[0] = a.data[0] * b.data[0] + a.data[4] * b.data[1] + a.data[8] * b.data[2] + a.data[12] * b.data[3]; - data[1] = a.data[1] * b.data[0] + a.data[5] * b.data[1] + a.data[9] * b.data[2] + a.data[13] * b.data[3]; - data[2] = a.data[2] * b.data[0] + a.data[6] * b.data[1] + a.data[10] * b.data[2] + a.data[14] * b.data[3]; - data[3] = 0.0f; - data[4] = a.data[0] * b.data[4] + a.data[4] * b.data[5] + a.data[8] * b.data[6] + a.data[12] * b.data[7]; - data[5] = a.data[1] * b.data[4] + a.data[5] * b.data[5] + a.data[9] * b.data[6] + a.data[13] * b.data[7]; - data[6] = a.data[2] * b.data[4] + a.data[6] * b.data[5] + a.data[10] * b.data[6] + a.data[14] * b.data[7]; - data[7] = 0.0f; - data[8] = a.data[0] * b.data[8] + a.data[4] * b.data[9] + a.data[8] * b.data[10] + a.data[12] * b.data[11]; - data[9] = a.data[1] * b.data[8] + a.data[5] * b.data[9] + a.data[9] * b.data[10] + a.data[13] * b.data[11]; - data[10]= a.data[2] * b.data[8] + a.data[6] * b.data[9] + a.data[10] * b.data[10] + a.data[14] * b.data[11]; - data[11]= 0.0f; - data[12]= a.data[0] * b.data[12] + a.data[4] * b.data[13] + a.data[8] * b.data[14] + a.data[12] * b.data[15]; - data[13]= a.data[1] * b.data[12] + a.data[5] * b.data[13] + a.data[9] * b.data[14] + a.data[13] * b.data[15]; - data[14]= a.data[2] * b.data[12] + a.data[6] * b.data[13] + a.data[10] * b.data[14] + a.data[14] * b.data[15]; - data[15]= 1.0f; - */ - } - //@} - - - /** @name Vector operations: */ - //@{ - - /** Transform 3d vector (w=0). */ - void TransformVec3(const Vec3 & restrict orig, Vec3 * restrict dest) const { - piDebugCheck(&orig != dest); - dest->x = orig.x * data[0] + orig.y * data[4] + orig.z * data[8]; - dest->y = orig.x * data[1] + orig.y * data[5] + orig.z * data[9]; - dest->z = orig.x * data[2] + orig.y * data[6] + orig.z * data[10]; - } - /** Transform 3d vector by the transpose (w=0). */ - void TransformVec3T(const Vec3 & restrict orig, Vec3 * restrict dest) const { - piDebugCheck(&orig != dest); - dest->x = orig.x * data[0] + orig.y * data[1] + orig.z * data[2]; - dest->y = orig.x * data[4] + orig.y * data[5] + orig.z * data[6]; - dest->z = orig.x * data[8] + orig.y * data[9] + orig.z * data[10]; - } - - /** Transform a 3d homogeneous vector, where the fourth coordinate is assumed to be 1. */ - void TransformPoint(const Vec3 & restrict orig, Vec3 * restrict dest) const { - piDebugCheck(&orig != dest); - dest->x = orig.x * data[0] + orig.y * data[4] + orig.z * data[8] + data[12]; - dest->y = orig.x * data[1] + orig.y * data[5] + orig.z * data[9] + data[13]; - dest->z = orig.x * data[2] + orig.y * data[6] + orig.z * data[10] + data[14]; - } - - /** Transform a point, normalize it, and return w. */ - scalar TransformPointAndNormalize(const Vec3 & restrict orig, Vec3 * restrict dest) const { - piDebugCheck(&orig != dest); - scalar w; - dest->x = orig.x * data[0] + orig.y * data[4] + orig.z * data[8] + data[12]; - dest->y = orig.x * data[1] + orig.y * data[5] + orig.z * data[9] + data[13]; - dest->z = orig.x * data[2] + orig.y * data[6] + orig.z * data[10] + data[14]; - w = 1 / (orig.x * data[3] + orig.y * data[7] + orig.z * data[11] + data[15]); - *dest *= w; - return w; - } - - /** Transform a point and return w. */ - scalar TransformPointReturnW(const Vec3 & restrict orig, Vec3 * restrict dest) const { - piDebugCheck(&orig != dest); - dest->x = orig.x * data[0] + orig.y * data[4] + orig.z * data[8] + data[12]; - dest->y = orig.x * data[1] + orig.y * data[5] + orig.z * data[9] + data[13]; - dest->z = orig.x * data[2] + orig.y * data[6] + orig.z * data[10] + data[14]; - return orig.x * data[3] + orig.y * data[7] + orig.z * data[11] + data[15]; - } - - /** Transform a normalized 3d point by a 4d matrix and return the resulting 4d vector. */ - void TransformVec4(const Vec3 & orig, Vec4 * dest) const { - dest->x = orig.x * data[0] + orig.y * data[4] + orig.z * data[8] + data[12]; - dest->y = orig.x * data[1] + orig.y * data[5] + orig.z * data[9] + data[13]; - dest->z = orig.x * data[2] + orig.y * data[6] + orig.z * data[10] + data[14]; - dest->w = orig.x * data[3] + orig.y * data[7] + orig.z * data[11] + data[15]; - } - //@} - - /** @name Matrix analysis. */ - //@{ - - /** Get the ZYZ euler angles from the matrix. Assumes the matrix is orthonormal. */ - void GetEulerAnglesZYZ(scalar * s, scalar * t, scalar * r) const { - if( GetElem(2,2) < 1.0f ) { - if( GetElem(2,2) > -1.0f ) { - // cs*ct*cr-ss*sr -ss*ct*cr-cs*sr st*cr - // cs*ct*sr+ss*cr -ss*ct*sr+cs*cr st*sr - // -cs*st ss*st ct - *s = atan2(GetElem(1,2), -GetElem(0,2)); - *t = acos(GetElem(2,2)); - *r = atan2(GetElem(2,1), GetElem(2,0)); - } - else { - // -c(s-r) s(s-r) 0 - // s(s-r) c(s-r) 0 - // 0 0 -1 - *s = atan2(GetElem(0, 1), -GetElem(0, 0)); // = s-r - *t = PI; - *r = 0; - } - } - else { - // c(s+r) -s(s+r) 0 - // s(s+r) c(s+r) 0 - // 0 0 1 - *s = atan2(GetElem(0, 1), GetElem(0, 0)); // = s+r - *t = 0; - *r = 0; - } - } - - //@} - - MATHLIB_API friend PiStream & operator<< ( PiStream & s, Matrix & m ); - - /** Print to debug output. */ - void Print() const { - piDebug( "[ %5.2f %5.2f %5.2f %5.2f ]\n", data[0], data[4], data[8], data[12] ); - piDebug( "[ %5.2f %5.2f %5.2f %5.2f ]\n", data[1], data[5], data[9], data[13] ); - piDebug( "[ %5.2f %5.2f %5.2f %5.2f ]\n", data[2], data[6], data[10], data[14] ); - piDebug( "[ %5.2f %5.2f %5.2f %5.2f ]\n", data[3], data[7], data[11], data[15] ); - } - - -public: - - scalar data[16]; - -}; -#endif - - - - -#endif // NV_MATH_MATRIX_H +// This code is in the public domain -- castanyo@yahoo.es + +#ifndef NV_MATH_MATRIX_H +#define NV_MATH_MATRIX_H + +#include +#include + +namespace nv +{ + +// @@ Use scalar defined in Vector.h, but should use a template instead. + +/// 4x4 transformation matrix. +/// -# Matrices are stored in memory in column major order. +/// -# Points are to be though of as column vectors. +/// -# Transformation of a point p by a matrix M is: p' = M * p +class NVMATH_CLASS Matrix +{ +public: + typedef Matrix const & Arg; + + Matrix(); + Matrix(zero_t); + Matrix(identity_t); + Matrix(const Matrix & m); + + scalar data(uint idx) const; + scalar & data(uint idx); + scalar get(uint row, uint col) const; + scalar operator()(uint row, uint col) const; + scalar & operator()(uint row, uint col); + const scalar * ptr() const; + + Vector4 row(uint i) const; + Vector4 column(uint i) const; + + void scale(scalar s); + void scale(Vector3::Arg s); + void translate(Vector3::Arg t); + void rotate(scalar theta, scalar v0, scalar v1, scalar v2); + scalar determinant() const; + + void apply(Matrix::Arg m); + +private: + scalar m_data[16]; +}; + + +inline Matrix::Matrix() +{ +} + +inline Matrix::Matrix(zero_t) +{ + for(int i = 0; i < 16; i++) { + m_data[i] = 0.0f; + } +} + +inline Matrix::Matrix(identity_t) +{ + for(int i = 0; i < 4; i++) { + for(int j = 0; j < 4; j++) { + m_data[4*j+i] = (i == j) ? 1.0f : 0.0f; + } + } +} + +inline Matrix::Matrix(const Matrix & m) +{ + for(int i = 0; i < 16; i++) { + m_data[i] = m.m_data[i]; + } +} + + +// Accessors +inline scalar Matrix::data(uint idx) const +{ + nvDebugCheck(idx < 16); + return m_data[idx]; +} +inline scalar & Matrix::data(uint idx) +{ + nvDebugCheck(idx < 16); + return m_data[idx]; +} +inline scalar Matrix::get(uint row, uint col) const +{ + nvDebugCheck(row < 4 && col < 4); + return m_data[col * 4 + row]; +} +inline scalar Matrix::operator()(uint row, uint col) const +{ + nvDebugCheck(row < 4 && col < 4); + return m_data[col * 4 + row]; +} +inline scalar & Matrix::operator()(uint row, uint col) +{ + nvDebugCheck(row < 4 && col < 4); + return m_data[col * 4 + row]; +} + +inline const scalar * Matrix::ptr() const +{ + return m_data; +} + +inline Vector4 Matrix::row(uint i) const +{ + nvDebugCheck(i < 4); + return Vector4(get(i, 0), get(i, 1), get(i, 2), get(i, 3)); +} + +inline Vector4 Matrix::column(uint i) const +{ + nvDebugCheck(i < 4); + return Vector4(get(0, i), get(1, i), get(2, i), get(3, i)); +} + +/// Apply scale. +inline void Matrix::scale(scalar s) +{ + m_data[0] *= s; m_data[1] *= s; m_data[2] *= s; m_data[3] *= s; + m_data[4] *= s; m_data[5] *= s; m_data[6] *= s; m_data[7] *= s; + m_data[8] *= s; m_data[9] *= s; m_data[10] *= s; m_data[11] *= s; + m_data[12] *= s; m_data[13] *= s; m_data[14] *= s; m_data[15] *= s; +} + +/// Apply scale. +inline void Matrix::scale(Vector3::Arg s) +{ + m_data[0] *= s.x(); m_data[1] *= s.x(); m_data[2] *= s.x(); m_data[3] *= s.x(); + m_data[4] *= s.y(); m_data[5] *= s.y(); m_data[6] *= s.y(); m_data[7] *= s.y(); + m_data[8] *= s.z(); m_data[9] *= s.z(); m_data[10] *= s.z(); m_data[11] *= s.z(); +} + +/// Apply translation. +inline void Matrix::translate(Vector3::Arg t) +{ + m_data[12] = m_data[0] * t.x() + m_data[4] * t.y() + m_data[8] * t.z() + m_data[12]; + m_data[13] = m_data[1] * t.x() + m_data[5] * t.y() + m_data[9] * t.z() + m_data[13]; + m_data[14] = m_data[2] * t.x() + m_data[6] * t.y() + m_data[10] * t.z() + m_data[14]; + m_data[15] = m_data[3] * t.x() + m_data[7] * t.y() + m_data[11] * t.z() + m_data[15]; +} + +Matrix rotation(scalar theta, scalar v0, scalar v1, scalar v2); + +/// Apply rotation. +inline void Matrix::rotate(scalar theta, scalar v0, scalar v1, scalar v2) +{ + Matrix R(rotation(theta, v0, v1, v2)); + apply(R); +} + +/// Apply transform. +inline void Matrix::apply(Matrix::Arg m) +{ + nvDebugCheck(this != &m); + + for(int i = 0; i < 4; i++) { + const scalar ai0 = get(i,0), ai1 = get(i,1), ai2 = get(i,2), ai3 = get(i,3); + m_data[0 + i] = ai0 * m(0,0) + ai1 * m(1,0) + ai2 * m(2,0) + ai3 * m(3,0); + m_data[4 + i] = ai0 * m(0,1) + ai1 * m(1,1) + ai2 * m(2,1) + ai3 * m(3,1); + m_data[8 + i] = ai0 * m(0,2) + ai1 * m(1,2) + ai2 * m(2,2) + ai3 * m(3,2); + m_data[12+ i] = ai0 * m(0,3) + ai1 * m(1,3) + ai2 * m(2,3) + ai3 * m(3,3); + } +} + +/// Get scale matrix. +inline Matrix scale(Vector3::Arg s) +{ + Matrix m(identity); + m(0,0) = s.x(); + m(1,1) = s.y(); + m(2,2) = s.z(); + return m; +} + +/// Get scale matrix. +inline Matrix scale(scalar s) +{ + Matrix m(identity); + m(0,0) = m(1,1) = m(2,2) = s; + return m; +} + +/// Get translation matrix. +inline Matrix translation(Vector3::Arg t) +{ + Matrix m(identity); + m(0,3) = t.x(); + m(1,3) = t.y(); + m(2,3) = t.z(); + return m; +} + +/// Get rotation matrix. +inline Matrix rotation(scalar theta, scalar v0, scalar v1, scalar v2) +{ + scalar cost = cosf(theta); + scalar sint = sinf(theta); + + Matrix m(identity); + + if( 1 == v0 && 0 == v1 && 0 == v2 ) { + m(1,1) = cost; m(2,1) = -sint; + m(1,2) = sint; m(2,2) = cost; + } + else if( 0 == v0 && 1 == v1 && 0 == v2 ) { + m(0,0) = cost; m(2,0) = sint; + m(1,2) = -sint; m(2,2) = cost; + } + else if( 0 == v0 && 0 == v1 && 1 == v2 ) { + m(0,0) = cost; m(1,0) = -sint; + m(0,1) = sint; m(1,1) = cost; + } + else { + scalar a2, b2, c2; + a2 = v0 * v0; + b2 = v1 * v1; + c2 = v2 * v2; + + scalar iscale = 1.0f / sqrtf(a2 + b2 + c2); + v0 *= iscale; + v1 *= iscale; + v2 *= iscale; + + scalar abm, acm, bcm; + scalar mcos, asin, bsin, csin; + mcos = 1.0f - cost; + abm = v0 * v1 * mcos; + acm = v0 * v2 * mcos; + bcm = v1 * v2 * mcos; + asin = v0 * sint; + bsin = v1 * sint; + csin = v2 * sint; + m(0,0) = a2 * mcos + cost; + m(1,0) = abm - csin; + m(2,0) = acm + bsin; + m(3,0) = abm + csin; + m(1,1) = b2 * mcos + cost; + m(2,1) = bcm - asin; + m(3,1) = acm - bsin; + m(1,2) = bcm + asin; + m(2,2) = c2 * mcos + cost; + } + return m; +} + +//Matrix rotation(scalar yaw, scalar pitch, scalar roll); +//Matrix skew(scalar angle, Vector3::Arg v1, Vector3::Arg v2); + +/// Get frustum matrix. +inline Matrix frustum(scalar xmin, scalar xmax, scalar ymin, scalar ymax, scalar zNear, scalar zFar) +{ + Matrix m(zero); + + scalar doubleznear = 2.0f * zNear; + scalar one_deltax = 1.0f / (xmax - xmin); + scalar one_deltay = 1.0f / (ymax - ymin); + scalar one_deltaz = 1.0f / (zFar - zNear); + + m(0,0) = doubleznear * one_deltax; + m(1,1) = doubleznear * one_deltay; + m(0,2) = (xmax + xmin) * one_deltax; + m(1,2) = (ymax + ymin) * one_deltay; + m(2,2) = -(zFar + zNear) * one_deltaz; + m(3,2) = -1.0f; + m(2,3) = -(zFar * doubleznear) * one_deltaz; + + return m; +} + +/// Get infinite frustum matrix. +inline Matrix frustum(scalar xmin, scalar xmax, scalar ymin, scalar ymax, scalar zNear) +{ + Matrix m(zero); + + scalar doubleznear = 2.0f * zNear; + scalar one_deltax = 1.0f / (xmax - xmin); + scalar one_deltay = 1.0f / (ymax - ymin); + scalar nudge = 1.0; // 0.999; + + m(0,0) = doubleznear * one_deltax; + m(1,1) = doubleznear * one_deltay; + m(0,2) = (xmax + xmin) * one_deltax; + m(1,2) = (ymax + ymin) * one_deltay; + m(2,2) = -1.0f * nudge; + m(3,2) = -1.0f; + m(2,3) = -doubleznear * nudge; + + return m; +} + +/// Get perspective matrix. +inline Matrix perspective(scalar fovy, scalar aspect, scalar zNear, scalar zFar) +{ + scalar xmax = zNear * tan(fovy / 2); + scalar xmin = -xmax; + + scalar ymax = xmax / aspect; + scalar ymin = -ymax; + + return frustum(xmin, xmax, ymin, ymax, zNear, zFar); +} + +/// Get infinite perspective matrix. +inline Matrix perspective(scalar fovy, scalar aspect, scalar zNear) +{ + scalar x = zNear * tan(fovy / 2); + scalar y = x / aspect; + return frustum( -x, x, -y, y, zNear ); +} + +/// Get matrix determinant. +inline scalar Matrix::determinant() const +{ + return + m_data[3] * m_data[6] * m_data[ 9] * m_data[12] - m_data[2] * m_data[7] * m_data[ 9] * m_data[12] - m_data[3] * m_data[5] * m_data[10] * m_data[12] + m_data[1] * m_data[7] * m_data[10] * m_data[12] + + m_data[2] * m_data[5] * m_data[11] * m_data[12] - m_data[1] * m_data[6] * m_data[11] * m_data[12] - m_data[3] * m_data[6] * m_data[ 8] * m_data[13] + m_data[2] * m_data[7] * m_data[ 8] * m_data[13] + + m_data[3] * m_data[4] * m_data[10] * m_data[13] - m_data[0] * m_data[7] * m_data[10] * m_data[13] - m_data[2] * m_data[4] * m_data[11] * m_data[13] + m_data[0] * m_data[6] * m_data[11] * m_data[13] + + m_data[3] * m_data[5] * m_data[ 8] * m_data[14] - m_data[1] * m_data[7] * m_data[ 8] * m_data[14] - m_data[3] * m_data[4] * m_data[ 9] * m_data[14] + m_data[0] * m_data[7] * m_data[ 9] * m_data[14] + + m_data[1] * m_data[4] * m_data[11] * m_data[14] - m_data[0] * m_data[5] * m_data[11] * m_data[14] - m_data[2] * m_data[5] * m_data[ 8] * m_data[15] + m_data[1] * m_data[6] * m_data[ 8] * m_data[15] + + m_data[2] * m_data[4] * m_data[ 9] * m_data[15] - m_data[0] * m_data[6] * m_data[ 9] * m_data[15] - m_data[1] * m_data[4] * m_data[10] * m_data[15] + m_data[0] * m_data[5] * m_data[10] * m_data[15]; +} + +inline Matrix transpose(Matrix::Arg m) +{ + Matrix r; + for (int i = 0; i < 4; i++) + { + for (int j = 0; j < 4; i++) + { + r(i, j) = m(j, i); + } + } + return r; +} + +inline Matrix inverse(Matrix::Arg m) +{ + Matrix r; + r.data( 0) = m.data(6)*m.data(11)*m.data(13) - m.data(7)*m.data(10)*m.data(13) + m.data(7)*m.data(9)*m.data(14) - m.data(5)*m.data(11)*m.data(14) - m.data(6)*m.data(9)*m.data(15) + m.data(5)*m.data(10)*m.data(15); + r.data( 1) = m.data(3)*m.data(10)*m.data(13) - m.data(2)*m.data(11)*m.data(13) - m.data(3)*m.data(9)*m.data(14) + m.data(1)*m.data(11)*m.data(14) + m.data(2)*m.data(9)*m.data(15) - m.data(1)*m.data(10)*m.data(15); + r.data( 2) = m.data(2)*m.data( 7)*m.data(13) - m.data(3)*m.data( 6)*m.data(13) + m.data(3)*m.data(5)*m.data(14) - m.data(1)*m.data( 7)*m.data(14) - m.data(2)*m.data(5)*m.data(15) + m.data(1)*m.data( 6)*m.data(15); + r.data( 3) = m.data(3)*m.data( 6)*m.data( 9) - m.data(2)*m.data( 7)*m.data( 9) - m.data(3)*m.data(5)*m.data(10) + m.data(1)*m.data( 7)*m.data(10) + m.data(2)*m.data(5)*m.data(11) - m.data(1)*m.data( 6)*m.data(11); + r.data( 4) = m.data(7)*m.data(10)*m.data(12) - m.data(6)*m.data(11)*m.data(12) - m.data(7)*m.data(8)*m.data(14) + m.data(4)*m.data(11)*m.data(14) + m.data(6)*m.data(8)*m.data(15) - m.data(4)*m.data(10)*m.data(15); + r.data( 5) = m.data(2)*m.data(11)*m.data(12) - m.data(3)*m.data(10)*m.data(12) + m.data(3)*m.data(8)*m.data(14) - m.data(0)*m.data(11)*m.data(14) - m.data(2)*m.data(8)*m.data(15) + m.data(0)*m.data(10)*m.data(15); + r.data( 6) = m.data(3)*m.data( 6)*m.data(12) - m.data(2)*m.data( 7)*m.data(12) - m.data(3)*m.data(4)*m.data(14) + m.data(0)*m.data( 7)*m.data(14) + m.data(2)*m.data(4)*m.data(15) - m.data(0)*m.data( 6)*m.data(15); + r.data( 7) = m.data(2)*m.data( 7)*m.data( 8) - m.data(3)*m.data( 6)*m.data( 8) + m.data(3)*m.data(4)*m.data(10) - m.data(0)*m.data( 7)*m.data(10) - m.data(2)*m.data(4)*m.data(11) + m.data(0)*m.data( 6)*m.data(11); + r.data( 8) = m.data(5)*m.data(11)*m.data(12) - m.data(7)*m.data( 9)*m.data(12) + m.data(7)*m.data(8)*m.data(13) - m.data(4)*m.data(11)*m.data(13) - m.data(5)*m.data(8)*m.data(15) + m.data(4)*m.data( 9)*m.data(15); + r.data( 9) = m.data(3)*m.data( 9)*m.data(12) - m.data(1)*m.data(11)*m.data(12) - m.data(3)*m.data(8)*m.data(13) + m.data(0)*m.data(11)*m.data(13) + m.data(1)*m.data(8)*m.data(15) - m.data(0)*m.data( 9)*m.data(15); + r.data(10) = m.data(1)*m.data( 7)*m.data(12) - m.data(3)*m.data( 5)*m.data(12) + m.data(3)*m.data(4)*m.data(13) - m.data(0)*m.data( 7)*m.data(13) - m.data(1)*m.data(4)*m.data(15) + m.data(0)*m.data( 5)*m.data(15); + r.data(11) = m.data(3)*m.data( 5)*m.data( 8) - m.data(1)*m.data( 7)*m.data( 8) - m.data(3)*m.data(4)*m.data( 9) + m.data(0)*m.data( 7)*m.data( 9) + m.data(1)*m.data(4)*m.data(11) - m.data(0)*m.data( 5)*m.data(11); + r.data(12) = m.data(6)*m.data( 9)*m.data(12) - m.data(5)*m.data(10)*m.data(12) - m.data(6)*m.data(8)*m.data(13) + m.data(4)*m.data(10)*m.data(13) + m.data(5)*m.data(8)*m.data(14) - m.data(4)*m.data( 9)*m.data(14); + r.data(13) = m.data(1)*m.data(10)*m.data(12) - m.data(2)*m.data( 9)*m.data(12) + m.data(2)*m.data(8)*m.data(13) - m.data(0)*m.data(10)*m.data(13) - m.data(1)*m.data(8)*m.data(14) + m.data(0)*m.data( 9)*m.data(14); + r.data(14) = m.data(2)*m.data( 5)*m.data(12) - m.data(1)*m.data( 6)*m.data(12) - m.data(2)*m.data(4)*m.data(13) + m.data(0)*m.data( 6)*m.data(13) + m.data(1)*m.data(4)*m.data(14) - m.data(0)*m.data( 5)*m.data(14); + r.data(15) = m.data(1)*m.data( 6)*m.data( 8) - m.data(2)*m.data( 5)*m.data( 8) + m.data(2)*m.data(4)*m.data( 9) - m.data(0)*m.data( 6)*m.data( 9) - m.data(1)*m.data(4)*m.data(10) + m.data(0)*m.data( 5)*m.data(10); + r.scale(1.0f / m.determinant()); + return r; +} + +//Matrix isometryInverse(Matrix::Arg m); +//Matrix affineInverse(Matrix::Arg m); + +/// Transform the given 3d point with the given matrix. +inline Vector3 transformPoint(Matrix::Arg m, Vector3::Arg p) +{ + return Vector3( + p.x() * m(0,0) + p.y() * m(0,1) + p.z() * m(0,2) + m(0,3), + p.x() * m(1,0) + p.y() * m(1,1) + p.z() * m(1,2) + m(1,3), + p.x() * m(2,0) + p.y() * m(2,1) + p.z() * m(2,2) + m(2,3)); +} + +/// Transform the given 3d vector with the given matrix. +inline Vector3 transformVector(Matrix::Arg m, Vector3::Arg p) +{ + return Vector3( + p.x() * m(0,0) + p.y() * m(0,1) + p.z() * m(0,2), + p.x() * m(1,0) + p.y() * m(1,1) + p.z() * m(1,2), + p.x() * m(2,0) + p.y() * m(2,1) + p.z() * m(2,2)); +} + +/// Transform the given 4d vector with the given matrix. +inline Vector4 transform(Matrix::Arg m, Vector4::Arg p) +{ + return Vector4( + p.x() * m(0,0) + p.y() * m(0,1) + p.z() * m(0,2) + p.w() * m(0,3), + p.x() * m(1,0) + p.y() * m(1,1) + p.z() * m(1,2) + p.w() * m(1,3), + p.x() * m(2,0) + p.y() * m(2,1) + p.z() * m(2,2) + p.w() * m(2,3), + p.x() * m(3,0) + p.y() * m(3,1) + p.z() * m(3,2) + p.w() * m(3,3)); +} + + +} // nv namespace + + + + +#if 0 + /** @name Special matrices. */ + //@{ + /** Generate a translation matrix. */ + void TranslationMatrix(const Vec3 & v) { + data[0] = 1; data[1] = 0; data[2] = 0; data[3] = 0; + data[4] = 0; data[5] = 1; data[6] = 0; data[7] = 0; + data[8] = 0; data[9] = 0; data[10] = 1; data[11] = 0; + data[12] = v.x; data[13] = v.y; data[14] = v.z; data[15] = 1; + } + + /** Rotate theta degrees around v. */ + void RotationMatrix( scalar theta, scalar v0, scalar v1, scalar v2 ) { + scalar cost = cos(theta); + scalar sint = sin(theta); + + if( 1 == v0 && 0 == v1 && 0 == v2 ) { + data[0] = 1.0f; data[1] = 0.0f; data[2] = 0.0f; data[3] = 0.0f; + data[4] = 0.0f; data[5] = cost; data[6] = -sint;data[7] = 0.0f; + data[8] = 0.0f; data[9] = sint; data[10] = cost;data[11] = 0.0f; + data[12] = 0.0f;data[13] = 0.0f;data[14] = 0.0f;data[15] = 1.0f; + } + else if( 0 == v0 && 1 == v1 && 0 == v2 ) { + data[0] = cost; data[1] = 0.0f; data[2] = sint; data[3] = 0.0f; + data[4] = 0.0f; data[5] = 1.0f; data[6] = 0.0f; data[7] = 0.0f; + data[8] = -sint;data[9] = 0.0f;data[10] = cost; data[11] = 0.0f; + data[12] = 0.0f;data[13] = 0.0f;data[14] = 0.0f;data[15] = 1.0f; + } + else if( 0 == v0 && 0 == v1 && 1 == v2 ) { + data[0] = cost; data[1] = -sint;data[2] = 0.0f; data[3] = 0.0f; + data[4] = sint; data[5] = cost; data[6] = 0.0f; data[7] = 0.0f; + data[8] = 0.0f; data[9] = 0.0f; data[10] = 1.0f;data[11] = 0.0f; + data[12] = 0.0f;data[13] = 0.0f;data[14] = 0.0f;data[15] = 1.0f; + } + else { + //we need scale a,b,c to unit length. + scalar a2, b2, c2; + a2 = v0 * v0; + b2 = v1 * v1; + c2 = v2 * v2; + + scalar iscale = 1.0f / sqrtf(a2 + b2 + c2); + v0 *= iscale; + v1 *= iscale; + v2 *= iscale; + + scalar abm, acm, bcm; + scalar mcos, asin, bsin, csin; + mcos = 1.0f - cost; + abm = v0 * v1 * mcos; + acm = v0 * v2 * mcos; + bcm = v1 * v2 * mcos; + asin = v0 * sint; + bsin = v1 * sint; + csin = v2 * sint; + data[0] = a2 * mcos + cost; + data[1] = abm - csin; + data[2] = acm + bsin; + data[3] = abm + csin; + data[4] = 0.0f; + data[5] = b2 * mcos + cost; + data[6] = bcm - asin; + data[7] = acm - bsin; + data[8] = 0.0f; + data[9] = bcm + asin; + data[10] = c2 * mcos + cost; + data[11] = 0.0f; + data[12] = 0.0f; + data[13] = 0.0f; + data[14] = 0.0f; + data[15] = 1.0f; + } + } + + /* + void SkewMatrix(scalar angle, const Vec3 & v1, const Vec3 & v2) { + v1.Normalize(); + v2.Normalize(); + + Vec3 v3; + v3.Cross(v1, v2); + v3.Normalize(); + + // Get skew factor. + scalar costheta = Vec3DotProduct(v1, v2); + scalar sintheta = Real.Sqrt(1 - costheta * costheta); + scalar skew = tan(Trig.DegreesToRadians(angle) + acos(sintheta)) * sintheta - costheta; + + // Build orthonormal matrix. + v1 = FXVector3.Cross(v3, v2); + v1.Normalize(); + + Matrix R = Matrix::Identity; + R[0, 0] = v3.X; // Not sure this is in the correct order... + R[1, 0] = v3.Y; + R[2, 0] = v3.Z; + R[0, 1] = v1.X; + R[1, 1] = v1.Y; + R[2, 1] = v1.Z; + R[0, 2] = v2.X; + R[1, 2] = v2.Y; + R[2, 2] = v2.Z; + + // Build skew matrix. + Matrix S = Matrix::Identity; + S[2, 1] = -skew; + + // Return skew transform. + return R * S * R.Transpose; // Not sure this is in the correct order... + } + */ + + /** + * Generate rotation matrix for the euler angles. This is the same as computing + * 3 rotation matrices and multiplying them together in our custom order. + * + * @todo Have to recompute this code for our new convention. + **/ + void RotationMatrix( scalar yaw, scalar pitch, scalar roll ) { + scalar sy = sin(yaw+ToRadian(90)); + scalar cy = cos(yaw+ToRadian(90)); + scalar sp = sin(pitch-ToRadian(90)); + scalar cp = cos(pitch-ToRadian(90)); + scalar sr = sin(roll); + scalar cr = cos(roll); + + data[0] = cr*cy + sr*sp*sy; + data[1] = cp*sy; + data[2] = -sr*cy + cr*sp*sy; + data[3] = 0; + + data[4] = -cr*sy + sr*sp*cy; + data[5] = cp*cy; + data[6] = sr*sy + cr*sp*cy; + data[7] = 0; + + data[8] = sr*cp; + data[9] = -sp; + data[10] = cr*cp; + data[11] = 0; + + data[12] = 0; + data[13] = 0; + data[14] = 0; + data[15] = 1; + } + + /** Create a frustum matrix with the far plane at the infinity. */ + void Frustum( scalar xmin, scalar xmax, scalar ymin, scalar ymax, scalar zNear, scalar zFar ) { + scalar one_deltax, one_deltay, one_deltaz, doubleznear; + + doubleznear = 2.0f * zNear; + one_deltax = 1.0f / (xmax - xmin); + one_deltay = 1.0f / (ymax - ymin); + one_deltaz = 1.0f / (zFar - zNear); + + data[0] = (scalar)(doubleznear * one_deltax); + data[1] = 0.0f; + data[2] = 0.0f; + data[3] = 0.0f; + data[4] = 0.0f; + data[5] = (scalar)(doubleznear * one_deltay); + data[6] = 0.f; + data[7] = 0.f; + data[8] = (scalar)((xmax + xmin) * one_deltax); + data[9] = (scalar)((ymax + ymin) * one_deltay); + data[10] = (scalar)(-(zFar + zNear) * one_deltaz); + data[11] = -1.f; + data[12] = 0.f; + data[13] = 0.f; + data[14] = (scalar)(-(zFar * doubleznear) * one_deltaz); + data[15] = 0.f; + } + + /** Create a frustum matrix with the far plane at the infinity. */ + void FrustumInf( scalar xmin, scalar xmax, scalar ymin, scalar ymax, scalar zNear ) { + scalar one_deltax, one_deltay, doubleznear, nudge; + + doubleznear = 2.0f * zNear; + one_deltax = 1.0f / (xmax - xmin); + one_deltay = 1.0f / (ymax - ymin); + nudge = 1.0; // 0.999; + + data[0] = doubleznear * one_deltax; + data[1] = 0.0f; + data[2] = 0.0f; + data[3] = 0.0f; + + data[4] = 0.0f; + data[5] = doubleznear * one_deltay; + data[6] = 0.f; + data[7] = 0.f; + + data[8] = (xmax + xmin) * one_deltax; + data[9] = (ymax + ymin) * one_deltay; + data[10] = -1.0f * nudge; + data[11] = -1.0f; + + data[12] = 0.f; + data[13] = 0.f; + data[14] = -doubleznear * nudge; + data[15] = 0.f; + } + + /** Create an inverse frustum matrix with the far plane at the infinity. */ + void FrustumInfInv( scalar left, scalar right, scalar bottom, scalar top, scalar zNear ) { + // this matrix is wrong (not tested scalarly) I think it should be transposed. + data[0] = (right - left) / (2 * zNear); + data[1] = 0; + data[2] = 0; + data[3] = (right + left) / (2 * zNear); + data[4] = 0; + data[5] = (top - bottom) / (2 * zNear); + data[6] = 0; + data[7] = (top + bottom) / (2 * zNear); + data[8] = 0; + data[9] = 0; + data[10] = 0; + data[11] = -1; + data[12] = 0; + data[13] = 0; + data[14] = -1 / (2 * zNear); + data[15] = 1 / (2 * zNear); + } + + /** Create an homogeneous projection matrix. */ + void Perspective( scalar fov, scalar aspect, scalar zNear, scalar zFar ) { + scalar xmin, xmax, ymin, ymax; + + xmax = zNear * tan( fov/2 ); + xmin = -xmax; + + ymax = xmax / aspect; + ymin = -ymax; + + Frustum(xmin, xmax, ymin, ymax, zNear, zFar); + } + + /** Create a projection matrix with the far plane at the infinity. */ + void PerspectiveInf( scalar fov, scalar aspect, scalar zNear ) { + scalar x = zNear * tan( fov/2 ); + scalar y = x / aspect; + FrustumInf( -x, x, -y, y, zNear ); + } + + /** Create an inverse projection matrix with far plane at the infinity. */ + void PerspectiveInfInv( scalar fov, scalar aspect, scalar zNear ) { + scalar x = zNear * tan( fov/2 ); + scalar y = x / aspect; + FrustumInfInv( -x, x, -y, y, zNear ); + } + + /** Build bone matrix from quatertion and offset. */ + void BoneMatrix(const Quat & q, const Vec3 & offset) { + scalar x2, y2, z2, xx, xy, xz, yy, yz, zz, wx, wy, wz; + + // calculate coefficients + x2 = q.x + q.x; + y2 = q.y + q.y; + z2 = q.z + q.z; + + xx = q.x * x2; xy = q.x * y2; xz = q.x * z2; + yy = q.y * y2; yz = q.y * z2; zz = q.z * z2; + wx = q.w * x2; wy = q.w * y2; wz = q.w * z2; + + data[0] = 1.0f - (yy + zz); + data[1] = xy - wz; + data[2] = xz + wy; + data[3] = 0.0f; + + data[4] = xy + wz; + data[5] = 1.0f - (xx + zz); + data[6] = yz - wx; + data[7] = 0.0f; + + data[8] = xz - wy; + data[9] = yz + wx; + data[10] = 1.0f - (xx + yy); + data[11] = 0.0f; + + data[12] = offset.x; + data[13] = offset.y; + data[14] = offset.z; + data[15] = 1.0f; + } + + //@} + + + /** @name Transformations: */ + //@{ + + /** Apply a general scale. */ + void Scale( scalar x, scalar y, scalar z ) { + data[0] *= x; data[4] *= y; data[8] *= z; + data[1] *= x; data[5] *= y; data[9] *= z; + data[2] *= x; data[6] *= y; data[10] *= z; + data[3] *= x; data[7] *= y; data[11] *= z; + } + + /** Apply a rotation of theta degrees around the axis v*/ + void Rotate( scalar theta, const Vec3 & v ) { + Matrix b; + b.RotationMatrix( theta, v[0], v[1], v[2] ); + Multiply4x3( b ); + } + + /** Apply a rotation of theta degrees around the axis v*/ + void Rotate( scalar theta, scalar v0, scalar v1, scalar v2 ) { + Matrix b; + b.RotationMatrix( theta, v0, v1, v2 ); + Multiply4x3( b ); + } + + /** + * Translate the matrix by t. This is the same as multiplying by a + * translation matrix with the given offset. + * this = T * this + */ + void Translate( const Vec3 &t ) { + data[12] = data[0] * t.x + data[4] * t.y + data[8] * t.z + data[12]; + data[13] = data[1] * t.x + data[5] * t.y + data[9] * t.z + data[13]; + data[14] = data[2] * t.x + data[6] * t.y + data[10] * t.z + data[14]; + data[15] = data[3] * t.x + data[7] * t.y + data[11] * t.z + data[15]; + } + + /** + * Translate the matrix by x, y, z. This is the same as multiplying by a + * translation matrix with the given offsets. + */ + void Translate( scalar x, scalar y, scalar z ) { + data[12] = data[0] * x + data[4] * y + data[8] * z + data[12]; + data[13] = data[1] * x + data[5] * y + data[9] * z + data[13]; + data[14] = data[2] * x + data[6] * y + data[10] * z + data[14]; + data[15] = data[3] * x + data[7] * y + data[11] * z + data[15]; + } + + /** Compute the transposed matrix. */ + void Transpose() { + piSwap(data[1], data[4]); + piSwap(data[2], data[8]); + piSwap(data[6], data[9]); + piSwap(data[3], data[12]); + piSwap(data[7], data[13]); + piSwap(data[11], data[14]); + } + + /** Compute the inverse of a rigid-body/isometry/orthonormal matrix. */ + void IsometryInverse() { + // transposed 3x3 upper left matrix + piSwap(data[1], data[4]); + piSwap(data[2], data[8]); + piSwap(data[6], data[9]); + + // translate by the negative offsets + Vec3 v(-data[12], -data[13], -data[14]); + data[12] = data[13] = data[14] = 0; + Translate(v); + } + + /** Compute the inverse of the affine portion of this matrix. */ + void AffineInverse() { + data[12] = data[13] = data[14] = 0; + Transpose(); + } + //@} + + /** @name Matrix operations: */ + //@{ + + /** Return the determinant of this matrix. */ + scalar Determinant() const { + return data[0] * data[5] * data[10] * data[15] + + data[1] * data[6] * data[11] * data[12] + + data[2] * data[7] * data[ 8] * data[13] + + data[3] * data[4] * data[ 9] * data[14] - + data[3] * data[6] * data[ 9] * data[12] - + data[2] * data[5] * data[ 8] * data[15] - + data[1] * data[4] * data[11] * data[14] - + data[0] * data[7] * data[10] * data[12]; + } + + + /** Standard matrix product: this *= B. */ + void Multiply4x4( const Matrix & restrict B ) { + Multiply4x4(*this, B); + } + + /** Standard matrix product: this = A * B. this != B*/ + void Multiply4x4( const Matrix & A, const Matrix & restrict B ) { + piDebugCheck(this != &B); + + for(int i = 0; i < 4; i++) { + const scalar ai0 = A(i,0), ai1 = A(i,1), ai2 = A(i,2), ai3 = A(i,3); + GetElem(i,0) = ai0 * B(0,0) + ai1 * B(1,0) + ai2 * B(2,0) + ai3 * B(3,0); + GetElem(i,1) = ai0 * B(0,1) + ai1 * B(1,1) + ai2 * B(2,1) + ai3 * B(3,1); + GetElem(i,2) = ai0 * B(0,2) + ai1 * B(1,2) + ai2 * B(2,2) + ai3 * B(3,2); + GetElem(i,3) = ai0 * B(0,3) + ai1 * B(1,3) + ai2 * B(2,3) + ai3 * B(3,3); + } + + /* Unrolled but does not allow this == A + data[0] = A.data[0] * B.data[0] + A.data[4] * B.data[1] + A.data[8] * B.data[2] + A.data[12] * B.data[3]; + data[1] = A.data[1] * B.data[0] + A.data[5] * B.data[1] + A.data[9] * B.data[2] + A.data[13] * B.data[3]; + data[2] = A.data[2] * B.data[0] + A.data[6] * B.data[1] + A.data[10] * B.data[2] + A.data[14] * B.data[3]; + data[3] = A.data[3] * B.data[0] + A.data[7] * B.data[1] + A.data[11] * B.data[2] + A.data[15] * B.data[3]; + data[4] = A.data[0] * B.data[4] + A.data[4] * B.data[5] + A.data[8] * B.data[6] + A.data[12] * B.data[7]; + data[5] = A.data[1] * B.data[4] + A.data[5] * B.data[5] + A.data[9] * B.data[6] + A.data[13] * B.data[7]; + data[6] = A.data[2] * B.data[4] + A.data[6] * B.data[5] + A.data[10] * B.data[6] + A.data[14] * B.data[7]; + data[7] = A.data[3] * B.data[4] + A.data[7] * B.data[5] + A.data[11] * B.data[6] + A.data[15] * B.data[7]; + data[8] = A.data[0] * B.data[8] + A.data[4] * B.data[9] + A.data[8] * B.data[10] + A.data[12] * B.data[11]; + data[9] = A.data[1] * B.data[8] + A.data[5] * B.data[9] + A.data[9] * B.data[10] + A.data[13] * B.data[11]; + data[10]= A.data[2] * B.data[8] + A.data[6] * B.data[9] + A.data[10] * B.data[10] + A.data[14] * B.data[11]; + data[11]= A.data[3] * B.data[8] + A.data[7] * B.data[9] + A.data[11] * B.data[10] + A.data[15] * B.data[11]; + data[12]= A.data[0] * B.data[12] + A.data[4] * B.data[13] + A.data[8] * B.data[14] + A.data[12] * B.data[15]; + data[13]= A.data[1] * B.data[12] + A.data[5] * B.data[13] + A.data[9] * B.data[14] + A.data[13] * B.data[15]; + data[14]= A.data[2] * B.data[12] + A.data[6] * B.data[13] + A.data[10] * B.data[14] + A.data[14] * B.data[15]; + data[15]= A.data[3] * B.data[12] + A.data[7] * B.data[13] + A.data[11] * B.data[14] + A.data[15] * B.data[15]; + */ + } + + /** Standard matrix product: this *= B. */ + void Multiply4x3( const Matrix & restrict B ) { + Multiply4x3(*this, B); + } + + /** Standard product of matrices, where the last row is [0 0 0 1]. */ + void Multiply4x3( const Matrix & A, const Matrix & restrict B ) { + piDebugCheck(this != &B); + + for(int i = 0; i < 3; i++) { + const scalar ai0 = A(i,0), ai1 = A(i,1), ai2 = A(i,2), ai3 = A(i,3); + GetElem(i,0) = ai0 * B(0,0) + ai1 * B(1,0) + ai2 * B(2,0) + ai3 * B(3,0); + GetElem(i,1) = ai0 * B(0,1) + ai1 * B(1,1) + ai2 * B(2,1) + ai3 * B(3,1); + GetElem(i,2) = ai0 * B(0,2) + ai1 * B(1,2) + ai2 * B(2,2) + ai3 * B(3,2); + GetElem(i,3) = ai0 * B(0,3) + ai1 * B(1,3) + ai2 * B(2,3) + ai3 * B(3,3); + } + data[3] = 0.0f; data[7] = 0.0f; data[11] = 0.0f; data[15] = 1.0f; + + /* Unrolled but does not allow this == A + data[0] = a.data[0] * b.data[0] + a.data[4] * b.data[1] + a.data[8] * b.data[2] + a.data[12] * b.data[3]; + data[1] = a.data[1] * b.data[0] + a.data[5] * b.data[1] + a.data[9] * b.data[2] + a.data[13] * b.data[3]; + data[2] = a.data[2] * b.data[0] + a.data[6] * b.data[1] + a.data[10] * b.data[2] + a.data[14] * b.data[3]; + data[3] = 0.0f; + data[4] = a.data[0] * b.data[4] + a.data[4] * b.data[5] + a.data[8] * b.data[6] + a.data[12] * b.data[7]; + data[5] = a.data[1] * b.data[4] + a.data[5] * b.data[5] + a.data[9] * b.data[6] + a.data[13] * b.data[7]; + data[6] = a.data[2] * b.data[4] + a.data[6] * b.data[5] + a.data[10] * b.data[6] + a.data[14] * b.data[7]; + data[7] = 0.0f; + data[8] = a.data[0] * b.data[8] + a.data[4] * b.data[9] + a.data[8] * b.data[10] + a.data[12] * b.data[11]; + data[9] = a.data[1] * b.data[8] + a.data[5] * b.data[9] + a.data[9] * b.data[10] + a.data[13] * b.data[11]; + data[10]= a.data[2] * b.data[8] + a.data[6] * b.data[9] + a.data[10] * b.data[10] + a.data[14] * b.data[11]; + data[11]= 0.0f; + data[12]= a.data[0] * b.data[12] + a.data[4] * b.data[13] + a.data[8] * b.data[14] + a.data[12] * b.data[15]; + data[13]= a.data[1] * b.data[12] + a.data[5] * b.data[13] + a.data[9] * b.data[14] + a.data[13] * b.data[15]; + data[14]= a.data[2] * b.data[12] + a.data[6] * b.data[13] + a.data[10] * b.data[14] + a.data[14] * b.data[15]; + data[15]= 1.0f; + */ + } + //@} + + + /** @name Vector operations: */ + //@{ + + /** Transform 3d vector (w=0). */ + void TransformVec3(const Vec3 & restrict orig, Vec3 * restrict dest) const { + piDebugCheck(&orig != dest); + dest->x = orig.x * data[0] + orig.y * data[4] + orig.z * data[8]; + dest->y = orig.x * data[1] + orig.y * data[5] + orig.z * data[9]; + dest->z = orig.x * data[2] + orig.y * data[6] + orig.z * data[10]; + } + /** Transform 3d vector by the transpose (w=0). */ + void TransformVec3T(const Vec3 & restrict orig, Vec3 * restrict dest) const { + piDebugCheck(&orig != dest); + dest->x = orig.x * data[0] + orig.y * data[1] + orig.z * data[2]; + dest->y = orig.x * data[4] + orig.y * data[5] + orig.z * data[6]; + dest->z = orig.x * data[8] + orig.y * data[9] + orig.z * data[10]; + } + + /** Transform a 3d homogeneous vector, where the fourth coordinate is assumed to be 1. */ + void TransformPoint(const Vec3 & restrict orig, Vec3 * restrict dest) const { + piDebugCheck(&orig != dest); + dest->x = orig.x * data[0] + orig.y * data[4] + orig.z * data[8] + data[12]; + dest->y = orig.x * data[1] + orig.y * data[5] + orig.z * data[9] + data[13]; + dest->z = orig.x * data[2] + orig.y * data[6] + orig.z * data[10] + data[14]; + } + + /** Transform a point, normalize it, and return w. */ + scalar TransformPointAndNormalize(const Vec3 & restrict orig, Vec3 * restrict dest) const { + piDebugCheck(&orig != dest); + scalar w; + dest->x = orig.x * data[0] + orig.y * data[4] + orig.z * data[8] + data[12]; + dest->y = orig.x * data[1] + orig.y * data[5] + orig.z * data[9] + data[13]; + dest->z = orig.x * data[2] + orig.y * data[6] + orig.z * data[10] + data[14]; + w = 1 / (orig.x * data[3] + orig.y * data[7] + orig.z * data[11] + data[15]); + *dest *= w; + return w; + } + + /** Transform a point and return w. */ + scalar TransformPointReturnW(const Vec3 & restrict orig, Vec3 * restrict dest) const { + piDebugCheck(&orig != dest); + dest->x = orig.x * data[0] + orig.y * data[4] + orig.z * data[8] + data[12]; + dest->y = orig.x * data[1] + orig.y * data[5] + orig.z * data[9] + data[13]; + dest->z = orig.x * data[2] + orig.y * data[6] + orig.z * data[10] + data[14]; + return orig.x * data[3] + orig.y * data[7] + orig.z * data[11] + data[15]; + } + + /** Transform a normalized 3d point by a 4d matrix and return the resulting 4d vector. */ + void TransformVec4(const Vec3 & orig, Vec4 * dest) const { + dest->x = orig.x * data[0] + orig.y * data[4] + orig.z * data[8] + data[12]; + dest->y = orig.x * data[1] + orig.y * data[5] + orig.z * data[9] + data[13]; + dest->z = orig.x * data[2] + orig.y * data[6] + orig.z * data[10] + data[14]; + dest->w = orig.x * data[3] + orig.y * data[7] + orig.z * data[11] + data[15]; + } + //@} + + /** @name Matrix analysis. */ + //@{ + + /** Get the ZYZ euler angles from the matrix. Assumes the matrix is orthonormal. */ + void GetEulerAnglesZYZ(scalar * s, scalar * t, scalar * r) const { + if( GetElem(2,2) < 1.0f ) { + if( GetElem(2,2) > -1.0f ) { + // cs*ct*cr-ss*sr -ss*ct*cr-cs*sr st*cr + // cs*ct*sr+ss*cr -ss*ct*sr+cs*cr st*sr + // -cs*st ss*st ct + *s = atan2(GetElem(1,2), -GetElem(0,2)); + *t = acos(GetElem(2,2)); + *r = atan2(GetElem(2,1), GetElem(2,0)); + } + else { + // -c(s-r) s(s-r) 0 + // s(s-r) c(s-r) 0 + // 0 0 -1 + *s = atan2(GetElem(0, 1), -GetElem(0, 0)); // = s-r + *t = PI; + *r = 0; + } + } + else { + // c(s+r) -s(s+r) 0 + // s(s+r) c(s+r) 0 + // 0 0 1 + *s = atan2(GetElem(0, 1), GetElem(0, 0)); // = s+r + *t = 0; + *r = 0; + } + } + + //@} + + MATHLIB_API friend PiStream & operator<< ( PiStream & s, Matrix & m ); + + /** Print to debug output. */ + void Print() const { + piDebug( "[ %5.2f %5.2f %5.2f %5.2f ]\n", data[0], data[4], data[8], data[12] ); + piDebug( "[ %5.2f %5.2f %5.2f %5.2f ]\n", data[1], data[5], data[9], data[13] ); + piDebug( "[ %5.2f %5.2f %5.2f %5.2f ]\n", data[2], data[6], data[10], data[14] ); + piDebug( "[ %5.2f %5.2f %5.2f %5.2f ]\n", data[3], data[7], data[11], data[15] ); + } + + +public: + + scalar data[16]; + +}; +#endif + + + + +#endif // NV_MATH_MATRIX_H