<commit_before>package org.sunflow.core.renderer;

import org.sunflow.core.BucketOrder;
import org.sunflow.core.Display;
import org.sunflow.core.Filter;
import org.sunflow.core.ImageSampler;
import org.sunflow.core.Instance;
import org.sunflow.core.IntersectionState;
import org.sunflow.core.Options;
import org.sunflow.core.Scene;
import org.sunflow.core.Shader;
import org.sunflow.core.ShadingState;
import org.sunflow.core.bucket.BucketOrderFactory;
import org.sunflow.core.filter.BoxFilter;
import org.sunflow.core.filter.FilterFactory;
import org.sunflow.image.Bitmap;
import org.sunflow.image.Color;
import org.sunflow.math.MathUtils;
import org.sunflow.math.QMC;
import org.sunflow.system.Timer;
import org.sunflow.system.UI;
import org.sunflow.system.UI.Module;

public class BucketRenderer implements ImageSampler {
    private Scene scene;
    private Display display;
    // resolution
    private int imageWidth;
    private int imageHeight;
    // bucketing
    private String bucketOrderName;
    private BucketOrder bucketOrder;
    private int bucketSize;
    private int bucketCounter;
    private int[] bucketCoords;
    private boolean dumpBuckets;

    // anti-aliasing
    private int minAADepth;
    private int maxAADepth;
    private int superSampling;
    private float contrastThreshold;
    private boolean jitter;
    private boolean displayAA;

    // derived quantities
    private double invSuperSampling;
    private int subPixelSize;
    private int minStepSize;
    private int maxStepSize;
    private int[] sigma;
    private float thresh;
    private boolean useJitter;

    // filtering
    private String filterName;
    private Filter filter;
    private int fs;
    private float fhs;

    public BucketRenderer() {
        bucketSize = 32;
        bucketOrderName = "hilbert";
        displayAA = false;
        contrastThreshold = 0.1f;
        filterName = "box";
        jitter = false; // off by default
        dumpBuckets = false; // for debugging only - not user settable
    }

