Plotting the Star of Bethlehem

Hint: $Z$ is the Jacobian for the transformation between $(x,y)$ and $(s,t)$ coordinates. No need to even define $Z$, no need to invert polynomials, no branch cuts.

f[x_, y_] = 1/10 (4 - x^2 - 2 y^2)^2 + 1/2 (x^2 + y^2);
r[x_, y_] = D[f[x, y], {{x, y}}];

With[{span = 2, step = 0.001, binsize = 1/100},
  DensityHistogram[
    Join @@ Table[r[x, y], {x, -span, span, step}, {y, -span, span, step}],
    {-1, 1, binsize},
    ColorFunction -> GrayLevel]]

enter image description here

Same idea but much faster (takes 1.9 seconds on my laptop):

With[{span = 1.72, step = 0.001, binsize = 1/100},
  ArrayPlot[
    Transpose@BinCounts[Transpose[
      r @@ Transpose[Tuples[Range[-span, span, step], 2]]], {-1,1,binsize}, {-1,1,binsize}],
    ColorFunction -> GrayLevel]]

where the number 1.72 is Root[-5-3#+2#^3&, 1], as gleaned from Reduce[Thread[-1 <= r[x,y] <= 1], {x,y}].

Addendum

This method works with the addendum question as well:

f = ListInterpolation[
      RandomReal[2, {9, 9}] + Outer[#1^2 + #2^2 &, Range[9], Range[9]]/2];
r[x_, y_] = D[f[x, y], {{x, y}}];

With[{step = 0.005, binsize = 1/10},
  ArrayPlot[Transpose@BinCounts[Transpose[
    r @@ Transpose[Tuples[Range[1, 9, step], 2]]],
    {0, 10, binsize}, {0, 10, binsize}],
  ColorFunction -> GrayLevel]]

enter image description here

I'll leave it to skillful experts to make prettier plots. Here I'm only addressing the question of plotting efficiency.


The noise in the picture given by OP seems to suggest random number has been used, so here's my trial:

data = RandomReal[{-2, 2}, {2, 4 10^5}];

s = 1000;
func = Function[{x, y}, Round@Rescale[r[x, y], {-1, 1}, {1, s}] -> 1/Abs@F[x, y], 
   Listable];

stFlst = func @@ data; // AbsoluteTiming
(* {5.87326, Null} *)

SetSystemOptions["SparseArrayOptions" -> {"TreatRepeatedEntries" -> 1}];

array = SparseArray[
    DeleteCases[stFlst, ({x_, y_} -> _) /; ! (1 < x < s && 1 < y < s)], {s, 
     s}]; // AbsoluteTiming
(* {0.655598, Null} *)

ArrayPlot[array // Transpose, PlotRange -> {0, 10}, 
 ColorFunction -> "AvocadoColors"]

enter image description here


The following is a fast smooth plot, based on the discussion here:

Clear[s, x, y]

sol = {x, y} /. Solve[r[x, y] == {s, t}, {x, y}];

symbolicroots = Cases[sol, a__Root, Infinity] // Union

coef = CoefficientList[symbolicroots[[1, 1, 1]], #]

{x, y} = sol[[1]] /. __Root -> ro

nroots[c_List] := Block[{a}, a = DiagonalMatrix[ConstantArray[1., Length@c - 2], 1];
   a[[-1]] = -Most@c/Last@c;
   Eigenvalues[a]];

check = Function @@ {If[Abs@Im@# < 10^-6, 1, 0] // PiecewiseExpand // 
    Simplify`PWToUnitStep}

eps = 10^-6; dt = 2 10^-3; 
 data = ParallelTable[
   Block[{ro = Pick[#, check@#, 1] &@nroots[coef]}, 
    1/F[x, y] // Abs // Total], {s, -1 + eps, 1 + eps, dt}, {t, -1 + eps, 1 + eps, 
    dt}]; // AbsoluteTiming
(* {34.7344, Null}, dual core laptop *)    

ArrayPlot[data // Transpose, ColorFunction -> "AvocadoColors", PlotRange -> {0, 30}]

enter image description here


Solution to Addendum

The method above for smooth plot no longer works well on the f in addendum, but the first method using random number still works. I've used InterpolationToPiecewise to transform the InterpolatingFunction to something compilable.

SeedRandom["star"]; 
dataf = RandomReal[2, {9, 9}] + Outer[#1^2 + #2^2 &, Range[9], Range[9]]/2;

InterpolationToPiecewise[if_, x_] := Module[{main, default, grid}, grid = if["Grid"];
   Piecewise[{if@"GetPolynomial"[#, x - #], x < First@#} & /@ grid[[2 ;; -2]], 
   if@"GetPolynomial"[#, x - #] &@grid[[-1]]]] /; if["InterpolationMethod"] == "Hermite"

poly[x_, y_] = 
  InterpolationToPiecewise[
   ListInterpolation[InterpolationToPiecewise[ListInterpolation[#], y] & /@ dataf], x];

compile = Compile[{x, y}, #, RuntimeAttributes -> {Listable}] &;
r = compile@D[poly[x, y], {{x, y}}];
absdivideF = 
  Abs@Divide[1, (D[#, x, x] D[#, y, y] - D[#, x, y]^2)] &@poly[x, y] // compile;

domain = {0, 10};
{datax, datay} = RandomReal[domain, {2, 10^6}];

s = 1000;
func = Function[{x, y}, 
  Clip[Round@Rescale[r[x, y], domain, {1, s}], {1, s}] -> absdivideF[x, y]];

stFlst = func[datax, datay]; // AbsoluteTiming
(* {2.93232, Null} *)

SetSystemOptions["SparseArrayOptions" -> {"TreatRepeatedEntries" -> 1}];
array = SparseArray[stFlst, {s, s}];
ArrayPlot[array // Transpose, PlotRange -> {0, 2}, ColorFunction -> "AvocadoColors"]

enter image description here

Remark

If you have a C compiler installed, consider using the following definition of compile:

compile = Last@
    Compile[{{xlst, _Real, 1}, {ylst, _Real, 1}}, 
     Block[{x, y}, Table[x = xlst[[i]]; y = ylst[[i]]; #, {i, Length@xlst}]], 
     CompilationTarget -> "C", RuntimeOptions -> "Speed"] &;

It will vastly speed up the generation of stFlst, at the expense of long compilation time of r and absdivideF.


A compiled version of @Roman's idea (binning code adapted from this answer):

starCompiled = 
 Compile[{{xyspan, _Real}, {delta, _Real}, {binspan, _Real}, \
{binsize, _Real}}, 
  Block[{bins, dimx, dimy, x, y, tx, ty}, 
   bins = Table[
     0, {Floor[binspan 2/binsize] + 1}, {Floor[binspan 2/binsize] + 
       1}];
   {dimx, dimy} = Dimensions[bins];
   Do[{x, y} = {xx - 2/5 xx (4 - xx^2 - 2 yy^2), 
      yy - 4/5 yy (4 - xx^2 - 2 yy^2)};
    tx = Floor[(x + binspan)/binsize] + 1;
    ty = Floor[(y + binspan)/binsize] + 1;
    If[tx >= 1 && tx <= dimx && ty >= 1 && ty <= dimy, 
     bins[[tx, ty]] += 1], {xx, -xyspan, xyspan, delta}, {yy, -xyspan,
      xyspan, delta}];
   bins], CompilationTarget -> "C", RuntimeOptions -> "Speed"]

I seem to get a ~3.5x speedup on my machine, with this relatively sharp image taking ~1.5 seconds:

ArrayPlot[starCompiled[1.72,0.0005,1.,0.005]^\[Transpose],Frame->False,ColorFunction->"AvocadoColors"]

enter image description here

Addendum

For completeness, here's a compiled version of the binning along idea on the addendum. Credit for the compiled interpolating function goes to @xzczd and reference therein.

dataf = RandomReal[2, {9, 9}] + 
   Outer[#1^2 + #2^2 &, Range[9], Range[9]]/2;
InterpolationToPiecewise[if_, x_] := 
 Module[{main, default, grid}, grid = if["Grid"];
   Piecewise[{if@"GetPolynomial"[#, x - #], x < First@#} & /@ 
     grid[[2 ;; -2]], if@"GetPolynomial"[#, x - #] &@grid[[-1]]]] /; 
  if["InterpolationMethod"] == "Hermite"
poly[x_, y_] = 
  InterpolationToPiecewise[
   ListInterpolation[
    InterpolationToPiecewise[ListInterpolation[#], y] & /@ dataf], 
   x];
compile = 
  Compile[{x, y}, #, RuntimeAttributes -> {Listable}, 
    CompilationTarget -> "C", RuntimeOptions -> "Speed"] &;
r = compile@D[poly[x, y], {{x, y}}];
addendumCompiled = 
 Compile[{{xmin, _Real}, {xmax, _Real}, {ymin, _Real}, {ymax, _Real}, \
{delta, _Real}, {binsize, _Real}}, 
  Block[{bins, dimx, dimy, x, y, tx, ty}, 
   bins = Table[
     0, {Floor[(xmax - xmin)/binsize] + 
       1}, {Floor[(ymax - ymin)/binsize] + 1}];
   {dimx, dimy} = Dimensions[bins];
   Do[{x, y} = r[xx, yy];
    tx = Floor[(x - xmin)/binsize] + 1;
    ty = Floor[(y - ymin)/binsize] + 1;
    If[tx >= 1 && tx <= dimx && ty >= 1 && ty <= dimy, 
     bins[[tx, ty]] += 1], {xx, xmin, xmax, delta}, {yy, ymin, ymax, 
     delta}];
   bins], CompilationTarget -> "C", RuntimeOptions -> "Speed", 
  CompilationOptions -> {"InlineExternalDefinitions" -> True}]

Seems to be relatively fast (and CompilePrint confirms no calls to MainEvaluator):

AbsoluteTiming[bins = addendumCompiled[1, 9, 1, 9, 0.0005, 0.005];]
Image@Rescale@Log[bins + 1]

enter image description here

PS

Potentially (un)related (any politics aside), here's the same idea on a complex strange attractor given by the equation (from the book Symmetry in Chaos: A Search for Pattern in Mathematics, Art and Nature): $$ F(z) = \left(\lambda + \alpha z z^* + \beta \Re(z^n) + \delta \Re\left[\left(\frac{z}{|z|}\right)^{np}\right]|z|\right)z + \gamma z^{*n-1} $$

attractorNonLinear = 
 Compile[{{xmin, _Real}, {xmax, _Real}, {ymin, _Real}, {ymax, _Real}, \
{delta, _Real}, {itmax, _Integer}, {n, _Integer}, {lambda, _Real}, \
{a, _Real}, {b, _Real}, {c, _Real}, {d, _Real}, {p, _Integer}}, 
  Block[{bins, dim, x, y, tx, ty, z, b1, radii, normed, coordinates},
   bins = 
    Table[0, {Floor[(xmax - xmin)/delta] + 
       1}, {Floor[(ymax - ymin)/delta] + 1}];
   dim = Dimensions[bins];
   z = -0.3 + 0.2 I;
   Do[z = (lambda + a z Conjugate[z] + b Re[z^n] + 
         d Re[(z/Abs[z])^n p] Abs[z]) z + c Conjugate[z]^(n - 1);
    {x, y} = {Re[z], Im[z]};
    tx = Floor[(x - xmin)/delta] + 1;
    ty = Floor[(y - ymin)/delta] + 1;
    If[tx >= 1 && tx <= dim[[1]] && ty >= 1 && ty <= dim[[2]], 
     bins[[tx, ty]] += 1], {i, 1, itmax}];
   bins], CompilationTarget :> "C", RuntimeOptions -> "Speed"]

which gives the Star of David with the following parameter values:

AbsoluteTiming[bins=N[attractorNonLinear[-1.6,1.6,-1.6,1.6,0.001,5 10^7,6,-2.42,1.0,-0.04,0.14,0.088,0]];]
ArrayPlot[Log[bins+1],ColorFunction->"AvocadoColors",Frame->False]

enter image description here