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

163 lines
4.6 KiB
C
Raw Normal View History

2024-07-15 21:40:27 +02:00
// 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;
2024-07-08 15:33:01 +02:00
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;
2024-07-08 15:33:01 +02:00
return alloc(third_party_allocator, size);
}
2024-07-15 21:40:27 +02:00
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);
}
2024-07-08 15:33:01 +02:00
void third_party_free(void *p) {
assert(third_party_allocator.proc, "No third party allocator was set, but it was used!");
if (!p) return;
2024-07-08 15:33:01 +02:00
dealloc(third_party_allocator, p);
}
2024-07-08 15:33:01 +02:00
#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
2024-07-08 15:33:01 +02:00
#include "third_party/stb_truetype.h"
#define STBI_NO_STDIO
#define STBI_ASSERT(x) {if (!(x)) *(volatile char*)0 = 0;}
2024-07-08 15:33:01 +02:00
#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"
2024-07-08 15:33:01 +02:00
#define STB_VORBIS_NO_CRT
#include "third_party/stb_vorbis.c"
// Why Sean ?????
#undef R
#undef C
#undef L