    public boolean prepare(Options options, Scene scene, int w, int h) {
        this.scene = scene;
        imageWidth = w;
        imageHeight = h;

        // fetch options
        bucketSize = options.getInt("bucket.size", bucketSize);
        bucketOrderName = options.getString("bucket.order", bucketOrderName);
        minAADepth = options.getInt("aa.min", minAADepth);
        maxAADepth = options.getInt("aa.max", maxAADepth);
        superSampling = options.getInt("aa.samples", superSampling);
        displayAA = options.getBoolean("aa.display", displayAA);
        jitter = options.getBoolean("aa.jitter", jitter);
        contrastThreshold = options.getFloat("aa.contrast", contrastThreshold);

        // limit bucket size and compute number of buckets in each direction
        bucketSize = MathUtils.clamp(bucketSize, 16, 512);
        int numBucketsX = (imageWidth + bucketSize - 1) / bucketSize;
        int numBucketsY = (imageHeight + bucketSize - 1) / bucketSize;
        bucketOrder = BucketOrderFactory.create(bucketOrderName);
        bucketCoords = bucketOrder.getBucketSequence(numBucketsX, numBucketsY);
        // validate AA options
        minAADepth = MathUtils.clamp(minAADepth, -4, 5);
        maxAADepth = MathUtils.clamp(maxAADepth, minAADepth, 5);
        superSampling = MathUtils.clamp(superSampling, 1, 256);
        invSuperSampling = 1.0 / superSampling;
        // compute AA stepping sizes
        subPixelSize = (maxAADepth > 0) ? (1 << maxAADepth) : 1;
        minStepSize = maxAADepth >= 0 ? 1 : 1 << (-maxAADepth);
        if (minAADepth == maxAADepth)
            maxStepSize = minStepSize;
        else
            maxStepSize = minAADepth > 0 ? 1 << minAADepth : subPixelSize << (-minAADepth);
        useJitter = jitter && maxAADepth > 0;
        // compute anti-aliasing contrast thresholds
        contrastThreshold = MathUtils.clamp(contrastThreshold, 0, 1);
        thresh = contrastThreshold * (float) Math.pow(2.0f, minAADepth);
        // read filter settings from scene
        filterName = options.getString("filter", filterName);
        filter = FilterFactory.get(filterName);
        // adjust filter
        if (filter == null) {
            UI.printWarning(Module.BCKT, "Unrecognized filter type: \"%s\" - defaulting to box", filterName);
            filter = new BoxFilter(1);
            filterName = "box";
        }
        fhs = filter.getSize() * 0.5f;
        fs = (int) Math.ceil(subPixelSize * (fhs - 0.5f));

        // prepare QMC sampling
        sigma = QMC.generateSigmaTable(subPixelSize << 7);
        UI.printInfo(Module.BCKT, "Bucket renderer settings:");
        UI.printInfo(Module.BCKT, "  * Resolution:         %dx%d", imageWidth, imageHeight);
        UI.printInfo(Module.BCKT, "  * Bucket size:        %d", bucketSize);
        UI.printInfo(Module.BCKT, "  * Number of buckets:  %dx%d", numBucketsX, numBucketsY);
        int pixelMinAA = (minAADepth) < 0 ? -(1 << (-minAADepth)) : (1 << minAADepth);
        int pixelMaxAA = (maxAADepth) < 0 ? -(1 << (-maxAADepth)) : (1 << maxAADepth);
        UI.printInfo(Module.BCKT, "  * Anti-aliasing:      [%dx%d] -> [%dx%d]", pixelMinAA, pixelMinAA, pixelMaxAA, pixelMaxAA);
        UI.printInfo(Module.BCKT, "  * Rays per sample:    %d", superSampling);
        UI.printInfo(Module.BCKT, "  * Subpixel jitter:    %s", useJitter ? "on" : (jitter ? "auto-off" : "off"));
        UI.printInfo(Module.BCKT, "  * Contrast threshold: %.2f", contrastThreshold);
        UI.printInfo(Module.BCKT, "  * Filter type:        %s", filterName);
        UI.printInfo(Module.BCKT, "  * Filter size:        %.2f pixels", filter.getSize());
        return true;
    }
<commit_msg>Clarified anti-aliasing sampling rate<commit_after>package org.sunflow.core.renderer;

import org.sunflow.core.BucketOrder;
import org.sunflow.core.Display;
import org.sunflow.core.Filter;
import org.sunflow.core.ImageSampler;
import org.sunflow.core.Instance;
import org.sunflow.core.IntersectionState;
import org.sunflow.core.Options;
import org.sunflow.core.Scene;
import org.sunflow.core.Shader;
import org.sunflow.core.ShadingState;
import org.sunflow.core.bucket.BucketOrderFactory;
import org.sunflow.core.filter.BoxFilter;
import org.sunflow.core.filter.FilterFactory;
import org.sunflow.image.Bitmap;
import org.sunflow.image.Color;
import org.sunflow.math.MathUtils;
import org.sunflow.math.QMC;
import org.sunflow.system.Timer;
import org.sunflow.system.UI;
import org.sunflow.system.UI.Module;

public class BucketRenderer implements ImageSampler {
    private Scene scene;
    private Display display;
    // resolution
    private int imageWidth;
    private int imageHeight;
    // bucketing
    private String bucketOrderName;
    private BucketOrder bucketOrder;
    private int bucketSize;
    private int bucketCounter;
    private int[] bucketCoords;
    private boolean dumpBuckets;

    // anti-aliasing
    private int minAADepth;
    private int maxAADepth;
    private int superSampling;
    private float contrastThreshold;
    private boolean jitter;
    private boolean displayAA;

    // derived quantities
    private double invSuperSampling;
    private int subPixelSize;
    private int minStepSize;
    private int maxStepSize;
    private int[] sigma;
    private float thresh;
    private boolean useJitter;

    // filtering
    private String filterName;
    private Filter filter;
    private int fs;
    private float fhs;

    public BucketRenderer() {
        bucketSize = 32;
        bucketOrderName = "hilbert";
        displayAA = false;
        contrastThreshold = 0.1f;
        filterName = "box";
        jitter = false; // off by default
        dumpBuckets = false; // for debugging only - not user settable
    }

