setActualEffectToShaderProvider(ctx => MODULAR_MULTIPLY_ACCUMULATE_SHADER.withArgs(
     ...ketArgs(ctx, span, ['A', 'B', 'R']),
     WglArg.float("factor", -1))).
 setActualEffectToShaderProvider(ctx => X_TO_A_SHADER.withArgs(
     ...ketArgs(ctx, 1, ['A']),
     WglArg.float('factor', -Math.PI))).
let ModularMultiplyAccumulateGates = {};

const MODULAR_MULTIPLY_ACCUMULATE_SHADER = ketShaderPermute(
    `
        uniform float factor;
        ${ketInputGateShaderCode('A')}
        ${ketInputGateShaderCode('B')}
        ${ketInputGateShaderCode('R')}
        ${BIG_MUL_MOD_SHADER_CODE}
    `,
    `
        float r = read_input_R();
        float a = read_input_A();
        float b = read_input_B();

        float d = big_mul_mod(factor * a, b, r);

        float in_id = floor(mod(out_id - d + 0.5, r));
        if (in_id < 0.0) {
            in_id += r;
        }
        if (in_id >= r) {
            in_id -= r;
        }

        return out_id >= r ? out_id : in_id;
    `);

ModularMultiplyAccumulateGates.PlusABModRFamily = Gate.buildFamily(1, 16, (span, builder) => builder.
    setSerializedId("+ABmodR" + span).
Example #4
0
CircuitShaders.swap = (ctx, otherRow) =>
    SWAP_QUBITS_SHADER.withArgs(...ketArgs(ctx, otherRow - ctx.row + 1));
    let v = args.getGateContext('Input Range A');
    let denom_exponent = v === undefined ? 'ⁿ' : Util.digits_to_superscript_digits('' + v.length);
    let symbol = args.gate.symbol.replace('ⁿ', denom_exponent);
    GatePainting.paintBackground(args);
    GatePainting.paintOutline(args);
    GatePainting.paintGateSymbol(args, symbol);
}

const X_TO_A_SHADER = ketShader(
    `
        uniform float factor;
        ${ketInputGateShaderCode('A')}
    `,
    `
        float angle = read_input_A() * factor / _gen_input_span_A;
        float c = cos(angle) * 0.5;
        float s = sin(angle) * 0.5;
        vec2 u = vec2(0.5 + c, s);
        vec2 v = vec2(0.5 - c, -s);
        // multiply state by the matrix [[u, v], [v, u]]
        vec2 amp2 = inp(1.0-out_id);
        return cmul(u, amp) + cmul(v, amp2);
    `);

const Y_TO_A_SHADER = ketShader(
    `
        uniform float factor;
        ${ketInputGateShaderCode('A')}
    `,
    `
        float angle = read_input_A() * factor / _gen_input_span_A;
 ctx => PHASE_GRADIENT_SHADER.withArgs(...ketArgs(ctx, 4), WglArg.float('factor', -Math.PI/16)),
Example #7
0
    vec2 outputFor(float k) {
        return read_input(scatter(k));
    }`);

/**
 * Renders the result of applying a controlled swap operation to a superposition.
 *
 * @param {!CircuitEvalContext} ctx
 * @param {!int} otherRow
 * @returns {!WglConfiguredShader}
 */
CircuitShaders.swap = (ctx, otherRow) =>
    SWAP_QUBITS_SHADER.withArgs(...ketArgs(ctx, otherRow - ctx.row + 1));
const SWAP_QUBITS_SHADER = ketShaderPermute('', `
    float low_bit = mod(out_id, 2.0);
    float mid_bits = floor(mod(out_id, span*0.5)*0.5);
    float high_bit = floor(out_id*2.0/span);
    return high_bit + mid_bits*2.0 + low_bit*span*0.5;`);

/**
 * Returns a configured shader that renders the marginal states of each qubit, for each possible values of the other
 * qubits (i.e. folding still needs to be done), into a destination texture. The marginal states are laid out in
 * [a,br,bi,d] order within each pixel and represent the density matrix {{a, b},{b*, d}}.
 * @param {!WglTexture} inputTexture A superposition texture.
 * @param {undefined|!int=} keptBitMask A bit mask with a 1 at the positions corresponding to indicates of the desired
 * qubit densities.
 * @returns {!WglConfiguredShader}
 */
CircuitShaders.qubitDensities = (inputTexture, keptBitMask = undefined) => {
    if (keptBitMask === undefined) {
        keptBitMask = (1 << currentShaderCoder().vec2.arrayPowerSizeOfTexture(inputTexture)) - 1;
Example #8
0
import {Config} from "src/Config.js"
import {Gate} from "src/circuit/Gate.js"
import {ketArgs, ketShaderPermute, ketInputGateShaderCode} from "src/circuit/KetShaderUtil.js"
import {Util} from "src/base/Util.js"
import {WglArg} from "src/webgl/WglArg.js"

let BitCountGates = {};

const POP_COUNT_SHADER = ketShaderPermute(
    `
        uniform float factor;
        ${ketInputGateShaderCode('A')}
    `,
    `
        float d = read_input_A();
        float popcnt = 0.0;
        for (int i = 0; i < ${Config.MAX_WIRE_COUNT}; i++) {
            popcnt += mod(d, 2.0);
            d = floor(d / 2.0);
        }
        float offset = mod(popcnt * factor, span);
        return mod(out_id + span - offset, span);`);

BitCountGates.PlusBitCountAFamily = Gate.buildFamily(1, 16, (span, builder) => builder.
    setSerializedIdAndSymbol("+cntA" + span).
    setSymbol("+1s(A)").
    setTitle("Bit Count Gate").
    setBlurb("Counts the number of ON bits in input A and adds that into this output.").
    setRequiredContextKeys("Input Range A").
    setActualEffectToShaderProvider(ctx => POP_COUNT_SHADER.withArgs(
        ...ketArgs(ctx, span, ['A']),
Example #9
0
 setActualEffectToShaderProvider(ctx => POP_COUNT_SHADER.withArgs(
     ...ketArgs(ctx, span, ['A']),
     WglArg.float("factor", -1))).
let universalNot = ctx => UNIVERSAL_NOT_SHADER.withArgs(...ketArgs(ctx));
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import {GateBuilder} from "src/circuit/Gate.js"
import {ketArgs, ketShader} from "src/circuit/KetShaderUtil.js"
import {WglConfiguredShader} from "src/webgl/WglConfiguredShader.js"

/**
 * @param {!CircuitEvalContext} ctx
 * @returns {!WglConfiguredShader}
 */
let universalNot = ctx => UNIVERSAL_NOT_SHADER.withArgs(...ketArgs(ctx));
const UNIVERSAL_NOT_SHADER = ketShader(
    '',
    'vec2 other = inp(1.0 - out_id); return vec2(other.x, -other.y) * (1.0 - 2.0 * out_id);',
    1);

let UniversalNotGate = new GateBuilder().
    setSerializedId("__unstable__UniversalNot").
    setSymbol("UniNot").
    setTitle("Universal Not Gate").
    setBlurb("Mirrors through the origin of the Bloch sphere.\nImpossible in practice.").
    setActualEffectToShaderProvider(universalNot).
    promiseEffectIsStable().
    gate;

export {universalNot, UniversalNotGate}
Example #12
0
            r = floor(mod(f + 0.5, ${1<<MUL_STEP}.0));
            f -= r;
            t = floor(mod(t + b*r + 0.5, modulus));
            b = floor(mod(b * ${1<<MUL_STEP}.0 + 0.5, modulus));
            f /= ${1<<MUL_STEP}.0;
        }
        return t;
    }
`;

const MULTIPLY_ACCUMULATE_SHADER = ketShaderPermute(
    `
        uniform float factor;
        ${ketInputGateShaderCode('A')}
        ${ketInputGateShaderCode('B')}
        ${BIG_MUL_MOD_SHADER_CODE}
    `,
    `
        float d1 = read_input_A();
        float d2 = read_input_B();
        float d = floor(mod(big_mul_mod(d1, d2, span)*factor + 0.5, span));
        return mod(out_id + span - d, span);`);

MultiplyAccumulateGates.Legacy_MultiplyAddFamily = Gate.buildFamily(3, 16, (span, builder) => builder.
    setSerializedId("c+=ab" + span).
    setSymbol("c+=ab").
    setTitle("Multiply-Add Gate").
    setBlurb("Adds the product of two numbers into a third.").
    setDrawer(GatePainting.SECTIONED_DRAWER_MAKER(
        ["a", "b", "c+=ab"],
        sectionSizes(span).slice(0, 2).map(e => e/span))).
    setActualEffectToUpdateFunc(ctx => {
Example #13
0
 setActualEffectToShaderProvider(ctx => ADDITION_SHADER.withArgs(
     ...ketArgs(ctx, span, ['A']),
     WglArg.float("factor", +1))).
Example #14
0
const chunkedScaledAdditionPermutationMaker = (span, factor) => e => {
    let sa = Math.floor(span/2);
    let sb = Math.ceil(span/2);
    let a = e & ((1 << sa) - 1);
    let b = e >> sa;
    b += a * factor;
    b &= ((1 << sb) - 1);
    return a + (b << sa);
};

const ADDITION_SHADER = ketShaderPermute(
    `
        uniform float factor;
        ${ketInputGateShaderCode('A')}
    `,
    `
        float d = read_input_A();
        d *= factor;
        d = mod(d, span);
        return mod(out_id + span - d, span);`);

ArithmeticGates.Legacy_AdditionFamily = Gate.buildFamily(2, 16, (span, builder) => builder.
    setSerializedId("add" + span).
    setSymbol("b+=a").
    setTitle("Addition Gate").
    setBlurb("Adds a little-endian number into another.").
    setDrawer(GatePainting.SECTIONED_DRAWER_MAKER(["a", "b+=a"], [Math.floor(span/2) / span])).
    setActualEffectToUpdateFunc(ctx =>
        ArithmeticGates.PlusAFamily.ofSize(Math.ceil(span/2)).customOperation(
            ctx.withRow(ctx.row + Math.floor(span/2)).
                withInputSetToRange('A', ctx.row, Math.floor(span/2)))).