From 586a9ace2182b55cd17fe3959871680e009c775e Mon Sep 17 00:00:00 2001 From: Mikhail Romanko Date: Sun, 2 Feb 2025 21:40:31 +0300 Subject: Change file naming This is a follow-up to previous commit. --- CMakeLists.txt | 28 +- include/BH/Algo.h | 126 +++++ include/BH/Common.h | 25 + include/BH/Hashmap.h | 223 ++++++++ include/BH/IO.h | 252 +++++++++ include/BH/Math.h | 1400 ++++++++++++++++++++++++++++++++++++++++++++++ include/BH/Queue.h | 149 +++++ include/bh/algo.h | 126 ----- include/bh/common.h | 25 - include/bh/hashmap.h | 223 -------- include/bh/io.h | 252 --------- include/bh/math.h | 1400 ---------------------------------------------- include/bh/queue.h | 149 ----- src/Algo.c | 411 ++++++++++++++ src/Hashmap.c | 390 +++++++++++++ src/IO.c | 226 ++++++++ src/Math.c | 1449 ++++++++++++++++++++++++++++++++++++++++++++++++ src/Queue.c | 209 +++++++ src/algo.c | 411 -------------- src/dummy/File.c | 200 +++++++ src/dummy/file.c | 200 ------- src/hashmap.c | 390 ------------- src/io.c | 226 -------- src/math.c | 1449 ------------------------------------------------ src/posix/File.c | 406 ++++++++++++++ src/posix/file.c | 405 -------------- src/queue.c | 209 ------- src/win32/File.c | 405 ++++++++++++++ src/win32/file.c | 405 -------------- test/src/TestAlgo.c | 484 ++++++++++++++++ test/src/TestFile.c | 630 +++++++++++++++++++++ test/src/TestHashmap.c | 234 ++++++++ test/src/TestMath.c | 727 ++++++++++++++++++++++++ test/src/TestQueue.c | 171 ++++++ test/src/testalgo.c | 484 ---------------- test/src/testfile.c | 630 --------------------- test/src/testhashmap.c | 234 -------- test/src/testmath.c | 727 ------------------------ test/src/testqueue.c | 171 ------ unit/CMakeLists.txt | 4 +- unit/include/BH/Unit.h | 56 ++ unit/include/bh/unit.h | 56 -- unit/src/Unit.c | 61 ++ unit/src/unit.c | 61 -- 44 files changed, 8250 insertions(+), 8249 deletions(-) create mode 100755 include/BH/Algo.h create mode 100644 include/BH/Common.h create mode 100755 include/BH/Hashmap.h create mode 100644 include/BH/IO.h create mode 100644 include/BH/Math.h create mode 100755 include/BH/Queue.h delete mode 100755 include/bh/algo.h delete mode 100644 include/bh/common.h delete mode 100755 include/bh/hashmap.h delete mode 100644 include/bh/io.h delete mode 100644 include/bh/math.h delete mode 100755 include/bh/queue.h create mode 100755 src/Algo.c create mode 100755 src/Hashmap.c create mode 100644 src/IO.c create mode 100644 src/Math.c create mode 100755 src/Queue.c delete mode 100755 src/algo.c create mode 100644 src/dummy/File.c delete mode 100644 src/dummy/file.c delete mode 100755 src/hashmap.c delete mode 100644 src/io.c delete mode 100644 src/math.c create mode 100644 src/posix/File.c delete mode 100644 src/posix/file.c delete mode 100755 src/queue.c create mode 100644 src/win32/File.c delete mode 100644 src/win32/file.c create mode 100644 test/src/TestAlgo.c create mode 100644 test/src/TestFile.c create mode 100644 test/src/TestHashmap.c create mode 100644 test/src/TestMath.c create mode 100644 test/src/TestQueue.c delete mode 100644 test/src/testalgo.c delete mode 100644 test/src/testfile.c delete mode 100644 test/src/testhashmap.c delete mode 100644 test/src/testmath.c delete mode 100644 test/src/testqueue.c create mode 100755 unit/include/BH/Unit.h delete mode 100755 unit/include/bh/unit.h create mode 100755 unit/src/Unit.c delete mode 100755 unit/src/unit.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 0e2a50c..7af2e78 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -66,20 +66,20 @@ endif(TESTING) # Set library code set(BH_SOURCE - src/algo.c - src/hashmap.c - src/io.c - src/math.c - src/queue.c + src/Algo.c + src/Hashmap.c + src/IO.c + src/Math.c + src/Queue.c ) set(BH_HEADER - include/bh/common.h - include/bh/algo.h - include/bh/hashmap.h - include/bh/io.h - include/bh/math.h - include/bh/queue.h + include/BH/Common.h + include/BH/Algo.h + include/BH/Hashmap.h + include/BH/IO.h + include/BH/Math.h + include/BH/Queue.h ) set(BH_INCLUDE_DIRS @@ -93,21 +93,21 @@ if(WIN32) # Add platform dependent files list(APPEND BH_SOURCE - src/win32/file.c + src/win32/File.c ) elseif(UNIX) message(STATUS "Platform: Unix (Linux/BSD/MacOS X)") # Add platform dependent files list(APPEND BH_SOURCE - src/posix/file.c + src/posix/File.c ) else() message(STATUS "Platform: Unknown") # Add platform dependent files list(APPEND BH_SOURCE - src/dummy/file.c + src/dummy/File.c ) endif() diff --git a/include/BH/Algo.h b/include/BH/Algo.h new file mode 100755 index 0000000..2e5320e --- /dev/null +++ b/include/BH/Algo.h @@ -0,0 +1,126 @@ +#ifndef BH_ALGO_H +#define BH_ALGO_H + + +#include "Common.h" + + +/** + * Exchanges the values of two elements. + * + * \param dest Pointer to the element + * \param src Pointer to the element + * \param size Element size in bytes + */ +void BH_Swap(void *dest, + void *src, + size_t size); + + +/** + * Partitions the array relative to the specified pivot element. + * + * The pivot element can be part of the partitioned array. + * + * \param pivot Pointer to the pivot element + * \param array Pointer to the array + * \param size Array size + * \param element Element size in bytes + * \param equal Comparision function + * + * \return Pointer to the first element of the second partition. + */ +void *BH_Partition(void *pivot, + void *array, + size_t size, + size_t element, + BH_EqualCallback equal); + + +/** + * Sorts the array. + * + * \param array Pointer to the array + * \param size Array size + * \param element Element size in bytes + * \param equal Comparision function + */ +void BH_Sort(void *array, + size_t size, + size_t element, + BH_EqualCallback equal); + + +/** + * Makes heap in an array from the array. + * + * \param array Pointer to the array + * \param size Array size + * \param element Element size in bytes + * \param equal Comparision function + */ +void BH_HeapMake(void *array, + size_t size, + size_t element, + BH_EqualCallback equal); + + +/** + * Removes top/first element from a heap in an array. + * + * \param array Pointer to the array + * \param size Array size + * \param element Element size in bytes + * \param equal Comparasion function + */ +void BH_HeapRemove(void *array, + size_t size, + size_t element, + BH_EqualCallback equal); + + +/** + * Inserts new element into heap in an array. + * + * If the pointer to value is NULL, this function assumes that the new value + * is at the end of the array. + * + * \param value Pointer to the value + * \param array Pointer to the array + * \param size Array size + * \param element Element size in bytes + * \param equal Comparasion function + */ +void BH_HeapInsert(void *value, + void *array, + size_t size, + size_t element, + BH_EqualCallback equal); + + +/** + * Removes top/first element and inserts new element into heap in an array. + * + * If the pointer to value is NULL, this function assumes that the new value + * is at the end of the array. + * + * This function is roughly equivalent to the following code: + * \code + * BH_HeapRemove(array, size, element, equal); + * BH_HeapInsert(value, array, size - 1, element, equal); + * \endcode + * + * \param value Pointer to the value + * \param array Pointer to the array + * \param size Array size + * \param element Element size in bytes + * \param equal Comparasion function + */ +void BH_HeapReplace(void *value, + void *array, + size_t size, + size_t element, + BH_EqualCallback equal); + + +#endif /* BH_ALGO_H */ diff --git a/include/BH/Common.h b/include/BH/Common.h new file mode 100644 index 0000000..d4aadbe --- /dev/null +++ b/include/BH/Common.h @@ -0,0 +1,25 @@ +#ifndef BH_COMMON_H +#define BH_COMMON_H + +#include +#include + +#define BH_OK 0x0000 +#define BH_ERROR 0x0001 +#define BH_NOIMPL 0x0002 +#define BH_OOM 0x0003 +#define BH_INVALID 0x0004 +#define BH_FOUND 0x0005 +#define BH_NOTFOUND 0x0006 +#define BH_TIMEOUT 0x0007 + +#define BH_UNUSED(x) (void)(x) +#define BH_PTR2INT(x) ((intptr_t)(x)) +#define BH_INT2PTR(x) ((void*)(x)) + + +typedef int (*BH_EqualCallback)(const void *, const void *); +typedef size_t (*BH_HashCallback)(const void *); + +#endif /* BH_COMMON_H */ + diff --git a/include/BH/Hashmap.h b/include/BH/Hashmap.h new file mode 100755 index 0000000..615e747 --- /dev/null +++ b/include/BH/Hashmap.h @@ -0,0 +1,223 @@ +#ifndef BH_HASHMAP_H +#define BH_HASHMAP_H + + +#include "Common.h" + + +typedef struct BH_Hashmap BH_Hashmap; + + +/** + * Creates the new hashmap handle. + * + * \param equal Comparision function + * \param hash Key hash function + * + * \return On success, returns hashmap handle. + * \return On failure, returns a null pointer. + */ +BH_Hashmap *BH_HashmapNew(BH_EqualCallback equal, + BH_HashCallback hash); + + +/** + * Destroys the hashmap. + * + * \param hashmap Hashmap handle + */ +void BH_HashmapFree(BH_Hashmap *hashmap); + + +/** + * Clears the hashmap. + * + * \param hashmap Hashmap handle + */ +void BH_HashmapClear(BH_Hashmap *hashmap); + + +/** + * Reserves space in the hashmap. + * + * This function can both expand and shrink the available space in hashmap. + * This function takes into account current hashmap load factor. + * + * \param hashmap Hahsmap handle + * \param size Capacity + * + * \note Calling this function will invalidate iterators. + * \note Actual hashmap capacity can be bigger then requested. + * + * \return On success, returns zero value. + * \return On failure, returns error code. + */ +int BH_HashmapReserve(BH_Hashmap *hashmap, + size_t size); + + +/** + * Inserts the pair of key-value into the hashmap. + * + * \param hashmap Hashmap handle + * \param key Key + * \param value Value + * + * \note This function allows duplicates to be inserted. + * \note Calling this function will invalidate iterators. + * + * \return On success, returns zero value. + * \return On failure, returns error code. + */ +int BH_HashmapInsert(BH_Hashmap *hashmap, + void *key, + void *value); + + +/** + * Removes value from the hashmap. + * + * \param hashmap Hashmap handle + * \param key Key + * + * \note Calling this function will invalidate iterators. + * \note If hashmap contains several elements with the same key, this function + * will remove only one key-value pair. + */ +void BH_HashmapRemove(BH_Hashmap *hashmap, + void *key); + + +/** + * Returns value from the hashmap by key. + * + * \param hashmap Hashmap handle + * \param key Key + * \param value Value (optional) + * + * \return On success, returns zero value. + * \return On failure, returns error code. + */ +int BH_HashmapAt(BH_Hashmap *hashmap, + void *key, + void **value); + + +/** + * Checks if the hashmap is empty. + * + * \param hashmap Hashmap handle + * + * \return If hashmap is empty, returns non-zero value + * \return If hashmap is not empty, returns zero value + */ +int BH_HashmapEmpty(BH_Hashmap *hashmap); + + +/** + * Returns the size of the hashmap. + * + * \param hashmap Hashmap handle + * + * \return Returns the size of the hashmap. + */ +size_t BH_HashmapSize(BH_Hashmap *hashmap); + + +/** + * Returns the capacity of the hashmap. + * + * \param hashmap Hashmap handle + * + * \return Returns the capacity of the hashmap. + */ +size_t BH_HashmapCapacity(BH_Hashmap *hashmap); + + +/** + * Returns the load factor of the hashmap. + * + * \param hashmap Hashmap handle + * + * \return Returns the load factor of the hashmap. + */ +float BH_HashmapFactor(BH_Hashmap *hashmap); + + +/** + * Sets the load factor of the hashmap. + * + * \param hashmap Hashmap handle + * \param factor Load factor + * + * \note New load factor will be applied on the next reserve/insert operation. + */ +void BH_HashmapSetFactor(BH_Hashmap *hashmap, + float factor); + + +/** + * Returns the iterator to the element in the hashmap with specified key. + * + * \param hashmap Hashmap handle + * \param iter Iterator + * + * \return On success, returns iterator value. + * \return On failure, returns NULL pointer. + * + * \note If hashmap contains several elements with the same key, this function + * will return iterator to one of them + */ +void *BH_HashmapIterAt(BH_Hashmap *hashmap, + void *key); + + +/** + * Returns the iterator to the next element in the hashmap. + * + * If the iterator is NULL pointer, this function will return iterator to the + * first element of the hashmap. + * + * \param hashmap Hashmap handle + * \param iter Iterator + * + * \return On success, returns new iterator value for the next element. + * \return On failure, returns NULL pointer. + */ +void *BH_HashmapIterNext(BH_Hashmap *hashmap, + void *iter); + + +/** + * Removes value from the hashmap pointed by by iterator. + * + * \param hashmap Hashmap handle + * \param iter Iterator + * + * \note Calling this function will invalidate iterators. + */ +void BH_HashmapIterRemove(BH_Hashmap *hashmap, + void *iter); + + +/** + * Returns key, pointed by the iterator. + * + * \param iter Iterator + * + * \return Returns key. + */ +void *BH_HashmapIterKey(void *iter); + + +/** + * Returns value, pointed by the iterator. + * + * \param iter Iterator + * + * \return Returns value. + */ +void *BH_HashmapIterValue(void *iter); + + +#endif /* BH_HASHMAP_H */ diff --git a/include/BH/IO.h b/include/BH/IO.h new file mode 100644 index 0000000..e0a2fea --- /dev/null +++ b/include/BH/IO.h @@ -0,0 +1,252 @@ +#ifndef BH_IO_H +#define BH_IO_H + + +#include "Common.h" + + +#define BH_IO_INFO_CB 0x0000 +#define BH_IO_INIT_CB 0x0001 +#define BH_IO_DESTROY_CB 0x0002 +#define BH_IO_OPEN_CB 0x0003 +#define BH_IO_CLOSE_CB 0x0004 +#define BH_IO_READ_CB 0x0005 +#define BH_IO_WRITE_CB 0x0006 +#define BH_IO_PEEK_CB 0x0007 +#define BH_IO_TELL_CB 0x0008 +#define BH_IO_SEEK_CB 0x0009 +#define BH_IO_FLUSH_CB 0x000A +#define BH_IO_SIZE_CB 0x000B +#define BH_IO_FLAGS_CB 0x000C +#define BH_IO_CLEAR_CB 0x000D + + +#define BH_IO_READ 0x0001 +#define BH_IO_WRITE 0x0002 +#define BH_IO_READWRITE 0x0003 +#define BH_IO_APPEND 0x0010 +#define BH_IO_TRUNCATE 0x0020 +#define BH_IO_CREATE 0x0040 +#define BH_IO_EXIST 0x0080 + + +#define BH_IO_SEEK_SET 0x0000 +#define BH_IO_SEEK_CUR 0x0001 +#define BH_IO_SEEK_END 0x0002 + + +#define BH_IO_FLAG_OK 0x0000 +#define BH_IO_FLAG_ERROR 0x0001 +#define BH_IO_FLAG_EOF 0x0002 +#define BH_IO_FLAG_OPEN 0x0004 + +#define BH_FILE_CLASSNAME "BH_File" + + +typedef struct BH_IO BH_IO; +typedef int (*BH_IOCallback)(void *, int ,void *, void *); + + +/** + * Creates the IO handle that represents file. + * + * \param path Path to the file + * + * \return On success, returns IO handle. + * \return On failure, returns NULL pointer. + */ +BH_IO *BH_FileNew(const char *path); + + +/** + * Creates the IO handle that represents buffered IO. + * + * \param io IO handle + * + * \return On success, returns IO handle. + * \return On failure, returns NULL pointer. + */ +BH_IO *BH_BufferNew(BH_IO *io); + + +/** + * Creates the IO handle with specified handler and context. + * + * \param func IO actions handler + * \param data Initialization data + * + * \return On success, returns IO handle. + * \return On failure, returns NULL pointer. + */ +BH_IO *BH_IONew(BH_IOCallback cb, + void *data); + + +/** + * Destroys the IO. + * + * \param io IO handle + */ +void BH_IOFree(BH_IO *io); + + +/** + * Returns the IO instance classname. + * + * \param io IO handle + * + * \return On success, returns pointer to constant string. + * \return On failure, returns NULL pointer + */ +const char *BH_IOClassname(BH_IO* io); + + +/** + * Opens the IO in specified mode of operation. + * + * \param io IO handle + * \param mode Mode of operation + * + * \return On success, returns zero value. + * \return On failure, returns error code. + */ +int BH_IOOpen(BH_IO *io, + int mode); + + +/** + * Closes the IO. + * + * \param io IO handle + * + * \return On success, returns zero value. + * \return On failure, returns error code. + */ +int BH_IOClose(BH_IO *io); + + +/** + * Reads up to specified amount of bytes from the IO into memory buffer. + * + * \param io IO handle + * \param buffer Pointer to the buffer + * \param size Bytes to read + * \param actual Bytes read + * + * \return On success, returns zero value. + * \return On failure, returns error code. + */ +int BH_IORead(BH_IO *io, + char *buffer, + size_t size, + size_t *actual); + + +/** + * Writes up to specified amount of bytes into the IO from the memory buffer. + * + * \param io IO handle + * \param buffer Pointer to the buffer + * \param size Bytes to write + * \param actual Bytes written + * + * \return On success, returns zero value. + * \return On failure, returns error code. + */ +int BH_IOWrite(BH_IO *io, + const char *buffer, + size_t size, + size_t *actual); + + +/** + * Peeks up to specified amount of bytes from the IO handle. + * + * \param io IO handle + * \param buffer Pointer to the buffer + * \param size Bytes to peek + * \param actial Bytes peeked + * + * \return On success, returns zero value. + * \return On failure, returns error code. + */ +int BH_IOPeek(BH_IO *io, + char *buffer, + size_t size, + size_t *actual); + + +/** + * Tells current offset in the IO. + * + * \param io IO handle + * \param position Offset + * + * \return On success, returns zero value. + * \return On failure, returns error code. + */ +int BH_IOTell(BH_IO *io, + int64_t *position); + + +/** + * Seeks to specified offset in the IO. + * + * \param io IO handle + * \param position Offset + * \param direction Direction + * + * \return On success, returns zero value. + * \return On failure, returns error code. + */ +int BH_IOSeek(BH_IO *io, + int64_t position, + int direction); + + +/** + * Flushes the internal buffers of the IO. + * + * \param io IO handle + * + * \return On success, returns zero value. + * \return On failure, returns error code. + */ +int BH_IOFlush(BH_IO *io); + + +/** + * Returns the size of the IO (either total or available size). + * + * \param io IO handle + * \param size Available/total size + * + * \return On success, returns zero value. + * \return On failure, returns error code. + */ +int BH_IOSize(BH_IO *io, + int64_t *size); + + +/** + * Returns flags of the IO. + * + * \param io IO handle + * + * \return Flags of the IO + */ +int BH_IOFlags(BH_IO *io); + + +/** + * Clears errors of the IO. + * + * \param io IO handle + * + * \return On success, returns zero value. + * \return On failure, returns error code. + */ +int BH_IOClear(BH_IO *io); + + +#endif /* BH_IO_H */ diff --git a/include/BH/Math.h b/include/BH/Math.h new file mode 100644 index 0000000..badc092 --- /dev/null +++ b/include/BH/Math.h @@ -0,0 +1,1400 @@ +#ifndef BH_MATH_H +#define BH_MATH_H + + +#include "Common.h" + + +/** + * Adds \a a and \a b floating point vectors and stores result into \a out. + * + * \param a A 4D vector + * \param b B 4D vector + * \param out Output 4D vector + */ +void BH_Vec4fAdd(const float *a, + const float *b, + float *out); + + +/** + * Subtracts \a a and \a b floating point vectors and stores result into \a out. + * + * \param a A 4D vector + * \param b B 4D vector + * \param out Output 4D vector + */ +void BH_Vec4fSub(const float *a, + const float *b, + float *out); + + +/** + * Multiplies \a a and \a b floating point vectors and stores result into + * \a out. + * + * \param a A 4D vector + * \param b B 4D vector + * \param out Output 4D vector + */ +void BH_Vec4fMul(const float *a, + const float *b, + float *out); + + +/** + * Scales \a a vector by the value \a b and stores result into \a out. + * + * \param a A 4D vector + * \param b B value + * \param out Output vector + */ +void BH_Vec4fScale(const float *a, + float b, + float *out); + + +/** + * Multiples \a a and \a b vectors, adds to \a c and stores result into \a out. + * + * \param a A 4D vector + * \param b B 4D vector + * \param c C 4D vector + * \param out Output 4D vector + */ +void BH_Vec4fMulAdd(const float *a, + const float *b, + const float *c, + float *out); + + +/** + * Negates \a in vector and stores result into \a out. + * + * \param in Input 4D vector + * \param out Output 4D vector + */ +void BH_Vec4fNegate(const float *in, + float *out); + + +/** + * Computes dot product of \a a and \a b vectors and returns the result. + * + * \param a A 4D vector + * \param b B 4D vector + */ +float BH_Vec4fDot(const float *a, + const float *b); + + +/** + * Computes length of the \a in vector and returns the result. + * + * \param in Input 4D vector + */ +float BH_Vec4fLength(const float *in); + + +/** + * Computes normal vector from the \a in and stores result into \a out. + * + * \param in Input 4D vector + * \param out Output 4D vector + */ +void BH_Vec4fNormal(const float *in, + float *out); + + +/** + * Computes minimum vector from the \a a and \a b vectors and stores result + * into \a out. + * + * \param a A 4D vector + * \param b B 4D vector + * \param out Output 4D vector + */ +void BH_Vec4fMin(const float *a, + const float *b, + float *out); + + +/** + * Computes maximum vector from the \a a and \a b vectors and stores result + * into \a out. + * + * \param a A 4D vector + * \param b B 4D vector + * \param out Output 4D vector + */ +void BH_Vec4fMax(const float *a, + const float *b, + float *out); + + +/** + * Interpolates between \a a and \a b vector by \a t amount and stores result + * into \a out. + * + * \param a A 4D vector + * \param b B 4D vector + * \param t Amount + * \param out Output 4D vector + */ +void BH_Vec4fLerp(const float *a, + const float *b, + float t, + float *out); + + +/** + * Adds \a a and \a b floating point vectors and stores result into \a out. + * + * \param a A 3D vector + * \param b B 3D vector + * \param out Output 3D vector + */ +void BH_Vec3fAdd(const float *a, + const float *b, + float *out); + + +/** + * Subtracts \a a and \a b floating point vectors and stores result into \a out. + * + * \param a A 3D vector + * \param b B 3D vector + * \param out Output 3D vector + */ +void BH_Vec3fSub(const float *a, + const float *b, + float *out); + + +/** + * Multiplies \a a and \a b floating point vectors and stores result into + * \a out. + * + * \param a A 3D vector + * \param b B 3D vector + * \param out Output 3D vector + */ +void BH_Vec3fMul(const float *a, + const float *b, + float *out); + + +/** + * Scales \a a vector by the value \a b and stores result into \a out. + * + * \param a A 3D vector + * \param b B value + * \param out Output 3D vector + */ +void BH_Vec3fScale(const float *a, + float b, + float *out); + + +/** + * Multiples \a a and \a b vectors, adds to \a c and stores result into \a out. + * + * \param a A 3D vector + * \param b B 3D vector + * \param c C 3D vector + * \param out Output 3D vector + */ +void BH_Vec3fMulAdd(const float *a, + const float *b, + const float *c, + float *out); + + +/** + * Negates \a in vector and stores result into \a out. + * + * \param in Input 3D vector + * \param out Output 3D vector + * + */ +void BH_Vec3fNegate(const float *in, + float *out); + + +/** + * Computes dot product of \a a and \a b vectors and returns the result. + * + * \param a A 3D vector + * \param b B 3D vector + */ +float BH_Vec3fDot(const float *a, + const float *b); + + +/** + * Computes cross product of \a a and \a b vectors and stores + * result into \a out. + * + * \param a A 3D vector + * \param b B 3D vector + * \param out Output 3D vector + */ +void BH_Vec3fCross(const float *a, + const float *b, + float *out); + + +/** + * Computes length of the \a in vector and returns the result. + * + * \param in Input 3D vector + */ +float BH_Vec3fLength(const float *in); + + +/** + * Computes normal vector from the \a in and stores result into \a out. + * + * \param in Input 3D vector + * \param out Output 3D vector + */ +void BH_Vec3fNormal(const float *in, + float *out); + + +/** + * Computes minimum vector from the \a a and \a b vectors and stores result into + * \a out. + * + * \param a A 3D vector + * \param b B 3D vector + * \param out Output 3D vector + */ +void BH_Vec3fMin(const float *a, + const float *b, + float *out); + + +/** + * Computes maximum vector from the \a a and \a b vectors and stores result into + * \a out. + * + * \param a A 3D vector + * \param b B 3D vector + * \param out Output 3D vector + */ +void BH_Vec3fMax(const float *a, + const float *b, + float *out); + + +/** + * Interpolates between \a a and \a b vector by \a t amount and stores result + * into \a out. + * + * \param a A 3D vector + * \param b B 3D vector + * \param t Amount + * \param out Output 3D vector + */ +void BH_Vec3fLerp(const float *a, + const float *b, + float t, + float *out); + + +/** + * Adds \a a and \a b floating point vectors and stores result into \a out. + * + * \param a A 2D vector + * \param b B 2D vector + * \param out Output 2D vector + */ +void BH_Vec2fAdd(const float *a, + const float *b, + float *out); + + +/** + * Subtracts \a a and \a b floating point vectors and stores result into \a out. + * + * \param a A 2D vector + * \param b B 2D vector + * \param out Output 2D vector + */ +void BH_Vec2fSub(const float *a, + const float *b, + float *out); + + +/** + * Multiplies \a a and \a b floating point vectors and stores result into + * \a out. + * + * \param a A 2D vector + * \param b B 2D vector + * \param out Output 2D vector + */ +void BH_Vec2fMul(const float *a, + const float *b, + float *out); + + +/** + * Scales \a a vector by the value \a b and stores result into \a out. + * + * \param a A 2D vector + * \param b B value + * \param out Output 2D vector + */ +void BH_Vec2fScale(const float *a, + float b, + float *out); + + +/** + * Multiples \a a and \a b vectors, adds to \a c and stores result into \a out. + * + * \param a A 2D vector + * \param b B 2D vector + * \param c C 2D vector + * \param out Output 2D vector + */ +void BH_Vec2fMulAdd(const float *a, + const float *b, + const float *c, + float *out); + + +/** + * Negates \a in vector and stores result into \a out. + * + * \param in Input 2D vector + * \param out Output 2D vector + * + */ +void BH_Vec2fNegate(const float *in, + float *out); + + +/** + * Computes dot product of \a a and \a b vectors and returns the result. + * + * \param a A 2D vector + * \param b B 2D vector + */ +float BH_Vec2fDot(const float *a, + const float *b); + + +/** + * Computes cross product of \a a and \a b vectors and returns the result. + * + * \param a A 2D vector + * \param b B 2D vector + */ +float BH_Vec2fCross(const float *a, + const float *b); + + +/** + * Computes length of the \a in vector and returns the result. + * + * \param in Input 2D vector + */ +float BH_Vec2fLength(const float *in); + + +/** + * Computes normal vector from the \a in and stores result into + * \a out. + * + * \param in Input 2D vector + * \param out Output 2D vector + */ +void BH_Vec2fNormal(const float *in, + float *out); + + +/** + * Computes minimum vector from the \a a and \a b vectors and stores result into + * \a out. + * + * \param a A 2D vector + * \param b B 2D vector + * \param out Output 2D vector + */ +void BH_Vec2fMin(const float *a, + const float *b, + float *out); + + +/** + * Computes maximum vector from the \a a and \a b vectors and stores result into + * \a out. + * + * \param a A 2D vector + * \param b B 2D vector + * \param out Output 2D vector + */ +void BH_Vec2fMax(const float *a, + const float *b, + float *out); + + +/** + * Interpolates between \a a and \a b vector by \a t amount and stores result + * into \a out. + * + * \param a A 2D vector + * \param b B 2D vector + * \param t Amount + * \param out Output 2D vector + */ +void BH_Vec2fLerp(const float *a, + const float *b, + float t, + float *out); + + +/** + * Adds \a a and \a b integer vectors and stores result into \a out. + * + * \param a A 4D vector + * \param b B 4D vector + * \param out Output 4D vector + */ +void BH_Vec4iAdd(const int *a, + const int *b, + int *out); + + +/** + * Subtracts \a a and \a b integer vectors and stores result into \a out. + * + * \param a A 4D vector + * \param b B 4D vector + * \param out Output 4D vector + */ +void BH_Vec4iSub(const int *a, + const int *b, + int *out); + + +/** + * Multiplies \a a and \a b integers vectors and stores result into \a out. + * + * \param a A 4D vector + * \param b B 4D vector + * \param out Output vector + */ +void BH_Vec4iMul(const int *a, + const int *b, + int *out); + + +/** + * Scales \a a vector by the value \a b and stores result into \a out. + * + * \param a A 4D vector + * \param b B value + * \param out Output 4D vector + */ +void BH_Vec4iScale(const int *a, + int b, + int *out); + + +/** + * Multiples \a a and \a b vectors, adds to \a c and stores result into \a out. + * + * \param a A 4D vector + * \param b B 4D vector + * \param c C 4D vector + * \param out Output 4D vector + */ +void BH_Vec4iMulAdd(const int *a, + const int *b, + const int *c, + int *out); + + +/** + * Negates \a in vector and stores result into \a out. + * + * \param in Input 4D vector + * \param out Output 4D vector + */ +void BH_Vec4iNegate(const int *in, + int *out); + + +/** + * Computes minimum vector from the \a a and \a b vectors and stores result into + * \a out. + * + * \param a A 4D vector + * \param b B 4D vector + * \param out Output 4D vector + */ +void BH_Vec4iMin(const int *a, + const int *b, + int *out); + + +/** + * Computes maximum vector from the \a a and \a b vectors and stores result into + * \a out. + * + * \param a A 4D vector + * \param b B 4D vector + * \param out Output 4D vector + */ +void BH_Vec4iMax(const int *a, + const int *b, + int *out); + + +/** + * Adds \a a and \a b integer vectors and stores result into \a out. + * + * \param a A 3D vector + * \param b B 3D vector + * \param out Output 3D vector + */ +void BH_Vec3iAdd(const int *a, + const int *b, + int *out); + + +/** + * Subtracts \a a and \a b integer vectors and stores result into \a out. + * + * \param a A 3D vector + * \param b B 3D vector + * \param out Output 3D vector + */ +void BH_Vec3iSub(const int *a, + const int *b, + int *out); + + +/** + * Multiplies \a a and \a b integers vectors and stores result into \a out. + * + * \param a A 3D vector + * \param b B 3D vector + * \param out Output 3D vector + */ +void BH_Vec3iMul(const int *a, + const int *b, + int *out); + + +/** + * Scales \a a vector by the value \a b and stores result into \a out. + * + * \param a A 3D vector + * \param b B value + * \param out Output 3D vector + */ +void BH_Vec3iScale(const int *a, + int b, + int *out); + + +/** + * Multiples \a a and \a b vectors, adds to \a c and stores result into \a out. + * + * \param a A 3D vector + * \param b B 3D vector + * \param c C 3D vector + * \param out Output 3D vector + */ +void BH_Vec3iMulAdd(const int *a, + const int *b, + const int *c, + int *out); + + +/** + * Negates \a in vector and stores result into \a out. + * + * \param in Input 3D vector + * \param out Output 3D vector + * + */ +void BH_Vec3iNegate(const int *in, + int *out); + + +/** + * Computes minimum vector from the \a a and \a b vectors and stores result into + * \a out. + * + * \param a A 3D vector + * \param b B 3D vector + * \param out Output 3D vector + */ +void BH_Vec3iMin(const int *a, + const int *b, + int *out); + + +/** + * Computes maximum vector from the \a a and \a b vectors and stores result into + * \a out. + * + * \param a A 3D vector + * \param b B 3D vector + * \param out Output 3D vector + */ +void BH_Vec3iMax(const int *a, + const int *b, + int *out); + + +/** + * Adds \a a and \a b integer vectors and stores result into \a out. + * + * \param a A 2D vector + * \param b B 2D vector + * \param out Output 2D vector + */ +void BH_Vec2iAdd(const int *a, + const int *b, + int *out); + + +/** + * Subtracts \a a and \a b integer vectors and stores result into \a out. + * + * \param a A 2D vector + * \param b B 2D vector + * \param out Output 2D vector + */ +void BH_Vec2iSub(const int *a, + const int *b, + int *out); + + +/** + * Multiplies \a a and \a b integers vectors and stores result into \a out. + * + * \param a A 2D vector + * \param b B 2D vector + * \param out Output 2D vector + */ +void BH_Vec2iMul(const int *a, + const int *b, + int *out); + + +/** + * Scales \a a vector by the value \a b and stores result into \a out. + * + * \param a A 2D vector + * \param b B 2D value + * \param out Output 2D vector + */ +void BH_Vec2iScale(const int *a, + int b, + int *out); + + +/** + * Multiples \a a and \a b vectors, adds to \a c and stores result into \a out. + * + * \param a A 2D vector + * \param b B 2D vector + * \param c C 2D vector + * \param out Output 2D vector + */ +void BH_Vec2iMulAdd(const int *a, + const int *b, + const int *c, + int *out); + + +/** + * Negates \a in vector and stores result into \a out. + * + * \param in Input 2D vector + * \param out Output 2D vector + * + */ +void BH_Vec2iNegate(const int *in, + int *out); + + +/** + * Computes minimum vector from the \a a and \a b vectors and stores result into + * \a out. + * + * \param a A 2D vector + * \param b B 2D vector + * \param out Output 2D vector + */ +void BH_Vec2iMin(const int *a, + const int *b, + int *out); + + +/** + * Computes maximum vector from the \a a and \a b vectors and stores result into + * \a out. + * + * \param a A 2D vector + * \param b B 2D vector + * \param out Output 2D vector + */ +void BH_Vec2iMax(const int *a, + const int *b, + int *out); + + +/** + * Adds \a a and \a b floating point quaternions and stores result into \a out. + * + * \param a A quaternion + * \param b B quaternion + * \param out Output quaternion + */ +#define BH_Quat4fAdd(a, b, out) \ + BH_Vec4fAdd(a, b, out) + + +/** + * Subtracts \a a and \a b floating point quaternions and stores result into + * \a out. + * + * \param a A quaternion + * \param b B quaternion + * \param out Output quaternion + */ +#define BH_Quat4fSub(a, b, out) \ + BH_Vec4fSub(a, b, out) + + +/** + * Scales \a a quaternion by the value \a b and stores result into \a out. + * + * \param a A quaternion + * \param b B value + * \param out Output quaternion + */ +#define BH_Quat4fScale(a, b, out) \ + BH_Vec4fScale(a, b, out) + + +/** + * Negates \a in quaternion and stores result into \a out. + * + * \param in Input quaternion + * \param out Output quaternion + */ +#define BH_Quat4fNegate(in, out) \ + BH_Vec4fNegate(in, out) + + +/** + * Computes dot product of \a a and \a b quaternions and returns the result. + * + * \param a A quaternion + * \param b B quaternion + */ +#define BH_Quat4fDot(a, b) \ + BH_Vec4fDot(a, b) + + +/** + * Computes length of the \a in quaternion and returns the result. + * + * \param in Input quaternion + */ +#define BH_Quat4fLength(in) \ + BH_Vec4fLength(in) + + +/** + * Computes normal quaternion from the \a in and stores result into \a out. + * + * \param in Input quaternion + * \param out Output quaternion + */ +#define BH_Quat4fNormal(in, out) \ + BH_Vec4fNormal(in, out) + + +/** + * Interpolates between \a a and \a b quaternion by \a t amount and stores + * result into \a out. + * + * \param a A quaternion + * \param b B quaternion + * \param t Amount + * \param out Output quaternion + */ +#define BH_Quat4fLerp(a, b, t, out) \ + BH_Vec4fLerp(a, b, t, out) + + +/** + * Stores identity quaternion into \a out. + * + * \param out Output quaternion. + */ +void BH_Quat4fIdentity(float *out); + + +/** + * Conjugates the \a in quaternion and stores result into \a out. + * + * \param in Input quaternion + * \param out Output quaternion + */ +void BH_Quat4fConjugate(const float *in, + float *out); + + +/** + * Computes the inverse of the \a in quaternion and stores result into \a out. + * + * \param in Input quaternion + * \param out Output quaternion + */ +void BH_Quat4fInverse(const float *in, + float *out); + + +/** + * Multiplies the \a a and \a b quaternions and stores result into \a out. + * + * \param a A quaternion + * \param b B quaternion + * \param out Output quaternion + */ +void BH_Quat4fMul(const float *a, + const float *b, + float *out); + + +/** + * Spherically interpolates between \a a and \a b quaternions by \a t amount and + * stores result into \a out. + * + * \param a A quaternion + * \param b B quaternion + * \param t Amount + * \param out Output quaternion + */ +void BH_Quat4fSlerp(const float *a, + const float *b, + float t, + float *out); + + +/** + * Computes the quaternion that represents \a roll, \a pitch, \a yaw (euler + * angles) and stores result into \a out. + * + * Order of the rotation is ZYX (yaw, pitch, roll) + * + * \param roll Roll + * \param pitch Pitch + * \param yaw Yaw + * \param out Output quaternion + */ +void BH_Quat4fFromEuler(float roll, + float pitch, + float yaw, + float *out); + + +/** + * Computes quaternion that represents rotation by angle \a angle around + * axis \a axis and stores result into \a out. + * + * \param axis Axis 3D vector + * \param angle Angle + * \param out Output quaternion + */ +void BH_Quat4fFromAxis(const float *axis, + float angle, + float *out); + + +/** + * Computes euler angles from quaternion \a in and stores result into \a roll, + * \a pitch, \a yaw. + * + * Order of the rotation is ZYX (yaw, pitch, roll) + * + * \param in Input quaternion + * \param roll Output roll + * \param pitch Output pitch + * \param yaw Output yaw + */ +void BH_Quat4fToEuler(const float *in, + float *roll, + float *pitch, + float *yaw); + + +/** + * Computes rotation around axis from quaternion \a in and stores result into + * \a axis and \a angle. + * + * \param in Input quaternion + * \param axis Output axis 3D vector + * \param angle Output angle + */ +void BH_Quat4fToAxis(const float *in, + float *axis, + float *angle); + + +/** + * Computes 4x4 rotation matrix from quaternion \a in and stores result into + * \a out. + * + * \param in Input quaternion + * \param out Output 4x4 matrix + */ +void BH_Quat4fToMat4f(const float *in, + float *out); + + +/** + * Stores identity matrix into \a out. + * + * \param out Output 4x4 matrix. + */ +void BH_Mat4fIdentity(float *out); + + +/** + * Adds \a a and \a b floating point matricies and stores result into \a out. + * + * \param a A 4x4 matrix + * \param b B 4x4 matrix + * \param out Output 4x4 matrix + */ +void BH_Mat4fAdd(const float *a, + const float *b, + float *out); + + +/** + * Subtracts \a a and \a b floating point matricies and stores result into + * \a out. + * + * \param a A 4x4 matrix + * \param b B 4x4 matrix + * \param out Output 4x4 matrix + */ +void BH_Mat4fSub(const float *a, + const float *b, + float *out); + + +/** + * Multiplies \a a and \a b floating point matricies and stores result into + * \a out. + * + * \param a A 4x4 matrix + * \param b B 4x4 matrix + * \param out Output 4x4 matrix + */ +void BH_Mat4fMul(const float *a, + const float *b, + float *out); + + +/** + * Scales \a a matrix by the value \a b and stores result into \a out. + * + * \param a A 4x4 matrix + * \param b B value + * \param out Output 4x4 matrix + */ +void BH_Mat4fScale(const float *a, + float b, + float *out); + + +/** + * Transposes matrix \a in and stores result into \a out. + * + * \param in Input 4x4 matrix + * \param out Output 4x4 matrix + */ +void BH_Mat4fTranspose(const float *in, + float *out); + + +/** + * Computes \a in matrix trace and returns the result. + * + * \param in Input 4x4 matrix + */ +float BH_Mat4fTrace(const float *in); + + +/** + * Computes \a in matrix determinant and returns the result. + * + * \param in Input 4x4 matrix + */ +float BH_Mat4fDet(const float *in); + + +/** + * Computes inverse of \a in matrix and stores result into \a out. + * + * \param in Input 4x4 matrix + * \param out OUtput 4x4 matrix + * + * \return On success, returns zero. + * \return On failure, returns error code. + */ +int BH_Mat4fInverse(const float *in, + float *out); + + +/** + * Computes scaling matrix from values \a x, \a y, \a z and stores result into + * \a out. + * + * \param x X scale + * \param y Y scale + * \param z Z scale + * \param out Output 4x4 matrix + */ +void BH_Mat4fFromScale(float x, + float y, + float z, + float *out); + + +/** + * Computes translation matrix from values \a x, \a y, \a z and stores result + * into \a out. + * + * \param x X translation + * \param y Y translation + * \param z Z translation + * \param out Output 4x4 matrix + */ +void BH_Mat4fFromTranslation(float x, + float y, + float z, + float *out); + + +/** + * Computes rotation matrix around x axis with angle \a angle and stores + * result \a out. + * + * \param angle Angle + * \param out Output 4x4 matrix + */ +void BH_Mat4fFromRotationX(float angle, + float *out); + + +/** + * Computes rotation matrix around y axis with angle \a angle and stores + * result \a out. + * + * \param angle Angle + * \param out Output 4x4 matrix + */ +void BH_Mat4fFromRotationY(float angle, + float *out); + + +/** + * Computes rotation matrix around z axis with angle \a angle and stores + * result \a out. + * + * \param angle Angle + * \param out Output 4x4 matrix + */ +void BH_Mat4fFromRotationZ(float angle, + float *out); + + +/** + * Computes rotation matrix around axis \a axis with angle \a angle and stores + * result \a out. + * + * \param axis Axis 3D vector + * \param angle Angle + * \param out Output 4x4 matrix + */ +void BH_Mat4fFromAxis(const float *axis, + float angle, + float *out); + + +/** + * Computes the rotation matrix that represents \a roll, \a pitch, \a yaw (euler + * angles) and stores result into \a out. + * + * Order of the rotation is ZYX (yaw, pitch, roll) + * + * \param roll Roll + * \param pitch Pitch + * \param yaw Yaw + * \param out Output 4x4 matrix + */ +void BH_Mat4fFromEuler(float roll, + float pitch, + float yaw, + float *out); + + +/** + * Computes 4x4 rotation matrix from quaternion \a in and stores result into + * \a out. + * + * \param in Input quaternion + * \param out Output 4x4 matrix + */ +void BH_Mat4fFromQuat4f(const float *in, + float *out); + + +/** + * Computes orthographic projection matrix and stores result into \a out. + * + * \param x_min Min x value + * \param x_max Max x value + * \param y_min Min y value + * \param y_max Max y value + * \param z_min Min z value + * \param z_max Max z value + * \param out Output 4x4 matrix + */ +void BH_Mat4fFromOrtho(float xMin, + float xMax, + float yMin, + float yMax, + float zMin, + float zMax, + float *out); + + +/** + * Computes perspective projection matrix and stores result into \a out. + * + * \param fov Field of view + * \param aspect Aspect ratio + * \param z_min Min z value + * \param z_max Max z value + * \param out Output 4x4 matrix + */ +void BH_Mat4fFromFrustum(float fov, + float aspect, + float zMin, + float zMax, + float *out); + + +/** + * Computes camera view matrix and stores result into \a out. + * + * \param pos Position vector + * \param at Target vector + * \param up Up vector + * \param out Output 4x4 matrix + */ +void BH_Mat4fFromLookAt(const float *pos, + const float *at, + const float *up, + float *out); + + +/** + * Multiplies matrix \a a by vector \a b and stores result into \a out. + * + * \param a A 4x4 matrix + * \param b B 4D vector + * \param out Output 4D vector + */ +void BH_Mat4fApplyVec4f(const float *a, + const float *b, + float *out); + + +/** + * Multiplies matrix \a a by vector \a b and stores result into \a out. + * + * \param a A 4x4 matrix + * \param b B 3D vector + * \param out Output 3D vector + */ +void BH_Mat4fApplyVec4f(const float *a, + const float *b, + float *out); + + +/** + * Stores identity matrix into \a out. + * + * \param out Output 3x3 matrix. + */ +void BH_Mat3fIdentity(float *out); + + +/** + * Adds \a a and \a b floating point matricies and stores result into \a out. + * + * \param a A 3x3 matrix + * \param b B 3x3 matrix + * \param out Output 3x3 matrix + */ +void BH_Mat3fAdd(const float *a, + const float *b, + float *out); + + +/** + * Subtracts \a a and \a b floating point matricies and stores result into + * \a out. + * + * \param a A 3x3 matrix + * \param b B 3x3 matrix + * \param out Output 3x3 matrix + */ +void BH_Mat3fSub(const float *a, + const float *b, + float *out); + + +/** + * Multiplies \a a and \a b floating point matricies and stores result into + * \a out. + * + * \param a A 3x3 matrix + * \param b B 3x3 matrix + * \param out Output 3x3 matrix + */ +void BH_Mat3fMul(const float *a, + const float *b, + float *out); + + +/** + * Scales \a a matrix by the value \a b and stores result into \a out. + * + * \param a A 3x3 matrix + * \param b B value + * \param out Output 3x3 matrix + */ +void BH_Mat3fScale(const float *a, + float b, + float *out); + + +/** + * Transposes matrix \a in and stores result into \a out. + * + * \param in Input 3x3 matrix + * \param out Output 3x3 matrix + */ +void BH_Mat3fTranspose(const float *in, + float *out); + + +/** + * Computes \a in matrix trace and returns the result. + * + * \param in Input 3x3 matrix + */ +float BH_Mat3fTrace(const float *in); + + +/** + * Computes \a in matrix determinant and returns the result. + * + * \param in Input 3x3 matrix + */ +float BH_Mat3fDet(const float *in); + + +/** + * Computes inverse of \a in matrix and stores result into \a out. + * + * \param in Input 3x3 matrix + * \param out OUtput 3x3 matrix + * + * \return On success, returns zero. + * \return On failure, returns error code. + */ +int BH_Mat3fInverse(const float *in, + float *out); + + +/** + * Computes scaling matrix from values \a x, \a y and stores result into + * \a out. + * + * \param x X scale + * \param y Y scale + * \param out Output 3x3 matrix + */ +void BH_Mat3fFromScale(float x, + float y, + float *out); + + +/** + * Computes translation matrix from values \a x, \a y and stores result + * into \a out. + * + * \param x X translation + * \param y Y translation + * \param out Output 3x3 matrix + */ +void BH_Mat3fFromTranslation(float x, + float y, + float *out); + + +/** + * Computes rotation matrix around with angle \a angle and stores result \a out. + * + * \param angle Angle + * \param out Output 3x3 matrix + */ +void BH_Mat3fFromRotation(float angle, + float *out); + + +/** + * Multiplies matrix \a a by vector \a b and stores result into \a out. + * + * \param a A 3x3 matrix + * \param b B 3D vector + * \param out Output 3D vector + */ +void BH_Mat3fApplyVec3f(float *a, + float *b, + float *out); + + +/** + * Multiplies matrix \a a by vector \a b and stores result into \a out. + * + * \param a A 3x3 matrix + * \param b B 2D vector + * \param out Output 2D vector + */ +void BH_Mat3fApplyVec2f(float *a, + float *b, + float *out); + + +#endif /* BH_MATH_H */ diff --git a/include/BH/Queue.h b/include/BH/Queue.h new file mode 100755 index 0000000..5d6af58 --- /dev/null +++ b/include/BH/Queue.h @@ -0,0 +1,149 @@ +#ifndef BH_QUEUE_H +#define BH_QUEUE_H + + +#include "Common.h" + + +typedef struct BH_Queue BH_Queue; + + +/** + * Creates the new queue object. + * + * \return On success, returns the pointer to the new queue object. + * \return On failure, returns a null pointer. + */ +BH_Queue *BH_QueueNew(void); + + +/** + * Frees the \a queue object. + * + * \param queue Pointer to the queue object to be freed + */ +void BH_QueueFree(BH_Queue *queue); + + +/** + * Clears the \a queue object. + * + * \param queue Pointer to the queue object to be cleared + */ +void BH_QueueClear(BH_Queue *queue); + + +/** + * Reserves the space for \a size elements in the \a queue. + * + * This function can both expand and shrink the available space in \a queue. + * + * \param queue Pointer to the queue object to be resized in terms of capacity + * \param size New capacity of the queue + * + * \note Calling this function will invalidate iterators. + * \note Actual hashmap capacity can be bigger then requested. + * + * \return On success, returns zero value. + * \return On failure, returns error code. + */ +int BH_QueueReserve(BH_Queue *queue, + size_t size); + + +/** + * Inserts the \a value into the \a queue. + * + * \param queue Pointer to the queue object + * \param value Value to be inserted + * + * \note Calling this function will invalidate iterators. + * + * \return On success, returns zero value. + * \return On failure, returns error code. + */ +int BH_QueueInsert(BH_Queue *queue, + void *value); + + +/** + * Removes front value from the \a queue. + * + * \param queue Pointer to the queue object + * + * \note Calling this function will invalidate iterators. + */ +void BH_QueueRemove(BH_Queue *queue); + + +/** + * Returns front value from the \a queue. + * + * \param queue Pointer to the queue object + * + * \return On success, returns front value from the queue. + * \return On failure, returns null pointer. + */ +int BH_QueueFront(BH_Queue *queue, + void **value); + + +/** + * Checks if the \a queue is empty. + * + * \param queue Pointer to the queue object + * + * \return If queue is empty, returns non-zero value + * \return If queue is not empty, returns zero value + */ +int BH_QueueEmpty(BH_Queue *queue); + + +/** + * Returns the size of the \a queue. + * + * \param queue Pointer to the queue object + * + * \return Returns the size of the queue. + */ +size_t BH_QueueSize(BH_Queue *queue); + + +/** + * Returns the capacity of the \a queue. + * + * \param queue Pointer to the queue object + * + * \return Returns the capacity of the queue. + */ +size_t BH_QueueCapacity(BH_Queue *queue); + + +/** + * Returns the iterator to the next element in the \a queue. + * + * \param queue Pointer to the queue object + * \param iter Opaque iterator value + * + * \return If the \a iter doesn't point to the last element of the queue, + * returns next iterator value. + * \return If the \a iter point to the last element of the queue, returns + * null pointer. + * \return If the \a iter is the null pointer, returns iterator to the + * first element of the queue. + */ +void *BH_QueueIterNext(BH_Queue *queue, + void *iter); + + +/** + * Returns the value, pointed by the queue iterator \a iter. + * + * \param iter Opaque iterator value + * + * \return Returns value, pointed by iterator. + */ +void *BH_QueueIterValue(void *iter); + + +#endif /* BH_QUEUE_H */ diff --git a/include/bh/algo.h b/include/bh/algo.h deleted file mode 100755 index 5d9bb36..0000000 --- a/include/bh/algo.h +++ /dev/null @@ -1,126 +0,0 @@ -#ifndef BH_ALGO_H -#define BH_ALGO_H - - -#include "common.h" - - -/** - * Exchanges the values of two elements. - * - * \param dest Pointer to the element - * \param src Pointer to the element - * \param size Element size in bytes - */ -void BH_Swap(void *dest, - void *src, - size_t size); - - -/** - * Partitions the array relative to the specified pivot element. - * - * The pivot element can be part of the partitioned array. - * - * \param pivot Pointer to the pivot element - * \param array Pointer to the array - * \param size Array size - * \param element Element size in bytes - * \param equal Comparision function - * - * \return Pointer to the first element of the second partition. - */ -void *BH_Partition(void *pivot, - void *array, - size_t size, - size_t element, - BH_EqualCallback equal); - - -/** - * Sorts the array. - * - * \param array Pointer to the array - * \param size Array size - * \param element Element size in bytes - * \param equal Comparision function - */ -void BH_Sort(void *array, - size_t size, - size_t element, - BH_EqualCallback equal); - - -/** - * Makes heap in an array from the array. - * - * \param array Pointer to the array - * \param size Array size - * \param element Element size in bytes - * \param equal Comparision function - */ -void BH_HeapMake(void *array, - size_t size, - size_t element, - BH_EqualCallback equal); - - -/** - * Removes top/first element from a heap in an array. - * - * \param array Pointer to the array - * \param size Array size - * \param element Element size in bytes - * \param equal Comparasion function - */ -void BH_HeapRemove(void *array, - size_t size, - size_t element, - BH_EqualCallback equal); - - -/** - * Inserts new element into heap in an array. - * - * If the pointer to value is NULL, this function assumes that the new value - * is at the end of the array. - * - * \param value Pointer to the value - * \param array Pointer to the array - * \param size Array size - * \param element Element size in bytes - * \param equal Comparasion function - */ -void BH_HeapInsert(void *value, - void *array, - size_t size, - size_t element, - BH_EqualCallback equal); - - -/** - * Removes top/first element and inserts new element into heap in an array. - * - * If the pointer to value is NULL, this function assumes that the new value - * is at the end of the array. - * - * This function is roughly equivalent to the following code: - * \code - * BH_HeapRemove(array, size, element, equal); - * BH_HeapInsert(value, array, size - 1, element, equal); - * \endcode - * - * \param value Pointer to the value - * \param array Pointer to the array - * \param size Array size - * \param element Element size in bytes - * \param equal Comparasion function - */ -void BH_HeapReplace(void *value, - void *array, - size_t size, - size_t element, - BH_EqualCallback equal); - - -#endif /* BH_ALGO_H */ diff --git a/include/bh/common.h b/include/bh/common.h deleted file mode 100644 index d4aadbe..0000000 --- a/include/bh/common.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef BH_COMMON_H -#define BH_COMMON_H - -#include -#include - -#define BH_OK 0x0000 -#define BH_ERROR 0x0001 -#define BH_NOIMPL 0x0002 -#define BH_OOM 0x0003 -#define BH_INVALID 0x0004 -#define BH_FOUND 0x0005 -#define BH_NOTFOUND 0x0006 -#define BH_TIMEOUT 0x0007 - -#define BH_UNUSED(x) (void)(x) -#define BH_PTR2INT(x) ((intptr_t)(x)) -#define BH_INT2PTR(x) ((void*)(x)) - - -typedef int (*BH_EqualCallback)(const void *, const void *); -typedef size_t (*BH_HashCallback)(const void *); - -#endif /* BH_COMMON_H */ - diff --git a/include/bh/hashmap.h b/include/bh/hashmap.h deleted file mode 100755 index d3710e4..0000000 --- a/include/bh/hashmap.h +++ /dev/null @@ -1,223 +0,0 @@ -#ifndef BH_HASHMAP_H -#define BH_HASHMAP_H - - -#include "common.h" - - -typedef struct BH_Hashmap BH_Hashmap; - - -/** - * Creates the new hashmap handle. - * - * \param equal Comparision function - * \param hash Key hash function - * - * \return On success, returns hashmap handle. - * \return On failure, returns a null pointer. - */ -BH_Hashmap *BH_HashmapNew(BH_EqualCallback equal, - BH_HashCallback hash); - - -/** - * Destroys the hashmap. - * - * \param hashmap Hashmap handle - */ -void BH_HashmapFree(BH_Hashmap *hashmap); - - -/** - * Clears the hashmap. - * - * \param hashmap Hashmap handle - */ -void BH_HashmapClear(BH_Hashmap *hashmap); - - -/** - * Reserves space in the hashmap. - * - * This function can both expand and shrink the available space in hashmap. - * This function takes into account current hashmap load factor. - * - * \param hashmap Hahsmap handle - * \param size Capacity - * - * \note Calling this function will invalidate iterators. - * \note Actual hashmap capacity can be bigger then requested. - * - * \return On success, returns zero value. - * \return On failure, returns error code. - */ -int BH_HashmapReserve(BH_Hashmap *hashmap, - size_t size); - - -/** - * Inserts the pair of key-value into the hashmap. - * - * \param hashmap Hashmap handle - * \param key Key - * \param value Value - * - * \note This function allows duplicates to be inserted. - * \note Calling this function will invalidate iterators. - * - * \return On success, returns zero value. - * \return On failure, returns error code. - */ -int BH_HashmapInsert(BH_Hashmap *hashmap, - void *key, - void *value); - - -/** - * Removes value from the hashmap. - * - * \param hashmap Hashmap handle - * \param key Key - * - * \note Calling this function will invalidate iterators. - * \note If hashmap contains several elements with the same key, this function - * will remove only one key-value pair. - */ -void BH_HashmapRemove(BH_Hashmap *hashmap, - void *key); - - -/** - * Returns value from the hashmap by key. - * - * \param hashmap Hashmap handle - * \param key Key - * \param value Value (optional) - * - * \return On success, returns zero value. - * \return On failure, returns error code. - */ -int BH_HashmapAt(BH_Hashmap *hashmap, - void *key, - void **value); - - -/** - * Checks if the hashmap is empty. - * - * \param hashmap Hashmap handle - * - * \return If hashmap is empty, returns non-zero value - * \return If hashmap is not empty, returns zero value - */ -int BH_HashmapEmpty(BH_Hashmap *hashmap); - - -/** - * Returns the size of the hashmap. - * - * \param hashmap Hashmap handle - * - * \return Returns the size of the hashmap. - */ -size_t BH_HashmapSize(BH_Hashmap *hashmap); - - -/** - * Returns the capacity of the hashmap. - * - * \param hashmap Hashmap handle - * - * \return Returns the capacity of the hashmap. - */ -size_t BH_HashmapCapacity(BH_Hashmap *hashmap); - - -/** - * Returns the load factor of the hashmap. - * - * \param hashmap Hashmap handle - * - * \return Returns the load factor of the hashmap. - */ -float BH_HashmapFactor(BH_Hashmap *hashmap); - - -/** - * Sets the load factor of the hashmap. - * - * \param hashmap Hashmap handle - * \param factor Load factor - * - * \note New load factor will be applied on the next reserve/insert operation. - */ -void BH_HashmapSetFactor(BH_Hashmap *hashmap, - float factor); - - -/** - * Returns the iterator to the element in the hashmap with specified key. - * - * \param hashmap Hashmap handle - * \param iter Iterator - * - * \return On success, returns iterator value. - * \return On failure, returns NULL pointer. - * - * \note If hashmap contains several elements with the same key, this function - * will return iterator to one of them - */ -void *BH_HashmapIterAt(BH_Hashmap *hashmap, - void *key); - - -/** - * Returns the iterator to the next element in the hashmap. - * - * If the iterator is NULL pointer, this function will return iterator to the - * first element of the hashmap. - * - * \param hashmap Hashmap handle - * \param iter Iterator - * - * \return On success, returns new iterator value for the next element. - * \return On failure, returns NULL pointer. - */ -void *BH_HashmapIterNext(BH_Hashmap *hashmap, - void *iter); - - -/** - * Removes value from the hashmap pointed by by iterator. - * - * \param hashmap Hashmap handle - * \param iter Iterator - * - * \note Calling this function will invalidate iterators. - */ -void BH_HashmapIterRemove(BH_Hashmap *hashmap, - void *iter); - - -/** - * Returns key, pointed by the iterator. - * - * \param iter Iterator - * - * \return Returns key. - */ -void *BH_HashmapIterKey(void *iter); - - -/** - * Returns value, pointed by the iterator. - * - * \param iter Iterator - * - * \return Returns value. - */ -void *BH_HashmapIterValue(void *iter); - - -#endif /* BH_HASHMAP_H */ diff --git a/include/bh/io.h b/include/bh/io.h deleted file mode 100644 index ee2da95..0000000 --- a/include/bh/io.h +++ /dev/null @@ -1,252 +0,0 @@ -#ifndef BH_IO_H -#define BH_IO_H - - -#include "common.h" - - -#define BH_IO_INFO_CB 0x0000 -#define BH_IO_INIT_CB 0x0001 -#define BH_IO_DESTROY_CB 0x0002 -#define BH_IO_OPEN_CB 0x0003 -#define BH_IO_CLOSE_CB 0x0004 -#define BH_IO_READ_CB 0x0005 -#define BH_IO_WRITE_CB 0x0006 -#define BH_IO_PEEK_CB 0x0007 -#define BH_IO_TELL_CB 0x0008 -#define BH_IO_SEEK_CB 0x0009 -#define BH_IO_FLUSH_CB 0x000A -#define BH_IO_SIZE_CB 0x000B -#define BH_IO_FLAGS_CB 0x000C -#define BH_IO_CLEAR_CB 0x000D - - -#define BH_IO_READ 0x0001 -#define BH_IO_WRITE 0x0002 -#define BH_IO_READWRITE 0x0003 -#define BH_IO_APPEND 0x0010 -#define BH_IO_TRUNCATE 0x0020 -#define BH_IO_CREATE 0x0040 -#define BH_IO_EXIST 0x0080 - - -#define BH_IO_SEEK_SET 0x0000 -#define BH_IO_SEEK_CUR 0x0001 -#define BH_IO_SEEK_END 0x0002 - - -#define BH_IO_FLAG_OK 0x0000 -#define BH_IO_FLAG_ERROR 0x0001 -#define BH_IO_FLAG_EOF 0x0002 -#define BH_IO_FLAG_OPEN 0x0004 - -#define BH_FILE_CLASSNAME "BH_File" - - -typedef struct BH_IO BH_IO; -typedef int (*BH_IOCallback)(void *, int ,void *, void *); - - -/** - * Creates the IO handle that represents file. - * - * \param path Path to the file - * - * \return On success, returns IO handle. - * \return On failure, returns NULL pointer. - */ -BH_IO *BH_FileNew(const char *path); - - -/** - * Creates the IO handle that represents buffered IO. - * - * \param io IO handle - * - * \return On success, returns IO handle. - * \return On failure, returns NULL pointer. - */ -BH_IO *BH_BufferNew(BH_IO *io); - - -/** - * Creates the IO handle with specified handler and context. - * - * \param func IO actions handler - * \param data Initialization data - * - * \return On success, returns IO handle. - * \return On failure, returns NULL pointer. - */ -BH_IO *BH_IONew(BH_IOCallback cb, - void *data); - - -/** - * Destroys the IO. - * - * \param io IO handle - */ -void BH_IOFree(BH_IO *io); - - -/** - * Returns the IO instance classname. - * - * \param io IO handle - * - * \return On success, returns pointer to constant string. - * \return On failure, returns NULL pointer - */ -const char *BH_IOClassname(BH_IO* io); - - -/** - * Opens the IO in specified mode of operation. - * - * \param io IO handle - * \param mode Mode of operation - * - * \return On success, returns zero value. - * \return On failure, returns error code. - */ -int BH_IOOpen(BH_IO *io, - int mode); - - -/** - * Closes the IO. - * - * \param io IO handle - * - * \return On success, returns zero value. - * \return On failure, returns error code. - */ -int BH_IOClose(BH_IO *io); - - -/** - * Reads up to specified amount of bytes from the IO into memory buffer. - * - * \param io IO handle - * \param buffer Pointer to the buffer - * \param size Bytes to read - * \param actual Bytes read - * - * \return On success, returns zero value. - * \return On failure, returns error code. - */ -int BH_IORead(BH_IO *io, - char *buffer, - size_t size, - size_t *actual); - - -/** - * Writes up to specified amount of bytes into the IO from the memory buffer. - * - * \param io IO handle - * \param buffer Pointer to the buffer - * \param size Bytes to write - * \param actual Bytes written - * - * \return On success, returns zero value. - * \return On failure, returns error code. - */ -int BH_IOWrite(BH_IO *io, - const char *buffer, - size_t size, - size_t *actual); - - -/** - * Peeks up to specified amount of bytes from the IO handle. - * - * \param io IO handle - * \param buffer Pointer to the buffer - * \param size Bytes to peek - * \param actial Bytes peeked - * - * \return On success, returns zero value. - * \return On failure, returns error code. - */ -int BH_IOPeek(BH_IO *io, - char *buffer, - size_t size, - size_t *actual); - - -/** - * Tells current offset in the IO. - * - * \param io IO handle - * \param position Offset - * - * \return On success, returns zero value. - * \return On failure, returns error code. - */ -int BH_IOTell(BH_IO *io, - int64_t *position); - - -/** - * Seeks to specified offset in the IO. - * - * \param io IO handle - * \param position Offset - * \param direction Direction - * - * \return On success, returns zero value. - * \return On failure, returns error code. - */ -int BH_IOSeek(BH_IO *io, - int64_t position, - int direction); - - -/** - * Flushes the internal buffers of the IO. - * - * \param io IO handle - * - * \return On success, returns zero value. - * \return On failure, returns error code. - */ -int BH_IOFlush(BH_IO *io); - - -/** - * Returns the size of the IO (either total or available size). - * - * \param io IO handle - * \param size Available/total size - * - * \return On success, returns zero value. - * \return On failure, returns error code. - */ -int BH_IOSize(BH_IO *io, - int64_t *size); - - -/** - * Returns flags of the IO. - * - * \param io IO handle - * - * \return Flags of the IO - */ -int BH_IOFlags(BH_IO *io); - - -/** - * Clears errors of the IO. - * - * \param io IO handle - * - * \return On success, returns zero value. - * \return On failure, returns error code. - */ -int BH_IOClear(BH_IO *io); - - -#endif /* BH_IO_H */ diff --git a/include/bh/math.h b/include/bh/math.h deleted file mode 100644 index 5471a4a..0000000 --- a/include/bh/math.h +++ /dev/null @@ -1,1400 +0,0 @@ -#ifndef BH_MATH_H -#define BH_MATH_H - - -#include "common.h" - - -/** - * Adds \a a and \a b floating point vectors and stores result into \a out. - * - * \param a A 4D vector - * \param b B 4D vector - * \param out Output 4D vector - */ -void BH_Vec4fAdd(const float *a, - const float *b, - float *out); - - -/** - * Subtracts \a a and \a b floating point vectors and stores result into \a out. - * - * \param a A 4D vector - * \param b B 4D vector - * \param out Output 4D vector - */ -void BH_Vec4fSub(const float *a, - const float *b, - float *out); - - -/** - * Multiplies \a a and \a b floating point vectors and stores result into - * \a out. - * - * \param a A 4D vector - * \param b B 4D vector - * \param out Output 4D vector - */ -void BH_Vec4fMul(const float *a, - const float *b, - float *out); - - -/** - * Scales \a a vector by the value \a b and stores result into \a out. - * - * \param a A 4D vector - * \param b B value - * \param out Output vector - */ -void BH_Vec4fScale(const float *a, - float b, - float *out); - - -/** - * Multiples \a a and \a b vectors, adds to \a c and stores result into \a out. - * - * \param a A 4D vector - * \param b B 4D vector - * \param c C 4D vector - * \param out Output 4D vector - */ -void BH_Vec4fMulAdd(const float *a, - const float *b, - const float *c, - float *out); - - -/** - * Negates \a in vector and stores result into \a out. - * - * \param in Input 4D vector - * \param out Output 4D vector - */ -void BH_Vec4fNegate(const float *in, - float *out); - - -/** - * Computes dot product of \a a and \a b vectors and returns the result. - * - * \param a A 4D vector - * \param b B 4D vector - */ -float BH_Vec4fDot(const float *a, - const float *b); - - -/** - * Computes length of the \a in vector and returns the result. - * - * \param in Input 4D vector - */ -float BH_Vec4fLength(const float *in); - - -/** - * Computes normal vector from the \a in and stores result into \a out. - * - * \param in Input 4D vector - * \param out Output 4D vector - */ -void BH_Vec4fNormal(const float *in, - float *out); - - -/** - * Computes minimum vector from the \a a and \a b vectors and stores result - * into \a out. - * - * \param a A 4D vector - * \param b B 4D vector - * \param out Output 4D vector - */ -void BH_Vec4fMin(const float *a, - const float *b, - float *out); - - -/** - * Computes maximum vector from the \a a and \a b vectors and stores result - * into \a out. - * - * \param a A 4D vector - * \param b B 4D vector - * \param out Output 4D vector - */ -void BH_Vec4fMax(const float *a, - const float *b, - float *out); - - -/** - * Interpolates between \a a and \a b vector by \a t amount and stores result - * into \a out. - * - * \param a A 4D vector - * \param b B 4D vector - * \param t Amount - * \param out Output 4D vector - */ -void BH_Vec4fLerp(const float *a, - const float *b, - float t, - float *out); - - -/** - * Adds \a a and \a b floating point vectors and stores result into \a out. - * - * \param a A 3D vector - * \param b B 3D vector - * \param out Output 3D vector - */ -void BH_Vec3fAdd(const float *a, - const float *b, - float *out); - - -/** - * Subtracts \a a and \a b floating point vectors and stores result into \a out. - * - * \param a A 3D vector - * \param b B 3D vector - * \param out Output 3D vector - */ -void BH_Vec3fSub(const float *a, - const float *b, - float *out); - - -/** - * Multiplies \a a and \a b floating point vectors and stores result into - * \a out. - * - * \param a A 3D vector - * \param b B 3D vector - * \param out Output 3D vector - */ -void BH_Vec3fMul(const float *a, - const float *b, - float *out); - - -/** - * Scales \a a vector by the value \a b and stores result into \a out. - * - * \param a A 3D vector - * \param b B value - * \param out Output 3D vector - */ -void BH_Vec3fScale(const float *a, - float b, - float *out); - - -/** - * Multiples \a a and \a b vectors, adds to \a c and stores result into \a out. - * - * \param a A 3D vector - * \param b B 3D vector - * \param c C 3D vector - * \param out Output 3D vector - */ -void BH_Vec3fMulAdd(const float *a, - const float *b, - const float *c, - float *out); - - -/** - * Negates \a in vector and stores result into \a out. - * - * \param in Input 3D vector - * \param out Output 3D vector - * - */ -void BH_Vec3fNegate(const float *in, - float *out); - - -/** - * Computes dot product of \a a and \a b vectors and returns the result. - * - * \param a A 3D vector - * \param b B 3D vector - */ -float BH_Vec3fDot(const float *a, - const float *b); - - -/** - * Computes cross product of \a a and \a b vectors and stores - * result into \a out. - * - * \param a A 3D vector - * \param b B 3D vector - * \param out Output 3D vector - */ -void BH_Vec3fCross(const float *a, - const float *b, - float *out); - - -/** - * Computes length of the \a in vector and returns the result. - * - * \param in Input 3D vector - */ -float BH_Vec3fLength(const float *in); - - -/** - * Computes normal vector from the \a in and stores result into \a out. - * - * \param in Input 3D vector - * \param out Output 3D vector - */ -void BH_Vec3fNormal(const float *in, - float *out); - - -/** - * Computes minimum vector from the \a a and \a b vectors and stores result into - * \a out. - * - * \param a A 3D vector - * \param b B 3D vector - * \param out Output 3D vector - */ -void BH_Vec3fMin(const float *a, - const float *b, - float *out); - - -/** - * Computes maximum vector from the \a a and \a b vectors and stores result into - * \a out. - * - * \param a A 3D vector - * \param b B 3D vector - * \param out Output 3D vector - */ -void BH_Vec3fMax(const float *a, - const float *b, - float *out); - - -/** - * Interpolates between \a a and \a b vector by \a t amount and stores result - * into \a out. - * - * \param a A 3D vector - * \param b B 3D vector - * \param t Amount - * \param out Output 3D vector - */ -void BH_Vec3fLerp(const float *a, - const float *b, - float t, - float *out); - - -/** - * Adds \a a and \a b floating point vectors and stores result into \a out. - * - * \param a A 2D vector - * \param b B 2D vector - * \param out Output 2D vector - */ -void BH_Vec2fAdd(const float *a, - const float *b, - float *out); - - -/** - * Subtracts \a a and \a b floating point vectors and stores result into \a out. - * - * \param a A 2D vector - * \param b B 2D vector - * \param out Output 2D vector - */ -void BH_Vec2fSub(const float *a, - const float *b, - float *out); - - -/** - * Multiplies \a a and \a b floating point vectors and stores result into - * \a out. - * - * \param a A 2D vector - * \param b B 2D vector - * \param out Output 2D vector - */ -void BH_Vec2fMul(const float *a, - const float *b, - float *out); - - -/** - * Scales \a a vector by the value \a b and stores result into \a out. - * - * \param a A 2D vector - * \param b B value - * \param out Output 2D vector - */ -void BH_Vec2fScale(const float *a, - float b, - float *out); - - -/** - * Multiples \a a and \a b vectors, adds to \a c and stores result into \a out. - * - * \param a A 2D vector - * \param b B 2D vector - * \param c C 2D vector - * \param out Output 2D vector - */ -void BH_Vec2fMulAdd(const float *a, - const float *b, - const float *c, - float *out); - - -/** - * Negates \a in vector and stores result into \a out. - * - * \param in Input 2D vector - * \param out Output 2D vector - * - */ -void BH_Vec2fNegate(const float *in, - float *out); - - -/** - * Computes dot product of \a a and \a b vectors and returns the result. - * - * \param a A 2D vector - * \param b B 2D vector - */ -float BH_Vec2fDot(const float *a, - const float *b); - - -/** - * Computes cross product of \a a and \a b vectors and returns the result. - * - * \param a A 2D vector - * \param b B 2D vector - */ -float BH_Vec2fCross(const float *a, - const float *b); - - -/** - * Computes length of the \a in vector and returns the result. - * - * \param in Input 2D vector - */ -float BH_Vec2fLength(const float *in); - - -/** - * Computes normal vector from the \a in and stores result into - * \a out. - * - * \param in Input 2D vector - * \param out Output 2D vector - */ -void BH_Vec2fNormal(const float *in, - float *out); - - -/** - * Computes minimum vector from the \a a and \a b vectors and stores result into - * \a out. - * - * \param a A 2D vector - * \param b B 2D vector - * \param out Output 2D vector - */ -void BH_Vec2fMin(const float *a, - const float *b, - float *out); - - -/** - * Computes maximum vector from the \a a and \a b vectors and stores result into - * \a out. - * - * \param a A 2D vector - * \param b B 2D vector - * \param out Output 2D vector - */ -void BH_Vec2fMax(const float *a, - const float *b, - float *out); - - -/** - * Interpolates between \a a and \a b vector by \a t amount and stores result - * into \a out. - * - * \param a A 2D vector - * \param b B 2D vector - * \param t Amount - * \param out Output 2D vector - */ -void BH_Vec2fLerp(const float *a, - const float *b, - float t, - float *out); - - -/** - * Adds \a a and \a b integer vectors and stores result into \a out. - * - * \param a A 4D vector - * \param b B 4D vector - * \param out Output 4D vector - */ -void BH_Vec4iAdd(const int *a, - const int *b, - int *out); - - -/** - * Subtracts \a a and \a b integer vectors and stores result into \a out. - * - * \param a A 4D vector - * \param b B 4D vector - * \param out Output 4D vector - */ -void BH_Vec4iSub(const int *a, - const int *b, - int *out); - - -/** - * Multiplies \a a and \a b integers vectors and stores result into \a out. - * - * \param a A 4D vector - * \param b B 4D vector - * \param out Output vector - */ -void BH_Vec4iMul(const int *a, - const int *b, - int *out); - - -/** - * Scales \a a vector by the value \a b and stores result into \a out. - * - * \param a A 4D vector - * \param b B value - * \param out Output 4D vector - */ -void BH_Vec4iScale(const int *a, - int b, - int *out); - - -/** - * Multiples \a a and \a b vectors, adds to \a c and stores result into \a out. - * - * \param a A 4D vector - * \param b B 4D vector - * \param c C 4D vector - * \param out Output 4D vector - */ -void BH_Vec4iMulAdd(const int *a, - const int *b, - const int *c, - int *out); - - -/** - * Negates \a in vector and stores result into \a out. - * - * \param in Input 4D vector - * \param out Output 4D vector - */ -void BH_Vec4iNegate(const int *in, - int *out); - - -/** - * Computes minimum vector from the \a a and \a b vectors and stores result into - * \a out. - * - * \param a A 4D vector - * \param b B 4D vector - * \param out Output 4D vector - */ -void BH_Vec4iMin(const int *a, - const int *b, - int *out); - - -/** - * Computes maximum vector from the \a a and \a b vectors and stores result into - * \a out. - * - * \param a A 4D vector - * \param b B 4D vector - * \param out Output 4D vector - */ -void BH_Vec4iMax(const int *a, - const int *b, - int *out); - - -/** - * Adds \a a and \a b integer vectors and stores result into \a out. - * - * \param a A 3D vector - * \param b B 3D vector - * \param out Output 3D vector - */ -void BH_Vec3iAdd(const int *a, - const int *b, - int *out); - - -/** - * Subtracts \a a and \a b integer vectors and stores result into \a out. - * - * \param a A 3D vector - * \param b B 3D vector - * \param out Output 3D vector - */ -void BH_Vec3iSub(const int *a, - const int *b, - int *out); - - -/** - * Multiplies \a a and \a b integers vectors and stores result into \a out. - * - * \param a A 3D vector - * \param b B 3D vector - * \param out Output 3D vector - */ -void BH_Vec3iMul(const int *a, - const int *b, - int *out); - - -/** - * Scales \a a vector by the value \a b and stores result into \a out. - * - * \param a A 3D vector - * \param b B value - * \param out Output 3D vector - */ -void BH_Vec3iScale(const int *a, - int b, - int *out); - - -/** - * Multiples \a a and \a b vectors, adds to \a c and stores result into \a out. - * - * \param a A 3D vector - * \param b B 3D vector - * \param c C 3D vector - * \param out Output 3D vector - */ -void BH_Vec3iMulAdd(const int *a, - const int *b, - const int *c, - int *out); - - -/** - * Negates \a in vector and stores result into \a out. - * - * \param in Input 3D vector - * \param out Output 3D vector - * - */ -void BH_Vec3iNegate(const int *in, - int *out); - - -/** - * Computes minimum vector from the \a a and \a b vectors and stores result into - * \a out. - * - * \param a A 3D vector - * \param b B 3D vector - * \param out Output 3D vector - */ -void BH_Vec3iMin(const int *a, - const int *b, - int *out); - - -/** - * Computes maximum vector from the \a a and \a b vectors and stores result into - * \a out. - * - * \param a A 3D vector - * \param b B 3D vector - * \param out Output 3D vector - */ -void BH_Vec3iMax(const int *a, - const int *b, - int *out); - - -/** - * Adds \a a and \a b integer vectors and stores result into \a out. - * - * \param a A 2D vector - * \param b B 2D vector - * \param out Output 2D vector - */ -void BH_Vec2iAdd(const int *a, - const int *b, - int *out); - - -/** - * Subtracts \a a and \a b integer vectors and stores result into \a out. - * - * \param a A 2D vector - * \param b B 2D vector - * \param out Output 2D vector - */ -void BH_Vec2iSub(const int *a, - const int *b, - int *out); - - -/** - * Multiplies \a a and \a b integers vectors and stores result into \a out. - * - * \param a A 2D vector - * \param b B 2D vector - * \param out Output 2D vector - */ -void BH_Vec2iMul(const int *a, - const int *b, - int *out); - - -/** - * Scales \a a vector by the value \a b and stores result into \a out. - * - * \param a A 2D vector - * \param b B 2D value - * \param out Output 2D vector - */ -void BH_Vec2iScale(const int *a, - int b, - int *out); - - -/** - * Multiples \a a and \a b vectors, adds to \a c and stores result into \a out. - * - * \param a A 2D vector - * \param b B 2D vector - * \param c C 2D vector - * \param out Output 2D vector - */ -void BH_Vec2iMulAdd(const int *a, - const int *b, - const int *c, - int *out); - - -/** - * Negates \a in vector and stores result into \a out. - * - * \param in Input 2D vector - * \param out Output 2D vector - * - */ -void BH_Vec2iNegate(const int *in, - int *out); - - -/** - * Computes minimum vector from the \a a and \a b vectors and stores result into - * \a out. - * - * \param a A 2D vector - * \param b B 2D vector - * \param out Output 2D vector - */ -void BH_Vec2iMin(const int *a, - const int *b, - int *out); - - -/** - * Computes maximum vector from the \a a and \a b vectors and stores result into - * \a out. - * - * \param a A 2D vector - * \param b B 2D vector - * \param out Output 2D vector - */ -void BH_Vec2iMax(const int *a, - const int *b, - int *out); - - -/** - * Adds \a a and \a b floating point quaternions and stores result into \a out. - * - * \param a A quaternion - * \param b B quaternion - * \param out Output quaternion - */ -#define BH_Quat4fAdd(a, b, out) \ - BH_Vec4fAdd(a, b, out) - - -/** - * Subtracts \a a and \a b floating point quaternions and stores result into - * \a out. - * - * \param a A quaternion - * \param b B quaternion - * \param out Output quaternion - */ -#define BH_Quat4fSub(a, b, out) \ - BH_Vec4fSub(a, b, out) - - -/** - * Scales \a a quaternion by the value \a b and stores result into \a out. - * - * \param a A quaternion - * \param b B value - * \param out Output quaternion - */ -#define BH_Quat4fScale(a, b, out) \ - BH_Vec4fScale(a, b, out) - - -/** - * Negates \a in quaternion and stores result into \a out. - * - * \param in Input quaternion - * \param out Output quaternion - */ -#define BH_Quat4fNegate(in, out) \ - BH_Vec4fNegate(in, out) - - -/** - * Computes dot product of \a a and \a b quaternions and returns the result. - * - * \param a A quaternion - * \param b B quaternion - */ -#define BH_Quat4fDot(a, b) \ - BH_Vec4fDot(a, b) - - -/** - * Computes length of the \a in quaternion and returns the result. - * - * \param in Input quaternion - */ -#define BH_Quat4fLength(in) \ - BH_Vec4fLength(in) - - -/** - * Computes normal quaternion from the \a in and stores result into \a out. - * - * \param in Input quaternion - * \param out Output quaternion - */ -#define BH_Quat4fNormal(in, out) \ - BH_Vec4fNormal(in, out) - - -/** - * Interpolates between \a a and \a b quaternion by \a t amount and stores - * result into \a out. - * - * \param a A quaternion - * \param b B quaternion - * \param t Amount - * \param out Output quaternion - */ -#define BH_Quat4fLerp(a, b, t, out) \ - BH_Vec4fLerp(a, b, t, out) - - -/** - * Stores identity quaternion into \a out. - * - * \param out Output quaternion. - */ -void BH_Quat4fIdentity(float *out); - - -/** - * Conjugates the \a in quaternion and stores result into \a out. - * - * \param in Input quaternion - * \param out Output quaternion - */ -void BH_Quat4fConjugate(const float *in, - float *out); - - -/** - * Computes the inverse of the \a in quaternion and stores result into \a out. - * - * \param in Input quaternion - * \param out Output quaternion - */ -void BH_Quat4fInverse(const float *in, - float *out); - - -/** - * Multiplies the \a a and \a b quaternions and stores result into \a out. - * - * \param a A quaternion - * \param b B quaternion - * \param out Output quaternion - */ -void BH_Quat4fMul(const float *a, - const float *b, - float *out); - - -/** - * Spherically interpolates between \a a and \a b quaternions by \a t amount and - * stores result into \a out. - * - * \param a A quaternion - * \param b B quaternion - * \param t Amount - * \param out Output quaternion - */ -void BH_Quat4fSlerp(const float *a, - const float *b, - float t, - float *out); - - -/** - * Computes the quaternion that represents \a roll, \a pitch, \a yaw (euler - * angles) and stores result into \a out. - * - * Order of the rotation is ZYX (yaw, pitch, roll) - * - * \param roll Roll - * \param pitch Pitch - * \param yaw Yaw - * \param out Output quaternion - */ -void BH_Quat4fFromEuler(float roll, - float pitch, - float yaw, - float *out); - - -/** - * Computes quaternion that represents rotation by angle \a angle around - * axis \a axis and stores result into \a out. - * - * \param axis Axis 3D vector - * \param angle Angle - * \param out Output quaternion - */ -void BH_Quat4fFromAxis(const float *axis, - float angle, - float *out); - - -/** - * Computes euler angles from quaternion \a in and stores result into \a roll, - * \a pitch, \a yaw. - * - * Order of the rotation is ZYX (yaw, pitch, roll) - * - * \param in Input quaternion - * \param roll Output roll - * \param pitch Output pitch - * \param yaw Output yaw - */ -void BH_Quat4fToEuler(const float *in, - float *roll, - float *pitch, - float *yaw); - - -/** - * Computes rotation around axis from quaternion \a in and stores result into - * \a axis and \a angle. - * - * \param in Input quaternion - * \param axis Output axis 3D vector - * \param angle Output angle - */ -void BH_Quat4fToAxis(const float *in, - float *axis, - float *angle); - - -/** - * Computes 4x4 rotation matrix from quaternion \a in and stores result into - * \a out. - * - * \param in Input quaternion - * \param out Output 4x4 matrix - */ -void BH_Quat4fToMat4f(const float *in, - float *out); - - -/** - * Stores identity matrix into \a out. - * - * \param out Output 4x4 matrix. - */ -void BH_Mat4fIdentity(float *out); - - -/** - * Adds \a a and \a b floating point matricies and stores result into \a out. - * - * \param a A 4x4 matrix - * \param b B 4x4 matrix - * \param out Output 4x4 matrix - */ -void BH_Mat4fAdd(const float *a, - const float *b, - float *out); - - -/** - * Subtracts \a a and \a b floating point matricies and stores result into - * \a out. - * - * \param a A 4x4 matrix - * \param b B 4x4 matrix - * \param out Output 4x4 matrix - */ -void BH_Mat4fSub(const float *a, - const float *b, - float *out); - - -/** - * Multiplies \a a and \a b floating point matricies and stores result into - * \a out. - * - * \param a A 4x4 matrix - * \param b B 4x4 matrix - * \param out Output 4x4 matrix - */ -void BH_Mat4fMul(const float *a, - const float *b, - float *out); - - -/** - * Scales \a a matrix by the value \a b and stores result into \a out. - * - * \param a A 4x4 matrix - * \param b B value - * \param out Output 4x4 matrix - */ -void BH_Mat4fScale(const float *a, - float b, - float *out); - - -/** - * Transposes matrix \a in and stores result into \a out. - * - * \param in Input 4x4 matrix - * \param out Output 4x4 matrix - */ -void BH_Mat4fTranspose(const float *in, - float *out); - - -/** - * Computes \a in matrix trace and returns the result. - * - * \param in Input 4x4 matrix - */ -float BH_Mat4fTrace(const float *in); - - -/** - * Computes \a in matrix determinant and returns the result. - * - * \param in Input 4x4 matrix - */ -float BH_Mat4fDet(const float *in); - - -/** - * Computes inverse of \a in matrix and stores result into \a out. - * - * \param in Input 4x4 matrix - * \param out OUtput 4x4 matrix - * - * \return On success, returns zero. - * \return On failure, returns error code. - */ -int BH_Mat4fInverse(const float *in, - float *out); - - -/** - * Computes scaling matrix from values \a x, \a y, \a z and stores result into - * \a out. - * - * \param x X scale - * \param y Y scale - * \param z Z scale - * \param out Output 4x4 matrix - */ -void BH_Mat4fFromScale(float x, - float y, - float z, - float *out); - - -/** - * Computes translation matrix from values \a x, \a y, \a z and stores result - * into \a out. - * - * \param x X translation - * \param y Y translation - * \param z Z translation - * \param out Output 4x4 matrix - */ -void BH_Mat4fFromTranslation(float x, - float y, - float z, - float *out); - - -/** - * Computes rotation matrix around x axis with angle \a angle and stores - * result \a out. - * - * \param angle Angle - * \param out Output 4x4 matrix - */ -void BH_Mat4fFromRotationX(float angle, - float *out); - - -/** - * Computes rotation matrix around y axis with angle \a angle and stores - * result \a out. - * - * \param angle Angle - * \param out Output 4x4 matrix - */ -void BH_Mat4fFromRotationY(float angle, - float *out); - - -/** - * Computes rotation matrix around z axis with angle \a angle and stores - * result \a out. - * - * \param angle Angle - * \param out Output 4x4 matrix - */ -void BH_Mat4fFromRotationZ(float angle, - float *out); - - -/** - * Computes rotation matrix around axis \a axis with angle \a angle and stores - * result \a out. - * - * \param axis Axis 3D vector - * \param angle Angle - * \param out Output 4x4 matrix - */ -void BH_Mat4fFromAxis(const float *axis, - float angle, - float *out); - - -/** - * Computes the rotation matrix that represents \a roll, \a pitch, \a yaw (euler - * angles) and stores result into \a out. - * - * Order of the rotation is ZYX (yaw, pitch, roll) - * - * \param roll Roll - * \param pitch Pitch - * \param yaw Yaw - * \param out Output 4x4 matrix - */ -void BH_Mat4fFromEuler(float roll, - float pitch, - float yaw, - float *out); - - -/** - * Computes 4x4 rotation matrix from quaternion \a in and stores result into - * \a out. - * - * \param in Input quaternion - * \param out Output 4x4 matrix - */ -void BH_Mat4fFromQuat4f(const float *in, - float *out); - - -/** - * Computes orthographic projection matrix and stores result into \a out. - * - * \param x_min Min x value - * \param x_max Max x value - * \param y_min Min y value - * \param y_max Max y value - * \param z_min Min z value - * \param z_max Max z value - * \param out Output 4x4 matrix - */ -void BH_Mat4fFromOrtho(float xMin, - float xMax, - float yMin, - float yMax, - float zMin, - float zMax, - float *out); - - -/** - * Computes perspective projection matrix and stores result into \a out. - * - * \param fov Field of view - * \param aspect Aspect ratio - * \param z_min Min z value - * \param z_max Max z value - * \param out Output 4x4 matrix - */ -void BH_Mat4fFromFrustum(float fov, - float aspect, - float zMin, - float zMax, - float *out); - - -/** - * Computes camera view matrix and stores result into \a out. - * - * \param pos Position vector - * \param at Target vector - * \param up Up vector - * \param out Output 4x4 matrix - */ -void BH_Mat4fFromLookAt(const float *pos, - const float *at, - const float *up, - float *out); - - -/** - * Multiplies matrix \a a by vector \a b and stores result into \a out. - * - * \param a A 4x4 matrix - * \param b B 4D vector - * \param out Output 4D vector - */ -void BH_Mat4fApplyVec4f(const float *a, - const float *b, - float *out); - - -/** - * Multiplies matrix \a a by vector \a b and stores result into \a out. - * - * \param a A 4x4 matrix - * \param b B 3D vector - * \param out Output 3D vector - */ -void BH_Mat4fApplyVec4f(const float *a, - const float *b, - float *out); - - -/** - * Stores identity matrix into \a out. - * - * \param out Output 3x3 matrix. - */ -void BH_Mat3fIdentity(float *out); - - -/** - * Adds \a a and \a b floating point matricies and stores result into \a out. - * - * \param a A 3x3 matrix - * \param b B 3x3 matrix - * \param out Output 3x3 matrix - */ -void BH_Mat3fAdd(const float *a, - const float *b, - float *out); - - -/** - * Subtracts \a a and \a b floating point matricies and stores result into - * \a out. - * - * \param a A 3x3 matrix - * \param b B 3x3 matrix - * \param out Output 3x3 matrix - */ -void BH_Mat3fSub(const float *a, - const float *b, - float *out); - - -/** - * Multiplies \a a and \a b floating point matricies and stores result into - * \a out. - * - * \param a A 3x3 matrix - * \param b B 3x3 matrix - * \param out Output 3x3 matrix - */ -void BH_Mat3fMul(const float *a, - const float *b, - float *out); - - -/** - * Scales \a a matrix by the value \a b and stores result into \a out. - * - * \param a A 3x3 matrix - * \param b B value - * \param out Output 3x3 matrix - */ -void BH_Mat3fScale(const float *a, - float b, - float *out); - - -/** - * Transposes matrix \a in and stores result into \a out. - * - * \param in Input 3x3 matrix - * \param out Output 3x3 matrix - */ -void BH_Mat3fTranspose(const float *in, - float *out); - - -/** - * Computes \a in matrix trace and returns the result. - * - * \param in Input 3x3 matrix - */ -float BH_Mat3fTrace(const float *in); - - -/** - * Computes \a in matrix determinant and returns the result. - * - * \param in Input 3x3 matrix - */ -float BH_Mat3fDet(const float *in); - - -/** - * Computes inverse of \a in matrix and stores result into \a out. - * - * \param in Input 3x3 matrix - * \param out OUtput 3x3 matrix - * - * \return On success, returns zero. - * \return On failure, returns error code. - */ -int BH_Mat3fInverse(const float *in, - float *out); - - -/** - * Computes scaling matrix from values \a x, \a y and stores result into - * \a out. - * - * \param x X scale - * \param y Y scale - * \param out Output 3x3 matrix - */ -void BH_Mat3fFromScale(float x, - float y, - float *out); - - -/** - * Computes translation matrix from values \a x, \a y and stores result - * into \a out. - * - * \param x X translation - * \param y Y translation - * \param out Output 3x3 matrix - */ -void BH_Mat3fFromTranslation(float x, - float y, - float *out); - - -/** - * Computes rotation matrix around with angle \a angle and stores result \a out. - * - * \param angle Angle - * \param out Output 3x3 matrix - */ -void BH_Mat3fFromRotation(float angle, - float *out); - - -/** - * Multiplies matrix \a a by vector \a b and stores result into \a out. - * - * \param a A 3x3 matrix - * \param b B 3D vector - * \param out Output 3D vector - */ -void BH_Mat3fApplyVec3f(float *a, - float *b, - float *out); - - -/** - * Multiplies matrix \a a by vector \a b and stores result into \a out. - * - * \param a A 3x3 matrix - * \param b B 2D vector - * \param out Output 2D vector - */ -void BH_Mat3fApplyVec2f(float *a, - float *b, - float *out); - - -#endif /* BH_MATH_H */ diff --git a/include/bh/queue.h b/include/bh/queue.h deleted file mode 100755 index f7b8b12..0000000 --- a/include/bh/queue.h +++ /dev/null @@ -1,149 +0,0 @@ -#ifndef BH_QUEUE_H -#define BH_QUEUE_H - - -#include "common.h" - - -typedef struct BH_Queue BH_Queue; - - -/** - * Creates the new queue object. - * - * \return On success, returns the pointer to the new queue object. - * \return On failure, returns a null pointer. - */ -BH_Queue *BH_QueueNew(void); - - -/** - * Frees the \a queue object. - * - * \param queue Pointer to the queue object to be freed - */ -void BH_QueueFree(BH_Queue *queue); - - -/** - * Clears the \a queue object. - * - * \param queue Pointer to the queue object to be cleared - */ -void BH_QueueClear(BH_Queue *queue); - - -/** - * Reserves the space for \a size elements in the \a queue. - * - * This function can both expand and shrink the available space in \a queue. - * - * \param queue Pointer to the queue object to be resized in terms of capacity - * \param size New capacity of the queue - * - * \note Calling this function will invalidate iterators. - * \note Actual hashmap capacity can be bigger then requested. - * - * \return On success, returns zero value. - * \return On failure, returns error code. - */ -int BH_QueueReserve(BH_Queue *queue, - size_t size); - - -/** - * Inserts the \a value into the \a queue. - * - * \param queue Pointer to the queue object - * \param value Value to be inserted - * - * \note Calling this function will invalidate iterators. - * - * \return On success, returns zero value. - * \return On failure, returns error code. - */ -int BH_QueueInsert(BH_Queue *queue, - void *value); - - -/** - * Removes front value from the \a queue. - * - * \param queue Pointer to the queue object - * - * \note Calling this function will invalidate iterators. - */ -void BH_QueueRemove(BH_Queue *queue); - - -/** - * Returns front value from the \a queue. - * - * \param queue Pointer to the queue object - * - * \return On success, returns front value from the queue. - * \return On failure, returns null pointer. - */ -int BH_QueueFront(BH_Queue *queue, - void **value); - - -/** - * Checks if the \a queue is empty. - * - * \param queue Pointer to the queue object - * - * \return If queue is empty, returns non-zero value - * \return If queue is not empty, returns zero value - */ -int BH_QueueEmpty(BH_Queue *queue); - - -/** - * Returns the size of the \a queue. - * - * \param queue Pointer to the queue object - * - * \return Returns the size of the queue. - */ -size_t BH_QueueSize(BH_Queue *queue); - - -/** - * Returns the capacity of the \a queue. - * - * \param queue Pointer to the queue object - * - * \return Returns the capacity of the queue. - */ -size_t BH_QueueCapacity(BH_Queue *queue); - - -/** - * Returns the iterator to the next element in the \a queue. - * - * \param queue Pointer to the queue object - * \param iter Opaque iterator value - * - * \return If the \a iter doesn't point to the last element of the queue, - * returns next iterator value. - * \return If the \a iter point to the last element of the queue, returns - * null pointer. - * \return If the \a iter is the null pointer, returns iterator to the - * first element of the queue. - */ -void *BH_QueueIterNext(BH_Queue *queue, - void *iter); - - -/** - * Returns the value, pointed by the queue iterator \a iter. - * - * \param iter Opaque iterator value - * - * \return Returns value, pointed by iterator. - */ -void *BH_QueueIterValue(void *iter); - - -#endif /* BH_QUEUE_H */ diff --git a/src/Algo.c b/src/Algo.c new file mode 100755 index 0000000..7d0abcd --- /dev/null +++ b/src/Algo.c @@ -0,0 +1,411 @@ +#include +#include + + +void BH_Swap(void *dest, + void *src, + size_t size) +{ + int tmp; + + /* Swap bytes in int-sized chunks */ + while (size >= sizeof(tmp)) + { + memmove(&tmp, dest, sizeof(tmp)); + memmove(dest, src, sizeof(tmp)); + memmove(src, &tmp, sizeof(tmp)); + + dest = (char *)dest + sizeof(tmp); + src = (char *)src + sizeof(tmp); + size -= sizeof(tmp); + } + + /* Swap the remaining size */ + if (size) + { + memmove(&tmp, dest, size); + memmove(dest, src, size); + memmove(src, &tmp, size); + } +} + + +void *BH_Partition(void *pivot, + void *array, + size_t size, + size_t element, + BH_EqualCallback equal) +{ + char *start, *end, *i, *j; + + /* Calculate start, end and item pointers */ + start = (char *)array; + end = start + size * element; + i = start; + j = start + (size - 1) * element; + + /* Iterate over array */ + while (1) + { + /* Find first element from the left that are bigger then pivot */ + while (i < end && equal(i, pivot) < 0) + i += element; + + /* Find first element from the right that are less then pivot*/ + while (j >= start && equal(j, pivot) >= 0) + j -= element; + + /* If item elemetns passed each other - we are done */ + if (i >= j) + break; + + /* Special case when pivot is actually part of the array */ + if (pivot == i) + pivot = j; + else if (pivot == j) + pivot = i; + + /* Swap elements and continue */ + BH_Swap(i, j, element); + i += element; + j -= element; + } + + /* Return pointer to the middle of the partition */ + return j + element; +} + + +#if 0 +static void BH_SortInsert(void *array, + size_t size, + size_t element, + BH_EqualCallback equal) +{ + size_t i, j; + + /* Standard insert sort */ + for (i = 1; i < size; i++) + { + for (j = i; j >= 1; j -= 1) + { + char *lhs, *rhs; + + lhs = (char *)array + j * element; + rhs = (char *)array + (j - 1) * element; + + if (equal(lhs, rhs) < 0) + BH_Swap(lhs, rhs, element); + else + break; + } + } + +} +#endif + + +static void BH_SortShell(void *array, + size_t size, + size_t element, + BH_EqualCallback equal) +{ + static const size_t gaps[10] = {1750, 701, 301, 132, 57, 23, 10, 4, 1, 0}; + const size_t *gap; + size_t i, j; + + /* Shell sort with A102549 sequence */ + for (gap = gaps; *gap; ++gap) + { + for (i = *gap; i < size; i++) + { + for (j = i; j >= *gap; j -= *gap) + { + char *lhs, *rhs; + + lhs = (char *)array + j * element; + rhs = (char *)array + (j - *gap) * element; + + if (equal(lhs, rhs) < 0) + BH_Swap(lhs, rhs, element); + else + break; + } + } + } +} + + +static void BH_SortHeap(void *array, + size_t size, + size_t element, + BH_EqualCallback equal) +{ + size_t i; + + BH_HeapMake(array, size, element, equal); + for (i = size; i > 0; i--) + BH_HeapRemove(array, i, element, equal); +} + + +static void BH_SortIntroR(void *array, + size_t size, + size_t element, + BH_EqualCallback equal, + size_t depth) +{ + /* Introsort (with manual tail call optimization) */ + while (1) + { + char *start, *middle, *end, *pivot; + + if (size < 16) + { + /* There are less then 16 elements left - use Shell/Insert sort */ + BH_SortShell(array, size, element, equal); + return; + } + else if (!depth) + { + /* Max depth reached - use heap sort */ + BH_SortHeap(array, size, element, equal); + return; + } + + /* Calculate start, middle and end pointers */ + start = (char *)array; + middle = start + (size / 2) * element; + end = start + (size - 1) * element; + + /* Select middle element */ + if (equal(start, middle) > 0) + { + if (equal(middle, end) > 0) + pivot = middle; + else if (equal(start, end) > 0) + pivot = end; + else + pivot = start; + } + else + { + if (equal(start, end) > 0) + pivot = start; + else if (equal(middle, end) > 0) + pivot = end; + else + pivot = middle; + } + + /* Partition the array */ + middle = BH_Partition(pivot, array, size, element, equal); + + /* Recursive call into first half */ + BH_SortIntroR(array, (middle - start) / element, element, equal, depth - 1); + + /* Setup array and size for the second half */ + array = middle; + size = size - (middle - start) / element; + depth--; + } +} + + +void BH_Sort(void *array, + size_t size, + size_t element, + BH_EqualCallback equal) +{ + size_t depth, depth_log; + + /* Calculate max depth */ + depth = 0; + depth_log = 1; + while (depth_log < size) + { + depth++; + depth_log <<= 1; + } + + /* Call main sorting function */ + BH_SortIntroR(array, size, element, equal, depth); +} + + +void BH_HeapMake(void *array, + size_t size, + size_t element, + BH_EqualCallback equal) +{ + char *start, *end; + size_t i; + + /* Calculate start and end pointers of the array */ + start = (char *)array; + end = start + size * element; + + /* Bottom up heapify algorithm */ + for (i = size / 2 + 1; i; --i) + { + char *current, *left, *right; + + /* Calculate current and children pointers */ + current = start + (i - 1) * element; + left = start + (current - start) * 2 + element; + right = left + element; + + while (left < end) + { + char *biggest; + + /* Determine biggest child */ + biggest = left; + if (right < end && equal(left, right) < 0) + biggest = right; + + /* Compare biggest child with current */ + if (equal(current, biggest) < 0) + { + /* Swap content and recalculate children pointers */ + BH_Swap(current, biggest, element); + current = biggest; + left = start + (current - start) * 2 + element; + right = left + element; + } + else + break; + } + } +} + + +void BH_HeapRemove(void *array, + size_t size, + size_t element, + BH_EqualCallback equal) +{ + char *start, *end, *current, *left, *right; + + if (size <= 1) + return; + + /* Calculate start, end and children pointers */ + start = (char *)array; + end = start + (size - 1) * element; + current = start; + left = start + (current - start) * 2 + element; + right = left + element; + + /* Swap first and last element */ + BH_Swap(current, end, element); + + /* Iterate until we reach the end */ + while (left < end) + { + char *biggest; + + /* Determine biggest child */ + biggest = left; + if (right < end && equal(left, right) < 0) + biggest = right; + + /* Compare biggest child with current */ + if (equal(current, biggest) < 0) + { + /* Swap content and recalculate children pointers */ + BH_Swap(current, biggest, element); + current = biggest; + left = start + (current - start) * 2 + element; + right = left + element; + } + else + break; + } +} + + +void BH_HeapInsert(void *value, + void *array, + size_t size, + size_t element, + BH_EqualCallback equal) +{ + char *start, *end, *current; + + /* Calculate begin and end pointers */ + start = (char *)array; + end = start + size * element; + current = end; + + /* Copy value into array */ + if (value) + memmove(current, value, element); + + while (current > start) + { + char *parent; + + /* Calculate parent pointer */ + parent = start + (((current - start) / element - 1) / 2) * element; + + /* Compare current and parent */ + if (equal(parent, current) < 0) + { + /* Swap current and parent */ + BH_Swap(parent, current, element); + current = parent; + } + else + break; + } +} + + +void BH_HeapReplace(void *value, + void *array, + size_t size, + size_t element, + BH_EqualCallback equal) +{ + char *start, *end, *current, *left, *right; + + if (size < 1) + return; + + /* Calculate start, end and children pointers */ + start = (char *)array; + end = start + size * element; + current = start; + left = start + (current - start) * 2 + element; + right = left + element; + + /* Copy supplied element to the first (top) position */ + if (value) + memmove(current, value, element); + else + memmove(current, start + size * element, element); + + /* Iterate until we reach the end */ + while (left < end) + { + char *biggest; + + /* Determine biggest child */ + biggest = left; + if (right < end && equal(left, right) < 0) + biggest = right; + + /* Compare biggest child with current */ + if (equal(current, biggest) < 0) + { + /* Swap content and recalculate children pointers */ + BH_Swap(current, biggest, element); + current = biggest; + left = start + (current - start) * 2 + element; + right = left + element; + } + else + break; + } +} diff --git a/src/Hashmap.c b/src/Hashmap.c new file mode 100755 index 0000000..ad8e7bd --- /dev/null +++ b/src/Hashmap.c @@ -0,0 +1,390 @@ +#include +#include +#include + + +typedef struct BH_HashmapNode +{ + void *key; + void *value; +} BH_HashmapNode; + + +struct BH_Hashmap +{ + BH_HashmapNode *data; + size_t *psls; + size_t size; + size_t capacity; + size_t threshold; + BH_EqualCallback equal; + BH_HashCallback hash; + float factor; +}; + + +static void BH_HashmapInit(BH_Hashmap *hashmap, + BH_EqualCallback equal, + BH_HashCallback hash) +{ + memset(hashmap, 0, sizeof(*hashmap)); + hashmap->factor = 0.75f; + hashmap->equal = equal; + hashmap->hash = hash; +} + + +static void BH_HashmapDestroy(BH_Hashmap *hashmap) +{ + if (hashmap->capacity) + { + free(hashmap->data); + free(hashmap->psls); + } +} + + +static int BH_CalcCapacity(size_t size, + float factor, + size_t *capacity, + size_t *threshold) +{ + /* Check if we need any capacity at all */ + if (!size) + { + *capacity = 0; + *threshold = 0; + return BH_OK; + } + + /* Calculate nearest power of 2 capacity */ + *capacity = 16; + *threshold = *capacity * factor; + while (size > *threshold) + { + *capacity *= 2; + *threshold = *capacity * factor; + + /* Catch capacity overflow */ + if (*capacity < 16) + return BH_OOM; + } + + /* Catch malloc overflow */ + if (*capacity >= ((size_t)-1) / sizeof(BH_HashmapNode)) + return BH_OOM; + + return BH_OK; +} + + +static void BH_CopyHashmap(BH_Hashmap *dest, + BH_Hashmap *src) +{ + void *iter; + + /* Iterate and insert data into hashmap */ + iter = BH_HashmapIterNext(src, NULL); + while (iter) + { + void *key, *value; + + key = BH_HashmapIterKey(iter); + value = BH_HashmapIterValue(iter); + BH_HashmapInsert(dest, key, value); + + iter = BH_HashmapIterNext(src, iter); + } +} + + +BH_Hashmap *BH_HashmapNew(BH_EqualCallback equal, + BH_HashCallback hash) +{ + BH_Hashmap *result; + + result = malloc(sizeof(*result)); + if (result) + BH_HashmapInit(result, equal, hash); + + return result; +} + + +void BH_HashmapFree(BH_Hashmap *hashmap) +{ + BH_HashmapDestroy(hashmap); + free(hashmap); +} + + +void BH_HashmapClear(BH_Hashmap *hashmap) +{ + if (hashmap->capacity) + memset(hashmap->psls, 0, hashmap->capacity * sizeof(size_t)); + hashmap->size = 0; +} + + +int BH_HashmapReserve(BH_Hashmap *hashmap, + size_t size) +{ + BH_Hashmap other; + size_t capacity, threshold; + + /* New capacity can't be smaller then current hashmap size */ + if (size < hashmap->size) + size = hashmap->size; + + /* Calculate new capacity */ + if (BH_CalcCapacity(size, hashmap->factor, &capacity, &threshold)) + return BH_OOM; + + /* Prevent same size reallocation */ + if (capacity == hashmap->capacity) + return BH_OK; + + /* Initialize new hashmap */ + BH_HashmapInit(&other, hashmap->equal, hashmap->hash); + other.factor = hashmap->factor; + + if (capacity) + { + /* Allocate new memory for the hashmap */ + other.data = malloc(sizeof(*other.data) * capacity); + other.psls = malloc(sizeof(size_t) * capacity); + other.threshold = threshold; + other.capacity = capacity; + + /* Check for allocations failure */ + if (!other.data || !other.psls) + { + if (other.data) + free(other.data); + if (other.psls) + free(other.psls); + return BH_OOM; + } + + /* Reset probe sequence lengths */ + memset(other.psls, 0, sizeof(size_t) * other.capacity); + + /* Copy data from old hashmap to the new hashmap */ + BH_CopyHashmap(&other, hashmap); + } + + /* Swap hashmaps */ + BH_HashmapDestroy(hashmap); + *hashmap = other; + return BH_OK; +} + + +int BH_HashmapInsert(BH_Hashmap *hashmap, + void *key, + void *value) +{ + size_t bucket, psl, tmp_psl; + BH_HashmapNode item, tmp; + + /* Try to stay below hashmap threshold */ + if (hashmap->size + 1 > hashmap->threshold) + if (BH_HashmapReserve(hashmap, hashmap->size + 1)) + if (hashmap->size >= hashmap->capacity) + return BH_OOM; + + /* Prepare inserted data and set PSL to 1 */ + item.key = key; + item.value = value; + psl = 1; + + /* Calculate prefered bucket index */ + bucket = hashmap->hash(key) & (hashmap->capacity - 1); + + /* Find empty bucket */ + while (hashmap->psls[bucket]) + { + /* Current bucket is richer then us - swap elements */ + if (psl > hashmap->psls[bucket]) + { + tmp = hashmap->data[bucket]; + tmp_psl = hashmap->psls[bucket]; + hashmap->data[bucket] = item; + hashmap->psls[bucket] = psl; + item = tmp; + psl = tmp_psl; + } + + bucket = (bucket + 1) & (hashmap->capacity - 1); + psl++; + } + + /* Found empty bucket - place item here */ + hashmap->data[bucket] = item; + hashmap->psls[bucket] = psl; + hashmap->size++; + + return BH_OK; +} + + +void BH_HashmapRemove(BH_Hashmap *hashmap, + void *key) +{ + void *iter; + + iter = BH_HashmapIterAt(hashmap, key); + if (iter) + BH_HashmapIterRemove(hashmap, iter); +} + + +int BH_HashmapAt(BH_Hashmap *hashmap, + void *key, + void **value) +{ + void *iter; + iter = BH_HashmapIterAt(hashmap, key); + + if (!iter) + return BH_NOTFOUND; + + if (value) + *value = BH_HashmapIterValue(iter); + + return BH_OK; +} + + +int BH_HashmapEmpty(BH_Hashmap *hashmap) +{ + return !hashmap->size; +} + + +size_t BH_HashmapSize(BH_Hashmap *hashmap) +{ + return hashmap->size; +} + + +size_t BH_HashmapCapacity(BH_Hashmap *hashmap) +{ + return hashmap->capacity; +} + + +float BH_HashmapFactor(BH_Hashmap *hashmap) +{ + return hashmap->factor; +} + + +void BH_HashmapSetFactor(BH_Hashmap *hashmap, + float factor) +{ + /* Limit the factor value to [0.15, 1.0] */ + factor = (factor > 1.0f) ? (1.0f) : (factor); + factor = (factor < 0.15f) ? (0.15f) : (factor); + + /* Calculate new threshold value */ + hashmap->factor = factor; + hashmap->threshold = hashmap->capacity * factor; +} + + +void *BH_HashmapIterAt(BH_Hashmap *hashmap, + void *key) +{ + size_t bucket, psl; + + /* Nothing can be in empty map */ + if (!hashmap->size) + return NULL; + + /* Calculate prefered bucket index and set PSL to 1 */ + bucket = hashmap->hash(key) & (hashmap->capacity - 1); + psl = 1; + + /* Iterate hashmap until we find element or find richer bucket */ + while (hashmap->psls[bucket] >= psl && hashmap->equal(hashmap->data[bucket].key, key)) + { + bucket = (bucket + 1) & (hashmap->capacity - 1); + psl++; + } + + /* If bucket is poorer or equal to us - we found our element */ + if (hashmap->psls[bucket] >= psl) + return hashmap->data + bucket; + + return NULL; +} + + +void *BH_HashmapIterNext(BH_Hashmap *hashmap, + void *iter) +{ + BH_HashmapNode *item; + + item = (BH_HashmapNode *)iter; + while (1) + { + /* Advance or set iterator to the first element */ + if (item) + item++; + else + item = hashmap->data; + + /* Check iterator for validity */ + if (item >= hashmap->data + hashmap->capacity) + return NULL; + + /* Check iterator's item PSL */ + if (hashmap->psls[item - hashmap->data]) + return item; + } +} + + +void BH_HashmapIterRemove(BH_Hashmap *hashmap, + void *iter) +{ + size_t bucket, next_bucket; + + /* Check if hashmap is empty or we are given NULL iterator */ + if (!iter || !hashmap->size) + return; + + /* Adjust hashmap size, calculate current and next bucket index */ + hashmap->size--; + bucket = (BH_HashmapNode *)iter - hashmap->data; + next_bucket = (bucket + 1) & (hashmap->capacity - 1); + + /* Shift all elements toward their preffered place */ + while (hashmap->psls[next_bucket] > 1) + { + /* Copy item and adjust PSL */ + hashmap->data[bucket] = hashmap->data[next_bucket]; + hashmap->psls[bucket] = hashmap->psls[next_bucket] - 1; + + /* Calculate next bucket index */ + bucket = next_bucket; + next_bucket = (bucket + 1) & (hashmap->capacity - 1); + } + + /* Reset bucket's PSL (mark empty) */ + hashmap->psls[bucket] = 0; +} + + +void *BH_HashmapIterKey(void *iter) +{ + return ((BH_HashmapNode *)iter)->key; +} + + +void *BH_HashmapIterValue(void *iter) +{ + return ((BH_HashmapNode *)iter)->value; +} + diff --git a/src/IO.c b/src/IO.c new file mode 100644 index 0000000..d3c5673 --- /dev/null +++ b/src/IO.c @@ -0,0 +1,226 @@ +#include +#include + + +#define BUFFER_SIZE (sizeof(char *)) + +struct BH_IO +{ + BH_IOCallback cb; +}; + + +BH_IO *BH_IONew(BH_IOCallback cb, + void *data) +{ + size_t requested; + BH_IO *io; + + /* Get information about IO device size */ + if (cb(NULL, BH_IO_INFO_CB, &requested, NULL)) + return NULL; + + /* Allocate space for the IO device */ + io = malloc(sizeof(*io) + requested); + if (!io) + return NULL; + + /* Initialize IO device */ + io->cb = cb; + if (cb(io + 1, BH_IO_INIT_CB, data, NULL)) + { + free(io); + return NULL; + } + + return io; +} + + +void BH_IOFree(BH_IO *io) +{ + /* Prevent working with NULL io */ + if (!io) + return; + + /* Call the IO device destruction handler */ + io->cb(io + 1, BH_IO_DESTROY_CB, NULL, NULL); + + /* Deallocate object */ + free(io); +} + + +const char *BH_IOClassname(BH_IO *io) +{ + const char *name; + + if (!io) + goto error; + + if (io->cb(io + 1, BH_IO_INFO_CB, NULL, &name) != BH_OK) + goto error; + + return name; + +error: + return NULL; +} + + +int BH_IOOpen(BH_IO *io, + int mode) +{ + /* Prevent working with NULL io */ + if (!io) + return BH_ERROR; + + /* Call the IO device open handler with specified mode */ + return io->cb(io + 1, BH_IO_OPEN_CB, &mode, NULL); +} + + +int BH_IOClose(BH_IO *io) +{ + /* Prevent working with NULL io */ + if (!io) + return BH_ERROR; + + /* Call the IO device close handler */ + return io->cb(io + 1, BH_IO_CLOSE_CB, NULL, NULL); +} + + +int BH_IORead(BH_IO *io, + char *buffer, + size_t size, + size_t *actual) +{ + int code; + + /* Prevent working with NULL io */ + if (!io) + return BH_ERROR; + + /* Call the IO device read handler */ + code = io->cb(io + 1, BH_IO_READ_CB, buffer, &size); + + /* If caller wants to know actual read size - report it back */ + if (actual) + *actual = size; + + return code; +} + + +int BH_IOWrite(BH_IO *io, + const char *buffer, + size_t size, + size_t *actual) +{ + int code; + + /* Prevent working with NULL io */ + if (!io) + return BH_ERROR; + + /* Call the IO device write handler */ + code = io->cb(io + 1, BH_IO_WRITE_CB, (void *)buffer, &size); + + /* If caller wants to know actual written size - report it back */ + if (actual) + *actual = size; + + return code; +} + +int BH_IOPeek(BH_IO *io, + char *buffer, + size_t size, + size_t *actual) +{ + int code; + + /* Prevent working with NULL io */ + if (!io) + return BH_ERROR; + + /* Call the IO device peek handler */ + code = io->cb(io + 1, BH_IO_PEEK_CB, (void *)buffer, &size); + + /* If caller wants to know actual written size - report it back */ + if (actual) + *actual = size; + + return code; +} + + +int BH_IOTell(BH_IO *io, + int64_t *position) +{ + /* Prevent working with NULL io */ + if (!io) + return BH_ERROR; + + /* Call the IO device tell handler */ + return io->cb(io + 1, BH_IO_TELL_CB, position, NULL); +} + + +int BH_IOSeek(BH_IO *io, + int64_t position, + int direction) +{ + /* Prevent working with NULL io */ + if (!io) + return BH_ERROR; + + /* Call the IO device seek handler */ + return io->cb(io + 1, BH_IO_SEEK_CB, &position, &direction); +} + + +int BH_IOFlush(BH_IO *io) +{ + /* Prevent working with NULL io */ + if (!io) + return BH_ERROR; + + /* Call the IO device flush handler */ + return io->cb(io + 1, BH_IO_FLUSH_CB, NULL, NULL); +} + + +int BH_IOSize(BH_IO *io, + int64_t *size) +{ + /* Prevent working with NULL io */ + if (!io) + return BH_ERROR; + + /* Call the IO device size handler */ + return io->cb(io + 1, BH_IO_SIZE_CB, size, NULL); +} + + +int BH_IOFlags(BH_IO *io) +{ + /* Prevent working with NULL io */ + if (!io) + return BH_IO_FLAG_ERROR; + + /* Call the IO device flags handler */ + return io->cb(io + 1, BH_IO_FLAGS_CB, NULL, NULL); +} + + +int BH_IOClear(BH_IO *io) +{ + /* Prevent working with NULL io */ + if (!io) + return BH_OK; + + /* Call the IO device clear error handler */ + return io->cb(io + 1, BH_IO_CLEAR_CB, NULL, NULL); +} diff --git a/src/Math.c b/src/Math.c new file mode 100644 index 0000000..58ebcd3 --- /dev/null +++ b/src/Math.c @@ -0,0 +1,1449 @@ +#include +#include +#include + + +void BH_Vec4fAdd(const float *a, + const float *b, + float *out) +{ + out[0] = a[0] + b[0]; + out[1] = a[1] + b[1]; + out[2] = a[2] + b[2]; + out[3] = a[3] + b[3]; +} + + +void BH_Vec4fSub(const float *a, + const float *b, + float *out) +{ + out[0] = a[0] - b[0]; + out[1] = a[1] - b[1]; + out[2] = a[2] - b[2]; + out[3] = a[3] - b[3]; +} + + +void BH_Vec4fMul(const float *a, + const float *b, + float *out) +{ + out[0] = a[0] * b[0]; + out[1] = a[1] * b[1]; + out[2] = a[2] * b[2]; + out[3] = a[3] * b[3]; +} + + +void BH_Vec4fScale(const float *a, + const float b, + float *out) +{ + out[0] = a[0] * b; + out[1] = a[1] * b; + out[2] = a[2] * b; + out[3] = a[3] * b; +} + + +void BH_Vec4fMulAdd(const float *a, + const float *b, + const float *c, + float *out) +{ + out[0] = a[0] * b[0] + c[0]; + out[1] = a[1] * b[1] + c[1]; + out[2] = a[2] * b[2] + c[2]; + out[3] = a[3] * b[3] + c[3]; +} + + +void BH_Vec4fNegate(const float *in, + float *out) +{ + out[0] = -in[0]; + out[1] = -in[1]; + out[2] = -in[2]; + out[3] = -in[3]; +} + + +float BH_Vec4fDot(const float *a, + const float *b) +{ + return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]; +} + + +float BH_Vec4fLength(const float *in) +{ + return sqrt(BH_Vec4fDot(in, in)); +} + + +void BH_Vec4fNormal(const float *in, + float *out) +{ + BH_Vec4fScale(in, 1.0f / BH_Vec4fLength(in), out); +} + + +void BH_Vec4fMin(const float *a, + const float *b, + float *out) +{ + if (a[0] < b[0]) out[0] = a[0]; else out[0] = b[0]; + if (a[1] < b[1]) out[1] = a[1]; else out[1] = b[1]; + if (a[2] < b[2]) out[2] = a[2]; else out[2] = b[2]; + if (a[3] < b[3]) out[3] = a[3]; else out[3] = b[3]; +} + + +void BH_Vec4fMax(const float *a, + const float *b, + float *out) +{ + if (a[0] > b[0]) out[0] = a[0]; else out[0] = b[0]; + if (a[1] > b[1]) out[1] = a[1]; else out[1] = b[1]; + if (a[2] > b[2]) out[2] = a[2]; else out[2] = b[2]; + if (a[3] > b[3]) out[3] = a[3]; else out[3] = b[3]; +} + + +void BH_Vec4fLerp(const float *a, + const float *b, + float t, + float *out) +{ + float tmp[4]; + + BH_Vec4fSub(b, a, tmp); + BH_Vec4fScale(tmp, t, tmp); + BH_Vec4fAdd(a, tmp, out); +} + + +void BH_Vec3fAdd(const float *a, + const float *b, + float *out) +{ + out[0] = a[0] + b[0]; + out[1] = a[1] + b[1]; + out[2] = a[2] + b[2]; +} + + +void BH_Vec3fSub(const float *a, + const float *b, + float *out) +{ + out[0] = a[0] - b[0]; + out[1] = a[1] - b[1]; + out[2] = a[2] - b[2]; +} + + +void BH_Vec3fMul(const float *a, + const float *b, + float *out) +{ + out[0] = a[0] * b[0]; + out[1] = a[1] * b[1]; + out[2] = a[2] * b[2]; +} + + +void BH_Vec3fScale(const float *a, + const float b, + float *out) +{ + out[0] = a[0] * b; + out[1] = a[1] * b; + out[2] = a[2] * b; +} + + +void BH_Vec3fMulAdd(const float *a, + const float *b, + const float *c, + float *out) +{ + out[0] = a[0] * b[0] + c[0]; + out[1] = a[1] * b[1] + c[1]; + out[2] = a[2] * b[2] + c[2]; +} + + +void BH_Vec3fNegate(const float *in, + float *out) +{ + out[0] = -in[0]; + out[1] = -in[1]; + out[2] = -in[2]; +} + + +float BH_Vec3fDot(const float *a, + const float *b) +{ + return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; +} + + +void BH_Vec3fCross(const float *a, + const float *b, + float *out) +{ + float tmp[3]; + + tmp[0] = a[1] * b[2] - a[2] * b[1]; + tmp[1] = a[2] * b[0] - a[0] * b[2]; + tmp[2] = a[0] * b[1] - a[1] * b[0]; + memcpy(out, tmp, sizeof(tmp)); +} + + +float BH_Vec3fLength(const float *in) +{ + return sqrt(BH_Vec3fDot(in, in)); +} + + +void BH_Vec3fNormal(const float *in, + float *out) +{ + BH_Vec3fScale(in, 1.0f / BH_Vec3fLength(in), out); +} + + +void BH_Vec3fMin(const float *a, + const float *b, + float *out) +{ + if (a[0] < b[0]) out[0] = a[0]; else out[0] = b[0]; + if (a[1] < b[1]) out[1] = a[1]; else out[1] = b[1]; + if (a[2] < b[2]) out[2] = a[2]; else out[2] = b[2]; +} + + +void BH_Vec3fMax(const float *a, + const float *b, + float *out) +{ + if (a[0] > b[0]) out[0] = a[0]; else out[0] = b[0]; + if (a[1] > b[1]) out[1] = a[1]; else out[1] = b[1]; + if (a[2] > b[2]) out[2] = a[2]; else out[2] = b[2]; +} + + +void BH_Vec3fLerp(const float *a, + const float *b, + float t, + float *out) +{ + float tmp[3]; + + BH_Vec3fSub(b, a, tmp); + BH_Vec3fScale(tmp, t, tmp); + BH_Vec3fAdd(a, tmp, out); +} + + +void BH_Vec2fAdd(const float *a, + const float *b, + float *out) +{ + out[0] = a[0] + b[0]; + out[1] = a[1] + b[1]; +} + + +void BH_Vec2fSub(const float *a, + const float *b, + float *out) +{ + out[0] = a[0] - b[0]; + out[1] = a[1] - b[1]; +} + + +void BH_Vec2fMul(const float *a, + const float *b, + float *out) +{ + out[0] = a[0] * b[0]; + out[1] = a[1] * b[1]; +} + + +void BH_Vec2fScale(const float *a, + const float b, + float *out) +{ + out[0] = a[0] * b; + out[1] = a[1] * b; +} + + +void BH_Vec2fMulAdd(const float *a, + const float *b, + const float *c, + float *out) +{ + out[0] = a[0] * b[0] + c[0]; + out[1] = a[1] * b[1] + c[1]; +} + + +void BH_Vec2fNegate(const float *in, + float *out) +{ + out[0] = -in[0]; + out[1] = -in[1]; +} + + +float BH_Vec2fDot(const float *a, + const float *b) +{ + return a[0] * b[0] + a[1] * b[1]; +} + + +float BH_Vec2fCross(const float *a, + const float *b) +{ + return a[0] * b[1] - a[1] * b[0]; +} + + +float BH_Vec2fLength(const float *in) +{ + return sqrt(BH_Vec2fDot(in, in)); +} + + +void BH_Vec2fNormal(const float *in, + float *out) +{ + BH_Vec2fScale(in, 1.0f / BH_Vec2fLength(in), out); +} + + +void BH_Vec2fMin(const float *a, + const float *b, + float *out) +{ + if (a[0] < b[0]) out[0] = a[0]; else out[0] = b[0]; + if (a[1] < b[1]) out[1] = a[1]; else out[1] = b[1]; +} + + +void BH_Vec2fMax(const float *a, + const float *b, + float *out) +{ + if (a[0] > b[0]) out[0] = a[0]; else out[0] = b[0]; + if (a[1] > b[1]) out[1] = a[1]; else out[1] = b[1]; +} + + +void BH_Vec2fLerp(const float *a, + const float *b, + float t, + float *out) +{ + float tmp[2]; + + BH_Vec2fSub(b, a, tmp); + BH_Vec2fScale(tmp, t, tmp); + BH_Vec2fAdd(a, tmp, out); +} + + +void BH_Vec4iAdd(const int *a, + const int *b, + int *out) +{ + out[0] = a[0] + b[0]; + out[1] = a[1] + b[1]; + out[2] = a[2] + b[2]; + out[3] = a[3] + b[3]; +} + + +void BH_Vec4iSub(const int *a, + const int *b, + int *out) +{ + out[0] = a[0] - b[0]; + out[1] = a[1] - b[1]; + out[2] = a[2] - b[2]; + out[3] = a[3] - b[3]; +} + + +void BH_Vec4iMul(const int *a, + const int *b, + int *out) +{ + out[0] = a[0] * b[0]; + out[1] = a[1] * b[1]; + out[2] = a[2] * b[2]; + out[3] = a[3] * b[3]; +} + + +void BH_Vec4iScale(const int *a, + int b, + int *out) +{ + out[0] = a[0] * b; + out[1] = a[1] * b; + out[2] = a[2] * b; + out[3] = a[3] * b; +} + + +void BH_Vec4iMulAdd(const int *a, + const int *b, + const int *c, + int *out) +{ + out[0] = a[0] * b[0] + c[0]; + out[1] = a[1] * b[1] + c[1]; + out[2] = a[2] * b[2] + c[2]; + out[3] = a[3] * b[3] + c[3]; +} + + +void BH_Vec4iNegate(const int *in, + int *out) +{ + out[0] = -in[0]; + out[1] = -in[1]; + out[2] = -in[2]; + out[3] = -in[3]; +} + + +void BH_Vec4iMin(const int *a, + const int *b, + int *out) +{ + if (a[0] < b[0]) out[0] = a[0]; else out[0] = b[0]; + if (a[1] < b[1]) out[1] = a[1]; else out[1] = b[1]; + if (a[2] < b[2]) out[2] = a[2]; else out[2] = b[2]; + if (a[3] < b[3]) out[3] = a[3]; else out[3] = b[3]; +} + + +void BH_Vec4iMax(const int *a, + const int *b, + int *out) +{ + if (a[0] > b[0]) out[0] = a[0]; else out[0] = b[0]; + if (a[1] > b[1]) out[1] = a[1]; else out[1] = b[1]; + if (a[2] > b[2]) out[2] = a[2]; else out[2] = b[2]; + if (a[3] > b[3]) out[3] = a[3]; else out[3] = b[3]; +} + + +void BH_Vec3iAdd(const int *a, + const int *b, + int *out) +{ + out[0] = a[0] + b[0]; + out[1] = a[1] + b[1]; + out[2] = a[2] + b[2]; +} + + +void BH_Vec3iSub(const int *a, + const int *b, + int *out) +{ + out[0] = a[0] - b[0]; + out[1] = a[1] - b[1]; + out[2] = a[2] - b[2]; +} + + +void BH_Vec3iMul(const int *a, + const int *b, + int *out) +{ + out[0] = a[0] * b[0]; + out[1] = a[1] * b[1]; + out[2] = a[2] * b[2]; +} + + +void BH_Vec3iScale(const int *a, + int b, + int *out) +{ + out[0] = a[0] * b; + out[1] = a[1] * b; + out[2] = a[2] * b; +} + + +void BH_Vec3iMulAdd(const int *a, + const int *b, + const int *c, + int *out) +{ + out[0] = a[0] * b[0] + c[0]; + out[1] = a[1] * b[1] + c[1]; + out[2] = a[2] * b[2] + c[2]; +} + + +void BH_Vec3iNegate(const int *in, + int *out) +{ + out[0] = -in[0]; + out[1] = -in[1]; + out[2] = -in[2]; +} + + +void BH_Vec3iMin(const int *a, + const int *b, + int *out) +{ + if (a[0] < b[0]) out[0] = a[0]; else out[0] = b[0]; + if (a[1] < b[1]) out[1] = a[1]; else out[1] = b[1]; + if (a[2] < b[2]) out[2] = a[2]; else out[2] = b[2]; +} + + +void BH_Vec3iMax(const int *a, + const int *b, + int *out) +{ + if (a[0] > b[0]) out[0] = a[0]; else out[0] = b[0]; + if (a[1] > b[1]) out[1] = a[1]; else out[1] = b[1]; + if (a[2] > b[2]) out[2] = a[2]; else out[2] = b[2]; +} + + +void BH_Vec2iAdd(const int *a, + const int *b, + int *out) +{ + out[0] = a[0] + b[0]; + out[1] = a[1] + b[1]; +} + + +void BH_Vec2iSub(const int *a, + const int *b, + int *out) +{ + out[0] = a[0] - b[0]; + out[1] = a[1] - b[1]; +} + + +void BH_Vec2iMul(const int *a, + const int *b, + int *out) +{ + out[0] = a[0] * b[0]; + out[1] = a[1] * b[1]; +} + + +void BH_Vec2iScale(const int *a, + int b, + int *out) +{ + out[0] = a[0] * b; + out[1] = a[1] * b; +} + + +void BH_Vec2iMulAdd(const int *a, + const int *b, + const int *c, + int *out) +{ + out[0] = a[0] * b[0] + c[0]; + out[1] = a[1] * b[1] + c[1]; +} + + +void BH_Vec2iNegate(const int *in, + int *out) +{ + out[0] = -in[0]; + out[1] = -in[1]; +} + + +void BH_Vec2iMin(const int *a, + const int *b, + int *out) +{ + if (a[0] < b[0]) out[0] = a[0]; else out[0] = b[0]; + if (a[1] < b[1]) out[1] = a[1]; else out[1] = b[1]; +} + + +void BH_Vec2iMax(const int *a, + const int *b, + int *out) +{ + if (a[0] > b[0]) out[0] = a[0]; else out[0] = b[0]; + if (a[1] > b[1]) out[1] = a[1]; else out[1] = b[1]; +} + + +void BH_Quat4fIdentity(float *out) +{ + static const float ident[4] = {0.0f, 0.0f, 0.0f, 1.0f}; + memcpy(out, ident, sizeof(ident)); +} + + +void BH_Quat4fConjugate(const float *in, + float *out) +{ + out[0] = -in[0]; + out[1] = -in[1]; + out[2] = -in[2]; + out[3] = in[3]; +} + + +void BH_Quat4fInverse(const float *in, + float *out) +{ + float dot; + + dot = BH_Vec4fDot(in, in); + BH_Quat4fConjugate(in, out); + BH_Quat4fScale(out, 1.0f / dot, out); +} + + +void BH_Quat4fMul(const float *a, + const float *b, + float *out) +{ + float tmp1[4], tmp2[4], tmp3[4]; + float w; + + w = a[3] * b[3] - BH_Vec3fDot(a, b); + BH_Vec4fScale(a, b[3], tmp1); + BH_Vec4fScale(b, a[3], tmp2); + BH_Vec3fCross(a, b, tmp3); + BH_Vec4fAdd(tmp1, tmp2, out); + BH_Vec4fAdd(tmp3, out, out); + out[3] = w; +} + + +void BH_Quat4fSlerp(const float *a, + const float *b, + float t, + float *out) +{ + float angle, denom; + float from[4], to[4]; + + angle = acos(BH_Vec4fDot(a, b)); + if (angle == 0.0f) + { + BH_Vec4fLerp(a, b, t, out); + return; + } + + denom = 1.0f / sin(angle); + BH_Vec4fScale(a, sin((1 - t) * angle) * denom, from); + BH_Vec4fScale(b, sin(t * angle) * denom, to); + BH_Vec4fAdd(from, to, out); +} + + +void BH_Quat4fFromEuler(float roll, + float pitch, + float yaw, + float *out) +{ + float cr, cp, cy, sr, sp, sy; + + cr = cos(roll / 2.0f); + cp = cos(pitch / 2.0f); + cy = cos(yaw / 2.0f); + sr = sin(roll / 2.0f); + sp = sin(pitch / 2.0f); + sy = sin(yaw / 2.0f); + + out[0] = sr * cp * cy - cr * sp * sy; + out[1] = cr * sp * cy + sr * cp * sy; + out[2] = cr * cp * sy - sr * sp * cy; + out[3] = cr * cp * cy + sr * sp * sy; +} + + +void BH_Quat4fFromAxis(const float *axis, + float angle, + float *out) +{ + float c, s; + + c = cos(angle / 2.0f); + s = sin(angle / 2.0f); + + out[0] = axis[0] * s; + out[1] = axis[1] * s; + out[2] = axis[2] * s; + out[3] = c; +} + + +void BH_Quat4fToEuler(const float *in, + float *roll, + float *pitch, + float *yaw) +{ + float ww, xw, yw, zw, xx, xy, xz, yy, yz, zz, angle; + + xx = in[0] * in[0]; + xy = in[0] * in[1]; + xz = in[0] * in[2]; + xw = in[0] * in[3]; + yy = in[1] * in[1]; + yz = in[1] * in[2]; + yw = in[1] * in[3]; + zz = in[2] * in[2]; + zw = in[2] * in[3]; + ww = in[3] * in[3]; + + angle = 2.0f * (yw - xz); + if (angle > 1.0f) + angle = 1.0f; + if (angle < -1.0f) + angle = -1.0f; + + *pitch = asin(angle); + + if (*pitch == (M_PI / 2.0f)) + { + *roll = 0.0f; + *yaw = -2.0f * atan2(in[0], in[3]); + } + else if (*pitch == (M_PI / -2.0f)) + { + *roll = 0.0f; + *yaw = 2.0f * atan2(in[0], in[3]); + } + else + { + *roll = atan2(2.0f * (xw + yz), ww - xx - yy + zz); + *yaw = atan2(2.0f * (zw + xy), ww + xx - yy - zz); + } +} + + +void BH_Quat4fToAxis(const float *in, + float *axis, + float *angle) +{ + *angle = 2.0f * acos(in[3]); + + if (*angle == 0.0f) + { + axis[0] = 1.0f; + axis[1] = 0.0f; + axis[2] = 0.0f; + } + else + { + float tmp; + + tmp = sqrt(1.0f - in[3] * in[3]); + axis[0] = in[0] / tmp; + axis[1] = in[1] / tmp; + axis[2] = in[2] / tmp; + } +} + + +void BH_Quat4fToMat4f(const float *in, + float *out) +{ + float xx, xy, xz, xw, yy, yz, yw, zz, zw; + + xx = in[0] * in[0]; + xy = in[0] * in[1]; + xz = in[0] * in[2]; + xw = in[0] * in[3]; + yy = in[1] * in[1]; + yz = in[1] * in[2]; + yw = in[1] * in[3]; + zz = in[2] * in[2]; + zw = in[2] * in[3]; + + BH_Mat4fIdentity(out); + out[0] = 1.0f - 2.0f * (yy + zz); + out[1] = 2.0f * (xy + zw); + out[2] = 2.0f * (xz - yw); + out[4] = 2.0f * (xy - zw); + out[5] = 1.0f - 2.0f * (xx + zz); + out[6] = 2.0f * (yz + xw); + out[8] = 2.0f * (xz + yw); + out[9] = 2.0f * (yz - xw); + out[10] = 1.0f - 2.0f * (xx + yy); +} + + +void BH_Mat4fIdentity(float *out) +{ + const float ident[16] = + { + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + }; + + memcpy(out, ident, sizeof(ident)); +} + + +void BH_Mat4fAdd(const float *a, + const float *b, + float *out) +{ + BH_Vec4fAdd(&a[0], &b[0], &out[0]); + BH_Vec4fAdd(&a[4], &b[4], &out[4]); + BH_Vec4fAdd(&a[8], &b[8], &out[8]); + BH_Vec4fAdd(&a[12], &b[12], &out[12]); +} + + +void BH_Mat4fSub(const float *a, + const float *b, + float *out) +{ + BH_Vec4fSub(&a[0], &b[0], &out[0]); + BH_Vec4fSub(&a[4], &b[4], &out[4]); + BH_Vec4fSub(&a[8], &b[8], &out[8]); + BH_Vec4fSub(&a[12], &b[12], &out[12]); +} + + +void BH_Mat4fMul(const float *a, + const float *b, + float *out) +{ + float tmp[16], row[4]; + + row[0] = row[1] = row[2] = row[3] = b[0]; BH_Vec4fMul(&a[0], row, &tmp[0]); + row[0] = row[1] = row[2] = row[3] = b[1]; BH_Vec4fMulAdd(&a[4], row, &tmp[0], &tmp[0]); + row[0] = row[1] = row[2] = row[3] = b[2]; BH_Vec4fMulAdd(&a[8], row, &tmp[0], &tmp[0]); + row[0] = row[1] = row[2] = row[3] = b[3]; BH_Vec4fMulAdd(&a[12], row, &tmp[0], &tmp[0]); + + row[0] = row[1] = row[2] = row[3] = b[4]; BH_Vec4fMul(&a[0], row, &tmp[4]); + row[0] = row[1] = row[2] = row[3] = b[5]; BH_Vec4fMulAdd(&a[4], row, &tmp[4], &tmp[4]); + row[0] = row[1] = row[2] = row[3] = b[6]; BH_Vec4fMulAdd(&a[8], row, &tmp[4], &tmp[4]); + row[0] = row[1] = row[2] = row[3] = b[7]; BH_Vec4fMulAdd(&a[12], row, &tmp[4], &tmp[4]); + + row[0] = row[1] = row[2] = row[3] = b[8]; BH_Vec4fMul(&a[0], row, &tmp[8]); + row[0] = row[1] = row[2] = row[3] = b[9]; BH_Vec4fMulAdd(&a[4], row, &tmp[8], &tmp[8]); + row[0] = row[1] = row[2] = row[3] = b[10]; BH_Vec4fMulAdd(&a[8], row, &tmp[8], &tmp[8]); + row[0] = row[1] = row[2] = row[3] = b[11]; BH_Vec4fMulAdd(&a[12], row, &tmp[8], &tmp[8]); + + row[0] = row[1] = row[2] = row[3] = b[12]; BH_Vec4fMul(&a[0], row, &tmp[12]); + row[0] = row[1] = row[2] = row[3] = b[13]; BH_Vec4fMulAdd(&a[4], row, &tmp[12], &tmp[12]); + row[0] = row[1] = row[2] = row[3] = b[14]; BH_Vec4fMulAdd(&a[8], row, &tmp[12], &tmp[12]); + row[0] = row[1] = row[2] = row[3] = b[15]; BH_Vec4fMulAdd(&a[12], row, &tmp[12], &tmp[12]); + + memcpy(out, tmp, sizeof(tmp)); +} + + +void BH_Mat4fScale(const float *a, + float b, + float *out) +{ + BH_Vec4fScale(&a[0], b, &out[0]); + BH_Vec4fScale(&a[4], b, &out[4]); + BH_Vec4fScale(&a[8], b, &out[8]); + BH_Vec4fScale(&a[12], b, &out[12]); +} + + +void BH_Mat4fTranspose(const float *in, + float *out) +{ + float tmp[16]; + + tmp[0] = in[0]; tmp[4] = in[1]; tmp[8] = in[2]; tmp[12] = in[3]; + tmp[1] = in[4]; tmp[5] = in[5]; tmp[9] = in[6]; tmp[13] = in[7]; + tmp[2] = in[8]; tmp[6] = in[9]; tmp[10] = in[10]; tmp[14] = in[11]; + tmp[3] = in[12]; tmp[7] = in[13]; tmp[11] = in[14]; tmp[15] = in[15]; + + memcpy(out, tmp, sizeof(tmp)); +} + + +float BH_Mat4fTrace(const float *in) +{ + return in[0] + in[5] + in[10] + in[15]; +} + + +float BH_Mat4fDet(const float *in) +{ + float a, b, c, d, e, f, result; + + a = in[2] * in[7] - in[3] * in[6]; + b = in[2] * in[11] - in[3] * in[10]; + c = in[2] * in[15] - in[3] * in[14]; + d = in[6] * in[11] - in[7] * in[10]; + e = in[6] * in[15] - in[7] * in[14]; + f = in[10] * in[15] - in[11] * in[14]; + + result = 0.0f; + result += in[0] * (in[5] * f - in[9] * e + in[13] * d); + result -= in[4] * (in[1] * f - in[9] * c + in[13] * b); + result += in[8] * (in[1] * e - in[5] * c + in[13] * a); + result -= in[12] * (in[1] * d - in[5] * b + in[9] * a); + + return result; +} + + +int BH_Mat4fInverse(const float *in, + float *out) +{ + float a, b, c, d, e, f, det; + float tmp[16]; + + a = in[2] * in[7] - in[3] * in[6]; + b = in[2] * in[11] - in[3] * in[10]; + c = in[2] * in[15] - in[3] * in[14]; + d = in[6] * in[11] - in[7] * in[10]; + e = in[6] * in[15] - in[7] * in[14]; + f = in[10] * in[15] - in[11] * in[14]; + + tmp[0] = (in[5] * f - in[9] * e + in[13] * d); + tmp[1] = -(in[1] * f - in[9] * c + in[13] * b); + tmp[2] = (in[1] * e - in[5] * c + in[13] * a); + tmp[3] = -(in[1] * d - in[5] * b + in[9] * a); + + det = 0.0f; + det += in[0] * tmp[0]; + det += in[4] * tmp[1]; + det += in[8] * tmp[2]; + det += in[12] * tmp[3]; + + if (det == 0.0f) + return BH_ERROR; + + tmp[4] = -(in[4] * f - in[8] * e + in[12] * d); + tmp[5] = (in[0] * f - in[8] * c + in[12] * b); + tmp[6] = -(in[0] * e - in[4] * c + in[12] * a); + tmp[7] = (in[0] * d - in[4] * b + in[8] * a); + + a = in[1] * in[7] - in[3] * in[5]; + b = in[1] * in[11] - in[3] * in[9]; + c = in[1] * in[15] - in[3] * in[13]; + d = in[5] * in[11] - in[7] * in[9]; + e = in[5] * in[15] - in[7] * in[13]; + f = in[9] * in[15] - in[11] * in[13]; + + tmp[8] = (in[4] * f - in[8] * e + in[12] * d); + tmp[9] = -(in[0] * f - in[8] * c + in[12] * b); + tmp[10] = (in[0] * e - in[4] * c + in[12] * a); + tmp[11] = -(in[0] * d - in[4] * b + in[8] * a); + + a = in[1] * in[6] - in[2] * in[5]; + b = in[1] * in[10] - in[2] * in[9]; + c = in[1] * in[14] - in[2] * in[13]; + d = in[5] * in[10] - in[6] * in[9]; + e = in[5] * in[14] - in[6] * in[13]; + f = in[9] * in[14] - in[10] * in[13]; + + tmp[12] = -(in[4] * f - in[8] * e + in[12] * d); + tmp[13] = (in[0] * f - in[8] * c + in[12] * b); + tmp[14] = -(in[0] * e - in[4] * c + in[12] * a); + tmp[15] = (in[0] * d - in[4] * b + in[8] * a); + + BH_Mat4fScale(tmp, 1.0f / det, out); + return BH_OK; +} + + +void BH_Mat4fFromScale(float x, + float y, + float z, + float *out) +{ + BH_Mat4fIdentity(out); + out[0] = x; + out[5] = y; + out[10] = z; +} + + +void BH_Mat4fFromTranslation(float x, + float y, + float z, + float *out) +{ + BH_Mat4fIdentity(out); + out[12] = x; + out[13] = y; + out[14] = z; +} + + +void BH_Mat4fFromRotationX(float angle, + float *out) +{ + float c, s; + + c = cos(angle); + s = sin(angle); + + BH_Mat4fIdentity(out); + out[5] = c; + out[6] = s; + out[9] = -s; + out[10] = c; +} + + +void BH_Mat4fFromRotationY(float angle, + float *out) +{ + float c, s; + + c = cos(angle); + s = sin(angle); + + BH_Mat4fIdentity(out); + out[0] = c; + out[2] = -s; + out[8] = s; + out[10] = c; +} + + +void BH_Mat4fFromRotationZ(float angle, + float *out) +{ + float c, s; + + c = cos(angle); + s = sin(angle); + + BH_Mat4fIdentity(out); + out[0] = c; + out[1] = s; + out[4] = -s; + out[5] = c; +} + + +void BH_Mat4fFromAxis(const float *axis, + float angle, + float *out) +{ + float x, y, z, length; + float c, s, moc, xx, xy, xz, yy, yz, zz; + + length = BH_Vec3fLength(axis); + BH_Mat4fIdentity(out); + + if (length == 0.0f) + return; + + x = axis[0] / length; + y = axis[1] / length; + z = axis[2] / length; + + c = cos(angle); + s = sin(angle); + moc = 1.0f - c; + + xx = x * x; + xy = x * y; + xz = x * z; + yy = y * y; + yz = y * z; + zz = z * z; + + out[0] = c + xx * moc; + out[1] = xy * moc + z * s; + out[2] = xz * moc - y * s; + + out[4] = xy * moc - z * s; + out[5] = c + yy * moc; + out[6] = yz * moc + x * s; + + out[8] = xz * moc + y * s; + out[9] = yz * moc - x * s; + out[10] = c + zz * moc; +} + + +void BH_Mat4fFromEuler(float roll, + float pitch, + float yaw, + float *out) +{ + float rs, rc, ys, yc, ps, pc; + + rs = sin(roll); + rc = cos(roll); + ps = sin(pitch); + pc = cos(pitch); + ys = sin(yaw); + yc = cos(yaw); + + BH_Mat4fIdentity(out); + out[0] = pc * yc; + out[1] = pc * ys; + out[2] = -ps; + out[4] = ps * rs * yc - rc * ys; + out[5] = ps * rs * ys + rc * yc; + out[6] = pc * rs; + out[8] = rs * ys + ps * rc * yc; + out[9] = ps * rc * ys - rs * yc; + out[10] = pc * rc; +} + + +void BH_Mat4fFromQuat4f(const float *in, + float *out) +{ + BH_Quat4fToMat4f(in, out); +} + + +void BH_Mat4fFromOrtho(float xMin, + float xMax, + float yMin, + float yMax, + float zMin, + float zMax, + float *out) +{ + float dx, dy, dz; + + dx = xMax - xMin; + dy = yMax - yMin; + dz = zMax - zMin; + + BH_Mat4fIdentity(out); + + out[0] = 2.0f / dx; + out[5] = 2.0f / dy; + out[10] = -2.0f / dz; + out[12] = -(xMax + xMin) / dx; + out[13] = -(yMax + yMin) / dy; + out[14] = -(zMax + zMin) / dz; +} + + +void BH_Mat4fFromFrustum(float fov, + float aspect, + float zMin, + float zMax, + float *out) +{ + float t, dz; + + dz = zMax - zMin; + t = tanf(fov / 2.0f); + + BH_Mat4fIdentity(out); + + out[0] = 1.0f / (aspect * t); + out[5] = 1.0f / t; + out[10] = -(zMax + zMin) / dz; + out[11] = -1.0f; + out[14] = -(2.0f * zMax * zMin) / dz; + out[15] = 0.0f; +} + + +void BH_Mat4fFromLookAt(const float *pos, + const float *at, + const float *up, + float *out) +{ + float cdir[3], cright[3], cup[3]; + + BH_Vec3fSub(pos, at, cdir); + BH_Vec3fNormal(cdir, cdir); + BH_Vec3fCross(up, cdir, cright); + BH_Vec3fNormal(cright, cright); + BH_Vec3fCross(cdir, cright, cup); + + out[0] = cright[0]; + out[1] = cup[0]; + out[2] = cdir[0]; + out[3] = 0.0f; + + out[4] = cright[1]; + out[5] = cup[1]; + out[6] = cdir[1]; + out[7] = 0.0f; + + out[8] = cright[2]; + out[9] = cup[2]; + out[10] = cdir[2]; + out[11] = 0.0f; + + out[12] = -BH_Vec3fDot(cright, pos); + out[13] = -BH_Vec3fDot(cup, pos); + out[14] = -BH_Vec3fDot(cdir, pos); + out[15] = 1.0f; +} + + +void BH_Mat4fApplyVec4f(const float *a, + const float *b, + float *out) +{ + float tmp[4], row[4]; + + row[0] = row[1] = row[2] = row[3] = b[0]; BH_Vec4fMul(&a[0], row, tmp); + row[0] = row[1] = row[2] = row[3] = b[1]; BH_Vec4fMulAdd(&a[4], row, tmp, tmp); + row[0] = row[1] = row[2] = row[3] = b[2]; BH_Vec4fMulAdd(&a[8], row, tmp, tmp); + row[0] = row[1] = row[2] = row[3] = b[3]; BH_Vec4fMulAdd(&a[12], row, tmp, tmp); + + memcpy(out, tmp, sizeof(tmp)); +} + + +void BH_Mat4fApplyVec3f(const float *a, + const float *b, + float *out) +{ + float tmp[4], row[4]; + + row[0] = row[1] = row[2] = row[3] = b[0]; BH_Vec4fMul(&a[0], row, tmp); + row[0] = row[1] = row[2] = row[3] = b[1]; BH_Vec4fMulAdd(&a[4], row, tmp, tmp); + row[0] = row[1] = row[2] = row[3] = b[2]; BH_Vec4fMulAdd(&a[8], row, tmp, tmp); + row[0] = row[1] = row[2] = row[3] = 1.0f; BH_Vec4fMulAdd(&a[12], row, tmp, tmp); + + memcpy(out, tmp, sizeof(float) * 3); +} + + +void BH_Mat3fIdentity(float *out) +{ + static const float ident[9] = + { + 1.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 1.0f + }; + + memcpy(out, ident, sizeof(ident)); +} + + +void BH_Mat3fAdd(const float *a, + const float *b, + float *out) +{ + BH_Vec3fAdd(&a[0], &b[0], &out[0]); + BH_Vec3fAdd(&a[3], &b[3], &out[3]); + BH_Vec3fAdd(&a[6], &b[6], &out[6]); +} + + +void BH_Mat3fSub(const float *a, + const float *b, + float *out) +{ + BH_Vec3fSub(&a[0], &b[0], &out[0]); + BH_Vec3fSub(&a[3], &b[3], &out[3]); + BH_Vec3fSub(&a[6], &b[6], &out[6]); +} + + +void BH_Mat3fMul(const float *a, + const float *b, + float *out) +{ + float tmp[9], row[3]; + + row[0] = row[1] = row[2] = b[0]; BH_Vec3fMul(&a[0], row, &tmp[0]); + row[0] = row[1] = row[2] = b[1]; BH_Vec3fMulAdd(&a[3], row, &tmp[0], &tmp[0]); + row[0] = row[1] = row[2] = b[2]; BH_Vec3fMulAdd(&a[6], row, &tmp[0], &tmp[0]); + + row[0] = row[1] = row[2] = b[3]; BH_Vec3fMul(&a[0], row, &tmp[3]); + row[0] = row[1] = row[2] = b[4]; BH_Vec3fMulAdd(&a[3], row, &tmp[3], &tmp[3]); + row[0] = row[1] = row[2] = b[5]; BH_Vec3fMulAdd(&a[6], row, &tmp[3], &tmp[3]); + + row[0] = row[1] = row[2] = b[6]; BH_Vec3fMul(&a[0], row, &tmp[6]); + row[0] = row[1] = row[2] = b[7]; BH_Vec3fMulAdd(&a[3], row, &tmp[6], &tmp[6]); + row[0] = row[1] = row[2] = b[8]; BH_Vec3fMulAdd(&a[6], row, &tmp[6], &tmp[6]); + + memcpy(out, tmp, sizeof(tmp)); +} + + +void BH_Mat3fScale(const float *a, + float b, + float *out) +{ + BH_Vec3fScale(&a[0], b, &out[0]); + BH_Vec3fScale(&a[3], b, &out[3]); + BH_Vec3fScale(&a[6], b, &out[6]); +} + + +void BH_Mat3fTranspose(const float *in, + float *out) +{ + float tmp[9]; + + tmp[0] = in[0]; tmp[3] = in[1]; tmp[6] = in[2]; + tmp[1] = in[3]; tmp[4] = in[4]; tmp[7] = in[5]; + tmp[2] = in[6]; tmp[5] = in[7]; tmp[8] = in[8]; + + memcpy(out, tmp, sizeof(tmp)); +} + + +float BH_Mat3fTrace(const float *in) +{ + return in[0] + in[4] + in[8]; +} + + +float BH_Mat3fDet(const float *in) +{ + float a, b, c, result; + + a = in[4] * in[8] - in[7] * in[5]; + b = in[1] * in[8] - in[7] * in[2]; + c = in[1] * in[5] - in[4] * in[2]; + + result = 0.0f; + result += in[0] * a; + result -= in[3] * b; + result += in[6] * c; + + return result; +} + + +int BH_Mat3fInverse(const float *in, + float *out) +{ + float a, b, c, det; + float tmp[16]; + + a = in[4] * in[8] - in[7] * in[5]; + b = in[1] * in[8] - in[7] * in[2]; + c = in[1] * in[5] - in[4] * in[2]; + + tmp[0] = a; + tmp[1] = -b; + tmp[2] = c; + + det = 0.0f; + det += in[0] * tmp[0]; + det += in[3] * tmp[1]; + det += in[6] * tmp[2]; + + if (det == 0.0f) + return BH_ERROR; + + a = in[3] * in[8] - in[6] * in[5]; + b = in[0] * in[8] - in[6] * in[2]; + c = in[0] * in[5] - in[3] * in[2]; + + tmp[3] = -a; + tmp[4] = b; + tmp[5] = -c; + + a = in[3] * in[7] - in[6] * in[4]; + b = in[0] * in[7] - in[6] * in[1]; + c = in[0] * in[4] - in[3] * in[1]; + + tmp[6] = a; + tmp[7] = -b; + tmp[8] = c; + + BH_Mat3fScale(tmp, 1.0f / det, out); + return BH_OK; +} + + +void BH_Mat3fFromScale(float x, + float y, + float *out) +{ + BH_Mat3fIdentity(out); + out[0] = x; + out[4] = y; +} + + +void BH_Mat3fFromTranslation(float x, + float y, + float *out) +{ + BH_Mat3fIdentity(out); + out[6] = x; + out[7] = y; +} + + +void BH_Mat3fFromRotation(float angle, + float *out) +{ + float c, s; + + c = cos(angle); + s = sin(angle); + + BH_Mat3fIdentity(out); + out[0] = c; + out[1] = s; + out[3] = -s; + out[4] = c; +} + + +void BH_Mat3fApplyVec3f(float *a, + float *b, + float *out) +{ + float tmp[3], row[3]; + + row[0] = row[1] = row[2] = b[0]; BH_Vec3fMul(&a[0], row, tmp); + row[0] = row[1] = row[2] = b[1]; BH_Vec3fMulAdd(&a[3], row, tmp, tmp); + row[0] = row[1] = row[2] = b[2]; BH_Vec3fMulAdd(&a[6], row, tmp, tmp); + + memcpy(out, tmp, sizeof(tmp)); +} + + +void BH_Mat3fApplyVec2f(float *a, + float *b, + float *out) +{ + float tmp[3], row[3]; + + row[0] = row[1] = row[2] = b[0]; BH_Vec3fMul(&a[0], row, tmp); + row[0] = row[1] = row[2] = b[1]; BH_Vec3fMulAdd(&a[3], row, tmp, tmp); + row[0] = row[1] = row[2] = 1.0f; BH_Vec3fMulAdd(&a[6], row, tmp, tmp); + + memcpy(out, tmp, sizeof(float) * 2); +} diff --git a/src/Queue.c b/src/Queue.c new file mode 100755 index 0000000..4b9d06e --- /dev/null +++ b/src/Queue.c @@ -0,0 +1,209 @@ +#include +#include +#include + + +struct BH_Queue +{ + void **data; + size_t size; + size_t head; + size_t tail; + size_t capacity; +}; + + +static void BH_QueueInit(BH_Queue *queue) +{ + memset(queue, 0, sizeof(*queue)); +} + + +static void BH_QueueDestroy(BH_Queue *queue) +{ + if (queue->capacity) + free(queue->data); +} + + +static void BH_QueueCopy(BH_Queue *dest, + BH_Queue *src) +{ + void *iter; + + /* Iterate over old queue and insert data into new queue */ + iter = BH_QueueIterNext(src, NULL); + while (iter) + { + BH_QueueInsert(dest, BH_QueueIterValue(iter)); + iter = BH_QueueIterNext(src, iter); + } +} + + +BH_Queue *BH_QueueNew(void) +{ + BH_Queue *result; + + result = malloc(sizeof(*result)); + if (result) + BH_QueueInit(result); + + return result; +} + + +void BH_QueueFree(BH_Queue *queue) +{ + BH_QueueDestroy(queue); + free(queue); +} + + +void BH_QueueClear(BH_Queue *queue) +{ + queue->head = 0; + queue->tail = 0; + queue->size = 0; +} + + +int BH_QueueReserve(BH_Queue *queue, + size_t size) +{ + BH_Queue other; + + /* New capacity should be great or equal to current size */ + if (size < queue->size) + size = queue->size; + + /* Catch malloc overflow */ + if (size >= ((size_t)-1) / sizeof(void *)) + return BH_OOM; + + /* Prevent same size memory reallocation */ + if (size == queue->capacity) + return BH_OK; + + /* Prepare new empty queue */ + BH_QueueInit(&other); + if (size) + { + /* Allocate new capacity for the queue */ + other.data = malloc(size * sizeof(void *)); + other.capacity = size; + if (!other.data) + return BH_OOM; + + /* Iterate over old queue and insert data into new queue */ + BH_QueueCopy(&other, queue); + } + + /* If old queue had allocated data - free it */ + if (queue->capacity) + free(queue->data); + + /* Copy queue information */ + *queue = other; + return BH_OK; +} + + +int BH_QueueInsert(BH_Queue *queue, + void *value) +{ + /* Check if queue can contain new element */ + if (queue->size + 1 > queue->capacity) + { + size_t capacity; + + /* Check for capacity overflow and reserve capacity */ + capacity = (queue->capacity) ? (queue->capacity * 2) : (16); + if (capacity < queue->capacity || BH_QueueReserve(queue, capacity)) + return BH_OOM; + } + + /* Increase queue size and advance tail index */ + queue->data[queue->tail] = value; + queue->size++; + if (++queue->tail >= queue->capacity) + queue->tail = 0; + + return BH_OK; +} + + +void BH_QueueRemove(BH_Queue *queue) +{ + /* Do nothing if queue is empty */ + if (!queue->size) + return; + + /* Decrease queue size and advance head index */ + queue->size--; + if (++queue->head >= queue->capacity) + queue->head = 0; +} + + +int BH_QueueFront(BH_Queue *queue, void **value) +{ + /* Do nothing if queue is empty */ + if (!queue->size) + return BH_ERROR; + + /* Return front element */ + *value = queue->data[queue->head]; + return BH_OK; +} + + +int BH_QueueEmpty(BH_Queue *queue) +{ + return !queue->size; +} + + +size_t BH_QueueSize(BH_Queue *queue) +{ + return queue->size; +} + + +size_t BH_QueueCapacity(BH_Queue *queue) +{ + return queue->capacity; +} + + +void *BH_QueueIterNext(BH_Queue *queue, + void *iter) +{ + void **element = (void **)iter; + + /* Do nothing if queue is empty */ + if (!queue->size) + return NULL; + + /* Advance or set iterator */ + if (element) + { + element++; + if (element == queue->data + queue->capacity) + element = queue->data; + + /* Check if we reached the end */ + if (element == queue->data + queue->tail) + return NULL; + } + else + element = queue->data + queue->head; + + return element; +} + + +void *BH_QueueIterValue(void *iter) +{ + return *(void **)iter; +} diff --git a/src/algo.c b/src/algo.c deleted file mode 100755 index 8a42c95..0000000 --- a/src/algo.c +++ /dev/null @@ -1,411 +0,0 @@ -#include -#include - - -void BH_Swap(void *dest, - void *src, - size_t size) -{ - int tmp; - - /* Swap bytes in int-sized chunks */ - while (size >= sizeof(tmp)) - { - memmove(&tmp, dest, sizeof(tmp)); - memmove(dest, src, sizeof(tmp)); - memmove(src, &tmp, sizeof(tmp)); - - dest = (char *)dest + sizeof(tmp); - src = (char *)src + sizeof(tmp); - size -= sizeof(tmp); - } - - /* Swap the remaining size */ - if (size) - { - memmove(&tmp, dest, size); - memmove(dest, src, size); - memmove(src, &tmp, size); - } -} - - -void *BH_Partition(void *pivot, - void *array, - size_t size, - size_t element, - BH_EqualCallback equal) -{ - char *start, *end, *i, *j; - - /* Calculate start, end and item pointers */ - start = (char *)array; - end = start + size * element; - i = start; - j = start + (size - 1) * element; - - /* Iterate over array */ - while (1) - { - /* Find first element from the left that are bigger then pivot */ - while (i < end && equal(i, pivot) < 0) - i += element; - - /* Find first element from the right that are less then pivot*/ - while (j >= start && equal(j, pivot) >= 0) - j -= element; - - /* If item elemetns passed each other - we are done */ - if (i >= j) - break; - - /* Special case when pivot is actually part of the array */ - if (pivot == i) - pivot = j; - else if (pivot == j) - pivot = i; - - /* Swap elements and continue */ - BH_Swap(i, j, element); - i += element; - j -= element; - } - - /* Return pointer to the middle of the partition */ - return j + element; -} - - -#if 0 -static void BH_SortInsert(void *array, - size_t size, - size_t element, - BH_EqualCallback equal) -{ - size_t i, j; - - /* Standard insert sort */ - for (i = 1; i < size; i++) - { - for (j = i; j >= 1; j -= 1) - { - char *lhs, *rhs; - - lhs = (char *)array + j * element; - rhs = (char *)array + (j - 1) * element; - - if (equal(lhs, rhs) < 0) - BH_Swap(lhs, rhs, element); - else - break; - } - } - -} -#endif - - -static void BH_SortShell(void *array, - size_t size, - size_t element, - BH_EqualCallback equal) -{ - static const size_t gaps[10] = {1750, 701, 301, 132, 57, 23, 10, 4, 1, 0}; - const size_t *gap; - size_t i, j; - - /* Shell sort with A102549 sequence */ - for (gap = gaps; *gap; ++gap) - { - for (i = *gap; i < size; i++) - { - for (j = i; j >= *gap; j -= *gap) - { - char *lhs, *rhs; - - lhs = (char *)array + j * element; - rhs = (char *)array + (j - *gap) * element; - - if (equal(lhs, rhs) < 0) - BH_Swap(lhs, rhs, element); - else - break; - } - } - } -} - - -static void BH_SortHeap(void *array, - size_t size, - size_t element, - BH_EqualCallback equal) -{ - size_t i; - - BH_HeapMake(array, size, element, equal); - for (i = size; i > 0; i--) - BH_HeapRemove(array, i, element, equal); -} - - -static void BH_SortIntroR(void *array, - size_t size, - size_t element, - BH_EqualCallback equal, - size_t depth) -{ - /* Introsort (with manual tail call optimization) */ - while (1) - { - char *start, *middle, *end, *pivot; - - if (size < 16) - { - /* There are less then 16 elements left - use Shell/Insert sort */ - BH_SortShell(array, size, element, equal); - return; - } - else if (!depth) - { - /* Max depth reached - use heap sort */ - BH_SortHeap(array, size, element, equal); - return; - } - - /* Calculate start, middle and end pointers */ - start = (char *)array; - middle = start + (size / 2) * element; - end = start + (size - 1) * element; - - /* Select middle element */ - if (equal(start, middle) > 0) - { - if (equal(middle, end) > 0) - pivot = middle; - else if (equal(start, end) > 0) - pivot = end; - else - pivot = start; - } - else - { - if (equal(start, end) > 0) - pivot = start; - else if (equal(middle, end) > 0) - pivot = end; - else - pivot = middle; - } - - /* Partition the array */ - middle = BH_Partition(pivot, array, size, element, equal); - - /* Recursive call into first half */ - BH_SortIntroR(array, (middle - start) / element, element, equal, depth - 1); - - /* Setup array and size for the second half */ - array = middle; - size = size - (middle - start) / element; - depth--; - } -} - - -void BH_Sort(void *array, - size_t size, - size_t element, - BH_EqualCallback equal) -{ - size_t depth, depth_log; - - /* Calculate max depth */ - depth = 0; - depth_log = 1; - while (depth_log < size) - { - depth++; - depth_log <<= 1; - } - - /* Call main sorting function */ - BH_SortIntroR(array, size, element, equal, depth); -} - - -void BH_HeapMake(void *array, - size_t size, - size_t element, - BH_EqualCallback equal) -{ - char *start, *end; - size_t i; - - /* Calculate start and end pointers of the array */ - start = (char *)array; - end = start + size * element; - - /* Bottom up heapify algorithm */ - for (i = size / 2 + 1; i; --i) - { - char *current, *left, *right; - - /* Calculate current and children pointers */ - current = start + (i - 1) * element; - left = start + (current - start) * 2 + element; - right = left + element; - - while (left < end) - { - char *biggest; - - /* Determine biggest child */ - biggest = left; - if (right < end && equal(left, right) < 0) - biggest = right; - - /* Compare biggest child with current */ - if (equal(current, biggest) < 0) - { - /* Swap content and recalculate children pointers */ - BH_Swap(current, biggest, element); - current = biggest; - left = start + (current - start) * 2 + element; - right = left + element; - } - else - break; - } - } -} - - -void BH_HeapRemove(void *array, - size_t size, - size_t element, - BH_EqualCallback equal) -{ - char *start, *end, *current, *left, *right; - - if (size <= 1) - return; - - /* Calculate start, end and children pointers */ - start = (char *)array; - end = start + (size - 1) * element; - current = start; - left = start + (current - start) * 2 + element; - right = left + element; - - /* Swap first and last element */ - BH_Swap(current, end, element); - - /* Iterate until we reach the end */ - while (left < end) - { - char *biggest; - - /* Determine biggest child */ - biggest = left; - if (right < end && equal(left, right) < 0) - biggest = right; - - /* Compare biggest child with current */ - if (equal(current, biggest) < 0) - { - /* Swap content and recalculate children pointers */ - BH_Swap(current, biggest, element); - current = biggest; - left = start + (current - start) * 2 + element; - right = left + element; - } - else - break; - } -} - - -void BH_HeapInsert(void *value, - void *array, - size_t size, - size_t element, - BH_EqualCallback equal) -{ - char *start, *end, *current; - - /* Calculate begin and end pointers */ - start = (char *)array; - end = start + size * element; - current = end; - - /* Copy value into array */ - if (value) - memmove(current, value, element); - - while (current > start) - { - char *parent; - - /* Calculate parent pointer */ - parent = start + (((current - start) / element - 1) / 2) * element; - - /* Compare current and parent */ - if (equal(parent, current) < 0) - { - /* Swap current and parent */ - BH_Swap(parent, current, element); - current = parent; - } - else - break; - } -} - - -void BH_HeapReplace(void *value, - void *array, - size_t size, - size_t element, - BH_EqualCallback equal) -{ - char *start, *end, *current, *left, *right; - - if (size < 1) - return; - - /* Calculate start, end and children pointers */ - start = (char *)array; - end = start + size * element; - current = start; - left = start + (current - start) * 2 + element; - right = left + element; - - /* Copy supplied element to the first (top) position */ - if (value) - memmove(current, value, element); - else - memmove(current, start + size * element, element); - - /* Iterate until we reach the end */ - while (left < end) - { - char *biggest; - - /* Determine biggest child */ - biggest = left; - if (right < end && equal(left, right) < 0) - biggest = right; - - /* Compare biggest child with current */ - if (equal(current, biggest) < 0) - { - /* Swap content and recalculate children pointers */ - BH_Swap(current, biggest, element); - current = biggest; - left = start + (current - start) * 2 + element; - right = left + element; - } - else - break; - } -} diff --git a/src/dummy/File.c b/src/dummy/File.c new file mode 100644 index 0000000..2cb1cd6 --- /dev/null +++ b/src/dummy/File.c @@ -0,0 +1,200 @@ +#include + +typedef struct BH_File +{ + int implement; + int me; +} BH_File; + + +static int BH_FileInfo(BH_File *file, + size_t *size, + const char **name); + + +static int BH_FileInit(BH_File *file, + const char *path); + + +static int BH_FileDestroy(BH_File *file); + + +static int BH_FileOpen(BH_File *file, + int *mode); + + +static int BH_FileClose(BH_File *file); + + +static int BH_FileRead(BH_File *file, + char *data, + size_t *size); + + +static int BH_FileWrite(BH_File *file, + const char *data, + size_t *size); + + +static int BH_FilePeek(BH_File* file, + char *data, + size_t *size); + + +static int BH_FileFlush(BH_File *file); + + +static int BH_FileSeek(BH_File *file, + int64_t *pos, + int *dir); + + +static int BH_FileTell(BH_File *file, + int64_t *pos); + + +static int BH_FileSize(BH_File *file, + int64_t *size); + + +static int BH_FileFlags(BH_File *file); + + +static int BH_FileClear(BH_File *file); + + +static int BH_FileInfo(BH_File *file, + size_t *size, + const char **name) +{ + static const char classname[] = BH_FILE_CLASSNAME; + + if (size) + *size = sizeof(*file); + if (name) + *name = classname; + + return BH_NOIMPL; +} + + +static int BH_FileInit(BH_File *file, + const char *path) +{ + return BH_NOIMPL; +} + + +static int BH_FileDestroy(BH_File *file) +{ + return BH_NOIMPL; +} + + +static int BH_FileOpen(BH_File *file, + int *mode) +{ + return BH_NOIMPL; +} + + +static int BH_FileClose(BH_File *file) +{ + return BH_NOIMPL; +} + + +static int BH_FileRead(BH_File *file, + char *data, + size_t *size) +{ + return BH_NOIMPL; +} + + +static int BH_FileWrite(BH_File *file, + const char *data, + size_t *size) +{ + return BH_NOIMPL; +} + + +static int BH_FilePeek(BH_File *file, + char *data, + size_t *size) +{ + return BH_NOIMPL; +} + + +static int BH_FileFlush(BH_File *file) +{ + return BH_NOIMPL; +} + + +static int BH_FileSeek(BH_File *file, + int64_t *pos, + int *dir) +{ + return BH_NOIMPL; +} + + +static int BH_FileTell(BH_File *file, + int64_t *pos) +{ + return BH_NOIMPL; +} + + +static int BH_FileSize(BH_File *file, + int64_t *size) +{ + return BH_NOIMPL; +} + + +static int BH_FileFlags(BH_File *file) +{ + return BH_IO_FLAG_ERROR; +} + + +static int BH_FileClear(BH_File *file) +{ + return BH_NOIMPL; +} + + +static int BH_FileCallback(BH_File *file, + int type, + void *arg1, + void *arg2) +{ + switch (type) + { + case BH_IO_INFO_CB: return BH_FileInfo(file, (size_t *)arg1, (const char **)arg2); + case BH_IO_INIT_CB: return BH_FileInit(file, (const char *)arg1); + case BH_IO_DESTROY_CB: return BH_FileDestroy(file); + case BH_IO_OPEN_CB: return BH_FileOpen(file, (int *)arg1); + case BH_IO_CLOSE_CB: return BH_FileClose(file); + case BH_IO_READ_CB: return BH_FileRead(file, (char *)arg1, (size_t *)arg2); + case BH_IO_WRITE_CB: return BH_FileWrite(file, (const char *)arg1, (size_t *)arg2); + case BH_IO_PEEK_CB: return BH_FilePeek(file, (char *)arg1, (size_t *)arg2); + case BH_IO_FLUSH_CB: return BH_FileFlush(file); + case BH_IO_SEEK_CB: return BH_FileSeek(file, (int64_t *)arg1, (int *)arg2); + case BH_IO_TELL_CB: return BH_FileTell(file, (int64_t *)arg1); + case BH_IO_SIZE_CB: return BH_FileSize(file, (int64_t *)arg1); + case BH_IO_FLAGS_CB: return BH_FileFlags(file); + case BH_IO_CLEAR_CB: return BH_FileClear(file); + default: return BH_NOIMPL; + } +} + + +BH_IO *BH_FileNew(const char *path) +{ + return BH_IONew((BH_IOCallback)BH_FileCallback, (void *)path); +} diff --git a/src/dummy/file.c b/src/dummy/file.c deleted file mode 100644 index eab4c72..0000000 --- a/src/dummy/file.c +++ /dev/null @@ -1,200 +0,0 @@ -#include - -typedef struct BH_File -{ - int implement; - int me; -} BH_File; - - -static int BH_FileInfo(BH_File *file, - size_t *size, - const char **name); - - -static int BH_FileInit(BH_File *file, - const char *path); - - -static int BH_FileDestroy(BH_File *file); - - -static int BH_FileOpen(BH_File *file, - int *mode); - - -static int BH_FileClose(BH_File *file); - - -static int BH_FileRead(BH_File *file, - char *data, - size_t *size); - - -static int BH_FileWrite(BH_File *file, - const char *data, - size_t *size); - - -static int BH_FilePeek(BH_File* file, - char *data, - size_t *size); - - -static int BH_FileFlush(BH_File *file); - - -static int BH_FileSeek(BH_File *file, - int64_t *pos, - int *dir); - - -static int BH_FileTell(BH_File *file, - int64_t *pos); - - -static int BH_FileSize(BH_File *file, - int64_t *size); - - -static int BH_FileFlags(BH_File *file); - - -static int BH_FileClear(BH_File *file); - - -static int BH_FileInfo(BH_File *file, - size_t *size, - const char **name) -{ - static const char classname[] = BH_FILE_CLASSNAME; - - if (size) - *size = sizeof(*file); - if (name) - *name = classname; - - return BH_NOIMPL; -} - - -static int BH_FileInit(BH_File *file, - const char *path) -{ - return BH_NOIMPL; -} - - -static int BH_FileDestroy(BH_File *file) -{ - return BH_NOIMPL; -} - - -static int BH_FileOpen(BH_File *file, - int *mode) -{ - return BH_NOIMPL; -} - - -static int BH_FileClose(BH_File *file) -{ - return BH_NOIMPL; -} - - -static int BH_FileRead(BH_File *file, - char *data, - size_t *size) -{ - return BH_NOIMPL; -} - - -static int BH_FileWrite(BH_File *file, - const char *data, - size_t *size) -{ - return BH_NOIMPL; -} - - -static int BH_FilePeek(BH_File *file, - char *data, - size_t *size) -{ - return BH_NOIMPL; -} - - -static int BH_FileFlush(BH_File *file) -{ - return BH_NOIMPL; -} - - -static int BH_FileSeek(BH_File *file, - int64_t *pos, - int *dir) -{ - return BH_NOIMPL; -} - - -static int BH_FileTell(BH_File *file, - int64_t *pos) -{ - return BH_NOIMPL; -} - - -static int BH_FileSize(BH_File *file, - int64_t *size) -{ - return BH_NOIMPL; -} - - -static int BH_FileFlags(BH_File *file) -{ - return BH_IO_FLAG_ERROR; -} - - -static int BH_FileClear(BH_File *file) -{ - return BH_NOIMPL; -} - - -static int BH_FileCallback(BH_File *file, - int type, - void *arg1, - void *arg2) -{ - switch (type) - { - case BH_IO_INFO_CB: return BH_FileInfo(file, (size_t *)arg1, (const char **)arg2); - case BH_IO_INIT_CB: return BH_FileInit(file, (const char *)arg1); - case BH_IO_DESTROY_CB: return BH_FileDestroy(file); - case BH_IO_OPEN_CB: return BH_FileOpen(file, (int *)arg1); - case BH_IO_CLOSE_CB: return BH_FileClose(file); - case BH_IO_READ_CB: return BH_FileRead(file, (char *)arg1, (size_t *)arg2); - case BH_IO_WRITE_CB: return BH_FileWrite(file, (const char *)arg1, (size_t *)arg2); - case BH_IO_PEEK_CB: return BH_FilePeek(file, (char *)arg1, (size_t *)arg2); - case BH_IO_FLUSH_CB: return BH_FileFlush(file); - case BH_IO_SEEK_CB: return BH_FileSeek(file, (int64_t *)arg1, (int *)arg2); - case BH_IO_TELL_CB: return BH_FileTell(file, (int64_t *)arg1); - case BH_IO_SIZE_CB: return BH_FileSize(file, (int64_t *)arg1); - case BH_IO_FLAGS_CB: return BH_FileFlags(file); - case BH_IO_CLEAR_CB: return BH_FileClear(file); - default: return BH_NOIMPL; - } -} - - -BH_IO *BH_FileNew(const char *path) -{ - return BH_IONew((BH_IOCallback)BH_FileCallback, (void *)path); -} diff --git a/src/hashmap.c b/src/hashmap.c deleted file mode 100755 index 989f101..0000000 --- a/src/hashmap.c +++ /dev/null @@ -1,390 +0,0 @@ -#include -#include -#include - - -typedef struct BH_HashmapNode -{ - void *key; - void *value; -} BH_HashmapNode; - - -struct BH_Hashmap -{ - BH_HashmapNode *data; - size_t *psls; - size_t size; - size_t capacity; - size_t threshold; - BH_EqualCallback equal; - BH_HashCallback hash; - float factor; -}; - - -static void BH_HashmapInit(BH_Hashmap *hashmap, - BH_EqualCallback equal, - BH_HashCallback hash) -{ - memset(hashmap, 0, sizeof(*hashmap)); - hashmap->factor = 0.75f; - hashmap->equal = equal; - hashmap->hash = hash; -} - - -static void BH_HashmapDestroy(BH_Hashmap *hashmap) -{ - if (hashmap->capacity) - { - free(hashmap->data); - free(hashmap->psls); - } -} - - -static int BH_CalcCapacity(size_t size, - float factor, - size_t *capacity, - size_t *threshold) -{ - /* Check if we need any capacity at all */ - if (!size) - { - *capacity = 0; - *threshold = 0; - return BH_OK; - } - - /* Calculate nearest power of 2 capacity */ - *capacity = 16; - *threshold = *capacity * factor; - while (size > *threshold) - { - *capacity *= 2; - *threshold = *capacity * factor; - - /* Catch capacity overflow */ - if (*capacity < 16) - return BH_OOM; - } - - /* Catch malloc overflow */ - if (*capacity >= ((size_t)-1) / sizeof(BH_HashmapNode)) - return BH_OOM; - - return BH_OK; -} - - -static void BH_CopyHashmap(BH_Hashmap *dest, - BH_Hashmap *src) -{ - void *iter; - - /* Iterate and insert data into hashmap */ - iter = BH_HashmapIterNext(src, NULL); - while (iter) - { - void *key, *value; - - key = BH_HashmapIterKey(iter); - value = BH_HashmapIterValue(iter); - BH_HashmapInsert(dest, key, value); - - iter = BH_HashmapIterNext(src, iter); - } -} - - -BH_Hashmap *BH_HashmapNew(BH_EqualCallback equal, - BH_HashCallback hash) -{ - BH_Hashmap *result; - - result = malloc(sizeof(*result)); - if (result) - BH_HashmapInit(result, equal, hash); - - return result; -} - - -void BH_HashmapFree(BH_Hashmap *hashmap) -{ - BH_HashmapDestroy(hashmap); - free(hashmap); -} - - -void BH_HashmapClear(BH_Hashmap *hashmap) -{ - if (hashmap->capacity) - memset(hashmap->psls, 0, hashmap->capacity * sizeof(size_t)); - hashmap->size = 0; -} - - -int BH_HashmapReserve(BH_Hashmap *hashmap, - size_t size) -{ - BH_Hashmap other; - size_t capacity, threshold; - - /* New capacity can't be smaller then current hashmap size */ - if (size < hashmap->size) - size = hashmap->size; - - /* Calculate new capacity */ - if (BH_CalcCapacity(size, hashmap->factor, &capacity, &threshold)) - return BH_OOM; - - /* Prevent same size reallocation */ - if (capacity == hashmap->capacity) - return BH_OK; - - /* Initialize new hashmap */ - BH_HashmapInit(&other, hashmap->equal, hashmap->hash); - other.factor = hashmap->factor; - - if (capacity) - { - /* Allocate new memory for the hashmap */ - other.data = malloc(sizeof(*other.data) * capacity); - other.psls = malloc(sizeof(size_t) * capacity); - other.threshold = threshold; - other.capacity = capacity; - - /* Check for allocations failure */ - if (!other.data || !other.psls) - { - if (other.data) - free(other.data); - if (other.psls) - free(other.psls); - return BH_OOM; - } - - /* Reset probe sequence lengths */ - memset(other.psls, 0, sizeof(size_t) * other.capacity); - - /* Copy data from old hashmap to the new hashmap */ - BH_CopyHashmap(&other, hashmap); - } - - /* Swap hashmaps */ - BH_HashmapDestroy(hashmap); - *hashmap = other; - return BH_OK; -} - - -int BH_HashmapInsert(BH_Hashmap *hashmap, - void *key, - void *value) -{ - size_t bucket, psl, tmp_psl; - BH_HashmapNode item, tmp; - - /* Try to stay below hashmap threshold */ - if (hashmap->size + 1 > hashmap->threshold) - if (BH_HashmapReserve(hashmap, hashmap->size + 1)) - if (hashmap->size >= hashmap->capacity) - return BH_OOM; - - /* Prepare inserted data and set PSL to 1 */ - item.key = key; - item.value = value; - psl = 1; - - /* Calculate prefered bucket index */ - bucket = hashmap->hash(key) & (hashmap->capacity - 1); - - /* Find empty bucket */ - while (hashmap->psls[bucket]) - { - /* Current bucket is richer then us - swap elements */ - if (psl > hashmap->psls[bucket]) - { - tmp = hashmap->data[bucket]; - tmp_psl = hashmap->psls[bucket]; - hashmap->data[bucket] = item; - hashmap->psls[bucket] = psl; - item = tmp; - psl = tmp_psl; - } - - bucket = (bucket + 1) & (hashmap->capacity - 1); - psl++; - } - - /* Found empty bucket - place item here */ - hashmap->data[bucket] = item; - hashmap->psls[bucket] = psl; - hashmap->size++; - - return BH_OK; -} - - -void BH_HashmapRemove(BH_Hashmap *hashmap, - void *key) -{ - void *iter; - - iter = BH_HashmapIterAt(hashmap, key); - if (iter) - BH_HashmapIterRemove(hashmap, iter); -} - - -int BH_HashmapAt(BH_Hashmap *hashmap, - void *key, - void **value) -{ - void *iter; - iter = BH_HashmapIterAt(hashmap, key); - - if (!iter) - return BH_NOTFOUND; - - if (value) - *value = BH_HashmapIterValue(iter); - - return BH_OK; -} - - -int BH_HashmapEmpty(BH_Hashmap *hashmap) -{ - return !hashmap->size; -} - - -size_t BH_HashmapSize(BH_Hashmap *hashmap) -{ - return hashmap->size; -} - - -size_t BH_HashmapCapacity(BH_Hashmap *hashmap) -{ - return hashmap->capacity; -} - - -float BH_HashmapFactor(BH_Hashmap *hashmap) -{ - return hashmap->factor; -} - - -void BH_HashmapSetFactor(BH_Hashmap *hashmap, - float factor) -{ - /* Limit the factor value to [0.15, 1.0] */ - factor = (factor > 1.0f) ? (1.0f) : (factor); - factor = (factor < 0.15f) ? (0.15f) : (factor); - - /* Calculate new threshold value */ - hashmap->factor = factor; - hashmap->threshold = hashmap->capacity * factor; -} - - -void *BH_HashmapIterAt(BH_Hashmap *hashmap, - void *key) -{ - size_t bucket, psl; - - /* Nothing can be in empty map */ - if (!hashmap->size) - return NULL; - - /* Calculate prefered bucket index and set PSL to 1 */ - bucket = hashmap->hash(key) & (hashmap->capacity - 1); - psl = 1; - - /* Iterate hashmap until we find element or find richer bucket */ - while (hashmap->psls[bucket] >= psl && hashmap->equal(hashmap->data[bucket].key, key)) - { - bucket = (bucket + 1) & (hashmap->capacity - 1); - psl++; - } - - /* If bucket is poorer or equal to us - we found our element */ - if (hashmap->psls[bucket] >= psl) - return hashmap->data + bucket; - - return NULL; -} - - -void *BH_HashmapIterNext(BH_Hashmap *hashmap, - void *iter) -{ - BH_HashmapNode *item; - - item = (BH_HashmapNode *)iter; - while (1) - { - /* Advance or set iterator to the first element */ - if (item) - item++; - else - item = hashmap->data; - - /* Check iterator for validity */ - if (item >= hashmap->data + hashmap->capacity) - return NULL; - - /* Check iterator's item PSL */ - if (hashmap->psls[item - hashmap->data]) - return item; - } -} - - -void BH_HashmapIterRemove(BH_Hashmap *hashmap, - void *iter) -{ - size_t bucket, next_bucket; - - /* Check if hashmap is empty or we are given NULL iterator */ - if (!iter || !hashmap->size) - return; - - /* Adjust hashmap size, calculate current and next bucket index */ - hashmap->size--; - bucket = (BH_HashmapNode *)iter - hashmap->data; - next_bucket = (bucket + 1) & (hashmap->capacity - 1); - - /* Shift all elements toward their preffered place */ - while (hashmap->psls[next_bucket] > 1) - { - /* Copy item and adjust PSL */ - hashmap->data[bucket] = hashmap->data[next_bucket]; - hashmap->psls[bucket] = hashmap->psls[next_bucket] - 1; - - /* Calculate next bucket index */ - bucket = next_bucket; - next_bucket = (bucket + 1) & (hashmap->capacity - 1); - } - - /* Reset bucket's PSL (mark empty) */ - hashmap->psls[bucket] = 0; -} - - -void *BH_HashmapIterKey(void *iter) -{ - return ((BH_HashmapNode *)iter)->key; -} - - -void *BH_HashmapIterValue(void *iter) -{ - return ((BH_HashmapNode *)iter)->value; -} - diff --git a/src/io.c b/src/io.c deleted file mode 100644 index 8322707..0000000 --- a/src/io.c +++ /dev/null @@ -1,226 +0,0 @@ -#include -#include - - -#define BUFFER_SIZE (sizeof(char *)) - -struct BH_IO -{ - BH_IOCallback cb; -}; - - -BH_IO *BH_IONew(BH_IOCallback cb, - void *data) -{ - size_t requested; - BH_IO *io; - - /* Get information about IO device size */ - if (cb(NULL, BH_IO_INFO_CB, &requested, NULL)) - return NULL; - - /* Allocate space for the IO device */ - io = malloc(sizeof(*io) + requested); - if (!io) - return NULL; - - /* Initialize IO device */ - io->cb = cb; - if (cb(io + 1, BH_IO_INIT_CB, data, NULL)) - { - free(io); - return NULL; - } - - return io; -} - - -void BH_IOFree(BH_IO *io) -{ - /* Prevent working with NULL io */ - if (!io) - return; - - /* Call the IO device destruction handler */ - io->cb(io + 1, BH_IO_DESTROY_CB, NULL, NULL); - - /* Deallocate object */ - free(io); -} - - -const char *BH_IOClassname(BH_IO *io) -{ - const char *name; - - if (!io) - goto error; - - if (io->cb(io + 1, BH_IO_INFO_CB, NULL, &name) != BH_OK) - goto error; - - return name; - -error: - return NULL; -} - - -int BH_IOOpen(BH_IO *io, - int mode) -{ - /* Prevent working with NULL io */ - if (!io) - return BH_ERROR; - - /* Call the IO device open handler with specified mode */ - return io->cb(io + 1, BH_IO_OPEN_CB, &mode, NULL); -} - - -int BH_IOClose(BH_IO *io) -{ - /* Prevent working with NULL io */ - if (!io) - return BH_ERROR; - - /* Call the IO device close handler */ - return io->cb(io + 1, BH_IO_CLOSE_CB, NULL, NULL); -} - - -int BH_IORead(BH_IO *io, - char *buffer, - size_t size, - size_t *actual) -{ - int code; - - /* Prevent working with NULL io */ - if (!io) - return BH_ERROR; - - /* Call the IO device read handler */ - code = io->cb(io + 1, BH_IO_READ_CB, buffer, &size); - - /* If caller wants to know actual read size - report it back */ - if (actual) - *actual = size; - - return code; -} - - -int BH_IOWrite(BH_IO *io, - const char *buffer, - size_t size, - size_t *actual) -{ - int code; - - /* Prevent working with NULL io */ - if (!io) - return BH_ERROR; - - /* Call the IO device write handler */ - code = io->cb(io + 1, BH_IO_WRITE_CB, (void *)buffer, &size); - - /* If caller wants to know actual written size - report it back */ - if (actual) - *actual = size; - - return code; -} - -int BH_IOPeek(BH_IO *io, - char *buffer, - size_t size, - size_t *actual) -{ - int code; - - /* Prevent working with NULL io */ - if (!io) - return BH_ERROR; - - /* Call the IO device peek handler */ - code = io->cb(io + 1, BH_IO_PEEK_CB, (void *)buffer, &size); - - /* If caller wants to know actual written size - report it back */ - if (actual) - *actual = size; - - return code; -} - - -int BH_IOTell(BH_IO *io, - int64_t *position) -{ - /* Prevent working with NULL io */ - if (!io) - return BH_ERROR; - - /* Call the IO device tell handler */ - return io->cb(io + 1, BH_IO_TELL_CB, position, NULL); -} - - -int BH_IOSeek(BH_IO *io, - int64_t position, - int direction) -{ - /* Prevent working with NULL io */ - if (!io) - return BH_ERROR; - - /* Call the IO device seek handler */ - return io->cb(io + 1, BH_IO_SEEK_CB, &position, &direction); -} - - -int BH_IOFlush(BH_IO *io) -{ - /* Prevent working with NULL io */ - if (!io) - return BH_ERROR; - - /* Call the IO device flush handler */ - return io->cb(io + 1, BH_IO_FLUSH_CB, NULL, NULL); -} - - -int BH_IOSize(BH_IO *io, - int64_t *size) -{ - /* Prevent working with NULL io */ - if (!io) - return BH_ERROR; - - /* Call the IO device size handler */ - return io->cb(io + 1, BH_IO_SIZE_CB, size, NULL); -} - - -int BH_IOFlags(BH_IO *io) -{ - /* Prevent working with NULL io */ - if (!io) - return BH_IO_FLAG_ERROR; - - /* Call the IO device flags handler */ - return io->cb(io + 1, BH_IO_FLAGS_CB, NULL, NULL); -} - - -int BH_IOClear(BH_IO *io) -{ - /* Prevent working with NULL io */ - if (!io) - return BH_OK; - - /* Call the IO device clear error handler */ - return io->cb(io + 1, BH_IO_CLEAR_CB, NULL, NULL); -} diff --git a/src/math.c b/src/math.c deleted file mode 100644 index bdb90be..0000000 --- a/src/math.c +++ /dev/null @@ -1,1449 +0,0 @@ -#include -#include -#include - - -void BH_Vec4fAdd(const float *a, - const float *b, - float *out) -{ - out[0] = a[0] + b[0]; - out[1] = a[1] + b[1]; - out[2] = a[2] + b[2]; - out[3] = a[3] + b[3]; -} - - -void BH_Vec4fSub(const float *a, - const float *b, - float *out) -{ - out[0] = a[0] - b[0]; - out[1] = a[1] - b[1]; - out[2] = a[2] - b[2]; - out[3] = a[3] - b[3]; -} - - -void BH_Vec4fMul(const float *a, - const float *b, - float *out) -{ - out[0] = a[0] * b[0]; - out[1] = a[1] * b[1]; - out[2] = a[2] * b[2]; - out[3] = a[3] * b[3]; -} - - -void BH_Vec4fScale(const float *a, - const float b, - float *out) -{ - out[0] = a[0] * b; - out[1] = a[1] * b; - out[2] = a[2] * b; - out[3] = a[3] * b; -} - - -void BH_Vec4fMulAdd(const float *a, - const float *b, - const float *c, - float *out) -{ - out[0] = a[0] * b[0] + c[0]; - out[1] = a[1] * b[1] + c[1]; - out[2] = a[2] * b[2] + c[2]; - out[3] = a[3] * b[3] + c[3]; -} - - -void BH_Vec4fNegate(const float *in, - float *out) -{ - out[0] = -in[0]; - out[1] = -in[1]; - out[2] = -in[2]; - out[3] = -in[3]; -} - - -float BH_Vec4fDot(const float *a, - const float *b) -{ - return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]; -} - - -float BH_Vec4fLength(const float *in) -{ - return sqrt(BH_Vec4fDot(in, in)); -} - - -void BH_Vec4fNormal(const float *in, - float *out) -{ - BH_Vec4fScale(in, 1.0f / BH_Vec4fLength(in), out); -} - - -void BH_Vec4fMin(const float *a, - const float *b, - float *out) -{ - if (a[0] < b[0]) out[0] = a[0]; else out[0] = b[0]; - if (a[1] < b[1]) out[1] = a[1]; else out[1] = b[1]; - if (a[2] < b[2]) out[2] = a[2]; else out[2] = b[2]; - if (a[3] < b[3]) out[3] = a[3]; else out[3] = b[3]; -} - - -void BH_Vec4fMax(const float *a, - const float *b, - float *out) -{ - if (a[0] > b[0]) out[0] = a[0]; else out[0] = b[0]; - if (a[1] > b[1]) out[1] = a[1]; else out[1] = b[1]; - if (a[2] > b[2]) out[2] = a[2]; else out[2] = b[2]; - if (a[3] > b[3]) out[3] = a[3]; else out[3] = b[3]; -} - - -void BH_Vec4fLerp(const float *a, - const float *b, - float t, - float *out) -{ - float tmp[4]; - - BH_Vec4fSub(b, a, tmp); - BH_Vec4fScale(tmp, t, tmp); - BH_Vec4fAdd(a, tmp, out); -} - - -void BH_Vec3fAdd(const float *a, - const float *b, - float *out) -{ - out[0] = a[0] + b[0]; - out[1] = a[1] + b[1]; - out[2] = a[2] + b[2]; -} - - -void BH_Vec3fSub(const float *a, - const float *b, - float *out) -{ - out[0] = a[0] - b[0]; - out[1] = a[1] - b[1]; - out[2] = a[2] - b[2]; -} - - -void BH_Vec3fMul(const float *a, - const float *b, - float *out) -{ - out[0] = a[0] * b[0]; - out[1] = a[1] * b[1]; - out[2] = a[2] * b[2]; -} - - -void BH_Vec3fScale(const float *a, - const float b, - float *out) -{ - out[0] = a[0] * b; - out[1] = a[1] * b; - out[2] = a[2] * b; -} - - -void BH_Vec3fMulAdd(const float *a, - const float *b, - const float *c, - float *out) -{ - out[0] = a[0] * b[0] + c[0]; - out[1] = a[1] * b[1] + c[1]; - out[2] = a[2] * b[2] + c[2]; -} - - -void BH_Vec3fNegate(const float *in, - float *out) -{ - out[0] = -in[0]; - out[1] = -in[1]; - out[2] = -in[2]; -} - - -float BH_Vec3fDot(const float *a, - const float *b) -{ - return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; -} - - -void BH_Vec3fCross(const float *a, - const float *b, - float *out) -{ - float tmp[3]; - - tmp[0] = a[1] * b[2] - a[2] * b[1]; - tmp[1] = a[2] * b[0] - a[0] * b[2]; - tmp[2] = a[0] * b[1] - a[1] * b[0]; - memcpy(out, tmp, sizeof(tmp)); -} - - -float BH_Vec3fLength(const float *in) -{ - return sqrt(BH_Vec3fDot(in, in)); -} - - -void BH_Vec3fNormal(const float *in, - float *out) -{ - BH_Vec3fScale(in, 1.0f / BH_Vec3fLength(in), out); -} - - -void BH_Vec3fMin(const float *a, - const float *b, - float *out) -{ - if (a[0] < b[0]) out[0] = a[0]; else out[0] = b[0]; - if (a[1] < b[1]) out[1] = a[1]; else out[1] = b[1]; - if (a[2] < b[2]) out[2] = a[2]; else out[2] = b[2]; -} - - -void BH_Vec3fMax(const float *a, - const float *b, - float *out) -{ - if (a[0] > b[0]) out[0] = a[0]; else out[0] = b[0]; - if (a[1] > b[1]) out[1] = a[1]; else out[1] = b[1]; - if (a[2] > b[2]) out[2] = a[2]; else out[2] = b[2]; -} - - -void BH_Vec3fLerp(const float *a, - const float *b, - float t, - float *out) -{ - float tmp[3]; - - BH_Vec3fSub(b, a, tmp); - BH_Vec3fScale(tmp, t, tmp); - BH_Vec3fAdd(a, tmp, out); -} - - -void BH_Vec2fAdd(const float *a, - const float *b, - float *out) -{ - out[0] = a[0] + b[0]; - out[1] = a[1] + b[1]; -} - - -void BH_Vec2fSub(const float *a, - const float *b, - float *out) -{ - out[0] = a[0] - b[0]; - out[1] = a[1] - b[1]; -} - - -void BH_Vec2fMul(const float *a, - const float *b, - float *out) -{ - out[0] = a[0] * b[0]; - out[1] = a[1] * b[1]; -} - - -void BH_Vec2fScale(const float *a, - const float b, - float *out) -{ - out[0] = a[0] * b; - out[1] = a[1] * b; -} - - -void BH_Vec2fMulAdd(const float *a, - const float *b, - const float *c, - float *out) -{ - out[0] = a[0] * b[0] + c[0]; - out[1] = a[1] * b[1] + c[1]; -} - - -void BH_Vec2fNegate(const float *in, - float *out) -{ - out[0] = -in[0]; - out[1] = -in[1]; -} - - -float BH_Vec2fDot(const float *a, - const float *b) -{ - return a[0] * b[0] + a[1] * b[1]; -} - - -float BH_Vec2fCross(const float *a, - const float *b) -{ - return a[0] * b[1] - a[1] * b[0]; -} - - -float BH_Vec2fLength(const float *in) -{ - return sqrt(BH_Vec2fDot(in, in)); -} - - -void BH_Vec2fNormal(const float *in, - float *out) -{ - BH_Vec2fScale(in, 1.0f / BH_Vec2fLength(in), out); -} - - -void BH_Vec2fMin(const float *a, - const float *b, - float *out) -{ - if (a[0] < b[0]) out[0] = a[0]; else out[0] = b[0]; - if (a[1] < b[1]) out[1] = a[1]; else out[1] = b[1]; -} - - -void BH_Vec2fMax(const float *a, - const float *b, - float *out) -{ - if (a[0] > b[0]) out[0] = a[0]; else out[0] = b[0]; - if (a[1] > b[1]) out[1] = a[1]; else out[1] = b[1]; -} - - -void BH_Vec2fLerp(const float *a, - const float *b, - float t, - float *out) -{ - float tmp[2]; - - BH_Vec2fSub(b, a, tmp); - BH_Vec2fScale(tmp, t, tmp); - BH_Vec2fAdd(a, tmp, out); -} - - -void BH_Vec4iAdd(const int *a, - const int *b, - int *out) -{ - out[0] = a[0] + b[0]; - out[1] = a[1] + b[1]; - out[2] = a[2] + b[2]; - out[3] = a[3] + b[3]; -} - - -void BH_Vec4iSub(const int *a, - const int *b, - int *out) -{ - out[0] = a[0] - b[0]; - out[1] = a[1] - b[1]; - out[2] = a[2] - b[2]; - out[3] = a[3] - b[3]; -} - - -void BH_Vec4iMul(const int *a, - const int *b, - int *out) -{ - out[0] = a[0] * b[0]; - out[1] = a[1] * b[1]; - out[2] = a[2] * b[2]; - out[3] = a[3] * b[3]; -} - - -void BH_Vec4iScale(const int *a, - int b, - int *out) -{ - out[0] = a[0] * b; - out[1] = a[1] * b; - out[2] = a[2] * b; - out[3] = a[3] * b; -} - - -void BH_Vec4iMulAdd(const int *a, - const int *b, - const int *c, - int *out) -{ - out[0] = a[0] * b[0] + c[0]; - out[1] = a[1] * b[1] + c[1]; - out[2] = a[2] * b[2] + c[2]; - out[3] = a[3] * b[3] + c[3]; -} - - -void BH_Vec4iNegate(const int *in, - int *out) -{ - out[0] = -in[0]; - out[1] = -in[1]; - out[2] = -in[2]; - out[3] = -in[3]; -} - - -void BH_Vec4iMin(const int *a, - const int *b, - int *out) -{ - if (a[0] < b[0]) out[0] = a[0]; else out[0] = b[0]; - if (a[1] < b[1]) out[1] = a[1]; else out[1] = b[1]; - if (a[2] < b[2]) out[2] = a[2]; else out[2] = b[2]; - if (a[3] < b[3]) out[3] = a[3]; else out[3] = b[3]; -} - - -void BH_Vec4iMax(const int *a, - const int *b, - int *out) -{ - if (a[0] > b[0]) out[0] = a[0]; else out[0] = b[0]; - if (a[1] > b[1]) out[1] = a[1]; else out[1] = b[1]; - if (a[2] > b[2]) out[2] = a[2]; else out[2] = b[2]; - if (a[3] > b[3]) out[3] = a[3]; else out[3] = b[3]; -} - - -void BH_Vec3iAdd(const int *a, - const int *b, - int *out) -{ - out[0] = a[0] + b[0]; - out[1] = a[1] + b[1]; - out[2] = a[2] + b[2]; -} - - -void BH_Vec3iSub(const int *a, - const int *b, - int *out) -{ - out[0] = a[0] - b[0]; - out[1] = a[1] - b[1]; - out[2] = a[2] - b[2]; -} - - -void BH_Vec3iMul(const int *a, - const int *b, - int *out) -{ - out[0] = a[0] * b[0]; - out[1] = a[1] * b[1]; - out[2] = a[2] * b[2]; -} - - -void BH_Vec3iScale(const int *a, - int b, - int *out) -{ - out[0] = a[0] * b; - out[1] = a[1] * b; - out[2] = a[2] * b; -} - - -void BH_Vec3iMulAdd(const int *a, - const int *b, - const int *c, - int *out) -{ - out[0] = a[0] * b[0] + c[0]; - out[1] = a[1] * b[1] + c[1]; - out[2] = a[2] * b[2] + c[2]; -} - - -void BH_Vec3iNegate(const int *in, - int *out) -{ - out[0] = -in[0]; - out[1] = -in[1]; - out[2] = -in[2]; -} - - -void BH_Vec3iMin(const int *a, - const int *b, - int *out) -{ - if (a[0] < b[0]) out[0] = a[0]; else out[0] = b[0]; - if (a[1] < b[1]) out[1] = a[1]; else out[1] = b[1]; - if (a[2] < b[2]) out[2] = a[2]; else out[2] = b[2]; -} - - -void BH_Vec3iMax(const int *a, - const int *b, - int *out) -{ - if (a[0] > b[0]) out[0] = a[0]; else out[0] = b[0]; - if (a[1] > b[1]) out[1] = a[1]; else out[1] = b[1]; - if (a[2] > b[2]) out[2] = a[2]; else out[2] = b[2]; -} - - -void BH_Vec2iAdd(const int *a, - const int *b, - int *out) -{ - out[0] = a[0] + b[0]; - out[1] = a[1] + b[1]; -} - - -void BH_Vec2iSub(const int *a, - const int *b, - int *out) -{ - out[0] = a[0] - b[0]; - out[1] = a[1] - b[1]; -} - - -void BH_Vec2iMul(const int *a, - const int *b, - int *out) -{ - out[0] = a[0] * b[0]; - out[1] = a[1] * b[1]; -} - - -void BH_Vec2iScale(const int *a, - int b, - int *out) -{ - out[0] = a[0] * b; - out[1] = a[1] * b; -} - - -void BH_Vec2iMulAdd(const int *a, - const int *b, - const int *c, - int *out) -{ - out[0] = a[0] * b[0] + c[0]; - out[1] = a[1] * b[1] + c[1]; -} - - -void BH_Vec2iNegate(const int *in, - int *out) -{ - out[0] = -in[0]; - out[1] = -in[1]; -} - - -void BH_Vec2iMin(const int *a, - const int *b, - int *out) -{ - if (a[0] < b[0]) out[0] = a[0]; else out[0] = b[0]; - if (a[1] < b[1]) out[1] = a[1]; else out[1] = b[1]; -} - - -void BH_Vec2iMax(const int *a, - const int *b, - int *out) -{ - if (a[0] > b[0]) out[0] = a[0]; else out[0] = b[0]; - if (a[1] > b[1]) out[1] = a[1]; else out[1] = b[1]; -} - - -void BH_Quat4fIdentity(float *out) -{ - static const float ident[4] = {0.0f, 0.0f, 0.0f, 1.0f}; - memcpy(out, ident, sizeof(ident)); -} - - -void BH_Quat4fConjugate(const float *in, - float *out) -{ - out[0] = -in[0]; - out[1] = -in[1]; - out[2] = -in[2]; - out[3] = in[3]; -} - - -void BH_Quat4fInverse(const float *in, - float *out) -{ - float dot; - - dot = BH_Vec4fDot(in, in); - BH_Quat4fConjugate(in, out); - BH_Quat4fScale(out, 1.0f / dot, out); -} - - -void BH_Quat4fMul(const float *a, - const float *b, - float *out) -{ - float tmp1[4], tmp2[4], tmp3[4]; - float w; - - w = a[3] * b[3] - BH_Vec3fDot(a, b); - BH_Vec4fScale(a, b[3], tmp1); - BH_Vec4fScale(b, a[3], tmp2); - BH_Vec3fCross(a, b, tmp3); - BH_Vec4fAdd(tmp1, tmp2, out); - BH_Vec4fAdd(tmp3, out, out); - out[3] = w; -} - - -void BH_Quat4fSlerp(const float *a, - const float *b, - float t, - float *out) -{ - float angle, denom; - float from[4], to[4]; - - angle = acos(BH_Vec4fDot(a, b)); - if (angle == 0.0f) - { - BH_Vec4fLerp(a, b, t, out); - return; - } - - denom = 1.0f / sin(angle); - BH_Vec4fScale(a, sin((1 - t) * angle) * denom, from); - BH_Vec4fScale(b, sin(t * angle) * denom, to); - BH_Vec4fAdd(from, to, out); -} - - -void BH_Quat4fFromEuler(float roll, - float pitch, - float yaw, - float *out) -{ - float cr, cp, cy, sr, sp, sy; - - cr = cos(roll / 2.0f); - cp = cos(pitch / 2.0f); - cy = cos(yaw / 2.0f); - sr = sin(roll / 2.0f); - sp = sin(pitch / 2.0f); - sy = sin(yaw / 2.0f); - - out[0] = sr * cp * cy - cr * sp * sy; - out[1] = cr * sp * cy + sr * cp * sy; - out[2] = cr * cp * sy - sr * sp * cy; - out[3] = cr * cp * cy + sr * sp * sy; -} - - -void BH_Quat4fFromAxis(const float *axis, - float angle, - float *out) -{ - float c, s; - - c = cos(angle / 2.0f); - s = sin(angle / 2.0f); - - out[0] = axis[0] * s; - out[1] = axis[1] * s; - out[2] = axis[2] * s; - out[3] = c; -} - - -void BH_Quat4fToEuler(const float *in, - float *roll, - float *pitch, - float *yaw) -{ - float ww, xw, yw, zw, xx, xy, xz, yy, yz, zz, angle; - - xx = in[0] * in[0]; - xy = in[0] * in[1]; - xz = in[0] * in[2]; - xw = in[0] * in[3]; - yy = in[1] * in[1]; - yz = in[1] * in[2]; - yw = in[1] * in[3]; - zz = in[2] * in[2]; - zw = in[2] * in[3]; - ww = in[3] * in[3]; - - angle = 2.0f * (yw - xz); - if (angle > 1.0f) - angle = 1.0f; - if (angle < -1.0f) - angle = -1.0f; - - *pitch = asin(angle); - - if (*pitch == (M_PI / 2.0f)) - { - *roll = 0.0f; - *yaw = -2.0f * atan2(in[0], in[3]); - } - else if (*pitch == (M_PI / -2.0f)) - { - *roll = 0.0f; - *yaw = 2.0f * atan2(in[0], in[3]); - } - else - { - *roll = atan2(2.0f * (xw + yz), ww - xx - yy + zz); - *yaw = atan2(2.0f * (zw + xy), ww + xx - yy - zz); - } -} - - -void BH_Quat4fToAxis(const float *in, - float *axis, - float *angle) -{ - *angle = 2.0f * acos(in[3]); - - if (*angle == 0.0f) - { - axis[0] = 1.0f; - axis[1] = 0.0f; - axis[2] = 0.0f; - } - else - { - float tmp; - - tmp = sqrt(1.0f - in[3] * in[3]); - axis[0] = in[0] / tmp; - axis[1] = in[1] / tmp; - axis[2] = in[2] / tmp; - } -} - - -void BH_Quat4fToMat4f(const float *in, - float *out) -{ - float xx, xy, xz, xw, yy, yz, yw, zz, zw; - - xx = in[0] * in[0]; - xy = in[0] * in[1]; - xz = in[0] * in[2]; - xw = in[0] * in[3]; - yy = in[1] * in[1]; - yz = in[1] * in[2]; - yw = in[1] * in[3]; - zz = in[2] * in[2]; - zw = in[2] * in[3]; - - BH_Mat4fIdentity(out); - out[0] = 1.0f - 2.0f * (yy + zz); - out[1] = 2.0f * (xy + zw); - out[2] = 2.0f * (xz - yw); - out[4] = 2.0f * (xy - zw); - out[5] = 1.0f - 2.0f * (xx + zz); - out[6] = 2.0f * (yz + xw); - out[8] = 2.0f * (xz + yw); - out[9] = 2.0f * (yz - xw); - out[10] = 1.0f - 2.0f * (xx + yy); -} - - -void BH_Mat4fIdentity(float *out) -{ - const float ident[16] = - { - 1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 1.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f - }; - - memcpy(out, ident, sizeof(ident)); -} - - -void BH_Mat4fAdd(const float *a, - const float *b, - float *out) -{ - BH_Vec4fAdd(&a[0], &b[0], &out[0]); - BH_Vec4fAdd(&a[4], &b[4], &out[4]); - BH_Vec4fAdd(&a[8], &b[8], &out[8]); - BH_Vec4fAdd(&a[12], &b[12], &out[12]); -} - - -void BH_Mat4fSub(const float *a, - const float *b, - float *out) -{ - BH_Vec4fSub(&a[0], &b[0], &out[0]); - BH_Vec4fSub(&a[4], &b[4], &out[4]); - BH_Vec4fSub(&a[8], &b[8], &out[8]); - BH_Vec4fSub(&a[12], &b[12], &out[12]); -} - - -void BH_Mat4fMul(const float *a, - const float *b, - float *out) -{ - float tmp[16], row[4]; - - row[0] = row[1] = row[2] = row[3] = b[0]; BH_Vec4fMul(&a[0], row, &tmp[0]); - row[0] = row[1] = row[2] = row[3] = b[1]; BH_Vec4fMulAdd(&a[4], row, &tmp[0], &tmp[0]); - row[0] = row[1] = row[2] = row[3] = b[2]; BH_Vec4fMulAdd(&a[8], row, &tmp[0], &tmp[0]); - row[0] = row[1] = row[2] = row[3] = b[3]; BH_Vec4fMulAdd(&a[12], row, &tmp[0], &tmp[0]); - - row[0] = row[1] = row[2] = row[3] = b[4]; BH_Vec4fMul(&a[0], row, &tmp[4]); - row[0] = row[1] = row[2] = row[3] = b[5]; BH_Vec4fMulAdd(&a[4], row, &tmp[4], &tmp[4]); - row[0] = row[1] = row[2] = row[3] = b[6]; BH_Vec4fMulAdd(&a[8], row, &tmp[4], &tmp[4]); - row[0] = row[1] = row[2] = row[3] = b[7]; BH_Vec4fMulAdd(&a[12], row, &tmp[4], &tmp[4]); - - row[0] = row[1] = row[2] = row[3] = b[8]; BH_Vec4fMul(&a[0], row, &tmp[8]); - row[0] = row[1] = row[2] = row[3] = b[9]; BH_Vec4fMulAdd(&a[4], row, &tmp[8], &tmp[8]); - row[0] = row[1] = row[2] = row[3] = b[10]; BH_Vec4fMulAdd(&a[8], row, &tmp[8], &tmp[8]); - row[0] = row[1] = row[2] = row[3] = b[11]; BH_Vec4fMulAdd(&a[12], row, &tmp[8], &tmp[8]); - - row[0] = row[1] = row[2] = row[3] = b[12]; BH_Vec4fMul(&a[0], row, &tmp[12]); - row[0] = row[1] = row[2] = row[3] = b[13]; BH_Vec4fMulAdd(&a[4], row, &tmp[12], &tmp[12]); - row[0] = row[1] = row[2] = row[3] = b[14]; BH_Vec4fMulAdd(&a[8], row, &tmp[12], &tmp[12]); - row[0] = row[1] = row[2] = row[3] = b[15]; BH_Vec4fMulAdd(&a[12], row, &tmp[12], &tmp[12]); - - memcpy(out, tmp, sizeof(tmp)); -} - - -void BH_Mat4fScale(const float *a, - float b, - float *out) -{ - BH_Vec4fScale(&a[0], b, &out[0]); - BH_Vec4fScale(&a[4], b, &out[4]); - BH_Vec4fScale(&a[8], b, &out[8]); - BH_Vec4fScale(&a[12], b, &out[12]); -} - - -void BH_Mat4fTranspose(const float *in, - float *out) -{ - float tmp[16]; - - tmp[0] = in[0]; tmp[4] = in[1]; tmp[8] = in[2]; tmp[12] = in[3]; - tmp[1] = in[4]; tmp[5] = in[5]; tmp[9] = in[6]; tmp[13] = in[7]; - tmp[2] = in[8]; tmp[6] = in[9]; tmp[10] = in[10]; tmp[14] = in[11]; - tmp[3] = in[12]; tmp[7] = in[13]; tmp[11] = in[14]; tmp[15] = in[15]; - - memcpy(out, tmp, sizeof(tmp)); -} - - -float BH_Mat4fTrace(const float *in) -{ - return in[0] + in[5] + in[10] + in[15]; -} - - -float BH_Mat4fDet(const float *in) -{ - float a, b, c, d, e, f, result; - - a = in[2] * in[7] - in[3] * in[6]; - b = in[2] * in[11] - in[3] * in[10]; - c = in[2] * in[15] - in[3] * in[14]; - d = in[6] * in[11] - in[7] * in[10]; - e = in[6] * in[15] - in[7] * in[14]; - f = in[10] * in[15] - in[11] * in[14]; - - result = 0.0f; - result += in[0] * (in[5] * f - in[9] * e + in[13] * d); - result -= in[4] * (in[1] * f - in[9] * c + in[13] * b); - result += in[8] * (in[1] * e - in[5] * c + in[13] * a); - result -= in[12] * (in[1] * d - in[5] * b + in[9] * a); - - return result; -} - - -int BH_Mat4fInverse(const float *in, - float *out) -{ - float a, b, c, d, e, f, det; - float tmp[16]; - - a = in[2] * in[7] - in[3] * in[6]; - b = in[2] * in[11] - in[3] * in[10]; - c = in[2] * in[15] - in[3] * in[14]; - d = in[6] * in[11] - in[7] * in[10]; - e = in[6] * in[15] - in[7] * in[14]; - f = in[10] * in[15] - in[11] * in[14]; - - tmp[0] = (in[5] * f - in[9] * e + in[13] * d); - tmp[1] = -(in[1] * f - in[9] * c + in[13] * b); - tmp[2] = (in[1] * e - in[5] * c + in[13] * a); - tmp[3] = -(in[1] * d - in[5] * b + in[9] * a); - - det = 0.0f; - det += in[0] * tmp[0]; - det += in[4] * tmp[1]; - det += in[8] * tmp[2]; - det += in[12] * tmp[3]; - - if (det == 0.0f) - return BH_ERROR; - - tmp[4] = -(in[4] * f - in[8] * e + in[12] * d); - tmp[5] = (in[0] * f - in[8] * c + in[12] * b); - tmp[6] = -(in[0] * e - in[4] * c + in[12] * a); - tmp[7] = (in[0] * d - in[4] * b + in[8] * a); - - a = in[1] * in[7] - in[3] * in[5]; - b = in[1] * in[11] - in[3] * in[9]; - c = in[1] * in[15] - in[3] * in[13]; - d = in[5] * in[11] - in[7] * in[9]; - e = in[5] * in[15] - in[7] * in[13]; - f = in[9] * in[15] - in[11] * in[13]; - - tmp[8] = (in[4] * f - in[8] * e + in[12] * d); - tmp[9] = -(in[0] * f - in[8] * c + in[12] * b); - tmp[10] = (in[0] * e - in[4] * c + in[12] * a); - tmp[11] = -(in[0] * d - in[4] * b + in[8] * a); - - a = in[1] * in[6] - in[2] * in[5]; - b = in[1] * in[10] - in[2] * in[9]; - c = in[1] * in[14] - in[2] * in[13]; - d = in[5] * in[10] - in[6] * in[9]; - e = in[5] * in[14] - in[6] * in[13]; - f = in[9] * in[14] - in[10] * in[13]; - - tmp[12] = -(in[4] * f - in[8] * e + in[12] * d); - tmp[13] = (in[0] * f - in[8] * c + in[12] * b); - tmp[14] = -(in[0] * e - in[4] * c + in[12] * a); - tmp[15] = (in[0] * d - in[4] * b + in[8] * a); - - BH_Mat4fScale(tmp, 1.0f / det, out); - return BH_OK; -} - - -void BH_Mat4fFromScale(float x, - float y, - float z, - float *out) -{ - BH_Mat4fIdentity(out); - out[0] = x; - out[5] = y; - out[10] = z; -} - - -void BH_Mat4fFromTranslation(float x, - float y, - float z, - float *out) -{ - BH_Mat4fIdentity(out); - out[12] = x; - out[13] = y; - out[14] = z; -} - - -void BH_Mat4fFromRotationX(float angle, - float *out) -{ - float c, s; - - c = cos(angle); - s = sin(angle); - - BH_Mat4fIdentity(out); - out[5] = c; - out[6] = s; - out[9] = -s; - out[10] = c; -} - - -void BH_Mat4fFromRotationY(float angle, - float *out) -{ - float c, s; - - c = cos(angle); - s = sin(angle); - - BH_Mat4fIdentity(out); - out[0] = c; - out[2] = -s; - out[8] = s; - out[10] = c; -} - - -void BH_Mat4fFromRotationZ(float angle, - float *out) -{ - float c, s; - - c = cos(angle); - s = sin(angle); - - BH_Mat4fIdentity(out); - out[0] = c; - out[1] = s; - out[4] = -s; - out[5] = c; -} - - -void BH_Mat4fFromAxis(const float *axis, - float angle, - float *out) -{ - float x, y, z, length; - float c, s, moc, xx, xy, xz, yy, yz, zz; - - length = BH_Vec3fLength(axis); - BH_Mat4fIdentity(out); - - if (length == 0.0f) - return; - - x = axis[0] / length; - y = axis[1] / length; - z = axis[2] / length; - - c = cos(angle); - s = sin(angle); - moc = 1.0f - c; - - xx = x * x; - xy = x * y; - xz = x * z; - yy = y * y; - yz = y * z; - zz = z * z; - - out[0] = c + xx * moc; - out[1] = xy * moc + z * s; - out[2] = xz * moc - y * s; - - out[4] = xy * moc - z * s; - out[5] = c + yy * moc; - out[6] = yz * moc + x * s; - - out[8] = xz * moc + y * s; - out[9] = yz * moc - x * s; - out[10] = c + zz * moc; -} - - -void BH_Mat4fFromEuler(float roll, - float pitch, - float yaw, - float *out) -{ - float rs, rc, ys, yc, ps, pc; - - rs = sin(roll); - rc = cos(roll); - ps = sin(pitch); - pc = cos(pitch); - ys = sin(yaw); - yc = cos(yaw); - - BH_Mat4fIdentity(out); - out[0] = pc * yc; - out[1] = pc * ys; - out[2] = -ps; - out[4] = ps * rs * yc - rc * ys; - out[5] = ps * rs * ys + rc * yc; - out[6] = pc * rs; - out[8] = rs * ys + ps * rc * yc; - out[9] = ps * rc * ys - rs * yc; - out[10] = pc * rc; -} - - -void BH_Mat4fFromQuat4f(const float *in, - float *out) -{ - BH_Quat4fToMat4f(in, out); -} - - -void BH_Mat4fFromOrtho(float xMin, - float xMax, - float yMin, - float yMax, - float zMin, - float zMax, - float *out) -{ - float dx, dy, dz; - - dx = xMax - xMin; - dy = yMax - yMin; - dz = zMax - zMin; - - BH_Mat4fIdentity(out); - - out[0] = 2.0f / dx; - out[5] = 2.0f / dy; - out[10] = -2.0f / dz; - out[12] = -(xMax + xMin) / dx; - out[13] = -(yMax + yMin) / dy; - out[14] = -(zMax + zMin) / dz; -} - - -void BH_Mat4fFromFrustum(float fov, - float aspect, - float zMin, - float zMax, - float *out) -{ - float t, dz; - - dz = zMax - zMin; - t = tanf(fov / 2.0f); - - BH_Mat4fIdentity(out); - - out[0] = 1.0f / (aspect * t); - out[5] = 1.0f / t; - out[10] = -(zMax + zMin) / dz; - out[11] = -1.0f; - out[14] = -(2.0f * zMax * zMin) / dz; - out[15] = 0.0f; -} - - -void BH_Mat4fFromLookAt(const float *pos, - const float *at, - const float *up, - float *out) -{ - float cdir[3], cright[3], cup[3]; - - BH_Vec3fSub(pos, at, cdir); - BH_Vec3fNormal(cdir, cdir); - BH_Vec3fCross(up, cdir, cright); - BH_Vec3fNormal(cright, cright); - BH_Vec3fCross(cdir, cright, cup); - - out[0] = cright[0]; - out[1] = cup[0]; - out[2] = cdir[0]; - out[3] = 0.0f; - - out[4] = cright[1]; - out[5] = cup[1]; - out[6] = cdir[1]; - out[7] = 0.0f; - - out[8] = cright[2]; - out[9] = cup[2]; - out[10] = cdir[2]; - out[11] = 0.0f; - - out[12] = -BH_Vec3fDot(cright, pos); - out[13] = -BH_Vec3fDot(cup, pos); - out[14] = -BH_Vec3fDot(cdir, pos); - out[15] = 1.0f; -} - - -void BH_Mat4fApplyVec4f(const float *a, - const float *b, - float *out) -{ - float tmp[4], row[4]; - - row[0] = row[1] = row[2] = row[3] = b[0]; BH_Vec4fMul(&a[0], row, tmp); - row[0] = row[1] = row[2] = row[3] = b[1]; BH_Vec4fMulAdd(&a[4], row, tmp, tmp); - row[0] = row[1] = row[2] = row[3] = b[2]; BH_Vec4fMulAdd(&a[8], row, tmp, tmp); - row[0] = row[1] = row[2] = row[3] = b[3]; BH_Vec4fMulAdd(&a[12], row, tmp, tmp); - - memcpy(out, tmp, sizeof(tmp)); -} - - -void BH_Mat4fApplyVec3f(const float *a, - const float *b, - float *out) -{ - float tmp[4], row[4]; - - row[0] = row[1] = row[2] = row[3] = b[0]; BH_Vec4fMul(&a[0], row, tmp); - row[0] = row[1] = row[2] = row[3] = b[1]; BH_Vec4fMulAdd(&a[4], row, tmp, tmp); - row[0] = row[1] = row[2] = row[3] = b[2]; BH_Vec4fMulAdd(&a[8], row, tmp, tmp); - row[0] = row[1] = row[2] = row[3] = 1.0f; BH_Vec4fMulAdd(&a[12], row, tmp, tmp); - - memcpy(out, tmp, sizeof(float) * 3); -} - - -void BH_Mat3fIdentity(float *out) -{ - static const float ident[9] = - { - 1.0f, 0.0f, 0.0f, - 0.0f, 1.0f, 0.0f, - 0.0f, 0.0f, 1.0f - }; - - memcpy(out, ident, sizeof(ident)); -} - - -void BH_Mat3fAdd(const float *a, - const float *b, - float *out) -{ - BH_Vec3fAdd(&a[0], &b[0], &out[0]); - BH_Vec3fAdd(&a[3], &b[3], &out[3]); - BH_Vec3fAdd(&a[6], &b[6], &out[6]); -} - - -void BH_Mat3fSub(const float *a, - const float *b, - float *out) -{ - BH_Vec3fSub(&a[0], &b[0], &out[0]); - BH_Vec3fSub(&a[3], &b[3], &out[3]); - BH_Vec3fSub(&a[6], &b[6], &out[6]); -} - - -void BH_Mat3fMul(const float *a, - const float *b, - float *out) -{ - float tmp[9], row[3]; - - row[0] = row[1] = row[2] = b[0]; BH_Vec3fMul(&a[0], row, &tmp[0]); - row[0] = row[1] = row[2] = b[1]; BH_Vec3fMulAdd(&a[3], row, &tmp[0], &tmp[0]); - row[0] = row[1] = row[2] = b[2]; BH_Vec3fMulAdd(&a[6], row, &tmp[0], &tmp[0]); - - row[0] = row[1] = row[2] = b[3]; BH_Vec3fMul(&a[0], row, &tmp[3]); - row[0] = row[1] = row[2] = b[4]; BH_Vec3fMulAdd(&a[3], row, &tmp[3], &tmp[3]); - row[0] = row[1] = row[2] = b[5]; BH_Vec3fMulAdd(&a[6], row, &tmp[3], &tmp[3]); - - row[0] = row[1] = row[2] = b[6]; BH_Vec3fMul(&a[0], row, &tmp[6]); - row[0] = row[1] = row[2] = b[7]; BH_Vec3fMulAdd(&a[3], row, &tmp[6], &tmp[6]); - row[0] = row[1] = row[2] = b[8]; BH_Vec3fMulAdd(&a[6], row, &tmp[6], &tmp[6]); - - memcpy(out, tmp, sizeof(tmp)); -} - - -void BH_Mat3fScale(const float *a, - float b, - float *out) -{ - BH_Vec3fScale(&a[0], b, &out[0]); - BH_Vec3fScale(&a[3], b, &out[3]); - BH_Vec3fScale(&a[6], b, &out[6]); -} - - -void BH_Mat3fTranspose(const float *in, - float *out) -{ - float tmp[9]; - - tmp[0] = in[0]; tmp[3] = in[1]; tmp[6] = in[2]; - tmp[1] = in[3]; tmp[4] = in[4]; tmp[7] = in[5]; - tmp[2] = in[6]; tmp[5] = in[7]; tmp[8] = in[8]; - - memcpy(out, tmp, sizeof(tmp)); -} - - -float BH_Mat3fTrace(const float *in) -{ - return in[0] + in[4] + in[8]; -} - - -float BH_Mat3fDet(const float *in) -{ - float a, b, c, result; - - a = in[4] * in[8] - in[7] * in[5]; - b = in[1] * in[8] - in[7] * in[2]; - c = in[1] * in[5] - in[4] * in[2]; - - result = 0.0f; - result += in[0] * a; - result -= in[3] * b; - result += in[6] * c; - - return result; -} - - -int BH_Mat3fInverse(const float *in, - float *out) -{ - float a, b, c, det; - float tmp[16]; - - a = in[4] * in[8] - in[7] * in[5]; - b = in[1] * in[8] - in[7] * in[2]; - c = in[1] * in[5] - in[4] * in[2]; - - tmp[0] = a; - tmp[1] = -b; - tmp[2] = c; - - det = 0.0f; - det += in[0] * tmp[0]; - det += in[3] * tmp[1]; - det += in[6] * tmp[2]; - - if (det == 0.0f) - return BH_ERROR; - - a = in[3] * in[8] - in[6] * in[5]; - b = in[0] * in[8] - in[6] * in[2]; - c = in[0] * in[5] - in[3] * in[2]; - - tmp[3] = -a; - tmp[4] = b; - tmp[5] = -c; - - a = in[3] * in[7] - in[6] * in[4]; - b = in[0] * in[7] - in[6] * in[1]; - c = in[0] * in[4] - in[3] * in[1]; - - tmp[6] = a; - tmp[7] = -b; - tmp[8] = c; - - BH_Mat3fScale(tmp, 1.0f / det, out); - return BH_OK; -} - - -void BH_Mat3fFromScale(float x, - float y, - float *out) -{ - BH_Mat3fIdentity(out); - out[0] = x; - out[4] = y; -} - - -void BH_Mat3fFromTranslation(float x, - float y, - float *out) -{ - BH_Mat3fIdentity(out); - out[6] = x; - out[7] = y; -} - - -void BH_Mat3fFromRotation(float angle, - float *out) -{ - float c, s; - - c = cos(angle); - s = sin(angle); - - BH_Mat3fIdentity(out); - out[0] = c; - out[1] = s; - out[3] = -s; - out[4] = c; -} - - -void BH_Mat3fApplyVec3f(float *a, - float *b, - float *out) -{ - float tmp[3], row[3]; - - row[0] = row[1] = row[2] = b[0]; BH_Vec3fMul(&a[0], row, tmp); - row[0] = row[1] = row[2] = b[1]; BH_Vec3fMulAdd(&a[3], row, tmp, tmp); - row[0] = row[1] = row[2] = b[2]; BH_Vec3fMulAdd(&a[6], row, tmp, tmp); - - memcpy(out, tmp, sizeof(tmp)); -} - - -void BH_Mat3fApplyVec2f(float *a, - float *b, - float *out) -{ - float tmp[3], row[3]; - - row[0] = row[1] = row[2] = b[0]; BH_Vec3fMul(&a[0], row, tmp); - row[0] = row[1] = row[2] = b[1]; BH_Vec3fMulAdd(&a[3], row, tmp, tmp); - row[0] = row[1] = row[2] = 1.0f; BH_Vec3fMulAdd(&a[6], row, tmp, tmp); - - memcpy(out, tmp, sizeof(float) * 2); -} diff --git a/src/posix/File.c b/src/posix/File.c new file mode 100644 index 0000000..f8ee089 --- /dev/null +++ b/src/posix/File.c @@ -0,0 +1,406 @@ +#include + +#include +#include +#include +#include +#include +#include + + +typedef struct BH_File +{ + char *path; + int mode; + int flags; + int handle; +} BH_File; + + +static int BH_FileInfo(BH_File *file, + size_t *size, + const char **name); + + +static int BH_FileInit(BH_File *file, + const char *path); + + +static int BH_FileDestroy(BH_File *file); + + +static int BH_FileOpen(BH_File *file, + int *mode); + + +static int BH_FileClose(BH_File *file); + + +static int BH_FileRead(BH_File *file, + char *data, + size_t *size); + + +static int BH_FileWrite(BH_File *file, + const char *data, + size_t *size); + + +static int BH_FilePeek(BH_File* file, + char *data, + size_t *size); + + +static int BH_FileFlush(BH_File *file); + + +static int BH_FileSeek(BH_File *file, + int64_t *pos, + int *dir); + + +static int BH_FileTell(BH_File *file, + int64_t *pos); + + +static int BH_FileSize(BH_File *file, + int64_t *size); + + +static int BH_FileFlags(BH_File *file); + + +static int BH_FileClear(BH_File *file); + + +static int BH_FileInfo(BH_File *file, + size_t *size, + const char **name) +{ + static const char classname[] = BH_FILE_CLASSNAME; + + if (size) + *size = sizeof(*file); + if (name) + *name = classname; + return BH_OK; +} + + +static int BH_FileInit(BH_File *file, + const char *path) +{ + /* Check if path is valid */ + if (!path) + return BH_ERROR; + + /* Duplicate path string and initialize the file struct */ + file->path = strdup(path); + file->mode = 0; + file->handle = -1; + file->flags = 0; + + return BH_OK; +} + + +static int BH_FileDestroy(BH_File *file) +{ + /* Close the file handle on destruction */ + if (file->handle != -1) + BH_FileClose(file); + + /* Free path string */ + free(file->path); + + return BH_OK; +} + + +static int BH_FileOpenFlags(int mode) +{ + int flags = 0; + + /* Determine read/write flags */ + if ((mode & BH_IO_READWRITE) == BH_IO_READWRITE) + flags |= O_RDWR; + else if (mode & BH_IO_WRITE) + flags |= O_WRONLY; + else if (mode & BH_IO_READ) + flags |= O_RDONLY; + else + return -1; + + /* Check if existing file should be opened */ + if (!(mode & BH_IO_EXIST)) + { + flags |= O_CREAT; + + /* Check if file should be created */ + if (mode & BH_IO_CREATE) + flags |= O_EXCL; + } + + /* Check if file should be opened in append mode */ + if (mode & BH_IO_APPEND) + flags |= O_APPEND; + + /* Check if file should be truncated */ + if (mode & BH_IO_TRUNCATE) + flags |= O_TRUNC; + + return flags; +} + + +static int BH_FileOpen(BH_File *file, + int *mode) +{ + static const mode_t open_mode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); + int flags; + + /* If file is already opened - report error */ + if (file->handle != -1) + return BH_ERROR; + + /* Determine file open flags */ + flags = BH_FileOpenFlags(*mode); + if (flags == -1) + return BH_ERROR; + + /* Open the file */ + file->handle = open(file->path, flags, open_mode); + if (file->handle == -1) + return BH_ERROR; + + return BH_OK; +} + + +static int BH_FileClose(BH_File *file) +{ + /* If file is closed - report error */ + if (file->handle == -1) + return BH_ERROR; + + /* Close and reset the file handle */ + close(file->handle); + file->handle = -1; + + return BH_OK; +} + + +static int BH_FileRead(BH_File *file, + char *data, + size_t *size) +{ + ssize_t readed; + + /* Check if file is open */ + if (file->handle == -1) + goto error; + + /* Read data from the file */ + readed = read(file->handle, data, *size); + if (readed < 0) + goto error; + + /* Check for EOF condition */ + if (readed > 0) + file->flags &= ~BH_IO_FLAG_EOF; + else + file->flags |= BH_IO_FLAG_EOF; + + *size = readed; + return BH_OK; + +error: + file->flags |= BH_IO_FLAG_ERROR; + return BH_ERROR; +} + + +static int BH_FileWrite(BH_File *file, + const char *data, + size_t *size) +{ + ssize_t written; + + /* Check if file is open */ + if (file->handle == -1) + goto error; + + /* Write data to the file */ + written = write(file->handle, data, *size); + if (written < 0) + goto error; + + /* Check for EOF condition */ + if (!written) + file->flags |= BH_IO_FLAG_EOF; + else + file->flags &= ~BH_IO_FLAG_EOF; + + *size = written; + return BH_OK; + +error: + file->flags |= BH_IO_FLAG_ERROR; + return BH_ERROR; +} + + +static int BH_FilePeek(BH_File *file, + char *data, + size_t *size) +{ + int64_t position; + int direction; + + /* Check if file is open */ + if (file->handle == -1) + goto error; + + /* Read data from the file */ + if (BH_FileRead(file, data, size)) + goto error; + + /* Backtrack by the read amount */ + position = -((int64_t)*size); + direction = BH_IO_SEEK_CUR; + if (BH_FileSeek(file, &position, &direction)) + goto error; + + return BH_OK; + +error: + file->flags |= BH_IO_FLAG_ERROR; + return BH_ERROR; +} + + +static int BH_FileFlush(BH_File *file) +{ + /* Check if file is open */ + if (file->handle == -1) + { + file->flags |= BH_IO_FLAG_ERROR; + return BH_ERROR; + } + + /* Flush the buffers */ + fsync(file->handle); + return BH_OK; +} + + +static int BH_FileSeek(BH_File *file, + int64_t *pos, + int *dir) +{ + /* Check if file is open */ + if (file->handle == -1) + goto error; + + /* Seek to the specified position */ + if (lseek(file->handle, *pos, *dir) == -1) + goto error; + + return BH_OK; + +error: + file->flags |= BH_IO_FLAG_ERROR; + return BH_ERROR; +} + + +static int BH_FileTell(BH_File *file, + int64_t *pos) +{ + /* Check if file is open */ + if (file->handle == -1) + goto error; + + /* Get current offset in the file */ + if ((*pos = lseek(file->handle, 0, SEEK_CUR)) == -1) + goto error; + + return BH_OK; + +error: + file->flags |= BH_IO_FLAG_ERROR; + return BH_ERROR; +} + + +static int BH_FileSize(BH_File *file, + int64_t *size) +{ + struct stat sb; + + /* Check if file is open */ + if (file->handle == -1) + goto error; + + /* Get file size from the OS */ + if (fstat(file->handle, &sb)) + goto error; + + *size = sb.st_size; + return BH_OK; + +error: + file->flags |= BH_IO_FLAG_ERROR; + return BH_ERROR; +} + + +static int BH_FileFlags(BH_File *file) +{ + /* If file handle is valid - append IO_OPEN flag */ + if (file->handle != -1) + return file->flags | BH_IO_FLAG_OPEN; + + return file->flags; +} + + +static int BH_FileClear(BH_File *file) +{ + /* Clear IO_ERROR flag */ + file->flags &= ~BH_IO_FLAG_ERROR; + return BH_OK; +} + + +static int BH_FileCallback(BH_File *file, + int type, + void *arg1, + void *arg2) +{ + switch (type) + { + case BH_IO_INFO_CB: return BH_FileInfo(file, (size_t *)arg1, (const char **)arg2); + case BH_IO_INIT_CB: return BH_FileInit(file, (const char *)arg1); + case BH_IO_DESTROY_CB: return BH_FileDestroy(file); + case BH_IO_OPEN_CB: return BH_FileOpen(file, (int *)arg1); + case BH_IO_CLOSE_CB: return BH_FileClose(file); + case BH_IO_READ_CB: return BH_FileRead(file, (char *)arg1, (size_t *)arg2); + case BH_IO_WRITE_CB: return BH_FileWrite(file, (const char *)arg1, (size_t *)arg2); + case BH_IO_PEEK_CB: return BH_FilePeek(file, (char *)arg1, (size_t *)arg2); + case BH_IO_FLUSH_CB: return BH_FileFlush(file); + case BH_IO_SEEK_CB: return BH_FileSeek(file, (int64_t *)arg1, (int *)arg2); + case BH_IO_TELL_CB: return BH_FileTell(file, (int64_t *)arg1); + case BH_IO_SIZE_CB: return BH_FileSize(file, (int64_t *)arg1); + case BH_IO_FLAGS_CB: return BH_FileFlags(file); + case BH_IO_CLEAR_CB: return BH_FileClear(file); + default: return BH_NOIMPL; + } +} + + +BH_IO *BH_FileNew(const char *path) +{ + return BH_IONew((BH_IOCallback)BH_FileCallback, (void *)path); +} diff --git a/src/posix/file.c b/src/posix/file.c deleted file mode 100644 index 87a5a2b..0000000 --- a/src/posix/file.c +++ /dev/null @@ -1,405 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - - -typedef struct BH_File -{ - char *path; - int mode; - int flags; - int handle; -} BH_File; - - -static int BH_FileInfo(BH_File *file, - size_t *size, - const char **name); - - -static int BH_FileInit(BH_File *file, - const char *path); - - -static int BH_FileDestroy(BH_File *file); - - -static int BH_FileOpen(BH_File *file, - int *mode); - - -static int BH_FileClose(BH_File *file); - - -static int BH_FileRead(BH_File *file, - char *data, - size_t *size); - - -static int BH_FileWrite(BH_File *file, - const char *data, - size_t *size); - - -static int BH_FilePeek(BH_File* file, - char *data, - size_t *size); - - -static int BH_FileFlush(BH_File *file); - - -static int BH_FileSeek(BH_File *file, - int64_t *pos, - int *dir); - - -static int BH_FileTell(BH_File *file, - int64_t *pos); - - -static int BH_FileSize(BH_File *file, - int64_t *size); - - -static int BH_FileFlags(BH_File *file); - - -static int BH_FileClear(BH_File *file); - - -static int BH_FileInfo(BH_File *file, - size_t *size, - const char **name) -{ - static const char classname[] = BH_FILE_CLASSNAME; - - if (size) - *size = sizeof(*file); - if (name) - *name = classname; - return BH_OK; -} - - -static int BH_FileInit(BH_File *file, - const char *path) -{ - /* Check if path is valid */ - if (!path) - return BH_ERROR; - - /* Duplicate path string and initialize the file struct */ - file->path = strdup(path); - file->mode = 0; - file->handle = -1; - file->flags = 0; - - return BH_OK; -} - - -static int BH_FileDestroy(BH_File *file) -{ - /* Close the file handle on destruction */ - if (file->handle != -1) - BH_FileClose(file); - - /* Free path string */ - free(file->path); - - return BH_OK; -} - - -static int BH_FileOpenFlags(int mode) -{ - int flags = 0; - - /* Determine read/write flags */ - if ((mode & BH_IO_READWRITE) == BH_IO_READWRITE) - flags |= O_RDWR; - else if (mode & BH_IO_WRITE) - flags |= O_WRONLY; - else if (mode & BH_IO_READ) - flags |= O_RDONLY; - else - return -1; - - /* Check if existing file should be opened */ - if (!(mode & BH_IO_EXIST)) - { - flags |= O_CREAT; - - /* Check if file should be created */ - if (mode & BH_IO_CREATE) - flags |= O_EXCL; - } - - /* Check if file should be opened in append mode */ - if (mode & BH_IO_APPEND) - flags |= O_APPEND; - - /* Check if file should be truncated */ - if (mode & BH_IO_TRUNCATE) - flags |= O_TRUNC; - - return flags; -} - - -static int BH_FileOpen(BH_File *file, - int *mode) -{ - static const mode_t open_mode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); - int flags; - - /* If file is already opened - report error */ - if (file->handle != -1) - return BH_ERROR; - - /* Determine file open flags */ - flags = BH_FileOpenFlags(*mode); - if (flags == -1) - return BH_ERROR; - - /* Open the file */ - file->handle = open(file->path, flags, open_mode); - if (file->handle == -1) - return BH_ERROR; - - return BH_OK; -} - - -static int BH_FileClose(BH_File *file) -{ - /* If file is closed - report error */ - if (file->handle == -1) - return BH_ERROR; - - /* Close and reset the file handle */ - close(file->handle); - file->handle = -1; - - return BH_OK; -} - - -static int BH_FileRead(BH_File *file, - char *data, - size_t *size) -{ - ssize_t readed; - - /* Check if file is open */ - if (file->handle == -1) - goto error; - - /* Read data from the file */ - readed = read(file->handle, data, *size); - if (readed < 0) - goto error; - - /* Check for EOF condition */ - if (readed > 0) - file->flags &= ~BH_IO_FLAG_EOF; - else - file->flags |= BH_IO_FLAG_EOF; - - *size = readed; - return BH_OK; - -error: - file->flags |= BH_IO_FLAG_ERROR; - return BH_ERROR; -} - - -static int BH_FileWrite(BH_File *file, - const char *data, - size_t *size) -{ - ssize_t written; - - /* Check if file is open */ - if (file->handle == -1) - goto error; - - /* Write data to the file */ - written = write(file->handle, data, *size); - if (written < 0) - goto error; - - /* Check for EOF condition */ - if (!written) - file->flags |= BH_IO_FLAG_EOF; - else - file->flags &= ~BH_IO_FLAG_EOF; - - *size = written; - return BH_OK; - -error: - file->flags |= BH_IO_FLAG_ERROR; - return BH_ERROR; -} - - -static int BH_FilePeek(BH_File *file, - char *data, - size_t *size) -{ - int64_t position; - int direction; - - /* Check if file is open */ - if (file->handle == -1) - goto error; - - /* Read data from the file */ - if (BH_FileRead(file, data, size)) - goto error; - - /* Backtrack by the read amount */ - position = -((int64_t)*size); - direction = BH_IO_SEEK_CUR; - if (BH_FileSeek(file, &position, &direction)) - goto error; - - return BH_OK; - -error: - file->flags |= BH_IO_FLAG_ERROR; - return BH_ERROR; -} - - -static int BH_FileFlush(BH_File *file) -{ - /* Check if file is open */ - if (file->handle == -1) - { - file->flags |= BH_IO_FLAG_ERROR; - return BH_ERROR; - } - - /* Flush the buffers */ - fsync(file->handle); - return BH_OK; -} - - -static int BH_FileSeek(BH_File *file, - int64_t *pos, - int *dir) -{ - /* Check if file is open */ - if (file->handle == -1) - goto error; - - /* Seek to the specified position */ - if (lseek(file->handle, *pos, *dir) == -1) - goto error; - - return BH_OK; - -error: - file->flags |= BH_IO_FLAG_ERROR; - return BH_ERROR; -} - - -static int BH_FileTell(BH_File *file, - int64_t *pos) -{ - /* Check if file is open */ - if (file->handle == -1) - goto error; - - /* Get current offset in the file */ - if ((*pos = lseek(file->handle, 0, SEEK_CUR)) == -1) - goto error; - - return BH_OK; - -error: - file->flags |= BH_IO_FLAG_ERROR; - return BH_ERROR; -} - - -static int BH_FileSize(BH_File *file, - int64_t *size) -{ - struct stat sb; - - /* Check if file is open */ - if (file->handle == -1) - goto error; - - /* Get file size from the OS */ - if (fstat(file->handle, &sb)) - goto error; - - *size = sb.st_size; - return BH_OK; - -error: - file->flags |= BH_IO_FLAG_ERROR; - return BH_ERROR; -} - - -static int BH_FileFlags(BH_File *file) -{ - /* If file handle is valid - append IO_OPEN flag */ - if (file->handle != -1) - return file->flags | BH_IO_FLAG_OPEN; - - return file->flags; -} - - -static int BH_FileClear(BH_File *file) -{ - /* Clear IO_ERROR flag */ - file->flags &= ~BH_IO_FLAG_ERROR; - return BH_OK; -} - - -static int BH_FileCallback(BH_File *file, - int type, - void *arg1, - void *arg2) -{ - switch (type) - { - case BH_IO_INFO_CB: return BH_FileInfo(file, (size_t *)arg1, (const char **)arg2); - case BH_IO_INIT_CB: return BH_FileInit(file, (const char *)arg1); - case BH_IO_DESTROY_CB: return BH_FileDestroy(file); - case BH_IO_OPEN_CB: return BH_FileOpen(file, (int *)arg1); - case BH_IO_CLOSE_CB: return BH_FileClose(file); - case BH_IO_READ_CB: return BH_FileRead(file, (char *)arg1, (size_t *)arg2); - case BH_IO_WRITE_CB: return BH_FileWrite(file, (const char *)arg1, (size_t *)arg2); - case BH_IO_PEEK_CB: return BH_FilePeek(file, (char *)arg1, (size_t *)arg2); - case BH_IO_FLUSH_CB: return BH_FileFlush(file); - case BH_IO_SEEK_CB: return BH_FileSeek(file, (int64_t *)arg1, (int *)arg2); - case BH_IO_TELL_CB: return BH_FileTell(file, (int64_t *)arg1); - case BH_IO_SIZE_CB: return BH_FileSize(file, (int64_t *)arg1); - case BH_IO_FLAGS_CB: return BH_FileFlags(file); - case BH_IO_CLEAR_CB: return BH_FileClear(file); - default: return BH_NOIMPL; - } -} - - -BH_IO *BH_FileNew(const char *path) -{ - return BH_IONew((BH_IOCallback)BH_FileCallback, (void *)path); -} diff --git a/src/queue.c b/src/queue.c deleted file mode 100755 index 656d27d..0000000 --- a/src/queue.c +++ /dev/null @@ -1,209 +0,0 @@ -#include -#include -#include - - -struct BH_Queue -{ - void **data; - size_t size; - size_t head; - size_t tail; - size_t capacity; -}; - - -static void BH_QueueInit(BH_Queue *queue) -{ - memset(queue, 0, sizeof(*queue)); -} - - -static void BH_QueueDestroy(BH_Queue *queue) -{ - if (queue->capacity) - free(queue->data); -} - - -static void BH_QueueCopy(BH_Queue *dest, - BH_Queue *src) -{ - void *iter; - - /* Iterate over old queue and insert data into new queue */ - iter = BH_QueueIterNext(src, NULL); - while (iter) - { - BH_QueueInsert(dest, BH_QueueIterValue(iter)); - iter = BH_QueueIterNext(src, iter); - } -} - - -BH_Queue *BH_QueueNew(void) -{ - BH_Queue *result; - - result = malloc(sizeof(*result)); - if (result) - BH_QueueInit(result); - - return result; -} - - -void BH_QueueFree(BH_Queue *queue) -{ - BH_QueueDestroy(queue); - free(queue); -} - - -void BH_QueueClear(BH_Queue *queue) -{ - queue->head = 0; - queue->tail = 0; - queue->size = 0; -} - - -int BH_QueueReserve(BH_Queue *queue, - size_t size) -{ - BH_Queue other; - - /* New capacity should be great or equal to current size */ - if (size < queue->size) - size = queue->size; - - /* Catch malloc overflow */ - if (size >= ((size_t)-1) / sizeof(void *)) - return BH_OOM; - - /* Prevent same size memory reallocation */ - if (size == queue->capacity) - return BH_OK; - - /* Prepare new empty queue */ - BH_QueueInit(&other); - if (size) - { - /* Allocate new capacity for the queue */ - other.data = malloc(size * sizeof(void *)); - other.capacity = size; - if (!other.data) - return BH_OOM; - - /* Iterate over old queue and insert data into new queue */ - BH_QueueCopy(&other, queue); - } - - /* If old queue had allocated data - free it */ - if (queue->capacity) - free(queue->data); - - /* Copy queue information */ - *queue = other; - return BH_OK; -} - - -int BH_QueueInsert(BH_Queue *queue, - void *value) -{ - /* Check if queue can contain new element */ - if (queue->size + 1 > queue->capacity) - { - size_t capacity; - - /* Check for capacity overflow and reserve capacity */ - capacity = (queue->capacity) ? (queue->capacity * 2) : (16); - if (capacity < queue->capacity || BH_QueueReserve(queue, capacity)) - return BH_OOM; - } - - /* Increase queue size and advance tail index */ - queue->data[queue->tail] = value; - queue->size++; - if (++queue->tail >= queue->capacity) - queue->tail = 0; - - return BH_OK; -} - - -void BH_QueueRemove(BH_Queue *queue) -{ - /* Do nothing if queue is empty */ - if (!queue->size) - return; - - /* Decrease queue size and advance head index */ - queue->size--; - if (++queue->head >= queue->capacity) - queue->head = 0; -} - - -int BH_QueueFront(BH_Queue *queue, void **value) -{ - /* Do nothing if queue is empty */ - if (!queue->size) - return BH_ERROR; - - /* Return front element */ - *value = queue->data[queue->head]; - return BH_OK; -} - - -int BH_QueueEmpty(BH_Queue *queue) -{ - return !queue->size; -} - - -size_t BH_QueueSize(BH_Queue *queue) -{ - return queue->size; -} - - -size_t BH_QueueCapacity(BH_Queue *queue) -{ - return queue->capacity; -} - - -void *BH_QueueIterNext(BH_Queue *queue, - void *iter) -{ - void **element = (void **)iter; - - /* Do nothing if queue is empty */ - if (!queue->size) - return NULL; - - /* Advance or set iterator */ - if (element) - { - element++; - if (element == queue->data + queue->capacity) - element = queue->data; - - /* Check if we reached the end */ - if (element == queue->data + queue->tail) - return NULL; - } - else - element = queue->data + queue->head; - - return element; -} - - -void *BH_QueueIterValue(void *iter) -{ - return *(void **)iter; -} diff --git a/src/win32/File.c b/src/win32/File.c new file mode 100644 index 0000000..3cb1972 --- /dev/null +++ b/src/win32/File.c @@ -0,0 +1,405 @@ +#include +#include +#include +#include + + +typedef struct BH_File +{ + char *path; + int mode; + int flags; + HANDLE handle; +} BH_File; + + +static int BH_FileInfo(BH_File *file, + size_t *size, + const char **name); + + +static int BH_FileInit(BH_File *file, + const char *path); + + +static int BH_FileDestroy(BH_File *file); + + +static int BH_FileOpen(BH_File *file, + int *mode); + + +static int BH_FileClose(BH_File *file); + + +static int BH_FileRead(BH_File *file, + char *data, + size_t *size); + + +static int BH_FileWrite(BH_File *file, + const char *data, + size_t *size); + + +static int BH_FilePeek(BH_File* file, + char *data, + size_t *size); + + +static int BH_FileFlush(BH_File *file); + + +static int BH_FileSeek(BH_File *file, + int64_t *pos, + int *dir); + + +static int BH_FileTell(BH_File *file, + int64_t *pos); + + +static int BH_FileSize(BH_File *file, + int64_t *size); + + +static int BH_FileFlags(BH_File *file); + + +static int BH_FileClear(BH_File *file); + + +static int BH_FileInfo(BH_File *file, + size_t *size, + const char **name) +{ + static const char classname[] = BH_FILE_CLASSNAME; + + if (size) + *size = sizeof(*file); + if (name) + *name = classname; + + return BH_OK; +} + + +static int BH_FileInit(BH_File *file, + const char *path) +{ + /* Check if path is valid */ + if (!path) + return BH_ERROR; + + /* Duplicate path string and initialize the file struct */ + file->path = strdup(path); + file->mode = 0; + file->handle = INVALID_HANDLE_VALUE; + file->flags = 0; + + return BH_OK; +} + + +static int BH_FileDestroy(BH_File *file) +{ + /* Close the file handle on destruction */ + if (file->handle != INVALID_HANDLE_VALUE) + BH_FileClose(file); + + /* Free path string */ + free(file->path); + + return BH_OK; +} + + +static int BH_FileOpen(BH_File *file, + int *mode) +{ + DWORD access = 0, how = 0; + + /* Check if file is already openned */ + if (file->handle != INVALID_HANDLE_VALUE) + return BH_ERROR; + + /* Determine read/write access flags */ + if (*mode & BH_IO_READ) + access |= GENERIC_READ; + if (*mode & BH_IO_WRITE) + access |= GENERIC_WRITE; + + if (!access) + return BH_ERROR; + + /* Determine open mode flags */ + if (*mode & BH_IO_TRUNCATE) + { + switch (*mode & (BH_IO_CREATE | BH_IO_EXIST)) + { + case 0: how = CREATE_ALWAYS; break; + case BH_IO_CREATE: how = CREATE_NEW; break; + case BH_IO_EXIST: how = TRUNCATE_EXISTING; break; + default: return BH_ERROR; + } + } + else + { + switch (*mode & (BH_IO_CREATE | BH_IO_EXIST)) + { + case 0: how = OPEN_ALWAYS; break; + case BH_IO_CREATE: how = CREATE_NEW; break; + case BH_IO_EXIST: how = OPEN_EXISTING; break; + default: return BH_ERROR; + } + } + + /* Save mode that we are in and open file */ + file->mode = *mode; + file->handle = CreateFileA(file->path, access, FILE_SHARE_READ, NULL, how, FILE_ATTRIBUTE_NORMAL, NULL); + + if (file->handle == INVALID_HANDLE_VALUE) + return BH_ERROR; + + /* Truncate file if needed */ + if (*mode & BH_IO_TRUNCATE) + SetEndOfFile(file->handle); + + return BH_OK; +} + + +static int BH_FileClose(BH_File *file) +{ + /* If file is opened - close it */ + if (file->handle == INVALID_HANDLE_VALUE) + return BH_ERROR; + + /* Reset handle and mode values */ + CloseHandle(file->handle); + file->handle = INVALID_HANDLE_VALUE; + file->mode = 0; + return BH_OK; +} + + +static int BH_FileRead(BH_File *file, + char *data, + size_t *size) +{ + DWORD readed; + + /* Check if file is opened */ + if (file->handle == INVALID_HANDLE_VALUE) + goto error; + + /* Read data from the file */ + if (!ReadFile(file->handle, data, (DWORD)*size, &readed, NULL)) + goto error; + + /* Check if we reached end of file */ + if (!readed) + file->flags |= BH_IO_FLAG_EOF; + else + file->flags &= ~BH_IO_FLAG_EOF; + + *size = readed; + return BH_OK; + +error: + file->flags |= BH_IO_FLAG_ERROR; + return BH_ERROR; +} + + +static int BH_FileWrite(BH_File *file, + const char *data, + size_t *size) +{ + DWORD written; + + /* Check if file is opened */ + if (file->handle == INVALID_HANDLE_VALUE) + goto error; + + /* Adjust current position in the file to the end */ + if (file->mode & BH_IO_APPEND) + { + LARGE_INTEGER position; + + position.QuadPart = 0; + if (!SetFilePointerEx(file->handle, position, NULL, FILE_END)) + goto error; + } + + /* Write data to the file */ + if (!WriteFile(file->handle, data, (DWORD)*size, &written, NULL)) + goto error; + + /* Check for end of file */ + if (!written) + file->flags |= BH_IO_FLAG_EOF; + else + file->flags &= ~BH_IO_FLAG_EOF; + + *size = written; + return BH_OK; + +error: + file->flags |= BH_IO_FLAG_ERROR; + return BH_ERROR; +} + + +static int BH_FilePeek(BH_File *file, + char *data, + size_t *size) +{ + int64_t position; + int direction; + + /* Read data from the file */ + if (BH_FileRead(file, data, size)) + return BH_ERROR; + + /* Backtrack by the read amount */ + position = -((int64_t)*size); + direction = BH_IO_SEEK_CUR; + if (BH_FileSeek(file, &position, &direction)) + return BH_ERROR; + + return BH_OK; +} + + +static int BH_FileFlush(BH_File *file) +{ + /* Check if file is opened */ + if (file->handle == INVALID_HANDLE_VALUE) + goto error; + + /* Flush OS buffers */ + FlushFileBuffers(file->handle); + return BH_OK; + +error: + file->flags |= BH_IO_FLAG_ERROR; + return BH_ERROR; +} + + +static int BH_FileSeek(BH_File *file, + int64_t *pos, + int *dir) +{ + LARGE_INTEGER position; + + /* Check if file is opened */ + if (file->handle == INVALID_HANDLE_VALUE) + goto error; + + /* Set read/write position in the file */ + position.QuadPart = *pos; + if (!SetFilePointerEx(file->handle, position, NULL, *dir)) + goto error; + + return BH_OK; + +error: + file->flags |= BH_IO_FLAG_ERROR; + return BH_ERROR; +} + + +static int BH_FileTell(BH_File *file, + int64_t *pos) +{ + LARGE_INTEGER dummy, position; + + /* Check if file is opened */ + if (file->handle == INVALID_HANDLE_VALUE) + goto error; + + /* Readback current position in the file */ + dummy.QuadPart = 0; + if (!SetFilePointerEx(file->handle, dummy, &position, BH_IO_SEEK_CUR)) + goto error; + + *pos = position.QuadPart; + return BH_OK; + +error: + file->flags |= BH_IO_FLAG_ERROR; + return BH_ERROR; +} + + +static int BH_FileSize(BH_File *file, + int64_t *size) +{ + LARGE_INTEGER dummy; + + /* Check if file is opened */ + if (file->handle == INVALID_HANDLE_VALUE) + goto error; + + /* Get current file size */ + if (!GetFileSizeEx(file->handle, &dummy)) + goto error; + + *size = dummy.QuadPart; + return BH_OK; + +error: + file->flags |= BH_IO_FLAG_ERROR; + return BH_ERROR; +} + + +static int BH_FileFlags(BH_File *file) +{ + /* If file handle is valid - append IO_OPEN flag */ + if (file->handle != INVALID_HANDLE_VALUE) + return file->flags | BH_IO_FLAG_OPEN; + return file->flags; +} + + +static int BH_FileClear(BH_File *file) +{ + /* Clear IO_ERROR flag */ + file->flags &= ~BH_IO_FLAG_ERROR; + return BH_OK; +} + + +static int BH_FileCallback(BH_File *file, + int type, + void *arg1, + void *arg2) +{ + switch (type) + { + case BH_IO_INFO_CB: return BH_FileInfo(file, (size_t *)arg1, (const char **)arg2); + case BH_IO_INIT_CB: return BH_FileInit(file, (const char *)arg1); + case BH_IO_DESTROY_CB: return BH_FileDestroy(file); + case BH_IO_OPEN_CB: return BH_FileOpen(file, (int *)arg1); + case BH_IO_CLOSE_CB: return BH_FileClose(file); + case BH_IO_READ_CB: return BH_FileRead(file, (char *)arg1, (size_t *)arg2); + case BH_IO_WRITE_CB: return BH_FileWrite(file, (const char *)arg1, (size_t *)arg2); + case BH_IO_PEEK_CB: return BH_FilePeek(file, (char *)arg1, (size_t *)arg2); + case BH_IO_FLUSH_CB: return BH_FileFlush(file); + case BH_IO_SEEK_CB: return BH_FileSeek(file, (int64_t *)arg1, (int *)arg2); + case BH_IO_TELL_CB: return BH_FileTell(file, (int64_t *)arg1); + case BH_IO_SIZE_CB: return BH_FileSize(file, (int64_t *)arg1); + case BH_IO_FLAGS_CB: return BH_FileFlags(file); + case BH_IO_CLEAR_CB: return BH_FileClear(file); + default: return BH_NOIMPL; + } +} + + +BH_IO *BH_FileNew(const char *path) +{ + return BH_IONew((BH_IOCallback)BH_FileCallback, (void *)path); +} diff --git a/src/win32/file.c b/src/win32/file.c deleted file mode 100644 index bed16ab..0000000 --- a/src/win32/file.c +++ /dev/null @@ -1,405 +0,0 @@ -#include -#include -#include -#include - - -typedef struct BH_File -{ - char *path; - int mode; - int flags; - HANDLE handle; -} BH_File; - - -static int BH_FileInfo(BH_File *file, - size_t *size, - const char **name); - - -static int BH_FileInit(BH_File *file, - const char *path); - - -static int BH_FileDestroy(BH_File *file); - - -static int BH_FileOpen(BH_File *file, - int *mode); - - -static int BH_FileClose(BH_File *file); - - -static int BH_FileRead(BH_File *file, - char *data, - size_t *size); - - -static int BH_FileWrite(BH_File *file, - const char *data, - size_t *size); - - -static int BH_FilePeek(BH_File* file, - char *data, - size_t *size); - - -static int BH_FileFlush(BH_File *file); - - -static int BH_FileSeek(BH_File *file, - int64_t *pos, - int *dir); - - -static int BH_FileTell(BH_File *file, - int64_t *pos); - - -static int BH_FileSize(BH_File *file, - int64_t *size); - - -static int BH_FileFlags(BH_File *file); - - -static int BH_FileClear(BH_File *file); - - -static int BH_FileInfo(BH_File *file, - size_t *size, - const char **name) -{ - static const char classname[] = BH_FILE_CLASSNAME; - - if (size) - *size = sizeof(*file); - if (name) - *name = classname; - - return BH_OK; -} - - -static int BH_FileInit(BH_File *file, - const char *path) -{ - /* Check if path is valid */ - if (!path) - return BH_ERROR; - - /* Duplicate path string and initialize the file struct */ - file->path = strdup(path); - file->mode = 0; - file->handle = INVALID_HANDLE_VALUE; - file->flags = 0; - - return BH_OK; -} - - -static int BH_FileDestroy(BH_File *file) -{ - /* Close the file handle on destruction */ - if (file->handle != INVALID_HANDLE_VALUE) - BH_FileClose(file); - - /* Free path string */ - free(file->path); - - return BH_OK; -} - - -static int BH_FileOpen(BH_File *file, - int *mode) -{ - DWORD access = 0, how = 0; - - /* Check if file is already openned */ - if (file->handle != INVALID_HANDLE_VALUE) - return BH_ERROR; - - /* Determine read/write access flags */ - if (*mode & BH_IO_READ) - access |= GENERIC_READ; - if (*mode & BH_IO_WRITE) - access |= GENERIC_WRITE; - - if (!access) - return BH_ERROR; - - /* Determine open mode flags */ - if (*mode & BH_IO_TRUNCATE) - { - switch (*mode & (BH_IO_CREATE | BH_IO_EXIST)) - { - case 0: how = CREATE_ALWAYS; break; - case BH_IO_CREATE: how = CREATE_NEW; break; - case BH_IO_EXIST: how = TRUNCATE_EXISTING; break; - default: return BH_ERROR; - } - } - else - { - switch (*mode & (BH_IO_CREATE | BH_IO_EXIST)) - { - case 0: how = OPEN_ALWAYS; break; - case BH_IO_CREATE: how = CREATE_NEW; break; - case BH_IO_EXIST: how = OPEN_EXISTING; break; - default: return BH_ERROR; - } - } - - /* Save mode that we are in and open file */ - file->mode = *mode; - file->handle = CreateFileA(file->path, access, FILE_SHARE_READ, NULL, how, FILE_ATTRIBUTE_NORMAL, NULL); - - if (file->handle == INVALID_HANDLE_VALUE) - return BH_ERROR; - - /* Truncate file if needed */ - if (*mode & BH_IO_TRUNCATE) - SetEndOfFile(file->handle); - - return BH_OK; -} - - -static int BH_FileClose(BH_File *file) -{ - /* If file is opened - close it */ - if (file->handle == INVALID_HANDLE_VALUE) - return BH_ERROR; - - /* Reset handle and mode values */ - CloseHandle(file->handle); - file->handle = INVALID_HANDLE_VALUE; - file->mode = 0; - return BH_OK; -} - - -static int BH_FileRead(BH_File *file, - char *data, - size_t *size) -{ - DWORD readed; - - /* Check if file is opened */ - if (file->handle == INVALID_HANDLE_VALUE) - goto error; - - /* Read data from the file */ - if (!ReadFile(file->handle, data, (DWORD)*size, &readed, NULL)) - goto error; - - /* Check if we reached end of file */ - if (!readed) - file->flags |= BH_IO_FLAG_EOF; - else - file->flags &= ~BH_IO_FLAG_EOF; - - *size = readed; - return BH_OK; - -error: - file->flags |= BH_IO_FLAG_ERROR; - return BH_ERROR; -} - - -static int BH_FileWrite(BH_File *file, - const char *data, - size_t *size) -{ - DWORD written; - - /* Check if file is opened */ - if (file->handle == INVALID_HANDLE_VALUE) - goto error; - - /* Adjust current position in the file to the end */ - if (file->mode & BH_IO_APPEND) - { - LARGE_INTEGER position; - - position.QuadPart = 0; - if (!SetFilePointerEx(file->handle, position, NULL, FILE_END)) - goto error; - } - - /* Write data to the file */ - if (!WriteFile(file->handle, data, (DWORD)*size, &written, NULL)) - goto error; - - /* Check for end of file */ - if (!written) - file->flags |= BH_IO_FLAG_EOF; - else - file->flags &= ~BH_IO_FLAG_EOF; - - *size = written; - return BH_OK; - -error: - file->flags |= BH_IO_FLAG_ERROR; - return BH_ERROR; -} - - -static int BH_FilePeek(BH_File *file, - char *data, - size_t *size) -{ - int64_t position; - int direction; - - /* Read data from the file */ - if (BH_FileRead(file, data, size)) - return BH_ERROR; - - /* Backtrack by the read amount */ - position = -((int64_t)*size); - direction = BH_IO_SEEK_CUR; - if (BH_FileSeek(file, &position, &direction)) - return BH_ERROR; - - return BH_OK; -} - - -static int BH_FileFlush(BH_File *file) -{ - /* Check if file is opened */ - if (file->handle == INVALID_HANDLE_VALUE) - goto error; - - /* Flush OS buffers */ - FlushFileBuffers(file->handle); - return BH_OK; - -error: - file->flags |= BH_IO_FLAG_ERROR; - return BH_ERROR; -} - - -static int BH_FileSeek(BH_File *file, - int64_t *pos, - int *dir) -{ - LARGE_INTEGER position; - - /* Check if file is opened */ - if (file->handle == INVALID_HANDLE_VALUE) - goto error; - - /* Set read/write position in the file */ - position.QuadPart = *pos; - if (!SetFilePointerEx(file->handle, position, NULL, *dir)) - goto error; - - return BH_OK; - -error: - file->flags |= BH_IO_FLAG_ERROR; - return BH_ERROR; -} - - -static int BH_FileTell(BH_File *file, - int64_t *pos) -{ - LARGE_INTEGER dummy, position; - - /* Check if file is opened */ - if (file->handle == INVALID_HANDLE_VALUE) - goto error; - - /* Readback current position in the file */ - dummy.QuadPart = 0; - if (!SetFilePointerEx(file->handle, dummy, &position, BH_IO_SEEK_CUR)) - goto error; - - *pos = position.QuadPart; - return BH_OK; - -error: - file->flags |= BH_IO_FLAG_ERROR; - return BH_ERROR; -} - - -static int BH_FileSize(BH_File *file, - int64_t *size) -{ - LARGE_INTEGER dummy; - - /* Check if file is opened */ - if (file->handle == INVALID_HANDLE_VALUE) - goto error; - - /* Get current file size */ - if (!GetFileSizeEx(file->handle, &dummy)) - goto error; - - *size = dummy.QuadPart; - return BH_OK; - -error: - file->flags |= BH_IO_FLAG_ERROR; - return BH_ERROR; -} - - -static int BH_FileFlags(BH_File *file) -{ - /* If file handle is valid - append IO_OPEN flag */ - if (file->handle != INVALID_HANDLE_VALUE) - return file->flags | BH_IO_FLAG_OPEN; - return file->flags; -} - - -static int BH_FileClear(BH_File *file) -{ - /* Clear IO_ERROR flag */ - file->flags &= ~BH_IO_FLAG_ERROR; - return BH_OK; -} - - -static int BH_FileCallback(BH_File *file, - int type, - void *arg1, - void *arg2) -{ - switch (type) - { - case BH_IO_INFO_CB: return BH_FileInfo(file, (size_t *)arg1, (const char **)arg2); - case BH_IO_INIT_CB: return BH_FileInit(file, (const char *)arg1); - case BH_IO_DESTROY_CB: return BH_FileDestroy(file); - case BH_IO_OPEN_CB: return BH_FileOpen(file, (int *)arg1); - case BH_IO_CLOSE_CB: return BH_FileClose(file); - case BH_IO_READ_CB: return BH_FileRead(file, (char *)arg1, (size_t *)arg2); - case BH_IO_WRITE_CB: return BH_FileWrite(file, (const char *)arg1, (size_t *)arg2); - case BH_IO_PEEK_CB: return BH_FilePeek(file, (char *)arg1, (size_t *)arg2); - case BH_IO_FLUSH_CB: return BH_FileFlush(file); - case BH_IO_SEEK_CB: return BH_FileSeek(file, (int64_t *)arg1, (int *)arg2); - case BH_IO_TELL_CB: return BH_FileTell(file, (int64_t *)arg1); - case BH_IO_SIZE_CB: return BH_FileSize(file, (int64_t *)arg1); - case BH_IO_FLAGS_CB: return BH_FileFlags(file); - case BH_IO_CLEAR_CB: return BH_FileClear(file); - default: return BH_NOIMPL; - } -} - - -BH_IO *BH_FileNew(const char *path) -{ - return BH_IONew((BH_IOCallback)BH_FileCallback, (void *)path); -} diff --git a/test/src/TestAlgo.c b/test/src/TestAlgo.c new file mode 100644 index 0000000..b330ee7 --- /dev/null +++ b/test/src/TestAlgo.c @@ -0,0 +1,484 @@ +#include +#include +#include +#include + + +static int DBG_IntEqual(const void *lhs, + const void *rhs) +{ + return *(const int*)lhs - *(const int*)rhs; +} + + +static int DBG_VerifyPartition(size_t index, + int pivot, + int *array, + size_t size) +{ + size_t i; + + for (i = 0; i < index; i++) + if (array[i] >= pivot) + return -1; + + for (i = index; i < size; i++) + if (array[i] < pivot) + return -1; + + return 0; +} + + +static int DBG_VerifyHeap(int *array, + size_t size) +{ + size_t i, left, right; + + for (i = 0; i < size; i++) + { + left = i * 2 + 1; + right = i * 2 + 2; + + if (left < size && array[i] < array[left]) + return -1; + if (right < size && array[i] < array[right]) + return -1; + } + + return 0; +} + + +static int DBG_ReferenceRand(void) +{ + static uint32_t next = 2025; + next = next * 1103515245 + 12345; + return (next / 65536) % 32768; +} + + +static void DBG_ReferenceSort(int *array, + size_t size) +{ + size_t i, j; + int tmp; + + /* Reference sort is... buble sort! */ + for (i = 0; i < size; i++) + { + for (j = 1; j < size; j++) + { + if (array[j - 1] > array[j]) + { + tmp = array[j - 1]; + array[j - 1] = array[j]; + array[j] = tmp; + } + } + } +} + + +static void DBG_FillArrays(int *array, + int *reference, + size_t size, + int mask) +{ + size_t i; + int negate; + + /* Check if mask needs to be negated */ + negate = mask < 0; + if (negate) + mask = -mask; + + /* Fill the array */ + for (i = 0; i < size; ++i) + { + array[i] = DBG_ReferenceRand(); + + if (mask > 1) + array[i] = array[i] % mask; + + if (negate) + array[i] = -array[i]; + + if (reference) + reference[i] = array[i]; + } +} + + +static int CheckSort(void) +{ + size_t sizes[] = {1, 2, 3, 5, 11, 23, 41, 79, 163, 317, 0}, *size; + int reference[317], data[317]; + + /* Test empty array and one element arrays */ + data[0] = 1; data[1] = 2; data[2] = 3; + BH_Sort(data, 0, sizeof(int), DBG_IntEqual); + BH_VERIFY(data[0] == 1); + BH_VERIFY(data[1] == 2); + BH_VERIFY(data[2] == 3); + + BH_Sort(data, 1, sizeof(int), DBG_IntEqual); + BH_VERIFY(data[0] == 1); + BH_VERIFY(data[1] == 2); + BH_VERIFY(data[2] == 3); + + /* Test array against different sizes */ + for (size = sizes; *size; ++size) + { + DBG_FillArrays(data, reference, *size, 0); + DBG_ReferenceSort(reference, *size); + BH_Sort(data, *size, sizeof(int), DBG_IntEqual); + BH_VERIFY(memcmp(reference, data, *size * sizeof(int)) == 0); + } + + /* Test against negative values */ + for (size = sizes; *size; ++size) + { + DBG_FillArrays(data, reference, *size, -1); + DBG_ReferenceSort(reference, *size); + BH_Sort(data, *size, sizeof(int), DBG_IntEqual); + BH_VERIFY(memcmp(reference, data, *size * sizeof(int)) == 0); + } + + /* Test against duplicates */ + for (size = sizes; *size; ++size) + { + DBG_FillArrays(data, reference, *size, 4); + DBG_ReferenceSort(reference, *size); + BH_Sort(data, *size, sizeof(int), DBG_IntEqual); + BH_VERIFY(memcmp(reference, data, *size * sizeof(int)) == 0); + } + + return 0; +} + + +static int CheckPartition(void) +{ + size_t sizes[] = {1, 2, 3, 5, 11, 23, 41, 79, 163, 317, 0}, *size; + int reference[317], data[317], value, *pivot; + + /* Test empty array and one element array */ + data[0] = 1; data[1] = 2; data[2] = 3; + value = 0; + pivot = BH_Partition(&value, data, 0, sizeof(int), DBG_IntEqual); + BH_VERIFY(pivot != NULL); + BH_VERIFY(data[0] == 1); + BH_VERIFY(data[1] == 2); + BH_VERIFY(data[2] == 3); + + pivot = BH_Partition(&value, data, 1, sizeof(int), DBG_IntEqual); + BH_VERIFY(pivot == data); + BH_VERIFY(data[0] == 1); + BH_VERIFY(data[1] == 2); + BH_VERIFY(data[2] == 3); + + /* Test array against different sizes */ + for (size = sizes; *size; ++size) + { + DBG_FillArrays(data, reference, *size, 0); + value = 16384; + pivot = BH_Partition(&value, data, *size, sizeof(int), DBG_IntEqual); + BH_VERIFY(DBG_VerifyPartition(pivot - data, value, data, *size) == 0); + + DBG_ReferenceSort(data, *size); + DBG_ReferenceSort(reference, *size); + BH_VERIFY(memcmp(data, reference, *size * sizeof(int)) == 0); + } + + /* Test against negative values */ + for (size = sizes; *size; ++size) + { + DBG_FillArrays(data, reference, *size, -1); + value = -16384; + pivot = BH_Partition(&value, data, *size, sizeof(int), DBG_IntEqual); + BH_VERIFY(DBG_VerifyPartition(pivot - data, value, data, *size) == 0); + + DBG_ReferenceSort(data, *size); + DBG_ReferenceSort(reference, *size); + BH_VERIFY(memcmp(data, reference, *size * sizeof(int)) == 0); + } + + /* Test against duplicates */ + for (size = sizes; *size; ++size) + { + DBG_FillArrays(data, reference, *size, 4); + value = 2; + pivot = BH_Partition(&value, data, *size, sizeof(int), DBG_IntEqual); + BH_VERIFY(DBG_VerifyPartition(pivot - data, value, data, *size) == 0); + + DBG_ReferenceSort(data, *size); + DBG_ReferenceSort(reference, *size); + BH_VERIFY(memcmp(data, reference, *size * sizeof(int)) == 0); + } + + /* Test array against small pivots */ + for (size = sizes; *size; ++size) + { + DBG_FillArrays(data, reference, *size, 0); + value = -100; + pivot = BH_Partition(&value, data, *size, sizeof(int), DBG_IntEqual); + BH_VERIFY(DBG_VerifyPartition(pivot - data, value, data, *size) == 0); + + DBG_ReferenceSort(data, *size); + DBG_ReferenceSort(reference, *size); + BH_VERIFY(memcmp(data, reference, *size * sizeof(int)) == 0); + } + + /* Test array against large pivots */ + for (size = sizes; *size; ++size) + { + DBG_FillArrays(data, reference, *size, 0); + value = 65536; + pivot = BH_Partition(&value, data, *size, sizeof(int), DBG_IntEqual); + BH_VERIFY(DBG_VerifyPartition(pivot - data, value, data, *size) == 0); + + DBG_ReferenceSort(data, *size); + DBG_ReferenceSort(reference, *size); + BH_VERIFY(memcmp(data, reference, *size * sizeof(int)) == 0); + } + + /* Test array against different sizes (pivot inside the array) */ + for (size = sizes; *size; ++size) + { + DBG_FillArrays(data, reference, *size, 0); + value = data[0]; + pivot = BH_Partition(data, data, *size, sizeof(int), DBG_IntEqual); + BH_VERIFY(DBG_VerifyPartition(pivot - data, value, data, *size) == 0); + + DBG_ReferenceSort(data, *size); + DBG_ReferenceSort(reference, *size); + BH_VERIFY(memcmp(data, reference, *size * sizeof(int)) == 0); + } + + /* Test against negative values (pivot inside the array) */ + for (size = sizes; *size; ++size) + { + DBG_FillArrays(data, reference, *size, -1); + value = data[0]; + pivot = BH_Partition(data, data, *size, sizeof(int), DBG_IntEqual); + BH_VERIFY(DBG_VerifyPartition(pivot - data, value, data, *size) == 0); + + DBG_ReferenceSort(data, *size); + DBG_ReferenceSort(reference, *size); + BH_VERIFY(memcmp(data, reference, *size * sizeof(int)) == 0); + } + + /* Test against duplicates (pivot inside the array) */ + for (size = sizes; *size; ++size) + { + DBG_FillArrays(data, reference, *size, 4); + value = data[0]; + pivot = BH_Partition(data, data, *size, sizeof(int), DBG_IntEqual); + BH_VERIFY(DBG_VerifyPartition(pivot - data, value, data, *size) == 0); + + DBG_ReferenceSort(data, *size); + DBG_ReferenceSort(reference, *size); + BH_VERIFY(memcmp(data, reference, *size * sizeof(int)) == 0); + } + + /* Same data test */ + for (size = sizes; *size; ++size) + { + memset(data, 0, sizeof(int) * *size); + memset(reference, 0, sizeof(int) * *size); + value = data[*size - 1]; + pivot = BH_Partition(data + *size - 1, data, *size, sizeof(int), DBG_IntEqual); + BH_VERIFY(DBG_VerifyPartition(pivot - data, value, data, *size) == 0); + + DBG_ReferenceSort(data, *size); + DBG_ReferenceSort(reference, *size); + BH_VERIFY(memcmp(data, reference, *size * sizeof(int)) == 0); + } + + return 0; +} + + +static int CheckHeapMake(void) +{ + size_t sizes[] = {1, 2, 3, 5, 11, 23, 41, 79, 163, 317, 0}, *size; + int data[317]; + + /* Test empty array */ + data[0] = 1; data[1] = 2; data[2] = 3; + BH_HeapMake(data, 0, sizeof(int), DBG_IntEqual); + BH_VERIFY(data[0] == 1); + BH_VERIFY(data[1] == 2); + BH_VERIFY(data[2] == 3); + + /* Test array against different sizes */ + for (size = sizes; *size; ++size) + { + DBG_FillArrays(data, NULL, *size, 0); + BH_HeapMake(data, *size, sizeof(int), DBG_IntEqual); + BH_VERIFY(DBG_VerifyHeap(data, *size) == 0); + } + + /* Test array against negative values */ + for (size = sizes; *size; ++size) + { + DBG_FillArrays(data, NULL, *size, -1); + BH_HeapMake(data, *size, sizeof(int), DBG_IntEqual); + BH_VERIFY(DBG_VerifyHeap(data, *size) == 0); + } + + /* Test against duplicates */ + for (size = sizes; *size; ++size) + { + DBG_FillArrays(data, NULL, *size, 4); + BH_HeapMake(data, *size, sizeof(int), DBG_IntEqual); + BH_VERIFY(DBG_VerifyHeap(data, *size) == 0); + } + + return 0; +} + + +static int CheckHeapInsert(void) +{ + size_t sizes[] = {1, 2, 3, 5, 11, 23, 41, 79, 163, 317, 0}, *size; + int data[317], reference[317]; + + /* Test array against different sizes */ + for (size = sizes; *size; ++size) + { + size_t i; + DBG_FillArrays(data, reference, *size, 0); + for (i = 0; i < *size; ++i) + { + int value; + + value = data[i]; + BH_HeapInsert(&value, data, i, sizeof(int), DBG_IntEqual); + BH_VERIFY(DBG_VerifyHeap(data, i + 1) == 0); + } + + DBG_ReferenceSort(data, *size); + DBG_ReferenceSort(reference, *size); + BH_VERIFY(memcmp(data, reference, *size) == 0); + } + + /* Test array against different sizes (inplace)*/ + for (size = sizes; *size; ++size) + { + size_t i; + DBG_FillArrays(data, reference, *size, 0); + for (i = 0; i < *size; ++i) + { + BH_HeapInsert(NULL, data, i, sizeof(int), DBG_IntEqual); + BH_VERIFY(DBG_VerifyHeap(data, i + 1) == 0); + } + + DBG_ReferenceSort(data, *size); + DBG_ReferenceSort(reference, *size); + BH_VERIFY(memcmp(data, reference, *size) == 0); + } + + return 0; +} + + +static int CheckHeapRemove(void) +{ + size_t sizes[] = {1, 2, 3, 5, 11, 23, 41, 79, 163, 317, 0}, *size; + int data[317], reference[317]; + + /* Test array against different sizes */ + for (size = sizes; *size; ++size) + { + size_t i; + DBG_FillArrays(data, reference, *size, 0); + BH_HeapMake(data, *size, sizeof(int), DBG_IntEqual); + + for (i = *size; i > 0; i--) + { + BH_VERIFY(DBG_VerifyHeap(data, i) == 0); + BH_HeapRemove(data, i, sizeof(int), DBG_IntEqual); + } + + DBG_ReferenceSort(data, *size); + DBG_ReferenceSort(reference, *size); + BH_VERIFY(memcmp(data, reference, *size) == 0); + } + + return 0; +} + + +static int CheckHeapReplace(void) +{ + int data[11] = {1, 2, 3, 5, 11, 23, 41, 79, 163, 317, 0}; + int reference[11] = {1, 2, 3, 5, 11, 23, 41, 79, 163, 317, 0}; + int value; + + /* Prepare test arrays */ + BH_HeapMake(data, 10, sizeof(int), DBG_IntEqual); + BH_HeapMake(reference, 10, sizeof(int), DBG_IntEqual); + BH_VERIFY(DBG_VerifyHeap(data, 10) == 0); + BH_VERIFY(DBG_VerifyHeap(reference, 10) == 0); + + /* Verfify heap replace */ + value = 20; + BH_HeapReplace(&value, data, 10, sizeof(int), DBG_IntEqual); + BH_HeapRemove(reference, 10, sizeof(int), DBG_IntEqual); + BH_HeapInsert(&value, reference, 9, sizeof(int), DBG_IntEqual); + + BH_VERIFY(DBG_VerifyHeap(data, 10) == 0); + BH_VERIFY(DBG_VerifyHeap(reference, 10) == 0); + BH_Sort(data, 10, sizeof(int), DBG_IntEqual); + BH_Sort(reference, 10, sizeof(int), DBG_IntEqual); + BH_VERIFY(memcmp(data, reference, 10 * sizeof(int)) == 0); + + /* Verify heap replace on single element array */ + value = 400; + BH_HeapReplace(&value, data, 1, sizeof(int), DBG_IntEqual); + BH_HeapRemove(reference, 1, sizeof(int), DBG_IntEqual); + BH_HeapInsert(&value, reference, 0, sizeof(int), DBG_IntEqual); + + BH_VERIFY(DBG_VerifyHeap(data, 1) == 0); + BH_VERIFY(DBG_VerifyHeap(reference, 1) == 0); + BH_VERIFY(memcmp(data, reference, 1 * sizeof(int)) == 0); + + /* Prepare test arrays */ + BH_Sort(data, 10, sizeof(int), DBG_IntEqual); + BH_Sort(reference, 10, sizeof(int), DBG_IntEqual); + BH_HeapMake(data, 10, sizeof(int), DBG_IntEqual); + BH_HeapMake(reference, 10, sizeof(int), DBG_IntEqual); + BH_VERIFY(DBG_VerifyHeap(data, 10) == 0); + BH_VERIFY(DBG_VerifyHeap(reference, 10) == 0); + + data[10] = 1000; + value = 1000; + BH_HeapReplace(NULL, data, 10, sizeof(int), DBG_IntEqual); + BH_HeapRemove(reference, 10, sizeof(int), DBG_IntEqual); + BH_HeapInsert(&value, reference, 9, sizeof(int), DBG_IntEqual); + BH_VERIFY(DBG_VerifyHeap(data, 10) == 0); + BH_VERIFY(DBG_VerifyHeap(reference, 10) == 0); + BH_Sort(data, 10, sizeof(int), DBG_IntEqual); + BH_Sort(reference, 10, sizeof(int), DBG_IntEqual); + BH_VERIFY(memcmp(data, reference, 10 * sizeof(int)) == 0); + + return 0; +} + + +int main(int argc, char **argv) +{ + BH_UNUSED(argc); + BH_UNUSED(argv); + + BH_UnitAdd("Sort", CheckSort); + BH_UnitAdd("Partition", CheckPartition); + BH_UnitAdd("HeapMake", CheckHeapMake); + BH_UnitAdd("HeapInsert", CheckHeapInsert); + BH_UnitAdd("HeapRemove", CheckHeapRemove); + BH_UnitAdd("HeapReplace", CheckHeapReplace); + + return BH_UnitRun(); +} diff --git a/test/src/TestFile.c b/test/src/TestFile.c new file mode 100644 index 0000000..8fae14c --- /dev/null +++ b/test/src/TestFile.c @@ -0,0 +1,630 @@ +#include +#include +#include + + +#define FILENAME1 "bhfile1.dat" +#define FILENAME2 "bhfile2.dat" +#define FILENAME3 "bhfile3.dat" +#define FILENAME4 "bhfile4.dat" + + +/** + * Cleanup any files, that could be left from previous test runs. + */ +static void cleanup(void) +{ + remove(FILENAME1); + remove(FILENAME2); + remove(FILENAME3); + remove(FILENAME4); +} + + +/** + * Check for invalid arguments. + */ +static int checkNull(void) +{ + BH_IO *io; + + /* Check against NULL pointers */ + BH_VERIFY(BH_FileNew(NULL) == NULL); + BH_VERIFY(BH_IOClassname(NULL) == NULL); + BH_VERIFY(BH_IOOpen(NULL, 0) != BH_OK); + BH_VERIFY(BH_IOClose(NULL) != BH_OK); + BH_VERIFY(BH_IORead(NULL, NULL, 0, NULL) != BH_OK); + BH_VERIFY(BH_IOWrite(NULL, NULL, 0, NULL) != BH_OK); + BH_VERIFY(BH_IOPeek(NULL, NULL, 0, NULL) != BH_OK); + BH_VERIFY(BH_IOTell(NULL, NULL) != BH_OK); + BH_VERIFY(BH_IOSeek(NULL, 0, 0) != BH_OK); + BH_VERIFY(BH_IOFlush(NULL) != BH_OK); + BH_VERIFY(BH_IOSize(NULL, NULL) != BH_OK); + BH_VERIFY(BH_IOFlags(NULL) == BH_IO_FLAG_ERROR); + BH_VERIFY(BH_IOClear(NULL) == BH_OK); + BH_IOFree(NULL); + + /* Check against NULL pointers and valid IO object */ + BH_VERIFY((io = BH_FileNew(FILENAME1)) != NULL); + BH_VERIFY(strcmp(BH_IOClassname(io), BH_FILE_CLASSNAME) == 0); + BH_VERIFY(BH_IOOpen(io, 0) != BH_OK); + BH_VERIFY(BH_IOClose(io) != BH_OK); + BH_VERIFY(BH_IORead(io, NULL, 0, NULL) != BH_OK); + BH_VERIFY(BH_IOWrite(io, NULL, 0, NULL) != BH_OK); + BH_VERIFY(BH_IOPeek(io, NULL, 0, NULL) != BH_OK); + BH_VERIFY(BH_IOTell(io, NULL) != BH_OK); + BH_VERIFY(BH_IOSeek(io, 0, 0) != BH_OK); + BH_VERIFY(BH_IOFlush(io) != BH_OK); + BH_VERIFY(BH_IOSize(io, NULL) != BH_OK); + BH_VERIFY(BH_IOFlags(io) == BH_IO_FLAG_ERROR); + BH_VERIFY(BH_IOClear(io) == BH_OK); + BH_IOFree(io); + + return 0; +} + + +/** + * Check for normal mode. + */ +static int checkNormal(void) +{ + int64_t position; + char buffer[128]; + size_t actual; + BH_IO *io; + + /* Check operations for write only access */ + BH_VERIFY((io = BH_FileNew(FILENAME1)) != NULL); + BH_VERIFY(strcmp(BH_IOClassname(io), BH_FILE_CLASSNAME) == 0); + BH_VERIFY(BH_IOOpen(io, BH_IO_WRITE) == BH_OK); + BH_VERIFY(BH_IOFlags(io) & BH_IO_FLAG_OPEN); + + BH_VERIFY(BH_IOOpen(io, BH_IO_READ) != BH_OK); + + BH_VERIFY(BH_IOWrite(io, "1234567890", 10, &actual) == BH_OK); + BH_VERIFY(actual == 10); + + BH_VERIFY(BH_IOWrite(io, "1234567890", 10, &actual) == BH_OK); + BH_VERIFY(actual == 10); + + BH_VERIFY(BH_IOSeek(io, 10, BH_IO_SEEK_SET) == BH_OK); + BH_VERIFY(BH_IOWrite(io, "abcde", 5, &actual) == BH_OK); + BH_VERIFY(actual == 5); + + BH_VERIFY(BH_IOSeek(io, 0, BH_IO_SEEK_SET) == BH_OK); + BH_VERIFY(BH_IORead(io, buffer, 1, &actual) != BH_OK); + BH_VERIFY(BH_IOSeek(io, 0, BH_IO_SEEK_END) == BH_OK); + BH_VERIFY(BH_IOTell(io, &position) == BH_OK); + BH_VERIFY(position == 20); + BH_IOClose(io); + + /* Check operations for read only access */ + BH_VERIFY(BH_IOOpen(io, BH_IO_READ) == BH_OK); + BH_VERIFY(BH_IOFlags(io) & BH_IO_FLAG_OPEN); + BH_VERIFY(strcmp(BH_IOClassname(io), BH_FILE_CLASSNAME) == 0); + BH_VERIFY(BH_IORead(io, buffer, 10, &actual) == BH_OK); + BH_VERIFY(actual == 10); + BH_VERIFY(memcmp(buffer, "1234567890", 10) == 0); + + BH_VERIFY(BH_IORead(io, buffer, 5, &actual) == BH_OK); + BH_VERIFY(actual == 5); + BH_VERIFY(memcmp(buffer, "abcde", 5) == 0); + + BH_VERIFY(BH_IOSeek(io, 0, BH_IO_SEEK_SET) == BH_OK); + BH_VERIFY(BH_IORead(io, buffer, sizeof(buffer), &actual) == BH_OK); + BH_VERIFY(actual == 20); + BH_VERIFY(memcmp(buffer, "1234567890abcde67890", 20) == 0); + + BH_VERIFY(BH_IOWrite(io, "1234567890", 10, &actual) != BH_OK); + BH_VERIFY(BH_IOSeek(io, -5, BH_IO_SEEK_CUR) == BH_OK); + BH_VERIFY(BH_IORead(io, buffer, 5, &actual) == BH_OK); + BH_VERIFY(actual == 5); + BH_VERIFY(memcmp(buffer, "67890", 5) == 0); + BH_IOFree(io); + + /* Check operations for read and write access */ + BH_VERIFY((io = BH_FileNew(FILENAME1)) != NULL); + BH_VERIFY(strcmp(BH_IOClassname(io), BH_FILE_CLASSNAME) == 0); + BH_VERIFY(BH_IOOpen(io, BH_IO_WRITE | BH_IO_READ) == BH_OK); + BH_VERIFY(BH_IOFlags(io) & BH_IO_FLAG_OPEN); + + BH_VERIFY(BH_IOWrite(io, "abcde", 5, &actual) == BH_OK); + BH_VERIFY(actual == 5); + + BH_VERIFY(BH_IOWrite(io, "1234567890", 10, &actual) == BH_OK); + BH_VERIFY(actual == 10); + + BH_VERIFY(BH_IOWrite(io, "1234567890abcde67890", 20, &actual) == BH_OK); + BH_VERIFY(actual == 20); + + BH_VERIFY(BH_IOSeek(io, 0, BH_IO_SEEK_SET) == BH_OK); + BH_VERIFY(BH_IORead(io, buffer, 5, &actual) == BH_OK); + BH_VERIFY(actual == 5); + BH_VERIFY(memcmp(buffer, "abcde", 5) == 0); + + BH_VERIFY(BH_IORead(io, buffer, 10, &actual) == BH_OK); + BH_VERIFY(actual == 10); + BH_VERIFY(memcmp(buffer, "1234567890", 10) == 0); + + BH_VERIFY(BH_IOSeek(io, 0, BH_IO_SEEK_SET) == BH_OK); + BH_VERIFY(BH_IORead(io, buffer, 35, &actual) == BH_OK); + BH_VERIFY(actual == 35); + BH_VERIFY(memcmp(buffer, "abcde12345678901234567890abcde67890", 35) == 0); + BH_IOClose(io); + + BH_IOFree(io); + return 0; +} + + +/** + * Check for truncate mode. + */ +static int checkTruncate(void) +{ + int64_t position; + char buffer[128]; + size_t actual; + BH_IO *io; + + /* Check operations for write only access */ + BH_VERIFY((io = BH_FileNew(FILENAME1)) != NULL); + BH_VERIFY(strcmp(BH_IOClassname(io), BH_FILE_CLASSNAME) == 0); + BH_VERIFY(BH_IOOpen(io, BH_IO_WRITE | BH_IO_TRUNCATE) == BH_OK); + BH_VERIFY(BH_IOFlags(io) & BH_IO_FLAG_OPEN); + + BH_VERIFY(BH_IOWrite(io, "1234567890", 10, &actual) == BH_OK); + BH_VERIFY(actual == 10); + + BH_VERIFY(BH_IOWrite(io, "1234567890", 10, &actual) == BH_OK); + BH_VERIFY(actual == 10); + + BH_VERIFY(BH_IOSeek(io, 10, BH_IO_SEEK_SET) == BH_OK); + BH_VERIFY(BH_IOWrite(io, "abcde", 5, &actual) == BH_OK); + BH_VERIFY(actual == 5); + + BH_VERIFY(BH_IOSeek(io, 0, BH_IO_SEEK_SET) == BH_OK); + BH_VERIFY(BH_IORead(io, buffer, 1, &actual) != BH_OK); + BH_VERIFY(BH_IOSeek(io, 0, BH_IO_SEEK_END) == BH_OK); + BH_VERIFY(BH_IOTell(io, &position) == BH_OK); + BH_VERIFY(position == 20); + BH_IOClose(io); + + /* Check operations for read only access without truncate */ + BH_VERIFY(BH_IOOpen(io, BH_IO_READ) == BH_OK); + BH_VERIFY(BH_IOFlags(io) & BH_IO_FLAG_OPEN); + BH_VERIFY(BH_IORead(io, buffer, 10, &actual) == BH_OK); + BH_VERIFY(actual == 10); + BH_VERIFY(memcmp(buffer, "1234567890", 10) == 0); + + BH_VERIFY(BH_IORead(io, buffer, 5, &actual) == BH_OK); + BH_VERIFY(actual == 5); + BH_VERIFY(memcmp(buffer, "abcde", 5) == 0); + + BH_VERIFY(BH_IOSeek(io, 0, BH_IO_SEEK_SET) == BH_OK); + BH_VERIFY(BH_IORead(io, buffer, sizeof(buffer), &actual) == BH_OK); + BH_VERIFY(actual == 20); + BH_VERIFY(memcmp(buffer, "1234567890abcde67890", 20) == 0); + + BH_VERIFY(BH_IOSeek(io, -5, BH_IO_SEEK_CUR) == BH_OK); + BH_VERIFY(BH_IORead(io, buffer, 5, &actual) == BH_OK); + BH_VERIFY(actual == 5); + BH_VERIFY(memcmp(buffer, "67890", 5) == 0); + BH_IOClose(io); + + /* Check operations for read only access */ + BH_VERIFY(BH_IOOpen(io, BH_IO_READ | BH_IO_TRUNCATE) == BH_OK); + BH_VERIFY(BH_IOFlags(io) & BH_IO_FLAG_OPEN); + BH_VERIFY(BH_IORead(io, buffer, 10, &actual) == BH_OK); + BH_VERIFY(actual == 0); + + BH_VERIFY(BH_IORead(io, buffer, 5, &actual) == BH_OK); + BH_VERIFY(actual == 0); + + BH_VERIFY(BH_IOWrite(io, "1234567890", 10, &actual) != BH_OK); + BH_VERIFY(BH_IOSeek(io, 0, BH_IO_SEEK_SET) == BH_OK); + BH_VERIFY(BH_IORead(io, buffer, sizeof(buffer), &actual) == BH_OK); + BH_VERIFY(actual == 0); + BH_IOFree(io); + + /* Check operations for read and write access */ + BH_VERIFY((io = BH_FileNew(FILENAME1)) != NULL); + BH_VERIFY(strcmp(BH_IOClassname(io), BH_FILE_CLASSNAME) == 0); + BH_VERIFY(BH_IOOpen(io, BH_IO_WRITE | BH_IO_READ | BH_IO_TRUNCATE) == BH_OK); + BH_VERIFY(BH_IOFlags(io) & BH_IO_FLAG_OPEN); + + BH_VERIFY(BH_IOWrite(io, "abcde", 5, &actual) == BH_OK); + BH_VERIFY(actual == 5); + + BH_VERIFY(BH_IOWrite(io, "1234567890", 10, &actual) == BH_OK); + BH_VERIFY(actual == 10); + + BH_VERIFY(BH_IOWrite(io, "1234567890abcde67890", 20, &actual) == BH_OK); + BH_VERIFY(actual == 20); + + BH_VERIFY(BH_IOSeek(io, 0, BH_IO_SEEK_SET) == BH_OK); + BH_VERIFY(BH_IORead(io, buffer, 5, &actual) == BH_OK); + BH_VERIFY(actual == 5); + BH_VERIFY(memcmp(buffer, "abcde", 5) == 0); + + BH_VERIFY(BH_IORead(io, buffer, 10, &actual) == BH_OK); + BH_VERIFY(actual == 10); + BH_VERIFY(memcmp(buffer, "1234567890", 10) == 0); + + BH_VERIFY(BH_IOSeek(io, 0, BH_IO_SEEK_SET) == BH_OK); + BH_VERIFY(BH_IORead(io, buffer, 35, &actual) == BH_OK); + BH_VERIFY(actual == 35); + BH_VERIFY(memcmp(buffer, "abcde12345678901234567890abcde67890", 35) == 0); + BH_IOClose(io); + + BH_VERIFY(BH_IOOpen(io, BH_IO_WRITE | BH_IO_TRUNCATE) == BH_OK); + BH_VERIFY(BH_IOFlags(io) & BH_IO_FLAG_OPEN); + BH_IOClose(io); + + BH_IOFree(io); + return 0; +} + + +/** + * Check for exist mode. + */ +static int checkExist(void) +{ + int64_t position; + char buffer[128]; + size_t actual; + BH_IO *io; + + /* Check operations for write only access */ + BH_VERIFY((io = BH_FileNew(FILENAME1)) != NULL); + BH_VERIFY(strcmp(BH_IOClassname(io), BH_FILE_CLASSNAME) == 0); + BH_VERIFY(BH_IOOpen(io, BH_IO_WRITE | BH_IO_EXIST) == BH_OK); + BH_VERIFY(BH_IOFlags(io) & BH_IO_FLAG_OPEN); + + BH_VERIFY(BH_IOWrite(io, "1234567890", 10, &actual) == BH_OK); + BH_VERIFY(actual == 10); + + BH_VERIFY(BH_IOWrite(io, "1234567890", 10, &actual) == BH_OK); + BH_VERIFY(actual == 10); + + BH_VERIFY(BH_IOSeek(io, 10, BH_IO_SEEK_SET) == BH_OK); + BH_VERIFY(BH_IOWrite(io, "abcde", 5, &actual) == BH_OK); + BH_VERIFY(actual == 5); + + BH_VERIFY(BH_IOSeek(io, 0, BH_IO_SEEK_SET) == BH_OK); + BH_VERIFY(BH_IORead(io, buffer, 1, &actual) != BH_OK); + BH_VERIFY(BH_IOSeek(io, 0, BH_IO_SEEK_END) == BH_OK); + BH_VERIFY(BH_IOTell(io, &position) == BH_OK); + BH_VERIFY(position == 20); + BH_IOClose(io); + + /* Check operations for read only access */ + BH_VERIFY(BH_IOOpen(io, BH_IO_READ | BH_IO_EXIST) == BH_OK); + BH_VERIFY(BH_IOFlags(io) & BH_IO_FLAG_OPEN); + BH_VERIFY(BH_IORead(io, buffer, 10, &actual) == BH_OK); + BH_VERIFY(actual == 10); + BH_VERIFY(memcmp(buffer, "1234567890", 10) == 0); + + BH_VERIFY(BH_IORead(io, buffer, 5, &actual) == BH_OK); + BH_VERIFY(actual == 5); + BH_VERIFY(memcmp(buffer, "abcde", 5) == 0); + + BH_VERIFY(BH_IOSeek(io, 0, BH_IO_SEEK_SET) == BH_OK); + BH_VERIFY(BH_IORead(io, buffer, sizeof(buffer), &actual) == BH_OK); + BH_VERIFY(actual == 20); + BH_VERIFY(memcmp(buffer, "1234567890abcde67890", 20) == 0); + + BH_VERIFY(BH_IOWrite(io, "1234567890", 10, &actual) != BH_OK); + BH_VERIFY(BH_IOSeek(io, -5, BH_IO_SEEK_CUR) == BH_OK); + BH_VERIFY(BH_IORead(io, buffer, 5, &actual) == BH_OK); + BH_VERIFY(actual == 5); + BH_VERIFY(memcmp(buffer, "67890", 5) == 0); + BH_IOFree(io); + + /* Check operations for read and write access */ + BH_VERIFY((io = BH_FileNew(FILENAME1)) != NULL); + BH_VERIFY(strcmp(BH_IOClassname(io), BH_FILE_CLASSNAME) == 0); + BH_VERIFY(BH_IOOpen(io, BH_IO_WRITE | BH_IO_READ | BH_IO_EXIST) == BH_OK); + BH_VERIFY(BH_IOFlags(io) & BH_IO_FLAG_OPEN); + + BH_VERIFY(BH_IOWrite(io, "abcde", 5, &actual) == BH_OK); + BH_VERIFY(actual == 5); + + BH_VERIFY(BH_IOWrite(io, "1234567890", 10, &actual) == BH_OK); + BH_VERIFY(actual == 10); + + BH_VERIFY(BH_IOWrite(io, "1234567890abcde67890", 20, &actual) == BH_OK); + BH_VERIFY(actual == 20); + + BH_VERIFY(BH_IOSeek(io, 0, BH_IO_SEEK_SET) == BH_OK); + BH_VERIFY(BH_IORead(io, buffer, 5, &actual) == BH_OK); + BH_VERIFY(actual == 5); + BH_VERIFY(memcmp(buffer, "abcde", 5) == 0); + + BH_VERIFY(BH_IORead(io, buffer, 10, &actual) == BH_OK); + BH_VERIFY(actual == 10); + BH_VERIFY(memcmp(buffer, "1234567890", 10) == 0); + + BH_VERIFY(BH_IOSeek(io, 0, BH_IO_SEEK_SET) == BH_OK); + BH_VERIFY(BH_IORead(io, buffer, 35, &actual) == BH_OK); + BH_VERIFY(actual == 35); + BH_VERIFY(memcmp(buffer, "abcde12345678901234567890abcde67890", 35) == 0); + BH_IOClose(io); + BH_IOFree(io); + + /* Check against non existing files */ + BH_VERIFY((io = BH_FileNew(FILENAME2)) != NULL); + BH_VERIFY(strcmp(BH_IOClassname(io), BH_FILE_CLASSNAME) == 0); + BH_VERIFY(BH_IOOpen(io, BH_IO_WRITE | BH_IO_EXIST) != BH_OK); + BH_VERIFY((BH_IOFlags(io) & BH_IO_FLAG_OPEN) == 0); + BH_VERIFY(BH_IOOpen(io, BH_IO_READ | BH_IO_EXIST) != BH_OK); + BH_VERIFY((BH_IOFlags(io) & BH_IO_FLAG_OPEN) == 0); + BH_VERIFY(BH_IOOpen(io, BH_IO_WRITE | BH_IO_READ | BH_IO_EXIST) != BH_OK); + BH_VERIFY((BH_IOFlags(io) & BH_IO_FLAG_OPEN) == 0); + BH_IOFree(io); + return 0; +} + + +/** + * Check in append mode. + */ +static int checkAppend(void) +{ + int64_t position; + char buffer[128]; + size_t actual; + BH_IO *io; + + /* Explicitly call cleanup */ + cleanup(); + + /* Check operations for write only access */ + BH_VERIFY((io = BH_FileNew(FILENAME1)) != NULL); + BH_VERIFY(strcmp(BH_IOClassname(io), BH_FILE_CLASSNAME) == 0); + BH_VERIFY(BH_IOOpen(io, BH_IO_WRITE | BH_IO_APPEND) == BH_OK); + BH_VERIFY(BH_IOFlags(io) & BH_IO_FLAG_OPEN); + + BH_VERIFY(BH_IOWrite(io, "1234567890", 10, &actual) == BH_OK); + BH_VERIFY(actual == 10); + + BH_VERIFY(BH_IOWrite(io, "1234567890", 10, &actual) == BH_OK); + BH_VERIFY(actual == 10); + + BH_VERIFY(BH_IOSeek(io, 10, BH_IO_SEEK_SET) == BH_OK); + BH_VERIFY(BH_IOWrite(io, "abcde", 5, &actual) == BH_OK); + BH_VERIFY(actual == 5); + + BH_VERIFY(BH_IOSeek(io, 0, BH_IO_SEEK_SET) == BH_OK); + BH_VERIFY(BH_IORead(io, buffer, 1, &actual) != BH_OK); + BH_VERIFY(BH_IOSeek(io, 0, BH_IO_SEEK_END) == BH_OK); + BH_VERIFY(BH_IOTell(io, &position) == BH_OK); + BH_VERIFY(position == 25); + BH_IOClose(io); + + /* Check operations for read only access */ + BH_VERIFY(BH_IOOpen(io, BH_IO_READ | BH_IO_APPEND) == BH_OK); + BH_VERIFY(BH_IOFlags(io) & BH_IO_FLAG_OPEN); + BH_VERIFY(strcmp(BH_IOClassname(io), BH_FILE_CLASSNAME) == 0); + BH_VERIFY(BH_IORead(io, buffer, 10, &actual) == BH_OK); + BH_VERIFY(actual == 10); + BH_VERIFY(memcmp(buffer, "1234567890", 10) == 0); + + BH_VERIFY(BH_IORead(io, buffer, 10, &actual) == BH_OK); + BH_VERIFY(actual == 10); + BH_VERIFY(memcmp(buffer, "1234567890", 10) == 0); + + BH_VERIFY(BH_IORead(io, buffer, 5, &actual) == BH_OK); + BH_VERIFY(actual == 5); + BH_VERIFY(memcmp(buffer, "abcde", 5) == 0); + + BH_VERIFY(BH_IOWrite(io, "1234567890", 10, &actual) != BH_OK); + BH_VERIFY(BH_IOSeek(io, -5, BH_IO_SEEK_CUR) == BH_OK); + BH_VERIFY(BH_IORead(io, buffer, 5, &actual) == BH_OK); + BH_VERIFY(actual == 5); + BH_VERIFY(memcmp(buffer, "abcde", 5) == 0); + BH_IOClose(io); + + /* Check operations for read and write access */ + BH_VERIFY(BH_IOOpen(io, BH_IO_WRITE | BH_IO_READ | BH_IO_APPEND) == BH_OK); + BH_VERIFY(BH_IOFlags(io) & BH_IO_FLAG_OPEN); + + BH_VERIFY(BH_IOWrite(io, "abcde", 5, &actual) == BH_OK); + BH_VERIFY(actual == 5); + + BH_VERIFY(BH_IOWrite(io, "1234567890", 10, &actual) == BH_OK); + BH_VERIFY(actual == 10); + + BH_VERIFY(BH_IOSeek(io, 0, BH_IO_SEEK_SET) == BH_OK); + BH_VERIFY(BH_IORead(io, buffer, 40, &actual) == BH_OK); + BH_VERIFY(actual == 40); + BH_VERIFY(memcmp(buffer, "12345678901234567890abcdeabcde1234567890", 40) == 0); + BH_IOClose(io); + + BH_VERIFY(BH_IOOpen(io, BH_IO_WRITE | BH_IO_TRUNCATE) == BH_OK); + BH_VERIFY(BH_IOFlags(io) & BH_IO_FLAG_OPEN); + BH_IOClose(io); + + BH_IOFree(io); + return 0; +} + + +/** + * Check for create mode. + */ +static int checkCreate(void) +{ + BH_IO *io; + + /* Check for already existing file */ + BH_VERIFY((io = BH_FileNew(FILENAME1)) != NULL); + BH_VERIFY(strcmp(BH_IOClassname(io), BH_FILE_CLASSNAME) == 0); + BH_VERIFY(BH_IOOpen(io, BH_IO_WRITE | BH_IO_CREATE) != BH_OK); + BH_VERIFY((BH_IOFlags(io) & BH_IO_FLAG_OPEN) == 0); + BH_IOFree(io); + + /* Check for new file with write access */ + BH_VERIFY((io = BH_FileNew(FILENAME2)) != NULL); + BH_VERIFY(strcmp(BH_IOClassname(io), BH_FILE_CLASSNAME) == 0); + BH_VERIFY(BH_IOOpen(io, BH_IO_WRITE | BH_IO_CREATE) == BH_OK); + BH_VERIFY(BH_IOFlags(io) & BH_IO_FLAG_OPEN); + BH_IOFree(io); + + /* Check for new file with read access */ + BH_VERIFY((io = BH_FileNew(FILENAME3)) != NULL); + BH_VERIFY(strcmp(BH_IOClassname(io), BH_FILE_CLASSNAME) == 0); + BH_VERIFY(BH_IOOpen(io, BH_IO_READ | BH_IO_CREATE) == BH_OK); + BH_VERIFY(BH_IOFlags(io) & BH_IO_FLAG_OPEN); + BH_IOFree(io); + + /* Check for new file with read/write access */ + BH_VERIFY((io = BH_FileNew(FILENAME4)) != NULL); + BH_VERIFY(strcmp(BH_IOClassname(io), BH_FILE_CLASSNAME) == 0); + BH_VERIFY(BH_IOOpen(io, BH_IO_WRITE | BH_IO_READ | BH_IO_CREATE) == BH_OK); + BH_VERIFY(BH_IOFlags(io) & BH_IO_FLAG_OPEN); + BH_IOFree(io); + + return 0; +} + + +/** + * Check for EOF flags. + */ +static int checkEOF(void) +{ + char buffer[128]; + size_t actual; + BH_IO *io; + + BH_VERIFY((io = BH_FileNew(FILENAME1)) != NULL); + BH_VERIFY(strcmp(BH_IOClassname(io), BH_FILE_CLASSNAME) == 0); + BH_VERIFY(BH_IOOpen(io, BH_IO_READ | BH_IO_TRUNCATE) == BH_OK); + BH_VERIFY(BH_IOFlags(io) & BH_IO_FLAG_OPEN); + + BH_VERIFY(BH_IORead(io, buffer, 128, &actual) == BH_OK); + BH_VERIFY(actual == 0); + BH_VERIFY(BH_IOFlags(io) & BH_IO_FLAG_EOF); + + BH_IOClose(io); + BH_IOFree(io); + + return 0; +} + + +/** + * Check for error flags. + */ +static int checkError(void) +{ + size_t actual; + BH_IO *io; + + BH_VERIFY((io = BH_FileNew(FILENAME1)) != NULL); + BH_VERIFY(strcmp(BH_IOClassname(io), BH_FILE_CLASSNAME) == 0); + BH_VERIFY(BH_IOOpen(io, BH_IO_READ) == BH_OK); + BH_VERIFY(BH_IOFlags(io) & BH_IO_FLAG_OPEN); + + BH_VERIFY(BH_IOWrite(io, "12345", 5, &actual) != BH_OK); + BH_VERIFY(BH_IOFlags(io) & BH_IO_FLAG_ERROR); + BH_VERIFY(BH_IOClear(io) == BH_OK); + BH_VERIFY((BH_IOFlags(io) & BH_IO_FLAG_ERROR) == 0); + + BH_IOClose(io); + BH_IOFree(io); + + return 0; +} + + +/** + * Check peek operation. + */ +static int checkPeek(void) +{ + int64_t previous, current; + char buffer[128]; + size_t actual; + BH_IO *io; + + BH_VERIFY((io = BH_FileNew(FILENAME1)) != NULL); + BH_VERIFY(strcmp(BH_IOClassname(io), BH_FILE_CLASSNAME) == 0); + BH_VERIFY(BH_IOOpen(io, BH_IO_WRITE | BH_IO_READ | BH_IO_TRUNCATE) == BH_OK); + BH_VERIFY(BH_IOFlags(io) & BH_IO_FLAG_OPEN); + + BH_VERIFY(BH_IOWrite(io, "1234567890", 10, &actual) == BH_OK); + BH_VERIFY(actual == 10); + + BH_VERIFY(BH_IOWrite(io, "1234567890", 10, &actual) == BH_OK); + BH_VERIFY(actual == 10); + + BH_VERIFY(BH_IOSeek(io, 0, BH_IO_SEEK_SET) == BH_OK); + BH_VERIFY(BH_IOTell(io, &previous) == BH_OK); + BH_VERIFY(BH_IOPeek(io, buffer, 128, &actual) == BH_OK); + BH_VERIFY(BH_IOTell(io, ¤t) == BH_OK); + BH_VERIFY(actual == 20); + BH_VERIFY(memcmp(buffer, "12345678901234567890", 20) == 0); + BH_VERIFY(previous == current); + + BH_VERIFY(BH_IOSeek(io, 0, BH_IO_SEEK_SET) == BH_OK); + BH_VERIFY(BH_IOTell(io, &previous) == BH_OK); + BH_VERIFY(BH_IOPeek(io, buffer, 128, &actual) == BH_OK); + BH_VERIFY(BH_IOTell(io, ¤t) == BH_OK); + BH_VERIFY(actual == 20); + BH_VERIFY(memcmp(buffer, "12345678901234567890", 20) == 0); + BH_VERIFY(previous == current); + + BH_IOClose(io); + BH_IOFree(io); + + return 0; +} + + +/** + * Check file size operation. + */ +static int checkSize(void) +{ + BH_IO *io; + int64_t size; + + BH_VERIFY((io = BH_FileNew(FILENAME1)) != NULL); + BH_VERIFY(strcmp(BH_IOClassname(io), BH_FILE_CLASSNAME) == 0); + BH_VERIFY(BH_IOOpen(io, BH_IO_READ) == BH_OK); + + BH_VERIFY(BH_IOSize(io, &size) == BH_OK); + BH_VERIFY(size == 20); + + BH_IOClose(io); + BH_IOFree(io); + return 0; +} + + +int main(int argc, + char **argv) +{ + BH_UNUSED(argc); + BH_UNUSED(argv); + + /* Cleanup */ + cleanup(); + + BH_UnitAdd("Null", checkNull); + BH_UnitAdd("Normal", checkNormal); + BH_UnitAdd("Truncate", checkTruncate); + BH_UnitAdd("Exist", checkExist); + BH_UnitAdd("Append", checkAppend); + BH_UnitAdd("Create", checkCreate); + BH_UnitAdd("EOF", checkEOF); + BH_UnitAdd("Error", checkError); + BH_UnitAdd("Peek", checkPeek); + BH_UnitAdd("Size", checkSize); + + return BH_UnitRun(); +} diff --git a/test/src/TestHashmap.c b/test/src/TestHashmap.c new file mode 100644 index 0000000..da73e4b --- /dev/null +++ b/test/src/TestHashmap.c @@ -0,0 +1,234 @@ +#include +#include + + +static size_t DBG_PtrIntHash(const void *ptr) +{ + return BH_PTR2INT(ptr); +} + + +static int DBG_PtrIntEqual(const void *lhs, const void *rhs) +{ + return BH_PTR2INT(lhs) - BH_PTR2INT(rhs); +} + + +static int NewFree(void) +{ + BH_Hashmap *hashmap; + + hashmap = BH_HashmapNew(DBG_PtrIntEqual, DBG_PtrIntHash); + BH_VERIFY(hashmap != NULL); + + BH_VERIFY(BH_HashmapEmpty(hashmap) != 0); + BH_VERIFY(BH_HashmapSize(hashmap) == 0); + BH_VERIFY(BH_HashmapCapacity(hashmap) == 0); + BH_VERIFY(BH_HashmapFactor(hashmap) >= 0.15f); + BH_VERIFY(BH_HashmapFactor(hashmap) <= 1.0f); + + BH_HashmapFree(hashmap); + return 0; +} + +static int GrowShrink(void) +{ + BH_Hashmap *hashmap; + void *iter; + + hashmap = BH_HashmapNew(DBG_PtrIntEqual, DBG_PtrIntHash); + BH_VERIFY(hashmap != NULL); + + /* Allocate space for 1024 entries and insert 1 element */ + BH_VERIFY(BH_HashmapReserve(hashmap, 1024) == 0); + BH_VERIFY(BH_HashmapInsert(hashmap, BH_INT2PTR(1337), BH_INT2PTR(80085)) == 0); + + /* Check hashmap contents */ + iter = BH_HashmapIterNext(hashmap, NULL); + BH_VERIFY(iter != NULL); + BH_VERIFY(BH_PTR2INT(BH_HashmapIterKey(iter)) == 1337); + BH_VERIFY(BH_PTR2INT(BH_HashmapIterValue(iter)) == 80085); + BH_VERIFY(BH_HashmapIterNext(hashmap, iter) == NULL); + BH_VERIFY(BH_HashmapEmpty(hashmap) == 0); + BH_VERIFY(BH_HashmapSize(hashmap) == 1); + BH_VERIFY(BH_HashmapCapacity(hashmap) >= 1024); + + /* Change factor and grow */ + BH_HashmapSetFactor(hashmap, 0.35f); + + /* Check hashmap contents */ + iter = BH_HashmapIterNext(hashmap, NULL); + BH_VERIFY(iter != NULL); + BH_VERIFY(BH_PTR2INT(BH_HashmapIterKey(iter)) == 1337); + BH_VERIFY(BH_PTR2INT(BH_HashmapIterValue(iter)) == 80085); + BH_VERIFY(BH_HashmapIterNext(hashmap, iter) == NULL); + BH_VERIFY(BH_HashmapReserve(hashmap, 8192) == 0); + BH_VERIFY(BH_HashmapEmpty(hashmap) == 0); + BH_VERIFY(BH_HashmapSize(hashmap) == 1); + BH_VERIFY(BH_HashmapCapacity(hashmap) >= 8192); + BH_VERIFY_DELTA(BH_HashmapFactor(hashmap), 0.35f, 0.001f); + + /* Shrink */ + BH_VERIFY(BH_HashmapReserve(hashmap, 0) == 0); + + /* Check hashmap contents */ + iter = BH_HashmapIterNext(hashmap, NULL); + BH_VERIFY(iter != NULL); + BH_VERIFY(BH_PTR2INT(BH_HashmapIterKey(iter)) == 1337); + BH_VERIFY(BH_PTR2INT(BH_HashmapIterValue(iter)) == 80085); + BH_VERIFY(BH_HashmapIterNext(hashmap, iter) == NULL); + BH_VERIFY(BH_HashmapEmpty(hashmap) == 0); + BH_VERIFY(BH_HashmapSize(hashmap) == 1); + BH_VERIFY(BH_HashmapCapacity(hashmap) >= 1); + BH_VERIFY(BH_HashmapCapacity(hashmap) < 8192); + BH_VERIFY_DELTA(BH_HashmapFactor(hashmap), 0.35f, 0.001f); + + /* Shrink to 0 (deallocate) */ + BH_HashmapClear(hashmap); + BH_VERIFY(BH_HashmapEmpty(hashmap) != 0); + BH_VERIFY(BH_HashmapSize(hashmap) == 0); + BH_VERIFY(BH_HashmapCapacity(hashmap) > 0); + + BH_VERIFY(BH_HashmapReserve(hashmap, 0) == 0); + BH_VERIFY(BH_HashmapEmpty(hashmap) != 0); + BH_VERIFY(BH_HashmapSize(hashmap) == 0); + BH_VERIFY(BH_HashmapCapacity(hashmap) == 0); + + /* Check hashmap contents */ + iter = BH_HashmapIterNext(hashmap, NULL); + BH_VERIFY(iter == NULL); + + BH_HashmapFree(hashmap); + return 0; +} + +static int InsertRemove(void) +{ + BH_Hashmap *hashmap; + size_t i, added, removed; + void *iter; + + hashmap = BH_HashmapNew(DBG_PtrIntEqual, DBG_PtrIntHash); + BH_VERIFY(hashmap != NULL); + BH_HashmapSetFactor(hashmap, 1.0f); + + /* Insert elements into hashmap */ + added = 0; + for (i = 1024; i > 0; i--) + { + added += (i - 1) / 4; + BH_VERIFY(BH_HashmapInsert(hashmap, BH_INT2PTR((i - 1) / 4), BH_INT2PTR(i)) == 0); + } + + /* Remove elements */ + iter = BH_HashmapIterNext(hashmap, NULL); + removed = 0; + while (iter) + { + removed += BH_PTR2INT(BH_HashmapIterKey(iter)); + BH_HashmapIterRemove(hashmap, iter); + + iter = BH_HashmapIterNext(hashmap, NULL); + } + + /* Check inserted elements are equal to removed */ + BH_VERIFY(added == removed); + + BH_HashmapFree(hashmap); + return 0; +} + +static int Lookup(void) +{ + BH_Hashmap *hashmap; + size_t i; + + hashmap = BH_HashmapNew(DBG_PtrIntEqual, DBG_PtrIntHash); + BH_VERIFY(hashmap != NULL); + + /* Insert elements into hashmap */ + for (i = 0; i < 256; i++) + BH_VERIFY(BH_HashmapInsert(hashmap, BH_INT2PTR(i * 4), BH_INT2PTR(i)) == 0); + + /* Lookup inserted elements */ + for (i = 0; i < 256; i++) + { + void *value; + + BH_VERIFY(BH_HashmapAt(hashmap, BH_INT2PTR(i * 4), NULL) == BH_OK); + BH_VERIFY(BH_HashmapAt(hashmap, BH_INT2PTR(i * 4), &value) == BH_OK); + BH_VERIFY(BH_PTR2INT(value) == (int)i); + } + + /* Lookup non-existing elements */ + for (i = 256; i < 512; i++) + { + void *value; + + BH_VERIFY(BH_HashmapAt(hashmap, BH_INT2PTR(i * 4), NULL) != BH_OK); + BH_VERIFY(BH_HashmapAt(hashmap, BH_INT2PTR(i * 4), &value) != BH_OK); + } + + BH_HashmapFree(hashmap); + return 0; +} + +static int Clear(void) +{ + BH_Hashmap *hashmap; + size_t i; + + hashmap = BH_HashmapNew(DBG_PtrIntEqual, DBG_PtrIntHash); + BH_VERIFY(hashmap != NULL); + + /* Insert elements into hashmap */ + for (i = 0; i < 128; i++) + BH_VERIFY(BH_HashmapInsert(hashmap, BH_INT2PTR(i), 0) == 0); + + BH_HashmapClear(hashmap); + + /* Remove non-existing elements */ + for (i = 0; i < 128; i++) + BH_HashmapRemove(hashmap, BH_INT2PTR(i)); + + BH_HashmapFree(hashmap); + return 0; +} + +static int Fields(void) +{ + BH_Hashmap *hashmap; + size_t i; + + hashmap = BH_HashmapNew(DBG_PtrIntEqual, DBG_PtrIntHash); + BH_VERIFY(hashmap != NULL); + BH_VERIFY(BH_HashmapEmpty(hashmap) == 1); + + /* Insert elements into hashmap */ + for (i = 0; i < 14; i++) + BH_VERIFY(BH_HashmapInsert(hashmap, BH_INT2PTR(i), NULL) == 0); + + /* Check hashmap fields correspond to getter functions */ + BH_VERIFY(BH_HashmapSize(hashmap) == 14); + BH_VERIFY(BH_HashmapCapacity(hashmap) >= 14); + BH_VERIFY(BH_HashmapEmpty(hashmap) == 0); + + BH_HashmapFree(hashmap); + return 0; +} + +int main(int argc, char **argv) +{ + (void)argc; + (void)argv; + + /* Add unit tests */ + BH_UnitAdd("NewFree", NewFree); + BH_UnitAdd("GrowShrink", GrowShrink); + BH_UnitAdd("InsertRemove", InsertRemove); + BH_UnitAdd("Lookup", Lookup); + BH_UnitAdd("Clear", Clear); + BH_UnitAdd("Fields", Fields); + + return BH_UnitRun(); +} diff --git a/test/src/TestMath.c b/test/src/TestMath.c new file mode 100644 index 0000000..e03ca96 --- /dev/null +++ b/test/src/TestMath.c @@ -0,0 +1,727 @@ +#include +#include + + +#define ACCEPTABLE_DELTA 0.0001f + + +static int checkVec4f(void) +{ + float a[4], b[4], c[4], r[4]; + float value; + + a[0] = 1.0f; a[1] = 2.0f; a[2] = 3.0f; a[3] = 4.0f; + b[0] = 5.0f; b[1] = 6.0f; b[2] = 7.0f; b[3] = 8.0f; + c[0] = 1.5f; c[1] = 2.5f; c[2] = 3.5f; c[3] = 4.5f; + + BH_Vec4fAdd(a, b, r); + BH_VERIFY_DELTA(r[0], 6.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[1], 8.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[2], 10.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[3], 12.0000f, ACCEPTABLE_DELTA); + + BH_Vec4fSub(a, b, r); + BH_VERIFY_DELTA(r[0], -4.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[1], -4.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[2], -4.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[3], -4.0000f, ACCEPTABLE_DELTA); + + BH_Vec4fMul(a, b, r); + BH_VERIFY_DELTA(r[0], 5.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[1], 12.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[2], 21.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[3], 32.0000f, ACCEPTABLE_DELTA); + + BH_Vec4fScale(a, 10.0f, r); + BH_VERIFY_DELTA(r[0], 10.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[1], 20.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[2], 30.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[3], 40.0000f, ACCEPTABLE_DELTA); + + BH_Vec4fMulAdd(a, b, c, r); + BH_VERIFY_DELTA(r[0], 6.5000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[1], 14.5000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[2], 24.5000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[3], 36.5000f, ACCEPTABLE_DELTA); + + BH_Vec4fNegate(a, r); + BH_VERIFY_DELTA(r[0], -1.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[1], -2.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[2], -3.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[3], -4.0000f, ACCEPTABLE_DELTA); + + value = BH_Vec4fDot(a, b); + BH_VERIFY_DELTA(value, 70.0000f, ACCEPTABLE_DELTA); + + value = BH_Vec4fLength(a); + BH_VERIFY_DELTA(value, sqrt(30.0f), ACCEPTABLE_DELTA); + + BH_Vec4fNormal(a, r); + BH_VERIFY_DELTA(r[0], 1.0f / sqrt(30.0f), ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[1], 2.0f / sqrt(30.0f), ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[2], 3.0f / sqrt(30.0f), ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[3], 4.0f / sqrt(30.0f), ACCEPTABLE_DELTA); + + BH_Vec4fMin(a, b, r); + BH_VERIFY_DELTA(r[0], 1.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[1], 2.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[2], 3.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[3], 4.0000f, ACCEPTABLE_DELTA); + + BH_Vec4fMax(a, b, r); + BH_VERIFY_DELTA(r[0], 5.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[1], 6.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[2], 7.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[3], 8.0000f, ACCEPTABLE_DELTA); + + BH_Vec4fLerp(a, b, 0.0f, r); + BH_VERIFY_DELTA(r[0], 1.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[1], 2.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[2], 3.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[3], 4.0000f, ACCEPTABLE_DELTA); + + BH_Vec4fLerp(a, b, 0.5f, r); + BH_VERIFY_DELTA(r[0], 3.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[1], 4.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[2], 5.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[3], 6.0000f, ACCEPTABLE_DELTA); + + BH_Vec4fLerp(a, b, 1.0f, r); + BH_VERIFY_DELTA(r[0], 5.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[1], 6.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[2], 7.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[3], 8.0000f, ACCEPTABLE_DELTA); + + return 0; +} + + +static int checkVec3f(void) +{ + float a[3], b[3], c[3], r[3]; + float value; + + a[0] = 1.0f; a[1] = 2.0f; a[2] = 3.0f; + b[0] = 5.0f; b[1] = 6.0f; b[2] = 7.0f; + c[0] = 1.5f; c[1] = 2.5f; c[2] = 3.5f; + + BH_Vec3fAdd(a, b, r); + BH_VERIFY_DELTA(r[0], 6.0f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[1], 8.0f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[2], 10.0f, ACCEPTABLE_DELTA); + + BH_Vec3fSub(a, b, r); + BH_VERIFY_DELTA(r[0], -4.0f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[1], -4.0f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[2], -4.0f, ACCEPTABLE_DELTA); + + BH_Vec3fMul(a, b, r); + BH_VERIFY_DELTA(r[0], 5.0f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[1], 12.0f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[2], 21.0f, ACCEPTABLE_DELTA); + + BH_Vec3fScale(a, 10.0f, r); + BH_VERIFY_DELTA(r[0], 10.0f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[1], 20.0f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[2], 30.0f, ACCEPTABLE_DELTA); + + BH_Vec3fMulAdd(a, b, c, r); + BH_VERIFY_DELTA(r[0], 6.5f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[1], 14.5f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[2], 24.5f, ACCEPTABLE_DELTA); + + BH_Vec3fNegate(a, r); + BH_VERIFY_DELTA(r[0], -1.0f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[1], -2.0f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[2], -3.0f, ACCEPTABLE_DELTA); + + value = BH_Vec3fDot(a, b); + BH_VERIFY_DELTA(value, 38.0f, ACCEPTABLE_DELTA); + + BH_Vec3fCross(a, b, r); + BH_VERIFY_DELTA(r[0], -4.0f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[1], 8.0f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[2], -4.0f, ACCEPTABLE_DELTA); + + value = BH_Vec3fLength(a); + BH_VERIFY_DELTA(value, sqrt(14.0f), ACCEPTABLE_DELTA); + + BH_Vec3fNormal(a, r); + BH_VERIFY_DELTA(r[0], 1.0f / sqrt(14.0f), ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[1], 2.0f / sqrt(14.0f), ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[2], 3.0f / sqrt(14.0f), ACCEPTABLE_DELTA); + + BH_Vec3fMin(a, b, r); + BH_VERIFY_DELTA(r[0], 1.0f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[1], 2.0f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[2], 3.0f, ACCEPTABLE_DELTA); + + BH_Vec3fMax(a, b, r); + BH_VERIFY_DELTA(r[0], 5.0f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[1], 6.0f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[2], 7.0f, ACCEPTABLE_DELTA); + + BH_Vec3fLerp(a, b, 0.0f, r); + BH_VERIFY_DELTA(r[0], 1.0f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[1], 2.0f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[2], 3.0f, ACCEPTABLE_DELTA); + + BH_Vec3fLerp(a, b, 0.5f, r); + BH_VERIFY_DELTA(r[0], 3.0f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[1], 4.0f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[2], 5.0f, ACCEPTABLE_DELTA); + + BH_Vec3fLerp(a, b, 1.0f, r); + BH_VERIFY_DELTA(r[0], 5.0f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[1], 6.0f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[2], 7.0f, ACCEPTABLE_DELTA); + + return 0; +} + + +static int checkVec2f(void) +{ + float a[2], b[2], c[2], r[2]; + float value; + + a[0] = 1.0f; a[1] = 2.0f; + b[0] = 5.0f; b[1] = 6.0f; + c[0] = 1.5f; c[1] = 2.5f; + + BH_Vec2fAdd(a, b, r); + BH_VERIFY_DELTA(r[0], 6.0f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[1], 8.0f, ACCEPTABLE_DELTA); + + BH_Vec2fSub(a, b, r); + BH_VERIFY_DELTA(r[0], -4.0f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[1], -4.0f, ACCEPTABLE_DELTA); + + BH_Vec2fMul(a, b, r); + BH_VERIFY_DELTA(r[0], 5.0f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[1], 12.0f, ACCEPTABLE_DELTA); + + BH_Vec2fScale(a, 10.0f, r); + BH_VERIFY_DELTA(r[0], 10.0f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[1], 20.0f, ACCEPTABLE_DELTA); + + BH_Vec2fMulAdd(a, b, c, r); + BH_VERIFY_DELTA(r[0], 6.5f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[1], 14.5f, ACCEPTABLE_DELTA); + + BH_Vec2fNegate(a, r); + BH_VERIFY_DELTA(r[0], -1.0f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[1], -2.0f, ACCEPTABLE_DELTA); + + value = BH_Vec2fDot(a, b); + BH_VERIFY_DELTA(value, 17.0f, ACCEPTABLE_DELTA); + + value = BH_Vec2fCross(a, b); + BH_VERIFY_DELTA(value, -4.0f, ACCEPTABLE_DELTA); + + value = BH_Vec2fLength(a); + BH_VERIFY_DELTA(value, sqrt(5.0f), ACCEPTABLE_DELTA); + + BH_Vec2fNormal(a, r); + BH_VERIFY_DELTA(r[0], 1.0f / sqrt(5.0f), ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[1], 2.0f / sqrt(5.0f), ACCEPTABLE_DELTA); + + BH_Vec2fMin(a, b, r); + BH_VERIFY_DELTA(r[0], 1.0f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[1], 2.0f, ACCEPTABLE_DELTA); + + BH_Vec2fMax(a, b, r); + BH_VERIFY_DELTA(r[0], 5.0f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[1], 6.0f, ACCEPTABLE_DELTA); + + BH_Vec2fLerp(a, b, 0.0f, r); + BH_VERIFY_DELTA(r[0], 1.0f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[1], 2.0f, ACCEPTABLE_DELTA); + + BH_Vec2fLerp(a, b, 0.5f, r); + BH_VERIFY_DELTA(r[0], 3.0f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[1], 4.0f, ACCEPTABLE_DELTA); + + BH_Vec2fLerp(a, b, 1.0f, r); + BH_VERIFY_DELTA(r[0], 5.0f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[1], 6.0f, ACCEPTABLE_DELTA); + + return 0; +} + + +static int checkVec4i(void) +{ + int a[4], b[4], c[4], r[4]; + + a[0] = 1; a[1] = 2; a[2] = 3; a[3] = 4; + b[0] = 5; b[1] = 6; b[2] = 7; b[3] = 8; + c[0] = 4; c[1] = 3; c[2] = 2; c[3] = 1; + + BH_Vec4iAdd(a, b, r); + BH_VERIFY(r[0] == 6); + BH_VERIFY(r[1] == 8); + BH_VERIFY(r[2] == 10); + BH_VERIFY(r[3] == 12); + + BH_Vec4iSub(a, b, r); + BH_VERIFY(r[0] == -4); + BH_VERIFY(r[1] == -4); + BH_VERIFY(r[2] == -4); + BH_VERIFY(r[3] == -4); + + BH_Vec4iMul(a, b, r); + BH_VERIFY(r[0] == 5); + BH_VERIFY(r[1] == 12); + BH_VERIFY(r[2] == 21); + BH_VERIFY(r[3] == 32); + + BH_Vec4iScale(a, 10, r); + BH_VERIFY(r[0] == 10); + BH_VERIFY(r[1] == 20); + BH_VERIFY(r[2] == 30); + BH_VERIFY(r[3] == 40); + + BH_Vec4iMulAdd(a, b, c, r); + BH_VERIFY(r[0] == 9); + BH_VERIFY(r[1] == 15); + BH_VERIFY(r[2] == 23); + BH_VERIFY(r[3] == 33); + + BH_Vec4iNegate(a, r); + BH_VERIFY(r[0] == -1); + BH_VERIFY(r[1] == -2); + BH_VERIFY(r[2] == -3); + BH_VERIFY(r[3] == -4); + + BH_Vec4iMin(a, b, r); + BH_VERIFY(r[0] == 1); + BH_VERIFY(r[1] == 2); + BH_VERIFY(r[2] == 3); + BH_VERIFY(r[3] == 4); + + BH_Vec4iMax(a, b, r); + BH_VERIFY(r[0] == 5); + BH_VERIFY(r[1] == 6); + BH_VERIFY(r[2] == 7); + BH_VERIFY(r[3] == 8); + + return 0; +} + + +static int checkVec3i(void) +{ + int a[3], b[3], c[3], r[3]; + + a[0] = 1; a[1] = 2; a[2] = 3; + b[0] = 5; b[1] = 6; b[2] = 7; + c[0] = 4; c[1] = 3; c[2] = 2; + + BH_Vec3iAdd(a, b, r); + BH_VERIFY(r[0] == 6); + BH_VERIFY(r[1] == 8); + BH_VERIFY(r[2] == 10); + + BH_Vec3iSub(a, b, r); + BH_VERIFY(r[0] == -4); + BH_VERIFY(r[1] == -4); + BH_VERIFY(r[2] == -4); + + BH_Vec3iMul(a, b, r); + BH_VERIFY(r[0] == 5); + BH_VERIFY(r[1] == 12); + BH_VERIFY(r[2] == 21); + + BH_Vec3iScale(a, 10, r); + BH_VERIFY(r[0] == 10); + BH_VERIFY(r[1] == 20); + BH_VERIFY(r[2] == 30); + + BH_Vec3iMulAdd(a, b, c, r); + BH_VERIFY(r[0] == 9); + BH_VERIFY(r[1] == 15); + BH_VERIFY(r[2] == 23); + + BH_Vec3iNegate(a, r); + BH_VERIFY(r[0] == -1); + BH_VERIFY(r[1] == -2); + BH_VERIFY(r[2] == -3); + + BH_Vec3iMin(a, b, r); + BH_VERIFY(r[0] == 1); + BH_VERIFY(r[1] == 2); + BH_VERIFY(r[2] == 3); + + BH_Vec3iMax(a, b, r); + BH_VERIFY(r[0] == 5); + BH_VERIFY(r[1] == 6); + BH_VERIFY(r[2] == 7); + + return 0; +} + + +static int checkVec2i(void) +{ + int a[2], b[2], c[2], r[2]; + + a[0] = 1; a[1] = 2; + b[0] = 5; b[1] = 6; + c[0] = 4; c[1] = 3; + + BH_Vec2iAdd(a, b, r); + BH_VERIFY(r[0] == 6); + BH_VERIFY(r[1] == 8); + + BH_Vec2iSub(a, b, r); + BH_VERIFY(r[0] == -4); + BH_VERIFY(r[1] == -4); + + BH_Vec2iMul(a, b, r); + BH_VERIFY(r[0] == 5); + BH_VERIFY(r[1] == 12); + + BH_Vec2iScale(a, 10, r); + BH_VERIFY(r[0] == 10); + BH_VERIFY(r[1] == 20); + + BH_Vec2iMulAdd(a, b, c, r); + BH_VERIFY(r[0] == 9); + BH_VERIFY(r[1] == 15); + + BH_Vec2iNegate(a, r); + BH_VERIFY(r[0] == -1); + BH_VERIFY(r[1] == -2); + + BH_Vec2iMin(a, b, r); + BH_VERIFY(r[0] == 1); + BH_VERIFY(r[1] == 2); + + BH_Vec2iMax(a, b, r); + BH_VERIFY(r[0] == 5); + BH_VERIFY(r[1] == 6); + + return 0; +} + + +static int checkQuat(void) +{ + return 0; +} + + +static int checkMat4f(void) +{ + float a[16], b[16], r[16]; + float value; + + a[0] = 5.0f; a[4] = 1.0f; a[8] = 2.0f; a[12] = 7.0f; + a[1] = 3.0f; a[5] = 0.0f; a[9] = 0.0f; a[13] = 2.0f; + a[2] = 1.0f; a[6] = 3.0f; a[10] = 4.0f; a[14] = 5.0f; + a[3] = 2.0f; a[7] = 0.0f; a[11] = 0.0f; a[15] = 3.0f; + + b[0] = 5.0f; b[4] = 1.0f; b[8] = 2.0f; b[12] = 7.0f; + b[1] = 3.0f; b[5] = 1.0f; b[9] = 0.0f; b[13] = 2.0f; + b[2] = 4.0f; b[6] = 2.0f; b[10] = 4.0f; b[14] = 5.0f; + b[3] = 6.0f; b[7] = 2.0f; b[11] = 0.0f; b[15] = 4.0f; + + BH_Mat4fIdentity(r); + BH_VERIFY(r[0] == 1.0f); + BH_VERIFY(r[1] == 0.0f); + BH_VERIFY(r[2] == 0.0f); + BH_VERIFY(r[3] == 0.0f); + + BH_VERIFY(r[4] == 0.0f); + BH_VERIFY(r[5] == 1.0f); + BH_VERIFY(r[6] == 0.0f); + BH_VERIFY(r[7] == 0.0f); + + BH_VERIFY(r[8] == 0.0f); + BH_VERIFY(r[9] == 0.0f); + BH_VERIFY(r[10] == 1.0f); + BH_VERIFY(r[11] == 0.0f); + + BH_VERIFY(r[12] == 0.0f); + BH_VERIFY(r[13] == 0.0f); + BH_VERIFY(r[14] == 0.0f); + BH_VERIFY(r[15] == 1.0f); + + BH_Mat4fAdd(a, b, r); + BH_VERIFY_DELTA(r[0], 10.0f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[1], 6.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[2], 5.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[3], 8.0000f, ACCEPTABLE_DELTA); + + BH_VERIFY_DELTA(r[4], 2.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[5], 1.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[6], 5.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[7], 2.0000f, ACCEPTABLE_DELTA); + + BH_VERIFY_DELTA(r[8], 4.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[9], 0.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[10], 8.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[11], 0.0000f, ACCEPTABLE_DELTA); + + BH_VERIFY_DELTA(r[12], 14.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[13], 4.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[14], 10.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[15], 7.0000f, ACCEPTABLE_DELTA); + + BH_Mat4fSub(a, b, r); + BH_VERIFY_DELTA(r[0], 0.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[1], 0.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[2], -3.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[3], -4.0000f, ACCEPTABLE_DELTA); + + BH_VERIFY_DELTA(r[4], 0.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[5], -1.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[6], 1.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[7], -2.0000f, ACCEPTABLE_DELTA); + + BH_VERIFY_DELTA(r[8], 0.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[9], 0.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[10], 0.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[11], 0.0000f, ACCEPTABLE_DELTA); + + BH_VERIFY_DELTA(r[12], 0.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[13], 0.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[14], 0.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[15], -1.0000f, ACCEPTABLE_DELTA); + + BH_Mat4fMul(a, b, r); + BH_VERIFY_DELTA(r[0], 78.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[1], 27.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[2], 60.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[3], 28.0000f, ACCEPTABLE_DELTA); + + BH_VERIFY_DELTA(r[4], 24.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[5], 7.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[6], 22.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[7], 8.0000f, ACCEPTABLE_DELTA); + + BH_VERIFY_DELTA(r[8], 18.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[9], 6.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[10], 18.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[11], 4.0000f, ACCEPTABLE_DELTA); + + BH_VERIFY_DELTA(r[12], 75.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[13], 29.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[14], 53.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[15], 26.0000f, ACCEPTABLE_DELTA); + + BH_Mat4fScale(a, 10, r); + BH_VERIFY_DELTA(r[0], 50.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[1], 30.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[2], 10.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[3], 20.0000f, ACCEPTABLE_DELTA); + + BH_VERIFY_DELTA(r[4], 10.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[5], 0.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[6], 30.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[7], 0.0000f, ACCEPTABLE_DELTA); + + BH_VERIFY_DELTA(r[8], 20.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[9], 0.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[10], 40.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[11], 0.0000f, ACCEPTABLE_DELTA); + + BH_VERIFY_DELTA(r[12], 70.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[13], 20.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[14], 50.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[15], 30.0000f, ACCEPTABLE_DELTA); + + BH_Mat4fTranspose(a, r); + BH_VERIFY_DELTA(r[0], 5.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[1], 1.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[2], 2.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[3], 7.0000f, ACCEPTABLE_DELTA); + + BH_VERIFY_DELTA(r[4], 3.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[5], 0.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[6], 0.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[7], 2.0000f, ACCEPTABLE_DELTA); + + BH_VERIFY_DELTA(r[8], 1.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[9], 3.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[10], 4.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[11], 5.0000f, ACCEPTABLE_DELTA); + + BH_VERIFY_DELTA(r[12], 2.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[13], 0.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[14], 0.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[15], 3.0000f, ACCEPTABLE_DELTA); + + value = BH_Mat4fTrace(a); + BH_VERIFY_DELTA(value, 12.0000f, ACCEPTABLE_DELTA); + + value = BH_Mat4fDet(a); + BH_VERIFY_DELTA(value, 10.0000f, ACCEPTABLE_DELTA); + + value = BH_Mat4fDet(b); + BH_VERIFY_DELTA(value, 0.0000f, ACCEPTABLE_DELTA); + + BH_VERIFY(BH_Mat4fInverse(a, r) == BH_OK); + BH_VERIFY_DELTA(r[0], 0.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[1], -2.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[2], 1.5000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[3], 0.0000f, ACCEPTABLE_DELTA); + + BH_VERIFY_DELTA(r[4], 0.6000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[5], 1.8000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[6], -1.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[7], -0.4000f, ACCEPTABLE_DELTA); + + BH_VERIFY_DELTA(r[8], 0.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[9], 1.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[10], -0.5000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[11], 0.0000f, ACCEPTABLE_DELTA); + + BH_VERIFY_DELTA(r[12], -0.4000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[13], 1.8000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[14], -2.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[15], 0.6000f, ACCEPTABLE_DELTA); + + BH_VERIFY(BH_Mat4fInverse(b, r) != BH_OK); + + return 0; +} + + +static int checkMat3f(void) +{ + float a[9], b[9], r[9]; + float value; + + a[0] = 5.0f; a[3] = 1.0f; a[6] = 2.0f; + a[1] = 3.0f; a[4] = 0.0f; a[7] = 0.0f; + a[2] = 1.0f; a[5] = 3.0f; a[8] = 4.0f; + + b[0] = 2.0f; b[3] = 1.0f; b[6] = 2.0f; + b[1] = 3.0f; b[4] = 1.0f; b[7] = 0.0f; + b[2] = 4.0f; b[5] = 2.0f; b[8] = 4.0f; + + BH_Mat3fIdentity(r); + BH_VERIFY(r[0] == 1.0f); + BH_VERIFY(r[1] == 0.0f); + BH_VERIFY(r[2] == 0.0f); + + BH_VERIFY(r[3] == 0.0f); + BH_VERIFY(r[4] == 1.0f); + BH_VERIFY(r[5] == 0.0f); + + BH_VERIFY(r[6] == 0.0f); + BH_VERIFY(r[7] == 0.0f); + BH_VERIFY(r[8] == 1.0f); + + BH_Mat3fAdd(a, b, r); + BH_VERIFY_DELTA(r[0], 7.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[1], 6.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[2], 5.0000f, ACCEPTABLE_DELTA); + + BH_VERIFY_DELTA(r[3], 2.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[4], 1.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[5], 5.0000f, ACCEPTABLE_DELTA); + + BH_VERIFY_DELTA(r[6], 4.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[7], 0.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[8], 8.0000f, ACCEPTABLE_DELTA); + + BH_Mat3fSub(a, b, r); + BH_VERIFY_DELTA(r[0], 3.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[1], 0.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[2], -3.0000f, ACCEPTABLE_DELTA); + + BH_VERIFY_DELTA(r[3], 0.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[4], -1.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[5], 1.0000f, ACCEPTABLE_DELTA); + + BH_VERIFY_DELTA(r[6], 0.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[7], 0.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[8], 0.0000f, ACCEPTABLE_DELTA); + + BH_Mat3fMul(a, b, r); + BH_VERIFY_DELTA(r[0], 21.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[1], 6.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[2], 27.0000f, ACCEPTABLE_DELTA); + + BH_VERIFY_DELTA(r[3], 10.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[4], 3.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[5], 12.0000f, ACCEPTABLE_DELTA); + + BH_VERIFY_DELTA(r[6], 18.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[7], 6.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[8], 18.0000f, ACCEPTABLE_DELTA); + + BH_Mat3fScale(a, 10, r); + BH_VERIFY_DELTA(r[0], 50.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[1], 30.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[2], 10.0000f, ACCEPTABLE_DELTA); + + BH_VERIFY_DELTA(r[3], 10.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[4], 0.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[5], 30.0000f, ACCEPTABLE_DELTA); + + BH_VERIFY_DELTA(r[6], 20.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[7], 0.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[8], 40.0000f, ACCEPTABLE_DELTA); + + BH_Mat3fTranspose(a, r); + BH_VERIFY_DELTA(r[0], 5.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[1], 1.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[2], 2.0000f, ACCEPTABLE_DELTA); + + BH_VERIFY_DELTA(r[3], 3.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[4], 0.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[5], 0.0000f, ACCEPTABLE_DELTA); + + BH_VERIFY_DELTA(r[6], 1.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[7], 3.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[8], 4.0000f, ACCEPTABLE_DELTA); + + value = BH_Mat3fTrace(a); + BH_VERIFY_DELTA(value, 9.0000f, ACCEPTABLE_DELTA); + + value = BH_Mat3fDet(a); + BH_VERIFY_DELTA(value, 6.0000f, ACCEPTABLE_DELTA); + + value = BH_Mat3fDet(b); + BH_VERIFY_DELTA(value, 0.0000f, ACCEPTABLE_DELTA); + + BH_VERIFY(BH_Mat3fInverse(a, r) == BH_OK); + BH_VERIFY_DELTA(r[0], 0.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[1], -2.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[2], 1.5000f, ACCEPTABLE_DELTA); + + BH_VERIFY_DELTA(r[3], 0.3333f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[4], 3.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[5], -2.3333f, ACCEPTABLE_DELTA); + + BH_VERIFY_DELTA(r[6], 0.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[7], 1.0000f, ACCEPTABLE_DELTA); + BH_VERIFY_DELTA(r[8], -0.5000f, ACCEPTABLE_DELTA); + + BH_VERIFY(BH_Mat3fInverse(b, r) != BH_OK); + + return 0; +} + + +int main(int argc, char **argv) +{ + (void)argc; + (void)argv; + + BH_UnitAdd("Vec4f", checkVec4f); + BH_UnitAdd("Vec3f", checkVec3f); + BH_UnitAdd("Vec2f", checkVec2f); + BH_UnitAdd("Vec4i", checkVec4i); + BH_UnitAdd("Vec3i", checkVec3i); + BH_UnitAdd("Vec2i", checkVec2i); + BH_UnitAdd("Quat", checkQuat); + BH_UnitAdd("Mat4f", checkMat4f); + BH_UnitAdd("Mat3f", checkMat3f); + + return BH_UnitRun(); +} diff --git a/test/src/TestQueue.c b/test/src/TestQueue.c new file mode 100644 index 0000000..8f1fc75 --- /dev/null +++ b/test/src/TestQueue.c @@ -0,0 +1,171 @@ +#include +#include + + +static int NewFree(void) +{ + BH_Queue *queue; + + queue = BH_QueueNew(); + BH_VERIFY(queue != NULL); + BH_VERIFY(BH_QueueSize(queue) == 0); + BH_VERIFY(BH_QueueCapacity(queue) == 0); + BH_VERIFY(BH_QueueEmpty(queue) != 0); + + BH_QueueFree(queue); + return 0; +} + + +static int GrowShrink(void) +{ + BH_Queue *queue; + void *value; + + queue = BH_QueueNew(); + BH_VERIFY(queue != NULL); + + /* Reserve 1024 elements and insert item into queue */ + BH_VERIFY(BH_QueueReserve(queue, 1024) == BH_OK); + BH_VERIFY(BH_QueueInsert(queue, BH_INT2PTR(1337)) == BH_OK); + BH_VERIFY(BH_QueueCapacity(queue) >= 1024); + BH_VERIFY(BH_QueueSize(queue) == 1); + BH_VERIFY(BH_QueueEmpty(queue) == 0); + + /* Check queue content */ + BH_VERIFY(BH_QueueFront(queue, &value) == BH_OK); + BH_VERIFY(BH_PTR2INT(value) == 1337); + + /* Grow queue */ + BH_VERIFY(BH_QueueReserve(queue, 8192) == BH_OK); + BH_VERIFY(BH_QueueCapacity(queue) >= 8192); + BH_VERIFY(BH_QueueSize(queue) == 1); + BH_VERIFY(BH_QueueEmpty(queue) == 0); + + /* Check queue content */ + BH_VERIFY(BH_QueueFront(queue, &value) == BH_OK); + BH_VERIFY(BH_PTR2INT(value) == 1337); + + /* Shrink the queue */ + BH_VERIFY(BH_QueueReserve(queue, 0) == BH_OK); + BH_VERIFY(BH_QueueCapacity(queue) >= 1); + BH_VERIFY(BH_QueueCapacity(queue) < 8192); + BH_VERIFY(BH_QueueSize(queue) == 1); + BH_VERIFY(BH_QueueEmpty(queue) == 0); + + /* Check queue content */ + BH_VERIFY(BH_QueueFront(queue, &value) == BH_OK); + BH_VERIFY(BH_PTR2INT(value) == 1337); + + /* Shrink to 0 (deallocate) */ + BH_QueueClear(queue); + BH_VERIFY(BH_QueueSize(queue) == 0); + BH_VERIFY(BH_QueueEmpty(queue) != 0); + BH_VERIFY(BH_QueueCapacity(queue) >= 1); + + BH_VERIFY(BH_QueueReserve(queue, 0) == BH_OK); + BH_VERIFY(BH_QueueSize(queue) == 0); + BH_VERIFY(BH_QueueEmpty(queue) != 0); + BH_VERIFY(BH_QueueCapacity(queue) == 0); + + BH_QueueFree(queue); + return 0; +} + + +static int InsertRemove(void) +{ + BH_Queue *queue; + size_t i, added, removed; + void *iter; + + queue = BH_QueueNew(); + BH_VERIFY(queue != NULL); + + added = 0; + for (i = 0; i < 256; i++) + { + added += i * 2; + BH_VERIFY(BH_QueueInsert(queue, BH_INT2PTR(i * 2)) == BH_OK); + } + + removed = 0; + iter = BH_QueueIterNext(queue, NULL); + while (iter) + { + void *value; + + BH_VERIFY(BH_QueueFront(queue, &value) == BH_OK); + removed += BH_PTR2INT(value); + + BH_QueueRemove(queue); + iter = BH_QueueIterNext(queue, NULL); + } + + BH_VERIFY(added == removed); + BH_VERIFY(BH_QueueEmpty(queue) != 0); + BH_VERIFY(BH_QueueSize(queue) == 0); + + BH_QueueFree(queue); + return 0; +} + + +static int Rollover(void) +{ + BH_Queue *queue; + size_t i, j, capacity; + + queue = BH_QueueNew(); + BH_VERIFY(queue != NULL); + + BH_VERIFY(BH_QueueReserve(queue, 128) == 0); + capacity = BH_QueueCapacity(queue); + + for (i = 0; i < 128; i++) + { + for (j = 0; j < 3; j++) + BH_QueueRemove(queue); + + for (j = 0; j < 4 && BH_QueueSize(queue) < 128; j++) + BH_VERIFY(BH_QueueInsert(queue, BH_INT2PTR(i * 4 + j)) == 0); + } + + BH_VERIFY(BH_QueueSize(queue) == 128); + BH_VERIFY(BH_QueueCapacity(queue) == capacity); + + BH_QueueFree(queue); + return 0; +} + + +static int Fields(void) +{ + BH_Queue *queue; + + queue = BH_QueueNew(); + BH_VERIFY(queue != NULL); + + BH_VERIFY(BH_QueueInsert(queue, BH_INT2PTR(1337)) == 0); + BH_VERIFY(BH_QueueSize(queue) == 1); + BH_VERIFY(BH_QueueEmpty(queue) == 0); + BH_VERIFY(BH_QueueCapacity(queue) >= 1); + + BH_QueueFree(queue); + return 0; +} + + +int main(int argc, char **argv) +{ + (void)argc; + (void)argv; + + BH_UnitAdd("NewFree", NewFree); + BH_UnitAdd("GrowShrink", GrowShrink); + BH_UnitAdd("InsertRemove", InsertRemove); + BH_UnitAdd("Rollover", Rollover); + BH_UnitAdd("Fields", Fields); + + return BH_UnitRun(); +} diff --git a/test/src/testalgo.c b/test/src/testalgo.c deleted file mode 100644 index 63c1879..0000000 --- a/test/src/testalgo.c +++ /dev/null @@ -1,484 +0,0 @@ -#include -#include -#include -#include - - -static int DBG_IntEqual(const void *lhs, - const void *rhs) -{ - return *(const int*)lhs - *(const int*)rhs; -} - - -static int DBG_VerifyPartition(size_t index, - int pivot, - int *array, - size_t size) -{ - size_t i; - - for (i = 0; i < index; i++) - if (array[i] >= pivot) - return -1; - - for (i = index; i < size; i++) - if (array[i] < pivot) - return -1; - - return 0; -} - - -static int DBG_VerifyHeap(int *array, - size_t size) -{ - size_t i, left, right; - - for (i = 0; i < size; i++) - { - left = i * 2 + 1; - right = i * 2 + 2; - - if (left < size && array[i] < array[left]) - return -1; - if (right < size && array[i] < array[right]) - return -1; - } - - return 0; -} - - -static int DBG_ReferenceRand(void) -{ - static uint32_t next = 2025; - next = next * 1103515245 + 12345; - return (next / 65536) % 32768; -} - - -static void DBG_ReferenceSort(int *array, - size_t size) -{ - size_t i, j; - int tmp; - - /* Reference sort is... buble sort! */ - for (i = 0; i < size; i++) - { - for (j = 1; j < size; j++) - { - if (array[j - 1] > array[j]) - { - tmp = array[j - 1]; - array[j - 1] = array[j]; - array[j] = tmp; - } - } - } -} - - -static void DBG_FillArrays(int *array, - int *reference, - size_t size, - int mask) -{ - size_t i; - int negate; - - /* Check if mask needs to be negated */ - negate = mask < 0; - if (negate) - mask = -mask; - - /* Fill the array */ - for (i = 0; i < size; ++i) - { - array[i] = DBG_ReferenceRand(); - - if (mask > 1) - array[i] = array[i] % mask; - - if (negate) - array[i] = -array[i]; - - if (reference) - reference[i] = array[i]; - } -} - - -static int CheckSort(void) -{ - size_t sizes[] = {1, 2, 3, 5, 11, 23, 41, 79, 163, 317, 0}, *size; - int reference[317], data[317]; - - /* Test empty array and one element arrays */ - data[0] = 1; data[1] = 2; data[2] = 3; - BH_Sort(data, 0, sizeof(int), DBG_IntEqual); - BH_VERIFY(data[0] == 1); - BH_VERIFY(data[1] == 2); - BH_VERIFY(data[2] == 3); - - BH_Sort(data, 1, sizeof(int), DBG_IntEqual); - BH_VERIFY(data[0] == 1); - BH_VERIFY(data[1] == 2); - BH_VERIFY(data[2] == 3); - - /* Test array against different sizes */ - for (size = sizes; *size; ++size) - { - DBG_FillArrays(data, reference, *size, 0); - DBG_ReferenceSort(reference, *size); - BH_Sort(data, *size, sizeof(int), DBG_IntEqual); - BH_VERIFY(memcmp(reference, data, *size * sizeof(int)) == 0); - } - - /* Test against negative values */ - for (size = sizes; *size; ++size) - { - DBG_FillArrays(data, reference, *size, -1); - DBG_ReferenceSort(reference, *size); - BH_Sort(data, *size, sizeof(int), DBG_IntEqual); - BH_VERIFY(memcmp(reference, data, *size * sizeof(int)) == 0); - } - - /* Test against duplicates */ - for (size = sizes; *size; ++size) - { - DBG_FillArrays(data, reference, *size, 4); - DBG_ReferenceSort(reference, *size); - BH_Sort(data, *size, sizeof(int), DBG_IntEqual); - BH_VERIFY(memcmp(reference, data, *size * sizeof(int)) == 0); - } - - return 0; -} - - -static int CheckPartition(void) -{ - size_t sizes[] = {1, 2, 3, 5, 11, 23, 41, 79, 163, 317, 0}, *size; - int reference[317], data[317], value, *pivot; - - /* Test empty array and one element array */ - data[0] = 1; data[1] = 2; data[2] = 3; - value = 0; - pivot = BH_Partition(&value, data, 0, sizeof(int), DBG_IntEqual); - BH_VERIFY(pivot != NULL); - BH_VERIFY(data[0] == 1); - BH_VERIFY(data[1] == 2); - BH_VERIFY(data[2] == 3); - - pivot = BH_Partition(&value, data, 1, sizeof(int), DBG_IntEqual); - BH_VERIFY(pivot == data); - BH_VERIFY(data[0] == 1); - BH_VERIFY(data[1] == 2); - BH_VERIFY(data[2] == 3); - - /* Test array against different sizes */ - for (size = sizes; *size; ++size) - { - DBG_FillArrays(data, reference, *size, 0); - value = 16384; - pivot = BH_Partition(&value, data, *size, sizeof(int), DBG_IntEqual); - BH_VERIFY(DBG_VerifyPartition(pivot - data, value, data, *size) == 0); - - DBG_ReferenceSort(data, *size); - DBG_ReferenceSort(reference, *size); - BH_VERIFY(memcmp(data, reference, *size * sizeof(int)) == 0); - } - - /* Test against negative values */ - for (size = sizes; *size; ++size) - { - DBG_FillArrays(data, reference, *size, -1); - value = -16384; - pivot = BH_Partition(&value, data, *size, sizeof(int), DBG_IntEqual); - BH_VERIFY(DBG_VerifyPartition(pivot - data, value, data, *size) == 0); - - DBG_ReferenceSort(data, *size); - DBG_ReferenceSort(reference, *size); - BH_VERIFY(memcmp(data, reference, *size * sizeof(int)) == 0); - } - - /* Test against duplicates */ - for (size = sizes; *size; ++size) - { - DBG_FillArrays(data, reference, *size, 4); - value = 2; - pivot = BH_Partition(&value, data, *size, sizeof(int), DBG_IntEqual); - BH_VERIFY(DBG_VerifyPartition(pivot - data, value, data, *size) == 0); - - DBG_ReferenceSort(data, *size); - DBG_ReferenceSort(reference, *size); - BH_VERIFY(memcmp(data, reference, *size * sizeof(int)) == 0); - } - - /* Test array against small pivots */ - for (size = sizes; *size; ++size) - { - DBG_FillArrays(data, reference, *size, 0); - value = -100; - pivot = BH_Partition(&value, data, *size, sizeof(int), DBG_IntEqual); - BH_VERIFY(DBG_VerifyPartition(pivot - data, value, data, *size) == 0); - - DBG_ReferenceSort(data, *size); - DBG_ReferenceSort(reference, *size); - BH_VERIFY(memcmp(data, reference, *size * sizeof(int)) == 0); - } - - /* Test array against large pivots */ - for (size = sizes; *size; ++size) - { - DBG_FillArrays(data, reference, *size, 0); - value = 65536; - pivot = BH_Partition(&value, data, *size, sizeof(int), DBG_IntEqual); - BH_VERIFY(DBG_VerifyPartition(pivot - data, value, data, *size) == 0); - - DBG_ReferenceSort(data, *size); - DBG_ReferenceSort(reference, *size); - BH_VERIFY(memcmp(data, reference, *size * sizeof(int)) == 0); - } - - /* Test array against different sizes (pivot inside the array) */ - for (size = sizes; *size; ++size) - { - DBG_FillArrays(data, reference, *size, 0); - value = data[0]; - pivot = BH_Partition(data, data, *size, sizeof(int), DBG_IntEqual); - BH_VERIFY(DBG_VerifyPartition(pivot - data, value, data, *size) == 0); - - DBG_ReferenceSort(data, *size); - DBG_ReferenceSort(reference, *size); - BH_VERIFY(memcmp(data, reference, *size * sizeof(int)) == 0); - } - - /* Test against negative values (pivot inside the array) */ - for (size = sizes; *size; ++size) - { - DBG_FillArrays(data, reference, *size, -1); - value = data[0]; - pivot = BH_Partition(data, data, *size, sizeof(int), DBG_IntEqual); - BH_VERIFY(DBG_VerifyPartition(pivot - data, value, data, *size) == 0); - - DBG_ReferenceSort(data, *size); - DBG_ReferenceSort(reference, *size); - BH_VERIFY(memcmp(data, reference, *size * sizeof(int)) == 0); - } - - /* Test against duplicates (pivot inside the array) */ - for (size = sizes; *size; ++size) - { - DBG_FillArrays(data, reference, *size, 4); - value = data[0]; - pivot = BH_Partition(data, data, *size, sizeof(int), DBG_IntEqual); - BH_VERIFY(DBG_VerifyPartition(pivot - data, value, data, *size) == 0); - - DBG_ReferenceSort(data, *size); - DBG_ReferenceSort(reference, *size); - BH_VERIFY(memcmp(data, reference, *size * sizeof(int)) == 0); - } - - /* Same data test */ - for (size = sizes; *size; ++size) - { - memset(data, 0, sizeof(int) * *size); - memset(reference, 0, sizeof(int) * *size); - value = data[*size - 1]; - pivot = BH_Partition(data + *size - 1, data, *size, sizeof(int), DBG_IntEqual); - BH_VERIFY(DBG_VerifyPartition(pivot - data, value, data, *size) == 0); - - DBG_ReferenceSort(data, *size); - DBG_ReferenceSort(reference, *size); - BH_VERIFY(memcmp(data, reference, *size * sizeof(int)) == 0); - } - - return 0; -} - - -static int CheckHeapMake(void) -{ - size_t sizes[] = {1, 2, 3, 5, 11, 23, 41, 79, 163, 317, 0}, *size; - int data[317]; - - /* Test empty array */ - data[0] = 1; data[1] = 2; data[2] = 3; - BH_HeapMake(data, 0, sizeof(int), DBG_IntEqual); - BH_VERIFY(data[0] == 1); - BH_VERIFY(data[1] == 2); - BH_VERIFY(data[2] == 3); - - /* Test array against different sizes */ - for (size = sizes; *size; ++size) - { - DBG_FillArrays(data, NULL, *size, 0); - BH_HeapMake(data, *size, sizeof(int), DBG_IntEqual); - BH_VERIFY(DBG_VerifyHeap(data, *size) == 0); - } - - /* Test array against negative values */ - for (size = sizes; *size; ++size) - { - DBG_FillArrays(data, NULL, *size, -1); - BH_HeapMake(data, *size, sizeof(int), DBG_IntEqual); - BH_VERIFY(DBG_VerifyHeap(data, *size) == 0); - } - - /* Test against duplicates */ - for (size = sizes; *size; ++size) - { - DBG_FillArrays(data, NULL, *size, 4); - BH_HeapMake(data, *size, sizeof(int), DBG_IntEqual); - BH_VERIFY(DBG_VerifyHeap(data, *size) == 0); - } - - return 0; -} - - -static int CheckHeapInsert(void) -{ - size_t sizes[] = {1, 2, 3, 5, 11, 23, 41, 79, 163, 317, 0}, *size; - int data[317], reference[317]; - - /* Test array against different sizes */ - for (size = sizes; *size; ++size) - { - size_t i; - DBG_FillArrays(data, reference, *size, 0); - for (i = 0; i < *size; ++i) - { - int value; - - value = data[i]; - BH_HeapInsert(&value, data, i, sizeof(int), DBG_IntEqual); - BH_VERIFY(DBG_VerifyHeap(data, i + 1) == 0); - } - - DBG_ReferenceSort(data, *size); - DBG_ReferenceSort(reference, *size); - BH_VERIFY(memcmp(data, reference, *size) == 0); - } - - /* Test array against different sizes (inplace)*/ - for (size = sizes; *size; ++size) - { - size_t i; - DBG_FillArrays(data, reference, *size, 0); - for (i = 0; i < *size; ++i) - { - BH_HeapInsert(NULL, data, i, sizeof(int), DBG_IntEqual); - BH_VERIFY(DBG_VerifyHeap(data, i + 1) == 0); - } - - DBG_ReferenceSort(data, *size); - DBG_ReferenceSort(reference, *size); - BH_VERIFY(memcmp(data, reference, *size) == 0); - } - - return 0; -} - - -static int CheckHeapRemove(void) -{ - size_t sizes[] = {1, 2, 3, 5, 11, 23, 41, 79, 163, 317, 0}, *size; - int data[317], reference[317]; - - /* Test array against different sizes */ - for (size = sizes; *size; ++size) - { - size_t i; - DBG_FillArrays(data, reference, *size, 0); - BH_HeapMake(data, *size, sizeof(int), DBG_IntEqual); - - for (i = *size; i > 0; i--) - { - BH_VERIFY(DBG_VerifyHeap(data, i) == 0); - BH_HeapRemove(data, i, sizeof(int), DBG_IntEqual); - } - - DBG_ReferenceSort(data, *size); - DBG_ReferenceSort(reference, *size); - BH_VERIFY(memcmp(data, reference, *size) == 0); - } - - return 0; -} - - -static int CheckHeapReplace(void) -{ - int data[11] = {1, 2, 3, 5, 11, 23, 41, 79, 163, 317, 0}; - int reference[11] = {1, 2, 3, 5, 11, 23, 41, 79, 163, 317, 0}; - int value; - - /* Prepare test arrays */ - BH_HeapMake(data, 10, sizeof(int), DBG_IntEqual); - BH_HeapMake(reference, 10, sizeof(int), DBG_IntEqual); - BH_VERIFY(DBG_VerifyHeap(data, 10) == 0); - BH_VERIFY(DBG_VerifyHeap(reference, 10) == 0); - - /* Verfify heap replace */ - value = 20; - BH_HeapReplace(&value, data, 10, sizeof(int), DBG_IntEqual); - BH_HeapRemove(reference, 10, sizeof(int), DBG_IntEqual); - BH_HeapInsert(&value, reference, 9, sizeof(int), DBG_IntEqual); - - BH_VERIFY(DBG_VerifyHeap(data, 10) == 0); - BH_VERIFY(DBG_VerifyHeap(reference, 10) == 0); - BH_Sort(data, 10, sizeof(int), DBG_IntEqual); - BH_Sort(reference, 10, sizeof(int), DBG_IntEqual); - BH_VERIFY(memcmp(data, reference, 10 * sizeof(int)) == 0); - - /* Verify heap replace on single element array */ - value = 400; - BH_HeapReplace(&value, data, 1, sizeof(int), DBG_IntEqual); - BH_HeapRemove(reference, 1, sizeof(int), DBG_IntEqual); - BH_HeapInsert(&value, reference, 0, sizeof(int), DBG_IntEqual); - - BH_VERIFY(DBG_VerifyHeap(data, 1) == 0); - BH_VERIFY(DBG_VerifyHeap(reference, 1) == 0); - BH_VERIFY(memcmp(data, reference, 1 * sizeof(int)) == 0); - - /* Prepare test arrays */ - BH_Sort(data, 10, sizeof(int), DBG_IntEqual); - BH_Sort(reference, 10, sizeof(int), DBG_IntEqual); - BH_HeapMake(data, 10, sizeof(int), DBG_IntEqual); - BH_HeapMake(reference, 10, sizeof(int), DBG_IntEqual); - BH_VERIFY(DBG_VerifyHeap(data, 10) == 0); - BH_VERIFY(DBG_VerifyHeap(reference, 10) == 0); - - data[10] = 1000; - value = 1000; - BH_HeapReplace(NULL, data, 10, sizeof(int), DBG_IntEqual); - BH_HeapRemove(reference, 10, sizeof(int), DBG_IntEqual); - BH_HeapInsert(&value, reference, 9, sizeof(int), DBG_IntEqual); - BH_VERIFY(DBG_VerifyHeap(data, 10) == 0); - BH_VERIFY(DBG_VerifyHeap(reference, 10) == 0); - BH_Sort(data, 10, sizeof(int), DBG_IntEqual); - BH_Sort(reference, 10, sizeof(int), DBG_IntEqual); - BH_VERIFY(memcmp(data, reference, 10 * sizeof(int)) == 0); - - return 0; -} - - -int main(int argc, char **argv) -{ - BH_UNUSED(argc); - BH_UNUSED(argv); - - BH_UnitAdd("Sort", CheckSort); - BH_UnitAdd("Partition", CheckPartition); - BH_UnitAdd("HeapMake", CheckHeapMake); - BH_UnitAdd("HeapInsert", CheckHeapInsert); - BH_UnitAdd("HeapRemove", CheckHeapRemove); - BH_UnitAdd("HeapReplace", CheckHeapReplace); - - return BH_UnitRun(); -} diff --git a/test/src/testfile.c b/test/src/testfile.c deleted file mode 100644 index 194b52a..0000000 --- a/test/src/testfile.c +++ /dev/null @@ -1,630 +0,0 @@ -#include -#include -#include - - -#define FILENAME1 "bhfile1.dat" -#define FILENAME2 "bhfile2.dat" -#define FILENAME3 "bhfile3.dat" -#define FILENAME4 "bhfile4.dat" - - -/** - * Cleanup any files, that could be left from previous test runs. - */ -static void cleanup(void) -{ - remove(FILENAME1); - remove(FILENAME2); - remove(FILENAME3); - remove(FILENAME4); -} - - -/** - * Check for invalid arguments. - */ -static int checkNull(void) -{ - BH_IO *io; - - /* Check against NULL pointers */ - BH_VERIFY(BH_FileNew(NULL) == NULL); - BH_VERIFY(BH_IOClassname(NULL) == NULL); - BH_VERIFY(BH_IOOpen(NULL, 0) != BH_OK); - BH_VERIFY(BH_IOClose(NULL) != BH_OK); - BH_VERIFY(BH_IORead(NULL, NULL, 0, NULL) != BH_OK); - BH_VERIFY(BH_IOWrite(NULL, NULL, 0, NULL) != BH_OK); - BH_VERIFY(BH_IOPeek(NULL, NULL, 0, NULL) != BH_OK); - BH_VERIFY(BH_IOTell(NULL, NULL) != BH_OK); - BH_VERIFY(BH_IOSeek(NULL, 0, 0) != BH_OK); - BH_VERIFY(BH_IOFlush(NULL) != BH_OK); - BH_VERIFY(BH_IOSize(NULL, NULL) != BH_OK); - BH_VERIFY(BH_IOFlags(NULL) == BH_IO_FLAG_ERROR); - BH_VERIFY(BH_IOClear(NULL) == BH_OK); - BH_IOFree(NULL); - - /* Check against NULL pointers and valid IO object */ - BH_VERIFY((io = BH_FileNew(FILENAME1)) != NULL); - BH_VERIFY(strcmp(BH_IOClassname(io), BH_FILE_CLASSNAME) == 0); - BH_VERIFY(BH_IOOpen(io, 0) != BH_OK); - BH_VERIFY(BH_IOClose(io) != BH_OK); - BH_VERIFY(BH_IORead(io, NULL, 0, NULL) != BH_OK); - BH_VERIFY(BH_IOWrite(io, NULL, 0, NULL) != BH_OK); - BH_VERIFY(BH_IOPeek(io, NULL, 0, NULL) != BH_OK); - BH_VERIFY(BH_IOTell(io, NULL) != BH_OK); - BH_VERIFY(BH_IOSeek(io, 0, 0) != BH_OK); - BH_VERIFY(BH_IOFlush(io) != BH_OK); - BH_VERIFY(BH_IOSize(io, NULL) != BH_OK); - BH_VERIFY(BH_IOFlags(io) == BH_IO_FLAG_ERROR); - BH_VERIFY(BH_IOClear(io) == BH_OK); - BH_IOFree(io); - - return 0; -} - - -/** - * Check for normal mode. - */ -static int checkNormal(void) -{ - int64_t position; - char buffer[128]; - size_t actual; - BH_IO *io; - - /* Check operations for write only access */ - BH_VERIFY((io = BH_FileNew(FILENAME1)) != NULL); - BH_VERIFY(strcmp(BH_IOClassname(io), BH_FILE_CLASSNAME) == 0); - BH_VERIFY(BH_IOOpen(io, BH_IO_WRITE) == BH_OK); - BH_VERIFY(BH_IOFlags(io) & BH_IO_FLAG_OPEN); - - BH_VERIFY(BH_IOOpen(io, BH_IO_READ) != BH_OK); - - BH_VERIFY(BH_IOWrite(io, "1234567890", 10, &actual) == BH_OK); - BH_VERIFY(actual == 10); - - BH_VERIFY(BH_IOWrite(io, "1234567890", 10, &actual) == BH_OK); - BH_VERIFY(actual == 10); - - BH_VERIFY(BH_IOSeek(io, 10, BH_IO_SEEK_SET) == BH_OK); - BH_VERIFY(BH_IOWrite(io, "abcde", 5, &actual) == BH_OK); - BH_VERIFY(actual == 5); - - BH_VERIFY(BH_IOSeek(io, 0, BH_IO_SEEK_SET) == BH_OK); - BH_VERIFY(BH_IORead(io, buffer, 1, &actual) != BH_OK); - BH_VERIFY(BH_IOSeek(io, 0, BH_IO_SEEK_END) == BH_OK); - BH_VERIFY(BH_IOTell(io, &position) == BH_OK); - BH_VERIFY(position == 20); - BH_IOClose(io); - - /* Check operations for read only access */ - BH_VERIFY(BH_IOOpen(io, BH_IO_READ) == BH_OK); - BH_VERIFY(BH_IOFlags(io) & BH_IO_FLAG_OPEN); - BH_VERIFY(strcmp(BH_IOClassname(io), BH_FILE_CLASSNAME) == 0); - BH_VERIFY(BH_IORead(io, buffer, 10, &actual) == BH_OK); - BH_VERIFY(actual == 10); - BH_VERIFY(memcmp(buffer, "1234567890", 10) == 0); - - BH_VERIFY(BH_IORead(io, buffer, 5, &actual) == BH_OK); - BH_VERIFY(actual == 5); - BH_VERIFY(memcmp(buffer, "abcde", 5) == 0); - - BH_VERIFY(BH_IOSeek(io, 0, BH_IO_SEEK_SET) == BH_OK); - BH_VERIFY(BH_IORead(io, buffer, sizeof(buffer), &actual) == BH_OK); - BH_VERIFY(actual == 20); - BH_VERIFY(memcmp(buffer, "1234567890abcde67890", 20) == 0); - - BH_VERIFY(BH_IOWrite(io, "1234567890", 10, &actual) != BH_OK); - BH_VERIFY(BH_IOSeek(io, -5, BH_IO_SEEK_CUR) == BH_OK); - BH_VERIFY(BH_IORead(io, buffer, 5, &actual) == BH_OK); - BH_VERIFY(actual == 5); - BH_VERIFY(memcmp(buffer, "67890", 5) == 0); - BH_IOFree(io); - - /* Check operations for read and write access */ - BH_VERIFY((io = BH_FileNew(FILENAME1)) != NULL); - BH_VERIFY(strcmp(BH_IOClassname(io), BH_FILE_CLASSNAME) == 0); - BH_VERIFY(BH_IOOpen(io, BH_IO_WRITE | BH_IO_READ) == BH_OK); - BH_VERIFY(BH_IOFlags(io) & BH_IO_FLAG_OPEN); - - BH_VERIFY(BH_IOWrite(io, "abcde", 5, &actual) == BH_OK); - BH_VERIFY(actual == 5); - - BH_VERIFY(BH_IOWrite(io, "1234567890", 10, &actual) == BH_OK); - BH_VERIFY(actual == 10); - - BH_VERIFY(BH_IOWrite(io, "1234567890abcde67890", 20, &actual) == BH_OK); - BH_VERIFY(actual == 20); - - BH_VERIFY(BH_IOSeek(io, 0, BH_IO_SEEK_SET) == BH_OK); - BH_VERIFY(BH_IORead(io, buffer, 5, &actual) == BH_OK); - BH_VERIFY(actual == 5); - BH_VERIFY(memcmp(buffer, "abcde", 5) == 0); - - BH_VERIFY(BH_IORead(io, buffer, 10, &actual) == BH_OK); - BH_VERIFY(actual == 10); - BH_VERIFY(memcmp(buffer, "1234567890", 10) == 0); - - BH_VERIFY(BH_IOSeek(io, 0, BH_IO_SEEK_SET) == BH_OK); - BH_VERIFY(BH_IORead(io, buffer, 35, &actual) == BH_OK); - BH_VERIFY(actual == 35); - BH_VERIFY(memcmp(buffer, "abcde12345678901234567890abcde67890", 35) == 0); - BH_IOClose(io); - - BH_IOFree(io); - return 0; -} - - -/** - * Check for truncate mode. - */ -static int checkTruncate(void) -{ - int64_t position; - char buffer[128]; - size_t actual; - BH_IO *io; - - /* Check operations for write only access */ - BH_VERIFY((io = BH_FileNew(FILENAME1)) != NULL); - BH_VERIFY(strcmp(BH_IOClassname(io), BH_FILE_CLASSNAME) == 0); - BH_VERIFY(BH_IOOpen(io, BH_IO_WRITE | BH_IO_TRUNCATE) == BH_OK); - BH_VERIFY(BH_IOFlags(io) & BH_IO_FLAG_OPEN); - - BH_VERIFY(BH_IOWrite(io, "1234567890", 10, &actual) == BH_OK); - BH_VERIFY(actual == 10); - - BH_VERIFY(BH_IOWrite(io, "1234567890", 10, &actual) == BH_OK); - BH_VERIFY(actual == 10); - - BH_VERIFY(BH_IOSeek(io, 10, BH_IO_SEEK_SET) == BH_OK); - BH_VERIFY(BH_IOWrite(io, "abcde", 5, &actual) == BH_OK); - BH_VERIFY(actual == 5); - - BH_VERIFY(BH_IOSeek(io, 0, BH_IO_SEEK_SET) == BH_OK); - BH_VERIFY(BH_IORead(io, buffer, 1, &actual) != BH_OK); - BH_VERIFY(BH_IOSeek(io, 0, BH_IO_SEEK_END) == BH_OK); - BH_VERIFY(BH_IOTell(io, &position) == BH_OK); - BH_VERIFY(position == 20); - BH_IOClose(io); - - /* Check operations for read only access without truncate */ - BH_VERIFY(BH_IOOpen(io, BH_IO_READ) == BH_OK); - BH_VERIFY(BH_IOFlags(io) & BH_IO_FLAG_OPEN); - BH_VERIFY(BH_IORead(io, buffer, 10, &actual) == BH_OK); - BH_VERIFY(actual == 10); - BH_VERIFY(memcmp(buffer, "1234567890", 10) == 0); - - BH_VERIFY(BH_IORead(io, buffer, 5, &actual) == BH_OK); - BH_VERIFY(actual == 5); - BH_VERIFY(memcmp(buffer, "abcde", 5) == 0); - - BH_VERIFY(BH_IOSeek(io, 0, BH_IO_SEEK_SET) == BH_OK); - BH_VERIFY(BH_IORead(io, buffer, sizeof(buffer), &actual) == BH_OK); - BH_VERIFY(actual == 20); - BH_VERIFY(memcmp(buffer, "1234567890abcde67890", 20) == 0); - - BH_VERIFY(BH_IOSeek(io, -5, BH_IO_SEEK_CUR) == BH_OK); - BH_VERIFY(BH_IORead(io, buffer, 5, &actual) == BH_OK); - BH_VERIFY(actual == 5); - BH_VERIFY(memcmp(buffer, "67890", 5) == 0); - BH_IOClose(io); - - /* Check operations for read only access */ - BH_VERIFY(BH_IOOpen(io, BH_IO_READ | BH_IO_TRUNCATE) == BH_OK); - BH_VERIFY(BH_IOFlags(io) & BH_IO_FLAG_OPEN); - BH_VERIFY(BH_IORead(io, buffer, 10, &actual) == BH_OK); - BH_VERIFY(actual == 0); - - BH_VERIFY(BH_IORead(io, buffer, 5, &actual) == BH_OK); - BH_VERIFY(actual == 0); - - BH_VERIFY(BH_IOWrite(io, "1234567890", 10, &actual) != BH_OK); - BH_VERIFY(BH_IOSeek(io, 0, BH_IO_SEEK_SET) == BH_OK); - BH_VERIFY(BH_IORead(io, buffer, sizeof(buffer), &actual) == BH_OK); - BH_VERIFY(actual == 0); - BH_IOFree(io); - - /* Check operations for read and write access */ - BH_VERIFY((io = BH_FileNew(FILENAME1)) != NULL); - BH_VERIFY(strcmp(BH_IOClassname(io), BH_FILE_CLASSNAME) == 0); - BH_VERIFY(BH_IOOpen(io, BH_IO_WRITE | BH_IO_READ | BH_IO_TRUNCATE) == BH_OK); - BH_VERIFY(BH_IOFlags(io) & BH_IO_FLAG_OPEN); - - BH_VERIFY(BH_IOWrite(io, "abcde", 5, &actual) == BH_OK); - BH_VERIFY(actual == 5); - - BH_VERIFY(BH_IOWrite(io, "1234567890", 10, &actual) == BH_OK); - BH_VERIFY(actual == 10); - - BH_VERIFY(BH_IOWrite(io, "1234567890abcde67890", 20, &actual) == BH_OK); - BH_VERIFY(actual == 20); - - BH_VERIFY(BH_IOSeek(io, 0, BH_IO_SEEK_SET) == BH_OK); - BH_VERIFY(BH_IORead(io, buffer, 5, &actual) == BH_OK); - BH_VERIFY(actual == 5); - BH_VERIFY(memcmp(buffer, "abcde", 5) == 0); - - BH_VERIFY(BH_IORead(io, buffer, 10, &actual) == BH_OK); - BH_VERIFY(actual == 10); - BH_VERIFY(memcmp(buffer, "1234567890", 10) == 0); - - BH_VERIFY(BH_IOSeek(io, 0, BH_IO_SEEK_SET) == BH_OK); - BH_VERIFY(BH_IORead(io, buffer, 35, &actual) == BH_OK); - BH_VERIFY(actual == 35); - BH_VERIFY(memcmp(buffer, "abcde12345678901234567890abcde67890", 35) == 0); - BH_IOClose(io); - - BH_VERIFY(BH_IOOpen(io, BH_IO_WRITE | BH_IO_TRUNCATE) == BH_OK); - BH_VERIFY(BH_IOFlags(io) & BH_IO_FLAG_OPEN); - BH_IOClose(io); - - BH_IOFree(io); - return 0; -} - - -/** - * Check for exist mode. - */ -static int checkExist(void) -{ - int64_t position; - char buffer[128]; - size_t actual; - BH_IO *io; - - /* Check operations for write only access */ - BH_VERIFY((io = BH_FileNew(FILENAME1)) != NULL); - BH_VERIFY(strcmp(BH_IOClassname(io), BH_FILE_CLASSNAME) == 0); - BH_VERIFY(BH_IOOpen(io, BH_IO_WRITE | BH_IO_EXIST) == BH_OK); - BH_VERIFY(BH_IOFlags(io) & BH_IO_FLAG_OPEN); - - BH_VERIFY(BH_IOWrite(io, "1234567890", 10, &actual) == BH_OK); - BH_VERIFY(actual == 10); - - BH_VERIFY(BH_IOWrite(io, "1234567890", 10, &actual) == BH_OK); - BH_VERIFY(actual == 10); - - BH_VERIFY(BH_IOSeek(io, 10, BH_IO_SEEK_SET) == BH_OK); - BH_VERIFY(BH_IOWrite(io, "abcde", 5, &actual) == BH_OK); - BH_VERIFY(actual == 5); - - BH_VERIFY(BH_IOSeek(io, 0, BH_IO_SEEK_SET) == BH_OK); - BH_VERIFY(BH_IORead(io, buffer, 1, &actual) != BH_OK); - BH_VERIFY(BH_IOSeek(io, 0, BH_IO_SEEK_END) == BH_OK); - BH_VERIFY(BH_IOTell(io, &position) == BH_OK); - BH_VERIFY(position == 20); - BH_IOClose(io); - - /* Check operations for read only access */ - BH_VERIFY(BH_IOOpen(io, BH_IO_READ | BH_IO_EXIST) == BH_OK); - BH_VERIFY(BH_IOFlags(io) & BH_IO_FLAG_OPEN); - BH_VERIFY(BH_IORead(io, buffer, 10, &actual) == BH_OK); - BH_VERIFY(actual == 10); - BH_VERIFY(memcmp(buffer, "1234567890", 10) == 0); - - BH_VERIFY(BH_IORead(io, buffer, 5, &actual) == BH_OK); - BH_VERIFY(actual == 5); - BH_VERIFY(memcmp(buffer, "abcde", 5) == 0); - - BH_VERIFY(BH_IOSeek(io, 0, BH_IO_SEEK_SET) == BH_OK); - BH_VERIFY(BH_IORead(io, buffer, sizeof(buffer), &actual) == BH_OK); - BH_VERIFY(actual == 20); - BH_VERIFY(memcmp(buffer, "1234567890abcde67890", 20) == 0); - - BH_VERIFY(BH_IOWrite(io, "1234567890", 10, &actual) != BH_OK); - BH_VERIFY(BH_IOSeek(io, -5, BH_IO_SEEK_CUR) == BH_OK); - BH_VERIFY(BH_IORead(io, buffer, 5, &actual) == BH_OK); - BH_VERIFY(actual == 5); - BH_VERIFY(memcmp(buffer, "67890", 5) == 0); - BH_IOFree(io); - - /* Check operations for read and write access */ - BH_VERIFY((io = BH_FileNew(FILENAME1)) != NULL); - BH_VERIFY(strcmp(BH_IOClassname(io), BH_FILE_CLASSNAME) == 0); - BH_VERIFY(BH_IOOpen(io, BH_IO_WRITE | BH_IO_READ | BH_IO_EXIST) == BH_OK); - BH_VERIFY(BH_IOFlags(io) & BH_IO_FLAG_OPEN); - - BH_VERIFY(BH_IOWrite(io, "abcde", 5, &actual) == BH_OK); - BH_VERIFY(actual == 5); - - BH_VERIFY(BH_IOWrite(io, "1234567890", 10, &actual) == BH_OK); - BH_VERIFY(actual == 10); - - BH_VERIFY(BH_IOWrite(io, "1234567890abcde67890", 20, &actual) == BH_OK); - BH_VERIFY(actual == 20); - - BH_VERIFY(BH_IOSeek(io, 0, BH_IO_SEEK_SET) == BH_OK); - BH_VERIFY(BH_IORead(io, buffer, 5, &actual) == BH_OK); - BH_VERIFY(actual == 5); - BH_VERIFY(memcmp(buffer, "abcde", 5) == 0); - - BH_VERIFY(BH_IORead(io, buffer, 10, &actual) == BH_OK); - BH_VERIFY(actual == 10); - BH_VERIFY(memcmp(buffer, "1234567890", 10) == 0); - - BH_VERIFY(BH_IOSeek(io, 0, BH_IO_SEEK_SET) == BH_OK); - BH_VERIFY(BH_IORead(io, buffer, 35, &actual) == BH_OK); - BH_VERIFY(actual == 35); - BH_VERIFY(memcmp(buffer, "abcde12345678901234567890abcde67890", 35) == 0); - BH_IOClose(io); - BH_IOFree(io); - - /* Check against non existing files */ - BH_VERIFY((io = BH_FileNew(FILENAME2)) != NULL); - BH_VERIFY(strcmp(BH_IOClassname(io), BH_FILE_CLASSNAME) == 0); - BH_VERIFY(BH_IOOpen(io, BH_IO_WRITE | BH_IO_EXIST) != BH_OK); - BH_VERIFY((BH_IOFlags(io) & BH_IO_FLAG_OPEN) == 0); - BH_VERIFY(BH_IOOpen(io, BH_IO_READ | BH_IO_EXIST) != BH_OK); - BH_VERIFY((BH_IOFlags(io) & BH_IO_FLAG_OPEN) == 0); - BH_VERIFY(BH_IOOpen(io, BH_IO_WRITE | BH_IO_READ | BH_IO_EXIST) != BH_OK); - BH_VERIFY((BH_IOFlags(io) & BH_IO_FLAG_OPEN) == 0); - BH_IOFree(io); - return 0; -} - - -/** - * Check in append mode. - */ -static int checkAppend(void) -{ - int64_t position; - char buffer[128]; - size_t actual; - BH_IO *io; - - /* Explicitly call cleanup */ - cleanup(); - - /* Check operations for write only access */ - BH_VERIFY((io = BH_FileNew(FILENAME1)) != NULL); - BH_VERIFY(strcmp(BH_IOClassname(io), BH_FILE_CLASSNAME) == 0); - BH_VERIFY(BH_IOOpen(io, BH_IO_WRITE | BH_IO_APPEND) == BH_OK); - BH_VERIFY(BH_IOFlags(io) & BH_IO_FLAG_OPEN); - - BH_VERIFY(BH_IOWrite(io, "1234567890", 10, &actual) == BH_OK); - BH_VERIFY(actual == 10); - - BH_VERIFY(BH_IOWrite(io, "1234567890", 10, &actual) == BH_OK); - BH_VERIFY(actual == 10); - - BH_VERIFY(BH_IOSeek(io, 10, BH_IO_SEEK_SET) == BH_OK); - BH_VERIFY(BH_IOWrite(io, "abcde", 5, &actual) == BH_OK); - BH_VERIFY(actual == 5); - - BH_VERIFY(BH_IOSeek(io, 0, BH_IO_SEEK_SET) == BH_OK); - BH_VERIFY(BH_IORead(io, buffer, 1, &actual) != BH_OK); - BH_VERIFY(BH_IOSeek(io, 0, BH_IO_SEEK_END) == BH_OK); - BH_VERIFY(BH_IOTell(io, &position) == BH_OK); - BH_VERIFY(position == 25); - BH_IOClose(io); - - /* Check operations for read only access */ - BH_VERIFY(BH_IOOpen(io, BH_IO_READ | BH_IO_APPEND) == BH_OK); - BH_VERIFY(BH_IOFlags(io) & BH_IO_FLAG_OPEN); - BH_VERIFY(strcmp(BH_IOClassname(io), BH_FILE_CLASSNAME) == 0); - BH_VERIFY(BH_IORead(io, buffer, 10, &actual) == BH_OK); - BH_VERIFY(actual == 10); - BH_VERIFY(memcmp(buffer, "1234567890", 10) == 0); - - BH_VERIFY(BH_IORead(io, buffer, 10, &actual) == BH_OK); - BH_VERIFY(actual == 10); - BH_VERIFY(memcmp(buffer, "1234567890", 10) == 0); - - BH_VERIFY(BH_IORead(io, buffer, 5, &actual) == BH_OK); - BH_VERIFY(actual == 5); - BH_VERIFY(memcmp(buffer, "abcde", 5) == 0); - - BH_VERIFY(BH_IOWrite(io, "1234567890", 10, &actual) != BH_OK); - BH_VERIFY(BH_IOSeek(io, -5, BH_IO_SEEK_CUR) == BH_OK); - BH_VERIFY(BH_IORead(io, buffer, 5, &actual) == BH_OK); - BH_VERIFY(actual == 5); - BH_VERIFY(memcmp(buffer, "abcde", 5) == 0); - BH_IOClose(io); - - /* Check operations for read and write access */ - BH_VERIFY(BH_IOOpen(io, BH_IO_WRITE | BH_IO_READ | BH_IO_APPEND) == BH_OK); - BH_VERIFY(BH_IOFlags(io) & BH_IO_FLAG_OPEN); - - BH_VERIFY(BH_IOWrite(io, "abcde", 5, &actual) == BH_OK); - BH_VERIFY(actual == 5); - - BH_VERIFY(BH_IOWrite(io, "1234567890", 10, &actual) == BH_OK); - BH_VERIFY(actual == 10); - - BH_VERIFY(BH_IOSeek(io, 0, BH_IO_SEEK_SET) == BH_OK); - BH_VERIFY(BH_IORead(io, buffer, 40, &actual) == BH_OK); - BH_VERIFY(actual == 40); - BH_VERIFY(memcmp(buffer, "12345678901234567890abcdeabcde1234567890", 40) == 0); - BH_IOClose(io); - - BH_VERIFY(BH_IOOpen(io, BH_IO_WRITE | BH_IO_TRUNCATE) == BH_OK); - BH_VERIFY(BH_IOFlags(io) & BH_IO_FLAG_OPEN); - BH_IOClose(io); - - BH_IOFree(io); - return 0; -} - - -/** - * Check for create mode. - */ -static int checkCreate(void) -{ - BH_IO *io; - - /* Check for already existing file */ - BH_VERIFY((io = BH_FileNew(FILENAME1)) != NULL); - BH_VERIFY(strcmp(BH_IOClassname(io), BH_FILE_CLASSNAME) == 0); - BH_VERIFY(BH_IOOpen(io, BH_IO_WRITE | BH_IO_CREATE) != BH_OK); - BH_VERIFY((BH_IOFlags(io) & BH_IO_FLAG_OPEN) == 0); - BH_IOFree(io); - - /* Check for new file with write access */ - BH_VERIFY((io = BH_FileNew(FILENAME2)) != NULL); - BH_VERIFY(strcmp(BH_IOClassname(io), BH_FILE_CLASSNAME) == 0); - BH_VERIFY(BH_IOOpen(io, BH_IO_WRITE | BH_IO_CREATE) == BH_OK); - BH_VERIFY(BH_IOFlags(io) & BH_IO_FLAG_OPEN); - BH_IOFree(io); - - /* Check for new file with read access */ - BH_VERIFY((io = BH_FileNew(FILENAME3)) != NULL); - BH_VERIFY(strcmp(BH_IOClassname(io), BH_FILE_CLASSNAME) == 0); - BH_VERIFY(BH_IOOpen(io, BH_IO_READ | BH_IO_CREATE) == BH_OK); - BH_VERIFY(BH_IOFlags(io) & BH_IO_FLAG_OPEN); - BH_IOFree(io); - - /* Check for new file with read/write access */ - BH_VERIFY((io = BH_FileNew(FILENAME4)) != NULL); - BH_VERIFY(strcmp(BH_IOClassname(io), BH_FILE_CLASSNAME) == 0); - BH_VERIFY(BH_IOOpen(io, BH_IO_WRITE | BH_IO_READ | BH_IO_CREATE) == BH_OK); - BH_VERIFY(BH_IOFlags(io) & BH_IO_FLAG_OPEN); - BH_IOFree(io); - - return 0; -} - - -/** - * Check for EOF flags. - */ -static int checkEOF(void) -{ - char buffer[128]; - size_t actual; - BH_IO *io; - - BH_VERIFY((io = BH_FileNew(FILENAME1)) != NULL); - BH_VERIFY(strcmp(BH_IOClassname(io), BH_FILE_CLASSNAME) == 0); - BH_VERIFY(BH_IOOpen(io, BH_IO_READ | BH_IO_TRUNCATE) == BH_OK); - BH_VERIFY(BH_IOFlags(io) & BH_IO_FLAG_OPEN); - - BH_VERIFY(BH_IORead(io, buffer, 128, &actual) == BH_OK); - BH_VERIFY(actual == 0); - BH_VERIFY(BH_IOFlags(io) & BH_IO_FLAG_EOF); - - BH_IOClose(io); - BH_IOFree(io); - - return 0; -} - - -/** - * Check for error flags. - */ -static int checkError(void) -{ - size_t actual; - BH_IO *io; - - BH_VERIFY((io = BH_FileNew(FILENAME1)) != NULL); - BH_VERIFY(strcmp(BH_IOClassname(io), BH_FILE_CLASSNAME) == 0); - BH_VERIFY(BH_IOOpen(io, BH_IO_READ) == BH_OK); - BH_VERIFY(BH_IOFlags(io) & BH_IO_FLAG_OPEN); - - BH_VERIFY(BH_IOWrite(io, "12345", 5, &actual) != BH_OK); - BH_VERIFY(BH_IOFlags(io) & BH_IO_FLAG_ERROR); - BH_VERIFY(BH_IOClear(io) == BH_OK); - BH_VERIFY((BH_IOFlags(io) & BH_IO_FLAG_ERROR) == 0); - - BH_IOClose(io); - BH_IOFree(io); - - return 0; -} - - -/** - * Check peek operation. - */ -static int checkPeek(void) -{ - int64_t previous, current; - char buffer[128]; - size_t actual; - BH_IO *io; - - BH_VERIFY((io = BH_FileNew(FILENAME1)) != NULL); - BH_VERIFY(strcmp(BH_IOClassname(io), BH_FILE_CLASSNAME) == 0); - BH_VERIFY(BH_IOOpen(io, BH_IO_WRITE | BH_IO_READ | BH_IO_TRUNCATE) == BH_OK); - BH_VERIFY(BH_IOFlags(io) & BH_IO_FLAG_OPEN); - - BH_VERIFY(BH_IOWrite(io, "1234567890", 10, &actual) == BH_OK); - BH_VERIFY(actual == 10); - - BH_VERIFY(BH_IOWrite(io, "1234567890", 10, &actual) == BH_OK); - BH_VERIFY(actual == 10); - - BH_VERIFY(BH_IOSeek(io, 0, BH_IO_SEEK_SET) == BH_OK); - BH_VERIFY(BH_IOTell(io, &previous) == BH_OK); - BH_VERIFY(BH_IOPeek(io, buffer, 128, &actual) == BH_OK); - BH_VERIFY(BH_IOTell(io, ¤t) == BH_OK); - BH_VERIFY(actual == 20); - BH_VERIFY(memcmp(buffer, "12345678901234567890", 20) == 0); - BH_VERIFY(previous == current); - - BH_VERIFY(BH_IOSeek(io, 0, BH_IO_SEEK_SET) == BH_OK); - BH_VERIFY(BH_IOTell(io, &previous) == BH_OK); - BH_VERIFY(BH_IOPeek(io, buffer, 128, &actual) == BH_OK); - BH_VERIFY(BH_IOTell(io, ¤t) == BH_OK); - BH_VERIFY(actual == 20); - BH_VERIFY(memcmp(buffer, "12345678901234567890", 20) == 0); - BH_VERIFY(previous == current); - - BH_IOClose(io); - BH_IOFree(io); - - return 0; -} - - -/** - * Check file size operation. - */ -static int checkSize(void) -{ - BH_IO *io; - int64_t size; - - BH_VERIFY((io = BH_FileNew(FILENAME1)) != NULL); - BH_VERIFY(strcmp(BH_IOClassname(io), BH_FILE_CLASSNAME) == 0); - BH_VERIFY(BH_IOOpen(io, BH_IO_READ) == BH_OK); - - BH_VERIFY(BH_IOSize(io, &size) == BH_OK); - BH_VERIFY(size == 20); - - BH_IOClose(io); - BH_IOFree(io); - return 0; -} - - -int main(int argc, - char **argv) -{ - BH_UNUSED(argc); - BH_UNUSED(argv); - - /* Cleanup */ - cleanup(); - - BH_UnitAdd("Null", checkNull); - BH_UnitAdd("Normal", checkNormal); - BH_UnitAdd("Truncate", checkTruncate); - BH_UnitAdd("Exist", checkExist); - BH_UnitAdd("Append", checkAppend); - BH_UnitAdd("Create", checkCreate); - BH_UnitAdd("EOF", checkEOF); - BH_UnitAdd("Error", checkError); - BH_UnitAdd("Peek", checkPeek); - BH_UnitAdd("Size", checkSize); - - return BH_UnitRun(); -} diff --git a/test/src/testhashmap.c b/test/src/testhashmap.c deleted file mode 100644 index 88b7396..0000000 --- a/test/src/testhashmap.c +++ /dev/null @@ -1,234 +0,0 @@ -#include -#include - - -static size_t DBG_PtrIntHash(const void *ptr) -{ - return BH_PTR2INT(ptr); -} - - -static int DBG_PtrIntEqual(const void *lhs, const void *rhs) -{ - return BH_PTR2INT(lhs) - BH_PTR2INT(rhs); -} - - -static int NewFree(void) -{ - BH_Hashmap *hashmap; - - hashmap = BH_HashmapNew(DBG_PtrIntEqual, DBG_PtrIntHash); - BH_VERIFY(hashmap != NULL); - - BH_VERIFY(BH_HashmapEmpty(hashmap) != 0); - BH_VERIFY(BH_HashmapSize(hashmap) == 0); - BH_VERIFY(BH_HashmapCapacity(hashmap) == 0); - BH_VERIFY(BH_HashmapFactor(hashmap) >= 0.15f); - BH_VERIFY(BH_HashmapFactor(hashmap) <= 1.0f); - - BH_HashmapFree(hashmap); - return 0; -} - -static int GrowShrink(void) -{ - BH_Hashmap *hashmap; - void *iter; - - hashmap = BH_HashmapNew(DBG_PtrIntEqual, DBG_PtrIntHash); - BH_VERIFY(hashmap != NULL); - - /* Allocate space for 1024 entries and insert 1 element */ - BH_VERIFY(BH_HashmapReserve(hashmap, 1024) == 0); - BH_VERIFY(BH_HashmapInsert(hashmap, BH_INT2PTR(1337), BH_INT2PTR(80085)) == 0); - - /* Check hashmap contents */ - iter = BH_HashmapIterNext(hashmap, NULL); - BH_VERIFY(iter != NULL); - BH_VERIFY(BH_PTR2INT(BH_HashmapIterKey(iter)) == 1337); - BH_VERIFY(BH_PTR2INT(BH_HashmapIterValue(iter)) == 80085); - BH_VERIFY(BH_HashmapIterNext(hashmap, iter) == NULL); - BH_VERIFY(BH_HashmapEmpty(hashmap) == 0); - BH_VERIFY(BH_HashmapSize(hashmap) == 1); - BH_VERIFY(BH_HashmapCapacity(hashmap) >= 1024); - - /* Change factor and grow */ - BH_HashmapSetFactor(hashmap, 0.35f); - - /* Check hashmap contents */ - iter = BH_HashmapIterNext(hashmap, NULL); - BH_VERIFY(iter != NULL); - BH_VERIFY(BH_PTR2INT(BH_HashmapIterKey(iter)) == 1337); - BH_VERIFY(BH_PTR2INT(BH_HashmapIterValue(iter)) == 80085); - BH_VERIFY(BH_HashmapIterNext(hashmap, iter) == NULL); - BH_VERIFY(BH_HashmapReserve(hashmap, 8192) == 0); - BH_VERIFY(BH_HashmapEmpty(hashmap) == 0); - BH_VERIFY(BH_HashmapSize(hashmap) == 1); - BH_VERIFY(BH_HashmapCapacity(hashmap) >= 8192); - BH_VERIFY_DELTA(BH_HashmapFactor(hashmap), 0.35f, 0.001f); - - /* Shrink */ - BH_VERIFY(BH_HashmapReserve(hashmap, 0) == 0); - - /* Check hashmap contents */ - iter = BH_HashmapIterNext(hashmap, NULL); - BH_VERIFY(iter != NULL); - BH_VERIFY(BH_PTR2INT(BH_HashmapIterKey(iter)) == 1337); - BH_VERIFY(BH_PTR2INT(BH_HashmapIterValue(iter)) == 80085); - BH_VERIFY(BH_HashmapIterNext(hashmap, iter) == NULL); - BH_VERIFY(BH_HashmapEmpty(hashmap) == 0); - BH_VERIFY(BH_HashmapSize(hashmap) == 1); - BH_VERIFY(BH_HashmapCapacity(hashmap) >= 1); - BH_VERIFY(BH_HashmapCapacity(hashmap) < 8192); - BH_VERIFY_DELTA(BH_HashmapFactor(hashmap), 0.35f, 0.001f); - - /* Shrink to 0 (deallocate) */ - BH_HashmapClear(hashmap); - BH_VERIFY(BH_HashmapEmpty(hashmap) != 0); - BH_VERIFY(BH_HashmapSize(hashmap) == 0); - BH_VERIFY(BH_HashmapCapacity(hashmap) > 0); - - BH_VERIFY(BH_HashmapReserve(hashmap, 0) == 0); - BH_VERIFY(BH_HashmapEmpty(hashmap) != 0); - BH_VERIFY(BH_HashmapSize(hashmap) == 0); - BH_VERIFY(BH_HashmapCapacity(hashmap) == 0); - - /* Check hashmap contents */ - iter = BH_HashmapIterNext(hashmap, NULL); - BH_VERIFY(iter == NULL); - - BH_HashmapFree(hashmap); - return 0; -} - -static int InsertRemove(void) -{ - BH_Hashmap *hashmap; - size_t i, added, removed; - void *iter; - - hashmap = BH_HashmapNew(DBG_PtrIntEqual, DBG_PtrIntHash); - BH_VERIFY(hashmap != NULL); - BH_HashmapSetFactor(hashmap, 1.0f); - - /* Insert elements into hashmap */ - added = 0; - for (i = 1024; i > 0; i--) - { - added += (i - 1) / 4; - BH_VERIFY(BH_HashmapInsert(hashmap, BH_INT2PTR((i - 1) / 4), BH_INT2PTR(i)) == 0); - } - - /* Remove elements */ - iter = BH_HashmapIterNext(hashmap, NULL); - removed = 0; - while (iter) - { - removed += BH_PTR2INT(BH_HashmapIterKey(iter)); - BH_HashmapIterRemove(hashmap, iter); - - iter = BH_HashmapIterNext(hashmap, NULL); - } - - /* Check inserted elements are equal to removed */ - BH_VERIFY(added == removed); - - BH_HashmapFree(hashmap); - return 0; -} - -static int Lookup(void) -{ - BH_Hashmap *hashmap; - size_t i; - - hashmap = BH_HashmapNew(DBG_PtrIntEqual, DBG_PtrIntHash); - BH_VERIFY(hashmap != NULL); - - /* Insert elements into hashmap */ - for (i = 0; i < 256; i++) - BH_VERIFY(BH_HashmapInsert(hashmap, BH_INT2PTR(i * 4), BH_INT2PTR(i)) == 0); - - /* Lookup inserted elements */ - for (i = 0; i < 256; i++) - { - void *value; - - BH_VERIFY(BH_HashmapAt(hashmap, BH_INT2PTR(i * 4), NULL) == BH_OK); - BH_VERIFY(BH_HashmapAt(hashmap, BH_INT2PTR(i * 4), &value) == BH_OK); - BH_VERIFY(BH_PTR2INT(value) == (int)i); - } - - /* Lookup non-existing elements */ - for (i = 256; i < 512; i++) - { - void *value; - - BH_VERIFY(BH_HashmapAt(hashmap, BH_INT2PTR(i * 4), NULL) != BH_OK); - BH_VERIFY(BH_HashmapAt(hashmap, BH_INT2PTR(i * 4), &value) != BH_OK); - } - - BH_HashmapFree(hashmap); - return 0; -} - -static int Clear(void) -{ - BH_Hashmap *hashmap; - size_t i; - - hashmap = BH_HashmapNew(DBG_PtrIntEqual, DBG_PtrIntHash); - BH_VERIFY(hashmap != NULL); - - /* Insert elements into hashmap */ - for (i = 0; i < 128; i++) - BH_VERIFY(BH_HashmapInsert(hashmap, BH_INT2PTR(i), 0) == 0); - - BH_HashmapClear(hashmap); - - /* Remove non-existing elements */ - for (i = 0; i < 128; i++) - BH_HashmapRemove(hashmap, BH_INT2PTR(i)); - - BH_HashmapFree(hashmap); - return 0; -} - -static int Fields(void) -{ - BH_Hashmap *hashmap; - size_t i; - - hashmap = BH_HashmapNew(DBG_PtrIntEqual, DBG_PtrIntHash); - BH_VERIFY(hashmap != NULL); - BH_VERIFY(BH_HashmapEmpty(hashmap) == 1); - - /* Insert elements into hashmap */ - for (i = 0; i < 14; i++) - BH_VERIFY(BH_HashmapInsert(hashmap, BH_INT2PTR(i), NULL) == 0); - - /* Check hashmap fields correspond to getter functions */ - BH_VERIFY(BH_HashmapSize(hashmap) == 14); - BH_VERIFY(BH_HashmapCapacity(hashmap) >= 14); - BH_VERIFY(BH_HashmapEmpty(hashmap) == 0); - - BH_HashmapFree(hashmap); - return 0; -} - -int main(int argc, char **argv) -{ - (void)argc; - (void)argv; - - /* Add unit tests */ - BH_UnitAdd("NewFree", NewFree); - BH_UnitAdd("GrowShrink", GrowShrink); - BH_UnitAdd("InsertRemove", InsertRemove); - BH_UnitAdd("Lookup", Lookup); - BH_UnitAdd("Clear", Clear); - BH_UnitAdd("Fields", Fields); - - return BH_UnitRun(); -} diff --git a/test/src/testmath.c b/test/src/testmath.c deleted file mode 100644 index e41f726..0000000 --- a/test/src/testmath.c +++ /dev/null @@ -1,727 +0,0 @@ -#include -#include - - -#define ACCEPTABLE_DELTA 0.0001f - - -static int checkVec4f(void) -{ - float a[4], b[4], c[4], r[4]; - float value; - - a[0] = 1.0f; a[1] = 2.0f; a[2] = 3.0f; a[3] = 4.0f; - b[0] = 5.0f; b[1] = 6.0f; b[2] = 7.0f; b[3] = 8.0f; - c[0] = 1.5f; c[1] = 2.5f; c[2] = 3.5f; c[3] = 4.5f; - - BH_Vec4fAdd(a, b, r); - BH_VERIFY_DELTA(r[0], 6.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[1], 8.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[2], 10.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[3], 12.0000f, ACCEPTABLE_DELTA); - - BH_Vec4fSub(a, b, r); - BH_VERIFY_DELTA(r[0], -4.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[1], -4.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[2], -4.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[3], -4.0000f, ACCEPTABLE_DELTA); - - BH_Vec4fMul(a, b, r); - BH_VERIFY_DELTA(r[0], 5.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[1], 12.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[2], 21.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[3], 32.0000f, ACCEPTABLE_DELTA); - - BH_Vec4fScale(a, 10.0f, r); - BH_VERIFY_DELTA(r[0], 10.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[1], 20.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[2], 30.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[3], 40.0000f, ACCEPTABLE_DELTA); - - BH_Vec4fMulAdd(a, b, c, r); - BH_VERIFY_DELTA(r[0], 6.5000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[1], 14.5000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[2], 24.5000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[3], 36.5000f, ACCEPTABLE_DELTA); - - BH_Vec4fNegate(a, r); - BH_VERIFY_DELTA(r[0], -1.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[1], -2.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[2], -3.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[3], -4.0000f, ACCEPTABLE_DELTA); - - value = BH_Vec4fDot(a, b); - BH_VERIFY_DELTA(value, 70.0000f, ACCEPTABLE_DELTA); - - value = BH_Vec4fLength(a); - BH_VERIFY_DELTA(value, sqrt(30.0f), ACCEPTABLE_DELTA); - - BH_Vec4fNormal(a, r); - BH_VERIFY_DELTA(r[0], 1.0f / sqrt(30.0f), ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[1], 2.0f / sqrt(30.0f), ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[2], 3.0f / sqrt(30.0f), ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[3], 4.0f / sqrt(30.0f), ACCEPTABLE_DELTA); - - BH_Vec4fMin(a, b, r); - BH_VERIFY_DELTA(r[0], 1.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[1], 2.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[2], 3.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[3], 4.0000f, ACCEPTABLE_DELTA); - - BH_Vec4fMax(a, b, r); - BH_VERIFY_DELTA(r[0], 5.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[1], 6.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[2], 7.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[3], 8.0000f, ACCEPTABLE_DELTA); - - BH_Vec4fLerp(a, b, 0.0f, r); - BH_VERIFY_DELTA(r[0], 1.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[1], 2.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[2], 3.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[3], 4.0000f, ACCEPTABLE_DELTA); - - BH_Vec4fLerp(a, b, 0.5f, r); - BH_VERIFY_DELTA(r[0], 3.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[1], 4.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[2], 5.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[3], 6.0000f, ACCEPTABLE_DELTA); - - BH_Vec4fLerp(a, b, 1.0f, r); - BH_VERIFY_DELTA(r[0], 5.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[1], 6.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[2], 7.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[3], 8.0000f, ACCEPTABLE_DELTA); - - return 0; -} - - -static int checkVec3f(void) -{ - float a[3], b[3], c[3], r[3]; - float value; - - a[0] = 1.0f; a[1] = 2.0f; a[2] = 3.0f; - b[0] = 5.0f; b[1] = 6.0f; b[2] = 7.0f; - c[0] = 1.5f; c[1] = 2.5f; c[2] = 3.5f; - - BH_Vec3fAdd(a, b, r); - BH_VERIFY_DELTA(r[0], 6.0f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[1], 8.0f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[2], 10.0f, ACCEPTABLE_DELTA); - - BH_Vec3fSub(a, b, r); - BH_VERIFY_DELTA(r[0], -4.0f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[1], -4.0f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[2], -4.0f, ACCEPTABLE_DELTA); - - BH_Vec3fMul(a, b, r); - BH_VERIFY_DELTA(r[0], 5.0f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[1], 12.0f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[2], 21.0f, ACCEPTABLE_DELTA); - - BH_Vec3fScale(a, 10.0f, r); - BH_VERIFY_DELTA(r[0], 10.0f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[1], 20.0f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[2], 30.0f, ACCEPTABLE_DELTA); - - BH_Vec3fMulAdd(a, b, c, r); - BH_VERIFY_DELTA(r[0], 6.5f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[1], 14.5f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[2], 24.5f, ACCEPTABLE_DELTA); - - BH_Vec3fNegate(a, r); - BH_VERIFY_DELTA(r[0], -1.0f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[1], -2.0f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[2], -3.0f, ACCEPTABLE_DELTA); - - value = BH_Vec3fDot(a, b); - BH_VERIFY_DELTA(value, 38.0f, ACCEPTABLE_DELTA); - - BH_Vec3fCross(a, b, r); - BH_VERIFY_DELTA(r[0], -4.0f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[1], 8.0f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[2], -4.0f, ACCEPTABLE_DELTA); - - value = BH_Vec3fLength(a); - BH_VERIFY_DELTA(value, sqrt(14.0f), ACCEPTABLE_DELTA); - - BH_Vec3fNormal(a, r); - BH_VERIFY_DELTA(r[0], 1.0f / sqrt(14.0f), ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[1], 2.0f / sqrt(14.0f), ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[2], 3.0f / sqrt(14.0f), ACCEPTABLE_DELTA); - - BH_Vec3fMin(a, b, r); - BH_VERIFY_DELTA(r[0], 1.0f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[1], 2.0f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[2], 3.0f, ACCEPTABLE_DELTA); - - BH_Vec3fMax(a, b, r); - BH_VERIFY_DELTA(r[0], 5.0f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[1], 6.0f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[2], 7.0f, ACCEPTABLE_DELTA); - - BH_Vec3fLerp(a, b, 0.0f, r); - BH_VERIFY_DELTA(r[0], 1.0f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[1], 2.0f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[2], 3.0f, ACCEPTABLE_DELTA); - - BH_Vec3fLerp(a, b, 0.5f, r); - BH_VERIFY_DELTA(r[0], 3.0f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[1], 4.0f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[2], 5.0f, ACCEPTABLE_DELTA); - - BH_Vec3fLerp(a, b, 1.0f, r); - BH_VERIFY_DELTA(r[0], 5.0f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[1], 6.0f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[2], 7.0f, ACCEPTABLE_DELTA); - - return 0; -} - - -static int checkVec2f(void) -{ - float a[2], b[2], c[2], r[2]; - float value; - - a[0] = 1.0f; a[1] = 2.0f; - b[0] = 5.0f; b[1] = 6.0f; - c[0] = 1.5f; c[1] = 2.5f; - - BH_Vec2fAdd(a, b, r); - BH_VERIFY_DELTA(r[0], 6.0f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[1], 8.0f, ACCEPTABLE_DELTA); - - BH_Vec2fSub(a, b, r); - BH_VERIFY_DELTA(r[0], -4.0f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[1], -4.0f, ACCEPTABLE_DELTA); - - BH_Vec2fMul(a, b, r); - BH_VERIFY_DELTA(r[0], 5.0f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[1], 12.0f, ACCEPTABLE_DELTA); - - BH_Vec2fScale(a, 10.0f, r); - BH_VERIFY_DELTA(r[0], 10.0f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[1], 20.0f, ACCEPTABLE_DELTA); - - BH_Vec2fMulAdd(a, b, c, r); - BH_VERIFY_DELTA(r[0], 6.5f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[1], 14.5f, ACCEPTABLE_DELTA); - - BH_Vec2fNegate(a, r); - BH_VERIFY_DELTA(r[0], -1.0f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[1], -2.0f, ACCEPTABLE_DELTA); - - value = BH_Vec2fDot(a, b); - BH_VERIFY_DELTA(value, 17.0f, ACCEPTABLE_DELTA); - - value = BH_Vec2fCross(a, b); - BH_VERIFY_DELTA(value, -4.0f, ACCEPTABLE_DELTA); - - value = BH_Vec2fLength(a); - BH_VERIFY_DELTA(value, sqrt(5.0f), ACCEPTABLE_DELTA); - - BH_Vec2fNormal(a, r); - BH_VERIFY_DELTA(r[0], 1.0f / sqrt(5.0f), ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[1], 2.0f / sqrt(5.0f), ACCEPTABLE_DELTA); - - BH_Vec2fMin(a, b, r); - BH_VERIFY_DELTA(r[0], 1.0f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[1], 2.0f, ACCEPTABLE_DELTA); - - BH_Vec2fMax(a, b, r); - BH_VERIFY_DELTA(r[0], 5.0f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[1], 6.0f, ACCEPTABLE_DELTA); - - BH_Vec2fLerp(a, b, 0.0f, r); - BH_VERIFY_DELTA(r[0], 1.0f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[1], 2.0f, ACCEPTABLE_DELTA); - - BH_Vec2fLerp(a, b, 0.5f, r); - BH_VERIFY_DELTA(r[0], 3.0f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[1], 4.0f, ACCEPTABLE_DELTA); - - BH_Vec2fLerp(a, b, 1.0f, r); - BH_VERIFY_DELTA(r[0], 5.0f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[1], 6.0f, ACCEPTABLE_DELTA); - - return 0; -} - - -static int checkVec4i(void) -{ - int a[4], b[4], c[4], r[4]; - - a[0] = 1; a[1] = 2; a[2] = 3; a[3] = 4; - b[0] = 5; b[1] = 6; b[2] = 7; b[3] = 8; - c[0] = 4; c[1] = 3; c[2] = 2; c[3] = 1; - - BH_Vec4iAdd(a, b, r); - BH_VERIFY(r[0] == 6); - BH_VERIFY(r[1] == 8); - BH_VERIFY(r[2] == 10); - BH_VERIFY(r[3] == 12); - - BH_Vec4iSub(a, b, r); - BH_VERIFY(r[0] == -4); - BH_VERIFY(r[1] == -4); - BH_VERIFY(r[2] == -4); - BH_VERIFY(r[3] == -4); - - BH_Vec4iMul(a, b, r); - BH_VERIFY(r[0] == 5); - BH_VERIFY(r[1] == 12); - BH_VERIFY(r[2] == 21); - BH_VERIFY(r[3] == 32); - - BH_Vec4iScale(a, 10, r); - BH_VERIFY(r[0] == 10); - BH_VERIFY(r[1] == 20); - BH_VERIFY(r[2] == 30); - BH_VERIFY(r[3] == 40); - - BH_Vec4iMulAdd(a, b, c, r); - BH_VERIFY(r[0] == 9); - BH_VERIFY(r[1] == 15); - BH_VERIFY(r[2] == 23); - BH_VERIFY(r[3] == 33); - - BH_Vec4iNegate(a, r); - BH_VERIFY(r[0] == -1); - BH_VERIFY(r[1] == -2); - BH_VERIFY(r[2] == -3); - BH_VERIFY(r[3] == -4); - - BH_Vec4iMin(a, b, r); - BH_VERIFY(r[0] == 1); - BH_VERIFY(r[1] == 2); - BH_VERIFY(r[2] == 3); - BH_VERIFY(r[3] == 4); - - BH_Vec4iMax(a, b, r); - BH_VERIFY(r[0] == 5); - BH_VERIFY(r[1] == 6); - BH_VERIFY(r[2] == 7); - BH_VERIFY(r[3] == 8); - - return 0; -} - - -static int checkVec3i(void) -{ - int a[3], b[3], c[3], r[3]; - - a[0] = 1; a[1] = 2; a[2] = 3; - b[0] = 5; b[1] = 6; b[2] = 7; - c[0] = 4; c[1] = 3; c[2] = 2; - - BH_Vec3iAdd(a, b, r); - BH_VERIFY(r[0] == 6); - BH_VERIFY(r[1] == 8); - BH_VERIFY(r[2] == 10); - - BH_Vec3iSub(a, b, r); - BH_VERIFY(r[0] == -4); - BH_VERIFY(r[1] == -4); - BH_VERIFY(r[2] == -4); - - BH_Vec3iMul(a, b, r); - BH_VERIFY(r[0] == 5); - BH_VERIFY(r[1] == 12); - BH_VERIFY(r[2] == 21); - - BH_Vec3iScale(a, 10, r); - BH_VERIFY(r[0] == 10); - BH_VERIFY(r[1] == 20); - BH_VERIFY(r[2] == 30); - - BH_Vec3iMulAdd(a, b, c, r); - BH_VERIFY(r[0] == 9); - BH_VERIFY(r[1] == 15); - BH_VERIFY(r[2] == 23); - - BH_Vec3iNegate(a, r); - BH_VERIFY(r[0] == -1); - BH_VERIFY(r[1] == -2); - BH_VERIFY(r[2] == -3); - - BH_Vec3iMin(a, b, r); - BH_VERIFY(r[0] == 1); - BH_VERIFY(r[1] == 2); - BH_VERIFY(r[2] == 3); - - BH_Vec3iMax(a, b, r); - BH_VERIFY(r[0] == 5); - BH_VERIFY(r[1] == 6); - BH_VERIFY(r[2] == 7); - - return 0; -} - - -static int checkVec2i(void) -{ - int a[2], b[2], c[2], r[2]; - - a[0] = 1; a[1] = 2; - b[0] = 5; b[1] = 6; - c[0] = 4; c[1] = 3; - - BH_Vec2iAdd(a, b, r); - BH_VERIFY(r[0] == 6); - BH_VERIFY(r[1] == 8); - - BH_Vec2iSub(a, b, r); - BH_VERIFY(r[0] == -4); - BH_VERIFY(r[1] == -4); - - BH_Vec2iMul(a, b, r); - BH_VERIFY(r[0] == 5); - BH_VERIFY(r[1] == 12); - - BH_Vec2iScale(a, 10, r); - BH_VERIFY(r[0] == 10); - BH_VERIFY(r[1] == 20); - - BH_Vec2iMulAdd(a, b, c, r); - BH_VERIFY(r[0] == 9); - BH_VERIFY(r[1] == 15); - - BH_Vec2iNegate(a, r); - BH_VERIFY(r[0] == -1); - BH_VERIFY(r[1] == -2); - - BH_Vec2iMin(a, b, r); - BH_VERIFY(r[0] == 1); - BH_VERIFY(r[1] == 2); - - BH_Vec2iMax(a, b, r); - BH_VERIFY(r[0] == 5); - BH_VERIFY(r[1] == 6); - - return 0; -} - - -static int checkQuat(void) -{ - return 0; -} - - -static int checkMat4f(void) -{ - float a[16], b[16], r[16]; - float value; - - a[0] = 5.0f; a[4] = 1.0f; a[8] = 2.0f; a[12] = 7.0f; - a[1] = 3.0f; a[5] = 0.0f; a[9] = 0.0f; a[13] = 2.0f; - a[2] = 1.0f; a[6] = 3.0f; a[10] = 4.0f; a[14] = 5.0f; - a[3] = 2.0f; a[7] = 0.0f; a[11] = 0.0f; a[15] = 3.0f; - - b[0] = 5.0f; b[4] = 1.0f; b[8] = 2.0f; b[12] = 7.0f; - b[1] = 3.0f; b[5] = 1.0f; b[9] = 0.0f; b[13] = 2.0f; - b[2] = 4.0f; b[6] = 2.0f; b[10] = 4.0f; b[14] = 5.0f; - b[3] = 6.0f; b[7] = 2.0f; b[11] = 0.0f; b[15] = 4.0f; - - BH_Mat4fIdentity(r); - BH_VERIFY(r[0] == 1.0f); - BH_VERIFY(r[1] == 0.0f); - BH_VERIFY(r[2] == 0.0f); - BH_VERIFY(r[3] == 0.0f); - - BH_VERIFY(r[4] == 0.0f); - BH_VERIFY(r[5] == 1.0f); - BH_VERIFY(r[6] == 0.0f); - BH_VERIFY(r[7] == 0.0f); - - BH_VERIFY(r[8] == 0.0f); - BH_VERIFY(r[9] == 0.0f); - BH_VERIFY(r[10] == 1.0f); - BH_VERIFY(r[11] == 0.0f); - - BH_VERIFY(r[12] == 0.0f); - BH_VERIFY(r[13] == 0.0f); - BH_VERIFY(r[14] == 0.0f); - BH_VERIFY(r[15] == 1.0f); - - BH_Mat4fAdd(a, b, r); - BH_VERIFY_DELTA(r[0], 10.0f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[1], 6.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[2], 5.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[3], 8.0000f, ACCEPTABLE_DELTA); - - BH_VERIFY_DELTA(r[4], 2.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[5], 1.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[6], 5.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[7], 2.0000f, ACCEPTABLE_DELTA); - - BH_VERIFY_DELTA(r[8], 4.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[9], 0.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[10], 8.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[11], 0.0000f, ACCEPTABLE_DELTA); - - BH_VERIFY_DELTA(r[12], 14.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[13], 4.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[14], 10.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[15], 7.0000f, ACCEPTABLE_DELTA); - - BH_Mat4fSub(a, b, r); - BH_VERIFY_DELTA(r[0], 0.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[1], 0.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[2], -3.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[3], -4.0000f, ACCEPTABLE_DELTA); - - BH_VERIFY_DELTA(r[4], 0.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[5], -1.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[6], 1.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[7], -2.0000f, ACCEPTABLE_DELTA); - - BH_VERIFY_DELTA(r[8], 0.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[9], 0.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[10], 0.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[11], 0.0000f, ACCEPTABLE_DELTA); - - BH_VERIFY_DELTA(r[12], 0.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[13], 0.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[14], 0.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[15], -1.0000f, ACCEPTABLE_DELTA); - - BH_Mat4fMul(a, b, r); - BH_VERIFY_DELTA(r[0], 78.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[1], 27.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[2], 60.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[3], 28.0000f, ACCEPTABLE_DELTA); - - BH_VERIFY_DELTA(r[4], 24.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[5], 7.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[6], 22.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[7], 8.0000f, ACCEPTABLE_DELTA); - - BH_VERIFY_DELTA(r[8], 18.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[9], 6.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[10], 18.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[11], 4.0000f, ACCEPTABLE_DELTA); - - BH_VERIFY_DELTA(r[12], 75.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[13], 29.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[14], 53.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[15], 26.0000f, ACCEPTABLE_DELTA); - - BH_Mat4fScale(a, 10, r); - BH_VERIFY_DELTA(r[0], 50.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[1], 30.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[2], 10.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[3], 20.0000f, ACCEPTABLE_DELTA); - - BH_VERIFY_DELTA(r[4], 10.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[5], 0.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[6], 30.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[7], 0.0000f, ACCEPTABLE_DELTA); - - BH_VERIFY_DELTA(r[8], 20.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[9], 0.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[10], 40.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[11], 0.0000f, ACCEPTABLE_DELTA); - - BH_VERIFY_DELTA(r[12], 70.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[13], 20.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[14], 50.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[15], 30.0000f, ACCEPTABLE_DELTA); - - BH_Mat4fTranspose(a, r); - BH_VERIFY_DELTA(r[0], 5.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[1], 1.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[2], 2.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[3], 7.0000f, ACCEPTABLE_DELTA); - - BH_VERIFY_DELTA(r[4], 3.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[5], 0.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[6], 0.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[7], 2.0000f, ACCEPTABLE_DELTA); - - BH_VERIFY_DELTA(r[8], 1.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[9], 3.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[10], 4.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[11], 5.0000f, ACCEPTABLE_DELTA); - - BH_VERIFY_DELTA(r[12], 2.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[13], 0.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[14], 0.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[15], 3.0000f, ACCEPTABLE_DELTA); - - value = BH_Mat4fTrace(a); - BH_VERIFY_DELTA(value, 12.0000f, ACCEPTABLE_DELTA); - - value = BH_Mat4fDet(a); - BH_VERIFY_DELTA(value, 10.0000f, ACCEPTABLE_DELTA); - - value = BH_Mat4fDet(b); - BH_VERIFY_DELTA(value, 0.0000f, ACCEPTABLE_DELTA); - - BH_VERIFY(BH_Mat4fInverse(a, r) == BH_OK); - BH_VERIFY_DELTA(r[0], 0.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[1], -2.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[2], 1.5000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[3], 0.0000f, ACCEPTABLE_DELTA); - - BH_VERIFY_DELTA(r[4], 0.6000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[5], 1.8000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[6], -1.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[7], -0.4000f, ACCEPTABLE_DELTA); - - BH_VERIFY_DELTA(r[8], 0.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[9], 1.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[10], -0.5000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[11], 0.0000f, ACCEPTABLE_DELTA); - - BH_VERIFY_DELTA(r[12], -0.4000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[13], 1.8000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[14], -2.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[15], 0.6000f, ACCEPTABLE_DELTA); - - BH_VERIFY(BH_Mat4fInverse(b, r) != BH_OK); - - return 0; -} - - -static int checkMat3f(void) -{ - float a[9], b[9], r[9]; - float value; - - a[0] = 5.0f; a[3] = 1.0f; a[6] = 2.0f; - a[1] = 3.0f; a[4] = 0.0f; a[7] = 0.0f; - a[2] = 1.0f; a[5] = 3.0f; a[8] = 4.0f; - - b[0] = 2.0f; b[3] = 1.0f; b[6] = 2.0f; - b[1] = 3.0f; b[4] = 1.0f; b[7] = 0.0f; - b[2] = 4.0f; b[5] = 2.0f; b[8] = 4.0f; - - BH_Mat3fIdentity(r); - BH_VERIFY(r[0] == 1.0f); - BH_VERIFY(r[1] == 0.0f); - BH_VERIFY(r[2] == 0.0f); - - BH_VERIFY(r[3] == 0.0f); - BH_VERIFY(r[4] == 1.0f); - BH_VERIFY(r[5] == 0.0f); - - BH_VERIFY(r[6] == 0.0f); - BH_VERIFY(r[7] == 0.0f); - BH_VERIFY(r[8] == 1.0f); - - BH_Mat3fAdd(a, b, r); - BH_VERIFY_DELTA(r[0], 7.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[1], 6.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[2], 5.0000f, ACCEPTABLE_DELTA); - - BH_VERIFY_DELTA(r[3], 2.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[4], 1.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[5], 5.0000f, ACCEPTABLE_DELTA); - - BH_VERIFY_DELTA(r[6], 4.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[7], 0.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[8], 8.0000f, ACCEPTABLE_DELTA); - - BH_Mat3fSub(a, b, r); - BH_VERIFY_DELTA(r[0], 3.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[1], 0.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[2], -3.0000f, ACCEPTABLE_DELTA); - - BH_VERIFY_DELTA(r[3], 0.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[4], -1.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[5], 1.0000f, ACCEPTABLE_DELTA); - - BH_VERIFY_DELTA(r[6], 0.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[7], 0.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[8], 0.0000f, ACCEPTABLE_DELTA); - - BH_Mat3fMul(a, b, r); - BH_VERIFY_DELTA(r[0], 21.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[1], 6.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[2], 27.0000f, ACCEPTABLE_DELTA); - - BH_VERIFY_DELTA(r[3], 10.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[4], 3.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[5], 12.0000f, ACCEPTABLE_DELTA); - - BH_VERIFY_DELTA(r[6], 18.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[7], 6.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[8], 18.0000f, ACCEPTABLE_DELTA); - - BH_Mat3fScale(a, 10, r); - BH_VERIFY_DELTA(r[0], 50.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[1], 30.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[2], 10.0000f, ACCEPTABLE_DELTA); - - BH_VERIFY_DELTA(r[3], 10.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[4], 0.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[5], 30.0000f, ACCEPTABLE_DELTA); - - BH_VERIFY_DELTA(r[6], 20.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[7], 0.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[8], 40.0000f, ACCEPTABLE_DELTA); - - BH_Mat3fTranspose(a, r); - BH_VERIFY_DELTA(r[0], 5.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[1], 1.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[2], 2.0000f, ACCEPTABLE_DELTA); - - BH_VERIFY_DELTA(r[3], 3.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[4], 0.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[5], 0.0000f, ACCEPTABLE_DELTA); - - BH_VERIFY_DELTA(r[6], 1.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[7], 3.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[8], 4.0000f, ACCEPTABLE_DELTA); - - value = BH_Mat3fTrace(a); - BH_VERIFY_DELTA(value, 9.0000f, ACCEPTABLE_DELTA); - - value = BH_Mat3fDet(a); - BH_VERIFY_DELTA(value, 6.0000f, ACCEPTABLE_DELTA); - - value = BH_Mat3fDet(b); - BH_VERIFY_DELTA(value, 0.0000f, ACCEPTABLE_DELTA); - - BH_VERIFY(BH_Mat3fInverse(a, r) == BH_OK); - BH_VERIFY_DELTA(r[0], 0.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[1], -2.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[2], 1.5000f, ACCEPTABLE_DELTA); - - BH_VERIFY_DELTA(r[3], 0.3333f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[4], 3.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[5], -2.3333f, ACCEPTABLE_DELTA); - - BH_VERIFY_DELTA(r[6], 0.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[7], 1.0000f, ACCEPTABLE_DELTA); - BH_VERIFY_DELTA(r[8], -0.5000f, ACCEPTABLE_DELTA); - - BH_VERIFY(BH_Mat3fInverse(b, r) != BH_OK); - - return 0; -} - - -int main(int argc, char **argv) -{ - (void)argc; - (void)argv; - - BH_UnitAdd("Vec4f", checkVec4f); - BH_UnitAdd("Vec3f", checkVec3f); - BH_UnitAdd("Vec2f", checkVec2f); - BH_UnitAdd("Vec4i", checkVec4i); - BH_UnitAdd("Vec3i", checkVec3i); - BH_UnitAdd("Vec2i", checkVec2i); - BH_UnitAdd("Quat", checkQuat); - BH_UnitAdd("Mat4f", checkMat4f); - BH_UnitAdd("Mat3f", checkMat3f); - - return BH_UnitRun(); -} diff --git a/test/src/testqueue.c b/test/src/testqueue.c deleted file mode 100644 index edeb75c..0000000 --- a/test/src/testqueue.c +++ /dev/null @@ -1,171 +0,0 @@ -#include -#include - - -static int NewFree(void) -{ - BH_Queue *queue; - - queue = BH_QueueNew(); - BH_VERIFY(queue != NULL); - BH_VERIFY(BH_QueueSize(queue) == 0); - BH_VERIFY(BH_QueueCapacity(queue) == 0); - BH_VERIFY(BH_QueueEmpty(queue) != 0); - - BH_QueueFree(queue); - return 0; -} - - -static int GrowShrink(void) -{ - BH_Queue *queue; - void *value; - - queue = BH_QueueNew(); - BH_VERIFY(queue != NULL); - - /* Reserve 1024 elements and insert item into queue */ - BH_VERIFY(BH_QueueReserve(queue, 1024) == BH_OK); - BH_VERIFY(BH_QueueInsert(queue, BH_INT2PTR(1337)) == BH_OK); - BH_VERIFY(BH_QueueCapacity(queue) >= 1024); - BH_VERIFY(BH_QueueSize(queue) == 1); - BH_VERIFY(BH_QueueEmpty(queue) == 0); - - /* Check queue content */ - BH_VERIFY(BH_QueueFront(queue, &value) == BH_OK); - BH_VERIFY(BH_PTR2INT(value) == 1337); - - /* Grow queue */ - BH_VERIFY(BH_QueueReserve(queue, 8192) == BH_OK); - BH_VERIFY(BH_QueueCapacity(queue) >= 8192); - BH_VERIFY(BH_QueueSize(queue) == 1); - BH_VERIFY(BH_QueueEmpty(queue) == 0); - - /* Check queue content */ - BH_VERIFY(BH_QueueFront(queue, &value) == BH_OK); - BH_VERIFY(BH_PTR2INT(value) == 1337); - - /* Shrink the queue */ - BH_VERIFY(BH_QueueReserve(queue, 0) == BH_OK); - BH_VERIFY(BH_QueueCapacity(queue) >= 1); - BH_VERIFY(BH_QueueCapacity(queue) < 8192); - BH_VERIFY(BH_QueueSize(queue) == 1); - BH_VERIFY(BH_QueueEmpty(queue) == 0); - - /* Check queue content */ - BH_VERIFY(BH_QueueFront(queue, &value) == BH_OK); - BH_VERIFY(BH_PTR2INT(value) == 1337); - - /* Shrink to 0 (deallocate) */ - BH_QueueClear(queue); - BH_VERIFY(BH_QueueSize(queue) == 0); - BH_VERIFY(BH_QueueEmpty(queue) != 0); - BH_VERIFY(BH_QueueCapacity(queue) >= 1); - - BH_VERIFY(BH_QueueReserve(queue, 0) == BH_OK); - BH_VERIFY(BH_QueueSize(queue) == 0); - BH_VERIFY(BH_QueueEmpty(queue) != 0); - BH_VERIFY(BH_QueueCapacity(queue) == 0); - - BH_QueueFree(queue); - return 0; -} - - -static int InsertRemove(void) -{ - BH_Queue *queue; - size_t i, added, removed; - void *iter; - - queue = BH_QueueNew(); - BH_VERIFY(queue != NULL); - - added = 0; - for (i = 0; i < 256; i++) - { - added += i * 2; - BH_VERIFY(BH_QueueInsert(queue, BH_INT2PTR(i * 2)) == BH_OK); - } - - removed = 0; - iter = BH_QueueIterNext(queue, NULL); - while (iter) - { - void *value; - - BH_VERIFY(BH_QueueFront(queue, &value) == BH_OK); - removed += BH_PTR2INT(value); - - BH_QueueRemove(queue); - iter = BH_QueueIterNext(queue, NULL); - } - - BH_VERIFY(added == removed); - BH_VERIFY(BH_QueueEmpty(queue) != 0); - BH_VERIFY(BH_QueueSize(queue) == 0); - - BH_QueueFree(queue); - return 0; -} - - -static int Rollover(void) -{ - BH_Queue *queue; - size_t i, j, capacity; - - queue = BH_QueueNew(); - BH_VERIFY(queue != NULL); - - BH_VERIFY(BH_QueueReserve(queue, 128) == 0); - capacity = BH_QueueCapacity(queue); - - for (i = 0; i < 128; i++) - { - for (j = 0; j < 3; j++) - BH_QueueRemove(queue); - - for (j = 0; j < 4 && BH_QueueSize(queue) < 128; j++) - BH_VERIFY(BH_QueueInsert(queue, BH_INT2PTR(i * 4 + j)) == 0); - } - - BH_VERIFY(BH_QueueSize(queue) == 128); - BH_VERIFY(BH_QueueCapacity(queue) == capacity); - - BH_QueueFree(queue); - return 0; -} - - -static int Fields(void) -{ - BH_Queue *queue; - - queue = BH_QueueNew(); - BH_VERIFY(queue != NULL); - - BH_VERIFY(BH_QueueInsert(queue, BH_INT2PTR(1337)) == 0); - BH_VERIFY(BH_QueueSize(queue) == 1); - BH_VERIFY(BH_QueueEmpty(queue) == 0); - BH_VERIFY(BH_QueueCapacity(queue) >= 1); - - BH_QueueFree(queue); - return 0; -} - - -int main(int argc, char **argv) -{ - (void)argc; - (void)argv; - - BH_UnitAdd("NewFree", NewFree); - BH_UnitAdd("GrowShrink", GrowShrink); - BH_UnitAdd("InsertRemove", InsertRemove); - BH_UnitAdd("Rollover", Rollover); - BH_UnitAdd("Fields", Fields); - - return BH_UnitRun(); -} diff --git a/unit/CMakeLists.txt b/unit/CMakeLists.txt index 28d7ce9..42e9ffb 100755 --- a/unit/CMakeLists.txt +++ b/unit/CMakeLists.txt @@ -10,11 +10,11 @@ set(CMAKE_C_EXTENSIONS OFF) # Library code set(BHUNIT_SOURCE - src/unit.c + src/Unit.c ) set(BHUNIT_HEADER - include/bh/unit.h + include/BH/Unit.h ) # Library diff --git a/unit/include/BH/Unit.h b/unit/include/BH/Unit.h new file mode 100755 index 0000000..3b3b2b6 --- /dev/null +++ b/unit/include/BH/Unit.h @@ -0,0 +1,56 @@ +#ifndef BH_UNIT_H +#define BH_UNIT_H + +#include +#include + +typedef int (*BH_UnitCallback)(void); + +#define BH_VERIFY(e) \ + do { \ + if (!(e)) { \ + printf("%s:%d\t%s\n", __FILE__, __LINE__, #e); \ + return -1; \ + } \ + } while(0) + + +#define BH_FAIL(msg) \ + do { \ + printf("%s:%d\t%s\n", __FILE__, __LINE__, msg); \ + return -1; \ + } while(0) + + +#define BH_VERIFY_DELTA(x, y, e) \ + do { \ + double BH_VERIFY_DELTA = (x)-(y); \ + if (BH_VERIFY_DELTA < 0.0) \ + BH_VERIFY_DELTA = -BH_VERIFY_DELTA; \ + if (BH_VERIFY_DELTA > (e)) { \ + printf("%s:%d\t%s (differs by %f)\n", __FILE__, __LINE__, #x " == " #y, BH_VERIFY_DELTA); \ + return -1; \ + } \ + } while(0) + + + +/** + * Adds unit test \a cb with name \a name for the testing. + * + * \param name Unit test name + * \param cb Unit test function + */ +void BH_UnitAdd(const char *name, + BH_UnitCallback cb); + + +/** + * Runs unit tests. + * + * \return On success, returns zero. + * \return On failure, returns error code. + */ +int BH_UnitRun(void); + +#endif /* BH_UNIT_H */ diff --git a/unit/include/bh/unit.h b/unit/include/bh/unit.h deleted file mode 100755 index 3b3b2b6..0000000 --- a/unit/include/bh/unit.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef BH_UNIT_H -#define BH_UNIT_H - -#include -#include - -typedef int (*BH_UnitCallback)(void); - -#define BH_VERIFY(e) \ - do { \ - if (!(e)) { \ - printf("%s:%d\t%s\n", __FILE__, __LINE__, #e); \ - return -1; \ - } \ - } while(0) - - -#define BH_FAIL(msg) \ - do { \ - printf("%s:%d\t%s\n", __FILE__, __LINE__, msg); \ - return -1; \ - } while(0) - - -#define BH_VERIFY_DELTA(x, y, e) \ - do { \ - double BH_VERIFY_DELTA = (x)-(y); \ - if (BH_VERIFY_DELTA < 0.0) \ - BH_VERIFY_DELTA = -BH_VERIFY_DELTA; \ - if (BH_VERIFY_DELTA > (e)) { \ - printf("%s:%d\t%s (differs by %f)\n", __FILE__, __LINE__, #x " == " #y, BH_VERIFY_DELTA); \ - return -1; \ - } \ - } while(0) - - - -/** - * Adds unit test \a cb with name \a name for the testing. - * - * \param name Unit test name - * \param cb Unit test function - */ -void BH_UnitAdd(const char *name, - BH_UnitCallback cb); - - -/** - * Runs unit tests. - * - * \return On success, returns zero. - * \return On failure, returns error code. - */ -int BH_UnitRun(void); - -#endif /* BH_UNIT_H */ diff --git a/unit/src/Unit.c b/unit/src/Unit.c new file mode 100755 index 0000000..ead5449 --- /dev/null +++ b/unit/src/Unit.c @@ -0,0 +1,61 @@ +#include +#include + +typedef struct BH_Unit +{ + struct BH_Unit *next; + const char *name; + BH_UnitCallback cb; +} BH_Unit; + + +static BH_Unit *root = NULL; + + +void BH_UnitAdd(const char *name, BH_UnitCallback cb) +{ + BH_Unit *unit, *current; + + /* Allocate and fill new unit test entry */ + unit = malloc(sizeof(*unit)); + if (!unit) + return; + + unit->next = NULL; + unit->name = name; + unit->cb = cb; + + /* Append unit test entry */ + current = root; + while (current && current->next) + current = current->next; + + if (current) + current->next = unit; + else + root = unit; +} + + +int BH_UnitRun(void) +{ + BH_Unit *current; + printf("Running tests...\n"); + + current = root; + while (current) + { + printf("%s\n", current->name); + if (current->cb()) + { + printf("\tFAIL\n"); + return -1; + } + printf("\tPASS\n"); + fflush(stdout); + current = current->next; + } + + return 0; +} + diff --git a/unit/src/unit.c b/unit/src/unit.c deleted file mode 100755 index 6063a4f..0000000 --- a/unit/src/unit.c +++ /dev/null @@ -1,61 +0,0 @@ -#include -#include - -typedef struct BH_Unit -{ - struct BH_Unit *next; - const char *name; - BH_UnitCallback cb; -} BH_Unit; - - -static BH_Unit *root = NULL; - - -void BH_UnitAdd(const char *name, BH_UnitCallback cb) -{ - BH_Unit *unit, *current; - - /* Allocate and fill new unit test entry */ - unit = malloc(sizeof(*unit)); - if (!unit) - return; - - unit->next = NULL; - unit->name = name; - unit->cb = cb; - - /* Append unit test entry */ - current = root; - while (current && current->next) - current = current->next; - - if (current) - current->next = unit; - else - root = unit; -} - - -int BH_UnitRun(void) -{ - BH_Unit *current; - printf("Running tests...\n"); - - current = root; - while (current) - { - printf("%s\n", current->name); - if (current->cb()) - { - printf("\tFAIL\n"); - return -1; - } - printf("\tPASS\n"); - fflush(stdout); - current = current->next; - } - - return 0; -} - -- cgit v1.2.3