This work presents a code translation of Andy Sloane's fixed-point donut.c into Wolfram Language, utilizing the FunctionCompile feature for efficient computation. The project demonstrates how low-level C algorithms can be faithfully reproduced in a high-level symbolic environment. By combining Style and ListAnimate, the implementation enables smooth ASCII-based animation with customizable color effects.
In[]:=
Clear[RotateStep,IntDonutFrame];
Create a compiler environment to store the declarations of the functions:
In[]:=
env=CreateCompilerEnvironment[];
CORDIC + Newton step to keep precision for repeated computation:
In[]:=
decl1=FunctionDeclaration[RotateStep,Typed[{"PackedArray"::["MachineInteger",1],"MachineInteger","MachineInteger"}->"PackedArray"::["MachineInteger",1]]@Function[{arg1,mul,shift},Module[{xx=arg1[[1]],yy=arg1[[2]],tmp,star},tmp=xx;xx=xx-BitShiftRight[mul*yy,shift];yy=yy+BitShiftRight[mul*tmp,shift];star=BitShiftRight[3145728-xx*xx-yy*yy,11];xx=BitShiftRight[xx*star,10];yy=BitShiftRight[yy*star,10];{xx,yy}]]];
Declare the core function that handles rotation and ASCII rendering:
In[]:=
decl2=FunctionDeclaration[IntDonutFrame,Typed[{"MachineInteger","MachineInteger","MachineInteger","MachineInteger"}->"ListVector"::["String"]]@Function[{cA,sA,cB,sB},Module[{w=80,h=22,chars={".",",","-","~",":",";","=","!","*","#","$","@"},b=CreateDataStructure["FixedArray"," ",1760],z=CreateDataStructure["FixedArray",127,1760],sj=0,cj=1024,si=0,ci=0,R1=1,R2=2048,K2=5120*1024,x0,x1,x2,x3,x4,x5,x6,x7,x,y,Nl=1,o=0,zz},Do[si=0;ci=1024;Do[x0=R1*cj+R2;x1=BitShiftRight[ci*x0,10];x2=BitShiftRight[cA*sj,10];x3=BitShiftRight[si*x0,10];x4=R1*x2-BitShiftRight[sA*x3,10];x5=BitShiftRight[sA*sj,10];x6=K2+R1*1024*x5+cA*x3;x7=BitShiftRight[cj*si,10];x=40+Quotient[30*(cB*x1-sB*x4),x6];y=12+Quotient[15*(cB*x4+sB*x1),x6];Nl=BitShiftRight[-cA*x7-cB*(BitShiftRight[-sA*x7,10]+x2)-ci*BitShiftRight[cj*sB,10],10];Nl=BitShiftRight[Nl-x5,7];o=x+80*y;zz=BitShiftRight[x6-K2,15];If[0<y<22&&0<x<80&&zz<z["Part",o+1],z["SetPart",o+1,zz];b["SetPart",o+1,chars[[If[Nl>0,Nl+1,1]]]]];{ci,si}=RotateStep[{ci,si},5,8];,{i,0,323,1}];{cj,sj}=RotateStep[{cj,sj},9,7];,{j,0,89,1}];b["Elements"]]]];
Put two declarations into one environment:
In[]:=
CompilerEnvironmentAppendTo[env,{decl1,decl2}]
Out[]=
CompilerEnvironmentObject
Compile the rotation function and core function:
In[]:=
cfRotateStep=FunctionCompile[Function[{Typed[arg1,"PackedArray"::["MachineInteger",1]],Typed[m,"MachineInteger"],Typed[s,"MachineInteger"]},RotateStep[arg1,m,s]],CompilerEnvironment->env];
In[]:=
Information@cfRotateStep
Out[]=
In[]:=
cfIntDonutFrame=FunctionCompile[Function[{Typed[cA,"MachineInteger"],Typed[sA,"MachineInteger"],Typed[cB,"MachineInteger"],Typed[sB,"MachineInteger"]},IntDonutFrame[cA,sA,cB,sB]],CompilerEnvironment->env];
The summary of the internal structure of the function:
In[]:=
Information@cfIntDonutFrame
Out[]=
Use the compiled function cfRotateStep to create a list with 600 sets of orientation for the 3-D donut:
In[]:=
configs=Join@@@Transpose@{NestList[cfRotateStep[#,5,7]&,{0,1024},600],NestList[cfRotateStep[#,5,7]&,{1024,0},600]};
Distribute the definitions of my functions onto subkernels:
In[]:=
Once[LaunchKernels[];DistributeDefinitions[cfRotateStep,cfIntDonutFrame]];
On my Mac air M2, it takes less than 2 seconds to generate all 600 frames on 8 parallel subkernels:
In[]:=
AbsoluteTiming[data=ParallelMap[StringJoin/@Partition[cfIntDonutFrame[Sequence@@#],80]&,configs];]
Out[]=
{1.02595,Null}
Customized the color scheme used in the example:
In[]:=
(*hbrw=RGBColor[107/256,218/256,70/256];tomatchcolorschemeinmactermimalhomebrewcolor*)clb=Blend[{White,RGBColor["#9B2A7F"],RGBColor["#748358"],RGBColor["#57C78B"],RGBColor["#E647AE"],White},#]&;
Run animation with other settings in Style function to adjust size. Highly recommend to run the code in the dark mode:
In[]:=
ListAnimate[Table[Style[Column[data[[i]],Spacings->0.2],Bold,FontFamily->"Courier",FontSize->12,clb[i/600](*hbrw*)],{i,600}],60,SaveDefinitions->True]
Out[]=
The compiled version is roughly 100 times faster than the uncompiled version.
CITE THIS NOTEBOOK
CITE THIS NOTEBOOK
Reconstructing the classic ASCII Donut in Wolfram language using FunctionCompile
by Shenghui Yang
Wolfram Community, STAFF PICKS, October 24, 2025
https://community.wolfram.com/groups/-/m/t/3564927
by Shenghui Yang
Wolfram Community, STAFF PICKS, October 24, 2025
https://community.wolfram.com/groups/-/m/t/3564927