diff --git a/2006/monge/.gitignore b/2006/monge/.gitignore index 34f266b2b..bb2b24faf 100644 --- a/2006/monge/.gitignore +++ b/2006/monge/.gitignore @@ -1,3 +1,4 @@ monge +monge.alt monge.orig prog.orig diff --git a/2006/monge/Makefile b/2006/monge/Makefile index 3bc34d80a..2f67911e9 100644 --- a/2006/monge/Makefile +++ b/2006/monge/Makefile @@ -42,7 +42,7 @@ CSILENCE= -Wno-bitwise-op-parentheses -Wno-conditional-type-mismatch \ -Wno-declaration-after-statement -Wno-dollar-in-identifier-extension \ -Wno-error -Wno-implicit-function-declaration \ -Wno-incompatible-pointer-types -Wno-int-conversion -Wno-parentheses \ - -Wno-return-type -Wno-strict-prototypes + -Wno-return-type -Wno-strict-prototypes -Wno-implicit-int # Common C compiler warning flags # @@ -119,8 +119,8 @@ OBJ= ${PROG}.o DATA= TARGET= ${PROG} # -ALT_OBJ= -ALT_TARGET= +ALT_OBJ= ${PROG}.alt.o +ALT_TARGET= ${PROG}.alt ################# @@ -143,6 +143,9 @@ ${PROG}: ${PROG}.c alt: data ${ALT_TARGET} @${TRUE} +${PROG}.alt: ${PROG}.alt.c + ${CC} ${CFLAGS} $< -o $@ ${LDFLAGS} + # data files # data: ${DATA} diff --git a/2006/monge/README.md b/2006/monge/README.md index b1616c263..4fe28852b 100644 --- a/2006/monge/README.md +++ b/2006/monge/README.md @@ -6,6 +6,9 @@ Make sure you have the SDL1 (not SDL2!) development environment installed. make ``` +There is alternate code that lets you redefine the width and height and number +of iterations to use. See [alternate code](#alternate-code) below. + ### Bugs and (Mis)features: @@ -42,6 +45,49 @@ That's not a bug, that's a feature. ``` +## Alternate code: + +This alternate code lets you specify the width and height of the image as well +as the number of iterations to perform. + + +### Alternate build: + + +To use the default values, the same as [monge.c](monge.c), just do: + + +```sh +make alt +``` + +But if you wish to actually make use of it you will want to redefine one or more +of the variables `W`, `H` and `I`. The defaults are (respectively) 400, 300 and +\128. If you wish to change the image size to 500x500 but keep the iterations +the same then do: + +```sh +make clobber CDEFINE="-DW=500 -DH=500" alt +``` + +If you wish to keep the dimensions the same but change the iterations to 512: + +```sh +make clobber CDEFINE="-DI=512" alt +``` + +If you specify a value less than 1 for any of these it sets it back to the +default. The value 1 was selected arbitrarily and such a small number as 1 will +not do anything useful but as long as it's at least 1 it'll not be redefined. +Does not try taking care of overflows but such large values would be impractical +anyway. + + +### Alternate use: + +Use `monge.alt` exactly as you would `monge` above. + + ## Judges' remarks: For those who are familiar with the previous [IOCCC winners](/winners.html), @@ -81,6 +127,7 @@ needed. 4. Enjoy, unless you're more interested in trying to understand how it works. :) + ### Introduction This is a fractal generator that supports custom formulas and real time zoom. @@ -103,68 +150,81 @@ as you like (as understood by the C function `isspace()`). Supported operations and functions are: +``` Operation | Description :-------- | :---------- -`+,-,*,/` | Arithmetic operations, priority of `*`,`/` over `+,-` is - respected. + +,-,*,/ | Arithmetic operations, priority of * , / over +,- is + | respected. | -`<,>` | Compares the real parts of two complex numbers (the imaginary part + <,> | Compares the real parts of two complex numbers (the imaginary part | is ignored). Any number of conditions is allowed, the iteration | will just stop as soon as one of them fails. -`Abs2` | Calculates the squared norm, i.e.: `Abs2(a+b*i)` is `(a*a+b*b)+0*i`. -`Re` | Extract the real part, i.e.: `Re(a+b*i)` is `a+0*i`. -`Im` | Extract the imaginary part, i.e.: `Im(a+b*i) is b+0*i`. -`Exp` | Calculates the complex exponential, i.e. `Exp(a+b*i)` is - | `e^a*(cos(b)+sin(b)*i)` -`Ln` | Calculates the principal value of the natural logarithm, i.e. - `Ln(a+b*i)` is `ln(a*a+b*b)/2` + `atan(b/a)*i` + Abs2 | Calculates the squared norm, i.e.: Abs2(a+b*i) is (a*a+b*b)+0*i. + Re | Extract the real part, i.e.: Re(a+b*i) is a+0*i. + Im | Extract the imaginary part, i.e.: Im(a+b*i) is b+0*i. + Exp | Calculates the complex exponential, i.e. Exp(a+b*i) is + | e^a*(cos(b)+sin(b)*i). + Ln | Calculates the principal value of the natural logarithm, i.e. + Ln(a+b*i) is ln(a*a+b*b)/2 + atan(b/a)*i. +``` Here are a few examples of fractals you can draw: - Mandelbrot: - ./monge "z=1" "z=z*z+c; Abs2(z)<4" +```sh +./monge "z=1" "z=z*z+c; Abs2(z)<4" +``` - Mandelbrot (return time variation): - ./monge "z=c" "z=z*z+c; Abs2(z-c)>0.0001" +```sh +./monge "z=c" "z=z*z+c; Abs2(z-c)>0.0001" +``` - Julia, for `c=0.31+i*0.5`: - ./monge "z=c; c=0.31+i*0.5" "z=z*z+c; Abs2(z)<4" +```sh +./monge "z=c; c=0.31+i*0.5" "z=z*z+c; Abs2(z)<4" +``` - Julia (return time variation), `for c=0.31+i*0.5`: - ./monge "z=c; c=0.31+i*0.5" "z=z*z+c; Abs2(z-c)>0.0001" +```sh +./monge "z=c; c=0.31+i*0.5" "z=z*z+c; Abs2(z-c)>0.0001" +``` - Newton, for `x^3-1`: - ./monge "z=c" "p=z; z=0.6666*z+0.3333/(z*z); Abs2(p-z) > 0.001" +```sh +./monge "z=c" "p=z; z=0.6666*z+0.3333/(z*z); Abs2(p-z) > 0.001" +``` - Newton-Mandelbrot: -``` +```sh ./monge "z=0" "p=z; z=z-(z*z*z + (c-1)*z - c)/(3*z*z+c-1); Abs2(p-z) > 0.001" ``` - Phoenix, Mandelbrot version: -``` +```sh ./monge "z=0; q=0" "t=z; z=z*z+Re(c)+Im(c)*q; q=t; Abs2(z)<4" ``` - Phoenix, Julia version for `c=0.56667-i*0.5`: -``` +```sh ./monge "z=c; c=0.56667-i*0.5; q=0" "t=z; z=z*z+Re(c)+Im(c)*q; q=t; Abs2(z)<4" ``` + ### Compilation and portability This program will only work on x86 (with an x87 FPU) or x86_64 machines, but it requires the SDL library. -Another system requirement is the `mmap()` function (as `#define`d at the +Another system requirement is the `mmap(2)` function (as `#define`d at the beginning of the program). If it is not available the macro `M(a)` will have to be replaced with a system dependent function that allocates readable, writable *AND* executable memory (it will not be possible to make this program run on @@ -186,17 +246,18 @@ changing the definitions of `W`, `H` and `I` at the beginning of the code. - Many SDL identifiers are hardcoded as number, this is safe up to ABI incompatibility. - Better optimization could be done treating known real numbers as just one - double, instead of adding a 0 imaginary part to treat them as complex + `double`, instead of adding a 0 imaginary part to treat them as complex numbers. - There should be some way to switch from Mandelbrot to Julia with chosen parameter. + ### Spoiler Sure, I don't want to deprive you of the pleasure of digging into the infernal mess created by my corrupted mind (writing this remark I noticed that I was ending sentences with ';' instead -that with '.', and I worried for my sanity), but just in case... +of with '.', and I worried for my sanity), but just in case... I used many obfuscation techniques, including a few ones that are different from the tricks used in most common IOCCC program diff --git a/2006/monge/monge.alt.c b/2006/monge/monge.alt.c new file mode 100644 index 000000000..a02351c8b --- /dev/null +++ b/2006/monge/monge.alt.c @@ -0,0 +1,79 @@ +#include +#include + +#include +#define M(a) mmap(0, a, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0) + +#ifndef W +#define W 400 +#elif W < 1 +#undef W +#define W 400 +#endif +#ifndef H +#define H 300 +#elif H < 1 +#undef H +#define H 300 +#endif +#ifndef I +#define I 128 +#elif I < 1 +#undef I +#define I 128 +#endif + +#define L char* +#define _ Sint32 +#define h(a,b) for(a=0; a7?J(Yv]#JJ), P(S++):o++ + :s(4); } s(_ n){ O o96?a(A),P(Z+i-97),a + (A),P (Z+*e++-71) :(p(index( e, 40)+1,1,t), i^82?i^73?i^65?i^69?i^76?1:J + (%YhY`%YmY}]YYB%YBXHYIXH$^A$YqYJ$Ys):J(%Y{YJ%Yj^IY@Y|\\iYIYp%Yh$^AY}$]Y\\J$^I) + : J(XHYIXH^AYn):J(]YYn) : J (]XYn),e= index( *t,41 )+ 1): p ( e , q+ 1, &e); A + = "&%YCXJYLXIYK\\J$^I$^k$^A"; (x -=3)<1?J(&]X]Y),1L <<31<0? J(Zi_`#JO):J(_i]X),x + ?J (#HH):J(#HC),J(#AD#IJPC) ,o-=4:--x?--x?--x?x-3?J(&%YA%YAXHYIXH^AYh$^q\\J$^IY`) + , a(A): 1:a(A):J(&$^j$^j):J(&$^B$^B); } O q==(x=*(*t=e++))/2); } main(_ r,L*U){ + X =V=(Z =(S=(K=M(Y*32))+Y)+ Y)+Y; J(h#AA#AA#AA#AA#FJ:+-*/); h(q,2){ A =E =Q=U[ q+1]; O * A=*A^B++ + [ ";<>+-*/" ]?*A:B,(B%=7)||(isspace(*E=*A)||++E,*A++)); E=V; O B=*Q){ if(Q[1]-61)p( + Q,1,&Q); else{ p(Q+2,1,&Q); h(j,2){ J(]#JJ); P(Z+B-71-j*26); o--; } } *Q&&Q++; } + } J(#PPJ#AP#IF); P (E -V+X +1); J(#IJPC); 0[u =X+7] =I; SDL_Init( 32 ); F= + SDL_SetVideoMode(W,H,8 ,0); A=F->pixels; B=F->pitch; O 1){ C^=3; h(j,H)h(i, + W )b C+2]=9; if(r=(k =SDL_GetMouseState(&x,&y))&5){ f=z/50; f=k&1 ?f:-f ; + c+=(x*T-T/R)*f; g += f*y*T-f; z*=f=1-f/z; v=1/f; h(j,H)h(i,W)h(q,4){ k= + x+(i- x)* f +q/2; l=y+(j-y)*f+q%2; if(k>=0&k=0&l