add generated benchmark, split macro defs

This commit is contained in:
Alwin Berger 2025-05-15 07:31:01 +00:00
parent 969ca1886d
commit 274a2428c8
9 changed files with 1591 additions and 143 deletions

View File

@ -131,5 +131,5 @@ extern void vLoggingPrintf( const char * pcFormatString,
#endif
#define configUSE_TASK_NOTIFICATIONS 1
#define configTASK_NOTIFICATION_ARRAY_ENTRIES 4
#define configTASK_NOTIFICATION_ARRAY_ENTRIES 10
#endif /* FREERTOS_CONFIG_H */

View File

@ -159,6 +159,16 @@ ifeq ($(RELEASE_DEMO), 1)
SOURCE_FILES += main_release.c
CFLAGS := -DmainCREATE_RELEASE_DEMO=1
else
ifeq ($(WATERSGEN_DEMO), 1)
SOURCE_FILES += main_watersgen$(SEED).c
CFLAGS := -DmainCREATE_WATERSGEN_DEMO=1
else
ifeq ($(TEST_DEMO), 1)
SOURCE_FILES += main_test.c
CFLAGS := -DmainCREATE_TEST_DEMO=1
else
SOURCE_FILES += main_blinky.c
@ -184,6 +194,8 @@ endif
endif
endif
endif
endif
endif
ifeq ($(IGNORE_BYTES), 1)
CFLAGS += -D IGNORE_BYTES=1

View File

@ -3,6 +3,7 @@
#include <limits.h>
#include <stdint.h>
#include "util_macros.h"
// Time wasters =====
volatile long _NONSENSE_VAR = 0;
@ -24,149 +25,9 @@ volatile long _NONSENSE_VAR = 0;
#define PRINT_MSEC(X,Y) PRINT_NSEC(X*1000000,Y)
// #define PRINT_TIME(X,Y) WASTE_TIME(X)
// Clamps ===========
#define CLAMP_FLOOR(X,LB) ((((X)>(LB))*(X))+(((X)<=(LB))*(LB)))
#define CLAMP_CEILING(X,UB) (((X)>(UB))*(UB)+((X)<=(UB))*(X))
#define CLAMP(X,LB,UB) CLAMP_CEILING((CLAMP_FLOOR(X,LB)),UB) // branch-less clamping
// Random numbers ===
// glibc
// https://en.wikipedia.org/wiki/Linear_congruential_generator
#define A 1103515245ull
#define M 0x80000000ull
#define C 12345ull
// Random state ======
static unsigned long long rng_seed = 2345745ull;
#define RNG rng_seed=((A*rng_seed+C) % M)
#define RNG_FROM(X) ((A*(X)+C) % M)
// Challanges =======
#define CHANCE_1_IN_POWOF2(X,Y) (RNG_FROM(X)<(M>>Y)) // assume the type of x has more than y bits
// polynomes
#define IF_ELSE(X,Y,Z) ((X) ? (Y) : (Z))
// #define IF_ELSE(X,Y,Z) (((X)*(Y))+((!(X))*(Z))) // branchless, takes a huge hit on performance
#define SADD(X,Y) IF_ELSE(((int32_t)(Y))<0, IF_ELSE(((int32_t)(X))<INT_MIN-((int32_t)(Y)), INT_MIN, ((int32_t)(X))+((int32_t)Y)), IF_ELSE(((int32_t)(X))>INT_MAX-((int32_t)(Y)), INT_MAX, ((int32_t)(X))+((int32_t)(Y))))
#define SSUB(X,Y) IF_ELSE(((int32_t)(Y))<0, IF_ELSE(((int32_t)(X))<INT_MAX+((int32_t)(Y)), ((int32_t)(X))-((int32_t)Y), INT_MAX), IF_ELSE(((int32_t)(X))>INT_MIN+((int32_t)(Y)), ((int32_t)(X))-((int32_t)(Y)), INT_MIN))
#define ABS_DIFF(X,Y) (IF_ELSE(((int32_t)(X)<(int32_t)(Y)),(SSUB(Y,X)),(SSUB(X,Y))))
#define SQUARE(X) ((X)*(X))
#define AVG(X,Y) (((X)/2)+((Y)/2))
#define U_ABS_DIFF(X,Y) (__uint32_t)(((__uint32_t)X<(__uint32_t)Y)*((__uint32_t)Y-(__uint32_t)X)+((__uint32_t)X>=(__uint32_t)Y)*((__uint32_t)X-(__uint32_t)Y))
#define CHECKED_SQUARE(X) IF_ELSE((X)<=0x0000B504,SQUARE(X), INT_MAX) // int32_t safe
#define LIN(X,N,D,C) (C+((N)*((X)/(D))))
int32_t hill(int32_t x, int32_t off, int32_t h, int32_t w) {
return CLAMP_FLOOR(SSUB(h,CHECKED_SQUARE(ABS_DIFF(x,off)/w)),0);
}
int32_t valley(int32_t x, int32_t off, int32_t h, int32_t w) {
return CLAMP_CEILING(SADD(h,CHECKED_SQUARE(ABS_DIFF(x,off)/w)),0);
}
#define HILL(X, OFF, H, W) hill(X, OFF, H, W)
#define VALLEY(X, OFF, H, W) valley(X, OFF, H, W)
// #define HILL(X, OFF, H, W) CLAMP_FLOOR(SSUB(H,CHECKED_SQUARE(ABS_DIFF(X,OFF)/W)),0)
// #define VALLEY(X, OFF, H, W) CLAMP_CEILING(SADD(H,CHECKED_SQUARE(ABS_DIFF(X,OFF)/W)),0)
#define STRETCH_i32(X) (X<<(8*(sizeof(int32_t)-sizeof(X)))) // stretch any integer to 32 bits
#define JITTER(X, B) (RNG_FROM(X+B)%B)
#define TRANSLATE_BOUNDS(X, FLB, FUB, TLB, TUB) (CLAMP(X,FLB,FUB)-FLB) / ((FUB-FLB)/(TUB-TLB)) + TLB
#define FUNCTION_1(X) \
HILL(X, 0, 200000, 800000) \
+ HILL(X, (INT_MIN/4)*3, 400000, 1500000) \
+ HILL(X, INT_MAX/2, 800000, 200000) \
+ CLAMP_FLOOR(LIN(SSUB(X, INT_MAX/4),5,100000,0),0) \
+ CLAMP_FLOOR(LIN(-X,5,100000,0),0) \
+ 200000 \
- JITTER(X, 30000)
#define FUNCTION_2(X) \
VALLEY(X, 0, -200000, 800000) \
+ VALLEY(X, (INT_MIN/4)*3, -400000, 1500000) \
+ VALLEY(X, INT_MAX/2, -800000, 200000) \
+ CLAMP_FLOOR(LIN(SSUB(X, INT_MAX/4),5,100000,0),0) \
+ CLAMP_FLOOR(LIN(-X,5,-100000,0),0) \
+ 200000 \
- JITTER(X, 30000)
#define FUNCTION_3(X) \
LIN(SADD(X, INT_MAX/2),5,100000,0) \
+ LIN(-X,2,100000,0) \
- JITTER(X, 10000)
#define FUNCTION_4(X) \
LIN(SADD(X, 3*(INT_MAX/8)),-30,100000,0) \
+ LIN(SSUB(X, 3*(INT_MAX/8)),30,100000,0) \
- JITTER(X, 10000)
#define FUNCTION_5(X) \
VALLEY(X, 0, -200000, 10000000) \
+ HILL(X, 0, 42000, 5000000) \
- JITTER(X, 1000)
#define FUNCTION_6(X) \
LIN(X,1,2,0) \
+ HILL(X, -1500000000, 1000000000, 50000) \
+ VALLEY(X, 1500000000, -1000000000, 50000) \
- JITTER(X, 1000)
#define FUNCTION_7(X) \
LIN(X,1,100000,0) \
+ HILL(X, 7*(INT_MIN/8), 140000, 200000) \
+ HILL(X, 6*(INT_MIN/8), 100000, 200000) \
+ HILL(X, 5*(INT_MIN/8), 80000, 200000) \
+ HILL(X, 4*(INT_MIN/8), 60000, 200000) \
+ HILL(X, 3*(INT_MIN/8), 70000, 200000) \
+ HILL(X, 2*(INT_MIN/8), 80000, 200000) \
+ HILL(X, 1*(INT_MIN/8), 90000, 200000) \
+ HILL(X, 1*(INT_MAX/8), 90000, 200000) \
+ HILL(X, 2*(INT_MAX/8), 80000, 200000) \
+ HILL(X, 3*(INT_MAX/8), 70000, 200000) \
+ HILL(X, 4*(INT_MAX/8), 60000, 200000) \
+ HILL(X, 5*(INT_MAX/8), 50000, 200000) \
+ HILL(X, 6*(INT_MAX/8), 40000, 200000) \
+ HILL(X, 7*(INT_MAX/8), 30000, 200000) \
- JITTER(X, 1000)
#define FUNCTION_8(X) \
(X>INT_MIN/2)*HILL((X%(INT_MAX/3)), 0, 10000000, 50000) * (ABS_DIFF(X,0)/100000000) \
+ LIN(X, -1, 100, 0) \
- JITTER(X, 1000)
#define FUNCTION_9(X) \
HILL(X, 3*(INT_MIN/4), 200000, 800000) \
+ HILL(X, 1*(INT_MIN/4), 200000, 800000) \
+ HILL(X, 3*(INT_MAX/4), 400000, 400000) \
+ (X<0)*LIN(X, 1, 10000, 0) \
+ (X>0)*LIN(X, -1, 10000, 0) \
- JITTER(X, 1000)
#define FUNCTION_10(X) \
+ (X<=0)*LIN(X, 1, 10000, 0) \
+ (X>0)*LIN(X, -1, 10000, 0) \
+ VALLEY(X, 0, -200000, 1000000) \
+ 200000 \
- JITTER(X, 1000)
#define TRANSLATE_1(I, LB,UB) TRANSLATE_BOUNDS((I), 180000, 1000000, LB, UB) // FN 1
#define TRANSLATE_2(I, LB,UB) TRANSLATE_BOUNDS((I), -500000, 390000, LB, UB) // FN 2
#define TRANSLATE_3(I, LB,UB) TRANSLATE_BOUNDS((I), -8000, 80000, LB, UB) // FN 3
#define TRANSLATE_4(I, LB,UB) TRANSLATE_BOUNDS((I), -480000, -250000, LB, UB) // FN 4
#define TRANSLATE_5(I, LB,UB) TRANSLATE_BOUNDS((I), -193000, -155000, LB, UB) // FN 5
#define TRANSLATE_6(I, LB,UB) TRANSLATE_BOUNDS((I), -400000000, 400000000, LB, UB) // FN 6
#define TRANSLATE_7(I, LB,UB) TRANSLATE_BOUNDS((I), -20000, 120000, LB, UB) // FN 7
#define TRANSLATE_8(I, LB,UB) TRANSLATE_BOUNDS((I), -20000000, 120000000, LB, UB) // FN 8
#define TRANSLATE_9(I, LB,UB) TRANSLATE_BOUNDS((I), -200000, 220000, LB, UB) // FN 9
#define TRANSLATE_10(I, LB,UB) TRANSLATE_BOUNDS((I), -10000, 150000, LB, UB) // FN 10
#define RNG rng_seed=RNG_FROM(rng_seed);
#endif

View File

@ -0,0 +1,184 @@
#![allow(non_camel_case_types,non_snake_case,non_upper_case_globals,deref_nullptr,unused)]
use serde::{Deserialize, Serialize};
/*========== Start of generated Code =============*/
pub type char_ptr = ::std::os::raw::c_uint;
pub type void_ptr = ::std::os::raw::c_uint;
pub type ListItem_t_ptr = ::std::os::raw::c_uint;
pub type QueueDefinition_ptr = ::std::os::raw::c_uint;
pub type StackType_t_ptr = ::std::os::raw::c_uint;
pub type i_ptr8 = ::std::os::raw::c_uint;
pub type tskTaskControlBlock_ptr = ::std::os::raw::c_uint;
pub type xLIST_ptr = ::std::os::raw::c_uint;
pub type xLIST_ITEM_ptr = ::std::os::raw::c_uint;
/* automatically generated by rust-bindgen 0.71.1 */
pub const configASSERT_DEFINED: u32 = 1;
pub const configQUEUE_REGISTRY_SIZE: u32 = 20;
pub const configUSE_PREEMPTION: u32 = 1;
pub const configUSE_TIME_SLICING: u32 = 0;
pub const configUSE_PORT_OPTIMISED_TASK_SELECTION: u32 = 0;
pub const configUSE_IDLE_HOOK: u32 = 1;
pub const configUSE_TICK_HOOK: u32 = 1;
pub const configUSE_DAEMON_TASK_STARTUP_HOOK: u32 = 0;
pub const configMAX_TASK_NAME_LEN: u32 = 10;
pub const configUSE_TRACE_FACILITY: u32 = 0;
pub const configUSE_STATS_FORMATTING_FUNCTIONS: u32 = 0;
pub const configUSE_16_BIT_TICKS: u32 = 0;
pub const configIDLE_SHOULD_YIELD: u32 = 1;
pub const configUSE_CO_ROUTINES: u32 = 0;
pub const configMAX_PRIORITIES: u32 = 15;
pub const configMAX_CO_ROUTINE_PRIORITIES: u32 = 2;
pub const configTIMER_QUEUE_LENGTH: u32 = 20;
pub const configTIMER_TASK_PRIORITY: u32 = 14;
pub const configUSE_COUNTING_SEMAPHORES: u32 = 1;
pub const configSUPPORT_DYNAMIC_ALLOCATION: u32 = 1;
pub const configSUPPORT_STATIC_ALLOCATION: u32 = 1;
pub const configNUM_TX_DESCRIPTORS: u32 = 15;
pub const configSTREAM_BUFFER_TRIGGER_LEVEL_TEST_MARGIN: u32 = 2;
pub const configUSE_QUEUE_SETS: u32 = 1;
pub const configUSE_MALLOC_FAILED_HOOK: u32 = 1;
pub const configUSE_MUTEXES: u32 = 1;
pub const configUSE_RECURSIVE_MUTEXES: u32 = 1;
pub const configUSE_TIMERS: u32 = 1;
pub const INCLUDE_vTaskPrioritySet: u32 = 1;
pub const INCLUDE_uxTaskPriorityGet: u32 = 1;
pub const INCLUDE_vTaskDelete: u32 = 1;
pub const INCLUDE_vTaskCleanUpResources: u32 = 0;
pub const INCLUDE_vTaskSuspend: u32 = 1;
pub const INCLUDE_vTaskDelayUntil: u32 = 1;
pub const INCLUDE_vTaskDelay: u32 = 1;
pub const INCLUDE_uxTaskGetStackHighWaterMark: u32 = 1;
pub const INCLUDE_uxTaskGetStackHighWaterMark2: u32 = 1;
pub const INCLUDE_xTaskGetSchedulerState: u32 = 1;
pub const INCLUDE_xTimerGetTimerDaemonTaskHandle: u32 = 1;
pub const INCLUDE_xTaskGetIdleTaskHandle: u32 = 1;
pub const INCLUDE_xTaskGetHandle: u32 = 1;
pub const INCLUDE_eTaskGetState: u32 = 1;
pub const INCLUDE_xSemaphoreGetMutexHolder: u32 = 1;
pub const INCLUDE_xTimerPendFunctionCall: u32 = 1;
pub const INCLUDE_xTaskAbortDelay: u32 = 1;
pub const projCOVERAGE_TEST: u32 = 0;
pub const configKERNEL_INTERRUPT_PRIORITY: u32 = 255;
pub const configMAX_SYSCALL_INTERRUPT_PRIORITY: u32 = 191;
pub const configMAC_INTERRUPT_PRIORITY: u32 = 5;
pub const configUSE_TASK_NOTIFICATIONS: u32 = 1;
pub const configTASK_NOTIFICATION_ARRAY_ENTRIES: u32 = 10;
/* automatically generated by rust-bindgen 0.71.1 */
pub type StackType_t = u32;
pub type UBaseType_t = ::std::os::raw::c_uint;
pub type TickType_t = u32;
#[repr(C)]
#[derive(Debug, Copy, Clone, Default, Serialize, Deserialize)]
pub struct xLIST_ITEM {
pub xItemValue: TickType_t,
pub pxNext: xLIST_ITEM_ptr,
pub pxPrevious: xLIST_ITEM_ptr,
pub pvOwner: void_ptr,
pub pvContainer: xLIST_ptr,
}
pub type ListItem_t = xLIST_ITEM;
#[repr(C)]
#[derive(Debug, Copy, Clone, Default, Serialize, Deserialize)]
pub struct xMINI_LIST_ITEM {
pub xItemValue: TickType_t,
pub pxNext: xLIST_ITEM_ptr,
pub pxPrevious: xLIST_ITEM_ptr,
}
pub type MiniListItem_t = xMINI_LIST_ITEM;
#[repr(C)]
#[derive(Debug, Copy, Clone, Default, Serialize, Deserialize)]
pub struct xLIST {
pub uxNumberOfItems: UBaseType_t,
pub pxIndex: ListItem_t_ptr,
pub xListEnd: MiniListItem_t,
}
pub type List_t = xLIST;
pub type TaskHandle_t = tskTaskControlBlock_ptr;
pub const eTaskState_eRunning: eTaskState = 0;
pub const eTaskState_eReady: eTaskState = 1;
pub const eTaskState_eBlocked: eTaskState = 2;
pub const eTaskState_eSuspended: eTaskState = 3;
pub const eTaskState_eDeleted: eTaskState = 4;
pub const eTaskState_eInvalid: eTaskState = 5;
pub type eTaskState = ::std::os::raw::c_uint;
#[repr(C)]
#[derive(Debug, Copy, Clone, Default, Serialize, Deserialize)]
pub struct xTASK_STATUS {
pub xHandle: TaskHandle_t,
pub pcTaskName: char_ptr,
pub xTaskNumber: UBaseType_t,
pub eCurrentState: eTaskState,
pub uxCurrentPriority: UBaseType_t,
pub uxBasePriority: UBaseType_t,
pub ulRunTimeCounter: u32,
pub pxStackBase: StackType_t_ptr,
pub usStackHighWaterMark: u16,
}
pub type TaskStatus_t = xTASK_STATUS;
pub type QueueHandle_t = QueueDefinition_ptr;
#[repr(C)]
#[derive(Debug, Copy, Clone, Default, Serialize, Deserialize)]
pub struct QueuePointers {
pub pcTail: i_ptr8,
pub pcReadFrom: i_ptr8,
}
pub type QueuePointers_t = QueuePointers;
#[repr(C)]
#[derive(Debug, Copy, Clone, Default, Serialize, Deserialize)]
pub struct SemaphoreData {
pub xMutexHolder: TaskHandle_t,
pub uxRecursiveCallCount: UBaseType_t,
}
pub type SemaphoreData_t = SemaphoreData;
#[repr(C)]
#[derive(Copy, Clone)]
pub struct QueueDefinition {
pub pcHead: i_ptr8,
pub pcWriteTo: i_ptr8,
pub u: QueueDefinition__bindgen_ty_1,
pub xTasksWaitingToSend: List_t,
pub xTasksWaitingToReceive: List_t,
pub uxMessagesWaiting: UBaseType_t,
pub uxLength: UBaseType_t,
pub uxItemSize: UBaseType_t,
pub cRxLock: i8,
pub cTxLock: i8,
pub ucStaticallyAllocated: u8,
pub pxQueueSetContainer: QueueDefinition_ptr,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub union QueueDefinition__bindgen_ty_1 {
pub xQueue: QueuePointers_t,
pub xSemaphore: SemaphoreData_t,
}
pub type xQUEUE = QueueDefinition;
pub type Queue_t = xQUEUE;
#[repr(C)]
#[derive(Debug, Copy, Clone, Default, Serialize, Deserialize)]
pub struct QUEUE_REGISTRY_ITEM {
pub pcQueueName: char_ptr,
pub xHandle: QueueHandle_t,
}
pub type xQueueRegistryItem = QUEUE_REGISTRY_ITEM;
pub type QueueRegistryItem_t = xQueueRegistryItem;
#[repr(C)]
#[derive(Debug, Copy, Clone, Default, Serialize, Deserialize)]
pub struct tskTaskControlBlock {
pub pxTopOfStack: StackType_t_ptr,
pub xStateListItem: ListItem_t,
pub xEventListItem: ListItem_t,
pub uxPriority: UBaseType_t,
pub pxStack: StackType_t_ptr,
pub pcTaskName: [::std::os::raw::c_char; 10usize],
pub uxBasePriority: UBaseType_t,
pub uxMutexesHeld: UBaseType_t,
pub ulNotifiedValue: [u32; 10usize],
pub ucNotifyState: [u8; 10usize],
pub ucStaticallyAllocated: u8,
pub ucDelayAborted: u8,
}
pub type tskTCB = tskTaskControlBlock;
pub type TCB_t = tskTCB;

View File

@ -127,6 +127,14 @@ int main()
{
main_osek();
}
#elif ( mainCREATE_WATERSGEN_DEMO == 1 )
{
main_waters();
}
#elif ( mainCREATE_TEST_DEMO == 1 )
{
main_test();
}
#else
{

View File

@ -9,6 +9,7 @@
// tight and force preemptions
#define NUM_TASKS 15
#include "fuzzhelper.c"
#include "polynomic_functions.h"
// #ifdef INSERT_WC
// #include "wcinput.h"

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,94 @@
#ifndef __POLYNOMIC_FUNCTIONS_H__
#define __POLYNOMIC_FUNCTIONS_H__
#include "util_macros.h"
#define FUNCTION_1(X) \
HILL(X, 0, 200000, 800000) \
+ HILL(X, (INT_MIN/4)*3, 400000, 1500000) \
+ HILL(X, INT_MAX/2, 800000, 200000) \
+ CLAMP_FLOOR(LIN(SSUB(X, INT_MAX/4),5,100000,0),0) \
+ CLAMP_FLOOR(LIN(-X,5,100000,0),0) \
+ 200000 \
- JITTER(X, 30000)
#define FUNCTION_2(X) \
VALLEY(X, 0, -200000, 800000) \
+ VALLEY(X, (INT_MIN/4)*3, -400000, 1500000) \
+ VALLEY(X, INT_MAX/2, -800000, 200000) \
+ CLAMP_FLOOR(LIN(SSUB(X, INT_MAX/4),5,100000,0),0) \
+ CLAMP_FLOOR(LIN(-X,5,-100000,0),0) \
+ 200000 \
- JITTER(X, 30000)
#define FUNCTION_3(X) \
LIN(SADD(X, INT_MAX/2),5,100000,0) \
+ LIN(-X,2,100000,0) \
- JITTER(X, 10000)
#define FUNCTION_4(X) \
LIN(SADD(X, 3*(INT_MAX/8)),-30,100000,0) \
+ LIN(SSUB(X, 3*(INT_MAX/8)),30,100000,0) \
- JITTER(X, 10000)
#define FUNCTION_5(X) \
VALLEY(X, 0, -200000, 10000000) \
+ HILL(X, 0, 42000, 5000000) \
- JITTER(X, 1000)
#define FUNCTION_6(X) \
LIN(X,1,2,0) \
+ HILL(X, -1500000000, 1000000000, 50000) \
+ VALLEY(X, 1500000000, -1000000000, 50000) \
- JITTER(X, 1000)
#define FUNCTION_7(X) \
LIN(X,1,100000,0) \
+ HILL(X, 7*(INT_MIN/8), 140000, 200000) \
+ HILL(X, 6*(INT_MIN/8), 100000, 200000) \
+ HILL(X, 5*(INT_MIN/8), 80000, 200000) \
+ HILL(X, 4*(INT_MIN/8), 60000, 200000) \
+ HILL(X, 3*(INT_MIN/8), 70000, 200000) \
+ HILL(X, 2*(INT_MIN/8), 80000, 200000) \
+ HILL(X, 1*(INT_MIN/8), 90000, 200000) \
+ HILL(X, 1*(INT_MAX/8), 90000, 200000) \
+ HILL(X, 2*(INT_MAX/8), 80000, 200000) \
+ HILL(X, 3*(INT_MAX/8), 70000, 200000) \
+ HILL(X, 4*(INT_MAX/8), 60000, 200000) \
+ HILL(X, 5*(INT_MAX/8), 50000, 200000) \
+ HILL(X, 6*(INT_MAX/8), 40000, 200000) \
+ HILL(X, 7*(INT_MAX/8), 30000, 200000) \
- JITTER(X, 1000)
#define FUNCTION_8(X) \
(X>INT_MIN/2)*HILL((X%(INT_MAX/3)), 0, 10000000, 50000) * (ABS_DIFF(X,0)/100000000) \
+ LIN(X, -1, 100, 0) \
- JITTER(X, 1000)
#define FUNCTION_9(X) \
HILL(X, 3*(INT_MIN/4), 200000, 800000) \
+ HILL(X, 1*(INT_MIN/4), 200000, 800000) \
+ HILL(X, 3*(INT_MAX/4), 400000, 400000) \
+ (X<0)*LIN(X, 1, 10000, 0) \
+ (X>0)*LIN(X, -1, 10000, 0) \
- JITTER(X, 1000)
#define FUNCTION_10(X) \
+ (X<=0)*LIN(X, 1, 10000, 0) \
+ (X>0)*LIN(X, -1, 10000, 0) \
+ VALLEY(X, 0, -200000, 1000000) \
+ 200000 \
- JITTER(X, 1000)
#define TRANSLATE_1(I, LB,UB) TRANSLATE_BOUNDS((I), 180000, 1000000, LB, UB) // FN 1
#define TRANSLATE_2(I, LB,UB) TRANSLATE_BOUNDS((I), -500000, 390000, LB, UB) // FN 2
#define TRANSLATE_3(I, LB,UB) TRANSLATE_BOUNDS((I), -8000, 80000, LB, UB) // FN 3
#define TRANSLATE_4(I, LB,UB) TRANSLATE_BOUNDS((I), -480000, -250000, LB, UB) // FN 4
#define TRANSLATE_5(I, LB,UB) TRANSLATE_BOUNDS((I), -193000, -155000, LB, UB) // FN 5
#define TRANSLATE_6(I, LB,UB) TRANSLATE_BOUNDS((I), -400000000, 400000000, LB, UB) // FN 6
#define TRANSLATE_7(I, LB,UB) TRANSLATE_BOUNDS((I), -20000, 120000, LB, UB) // FN 7
#define TRANSLATE_8(I, LB,UB) TRANSLATE_BOUNDS((I), -20000000, 120000000, LB, UB) // FN 8
#define TRANSLATE_9(I, LB,UB) TRANSLATE_BOUNDS((I), -200000, 220000, LB, UB) // FN 9
#define TRANSLATE_10(I, LB,UB) TRANSLATE_BOUNDS((I), -10000, 150000, LB, UB) // FN 10
#endif

View File

@ -0,0 +1,131 @@
#ifndef __UTIL_MACROS_H__
#define __UTIL_MACROS_H__
#include <limits.h>
#include <stdint.h>
// Veriadic macros ==
#define REP_VA0(...)
#define REP_VA1(...) __VA_ARGS__
#define REP_VA2(...) REP_VA1(__VA_ARGS__),__VA_ARGS__
#define REP_VA3(...) REP_VA2(__VA_ARGS__),__VA_ARGS__
#define REP_VA4(...) REP_VA3(__VA_ARGS__),__VA_ARGS__
#define REP_VA5(...) REP_VA4(__VA_ARGS__),__VA_ARGS__
#define REP_VA6(...) REP_VA5(__VA_ARGS__),__VA_ARGS__
#define REP_VA7(...) REP_VA6(__VA_ARGS__),__VA_ARGS__
#define REP_VA8(...) REP_VA7(__VA_ARGS__),__VA_ARGS__
#define REP_VA9(...) REP_VA8(__VA_ARGS__),__VA_ARGS__
#define REP_VA10(...) REP_VA9(__VA_ARGS__),__VA_ARGS__
#define REP_VA(HUNDREDS,TENS,ONES,...) \
REP_VA##HUNDREDS(REP_VA10(REP_VA10(__VA_ARGS__))) \
REP_VA##TENS(REP_VA10(__VA_ARGS__)) \
REP_VA##ONES(__VA_ARGS__)
// Random numbers ===
// glibc
// https://en.wikipedia.org/wiki/Linear_congruential_generator
#define __UTIL_RNG_A 1103515245ull
#define __UTIL_RNG_M 0x80000000ull
#define __UTIL_RNG_C 12345ull
#define RNG_FROM(X) ((__UTIL_RNG_A*(X)+__UTIL_RNG_C) % __UTIL_RNG_M)
#define IF_ELSE(X,Y,Z) ((X) ? (Y) : (Z))
// Challanges =======
#define CHANCE_1_IN_POWOF2(X,Y) (RNG_FROM(X)<(M>>Y)) // assume the type of x has more than y bits
// branchless, takes a large hit on performance
#ifdef BRANCHLESS_TERNARY
#define IF_ELSE(X,Y,Z) (((X)*(Y))+((!(X))*(Z)))
#else
#define IF_ELSE(X,Y,Z) ((X) ? (Y) : (Z))
#endif
// Arithmetic =======
static inline int32_t sadd_i32(int32_t a, int32_t b) {
return IF_ELSE((b>=0),
IF_ELSE((a > INT32_MAX - b), INT32_MAX, a + b),
IF_ELSE((a < INT32_MIN - b), INT32_MIN, a + b));
}
static inline int32_t ssub_i32(int32_t a, int32_t b) {
return IF_ELSE((b>=0),
IF_ELSE((a < INT32_MIN + b), INT32_MIN, a - b),
IF_ELSE((a > INT32_MAX + b), INT32_MAX, a - b));
}
static inline int32_t ssquare_i32(int32_t a) {
return IF_ELSE((a <= 0x0000B504 ), a*a, INT32_MAX);
}
static inline int32_t abs_i32(int32_t a) {
return IF_ELSE((a > 0), a, IF_ELSE((a == INT32_MIN), INT32_MAX, -a));
}
static inline int32_t abs_diff_i32(int32_t a, int32_t b) {
return IF_ELSE((a > b), (a-b), (b-a));
}
static inline int32_t min_i32(int32_t a, int32_t b) {
return IF_ELSE((a > b), b, a);
}
static inline int32_t max_i32(int32_t a, int32_t b) {
return IF_ELSE((a > b), b, a);
}
static inline int32_t clamp_i32(int32_t x, int32_t lb, int32_t ub) {
return IF_ELSE((x < lb), lb, IF_ELSE((x > ub), ub, x));
}
static inline int32_t lin_i32(int32_t x, int32_t nom, int32_t den, int32_t c) {
int64_t tmp = ((int64_t)x * nom) / den + c;
return IF_ELSE((tmp < (int64_t)INT32_MAX), (int32_t)tmp, INT32_MAX);
}
static inline int32_t hill_i32(int32_t x, int32_t off, int32_t h, int32_t w) {
return max_i32(ssub_i32(h,ssquare_i32(abs_diff_i32(x,off)/w)),0);
}
static inline int32_t valley_i32(int32_t x, int32_t off, int32_t h, int32_t w) {
return min_i32(sadd_i32(h,ssquare_i32(abs_diff_i32(x,off)/w)),0);
}
//#define MACRO_ONLY
#ifdef MACRO_ONLY
// macros only increses the code size exponentially
// Branchless clamps ===========
#define CLAMP_FLOOR(X,LB) ((((X)>(LB))*(X))+(((X)<=(LB))*(LB)))
#define CLAMP_CEILING(X,UB) (((X)>(UB))*(UB)+((X)<=(UB))*(X))
#define CLAMP(X,LB,UB) CLAMP_CEILING((CLAMP_FLOOR(X,LB)),UB)
#define SADD(X,Y) IF_ELSE(((int32_t)(Y))<0, IF_ELSE(((int32_t)(X))<INT_MIN-((int32_t)(Y)), INT_MIN, ((int32_t)(X))+((int32_t)Y)), IF_ELSE(((int32_t)(X))>INT_MAX-((int32_t)(Y)), INT_MAX, ((int32_t)(X))+((int32_t)(Y))))
#define SSUB(X,Y) IF_ELSE(((int32_t)(Y))<0, IF_ELSE(((int32_t)(X))<INT_MAX+((int32_t)(Y)), ((int32_t)(X))-((int32_t)Y), INT_MAX), IF_ELSE(((int32_t)(X))>INT_MIN+((int32_t)(Y)), ((int32_t)(X))-((int32_t)(Y)), INT_MIN))
#define ABS_DIFF(X,Y) (IF_ELSE(((int32_t)(X)<(int32_t)(Y)),(SSUB(Y,X)),(SSUB(X,Y))))
#define AVG(X,Y) (((X)/2)+((Y)/2))
#define SQUARE(X) ((X)*(X))
#define CHECKED_SQUARE(X) IF_ELSE((X)<=0x0000B504,SQUARE(X), INT_MAX) // int32_t safe
#define LIN(X,N,D,C) (C+((N)*((X)/(D))))
#define HILL(X, OFF, H, W) (CLAMP_FLOOR(SSUB(h,CHECKED_SQUARE(ABS_DIFF(x,off)/w)),0))
#define VALLEY(X, OFF, H, W) (CLAMP_CEILING(SADD(h,CHECKED_SQUARE(ABS_DIFF(x,off)/w)),0))
#else
#define CLAMP_FLOOR(X,LB) max_i32(X, LB)
#define CLAMP_CEILING(X,UB) min_i32(X, UB)
#define CLAMP(X,LB,UB) clamp_i32(X, LB, UB)
#define SADD(X,Y) sadd_i32(X, Y)
#define SSUB(X,Y) ssub_i32(X, Y)
#define ABS_DIFF(X,Y) abs_diff_i32(X,Y)
#define AVG(X,Y) (((X)/2)+((Y)/2))
#define SQUARE(X) ((X)*(X))
#define CHECKED_SQUARE(X) ssquare_i32(X)
#define LIN(X,N,D,C) lin_i32(X,N,D,C)
#define HILL(X, OFF, H, W) hill_i32(X, OFF, H, W)
#define VALLEY(X, OFF, H, W) valley_i32(X, OFF, H, W)
#endif
// Input handling ==
#define STRETCH_i32(X) (X<<(8*(sizeof(int32_t)-sizeof(X)))) // stretch any integer to 32 bits
#define JITTER(X, B) (RNG_FROM(X+B)%B)
//#define TRANSLATE_BOUNDS(X, FLB, FUB, TLB, TUB) (CLAMP(X,FLB,FUB)-FLB) / ((FUB-FLB)/(TUB-TLB)) + TLB
#define TRANSLATE_BOUNDS(X, FLB, FUB, TLB, TUB) ( ((CLAMP(X,FLB,FUB)-FLB)*(TUB-TLB)) / ((FUB-FLB)) + TLB )
#endif // __UTIL_MACROS_H__