Skip to content

Commit

Permalink
Merge pull request #339 from Strilanc/dev
Browse files Browse the repository at this point in the history
Final preparations for April release
  • Loading branch information
Strilanc authored Apr 30, 2017
2 parents a76c1cb + 777b3c2 commit 275c656
Show file tree
Hide file tree
Showing 31 changed files with 429 additions and 260 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"title": "Quirk",
"description": "A drag-and-drop toy for exploring and understanding small quantum circuits.",
"license": "Apache-2.0",
"version": "1.9.1",
"version": "2.0.0",
"homepage": "https://github.com/Strilanc/Quirk",
"bugs": {
"url": "https://github.com/Strilanc/Quirk/issues"
Expand Down
14 changes: 6 additions & 8 deletions src/base/Util.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,37 +104,35 @@ class Util {

/**
* @param {!int} n
* @returns {!int}
* @returns {!int} A value p such that 2**(p-1) < n <= 2**p.
*/
static ceilLg2(n) {
if (n <= 1) {
return 0;
}
let p = Math.ceil(Math.log2(n));
let v = 1 << p;
if (v < n) {
if (1<<p < n) {
return p + 1;
}
if (v >= n*2) {
if (n <= 1<<(p-1)) {
return p - 1;
}
return p;
}

/**
* @param {!int} n
* @returns {!int}
* @returns {!int} A value p such that 2**p <= n < 2**(p+1).
*/
static floorLg2(n) {
if (n <= 1) {
return 0;
}
let p = Math.floor(Math.log2(n));
let v = 1 << p;
if (v*2 < n) {
if (1<<(p+1) <= n) {
return p + 1;
}
if (v > n) {
if (n < 1<<p) {
return p - 1;
}
return p;
Expand Down
6 changes: 4 additions & 2 deletions src/browser/Polyfills.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,9 @@ if (GL !== undefined && GL.INVALID_ENUM === undefined) {
'VERTEX_SHADER'
];
let gl = document.createElement('canvas').getContext('webgl');
for (let key of keys) {
GL[key] = GL[key] || gl[key];
if (gl !== null && gl !== undefined) {
for (let key of keys) {
GL[key] = GL[key] || gl[key];
}
}
}
2 changes: 1 addition & 1 deletion src/circuit/CircuitDefinition.js
Original file line number Diff line number Diff line change
Expand Up @@ -975,7 +975,7 @@ class CircuitDefinition {
];

// Input->Output gate connections.
for (let letter of ["A", "B"]) {
for (let letter of Gates.InputGates.Letters) {
let key = `Input Range ${letter}`;
let altInKey = `Input Default ${letter}`;
let altOutKey = `Input NO_DEFAULT Range ${letter}`;
Expand Down
13 changes: 8 additions & 5 deletions src/gates/AllGates.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ import {HalfTurnGates} from "src/gates/HalfTurnGates.js"
import {InputGates} from "src/gates/InputGates.js"
import {InterleaveBitsGates} from "src/gates/InterleaveBitsGates.js"
import {MeasurementGate} from "src/gates/MeasurementGate.js"
import {ModularArithmeticGates} from "src/gates/ModularArithmeticGates.js"
import {ModularIncrementGates} from "src/gates/ModularIncrementGates.js"
import {ModularAdditionGates} from "src/gates/ModularAdditionGates.js"
import {ModularMultiplicationGates} from "src/gates/ModularMultiplicationGates.js"
import {MultiplicationGates} from "src/gates/MultiplicationGates.js"
import {MultiplyAccumulateGates} from "src/gates/MultiplyAccumulateGates.js"
Expand Down Expand Up @@ -72,7 +73,8 @@ Gates.FourierTransformGates = FourierTransformGates;
Gates.HalfTurns = HalfTurnGates;
Gates.InputGates = InputGates;
Gates.InterleaveBitsGates = InterleaveBitsGates;
Gates.ModularArithmeticGates = ModularArithmeticGates;
Gates.ModularIncrementGates = ModularIncrementGates;
Gates.ModularAdditionGates = ModularAdditionGates;
Gates.ModularMultiplicationGates = ModularMultiplicationGates;
Gates.MultiplicationGates = MultiplicationGates;
Gates.MultiplyAccumulateGates = MultiplyAccumulateGates;
Expand Down Expand Up @@ -118,7 +120,8 @@ Gates.KnownToSerializer = [
...FourierTransformGates.all,
...HalfTurnGates.all,
...InterleaveBitsGates.all,
...ModularArithmeticGates.all,
...ModularAdditionGates.all,
...ModularIncrementGates.all,
...ModularMultiplicationGates.all,
...MultiplicationGates.all,
...MultiplyAccumulateGates.all,
Expand Down Expand Up @@ -282,8 +285,8 @@ Gates.BottomToolboxGroups = [
{
hint: "Modular",
gates: [
ModularArithmeticGates.IncrementModRFamily.ofSize(2), ModularArithmeticGates.DecrementModRFamily.ofSize(2),
ModularArithmeticGates.PlusAModRFamily.ofSize(2), ModularArithmeticGates.MinusAModRFamily.ofSize(2),
ModularIncrementGates.IncrementModRFamily.ofSize(2), ModularIncrementGates.DecrementModRFamily.ofSize(2),
ModularAdditionGates.PlusAModRFamily.ofSize(2), ModularAdditionGates.MinusAModRFamily.ofSize(2),
ModularMultiplicationGates.TimesAModRFamily.ofSize(2),
ModularMultiplicationGates.TimesAModRInverseFamily.ofSize(2),
ModularMultiplicationGates.TimesBToTheAModRFamily.ofSize(2),
Expand Down
2 changes: 1 addition & 1 deletion src/gates/ArithmeticGates.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ ArithmeticGates.IncrementFamily = Gate.buildFamily(1, 16, (span, builder) => bui

ArithmeticGates.DecrementFamily = Gate.buildFamily(1, 16, (span, builder) => builder.
setSerializedId("dec" + span).
setSymbol("-1").
setSymbol("1").
setTitle("Decrement Gate").
setBlurb("Subtracts 1 from the little-endian number represented by a block of qubits.").
setActualEffectToShaderProvider(ctx => offsetShader.withArgs(
Expand Down
3 changes: 2 additions & 1 deletion src/gates/InputGates.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ let makeSetInputGate = key => new GateBuilder().
return oldGate;
}

let val = Number.parseInt(txt);
let val = parseInt(txt);
if (!Number.isInteger(val) || val < 0 || val >= 1<<16) {
alert(`'${txt}' isn't an integer between 0 and 65535. Keeping ${oldGate.param}.`);
return oldGate;
Expand All @@ -109,6 +109,7 @@ InputGates.InputRevBFamily = makeInputGate('B', true);
InputGates.SetA = makeSetInputGate('A');
InputGates.SetB = makeSetInputGate('B');
InputGates.SetR = makeSetInputGate('R');
InputGates.Letters = ["A", "B", "R"];

InputGates.all = [
...InputGates.InputAFamily.all,
Expand Down
63 changes: 63 additions & 0 deletions src/gates/ModularAdditionGates.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
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"
import {modulusTooBigChecker} from "src/gates/ModularIncrementGates.js"

let ModularAdditionGates = {};

const MODULAR_ADDITION_SHADER = ketShaderPermute(
`
uniform float factor;
${ketInputGateShaderCode('A')}
${ketInputGateShaderCode('R')}
`,
`
float r = read_input_R();
if (out_id >= r) {
return out_id;
}
float d = read_input_A();
d *= factor;
d = mod(d, r);
float result = mod(out_id + r - d, r);
// Despite sanity, I consistently get result=33 instead of result=0 when out_id=0, d=0, r=33.
// HACK: Fix it by hand.
if (result >= r) {
result -= r;
}
return result;
`);

ModularAdditionGates.PlusAModRFamily = Gate.buildFamily(1, 16, (span, builder) => builder.
setSerializedId("+AmodR" + span).
setSymbol("+A\nmod R").
setTitle("Modular Addition Gate").
setBlurb("Adds input A into the target, mod input R.\nOnly affects values below R.").
setRequiredContextKeys("Input Range A", "Input Range R").
setExtraDisableReasonFinder(modulusTooBigChecker("R", span)).
setActualEffectToShaderProvider(ctx => MODULAR_ADDITION_SHADER.withArgs(
...ketArgs(ctx, span, ['A', 'R']),
WglArg.float("factor", +1))).
setKnownEffectToParametrizedPermutation((t, a, b) => t < b ? (t + a) % b : t));

ModularAdditionGates.MinusAModRFamily = Gate.buildFamily(1, 16, (span, builder) => builder.
setSerializedId("-AmodR" + span).
setSymbol("−A\nmod R").
setTitle("Modular Subtraction Gate").
setBlurb("Subtracts input A out of the target, mod input R.\nOnly affects values below R.").
setRequiredContextKeys("Input Range A", "Input Range R").
setExtraDisableReasonFinder(modulusTooBigChecker("R", span)).
setActualEffectToShaderProvider(ctx => MODULAR_ADDITION_SHADER.withArgs(
...ketArgs(ctx, span, ['A', 'R']),
WglArg.float("factor", -1))).
setKnownEffectToParametrizedPermutation((t, a, b) => t < b ? Util.properMod(t - a, b) : t));

ModularAdditionGates.all = [
...ModularAdditionGates.PlusAModRFamily.all,
...ModularAdditionGates.MinusAModRFamily.all,
];

export {ModularAdditionGates}
110 changes: 0 additions & 110 deletions src/gates/ModularArithmeticGates.js

This file was deleted.

68 changes: 68 additions & 0 deletions src/gates/ModularIncrementGates.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
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 ModularIncrementGates = {};

/**
* @param {!string} inputKey
* @param {!int} span
* @returns {!function(!GateCheckArgs) : (undefined|!string)}
*/
let modulusTooBigChecker = (inputKey, span) => args => {
let r = args.context.get('Input Range ' + inputKey);
let d = args.context.get('Input Default ' + inputKey);
if (r !== undefined && r.length > span) {
return "mod\ntoo\nbig";
}
if (r === undefined && d !== undefined && d > 1<<span) {
return "mod\ntoo\nbig";
}
return undefined;
};

const MODULAR_INCREMENT_SHADER = ketShaderPermute(
`
uniform float amount;
${ketInputGateShaderCode('R')}
`,
`
float r = read_input_R();
return out_id >= r
? out_id
// HACK: sometimes mod(value-equal-to-r, r) returns r instead of 0. The perturbation works around it.
: floor(mod(out_id + r - amount, r - 0.000001));`);

ModularIncrementGates.IncrementModRFamily = Gate.buildFamily(1, 16, (span, builder) => builder.
setSerializedId("incmodR" + span).
setSymbol("+1\nmod R").
setTitle("Modular Increment Gate").
setBlurb("Adds 1 into the target, but wraps R-1 to 0.\n" +
"Only affects values less than R.").
setRequiredContextKeys("Input Range R").
setExtraDisableReasonFinder(modulusTooBigChecker("R", span)).
setActualEffectToShaderProvider(ctx => MODULAR_INCREMENT_SHADER.withArgs(
...ketArgs(ctx, span, ['R']),
WglArg.float("amount", +1))).
setKnownEffectToParametrizedPermutation((t, a) => t < a ? (t + 1) % a : t));

ModularIncrementGates.DecrementModRFamily = Gate.buildFamily(1, 16, (span, builder) => builder.
setSerializedId("decmodR" + span).
setSymbol("−1\nmod R").
setTitle("Modular Decrement Gate").
setBlurb("Subtracts 1 out of the target, but wraps 0 to R-1.\n" +
"Only affects values less than R.").
setRequiredContextKeys("Input Range R").
setExtraDisableReasonFinder(modulusTooBigChecker("R", span)).
setActualEffectToShaderProvider(ctx => MODULAR_INCREMENT_SHADER.withArgs(
...ketArgs(ctx, span, ['R']),
WglArg.float("amount", -1))).
setKnownEffectToParametrizedPermutation((t, a) => t < a ? Util.properMod(t - 1, a) : t));

ModularIncrementGates.all = [
...ModularIncrementGates.IncrementModRFamily.all,
...ModularIncrementGates.DecrementModRFamily.all,
];

export {ModularIncrementGates, modulusTooBigChecker}
Loading

0 comments on commit 275c656

Please sign in to comment.