import '../../../../../globals.js';
// Copyright 2023-2024, University of Colorado Boulder
/**
 * All of the needed logic for a raked workgroup scan (including the logic to load and store the data).
 *
 * @author Jonathan Olson <jonathan.olson@colorado.edu>
 */
import { alpenglow, coalescedLoopWGSL, commentWGSL, loadMultipleWGSL, scanRakedWGSL, wgsl } from '../../../imports.js';
import { optionize3 } from '../../../../../phet-core/js/optionize.js';
export const SCAN_COMPREHENSIVE_DEFAULTS = {
    exclusive: false,
    getAddedValue: null
};
const scanComprehensiveWGSL = (providedOptions) => {
    // TODO: how to specify that we don't fill in defaults for things like factorOutSubexpressions?
    const options = optionize3()({}, SCAN_COMPREHENSIVE_DEFAULTS, providedOptions);
    const input = options.input;
    const output = options.output;
    const scratch = options.scratch;
    const exclusive = options.exclusive;
    const getAddedValue = options.getAddedValue;
    const binaryOp = options.binaryOp;
    return wgsl `
    ${commentWGSL(`begin scan_comprehensive ${exclusive ? 'exclusive' : 'inclusive'}`)}

    // Load into workgroup memory
    ${loadMultipleWGSL({
        loadExpression: index => wgsl `${input}[ ${index} ]`,
        storeStatements: (index, value) => wgsl `${scratch}[ ${index} ] = ${value};`,
        workgroupSize: options.workgroupSize,
        grainSize: options.grainSize,
        type: binaryOp.type,
        lengthExpression: options.lengthExpression,
        globalIndex: options.globalIndex,
        workgroupIndex: options.workgroupIndex,
        localIndex: options.localIndex,
        outOfRangeValue: binaryOp.identityWGSL,
        inputOrder: options.inputOrder,
        inputAccessOrder: options.inputAccessOrder,
        factorOutSubexpressions: options.factorOutSubexpressions
    })}

    workgroupBarrier();
    
    ${scanRakedWGSL({
        // TODO: we're missing error checking here? Use optionize3?
        scratch: scratch,
        binaryOp: binaryOp,
        workgroupSize: options.workgroupSize,
        grainSize: options.grainSize,
        workgroupIndex: options.workgroupIndex,
        localIndex: options.localIndex,
        exclusive: false,
        getAddedValue: getAddedValue,
        addedValueNeedsWorkgroupBarrier: options.addedValueNeedsWorkgroupBarrier,
        storeReduction: options.storeReduction,
        stripeReducedOutput: options.stripeReducedOutput
    })}

    workgroupBarrier();

    // Write our output in a coalesced order.
    ${commentWGSL('begin (output write)')}
    ${coalescedLoopWGSL({
        workgroupSize: options.workgroupSize,
        grainSize: options.grainSize,
        lengthExpression: options.lengthExpression,
        workgroupIndex: options.workgroupIndex,
        localIndex: options.localIndex,
        callback: (localIndex, dataIndex) => wgsl `
        ${output}[ ${dataIndex} ] = ${exclusive ? wgsl `select( ${getAddedValue ? wgsl `workgroup_added_value` : binaryOp.identityWGSL}, ${scratch}[ ${localIndex} - 1u ], ${localIndex} > 0u )` : wgsl `${scratch}[ ${localIndex} ]`};
      `
    })}
    ${commentWGSL('end (output write)')}

    ${commentWGSL('end scan_comprehensive')}
  `;
};
export default scanComprehensiveWGSL;
alpenglow.register('scanComprehensiveWGSL', scanComprehensiveWGSL);
//# sourceMappingURL=scanComprehensiveWGSL.js.map