    public boolean prepare(Options options, Scene scene, int w, int h) {
        this.scene = scene;
        imageWidth = w;
        imageHeight = h;

        // fetch options
        bucketSize = options.getInt("bucket.size", bucketSize);
        bucketOrderName = options.getString("bucket.order", bucketOrderName);
        minAADepth = options.getInt("aa.min", minAADepth);
        maxAADepth = options.getInt("aa.max", maxAADepth);
        superSampling = options.getInt("aa.samples", superSampling);
        displayAA = options.getBoolean("aa.display", displayAA);
        jitter = options.getBoolean("aa.jitter", jitter);
        contrastThreshold = options.getFloat("aa.contrast", contrastThreshold);

        // limit bucket size and compute number of buckets in each direction
        bucketSize = MathUtils.clamp(bucketSize, 16, 512);
        int numBucketsX = (imageWidth + bucketSize - 1) / bucketSize;
        int numBucketsY = (imageHeight + bucketSize - 1) / bucketSize;
        bucketOrder = BucketOrderFactory.create(bucketOrderName);
        bucketCoords = bucketOrder.getBucketSequence(numBucketsX, numBucketsY);
        // validate AA options
        minAADepth = MathUtils.clamp(minAADepth, -4, 5);
        maxAADepth = MathUtils.clamp(maxAADepth, minAADepth, 5);
        superSampling = MathUtils.clamp(superSampling, 1, 256);
        invSuperSampling = 1.0 / superSampling;
        // compute AA stepping sizes
        subPixelSize = (maxAADepth > 0) ? (1 << maxAADepth) : 1;
        minStepSize = maxAADepth >= 0 ? 1 : 1 << (-maxAADepth);
        if (minAADepth == maxAADepth)
            maxStepSize = minStepSize;
        else
            maxStepSize = minAADepth > 0 ? 1 << minAADepth : subPixelSize << (-minAADepth);
        useJitter = jitter && maxAADepth > 0;
        // compute anti-aliasing contrast thresholds
        contrastThreshold = MathUtils.clamp(contrastThreshold, 0, 1);
        thresh = contrastThreshold * (float) Math.pow(2.0f, minAADepth);
        // read filter settings from scene
        filterName = options.getString("filter", filterName);
        filter = FilterFactory.get(filterName);
        // adjust filter
        if (filter == null) {
            UI.printWarning(Module.BCKT, "Unrecognized filter type: \"%s\" - defaulting to box", filterName);
            filter = new BoxFilter(1);
            filterName = "box";
        }
        fhs = filter.getSize() * 0.5f;
        fs = (int) Math.ceil(subPixelSize * (fhs - 0.5f));

        // prepare QMC sampling
        sigma = QMC.generateSigmaTable(subPixelSize << 7);
        UI.printInfo(Module.BCKT, "Bucket renderer settings:");
        UI.printInfo(Module.BCKT, "  * Resolution:         %dx%d", imageWidth, imageHeight);
        UI.printInfo(Module.BCKT, "  * Bucket size:        %d", bucketSize);
        UI.printInfo(Module.BCKT, "  * Number of buckets:  %dx%d", numBucketsX, numBucketsY);
        if (minAADepth != maxAADepth)
            UI.printInfo(Module.BCKT, "  * Anti-aliasing:      %s -> %s (adaptive)", aaDepthToString(minAADepth), aaDepthToString(maxAADepth));
        else
            UI.printInfo(Module.BCKT, "  * Anti-aliasing:      %s (fixed)", aaDepthToString(minAADepth));
        UI.printInfo(Module.BCKT, "  * Rays per sample:    %d", superSampling);
        UI.printInfo(Module.BCKT, "  * Subpixel jitter:    %s", useJitter ? "on" : (jitter ? "auto-off" : "off"));
        UI.printInfo(Module.BCKT, "  * Contrast threshold: %.2f", contrastThreshold);
        UI.printInfo(Module.BCKT, "  * Filter type:        %s", filterName);
        UI.printInfo(Module.BCKT, "  * Filter size:        %.2f pixels", filter.getSize());
        return true;
    }

    private String aaDepthToString(int depth) {
        int pixelMinAA = (depth) < 0 ? -(1 << (-depth)) : (1 << depth);
        return String.format("%s%d sample%s", depth < 0 ? "1/" : "", pixelMinAA * pixelMinAA, depth == 0 ? "" : "s");
    }

{'fraction_non_alphanumeric': 0.11301749893299189, 'fraction_numerical': 0.00802390098164746, 'mean_word_length': 2.841311475409836, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7551798', 'n_tokens_mistral': 3701, 'n_tokens_neox': 3551, 'n_words': 854}