public static DataD blockDivide(final FunctionTypes.ZeroInBlockD3 func, BlockD3 block, PlotData data) {
    final int width = data.resolution.width;
    final int height = data.resolution.height;
    final double max = data.max;
    final double error = data.error;
    
    final DataD.Builder3 mat = new DataD.Builder3(width, height, 1);
    Tester tester = new Tester() {
      private void split(BlockD3 block) {
        int xSplit = block.width / 2;
        int ySplit = block.height / 2;
        test(block.split(block.x,          block.y,          xSplit,               ySplit));
        test(block.split(block.x + xSplit, block.y,          block.width - xSplit, ySplit));
        test(block.split(block.x,          block.y + ySplit, xSplit,               ySplit));
        test(block.split(block.x + xSplit, block.y + ySplit, block.width - xSplit, block.height - ySplit));
      }
      int evals = 0;
      public void test(BlockD3 block) {
        if(block.width == 0 || block.height == 0) {
          return;
        }
        int count = 0;
        while(true) {
          if(block.z1 >= max) {
            return;
          }
          evals++;
          if(func.maybeHasZeroIn(block)) {
            if(block.width == 1 && block.height == 1) {
              if(block.depth() <= error) {
                mat.put(block.x, block.y, 0, (block.z0 + block.z1) / 2);
                
                break;
              } else {
                block.half();
              }
            } else if(count < 2) {
              count++;
              block.half();
            } else {
              split(block);
              break;
            }
          } else {
            block.next();
          }
        }
      }
      public void print() {
        System.out.println("evals: " + evals);
      }
    };
    tester.test(block);
    tester.print();
    return mat.build();
  }