This repository has been archived on 2025-02-04. You can view files and clone it, but cannot push or open issues or pull requests.
helpless/oogabooga/third_party.c
2024-07-15 21:40:27 +02:00

162 lines
4.6 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// YOINKED FROM https://gist.github.com/LingDong-/7e4c4cae5cbbc44400a05fba65f06f23
// (stb_vorbis uses math.h log() but that collides with oogabooga log() procedure)
/////////////////////////////////////////////////////////////
// ln.c
//
// simple, fast, accurate natural log approximation
// when without <math.h>
// featuring * floating point bit level hacking,
// * x=m*2^p => ln(x)=ln(m)+ln(2)p,
// * Remez algorithm
// by Lingdong Huang, 2020. Public domain.
// ============================================
float ln(float x) {
unsigned int bx = * (unsigned int *) (&x);
unsigned int ex = bx >> 23;
signed int t = (signed int)ex-(signed int)127;
unsigned int s = (t < 0) ? (-t) : t;
bx = 1065353216 | (bx & 8388607);
x = * (float *) (&bx);
return -1.49278+(2.11263+(-0.729104+0.10969*x)*x)*x+0.6931471806*t;
}
// done.
// ============================================
// Exact same function, with added comments:
float natural_log(float x) {
// ASSUMING:
// - non-denormalized numbers i.e. x > 2^126
// - integer is 32 bit. float is IEEE 32 bit.
// INSPIRED BY:
// - https://stackoverflow.com/a/44232045
// - http://mathonweb.com/help_ebook/html/algorithms.htm#ln
// - https://en.wikipedia.org/wiki/Fast_inverse_square_root
// FORMULA:
// x = m * 2^p =>
// ln(x) = ln(m) + ln(2)p,
// first normalize the value to between 1.0 and 2.0
// assuming normalized IEEE float
// sign exp frac
// 0b 0 [00000000] 00000000000000000000000
// value = (-1)^s * M * 2 ^ (exp-127)
//
// exp = 127 for x = 1,
// so 2^(exp-127) is the multiplier
// evil floating point bit level hacking
unsigned int bx = * (unsigned int *) (&x);
// extract exp, since x>0, sign bit must be 0
unsigned int ex = bx >> 23;
signed int t = (signed int)ex-(signed int)127;
unsigned int s = (t < 0) ? (-t) : t;
// reinterpret back to float
// 127 << 23 = 1065353216
// 0b11111111111111111111111 = 8388607
bx = 1065353216 | (bx & 8388607);
x = * (float *) (&bx);
// use remez algorithm to find approximation between [1,2]
// - see this answer https://stackoverflow.com/a/44232045
// - or this usage of C++/boost's remez implementation
// https://computingandrecording.wordpress.com/2017/04/24/
// e.g.
// boost::math::tools::remez_minimax<double> approx(
// [](const double& x) { return log(x); },
// 4, 0, 1, 2, false, 0, 0, 64);
//
// 4th order is:
// { -1.74178, 2.82117, -1.46994, 0.447178, -0.0565717 }
//
// 3rd order is:
// { -1.49278, 2.11263, -0.729104, 0.10969 }
return
/* less accurate */
-1.49278+(2.11263+(-0.729104+0.10969*x)*x)*x
/* OR more accurate */
// -1.7417939+(2.8212026+(-1.4699568+(0.44717955-0.056570851*x)*x)*x)*x
/* compensate for the ln(2)s. ln(2)=0.6931471806 */
+ 0.6931471806*t;
}
//////////////////////////////////////////////////////////////////////////////
#define STB_TRUETYPE_IMPLEMENTATION
#define STB_IMAGE_IMPLEMENTATION
typedef unsigned char u8;
typedef signed char s8;
typedef unsigned short u16;
typedef signed short s16;
typedef unsigned int u32;
typedef signed int s32;
thread_local Allocator third_party_allocator = {0};
void *third_party_malloc(size_t size) {
assert(third_party_allocator.proc, "No third party allocator was set, but it was used!");
if (!size) return 0;
return alloc(third_party_allocator, size);
}
void *third_party_realloc(void *p, size_t size) {
assert(third_party_allocator.proc, "No third party allocator was set, but it was used!");
if (!size) return 0;
if (!p) return third_party_malloc(size);
return third_party_allocator.proc(size, p, ALLOCATOR_REALLOCATE, 0);
}
void third_party_free(void *p) {
assert(third_party_allocator.proc, "No third party allocator was set, but it was used!");
if (!p) return;
dealloc(third_party_allocator, p);
}
#define STBTT_malloc(x,u) ((void)(u),third_party_malloc(x))
#define STBTT_free(x,u) ((void)(u),third_party_free(x))
#define STBTT_assert(x) assert(x)
size_t stbtt_strlen(const char* str) {
size_t count = 0;
while (str[count] != 0) count += 1;
return count;
}
#define STBTT_strlen(x) stbtt_strlen(x)
#define STBTT_memcpy memcpy
#define STBTT_memset memset
#include "third_party/stb_truetype.h"
#define STBI_NO_STDIO
#define STBI_ASSERT(x) {if (!(x)) *(volatile char*)0 = 0;}
#define STBI_MALLOC(sz) third_party_malloc(sz)
#define STBI_REALLOC(p,newsz) third_party_allocator.proc(newsz, p, ALLOCATOR_REALLOCATE, 0)
#define STBI_FREE(p) third_party_free(p)
#include "third_party/stb_image.h"
#define STB_VORBIS_NO_CRT
#include "third_party/stb_vorbis.c"
// Why Sean ?????
#undef R
#undef C
#undef L