Created
April 22, 2020 14:13
-
-
Save josecelano/471e1409b2b5c6699d1f08cb2698f8f9 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <math.h> | |
#ifndef FRACT_STDLIB_H_ | |
#define FRACT_STDLIB_H_ | |
#ifdef __cplusplus | |
extern "C" | |
{ | |
#endif | |
void fract_rand(double *re, double *im); | |
typedef struct s_arena *arena_t; | |
arena_t arena_create(int page_size, int max_pages); | |
void arena_clear(arena_t arena); | |
void arena_delete(arena_t arena); | |
void *arena_alloc( | |
arena_t arena, | |
int element_size, | |
int n_dimensions, | |
int *n_elements); | |
void array_get_int( | |
void *allocation, int n_dimensions, int *indexes, | |
int *pRetVal, int *pInBounds); | |
void array_get_double( | |
void *allocation, int n_dimensions, int *indexes, | |
double *pRetVal, int *pInBounds); | |
int array_set_int( | |
void *allocation, int n_dimensions, int *indexes, int val); | |
int array_set_double( | |
void *allocation, int n_dimensions, int *indexes, double val); | |
void *alloc_array1D(arena_t arena, int element_size, int size); | |
void *alloc_array2D(arena_t arena, int element_size, int xsize, int ysize); | |
void *alloc_array3D(arena_t arena, int element_size, int xsize, int ysize, int zsize); | |
void *alloc_array4D(arena_t arena, int element_size, int xsize, int ysize, int zsize, int wsize); | |
int read_int_array_1D(void *array, int x); | |
int write_int_array_1D(void *array, int x, int val); | |
int read_int_array_2D(void *array, int x, int y); | |
int write_int_array_2D(void *array, int x, int y, int val); | |
double read_float_array_1D(void *array, int x); | |
int write_float_array_1D(void *array, int x, double val); | |
double read_float_array_2D(void *array, int x, int y); | |
int write_float_array_2D(void *array, int x, int y, double val); | |
#ifdef __cplusplus | |
} | |
#endif | |
#endif | |
#ifndef PF_H_ | |
#define PF_H_ | |
/* C signature of point-funcs generated by compiler | |
This is essentially an opaque object with methods implemented in C. | |
Typical usage: | |
//#pixel.re, #pixel.im, #z.re, #z.im | |
double pparams[] = { 1.5, 0.0, 0.0, 0.0}; | |
double initparams[] = {5.0, 2.0}; | |
int nItersDone=0; | |
int nFate=0; | |
double dist=0.0; | |
int solid=0; | |
pf_obj *pf = pf_new(); | |
pf->vtbl->init(pf,0.001,initparams,2); | |
pf->vtbl->calc( | |
pf, | |
pparams, | |
100, | |
0,0,0, | |
&nItersDone, &nFate, &dist, &solid); | |
pf->vtbl->kill(pf); | |
*/ | |
// maximum number of params which can be passed to init | |
#define PF_MAXPARAMS 200 | |
// number of positional params used | |
#define N_PARAMS 11 | |
/* the 'fate' of a point. This can be either | |
Unknown (255) - not yet calculated | |
N - reached an attractor numbered N (up to 30) | |
N | FATE_INSIDE - did not escape | |
N | FATE_SOLID - color with solid color | |
N | FATE_DIRECT - color with DCA | |
*/ | |
typedef unsigned char fate_t; | |
#define FATE_UNKNOWN 255 | |
#define FATE_SOLID 0x80 | |
#define FATE_DIRECT 0x40 | |
#define FATE_INSIDE 0x20 | |
typedef enum { | |
INT = 0, | |
FLOAT = 1, | |
GRADIENT = 2, | |
PARAM_IMAGE = 3 | |
} e_paramtype; | |
struct s_param { | |
e_paramtype t; | |
int intval; | |
double doubleval; | |
void *gradient; | |
void *image; | |
}; | |
struct s_pf_data; | |
struct s_pf_vtable { | |
/* fill in params with the default values for this formula */ | |
void (*get_defaults)( | |
struct s_pf_data *p, | |
double *pos_params, | |
struct s_param *params, | |
int nparams | |
); | |
/* fill in fields in pf_data with appropriate stuff */ | |
void (*init)( | |
struct s_pf_data *p, | |
double *pos_params, | |
struct s_param *params, | |
int nparams | |
); | |
/* calculate one point. | |
perform up to nIters iterations, | |
return: | |
number of iters performed in pnIters | |
outcome in pFate: 0 = escaped, 1 = trapped. | |
More fates may be generated in future | |
dist : index into color table from 0.0 to 1.0 | |
*/ | |
void (*calc)( | |
struct s_pf_data *p, | |
// in params | |
const double *params, int nIters, int warp_param, | |
// tolerance params | |
int min_period_iter, double period_tolerance, | |
// only used for debugging | |
int x, int y, int aa, | |
// out params | |
int *pnIters, int *pFate, double *pDist, int *pSolid, | |
int *pDirectColorFlag, double *pColors | |
); | |
/* deallocate data in p */ | |
void (*kill)( | |
struct s_pf_data *p | |
); | |
}; | |
struct s_pf_data { | |
struct s_pf_vtable *vtbl; | |
void *arena; | |
}; | |
typedef struct s_pf_vtable pf_vtable; | |
typedef struct s_pf_data pf_obj; | |
#ifdef __cplusplus | |
extern "C" { | |
#endif | |
/* create a new pf_obj.*/ | |
extern pf_obj *pf_new(void); | |
#ifdef __cplusplus | |
} | |
#endif | |
#endif /* PF_H_ */ | |
typedef struct { | |
pf_obj parent; | |
struct s_param p[PF_MAXPARAMS]; | |
double pos_params[N_PARAMS]; | |
int f__bailout; | |
void *t__a__gradient; | |
double t__a_fbailout; | |
double z_re; | |
double z_im; | |
double t__f0; | |
double t__f1; | |
double t__f2; | |
double t__f3; | |
double t__f4; | |
double t__f5; | |
double t__f6; | |
double t__f7; | |
double t__f8; | |
double t__f9; | |
int t__f10; | |
double t__a_cf0_offset; | |
double t__a_cf0_density; | |
double t__a_cf0bailout; | |
double cf0ed; | |
double t__cf00; | |
double t__cf01; | |
double t__cf02; | |
double t__cf03; | |
double t__cf04; | |
double t__cf05; | |
double t__cf06; | |
double t__cf07; | |
double t__cf08; | |
double t__cf09; | |
double t__a_cf1_offset; | |
double t__a_cf1_density; | |
double t__cf10; | |
double t__cf11; | |
} pf_real; | |
static void pf_init( | |
struct s_pf_data *p_stub, | |
double *pos_params, | |
struct s_param *params, | |
int nparams) { | |
pf_real *pfo = (pf_real *) p_stub; | |
int i; | |
if (nparams > PF_MAXPARAMS) { | |
nparams = PF_MAXPARAMS; | |
} | |
for (i = 0; i < nparams; ++i) { | |
pfo->p[i] = params[i]; | |
/* printf("param %d = %.17g\n",i,params[i]); */ | |
} | |
for (i = 0; i < N_PARAMS; ++i) { | |
pfo->pos_params[i] = pos_params[i]; | |
} | |
} | |
static void pf_get_defaults( | |
// "object" pointer | |
struct s_pf_data *t__p_stub, | |
// in params | |
double *pos_params, | |
// out params | |
struct s_param *params, | |
// in param | |
int nparams | |
) { | |
pf_real *t__pfo = (pf_real *) t__p_stub; | |
/* | |
t__start_fdefault: ; | |
t__a_fbailout = 4.00000000000000000; | |
goto t__end_fdefault; | |
t__end_fdefault: ; | |
t__pfo->p[3].doubleval = t__a_cf0_density; | |
t__pfo->p[2].doubleval = t__a_cf0_offset; | |
t__pfo->p[4].doubleval = t__a_cf0bailout; | |
t__pfo->p[6].doubleval = t__a_cf1_density; | |
t__pfo->p[5].doubleval = t__a_cf1_offset; | |
t__pfo->p[0].gradient = t__a__gradient; | |
t__pfo->p[1].doubleval = t__a_fbailout; | |
*/ | |
} | |
static void pf_calc( | |
// "object" pointer | |
struct s_pf_data *t__p_stub, | |
// in params | |
const double *t__params, int maxiter, int t__warp_param, | |
// periodicity params | |
int min_period_iter, double period_tolerance, | |
// only used for debugging | |
int t__p_x, int t__p_y, int t__p_aa, | |
// out params | |
int *t__p_pnIters, int *t__p_pFate, double *t__p_pDist, int *t__p_pSolid, | |
int *t__p_pDirectColorFlag, double *t__p_pColors | |
) { | |
pf_real *t__pfo = (pf_real *) t__p_stub; | |
double pixel_re = t__params[0]; | |
double pixel_im = t__params[1]; | |
double t__h_zwpixel_re = t__params[2]; | |
double t__h_zwpixel_im = t__params[3]; | |
double t__h_index = 0.0; | |
int t__h_solid = 0; | |
int t__h_fate = 0; | |
int t__h_inside = 0; | |
double t__h_color_re = 0.0; | |
double t__h_color_i = 0.0; | |
double t__h_color_j = 0.0; | |
double t__h_color_k = 0.0; | |
*t__p_pDirectColorFlag = 0; | |
if (t__warp_param != -1) { | |
t__pfo->p[t__warp_param].doubleval = t__h_zwpixel_re; | |
t__pfo->p[t__warp_param + 1].doubleval = t__h_zwpixel_im; | |
t__h_zwpixel_re = t__h_zwpixel_im = 0.0; | |
} | |
/* variable declarations */ | |
int f__bailout = 0; | |
void *t__a__gradient = t__pfo->p[0].gradient; | |
double t__a_fbailout = t__pfo->p[1].doubleval; | |
double z_re = 0.00000000000000000; | |
double z_im = 0.00000000000000000; | |
double t__f0 = 0.00000000000000000; | |
double t__f1 = 0.00000000000000000; | |
double t__f2 = 0.00000000000000000; | |
double t__f3 = 0.00000000000000000; | |
double t__f4 = 0.00000000000000000; | |
double t__f5 = 0.00000000000000000; | |
double t__f6 = 0.00000000000000000; | |
double t__f7 = 0.00000000000000000; | |
double t__f8 = 0.00000000000000000; | |
double t__f9 = 0.00000000000000000; | |
int t__f10 = 0; | |
double t__a_cf0_offset = t__pfo->p[2].doubleval; | |
double t__a_cf0_density = t__pfo->p[3].doubleval; | |
double t__a_cf0bailout = t__pfo->p[4].doubleval; | |
double cf0ed = 0.00000000000000000; | |
double t__cf00 = 0.00000000000000000; | |
double t__cf01 = 0.00000000000000000; | |
double t__cf02 = 0.00000000000000000; | |
double t__cf03 = 0.00000000000000000; | |
double t__cf04 = 0.00000000000000000; | |
double t__cf05 = 0.00000000000000000; | |
double t__cf06 = 0.00000000000000000; | |
double t__cf07 = 0.00000000000000000; | |
double t__cf08 = 0.00000000000000000; | |
double t__cf09 = 0.00000000000000000; | |
double t__a_cf1_offset = t__pfo->p[5].doubleval; | |
double t__a_cf1_density = t__pfo->p[6].doubleval; | |
double t__cf10 = 0.00000000000000000; | |
double t__cf11 = 0.00000000000000000; | |
double old_z_re; | |
double old_z_im; | |
int period_iters = 0; | |
int save_mask = 9; | |
int save_incr = 1; | |
int next_save_incr = 4; | |
int t__h_numiter = 0; | |
t__start_finit:; | |
z_re = t__h_zwpixel_re; | |
z_im = t__h_zwpixel_im; | |
goto t__end_finit; | |
t__end_finit:; | |
old_z_re = z_re; | |
old_z_im = z_im; | |
do { | |
t__start_floop:; | |
t__f0 = z_re * z_re; | |
t__f1 = z_im * z_im; | |
t__f2 = z_re * z_im; | |
t__f3 = t__f0 - t__f1; | |
t__f4 = 2.00000000000000000 * t__f2; | |
t__f5 = t__f3 + pixel_re; | |
t__f6 = t__f4 + pixel_im; | |
z_re = t__f5; | |
z_im = t__f6; | |
goto t__end_floop; | |
t__end_floop:; | |
t__start_fbailout:; | |
t__f7 = z_re * z_re; | |
t__f8 = z_im * z_im; | |
t__f9 = t__f7 + t__f8; | |
t__f10 = t__f9 < t__a_fbailout; | |
f__bailout = t__f10; | |
goto t__end_fbailout; | |
t__end_fbailout:; | |
if (!f__bailout) break; | |
if (t__h_numiter >= min_period_iter) { | |
if ((t__h_numiter & save_mask) == 0) { | |
/* save a value */ | |
old_z_re = z_re; | |
old_z_im = z_im; | |
if (--save_incr == 0) { | |
/* lengthen period check */ | |
save_mask = (save_mask << 1) + 1; | |
save_incr = next_save_incr; | |
} | |
} else { | |
/* compare to an older value */ | |
if ((fabs(z_re - old_z_re) < period_tolerance) | |
&& (fabs(z_im - old_z_im) < period_tolerance)) { | |
period_iters = t__h_numiter; | |
//t__h_numiter = maxiter; | |
t__h_inside = 1; | |
*t__p_pFate = 1; | |
goto loop_done; | |
} | |
} | |
} | |
t__h_numiter++; | |
} while (t__h_numiter < maxiter); | |
/* fate of 0 = escaped, 1 = trapped */ | |
t__h_inside = (t__h_numiter >= maxiter); | |
*t__p_pFate = (t__h_numiter >= maxiter); | |
loop_done: | |
*t__p_pnIters = t__h_numiter; | |
if (t__h_inside == 0) { | |
t__start_cf0final:; | |
t__cf00 = z_re * z_re; | |
t__cf01 = z_im * z_im; | |
t__cf02 = t__cf00 + t__cf01; | |
t__cf03 = t__cf02 + 0.00000000100000000; | |
t__cf04 = t__a_cf0bailout / t__cf03; | |
cf0ed = t__cf04; | |
t__cf05 = ((double) t__h_numiter); | |
t__cf06 = t__cf05 + cf0ed; | |
t__cf07 = t__cf06 / 256.00000000000000000; | |
t__h_index = t__cf07; | |
t__cf08 = t__a_cf0_density * t__h_index; | |
t__cf09 = t__cf08 + t__a_cf0_offset; | |
t__h_index = t__cf09; | |
goto t__end_cf0final; | |
t__end_cf0final:; | |
; | |
} else { | |
t__start_cf1final:; | |
t__h_solid = 1; | |
t__cf10 = t__a_cf1_density * t__h_index; | |
t__cf11 = t__cf10 + t__a_cf1_offset; | |
t__h_index = t__cf11; | |
goto t__end_cf1final; | |
t__end_cf1final:; | |
; | |
} | |
*t__p_pFate = t__h_fate | (t__h_inside ? FATE_INSIDE : 0); | |
*t__p_pDist = t__h_index; | |
*t__p_pSolid = t__h_solid; | |
arena_clear((arena_t) (t__p_stub->arena)); | |
return; | |
} | |
static void pf_kill( | |
struct s_pf_data *p_stub) { | |
arena_delete((arena_t) (p_stub->arena)); | |
free(p_stub); | |
} | |
static struct s_pf_vtable vtbl = | |
{ | |
pf_get_defaults, | |
pf_init, | |
pf_calc, | |
pf_kill | |
}; | |
pf_obj *pf_new() { | |
pf_real *p = (pf_real *) malloc(sizeof(pf_real)); | |
if (!p) return NULL; | |
p->parent.vtbl = &vtbl; | |
p->parent.arena = arena_create(100000, 1); | |
return (pf_obj *) p; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment