-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathATOR.commands.json
315 lines (315 loc) · 151 KB
/
ATOR.commands.json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
[
null,
{
"name": "whatis",
"permissions": "NONE",
"restriction": "0",
"_id": "UStvb",
"actions": [
{
"info": "1",
"infoIndex": "1",
"storage": "1",
"varName": "menuoption",
"name": "Store Command Params"
},
{
"behavior": "0",
"interpretation": "1",
"code": "function myWhatis(a, b) {\n msg.channel.send(\"\\\"\"+a[b][0] + \"\\\"\"+\"\\n\\nLearn more about \"+ \"\\\"\" +x+ \"\\\"\"+\"\\n====\\n\" + a[b][1]);\n}\n\nlet myArray = [ \n ['defn','link'],\n ['Do what thou wilt shall be the whole of the Law. Love is the law, love under will.','https://en.wikipedia.org/wiki/Thelema'],\n ['We place no reliance On virgin or pigeon; Our Method is Science, Our Aim is Religion.','https://en.wikipedia.org/wiki/The_Equinox'],\n ['These are the adorations to be performed by aspirants to the A.·. A.·.', 'http://www.thelemapedia.org/index.php/Liber_Resh']\n];\n\nvar menu = { \"help\":0, \"the law\":1, \"scientific illuminism\":2, \"liber resh\":3};\n\nvar x = tempVars(\"menuoption\").toLowerCase(); \n\nswitch(menu[x]) {\n case 0:\n break;\n case 1: /* The Law */\n myWhatis(myArray,menu[x]);\n break;\n case 2: /*scientific illuminism */\n myWhatis(myArray,menu[x]);\n break;\n\n case 3: /* liber Resh */\n myWhatis(myArray,menu[x]);\n break;\n default:\n}\n",
"storage": "1",
"varName": "myresult",
"name": "Run Script"
}
]
},
{
"name": "rule",
"permissions": "NONE",
"restriction": "1",
"_id": "uvXTv",
"actions": [
{
"info": "0",
"infoIndex": "1",
"storage": "1",
"varName": "ruleNum",
"name": "Store Command Params"
},
{
"behavior": "0",
"interpretation": "1",
"code": "const alive = '█';\nconst dead = ' ';\n \n// ------------------------------------------------------------[ Bit banging ]--\nconst setBitAt = (val, idx) => BigInt(val) | (1n << BigInt(idx));\nconst clearBitAt = (val, idx) => BigInt(val) & ~(1n << BigInt(idx));\nconst getBitAt = val => idx => (BigInt(val) >> BigInt(idx)) & 1n;\nconst hasBitAt = val => idx => ((BigInt(val) >> BigInt(idx)) & 1n) === 1n;\n \n// ----------------------------------------------------------------[ Utility ]--\nconst makeArr = n => Array(n).fill(0);\nconst reverse = x => Array.from(x).reduce((p, c) => [c, ...p], []);\nconst numToLine = width => int => {\n const test = hasBitAt(int);\n const looper = makeArr(width);\n return reverse(looper.map((_, i) => test(i) ? alive : dead)).join('');\n}\n \n// -------------------------------------------------------------------[ Main ]--\nconst displayCA = (rule, width, lines, startIndex) => {\n const result = [];\n result.push(`Rule:${rule} Width:${width} Gen:${lines}\\n`)\n const ruleTest = hasBitAt(rule);\n const lineLoop = makeArr(lines);\n const looper = makeArr(width);\n const pLine = numToLine(width);\n \n let nTarget = setBitAt(0n, startIndex);\n result.push(pLine(nTarget));\n lineLoop.forEach(() => {\n const bitTest = getBitAt(nTarget);\n looper.forEach((e, i) => {\n const l = bitTest(i === 0 ? width - 1 : i - 1);\n const m = bitTest(i);\n const r = bitTest(i === width - 1 ? 0 : i + 1);\n nTarget = ruleTest(\n parseInt([l, m, r].join(''), 2))\n ? setBitAt(nTarget, i)\n : clearBitAt(nTarget, i);\n });\n result.push(pLine(nTarget));\n });\n return result.join('\\n');\n}\n \nmsg.reply(\"```\"+displayCA(parseInt(tempVars(\"ruleNum\"),2), 57, 15, 28)+\"```\");",
"storage": "0",
"varName": "",
"name": "Run Script"
}
]
},
{
"name": "qc",
"permissions": "NONE",
"restriction": "1",
"_id": "bkaCa",
"actions": [
{
"info": "0",
"infoIndex": "1",
"storage": "1",
"varName": "option",
"name": "Store Command Params"
},
{
"info": "1",
"infoIndex": "2",
"storage": "1",
"varName": "input",
"name": "Store Command Params"
},
{
"behavior": "0",
"interpretation": "1",
"code": "\n\n// Copyright © 2019–2020, Stewart Smith. See LICENSE for details.\n\n\n\n\nconst Q = function(){\n\n\n\t// Did we send arguments of the form\n\t// ( bandwidth, timewidth )?\n\n\tif( arguments.length === 2 &&\n\t\tArray.from( arguments ).every( function( argument ){\n\n\t\treturn Q.isUsefulInteger( argument )\n\n\t})){\n\n\t\treturn new Q.Circuit( arguments[ 0 ], arguments[ 1 ])\n\t}\n\n\n\t// Otherwise assume we are creating a circuit\n\t// from a text block.\n\n\treturn Q.Circuit.fromText( arguments[ 0 ])\n}\n\n\n\n\nObject.assign( Q, {\n\n\tverbosity: 0.5,\t\n\tlog: function( verbosityThreshold, ...remainingArguments ){\n\n\t\tif( Q.verbosity >= verbosityThreshold ) console.log( ...remainingArguments )\n\t\treturn '(log)'\n\t},\n\twarn: function(){\n\n\t\tconsole.warn( ...arguments )\n\t\treturn '(warn)'\n\t},\n\terror: function(){\n\n\t\tconsole.error( ...arguments )\n\t\treturn '(error)'\n\t},\n\textractDocumentation: function( f ){\n\n\t\t`\n\t\tI wanted a way to document code\n\t\tthat was cleaner, more legible, and more elegant\n\t\tthan the bullshit we put up with today.\n\t\tAlso wanted it to print nicely in the console.\n\t\t`\n\n\t\tf = f.toString()\n\t\t\n\t\tconst \n\t\tbegin = f.indexOf( '`' ) + 1,\n\t\tend = f.indexOf( '`', begin ),\n\t\tlines = f.substring( begin, end ).split( '\\n' )\n\n\n\t\tfunction countPrefixTabs( text ){\n\t\t\n\n\t\t\t// Is counting tabs “manually” \n\t\t\t// actually more performant than regex?\n\n\t\t\tlet count = index = 0\n\t\t\twhile( text.charAt( index ++ ) === '\\t' ) count ++\n\t\t\treturn count\n\t\t}\n\n\n\t\t//------------------- TO DO!\n\t\t// we should check that there is ONLY whitespace between the function opening and the tick mark!\n\t\t// otherwise it’s not documentation.\n\t\t\n\t\tlet\n\t\ttabs = Number.MAX_SAFE_INTEGER\n\t\t\n\t\tlines.forEach( function( line ){\n\n\t\t\tif( line ){\n\t\t\t\t\n\t\t\t\tconst lineTabs = countPrefixTabs( line )\n\t\t\t\tif( tabs > lineTabs ) tabs = lineTabs\n\t\t\t}\n\t\t})\n\t\tlines.forEach( function( line, i ){\n\n\t\t\tif( line.trim() === '' ) line = '\\n\\n'\n\t\t\tlines[ i ] = line.substring( tabs ).replace( / {2}$/, '\\n' )\n\t\t})\n\t\treturn lines.join( '' )\n\t},\n\thelp: function( f ){\n\n\t\tif( f === undefined ) f = Q\n\t\treturn Q.extractDocumentation( f )\n\t},\n\tconstants: {},\n\tcreateConstant: function( key, value ){\n\n\t\t//Object.freeze( value )\n\t\tthis[ key ] = value\n\t\t// Object.defineProperty( this, key, {\n\n\t\t// \tvalue,\n\t\t// \twritable: false\n\t\t// })\n\t\t// Object.defineProperty( this.constants, key, {\n\n\t\t// \tvalue,\n\t\t// \twritable: false\n\t\t// })\n\t\tthis.constants[ key ] = this[ key ]\n\t\tObject.freeze( this[ key ])\n\t},\n\tcreateConstants: function(){\n\n\t\tif( arguments.length % 2 !== 0 ){\n\n\t\t\treturn Q.error( 'Q attempted to create constants with invalid (KEY, VALUE) pairs.' )\n\t\t}\n\t\tfor( let i = 0; i < arguments.length; i += 2 ){\n\n\t\t\tthis.createConstant( arguments[ i ], arguments[ i + 1 ])\n\t\t}\n\t},\n\n\n\n\n\tisUsefulNumber: function( n ){\n\n\t\treturn isNaN( n ) === false && \n\t\t\t( typeof n === 'number' || n instanceof Number ) &&\n\t\t\tn !== Infinity &&\n\t\t\tn !== -Infinity\n\t},\n\tisUsefulInteger: function( n ){\n\n\t\treturn Q.isUsefulNumber( n ) && Number.isInteger( n )\n\t},\n\tloop: function(){},\n\n\n\n\n\thypotenuse: function( x, y ){\n\t\t\n\t\tlet\n\t\ta = Math.abs( x ),\n\t\tb = Math.abs( y )\n\n\t\tif( a < 2048 && b < 2048 ){\n\t\t\t\n\t\t\treturn Math.sqrt( a * a + b * b )\n\t\t}\n\t\tif( a < b ){\n\t\t\n\t\t\ta = b\n\t\t\tb = x / y\n\t\t} \n\t\telse b = y / x\n\t\treturn a * Math.sqrt( 1 + b * b )\n\t},\n\tlogHypotenuse: function( x, y ){\n\n\t\tconst\n\t\ta = Math.abs( x ),\n\t\tb = Math.abs( y )\n\n\t\tif( x === 0 ) return Math.log( b )\n\t\tif( y === 0 ) return Math.log( a )\n\t\tif( a < 2048 && b < 2048 ){\n\t\t\n\t\t\treturn Math.log( x * x + y * y ) / 2\n\t\t}\n\t\treturn Math.log( x / Math.cos( Math.atan2( y, x )))\n\t},\n\thyperbolicSine: function( n ){\n\n\t\treturn ( Math.exp( n ) - Math.exp( -n )) / 2\n\t},\n\thyperbolicCosine: function( n ){\n\n\t\treturn ( Math.exp( n ) + Math.exp( -n )) / 2\n\t},\n\tround: function( n, d ){\n\n\t\tif( typeof d !== 'number' ) d = 0\n\t\tconst f = Math.pow( 10, d )\n\t\treturn Math.round( n * f ) / f\n\t},\n\ttoTitleCase: function( text ){\n\n\t\ttext = text.replace( /_/g, ' ' )\n\t\treturn text.toLowerCase().split( ' ' ).map( function( word ){\n\t\t\n\t\t\treturn word.replace( word[ 0 ], word[ 0 ].toUpperCase() )\n\t\t\n\t\t}).join(' ')\n\t},\n\tcenterText: function( text, length, filler ){\n\n\t\tif( length > text.length ){\n\t\t\t\n\t\t\tif( typeof filler !== 'string' ) filler = ' '\n\n\t\t\tconst \n\t\t\tpadLengthLeft = Math.floor(( length - text.length ) / 2 ),\n\t\t\tpadLengthRight = length - text.length - padLengthLeft\n\n\t\t\treturn text\n\t\t\t\t.padStart( padLengthLeft + text.length, filler )\n\t\t\t\t.padEnd( length, filler )\n\t\t}\n\t\telse return text\n\t},\n\n\n\n\n\n\n\n\n\tnamesIndex: 0,\n\tshuffledNames: [],\n\tshuffleNames$: function(){\n\n\t\tlet m = []\n\t\tfor( let c = 0; c < Q.COLORS.length; c ++ ){\n\n\t\t\tfor( let a = 0; a < Q.ANIMALS.length; a ++ ){\n\n\t\t\t\tm.push([ c, a, Math.random() ])\n\t\t\t}\n\t\t}\t\t\n\t\tQ.shuffledNames = m.sort( function( a, b ){\n\n\t\t\treturn a[ 2 ] - b[ 2 ]\n\t\t})\n\t},\n\tgetRandomName$: function(){\n\n\t\tif( Q.shuffledNames.length === 0 ) Q.shuffleNames$()\t\n\t\t\n\t\tconst \n\t\tpair = Q.shuffledNames[ Q.namesIndex ],\n\t\tname = Q.COLORS[ pair[ 0 ]] +' '+ Q.ANIMALS[ pair[ 1 ]]\n\t\t\n\t\tQ.namesIndex = ( Q.namesIndex + 1 ) % Q.shuffledNames.length\n\t\treturn name\n\t},\n\thueToColorName: function( hue ){\n\n\t\thue = hue % 360\n\t\thue = Math.floor( hue / 10 )\n\t\treturn Q.COLORS[ hue ]\n\t},\n\tcolorIndexToHue: function( i ){\n\n\t\treturn i * 10\n\t}\n\n\n\n\n})\n\n\n\n\nQ.createConstants( \n\n\t'REVISION', 19,\n\n\n\t// Yeah... F’ing floating point numbers, Man!\n\t// Here’s the issue:\n\t// var a = new Q.ComplexNumber( 1, 2 )\n\t// a.multiply(a).isEqualTo( a.power( new Q.ComplexNumber( 2, 0 )))\n\t// That’s only true if Q.EPSILON >= Number.EPSILON * 6\n\t\n\t'EPSILON', Number.EPSILON * 6,\n\n\t'RADIANS_TO_DEGREES', 180 / Math.PI,\n\n\t'ANIMALS', [ \n\n\t\t'Aardvark',\n\t\t'Albatross',\n\t\t'Alligator',\n\t\t'Alpaca',\n\t\t'Ant',\n\t\t'Anteater',\n\t\t'Antelope',\n\t\t'Ape',\n\t\t'Armadillo',\n\t\t'Baboon',\n\t\t'Badger',\n\t\t'Barracuda',\n\t\t'Bat',\n\t\t'Bear',\n\t\t'Beaver',\n\t\t'Bee',\n\t\t'Bison',\n\t\t'Boar',\n\t\t'Buffalo',\n\t\t'Butterfly',\n\t\t'Camel',\n\t\t'Caribou',\n\t\t'Cat',\n\t\t'Caterpillar',\n\t\t'Cattle',\n\t\t'Chamois',\n\t\t'Cheetah',\n\t\t'Chicken',\n\t\t'Chimpanzee',\n\t\t'Chinchilla',\n\t\t'Chough',\n\t\t'Clam',\n\t\t'Cobra',\n\t\t'Cod',\n\t\t'Cormorant',\n\t\t'Coyote',\n\t\t'Crab',\n\t\t'Crane',\n\t\t'Crocodile',\n\t\t'Crow',\n\t\t'Curlew',\n\t\t'Deer',\n\t\t'Dinosaur',\n\t\t'Dog',\n\t\t'Dogfish',\n\t\t'Dolphin',\n\t\t'Donkey',\n\t\t'Dotterel',\n\t\t'Dove',\n\t\t'Dragonfly',\n\t\t'Duck',\n\t\t'Dugong',\n\t\t'Dunlin',\n\t\t'Eagle',\n\t\t'Echidna',\n\t\t'Eel',\n\t\t'Eland',\n\t\t'Elephant',\n\t\t'Elephant seal',\n\t\t'Elk',\n\t\t'Emu',\n\t\t'Falcon',\n\t\t'Ferret',\n\t\t'Finch',\n\t\t'Fish',\n\t\t'Flamingo',\n\t\t'Fly',\n\t\t'Fox',\n\t\t'Frog',\n\t\t'Galago',\n\t\t'Gaur',\n\t\t'Gazelle',\n\t\t'Gerbil',\n\t\t'Giant Panda',\n\t\t'Giraffe',\n\t\t'Gnat',\n\t\t'Gnu',\n\t\t'Goat',\n\t\t'Goose',\n\t\t'Goldfinch',\n\t\t'Goldfish',\n\t\t'Gorilla',\n\t\t'Goshawk',\n\t\t'Grasshopper',\n\t\t'Grouse',\n\t\t'Guanaco',\n\t\t'Guinea fowl',\n\t\t'Guinea pig',\n\t\t'Gull',\n\t\t'Guppy',\n\t\t'Hamster',\n\t\t'Hare',\n\t\t'Hawk',\n\t\t'Hedgehog',\n\t\t'Hen',\n\t\t'Heron',\n\t\t'Herring',\n\t\t'Hippopotamus',\n\t\t'Hornet',\n\t\t'Horse',\n\t\t'Human',\n\t\t'Hummingbird',\n\t\t'Hyena',\n\t\t'Ide',\n\t\t'Jackal',\n\t\t'Jaguar',\n\t\t'Jay',\n\t\t'Jellyfish',\n\t\t'Kangaroo',\n\t\t'Koala',\n\t\t'Koi',\n\t\t'Komodo dragon',\n\t\t'Kouprey',\n\t\t'Kudu',\n\t\t'Lapwing',\n\t\t'Lark',\n\t\t'Lemur',\n\t\t'Leopard',\n\t\t'Lion',\n\t\t'Llama',\n\t\t'Lobster',\n\t\t'Locust',\n\t\t'Loris',\n\t\t'Louse',\n\t\t'Lyrebird',\n\t\t'Magpie',\n\t\t'Mallard',\n\t\t'Manatee',\n\t\t'Marten',\n\t\t'Meerkat',\n\t\t'Mink',\n\t\t'Mole',\n\t\t'Monkey',\n\t\t'Moose',\n\t\t'Mouse',\n\t\t'Mosquito',\n\t\t'Mule',\n\t\t'Narwhal',\n\t\t'Newt',\n\t\t'Nightingale',\n\t\t'Octopus',\n\t\t'Okapi',\n\t\t'Opossum',\n\t\t'Oryx',\n\t\t'Ostrich',\n\t\t'Otter',\n\t\t'Owl',\n\t\t'Ox',\n\t\t'Oyster',\n\t\t'Panther',\n\t\t'Parrot',\n\t\t'Partridge',\n\t\t'Peafowl',\n\t\t'Pelican',\n\t\t'Penguin',\n\t\t'Pheasant',\n\t\t'Pig',\n\t\t'Pigeon',\n\t\t'Pony',\n\t\t'Porcupine',\n\t\t'Porpoise',\n\t\t'Prairie Dog',\n\t\t'Quail',\n\t\t'Quelea',\n\t\t'Rabbit',\n\t\t'Raccoon',\n\t\t'Rail',\n\t\t'Ram',\n\t\t'Raven',\n\t\t'Reindeer',\n\t\t'Rhinoceros',\n\t\t'Rook',\n\t\t'Ruff',\n\t\t'Salamander',\n\t\t'Salmon',\n\t\t'Sand Dollar',\n\t\t'Sandpiper',\n\t\t'Sardine',\n\t\t'Scorpion',\n\t\t'Sea lion',\n\t\t'Sea Urchin',\n\t\t'Seahorse',\n\t\t'Seal',\n\t\t'Shark',\n\t\t'Sheep',\n\t\t'Shrew',\n\t\t'Shrimp',\n\t\t'Skunk',\n\t\t'Snail',\n\t\t'Snake',\n\t\t'Sow',\n\t\t'Spider',\n\t\t'Squid',\n\t\t'Squirrel',\n\t\t'Starling',\n\t\t'Stingray',\n\t\t'Stinkbug',\n\t\t'Stork',\n\t\t'Swallow',\n\t\t'Swan',\n\t\t'Tapir',\n\t\t'Tarsier',\n\t\t'Termite',\n\t\t'Tiger',\n\t\t'Toad',\n\t\t'Trout',\n\t\t'Tui',\n\t\t'Turkey',\n\t\t'Turtle',\n\t\t// U\n\t\t'Vicuña',\n\t\t'Viper',\n\t\t'Vulture',\n\t\t'Wallaby',\n\t\t'Walrus',\n\t\t'Wasp',\n\t\t'Water buffalo',\n\t\t'Weasel',\n\t\t'Whale',\n\t\t'Wolf',\n\t\t'Wolverine',\n\t\t'Wombat',\n\t\t'Woodcock',\n\t\t'Woodpecker',\n\t\t'Worm',\n\t\t'Wren',\n\t\t// X\n\t\t'Yak',\n\t\t'Zebra'\n\n\t],\n\t'ANIMALS3', [\n\n\t\t'ape',\n\t\t'bee',\n\t\t'cat',\n\t\t'dog',\n\t\t'elk',\n\t\t'fox',\n\t\t'gup',\n\t\t'hen',\n\t\t'ide',\n\t\t'jay',\n\t\t'koi',\n\t\t'leo',\n\t\t'moo',\n\t\t'nit',\n\t\t'owl',\n\t\t'pig',\n\t\t// Q ?\n\t\t'ram',\n\t\t'sow',\n\t\t'tui',\n\t\t// U ?\n\t\t// V ?\n\t\t// W ?\n\t\t// X ?\n\t\t'yak',\n\t\t'zeb'\n\t],\n\t'COLORS', [\n\n\t\t'Red', // 0 RED\n\t\t'Scarlet', // 10\n\t\t'Tawny', // 20\n\t\t'Carrot', // 30\n\t\t'Pumpkin', // 40\n\t\t'Mustard', // 50\n\t\t'Lemon', // 60 Yellow\n\t\t'Lime', // 70\n\t\t'Spring bud', // 80\n\t\t'Spring grass',// 90\n\t\t'Pear', // 100\n\t\t'Kelly', // 110\n\t\t'Green', // 120 GREEN\n\t\t'Malachite', // 130\n\t\t'Sea green', // 140\n\t\t'Sea foam', // 150\n\t\t'Aquamarine', // 160\n\t\t'Turquoise', // 170\n\t\t'Cyan', // 180 Cyan\n\t\t'Pacific blue',// 190\n\t\t'Baby blue', // 200\n\t\t'Ocean blue', // 210\n\t\t'Sapphire', // 220\n\t\t'Azure', // 230\n\t\t'Blue', // 240 BLUE\n\t\t'Cobalt', // 250\n\t\t'Indigo', // 260\n\t\t'Violet', // 270\n\t\t'Lavender', // 280\n\t\t'Purple', // 290\n\t\t'Magenta', // 300 Magenta\n\t\t'Hot pink', // 310\n\t\t'Fuschia', // 320\n\t\t'Ruby', // 330\n\t\t'Crimson', // 340\n\t\t'Carmine' // 350\n\t]\n)\n\n\n\n\nconsole.log( `\n\n\n QQQQQQ\nQQ QQ\nQQ QQ\nQQ QQ\nQQ QQ QQ\nQQ QQ \n QQQQ ${Q.REVISION} \n\n\n\nhttps://quantumjavascript.app\n\n\n\n` )\n\n// Copyright © 2019–2020, Stewart Smith. See LICENSE for details.\n\n\n\n\nQ.ComplexNumber = function( real, imaginary ){\n\n\t`\n\tThe set of “real numbers” (ℝ) contains any number that can be expressed \n\talong an infinite timeline. https://en.wikipedia.org/wiki/Real_number \n\n\t … -3 -2 -1 0 +1 +2 +3 … \n\t ┄───┴───┴───┴───┴───┴─┬─┴──┬┴┬──┄ \n\t √2 𝒆 π \n\n\n\tMeanwhile, “imaginary numbers” (𝕀) consist of a real (ℝ) multiplier and \n\tthe symbol 𝒊, which is the impossible solution to the equation 𝒙² = −1. \n\tNote that no number when multiplied by itself can ever result in a \n\tnegative product, but the concept of 𝒊 gives us a way to reason around \n\tthis imaginary scenario nonetheless. \n\thttps://en.wikipedia.org/wiki/Imaginary_number \n\n\t … -3𝒊 -2𝒊 -1𝒊 0𝒊 +1𝒊 +2𝒊 +3𝒊 … \n\t ┄───┴───┴───┴───┴───┴───┴───┴───┄ \n\n\n\tA “complex number“ (ℂ) is a number that can be expressed in the form \n\t𝒂 + 𝒃𝒊, where 𝒂 is the real component (ℝ) and 𝒃𝒊 is the imaginary \n\tcomponent (𝕀). https://en.wikipedia.org/wiki/Complex_number \n\n\n\tOperation functions on Q.ComplexNumber instances generally accept as \n\targuments both sibling instances and pure Number instances, though the \n\tvalue returned is always an instance of Q.ComplexNumber.\n\n\t`\n\n\tif( real instanceof Q.ComplexNumber ){\n\n\t\timaginary = real.imaginary\n\t\treal = real.real\n\t\tQ.warn( 'Q.ComplexNumber tried to create a new instance with an argument that is already a Q.ComplexNumber — and that’s weird!' )\n\t}\n\telse if( real === undefined ) real = 0\n\tif( imaginary === undefined ) imaginary = 0\n\tif(( Q.ComplexNumber.isNumberLike( real ) !== true && isNaN( real ) !== true ) || \n\t ( Q.ComplexNumber.isNumberLike( imaginary ) !== true && isNaN( imaginary ) !== true ))\n\t\treturn Q.error( 'Q.ComplexNumber attempted to create a new instance but the arguments provided were not actual numbers.' )\n\n\tthis.real = real\n\tthis.imaginary = imaginary\n\tthis.index = Q.ComplexNumber.index ++\n}\n\n\n\n\nObject.assign( Q.ComplexNumber, {\n\n\tindex: 0,\n\thelp: function(){ return Q.help( this )},\n\tconstants: {},\n\tcreateConstant: Q.createConstant,\n\tcreateConstants: Q.createConstants,\n\n\n\n\n\ttoText: function( rNumber, iNumber, roundToDecimal, padPositive ){\n\n\n\t\t// Should we round these numbers?\n\t\t// Our default is yes: to 3 digits.\n\t\t// Otherwise round to specified decimal.\n\n\t\tif( typeof roundToDecimal !== 'number' ) roundToDecimal = 3\n\t\tconst factor = Math.pow( 10, roundToDecimal )\n\t\trNumber = Math.round( rNumber * factor ) / factor\n\t\tiNumber = Math.round( iNumber * factor ) / factor\n\n\n\t\t// Convert padPositive \n\t\t// from a potential Boolean\n\t\t// to a String.\n\t\t// If we don’t receive a FALSE\n\t\t// then we’ll pad the positive numbers.\n\n\t\tpadPositive = padPositive === false ? '' : ' '\n\n\n\t\t// We need the absolute values of each.\n\n\t\tlet\n\t\trAbsolute = Math.abs( rNumber ),\n\t\tiAbsolute = Math.abs( iNumber )\n\n\n\t\t// And an absolute value string.\n\n\t\tlet\n\t\trText = rAbsolute.toString(),\n\t\tiText = iAbsolute.toString()\n\n\n\t\t// Is this an IMAGINARY-ONLY number?\n\t\t// Don’t worry: -0 === 0.\n\n\t\tif( rNumber === 0 ){\n\n\t\t\tif( iNumber === Infinity ) return padPositive +'∞i'\n\t\t\tif( iNumber === -Infinity ) return '-∞i'\n\t\t\tif( iNumber === 0 ) return padPositive +'0'\n\t\t\tif( iNumber === -1 ) return '-i'\n\t\t\tif( iNumber === 1 ) return padPositive +'i'\n\t\t\tif( iNumber >= 0 ) return padPositive + iText +'i'\n\t\t\tif( iNumber < 0 ) return '-'+ iText +'i'\n\t\t\treturn iText +'i'// NaN\n\t\t}\n\t\t\n\n\t\t// This number contains a real component\n\t\t// and may also contain an imaginary one as well.\n\n\t\tif( rNumber === Infinity ) rText = padPositive +'∞'\n\t\telse if( rNumber === -Infinity ) rText = '-∞'\n\t\telse if( rNumber >= 0 ) rText = padPositive + rText\n\t\telse if( rNumber < 0 ) rText = '-'+ rText\n\n\t\tif( iNumber === Infinity ) return rText +' + ∞i'\n\t\tif( iNumber === -Infinity ) return rText +' - ∞i'\n\t\tif( iNumber === 0 ) return rText\n\t\tif( iNumber === -1 ) return rText +' - i'\n\t\tif( iNumber === 1 ) return rText +' + i'\n\t\tif( iNumber > 0 ) return rText +' + '+ iText +'i'\n\t\tif( iNumber < 0 ) return rText +' - '+ iText +'i'\n\t\treturn rText +' + '+ iText +'i'// NaN\n\t},\n\n\n\n\n\tisNumberLike: function( n ){\n\n\t\treturn isNaN( n ) === false && ( typeof n === 'number' || n instanceof Number )\n\t},\n\tisNaN: function( n ){\n\t\t\n\t\treturn isNaN( n.real ) || isNaN( n.imaginary )\n\t},\n\tisZero: function( n ){\n\n\t\treturn ( n.real === 0 || n.real === -0 ) &&\n\t\t ( n.imaginary === 0 || n.imaginary === -0 )\n\t},\n\tisFinite: function( n ){\n\n\t\treturn isFinite( n.real ) && isFinite( n.imaginary )\n\t},\n\tisInfinite: function( n ){\n\t\n\t\treturn !( this.isNaN( n ) || this.isFinite( n ))\n\t},\n\tareEqual: function( a, b ){\n\n\t\treturn Q.ComplexNumber.operate(\n\n\t\t\t'areEqual', a, b,\n\t\t\tfunction( a, b ){\n\t\t\t\t\n\t\t\t\treturn Math.abs( a - b ) < Q.EPSILON\n\t\t\t},\n\t\t\tfunction( a, b ){\n\n\t\t\t\treturn (\n\n\t\t\t\t\tMath.abs( a - b.real ) < Q.EPSILON &&\n\t\t\t\t\tMath.abs( b.imaginary ) < Q.EPSILON\n\t\t\t\t)\n\t\t\t},\n\t\t\tfunction( a, b ){\n\n\t\t\t\treturn (\n\n\t\t\t\t\tMath.abs( a.real - b ) < Q.EPSILON &&\n\t\t\t\t\tMath.abs( a.imaginary ) < Q.EPSILON\n\t\t\t\t)\n\t\t\t},\n\t\t\tfunction( a, b ){\n\n\t\t\t\treturn ( \n\t\t\n\t\t\t\t\tMath.abs( a.real - b.real ) < Q.EPSILON &&\n\t\t\t\t\tMath.abs( a.imaginary - b.imaginary ) < Q.EPSILON\n\t\t\t\t)\n\t\t\t}\n\t\t)\n\t},\n\n\n\n\n\tabsolute: function( n ){\n\t\n\t\treturn Q.hypotenuse( n.real, n.imaginary )\n\t},\n\tconjugate: function( n ){\n\n\t\treturn new Q.ComplexNumber( n.real, n.imaginary * -1 )\n\t},\n\toperate: function( \n\t\t\n\t\tname,\n\t\ta,\n\t\tb,\n\t\tnumberAndNumber,\n\t\tnumberAndComplex,\n\t\tcomplexAndNumber,\n\t\tcomplexAndComplex ){\n\n\t\tif( Q.ComplexNumber.isNumberLike( a )){\n\n\t\t\tif( Q.ComplexNumber.isNumberLike( b )) return numberAndNumber( a, b )\n\t\t\telse if( b instanceof Q.ComplexNumber ) return numberAndComplex( a, b )\n\t\t\telse return Q.error( 'Q.ComplexNumber attempted to', name, 'with the number', a, 'and something that is neither a Number or Q.ComplexNumber:', b )\n\t\t}\n\t\telse if( a instanceof Q.ComplexNumber ){\n\n\t\t\tif( Q.ComplexNumber.isNumberLike( b )) return complexAndNumber( a, b )\n\t\t\telse if( b instanceof Q.ComplexNumber ) return complexAndComplex( a, b )\n\t\t\telse return Q.error( 'Q.ComplexNumber attempted to', name, 'with the complex number', a, 'and something that is neither a Number or Q.ComplexNumber:', b )\n\t\t}\n\t\telse return Q.error( 'Q.ComplexNumber attempted to', name, 'with something that is neither a Number or Q.ComplexNumber:', a )\n\t},\t\n\n\n\n\n\tsine: function( n ){\n\n\t\tconst\n\t\ta = n.real,\n\t\tb = n.imaginary\n\t\t\n\t\treturn new Q.ComplexNumber(\n\t\t\n\t\t\tMath.sin( a ) * Q.hyperbolicCosine( b ),\n\t\t\tMath.cos( a ) * Q.hyperbolicSine( b )\n\t\t)\n\t},\n\tcosine: function( n ){\n\n\t\tconst\n\t\ta = n.real,\n\t\tb = n.imaginary\n\t\t\n\t\treturn new Q.ComplexNumber(\n\t\t\n\t\t\t Math.cos( a ) * Q.hyperbolicCosine( b ),\n\t\t\t-Math.sin( a ) * Q.hyperbolicSine( b )\n\t\t)\n\t},\n arcCosine: function( n ){\n \t\n\t\tconst\n\t\ta = n.real,\n\t\tb = n.imaginary,\n\t\tt1 = Q.ComplexNumber.squareRoot( new Q.ComplexNumber(\n\n\t\t\tb * b - a * a + 1,\n\t\t\ta * b * -2\n\t\t\n\t\t)),\n\t\tt2 = Q.ComplexNumber.log( new Q.ComplexNumber(\n\t\t\t\n\t\t\tt1.real - b,\n\t\t\tt1.imaginary + a\n\t\t))\n\t\treturn new Q.ComplexNumber( Math.PI / 2 - t2.imaginary, t2.real )\n\t},\n\tarcTangent: function( n ){\n\n\t\tconst\n\t\ta = n.real,\n\t\tb = n.imaginary\n\n\t\tif( a === 0 ){\n\n\t\t\tif( b === 1 ) return new Q.ComplexNumber( 0, Infinity )\n\t\t\tif( b === -1 ) return new Q.ComplexNumber( 0, -Infinity )\n\t\t}\n\n\t\tconst \n\t\td = a * a + ( 1 - b ) * ( 1 - b ),\n\t\tt = Q.ComplexNumber.log( new Q.ComplexNumber(\n\t\t\t\n\t\t\t( 1 - b * b - a * a ) / d,\n\t\t\ta / d * -2\n\n\t\t))\n\t\treturn new Q.ComplexNumber( t.imaginary / 2, t.real / 2 )\n\t},\n\n\n\n\n\tpower: function( a, b ){\n\n\t\tif( Q.ComplexNumber.isNumberLike( a )) a = new Q.ComplexNumber( a )\n\t\tif( Q.ComplexNumber.isNumberLike( b )) b = new Q.ComplexNumber( b )\n\n\n\t\t// Anything raised to the Zero power is 1.\n\n\t\tif( b.isZero() ) return Q.ComplexNumber.ONE\n\n\n\t\t// Zero raised to any power is 0.\n\t\t// Note: What happens if b.real is zero or negative?\n\t\t// What happens if b.imaginary is negative?\n\t\t// Do we really need those conditionals??\n\n\t\tif( a.isZero() &&\n\t\t\tb.real > 0 && \n\t\t\tb.imaginary >= 0 ){\n\n\t\t\treturn Q.ComplexNumber.ZERO\n\t\t}\n\n\n\t\t// If our exponent is Real (has no Imaginary component)\n\t\t// then we’re really just raising to a power.\n\t\t\n\t\tif( b.imaginary === 0 ){\n\n\t\t\tif( a.real >= 0 && a.imaginary === 0 ){\n\n\t\t\t\treturn new Q.ComplexNumber( Math.pow( a.real, b.real ), 0 )\n\t\t\t}\n\t\t\telse if( a.real === 0 ){// If our base is Imaginary (has no Real component).\n\n\t\t\t\tswitch(( b.real % 4 + 4 ) % 4 ){\n\t\t\t\n\t\t\t\t\tcase 0:\n\t\t\t\t\t\treturn new Q.ComplexNumber( Math.pow( a.imaginary, b.real ), 0 )\n\t\t\t\t\tcase 1:\n\t\t\t\t\t\treturn new Q.ComplexNumber( 0, Math.pow( a.imaginary, b.real ))\n\t\t\t\t\tcase 2:\n\t\t\t\t\t\treturn new Q.ComplexNumber( -Math.pow( a.imaginary, b.real ), 0 )\n\t\t\t\t\tcase 3:\n\t\t\t\t\t\treturn new Q.ComplexNumber( 0, -Math.pow( a.imaginary, b.real ))\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\n\t\tconst\n\t\tarctangent2 = Math.atan2( a.imaginary, a.real ),\n\t\tlogHypotenuse = Q.logHypotenuse( a.real, a.imaginary ),\n\t\tx = Math.exp( b.real * logHypotenuse - b.imaginary * arctangent2 ),\n\t\ty = b.imaginary * logHypotenuse + b.real * arctangent2\n\n\t\treturn new Q.ComplexNumber(\n\t\t\n\t\t\tx * Math.cos( y ),\n\t\t\tx * Math.sin( y )\n\t\t)\n\t},\n\tsquareRoot: function( a ){\n\n\t\tconst \n\t\tresult = new Q.ComplexNumber( 0, 0 ),\n\t\tabsolute = Q.ComplexNumber.absolute( a )\n\n\t\tif( a.real >= 0 ){\n\n\t\t\tif( a.imaginary === 0 ){\n\t\t\t\t\n\t\t\t\tresult.real = Math.sqrt( a.real )// and imaginary already equals 0.\n\t\t\t}\n\t\t\telse {\n\t\t\t\t\n\t\t\t\tresult.real = Math.sqrt( 2 * ( absolute + a.real )) / 2\n\t\t\t}\n\t\t} \n\t\telse {\n\t\t\t\n\t\t\tresult.real = Math.abs( a.imaginary ) / Math.sqrt( 2 * ( absolute - a.real ))\n\t\t}\n\t\tif( a.real <= 0 ){\n\t\t\t\n\t\t\tresult.imaginary = Math.sqrt( 2 * ( absolute - a.real )) / 2\n\t\t}\n\t\telse {\n\t\t\t\n\t\t\tresult.imaginary = Math.abs( a.imaginary ) / Math.sqrt( 2 * ( absolute + a.real ))\n\t\t}\n\t\tif( a.imaginary < 0 ) result.imaginary *= -1\n\t\treturn result\n\t},\n\tlog: function( a ){\n\n\t\treturn new Q.ComplexNumber(\n\t\t\n\t\t\tQ.logHypotenuse( a.real, a.imaginary ),\n\t\t\tMath.atan2( a.imaginary, a.real )\n\t\t)\n\t},\n\tmultiply: function( a, b ){\n\t\t\n\t\treturn Q.ComplexNumber.operate(\n\n\t\t\t'multiply', a, b,\n\t\t\tfunction( a, b ){\n\t\t\t\t\n\t\t\t\treturn new Q.ComplexNumber( a * b )\n\t\t\t},\n\t\t\tfunction( a, b ){\n\n\t\t\t\treturn new Q.ComplexNumber( \n\n\t\t\t\t\ta * b.real,\n\t\t\t\t\ta * b.imaginary\n\t\t\t\t)\n\t\t\t},\n\t\t\tfunction( a, b ){\n\n\t\t\t\treturn new Q.ComplexNumber( \n\n\t\t\t\t\ta.real * b,\n\t\t\t\t\ta.imaginary * b\n\t\t\t\t)\n\t\t\t},\n\t\t\tfunction( a, b ){\n\n\n\t\t\t\t// FOIL Method that shit.\n\t\t\t\t// https://en.wikipedia.org/wiki/FOIL_method\n\n\t\t\t\tconst\n\t\t\t\tfirsts = a.real * b.real,\n\t\t\t\touters = a.real * b.imaginary,\n\t\t\t\tinners = a.imaginary * b.real,\t\t\t\t\n\t\t\t\tlasts = a.imaginary * b.imaginary * -1// Because i² = -1.\n\t\t\t\t\n\t\t\t\treturn new Q.ComplexNumber( \n\n\t\t\t\t\tfirsts + lasts,\n\t\t\t\t\touters + inners\n\t\t\t\t)\n\t\t\t}\n\t\t)\n\t},\n\tdivide: function( a, b ){\n\n\t\treturn Q.ComplexNumber.operate(\n\n\t\t\t'divide', a, b,\n\t\t\tfunction( a, b ){\n\t\t\t\t\n\t\t\t\treturn new Q.ComplexNumber( a / b )\n\t\t\t},\n\t\t\tfunction( a, b ){\n\n\t\t\t\treturn new Q.ComplexNumber( a ).divide( b )\n\t\t\t},\n\t\t\tfunction( a, b ){\n\n\t\t\t\treturn new Q.ComplexNumber( \n\n\t\t\t\t\ta.real / b,\n\t\t\t\t\ta.imaginary / b\n\t\t\t\t)\n\t\t\t},\n\t\t\tfunction( a, b ){\n\n\n\t\t\t\t// Ermergerd I had to look this up because it’s been so long.\n\t\t\t\t// https://www.khanacademy.org/math/precalculus/imaginary-and-complex-numbers/complex-conjugates-and-dividing-complex-numbers/a/dividing-complex-numbers-review\n\n\t\t\t\tconst \n\t\t\t\tconjugate = b.conjugate(),\n\t\t\t\tnumerator = a.multiply( conjugate ),\n\n\n\t\t\t\t// The .imaginary will be ZERO for sure, \n\t\t\t\t// so this forces a ComplexNumber.divide( Number ) ;)\n\t\t\t\t\n\t\t\t\tdenominator = b.multiply( conjugate ).real\n\n\t\t\t\treturn numerator.divide( denominator )\n\t\t\t}\n\t\t)\n\t},\n\tadd: function( a, b ){\n\t\t\n\t\treturn Q.ComplexNumber.operate(\n\n\t\t\t'add', a, b,\n\t\t\tfunction( a, b ){\n\n\t\t\t\treturn new Q.ComplexNumber( a + b )\n\t\t\t},\n\t\t\tfunction( a, b ){\n\n\t\t\t\treturn new Q.ComplexNumber(\n\n\t\t\t\t\tb.real + a,\n\t\t\t\t\tb.imaginary\n\t\t\t\t)\n\t\t\t},\n\t\t\tfunction( a, b ){\n\n\t\t\t\treturn new Q.ComplexNumber(\n\n\t\t\t\t\ta.real + b,\n\t\t\t\t\ta.imaginary\n\t\t\t\t)\n\t\t\t},\n\t\t\tfunction( a, b ){\n\n\t\t\t\treturn new Q.ComplexNumber(\n\n\t\t\t\t\ta.real + b.real,\n\t\t\t\t\ta.imaginary + b.imaginary\n\t\t\t\t)\n\t\t\t}\n\t\t)\n\t},\n\tsubtract: function( a, b ){\n\n\t\treturn Q.ComplexNumber.operate(\n\n\t\t\t'subtract', a, b,\n\t\t\tfunction( a, b ){\n\n\t\t\t\treturn new Q.ComplexNumber( a - b )\n\t\t\t},\n\t\t\tfunction( a, b ){\n\n\t\t\t\treturn new Q.ComplexNumber(\n\n\t\t\t\t\tb.real - a,\n\t\t\t\t\tb.imaginary\n\t\t\t\t)\n\t\t\t},\n\t\t\tfunction( a, b ){\n\n\t\t\t\treturn new Q.ComplexNumber(\n\n\t\t\t\t\ta.real - b,\n\t\t\t\t\ta.imaginary\n\t\t\t\t)\n\t\t\t},\n\t\t\tfunction( a, b ){\n\n\t\t\t\treturn new Q.ComplexNumber(\n\n\t\t\t\t\ta.real - b.real,\n\t\t\t\t\ta.imaginary - b.imaginary\n\t\t\t\t)\n\t\t\t}\n\t\t)\n\t}\n})\n\n\n\n\nQ.ComplexNumber.createConstants(\n\n\t'ZERO', new Q.ComplexNumber( 0, 0 ),\n\t'ONE', new Q.ComplexNumber( 1, 0 ),\n\t'E', new Q.ComplexNumber( Math.E, 0 ),\n\t'PI', new Q.ComplexNumber( Math.PI, 0 ),\n\t'I', new Q.ComplexNumber( 0, 1 ),\n\t'EPSILON', new Q.ComplexNumber( Q.EPSILON, Q.EPSILON ),\n\t'INFINITY', new Q.ComplexNumber( Infinity, Infinity ),\n\t'NAN', new Q.ComplexNumber( NaN, NaN )\n)\n\n\n\n\nObject.assign( Q.ComplexNumber.prototype, {\n\n\n\t// NON-destructive operations.\n\n\tclone: function(){\n\n\t\treturn new Q.ComplexNumber( this.real, this.imaginary )\n\t},\n\treduce: function(){\n\n\t\t\n\t\t// Note: this *might* kill function chaining.\n\n\t\tif( this.imaginary === 0 ) return this.real\n\t\treturn this\n\t},\n\ttoText: function( roundToDecimal, padPositive ){\n\n\n\t\t// Note: this will kill function chaining.\n\n\t\treturn Q.ComplexNumber.toText( this.real, this.imaginary, roundToDecimal, padPositive )\n\t},\n\n\n\tisNaN: function( n ){\n\t\t\n\t\treturn Q.ComplexNumber.isNaN( this )// Returned boolean will kill function chaining.\n\t},\n\tisZero: function( n ){\n\n\t\treturn Q.ComplexNumber.isZero( this )// Returned boolean will kill function chaining.\n\t},\n\tisFinite: function( n ){\n\n\t\treturn Q.ComplexNumber.isFinite( this )// Returned boolean will kill function chaining.\n\t},\n\tisInfinite: function( n ){\n\t\n\t\treturn Q.ComplexNumber.isInfinite( this )// Returned boolean will kill function chaining.\n\t},\n\tisEqualTo: function( b ){\n\n\t\treturn Q.ComplexNumber.areEqual( this, b )// Returned boolean will kill function chaining.\n\t},\n\n\n\tabsolute: function(){\n\t\n\t\treturn Q.ComplexNumber.absolute( this )// Returned number will kill function chaining.\n\t},\n\tconjugate: function(){\n\n\t\treturn Q.ComplexNumber.conjugate( this )\n\t},\n\t\n\n\tpower: function( b ){\n\n\t\treturn Q.ComplexNumber.power( this, b )\n\t},\n\tsquareRoot: function(){\n\n\t\treturn Q.ComplexNumber.squareRoot( this )\n\t},\n\tlog: function(){\n\n\t\treturn Q.ComplexNumber.log( this )\n\t},\n\tmultiply: function( b ){\n\n\t\treturn Q.ComplexNumber.multiply( this, b )\n\t},\n\tdivide: function( b ){\n\n\t\treturn Q.ComplexNumber.divide( this, b )\n\t},\n\tadd: function( b ){\n\n\t\treturn Q.ComplexNumber.add( this, b )\n\t},\n\tsubtract: function( b ){\n\n\t\treturn Q.ComplexNumber.subtract( this, b )\n\t},\n\n\n\n\n\t// DESTRUCTIVE operations.\n\n\tcopy$: function( b ){\n\t\t\n\t\tif( b instanceof Q.ComplexNumber !== true )\n\t\t\treturn Q.error( `Q.ComplexNumber attempted to copy something that was not a complex number in to this complex number #${this.index}.`, this )\n\t\t\n\t\tthis.real = b.real\n\t\tthis.imaginary = b.imaginary\n\t\treturn this\n\t},\n\tconjugate$: function(){\n\n\t\treturn this.copy$( this.conjugate() )\n\t},\n\tpower$: function( b ){\n\n\t\treturn this.copy$( this.power( b ))\n\t},\n\tsquareRoot$: function(){\n\n\t\treturn this.copy$( this.squareRoot() )\n\t},\n\tlog$: function(){\n\n\t\treturn this.copy$( this.log() )\n\t},\n\tmultiply$: function( b ){\n\n\t\treturn this.copy$( this.multiply( b ))\n\t},\n\tdivide$: function( b ){\n\n\t\treturn this.copy$( this.divide( b ))\n\t},\n\tadd$: function( b ){\n\n\t\treturn this.copy$( this.add( b ))\n\t},\n\tsubtract$: function( b ){\n\n\t\treturn this.copy$( this.subtract( b ))\n\t}\n})\n\n\n\n// Copyright © 2019–2020, Stewart Smith. See LICENSE for details.\n\n\n\n\nQ.Matrix = function(){\n\n\n\t// We’re keeping track of how many matrices are\n\t// actually being generated. Just curiosity.\n\n\tthis.index = Q.Matrix.index ++\n\n\n\tlet matrixWidth = null\n\n\n\t// Has Matrix been called with two numerical arguments?\n\t// If so, we need to create an empty Matrix \n\t// with dimensions of those values.\n\t\n\tif( arguments.length == 1 &&\n\t\tQ.ComplexNumber.isNumberLike( arguments[ 0 ])){\n\n\t\tmatrixWidth = arguments[ 0 ]\n\t\tthis.rows = new Array( matrixWidth ).fill( 0 ).map( function(){\n\n\t\t\treturn new Array( matrixWidth ).fill( 0 )\n\t\t})\n\t}\n\telse if( arguments.length == 2 &&\n\t\tQ.ComplexNumber.isNumberLike( arguments[ 0 ]) &&\n\t Q.ComplexNumber.isNumberLike( arguments[ 1 ])){\n\n\t\tmatrixWidth = arguments[ 0 ]\n\t\tthis.rows = new Array( arguments[ 1 ]).fill( 0 ).map( function(){\n\n\t\t\treturn new Array( matrixWidth ).fill( 0 )\n\t\t})\n\t}\n\telse {\n\n\t\t// Matrices’ primary organization is by rows,\n\t\t// which is more congruent with our written langauge;\n\t\t// primarily organizated by horizontally juxtaposed glyphs.\n\t\t// That means it’s easier to write an instance invocation in code\n\t\t// and easier to read when inspecting properties in the console.\n\n\t\tlet matrixWidthIsBroken = false\n\t\tthis.rows = Array.from( arguments )\n\t\tthis.rows.forEach( function( row ){\n\n\t\t\tif( row instanceof Array !== true ) row = [ row ]\n\t\t\tif( matrixWidth === null ) matrixWidth = row.length\n\t\t\telse if( matrixWidth !== row.length ) matrixWidthIsBroken = true\n\t\t})\n\t\tif( matrixWidthIsBroken )\n\t\t\treturn Q.error( `Q.Matrix found upon initialization that matrix#${this.index} row lengths were not equal. You are going to have a bad time.`, this )\n\t}\n\n\n\n\n\n\n\t// But for convenience we can also organize by columns.\n\t// Note this represents the transposed version of itself!\n\n\tconst matrix = this\n\tthis.columns = []\n\tfor( let x = 0; x < matrixWidth; x ++ ){\n\t\n\t\tconst column = []\n\t\tfor( let y = 0; y < this.rows.length; y ++ ){\n\n\n\t\t\t// Since we’re combing through here\n\t\t\t// this is a good time to convert Number to ComplexNumber!\n\n\t\t\tconst value = matrix.rows[ y ][ x ]\n\t\t\tif( typeof value === 'number' ){\n\t\t\t\t\n\t\t\t\t// console.log('Created a complex number!')\n\t\t\t\tmatrix.rows[ y ][ x ] = new Q.ComplexNumber( value )\n\t\t\t}\n\t\t\telse if( value instanceof Q.ComplexNumber === false ){\n\t\t\t\treturn Q.error( `Q.Matrix found upon initialization that matrix#${this.index} contained non-quantitative values. A+ for creativity, but F for functionality.`, this )\n\t\t\t}\n\n\t\t\t// console.log( x, y, matrix.rows[ y ][ x ])\n\t\t\t\n\n\t\t\tObject.defineProperty( column, y, { \n\n\t\t\t\tget: function(){ return matrix.rows[ y ][ x ]},\n\t\t\t\tset: function( n ){ matrix.rows[ y ][ x ] = n }\n\t\t\t})\n\t\t}\n\t\tthis.columns.push( column )\n\t}\n}\n\n\n\n\n\n\n ///////////////////////////\n // //\n // Static properties //\n // //\n///////////////////////////\n\n\nObject.assign( Q.Matrix, {\n\n\tindex: 0,\n\thelp: function(){ return Q.help( this )},\n\tconstants: {},// Only holds references; an easy way to look up what constants exist.\n\tcreateConstant: Q.createConstant,\n\tcreateConstants: Q.createConstants,\n\n\n\tisMatrixLike: function( obj ){\n\n\t\t//return obj instanceof Q.Matrix || Q.Matrix.prototype.isPrototypeOf( obj )\n\t\treturn obj instanceof this || this.prototype.isPrototypeOf( obj )\n\t},\n\tisWithinRange: function( n, minimum, maximum ){\n\n\t\treturn typeof n === 'number' && \n\t\t\tn >= minimum && \n\t\t\tn <= maximum && \n\t\t\tn == parseInt( n )\n\t},\n\tgetWidth: function( matrix ){\n\n\t\treturn matrix.columns.length\n\t},\n\tgetHeight: function( matrix ){\n\n\t\treturn matrix.rows.length\n\t},\n\thaveEqualDimensions: function( matrix0, matrix1 ){\n\n\t\treturn (\n\t\t\n\t\t\tmatrix0.rows.length === matrix1.rows.length && \n\t\t\tmatrix0.columns.length === matrix1.columns.length\n\t\t)\n\t},\n\tareEqual: function( matrix0, matrix1 ){\n\n\t\tif( matrix0 instanceof Q.Matrix !== true ) return false\n\t\tif( matrix1 instanceof Q.Matrix !== true ) return false\n\t\tif( Q.Matrix.haveEqualDimensions( matrix0, matrix1 ) !== true ) return false\n\t\treturn matrix0.rows.reduce( function( state, row, r ){\n\n\t\t\treturn state && row.reduce( function( state, cellValue, c ){\n\n\t\t\t\treturn state && cellValue.isEqualTo( matrix1.rows[ r ][ c ])\n\n\t\t\t}, true )\n\n\t\t}, true )\n\t},\n\n\n\n\n\tcreateSquare: function( size, f ){\n\n\t\tif( typeof size !== 'number' ) size = 2\n\t\tif( typeof f !== 'function' ) f = function(){ return 0 }\n\t\tconst data = []\n\t\tfor( let y = 0; y < size; y ++ ){\n\n\t\t\tconst row = []\n\t\t\tfor( let x = 0; x < size; x ++ ){\n\n\t\t\t\trow.push( f( x, y ))\n\t\t\t}\n\t\t\tdata.push( row )\n\t\t}\n\t\treturn new Q.Matrix( ...data )\n\t},\n\tcreateZero: function( size ){\n\t\n\t\treturn new Q.Matrix.createSquare( size )\n\t},\n\tcreateOne: function( size ){\n\t\n\t\treturn new Q.Matrix.createSquare( size, function(){ return 1 })\n\t},\n\tcreateIdentity: function( size ){\n\n\t\treturn new Q.Matrix.createSquare( size, function( x, y ){ return x === y ? 1 : 0 })\n\t},\n\n\t\n\n\n\t// Import FROM a format.\n\n\tfrom: function( format ){\n\n\t\tif( typeof format !== 'string' ) format = 'Array'\n\t\tconst f = Q.Matrix[ 'from'+ format ]\n\t\tformat = format.toLowerCase()\n\t\tif( typeof f !== 'function' )\n\t\t\treturn Q.error( `Q.Matrix could not find an importer for “${format}” data.` )\n\t\treturn f\n\t},\n\tfromArray: function( array ){\n\n\t\treturn new Q.Matrix( ...array )\n\t},\n\tfromXsv: function( input, rowSeparator, valueSeparator ){\n\n\t\t`\n\t\tIngest string data organized by row, then by column\n\t\twhere rows are separated by one token (default: \\n)\n\t\tand column values are separated by another token\n\t\t(default: \\t).\n\n\t\t`\n\n\t\tif( typeof rowSeparator !== 'string' ) rowSeparator = '\\n'\n\t\tif( typeof valueSeparator !== 'string' ) valueSeparator = '\\t'\n\n\t\tconst \n\t\tinputRows = input.split( rowSeparator ),\n\t\toutputRows = []\n\n\t\tinputRows.forEach( function( inputRow ){\n\n\t\t\tinputRow = inputRow.trim()\n\t\t\tif( inputRow === '' ) return\n\t\t\t\n\t\t\tconst outputRow = []\n\t\t\tinputRow.split( valueSeparator ).forEach( function( cellValue ){\n\n\t\t\t\toutputRow.push( parseFloat( cellValue ))\n\t\t\t})\n\t\t\toutputRows.push( outputRow )\n\t\t})\n\t\treturn new Q.Matrix( ...outputRows )\n\t},\n\tfromCsv: function( csv ){\n\n\t\treturn Q.Matrix.fromXsv( csv.replace( /\\r/g, '\\n' ), '\\n', ',' )\n\t},\n\tfromTsv: function( tsv ){\n\n\t\treturn Q.Matrix.fromXsv( tsv, '\\n', '\\t' )\n\t},\n\tfromHtml: function( html ){\n\n\t\treturn Q.Matrix.fromXsv(\n\n\t\t\thtml\n\t\t\t\t.replace( /\\r?\\n|\\r|<tr>|<td>/g, '' )\n\t\t\t\t.replace( /<\\/td>(\\s*)<\\/tr>/g, '</tr>' )\n\t\t\t\t.match( /<table>(.*)<\\/table>/i )[ 1 ],\n\t\t\t'</tr>',\n\t\t\t'</td>'\n\t\t)\n\t},\n\n\n\n\n\t// Export TO a format.\n\n\ttoXsv: function( matrix, rowSeparator, valueSeparator ){\n\t\t\n\t\treturn matrix.rows.reduce( function( xsv, row ){\n\n\t\t\treturn xsv + rowSeparator + row.reduce( function( xsv, cell, c ){\n\n\t\t\t\treturn xsv + ( c > 0 ? valueSeparator : '' ) + cell.toText()\n\t\t\t\n\t\t\t}, '' )\n\t\t\n\t\t}, '' )\n\t},\n\ttoCsv: function( matrix ){\n\n\t\treturn Q.Matrix.toXsv( matrix, '\\n', ',' )\n\t},\n\ttoTsv: function( matrix ){\n\n\t\treturn Q.Matrix.toXsv( matrix, '\\n', '\\t' )\n\t},\n\n\n\n\n\t// Operate NON-destructive.\n\n\tadd: function( matrix0, matrix1 ){\n\n\t\tif( Q.Matrix.isMatrixLike( matrix0 ) !== true ||\n\t\t\tQ.Matrix.isMatrixLike( matrix1 ) !== true ){\n\n\t\t\treturn Q.error( `Q.Matrix attempted to add something that was not a matrix.` )\n\t\t}\n\t\tif( Q.Matrix.haveEqualDimensions( matrix0, matrix1 ) !== true )\n\t\t\treturn Q.error( `Q.Matrix cannot add matrix#${matrix0.index} of dimensions ${matrix0.columns.length}x${matrix0.rows.length} to matrix#${matrix1.index} of dimensions ${matrix1.columns.length}x${matrix1.rows.length}.`)\n\n\t\treturn new Q.Matrix( ...matrix0.rows.reduce( function( resultMatrixRow, row, r ){\n\n\t\t\tresultMatrixRow.push( row.reduce( function( resultMatrixColumn, cellValue, c ){\n\n\t\t\t\t// resultMatrixColumn.push( cellValue + matrix1.rows[ r ][ c ])\n\t\t\t\tresultMatrixColumn.push( cellValue.add( matrix1.rows[ r ][ c ]))\n\t\t\t\treturn resultMatrixColumn\n\n\t\t\t}, [] ))\n\t\t\treturn resultMatrixRow\n\n\t\t}, [] ))\n\t},\n\tmultiplyScalar: function( matrix, scalar ){\n\n\t\tif( Q.Matrix.isMatrixLike( matrix ) !== true ){\n\n\t\t\treturn Q.error( `Q.Matrix attempted to scale something that was not a matrix.` )\n\t\t}\n\t\tif( typeof scalar !== 'number' ){\n\n\t\t\treturn Q.error( `Q.Matrix attempted to scale this matrix#${matrix.index} by an invalid scalar: ${scalar}.` )\n\t\t}\n\t\treturn new Q.Matrix( ...matrix.rows.reduce( function( resultMatrixRow, row ){\n\n\t\t\tresultMatrixRow.push( row.reduce( function( resultMatrixColumn, cellValue ){\n\n\t\t\t\t// resultMatrixColumn.push( cellValue * scalar )\n\t\t\t\tresultMatrixColumn.push( cellValue.multiply( scalar ))\n\t\t\t\treturn resultMatrixColumn\n\t\t\t\n\t\t\t}, [] ))\n\t\t\treturn resultMatrixRow\n\n\t\t}, [] ))\n\t},\n\tmultiply: function( matrix0, matrix1 ){\n\n\t\t`\n\t\tTwo matrices can be multiplied only when \n\t\tthe number of columns in the first matrix\n\t\tequals the number of rows in the second matrix.\n\t\tReminder: Matrix multiplication is not commutative\n\t\tso the order in which you multiply matters.\n\n\n\t\t\tSEE ALSO\n\n\t\thttps://en.wikipedia.org/wiki/Matrix_multiplication\n\t\t`\n\n\t\tif( Q.Matrix.isMatrixLike( matrix0 ) !== true ||\n\t\t\tQ.Matrix.isMatrixLike( matrix1 ) !== true ){\n\n\t\t\treturn Q.error( `Q.Matrix attempted to multiply something that was not a matrix.` )\n\t\t}\n\t\tif( matrix0.columns.length !== matrix1.rows.length ){\n\n\t\t\treturn Q.error( `Q.Matrix attempted to multiply Matrix#${matrix0.index}(cols==${matrix0.columns.length}) by Matrix#${matrix1.index}(rows==${matrix1.rows.length}) but their dimensions were not compatible for this.` )\n\t\t}\n\t\tconst resultMatrix = []\n\t\tmatrix0.rows.forEach( function( matrix0Row ){// Each row of THIS matrix\n\n\t\t\tconst resultMatrixRow = []\n\t\t\tmatrix1.columns.forEach( function( matrix1Column ){// Each column of OTHER matrix\n\n\t\t\t\tconst sum = new Q.ComplexNumber()\n\t\t\t\tmatrix1Column.forEach( function( matrix1CellValue, index ){// Work down the column of OTHER matrix\n\n\t\t\t\t\tsum.add$( matrix0Row[ index ].multiply( matrix1CellValue ))\n\t\t\t\t})\n\t\t\t\tresultMatrixRow.push( sum )\n\t\t\t})\n\t\t\tresultMatrix.push( resultMatrixRow )\n\t\t})\n\t\t//return new Q.Matrix( ...resultMatrix )\n\t\treturn new this( ...resultMatrix )\n\t},\n\tmultiplyTensor: function( matrix0, matrix1 ){\n\n\t\t`\n\t\thttps://en.wikipedia.org/wiki/Kronecker_product\n\t\thttps://en.wikipedia.org/wiki/Tensor_product\n\t\t`\n\n\t\tif( Q.Matrix.isMatrixLike( matrix0 ) !== true ||\n\t\t\tQ.Matrix.isMatrixLike( matrix1 ) !== true ){\n\n\t\t\treturn Q.error( `Q.Matrix attempted to tensor something that was not a matrix.` )\n\t\t}\n\n\t\tconst \n\t\tresultMatrix = [],\n\t\tresultMatrixWidth = matrix0.columns.length * matrix1.columns.length,\n\t\tresultMatrixHeight = matrix0.rows.length * matrix1.rows.length\n\n\t\tfor( let y = 0; y < resultMatrixHeight; y ++ ){\n\n\t\t\tconst resultMatrixRow = []\n\t\t\tfor( let x = 0; x < resultMatrixWidth; x ++ ){\n\n\t\t\t\tconst \n\t\t\t\tmatrix0X = Math.floor( x / matrix0.columns.length ),\n\t\t\t\tmatrix0Y = Math.floor( y / matrix0.rows.length ),\n\t\t\t\tmatrix1X = x % matrix1.columns.length,\n\t\t\t\tmatrix1Y = y % matrix1.rows.length\n\n\t\t\t\tresultMatrixRow.push( \n\n\t\t\t\t\t//matrix0.rows[ matrix0Y ][ matrix0X ] * matrix1.rows[ matrix1Y ][ matrix1X ]\n\t\t\t\t\tmatrix0.rows[ matrix0Y ][ matrix0X ].multiply( matrix1.rows[ matrix1Y ][ matrix1X ])\n\t\t\t\t)\n\t\t\t}\n\t\t\tresultMatrix.push( resultMatrixRow )\n\t\t}\n\t\treturn new Q.Matrix( ...resultMatrix )\n\t}\n})\n\n\n\n\n\n\n //////////////////////////////\n // //\n // Prototype properties //\n // //\n//////////////////////////////\n\n\nObject.assign( Q.Matrix.prototype, {\n\n\tisValidRow: function( r ){\n\n\t\treturn Q.Matrix.isWithinRange( r, 0, this.rows.length - 1 )\n\t},\n\tisValidColumn: function( c ){\n\n\t\treturn Q.Matrix.isWithinRange( c, 0, this.columns.length - 1 )\n\t},\n\tisValidAddress: function( x, y ){\n\n\t\treturn this.isValidRow( y ) && this.isValidColumn( x )\n\t},\n\tgetWidth: function(){\n\n\t\treturn Q.Matrix.getWidth( this )\n\t},\n\tgetHeight: function(){\n\n\t\treturn Q.Matrix.getHeight( this )\n\t},\n\n\n\n\n\t// Read NON-destructive by nature. (Except quantum reads of course! ROFL!!)\n\n\tread: function( x, y ){\n\n\t\t`\n\t\tEquivalent to \n\t\tthis.columns[ x ][ y ] \n\t\tor \n\t\tthis.rows[ y ][ x ]\n\t\tbut with safety checks.\n\t\t`\n\t\t\n\t\tif( this.isValidAddress( x, y )) return this.rows[ y ][ x ]\n\t\treturn Q.error( `Q.Matrix could not read from cell address (x=${x}, y=${y}) in matrix#${this.index}.`, this )\n\t},\n\tclone: function(){\n\n\t\treturn new Q.Matrix( ...this.rows )\n\t},\n\tisEqualTo: function( otherMatrix ){\n\n\t\treturn Q.Matrix.areEqual( this, otherMatrix )\n\t},\n\n\n\ttoArray: function(){\n\n\t\treturn this.rows\n\t},\n\ttoXsv: function( rowSeparator, valueSeparator ){\n\t\t\n\t\treturn Q.Matrix.toXsv( this, rowSeparator, valueSeparator )\n\t},\n\ttoCsv: function(){\n\n\t\treturn Q.Matrix.toXsv( this, '\\n', ',' )\n\t},\n\ttoTsv: function(){\n\n\t\treturn Q.Matrix.toXsv( this, '\\n', '\\t' )\n\t},\n\ttoHtml: function(){\n\t\t\n\t\treturn this.rows.reduce( function( html, row ){\n\n\t\t\treturn html + row.reduce( function( html, cell ){\n\n\t\t\t\treturn html +'\\n\\t\\t<td>'+ cell.toText() +'</td>'\n\t\t\t\n\t\t\t}, '\\n\\t<tr>' ) + '\\n\\t</tr>'\n\t\t\n\t\t}, '\\n<table>' ) +'\\n</table>'\n\t},\n\n\n\n\n\t// Write is DESTRUCTIVE by nature. Not cuz I hate ya.\n\n\twrite$: function( x, y, n ){\n\n\t\t`\n\t\tEquivalent to \n\t\tthis.columns[ x ][ y ] = n \n\t\tor \n\t\tthis.rows[ y ][ x ] = n\n\t\tbut with safety checks.\n\t\t`\n\n\t\tif( this.isValidAddress( x, y )){\n\n\t\t\tif( Q.ComplexNumber.isNumberLike( n )) n = new Q.ComplexNumber( n )\n\t\t\tif( n instanceof Q.ComplexNumber !== true ) return Q.error( `Attempted to write an invalid value (${n}) to matrix#${this.index} at x=${x}, y=${y}`, this )\n\t\t\tthis.rows[ y ][ x ] = n\n\t\t\treturn this\n\t\t}\n\t\treturn Q.error( `Invalid cell address for Matrix#${this.index}: x=${x}, y=${y}`, this )\n\t},\n\tcopy$: function( matrix ){\n\n\t\tif( Q.Matrix.isMatrixLike( matrix ) !== true )\n\t\t\treturn Q.error( `Q.Matrix attempted to copy something that was not a matrix in to this matrix#${matrix.index}.`, this )\n\n\t\tif( Q.Matrix.haveEqualDimensions( matrix, this ) !== true )\n\t\t\treturn Q.error( `Q.Matrix cannot copy matrix#${matrix.index} of dimensions ${matrix.columns.length}x${matrix.rows.length} in to this matrix#${this.index} of dimensions ${this.columns.length}x${this.rows.length} because their dimensions do not match.`, this )\n\t\t\n\t\tconst that = this\n\t\tmatrix.rows.forEach( function( row, r ){\n\n\t\t\trow.forEach( function( n, c ){\n\n\t\t\t\tthat.rows[ r ][ c ] = n\n\t\t\t})\n\t\t})\n\t\treturn this\n\t},\n\tfromArray$: function( array ){\n\n\t\treturn this.copy$( Q.Matrix.fromArray( array ))\n\t},\n\tfromCsv$: function( csv ){\n\n\t\treturn this.copy$( Q.Matrix.fromCsv( csv ))\n\t},\n\tfromTsv$: function( tsv ){\n\n\t\treturn this.copy$( Q.Matrix.fromTsv( tsv ))\n\t},\n\tfromHtml$: function( html ){\n\n\t\treturn this.copy$( Q.Matrix.fromHtml( html ))\n\t},\n\n\n\n\n\t// Operate NON-destructive.\n\n\tadd: function( otherMatrix ){\n\n\t\treturn Q.Matrix.add( this, otherMatrix )\n\t},\n\tmultiplyScalar: function( scalar ){\n\n\t\treturn Q.Matrix.multiplyScalar( this, scalar )\n\t},\n\tmultiply: function( otherMatrix ){\n\n\t\treturn Q.Matrix.multiply( this, otherMatrix )\n\t},\n\tmultiplyTensor: function( otherMatrix ){\n\n\t\treturn Q.Matrix.multiplyTensor( this, otherMatrix )\n\t},\n\n\n\n\n\t// Operate DESTRUCTIVE.\n\n\tadd$: function( otherMatrix ){\n\n\t\treturn this.copy$( this.add( otherMatrix ))\n\t},\n\tmultiplyScalar$: function( scalar ){\n\n\t\treturn this.copy$( this.multiplyScalar( scalar ))\n\t}\n})\n\n\n\n\n\n\n //////////////////////////\n // //\n // Static constants //\n // //\n//////////////////////////\n\n\nQ.Matrix.createConstants(\n\n\t'IDENTITY_2X2', Q.Matrix.createIdentity( 2 ),\n\t'IDENTITY_3X3', Q.Matrix.createIdentity( 3 ),\n\t'IDENTITY_4X4', Q.Matrix.createIdentity( 4 ),\n\n\t'CONSTANT0_2X2', new Q.Matrix(\n\t\t[ 1, 1 ],\n\t\t[ 0, 0 ]),\n\n\t'CONSTANT1_2X2', new Q.Matrix(\n\t\t[ 0, 0 ],\n\t\t[ 1, 1 ]),\n\n\t'NEGATION_2X2', new Q.Matrix(\n\t\t[ 0, 1 ],\n\t\t[ 1, 0 ]),\n\n\t'TEST_MAP_9X9', new Q.Matrix(\n\t\t[ 11, 21, 31, 41, 51, 61, 71, 81, 91 ],\n\t\t[ 12, 22, 32, 42, 52, 62, 72, 82, 92 ],\n\t\t[ 13, 23, 33, 43, 53, 63, 73, 83, 93 ],\n\t\t[ 14, 24, 34, 44, 54, 64, 74, 84, 94 ],\n\t\t[ 15, 25, 35, 45, 55, 65, 75, 85, 95 ],\n\t\t[ 16, 26, 36, 46, 56, 66, 76, 86, 96 ],\n\t\t[ 17, 27, 37, 47, 57, 67, 77, 87, 97 ],\n\t\t[ 18, 28, 38, 48, 58, 68, 78, 88, 98 ],\n\t\t[ 19, 29, 39, 49, 59, 69, 79, 89, 99 ])\n)\n\n\n\n\n\n// Copyright © 2019–2020, Stewart Smith. See LICENSE for details.\n\n\n\n\nQ.Qubit = function( a, b, symbol, name ){\n\t\n\n\t// If we’ve received an instance of Q.Matrix as our first argument\n\t// then we’ll assume there are no further arguments\n\t// and just use that matrix as our new Q.Qubit instance.\n\n\tif( Q.Matrix.isMatrixLike( a ) && b === undefined ){\n\n\t\tb = a.rows[ 1 ][ 0 ]\n\t\ta = a.rows[ 0 ][ 0 ]\n\t}\n\telse {\n\n\n\t\t// All of our internal math now uses complex numbers\n\t\t// rather than Number literals\n\t\t// so we’d better convert!\n\n\t\tif( typeof a === 'number' ) a = new Q.ComplexNumber( a, 0 )\n\t\tif( typeof b === 'number' ) b = new Q.ComplexNumber( b, 0 )\n\n\n\t\t// If we receive undefined (or garbage inputs)\n\t\t// let’s try to make it useable.\n\t\t// This way we can always call Q.Qubit with no arguments\n\t\t// to make a new qubit available for computing with.\n\n\t\tif( a instanceof Q.ComplexNumber !== true ) a = new Q.ComplexNumber( 1, 0 )\n\t\tif( b instanceof Q.ComplexNumber !== true ){\n\n\n\t\t\t// 1 - |𝒂|² = |𝒃|²\n\t\t\t// So this does NOT account for if 𝒃 ought to be imaginary or not.\n\t\t\t// Perhaps for completeness we could randomly decide\n\t\t\t// to flip the real and imaginary components of 𝒃 after this line?\n\n\t\t\tb = Q.ComplexNumber.ONE.subtract( Math.pow( a.absolute(), 2 )).squareRoot()\n\t\t}\n\t}\n\n\n\t// Sanity check!\n\t// Does this constraint hold true? |𝒂|² + |𝒃|² = 1\n\n\tif( Math.pow( a.absolute(), 2 ) + Math.pow( b.absolute(), 2 ) - 1 > Q.EPSILON )\n\t \treturn Q.error( `Q.Qubit could not accept the initialization values of a=${a} and b=${b} because their squares do not add up to 1.` )\t\n\n\tQ.Matrix.call( this, [ a ],[ b ])\n\tthis.index = Q.Qubit.index ++\n\n\n\t// Convenience getters and setters for this qubit’s\n\t// controll bit and target bit.\n\n\tObject.defineProperty( this, 'alpha', { \n\n\t\tget: function(){ return this.rows[ 0 ][ 0 ]},\n\t\tset: function( n ){ this.rows[ 0 ][ 0 ] = n }\n\t})\n\tObject.defineProperty( this, 'beta', { \n\n\t\tget: function(){ return this.rows[ 1 ][ 0 ]},\n\t\tset: function( n ){ this.rows[ 1 ][ 0 ] = n }\n\t})\n\n\n\t// Used for Dirac notation: |?⟩\n\n\tif( typeof symbol === 'string' ) this.symbol = symbol\n\tif( typeof name === 'string' ) this.name = name\n\tif( this.symbol === undefined || this.name === undefined ){\n\n\t\tconst found = Object.values( Q.Qubit.constants ).find( function( qubit ){\n\n\t\t\treturn (\n\n\t\t\t\ta.isEqualTo( qubit.alpha ) && \n\t\t\t\tb.isEqualTo( qubit.beta )\n\t\t\t)\n\t\t})\n\t\tif( found === undefined ){\n\n\t\t\tthis.symbol = '?'\n\t\t\tthis.name = 'Unnamed'\n\t\t}\n\t\telse {\n\n\t\t\tif( this.symbol === undefined ) this.symbol = found.symbol\n\t\t\tif( this.name === undefined ) this.name = found.name\n\t\t}\n\t}\n}\nQ.Qubit.prototype = Object.create( Q.Matrix.prototype )\nQ.Qubit.prototype.constructor = Q.Qubit\n\n\n\n\nObject.assign( Q.Qubit, {\n\n\tindex: 0,\n\thelp: function(){ return Q.help( this )},\n\tconstants: {},\n\tcreateConstant: Q.createConstant,\n\tcreateConstants: Q.createConstants,\n\t\n\n\n\n\tfindBy: function( key, value ){\n\n\t\treturn (\n\t\t\t\n\t\t\tObject\n\t\t\t.values( Q.Qubit.constants )\n\t\t\t.find( function( item ){\n\n\t\t\t\tif( typeof value === 'string' && \n\t\t\t\t\ttypeof item[ key ] === 'string' ){\n\n\t\t\t\t\treturn value.toLowerCase() === item[ key ].toLowerCase()\n\t\t\t\t}\n\t\t\t\treturn value === item[ key ]\n\t\t\t})\n\t\t)\n\t},\n\tfindBySymbol: function( symbol ){\n\n\t\treturn Q.Qubit.findBy( 'symbol', symbol )\n\t},\n\tfindByName: function( name ){\n\n\t\treturn Q.Qubit.findBy( 'name', name )\n\t},\n\tfindByBeta: function( beta ){\n\n\t\tif( beta instanceof Q.ComplexNumber === false ){\n\n\t\t\tbeta = new Q.ComplexNumber( beta )\n\t\t}\n\t\treturn Object.values( Q.Qubit.constants ).find( function( qubit ){\n\n\t\t\treturn qubit.beta.isEqualTo( beta )\n\t\t})\n\t},\n\tareEqual: function( qubit0, qubit1 ){\n\n\t\treturn ( \n\n\t\t\tqubit0.alpha.isEqualTo( qubit1.alpha ) &&\n\t\t\tqubit0.beta.isEqualTo( qubit1.beta )\n\t\t)\n\t},\n\tcollapse: function( qubit ){\n\n\t\tconst \n\t\talpha2 = Math.pow( qubit.alpha.absolute(), 2 ),\n\t\tbeta2 = Math.pow( qubit.beta.absolute(), 2 ),\n\t\trandomNumberRange = Math.pow( 2, 32 ) - 1,\n\t\trandomNumber = new Uint32Array( 1 )\n\t\t\n\t\t// console.log( 'alpha^2', alpha2 )\n\t\t// console.log( 'beta^2', beta2 )\n\t\twindow.crypto.getRandomValues( randomNumber )\n\t\tconst randomNumberNormalized = randomNumber / randomNumberRange\n\t\tif( randomNumberNormalized <= alpha2 ){\n\n\t\t\treturn new Q.Qubit( 1, 0 )\n\t\t}\n\t\telse return new Q.Qubit( 0, 1 )\n\t},\n\tapplyGate: function( qubit, gate, ...args ){\n\n\t\t`\n\t\tThis is means of inverting what comes first:\n\t\tthe Gate or the Qubit?\n\t\tIf the Gate only operates on a single qubit,\n\t\tthen it doesn’t matter and we can do this:\n\t\t`\n\n\t\tif( gate instanceof Q.Gate === false ) return Q.error( `Q.Qubit attempted to apply something that was not a gate to this qubit #${ qubit.index }.` )\n\t\telse return gate.applyToQubit( qubit, ...args )\n\t},\n\ttoText: function( qubit ){\n\n\t\t//return `|${qubit.beta.toText()}⟩`\n\t\treturn qubit.alpha.toText() +'\\n'+ qubit.beta.toText()\n\t},\n\ttoStateVectorText: function( qubit ){\n\n\t\treturn `|${ qubit.beta.toText() }⟩`\n\t},\n\ttoStateVectorHtml: function( qubit ){\n\n\t\treturn `<span class=\"Q-state-vector ket\">${ qubit.beta.toText() }</span>`\n\t},\n\n\n\n\t// This code was a pain in the ass to figure out.\n\t// I’m not fluent in trigonometry\n\t// and none of the quantum primers actually lay out\n\t// how to convert arbitrary qubit states\n\t// to Bloch Sphere representation.\n\t// Oh, they provide equivalencies for specific states, sure.\n\t// I hope this is useful to you\n\t// unless you are porting this to a terrible language\n\t// like C# or Java or something ;)\n\t\n\ttoBlochSphere: function( qubit ){\n\n\t\t`\n\t\tBased on this qubit’s state return the\n\t\tPolar angle θ (theta),\n\t\tazimuth angle ϕ (phi),\n\t\tBloch vector,\n\t\tcorrected surface coordinate.\n\n\t\thttps://en.wikipedia.org/wiki/Bloch_sphere\n\t\t`\n\n\n\t\t// Polar angle θ (theta).\n\n\t\tconst theta = Q.ComplexNumber.arcCosine( qubit.alpha ).multiply( 2 )\n\t\tif( isNaN( theta.real )) theta.real = 0\n\t\tif( isNaN( theta.imaginary )) theta.imaginary = 0\n\n\t\t\n\t\t// Azimuth angle ϕ (phi).\n\t\t\n\t\tconst phi = Q.ComplexNumber.log( \n\n\t\t\tqubit.beta.divide( Q.ComplexNumber.sine( theta.divide( 2 )))\n\t\t)\n\t\t.divide( Q.ComplexNumber.I )\n\t\tif( isNaN( phi.real )) phi.real = 0\n\t\tif( isNaN( phi.imaginary )) phi.imaginary = 0\n\n\t\t\n\t\t// Bloch vector.\n\n\t\tconst vector = {\n\t\t\t\t\n\t\t\tx: Q.ComplexNumber.sine( theta ).multiply( Q.ComplexNumber.cosine( phi )).real,\n\t\t\ty: Q.ComplexNumber.sine( theta ).multiply( Q.ComplexNumber.sine( phi )).real,\n\t\t\tz: Q.ComplexNumber.cosine( theta ).real\n\t\t}\n\n\n\t\t// Bloch vector’s axes are wonked.\n\t\t// Let’s “correct” them for use with Three.js, etc.\n\n\t\tconst position = {\n\n\t\t\tx: vector.y,\n\t\t\ty: vector.z,\n\t\t\tz: vector.x\n\t\t}\n\n\t\treturn {\n\n\n\t\t\t// Wow does this make tweening easier down the road.\n\n\t\t\talphaReal: qubit.alpha.real,\n\t\t\talphaImaginary: qubit.alpha.imaginary,\n\t\t\tbetaReal: qubit.beta.real,\n\t\t\tbetaImaginary: qubit.beta.imaginary,\n\n\n\t\t\t// Ummm... I’m only returnig the REAL portions. Please forgive me!\n\n\t\t\ttheta: theta.real,\n\t\t\tphi: phi.real,\n\t\t\tvector, // Wonked YZX vector for maths because maths.\n\t\t\tposition// Un-wonked XYZ for use by actual 3D engines.\n\t\t}\n\t},\n\tfromBlochVector: function( x, y, z ){\n\n\n\t\t//basically from a Pauli Rotation\n\t}\n\n})\n\n\n\n\nQ.Qubit.createConstants(\n\n\n\t// Opposing pairs:\n\t// |H⟩ and |V⟩\n\t// |D⟩ and |A⟩\n\t// |R⟩ and |L⟩\n\n\t'HORIZONTAL', new Q.Qubit( 1, 0, 'H', 'Horizontal' ),// ZERO.\n\t'VERTICAL', new Q.Qubit( 0, 1, 'V', 'Vertical' ),// ONE.\n\t'DIAGONAL', new Q.Qubit( Math.SQRT1_2, Math.SQRT1_2, 'D', 'Diagonal' ),\n\t'ANTI_DIAGONAL', new Q.Qubit( Math.SQRT1_2, -Math.SQRT1_2, 'A', 'Anti-diagonal' ),\n\t'RIGHT_HAND_CIRCULAR_POLARIZED', new Q.Qubit( Math.SQRT1_2, new Q.ComplexNumber( 0, -Math.SQRT1_2 ), 'R', 'Right-hand Circular Polarized' ),// RHCP\n\t'LEFT_HAND_CIRCULAR_POLARIZED', new Q.Qubit( Math.SQRT1_2, new Q.ComplexNumber( 0, Math.SQRT1_2 ), 'L', 'Left-hand Circular Polarized' ) // LHCP\n)\n\n\n\n\nObject.assign( Q.Qubit.prototype, {\n\n\tcopy$: function( matrix ){\n\n\t\tif( Q.Matrix.isMatrixLike( matrix ) !== true )\n\t\t\treturn Q.error( `Q.Qubit attempted to copy something that was not a matrix in this qubit #${qubit.index}.`, this )\n\n\t\tif( Q.Matrix.haveEqualDimensions( matrix, this ) !== true )\n\t\t\treturn Q.error( `Q.Qubit cannot copy matrix#${matrix.index} of dimensions ${matrix.columns.length}x${matrix.rows.length} in to this qubit #${this.index} of dimensions ${this.columns.length}x${this.rows.length} because their dimensions do not match.`, this )\n\t\t\n\t\tconst that = this\n\t\tmatrix.rows.forEach( function( row, r ){\n\n\t\t\trow.forEach( function( n, c ){\n\n\t\t\t\tthat.rows[ r ][ c ] = n\n\t\t\t})\n\t\t})\n\t\tthis.dirac = matrix.dirac\n\t\treturn this\n\t},\n\tclone: function(){\n\n\t\treturn new Q.Qubit( this.alpha, this.beta )\n\t},\n\tisEqualTo: function( otherQubit ){\n\n\t\treturn Q.Qubit.areEqual( this, otherQubit )// Returns a Boolean, breaks function chaining!\n\t},\n\tcollapse: function(){\n\n\t\treturn Q.Qubit.collapse( this )\n\t},\n\tapplyGate: function( gate, ...args ){\n\n\t\treturn Q.Qubit.applyGate( this, gate, ...args )\n\t},\n\ttoText: function(){\n\n\t\treturn Q.Qubit.toText( this )// Returns a String, breaks function chaining!\n\t},\n\ttoStateVectorText: function(){\n\n\t\treturn Q.Qubit.toStateVectorText( this )// Returns a String, breaks function chaining!\n\t},\n\ttoStateVectorHtml: function(){\n\n\t\treturn Q.Qubit.toStateVectorHtml( this )// Returns a String, breaks function chaining!\n\t},\n\ttoBlochSphere: function(){\n\n\t\treturn Q.Qubit.toBlochSphere( this )// Returns an Object, breaks function chaining!\n\t},\n\tcollapse$: function(){\n\t\t\n\t\treturn this.copy$( Q.Qubit.collapse( this ))\n\t},\n\tapplyGate$: function( gate ){\n\n\t\treturn this.copy$( Q.Qubit.applyGate( this, gate ))\n\t},\n})\n\n\n\n\n\n\n\n// Copyright © 2019–2020, Stewart Smith. See LICENSE for details.\n\n\n\n\nQ.Gate = function( params ){\n\n\tObject.assign( this, params )\n\tthis.index = Q.Gate.index ++\n\t\n\tif( typeof this.symbol !== 'string' ) this.symbol = '?'\n\tif( typeof this.symbolAmazonBraket !== 'string' ) this.symbolAmazonBraket = this.symbol.toLowerCase()\n\t\n\t\n\t// We use symbols as unique identifiers\n\t// among gate CONSTANTS\n\t// so if you use the same symbol for a non-constant\n\t// that’s not a deal breaker\n\t// but it is good to know.\n\n\tconst \n\tscope = this,\n\tfoundConstant = Object\n\t.values( Q.Gate.constants )\n\t.find( function( gate ){ \n\n\t\treturn gate.symbol === scope.symbol\n\t})\n\n\tif( foundConstant ){\n\t\t\n\t\tQ.warn( `Q.Gate is creating a new instance, #${ this.index }, that uses the same symbol as a pre-existing Gate constant:`, foundConstant )\n\t}\n\n\tif( typeof this.name !== 'string' ) this.name = 'Unknown'\n\tif( typeof this.nameCss !== 'string' ) this.nameCss = 'unknown'\n\n\n\t// If our gate’s matrix is to be \n\t// dynamically created or updated\n\t// then we ouoght to do that now.\n\n\tif( typeof this.updateMatrix$ === 'function' ) this.updateMatrix$()\n\n\n\t// Every gate must have an applyToQubit method.\n\t// If it doesn’t exist we’ll create one\n\t// based on whether a matrix property exists or not.\n\n\tif( typeof this.applyToQubit !== 'function' ){\n\n\t\tif( this.matrix instanceof Q.Matrix === true ){\n\t\t\n\t\t\tthis.applyToQubit = function( qubit ){ \n\n\t\t\t\treturn new Q.Qubit( this.matrix.multiply( qubit ))\n\t\t\t}\n\t\t}\n\t\telse {\n\n\t\t\tthis.applyToQubit = function( qubit ){ return qubit }\n\t\t}\n\t}\n}\n\n\n\n\nObject.assign( Q.Gate, {\n\n\tindex: 0,\n\tconstants: {},\n\tcreateConstant: Q.createConstant,\n\tcreateConstants: Q.createConstants,\n\tfindBy: function( key, value ){\n\n\t\treturn (\n\t\t\t\n\t\t\tObject\n\t\t\t.values( Q.Gate.constants )\n\t\t\t.find( function( item ){\n\n\t\t\t\tif( typeof value === 'string' && \n\t\t\t\t\ttypeof item[ key ] === 'string' ){\n\n\t\t\t\t\treturn value.toLowerCase() === item[ key ].toLowerCase()\n\t\t\t\t}\n\t\t\t\treturn value === item[ key ]\n\t\t\t})\n\t\t)\n\t},\n\tfindBySymbol: function( symbol ){\n\n\t\treturn Q.Gate.findBy( 'symbol', symbol )\n\t},\n\tfindByName: function( name ){\n\n\t\treturn Q.Gate.findBy( 'name', name )\n\t}\n})\n\n\n\n\nObject.assign( Q.Gate.prototype, {\n\n\tclone: function( params ){\n\n\t\treturn new Q.Gate( Object.assign( {}, this, params ))\n\t},\n\tapplyToQubits: function(){\n\n\t\treturn Array.from( arguments ).map( this.applyToQubit.bind( this ))\n\t},\n\tset$: function( key, value ){\n\n\t\tthis[ key ] = value\n\t\treturn this\n\t},\n\tsetSymbol$: function( value ){\n\n\t\treturn this.set$( 'symbol', value )\n\t}\n})\n\n\n\n\nQ.Gate.createConstants(\n\n\n\t// Operate on a single qubit.\n\n\t'IDENTITY', new Q.Gate({\n\n\t\tsymbol: 'I',\n\t\tsymbolAmazonBraket: 'i',\n\t\tsymbolSvg: '',\n\t\tname: 'Identity',\n\t\tnameCss: 'identity',\n\t\tmatrix: Q.Matrix.IDENTITY_2X2\n\t}),\n\t'CURSOR', new Q.Gate({\n\n\t\tsymbol: '*',\n\t\tsymbolAmazonBraket: 'i',\n\t\tsymbolSvg: '',\n\t\tname: 'Identity',\n\t\tnameCss: 'identity',\n\t\tmatrix: Q.Matrix.IDENTITY_2X2\n\t}),\n\t'MEASURE', new Q.Gate({\n\n\t\tsymbol: 'M',\n\t\tsymbolAmazonBraket: 'm',\n\t\tsymbolSvg: '',\n\t\tname: 'Measure',\n\t\tnameCss: 'measure',\n\t\tmatrix: Q.Matrix.IDENTITY_2X2,\n\t\tapplyToQubit: function( state ){}\n\t}),\n\t'HADAMARD', new Q.Gate({\n\n\t\tsymbol: 'H',\n\t\tsymbolAmazonBraket: 'h',\n\t\tsymbolSvg: '',\n\t\tname: 'Hadamard',\n\t\tnameCss: 'hadamard',\n\t\tmatrix: new Q.Matrix(\n\t\t\t[ Math.SQRT1_2, Math.SQRT1_2 ],\n\t\t\t[ Math.SQRT1_2, -Math.SQRT1_2 ])\n\t}),\n\t'PAULI_X', new Q.Gate({\n\n\t\tsymbol: 'X',\n\t\tsymbolAmazonBraket: 'x',\n\t\tsymbolSvg: '',\n\t\tname: 'Pauli X',\n\t\tnameCss: 'pauli-x',\n\t\tmatrix: new Q.Matrix(\n\t\t\t[ 0, 1 ],\n\t\t\t[ 1, 0 ])\n\t}),\n\t'PAULI_Y', new Q.Gate({\n\n\t\tsymbol: 'Y',\n\t\tsymbolAmazonBraket: 'y',\n\t\tsymbolSvg: '',\n\t\tname: 'Pauli Y',\n\t\tnameCss: 'pauli-y',\n\t\tmatrix: new Q.Matrix(\n\t\t\t[ 0, new Q.ComplexNumber( 0, -1 )],\n\t\t\t[ new Q.ComplexNumber( 0, 1 ), 0 ])\n\t}),\n\t'PAULI_Z', new Q.Gate({\n\n\t\tsymbol: 'Z',\n\t\tsymbolAmazonBraket: 'z',\n\t\tsymbolSvg: '',\n\t\tname: 'Pauli Z',\n\t\tnameCss: 'pauli-z',\n\t\tmatrix: new Q.Matrix(\n\t\t\t[ 1, 0 ],\n\t\t\t[ 0, -1 ])\n\t}),\n\t'PHASE', new Q.Gate({\n\n\t\tsymbol: 'P',\n\t\tsymbolAmazonBraket: 'p',// !!! Double check this !!!\n\t\tsymbolSvg: '',\n\t\tname: 'Phase',\n\t\tnameCss: 'phase',\n\t\tphi: 1,\n\t\tupdateMatrix$: function( phi ){\n\n\t\t\tif( Q.isUsefulNumber( phi ) === true ) this.phi = phi\n\t\t\tthis.matrix = new Q.Matrix(\n\t\t\t\t[ 1, 0 ],\n\t\t\t\t[ 0, Q.ComplexNumber.E.power( new Q.ComplexNumber( 0, this.phi ))])\n\t\t\treturn this\n\t\t},\n\t\tapplyToQubit: function( qubit, phi ){\n\n\t\t\tif( Q.isUsefulNumber( phi ) !== true ) phi = this.phi\n\t\t\tconst matrix = new Q.Matrix(\n\t\t\t\t[ 1, 0 ],\n\t\t\t\t[ 0, Q.ComplexNumber.E.power( new Q.ComplexNumber( 0, phi ))])\n\t\t\treturn new Q.Qubit( matrix.multiply( qubit ))\n\t\t}\n\t}),\n\t'PI_8', new Q.Gate({\n\n\t\tsymbol: 'T',\n\t\tsymbolAmazonBraket: 't',// !!! Double check this !!!\n\t\tsymbolSvg: '',\n\t\tname: 'π ÷ 8',\n\t\tnameCss: 'pi8',\n\t\tmatrix: new Q.Matrix(\n\t\t\t[ 1, 0 ],\n\t\t\t[ 0, Q.ComplexNumber.E.power( new Q.ComplexNumber( 0, Math.PI / 4 )) ])\n\t}),\n\t'BLOCH', new Q.Gate({\n\n\t\tsymbol: 'B',\n\t\t//symbolAmazonBraket: Does not exist.\n\t\tsymbolSvg: '',\n\t\tname: 'Bloch sphere',\n\t\tnameCss: 'bloch',\n\t\tapplyToQubit: function( qubit ){\n\n\t\t\t// Create Bloch sphere visualizer instance.\n\t\t}\n\t}),\n\n\n\t// Operate on 2 qubits.\n\n\t'SWAP', new Q.Gate({\n\n\t\tsymbol: 'S',\n\t\tsymbolAmazonBraket: 's',// !!! Double check this !!!\n\t\tsymbolSvg: '',\n\t\tname: 'Swap',\n\t\tnameCss: 'swap',\n\t\tmatrix: new Q.Matrix(\n\t\t\t[ 1, 0, 0, 0 ],\n\t\t\t[ 0, 0, 1, 0 ],\n\t\t\t[ 0, 1, 0, 0 ],\n\t\t\t[ 0, 0, 0, 1 ])\n\t}),\n\t'SWAP1_2', new Q.Gate({\n\n\t\tsymbol: '√S',\n\t\t//symbolAmazonBraket: !!! UNKNOWN !!!\n\t\tsymbolSvg: '',\n\t\tname: '√Swap',\n\t\tnameCss: 'swap1-2',\n\t\tmatrix: new Q.Matrix(\n\t\t\t[ 1, 0, 0, 0 ],\n\t\t\t[ 0, new Q.ComplexNumber( 0.5, 0.5 ), new Q.ComplexNumber( 0.5, -0.5 ), 0 ],\n\t\t\t[ 0, new Q.ComplexNumber( 0.5, -0.5 ), new Q.ComplexNumber( 0.5, 0.5 ), 0 ],\n\t\t\t[ 0, 0, 0, 1 ])\n\t})\n\t/*\n\n\n\tAll further gates,\n\tsuch as Toffoli (CCNOT)\n\tor Fredkin (CSWAP)\n\tcan be easily constructed\n\tfrom the above gates\n\tusing Q conveniences.\n\n\n\t*/\n)\t\n\n\n\n\n// Copyright © 2019–2020, Stewart Smith. See LICENSE for details.\n\n\n\n\nQ.History = function( instance ){\n\n\tthis.instance = instance\n\tthis.entries = [[{\n\n\t\tredo: {},\n\t\tundo: [{}]\n\t}]]\n\tthis.index = 0\n\tthis.isRecording = true\n}\n\n\n\n\nObject.assign( Q.History.prototype, {\n\n\tassess: function(){\n\n\t\tconst instance = this.instance\n\t\tif( this.index > 0 ){\n\n\t\t\t/* window.dispatchEvent( new CustomEvent(\n\n\t\t\t\t'Q.History undo is capable', { detail: { instance }}\n\t\t\t)) */\n\t\t}\n\t\telse {\n\n\t\t\t/* window.dispatchEvent( new CustomEvent(\n\n\t\t\t\t'Q.History undo is depleted', { detail: { instance }}\n\t\t\t)) */\n\t\t}\n\t\tif( this.index + 1 < this.entries.length ){\n\n\t\t\t/* window.dispatchEvent( new CustomEvent(\n\n\t\t\t\t'Q.History redo is capable', { detail: { instance }}\n\t\t\t)) */\n\t\t}\n\t\telse {\n\n\t\t\t /* window.dispatchEvent( new CustomEvent(\n\n\t\t\t\t'Q.History redo is depleted', { detail: { instance }}\n\t\t\t)) */\n\t\t}\n\t\treturn this\n\t},\n\tcreateEntry$: function(){\n\t\t\n\t\tthis.entries.splice( this.index + 1 )\n\t\tthis.entries.push([])\n\t\tthis.index = this.entries.length - 1\n\t},\n\trecord$: function( entry ){\n\t\t\n\n\t\t// Are we recording this history?\n\t\t// Usually, yes.\n\t\t// But if our history state is “playback”\n\t\t// then we will NOT record this.\n\n\t\tif( this.isRecording ){\n\t\t\n\t\t\tthis.entries[ this.index ].push( entry )\n\t\t\tthis.index = this.entries.length - 1\n\t\t\tthis.assess()\n\t\t}\n\t\treturn this\n\t},\n\tstep$: function( direction ){\n\n\n\t\t// If we are stepping backward (undo)\n\t\t// we cannot go back further than index === 0\n\t\t// which we would happen if index is already 0\n\t\t// before we subtract 1.\n\t\t// Similarly, if stepping forward (redo)\n\t\t// we cannot go further than index === entries.length - 1\n\t\t// which would happen if the index is already entries.length\n\t\t// before we add 1.\n\n\t\tif(\n\t\t\t( direction < 0 && this.index < 1 ) || \n\t\t\t( direction > 0 && this.index > this.entries.length - 2 )\n\t\t) return false\n\n\n\t\t// Before we step backward (undo) or forward (redo)\n\t\t// we need to turn OFF history recording.\n\n\t\tthis.isRecording = false\n\n\t\tconst \n\t\tinstance = this.instance,\n\t\tcommand = direction < 0 ? 'undo' : 'redo'\n\n\n\t\t// If we are stepping forward (redo)\n\t\t// then we need to advance the history index\n\t\t// BEFORE we execute.\n\n\t\tif( direction > 0 ) this.index ++\n\n\n\t\t// Take this history entry, which itself is an Array.\n\t\t// It may contain several tasks.\n\t\t// Put my thing down, flip and reverse it.\n\t\t// .ti esrever dna pilf ,nwod gniht ym tuP\n\n\t\tconst entry = direction > 0 ?\n\t\t\tArray.from( this.entries[ this.index ]) :\n\t\t\tArray.from( this.entries[ this.index ]).reverse()\n\n\t\tentry\n\t\t.reduce( function( tasks, subentry, s ){\n\n\t\t\treturn tasks.concat( subentry[ command ])\n\n\t\t}, [] )\n\t\t.forEach( function( task, i ){\n\n\t\t\tif( typeof task.func === 'function' ){\n\n\t\t\t\ttask.func.apply( instance, task.args )\n\t\t\t}\n\t\t})\n\n\n\t\t// If we are stepping backward (undo)\n\t\t// then we decrement the history index\n\t\t// AFTER the execution above.\n\n\t\tif( direction < 0 ) this.index --\n\t\t\n\n\t\t// It’s now safe to turn recording back on.\n\n\t\tthis.isRecording = true\n\n\n\t\t// Emit an event so the GUI or anyone else listening\n\t\t// can know if we have available undo or redo commands\n\t\t// based on where or index is.\n\t\t\n\t\tthis.assess()\n\t\treturn true\n\t},\n\tundo$: function(){ return this.step$( -1 )},\n\tredo$: function(){ return this.step$( 1 )},\n\treport: function(){\n\n\t\tconst argsParse = function( output, entry, i ){\n\n\t\t\tif( i > 0 ) output += ', '\n\t\t\treturn output + ( typeof entry === 'object' && entry.name ? entry.name : entry )\n\t\t}\n\t\treturn this.entries.reduce( function( output, entry, i ){\n\n\t\t\toutput += '\\n\\n'+ i + ' ════════════════════════════════════════'+\n\t\t\tentry.reduce( function( output, entry, i ){\n\n\t\t\t\toutput += '\\n\\n '+ i +' ────────────────────────────────────────\\n'\n\t\t\t\tif( entry.redo ){\n\t\t\t\t\n\t\t\t\t\toutput += '\\n ⟳ Redo ── '+ entry.redo.name +' '\n\t\t\t\t\tif( entry.redo.args ) output += entry.redo.args.reduce( argsParse, '' )\n\t\t\t\t}\n\t\t\t\toutput += entry.undo.reduce( function( output, entry, i ){\n\n\t\t\t\t\toutput += '\\n ⟲ Undo '+ i +' ── '+ entry.name +' '\n\t\t\t\t\tif( entry.args ) output += entry.args.reduce( argsParse, '' )\n\t\t\t\t\treturn output\n\n\t\t\t\t}, '' )\n\n\t\t\t\treturn output\n\n\t\t\t}, '' )\n\t\t\treturn output\n\t\t\n\t\t}, 'History entry cursor: '+ this.index )\t\t\n\t}\n})\n\n\n\n\n\n// Copyright © 2019–2020, Stewart Smith. See LICENSE for details.\n\n\n\n\nQ.Circuit = function( bandwidth, timewidth ){\n\n\n\t// What number Circuit is this\n\t// that we’re attempting to make here?\n\t\n\tthis.index = Q.Circuit.index ++\n\n\n\t// How many qubits (registers) shall we use?\n\n\tif( !Q.isUsefulInteger( bandwidth )) bandwidth = 3\n\tthis.bandwidth = bandwidth\n\n\n\t// How many operations can we perform on each qubit?\n\t// Each operation counts as one moment; one clock tick.\n\n\tif( !Q.isUsefulInteger( timewidth )) timewidth = 5\n\tthis.timewidth = timewidth\n\n\n\t// We’ll start with Horizontal qubits (zeros) as inputs\n\t// but we can of course modify this after initialization.\n\n\tthis.qubits = new Array( bandwidth ).fill( Q.Qubit.HORIZONTAL )\n\n\n\t// What operations will we perform on our qubits?\n\t\n\tthis.operations = []\n\n\n\t// Does our circuit need evaluation?\n\t// Certainly, yes!\n\t// (And will again each time it is modified.)\n\n\tthis.needsEvaluation = true\n\t\n\n\t// When our circuit is evaluated \n\t// we store those results in this array.\n\n\tthis.results = []\n\tthis.matrix = null\n\n\n\t// Undo / Redo history.\n\n\tthis.history = new Q.History( this )\n}\n\n\n\n\nObject.assign( Q.Circuit, {\n\n\tindex: 0,\n\thelp: function(){ return Q.help( this )},\n\tconstants: {},\n\tcreateConstant: Q.createConstant,\n\tcreateConstants: Q.createConstants,\n\n\n\tfromText: function( text ){\n\n\n\t\t// This is a quick way to enable `fromText()`\n\t\t// to return a default new Q.Circuit().\n\n\t\tif( text === undefined ) return new Q.Circuit()\n\n\n\t\t// Is this a String Template -- as opposed to a regular String?\n\t\t// If so, let’s convert it to a regular String.\n\t\t// Yes, this maintains the line breaks.\n\n\t\tif( text.raw !== undefined ) text = ''+text.raw\t\t\n\t\treturn Q.Circuit.fromTableTransposed( \n\n\t\t\ttext\n\t\t\t.trim()\n\t\t\t.split( /\\r?\\n/ )\n\t\t\t.filter( function( item ){ return item.length })\n\t\t\t.map( function( item, r ){\n\n\t\t\t\treturn item\n\t\t\t\t.trim()\n\t\t\t\t.split( /[-+\\s+=+]/ )\n\t\t\t\t.filter( function( item ){ return item.length })\n\t\t\t\t.map( function( item, m ){\n\n\t\t\t\t\t//const matches = item.match( /(^\\w+)(#(\\w+))*(\\.(\\d+))*/ )\n\t\t\t\t\tconst matches = item.match( /(^\\w+)(\\.(\\w+))*(#(\\d+))*/ )\n\t\t\t\t\treturn {\n\t\t\t\t\t\t\n\t\t\t\t\t\tgateSymbol: matches[ 1 ],\n\t\t\t\t\t\toperationMomentId: matches[ 3 ],\n\t\t\t\t\t\tmappingIndex: +matches[ 5 ]\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t})\n\t\t)\n\t},\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n// Working out a new syntax here... Patience please!\n\n\n\tfromText2: function( text ){\n\n\n\t\ttext = `\n\t\t\tH C C\n\t\t\tI C1 C1\n\t\t\tI X1 S1\n\t\t\tI X1 S1`\n\n\n\t\t// This is a quick way to enable `fromText()`\n\t\t// to return a default new Q.Circuit().\n\n\t\tif( text === undefined ) return new Q.Circuit()\n\n\n\t\t// Is this a String Template -- as opposed to a regular String?\n\t\t// If so, let’s convert it to a regular String.\n\t\t// Yes, this maintains the line breaks.\n\n\t\tif( text.raw !== undefined ) text = ''+text.raw\n\n\n\n\t\ttext\n\t\t.trim()\n\t\t.split( /\\r?\\n/ )\n\t\t.filter( function( item ){ return item.length })\n\t\t.map( function( item, r ){\n\n\t\t\treturn item\n\t\t\t.trim()\n\t\t\t.split( /[-+\\s+=+]/ )\n\t\t\t.filter( function( item ){ return item.length })\n\t\t\t.map( function( item, m ){\n\n\t\t\t\t// +++++++++++++++++++++++\n\t\t\t\t// need to map LETTER[] optional NUMBER ]\n\n\t\t\t\tconst matches = item.match( /(^\\w+)(\\.(\\w+))*(#(\\d+))*/ )\n\n\t\t\t\t//const matches = item.match( /(^\\w+)(#(\\w+))*(\\.(\\d+))*/ )\n\t\t\t\t// const matches = item.match( /(^\\w+)(\\.(\\w+))*(#(\\d+))*/ )\n\t\t\t\t// return {\n\t\t\t\t\t\n\t\t\t\t// \tgateSymbol: matches[ 1 ],\n\t\t\t\t// \toperationMomentId: matches[ 3 ],\n\t\t\t\t// \tmappingIndex: +matches[ 5 ]\n\t\t\t\t// }\n\t\t\t})\n\t\t})\n\n\t},\n\n\n\n//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\n\n\n\n\n\n\n\n\n\n\n\tfromTableTransposed: function( table ){\n\n\t\tconst\n\t\tbandwidth = table.length,\n\t\ttimewidth = table.reduce( function( max, moments ){\n\n\t\t\treturn Math.max( max, moments.length )\n\t\t\n\t\t}, 0 ),\n\t\tcircuit = new Q.Circuit( bandwidth, timewidth )\n\t\t\n\t\tcircuit.bandwidth = bandwidth\n\t\tcircuit.timewidth = timewidth\n\t\tfor( let r = 0; r < bandwidth; r ++ ){\n\n\t\t\tconst registerIndex = r + 1\n\t\t\tfor( let m = 0; m < timewidth; m ++ ){\n\n\t\t\t\tconst \n\t\t\t\tmomentIndex = m + 1,\n\t\t\t\toperation = table[ r ][ m ]\n\n\t\t\t\tlet siblingHasBeenFound = false\n\t\t\t\tfor( let s = 0; s < r; s ++ ){\n\n\t\t\t\t\tconst sibling = table[ s ][ m ]\n\t\t\t\t\tif( operation.gateSymbol === sibling.gateSymbol &&\n\t\t\t\t\t\toperation.operationMomentId === sibling.operationMomentId &&\n\t\t\t\t\t\tQ.isUsefulInteger( operation.mappingIndex ) &&\n\t\t\t\t\t\tQ.isUsefulInteger( sibling.mappingIndex ) &&\n\t\t\t\t\t\toperation.mappingIndex !== sibling.mappingIndex ){\n\n\n\t\t\t\t\t\t// We’ve found a sibling !\n\n\t\t\t\t\t\tconst operationsIndex = circuit.operations.findIndex( function( operation ){\n\n\t\t\t\t\t\t\treturn (\n\n\t\t\t\t\t\t\t\toperation.momentIndex === momentIndex &&\n\t\t\t\t\t\t\t\toperation.registerIndices.includes( s + 1 )\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t})\n\t\t\t\t\t\t// console.log( 'operationsIndex?', operationsIndex )\n\t\t\t\t\t\tcircuit.operations[ operationsIndex ].registerIndices[ operation.mappingIndex ] = registerIndex\n\t\t\t\t\t\tcircuit.operations[ operationsIndex ].isControlled = operation.gateSymbol != '*'// Q.Gate.SWAP.\n\t\t\t\t\t\tsiblingHasBeenFound = true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif( siblingHasBeenFound === false && operation.gateSymbol !== 'I' ){\n\n\t\t\t\t\tconst \n\t\t\t\t\tgate = Q.Gate.findBySymbol( operation.gateSymbol ),\n\t\t\t\t\tregisterIndices = []\t\t\t\t\t\n\n\t\t\t\t\tif( Q.isUsefulInteger( operation.mappingIndex )){\n\t\t\t\t\t\n\t\t\t\t\t\tregisterIndices[ operation.mappingIndex ] = registerIndex\n\t\t\t\t\t}\n\t\t\t\t\telse registerIndices[ 0 ] = registerIndex\t\t\t\t\t\n\t\t\t\t\tcircuit.operations.push({\n\n\t\t\t\t\t\tgate,\n\t\t\t\t\t\tmomentIndex,\n\t\t\t\t\t\tregisterIndices,\n\t\t\t\t\t\tisControlled: false,\n\t\t\t\t\t\toperationMomentId: operation.operationMomentId\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tcircuit.sort$()\n\t\treturn circuit\n\t},\n\n\n\n\n\tcontrolled: function( U ){\n\t\t\n\n\t\t// we should really just replace this with a nice Matrix.copy({}) command!!!!\n\n\t\t// console.log( 'U?', U )\n\n\t\tconst \n\t\tsize = U.getWidth(),\n\t\tresult = Q.Matrix.createIdentity( size * 2 )\n\n\t\t// console.log( 'U', U.toTsv() )\n\t\t// console.log( 'size', size )\n\t\t// console.log( 'result', result.toTsv() )\n\t\t\n\t\tfor( let x = 0; x < size; x ++ ){\n\t\t\t\n\t\t\tfor( let y = 0; y < size; y ++ ){\n\t\t\t\t\n\t\t\t\tconst v = U.read( x, y )\n\t\t\t\t// console.log( `value at ${x}, ${y}`, v )\n\t\t\t\tresult.write$( x + size, y + size, v )\n\t\t\t}\n\t\t}\n\t\treturn result\n\t},\n\t\n\n\n\t// Return transformation over entire nqubit register that applies U to\n\t// specified qubits (in order given).\n\t// Algorithm from Lee Spector's \"Automatic Quantum Computer Programming\"\n\t// Page 21 in the 2004 PDF?\n\t// http://148.206.53.84/tesiuami/S_pdfs/AUTOMATIC%20QUANTUM%20COMPUTER%20PROGRAMMING.pdf\n\n\texpandMatrix: function( circuitBandwidth, U, qubitIndices ){\n\t\t\n\t\t// console.log( 'EXPANDING THE MATRIX...' )\n\t\t// console.log( 'this one: U', U.toTsv())\n\n\t\tconst _qubits = []\n\t\tconst n = Math.pow( 2, circuitBandwidth )\n\t\t\n\n\t\t// console.log( 'qubitIndices used by this operation:', qubitIndices )\n\t\t// console.log( 'qubits before slice', qubitIndices )\n\t\t// qubitIndices = qubitIndices.slice( 0 )\n\t\t// console.log( 'qubits AFTER slice', qubitIndices )\n\t\t\n\n\t\t\n\n\t\tfor( let i = 0; i < qubitIndices.length; i ++ ){\n\t\t\t\n\t\t\t//qubitIndices[ i ] = ( circuitBandwidth - 1 ) - qubitIndices[ i ]\n\t\t\tqubitIndices[ i ] = ( circuitBandwidth - 0 ) - qubitIndices[ i ]\n\t\t}\n\t\t// console.log( 'qubits AFTER manipulation', qubitIndices )\n\n\t\t\n\t\tqubitIndices.reverse()\n\t\tfor( let i = 0; i < circuitBandwidth; i ++ ){\n\t\t\t\n\t\t\tif( qubitIndices.indexOf( i ) == -1 ){\n\t\t\t\t\n\t\t\t\t_qubits.push( i )\n\t\t\t}\n\t\t}\n\n\n\t\t// console.log( 'qubitIndices vs _qubits:' )\n\t\t// console.log( 'qubitIndices', qubitIndices )\n\t\t// console.log( '_qubits', _qubits )\n\t\t\n\n\n\t\tconst result = new Q.Matrix.createZero( n )\n\n\n\t\t// const X = numeric.rep([n, n], 0);\n\t\t// const Y = numeric.rep([n, n], 0);\n\t\t\n\n\t\tlet i = n\n\t\twhile( i -- ){\n\t\t\t\n\t\t\tlet j = n\n\t\t\twhile( j -- ){\n\t\t\t\t\n\t\t\t\tlet\n\t\t\t\tbitsEqual = true,\n\t\t\t\tk = _qubits.length\n\t\t\t\t\n\t\t\t\twhile( k -- ){\n\t\t\t\t\t\n\t\t\t\t\tif(( i & ( 1 << _qubits[ k ])) != ( j & ( 1 << _qubits[ k ]))){\n\t\t\t\t\t\t\n\t\t\t\t\t\tbitsEqual = false\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif( bitsEqual ){\n\n\t\t\t\t\t// console.log( 'bits ARE equal' )\n\t\t\t\t\t\n\t\t\t\t\tlet\n\t\t\t\t\tistar = 0,\n\t\t\t\t\tjstar = 0,\n\t\t\t\t\tk = qubitIndices.length\n\t\t\t\t\t\n\t\t\t\t\twhile( k -- ){\n\t\t\t\t\t\t\n\t\t\t\t\t\tconst q = qubitIndices[ k ]\n\t\t\t\t\t\tistar |= (( i & ( 1 << q )) >> q ) << k\n\t\t\t\t\t\tjstar |= (( j & ( 1 << q )) >> q ) << k\n\t\t\t\t\t}\n\n\n\t\t\t\t\t//console.log( 'U.read( istar, jstar )', U.read( istar, jstar ).toText() )\n\n\t\t\t\t\t// console.log( 'before write$', result.toTsv())\n\n\t\t\t\t\t// console.log( 'U.read at ', istar, jstar, '=', U.read( istar, jstar ).toText())\n\t\t\t\t\tresult.write$( i, j, U.read( istar, jstar ))\n\n\t\t\t\t\t// console.log( 'after write$', result.toTsv())\n\t\t\t\t\t\n\t\t\t\t\t// X[i][j] = U.x[ istar ][ jstar ]\n\t\t\t\t\t// Y[i][j] = U.y[ istar ][ jstar ]\n\t\t\t\t}\n\t\t\t\t// else console.log('bits NOT equal')\n\t\t\t}\n\t\t}\n\t\t//return new numeric.T(X, Y);\n\n\t\t// console.log( 'expanded matrix to:', result.toTsv() )\n\t\treturn result\n\t},\n\n\n\n\n\tevaluate: function( circuit ){\n\n\n\t\t// console.log( circuit.toDiagram() )\n\n\n\t\t/* window.dispatchEvent( new CustomEvent( \n\n\t\t\t'Q.Circuit.evaluate began', { \n\n\t\t\t\tdetail: { circuit }\n\t\t\t}\n\t\t)) */\n\n\n\t\t// Our circuit’s operations must be in the correct order\n\t\t// before we attempt to step through them!\n\n\t\tcircuit.sort$()\n\n\n\n\t\t// Create a new matrix (or more precisely, a vector)\n\t\t// that is a 1 followed by all zeros.\n\t\t//\n\t\t// ┌ ┐\n\t\t// │ 1 │\n\t\t// │ 0 │\n\t\t// │ 0 │\n\t\t// │ . │\n\t\t// │ . │\n\t\t// │ . │\n\t\t// └ ┘\n\n\t\tconst state = new Q.Matrix( 1, Math.pow( 2, circuit.bandwidth ))\n\t\tstate.write$( 0, 0, 1 )\n\n\n\n\n\t\t// Create a state matrix from this circuit’s input qubits.\n\t\t\n\t\t// const state2 = circuit.qubits.reduce( function( state, qubit, i ){\n\n\t\t// \tif( i > 0 ) return state.multiplyTensor( qubit )\n\t\t// \telse return state\n\n\t\t// }, circuit.qubits[ 0 ])\n\t\t// console.log( 'Initial state', state2.toTsv() )\n\t\t// console.log( 'multiplied', state2.multiplyTensor( state ).toTsv() )\n\t\t\n\n\n\n\n\t\tconst operationsTotal = circuit.operations.length\n\t\tlet operationsCompleted = 0\n\t\tlet matrix = circuit.operations.reduce( function( state, operation, i ){\n\n\n\n\t\t\tlet U\n\t\t\tif( operation.registerIndices.length < Infinity ){\n\t\t\t\n\t\t\t\tif( operation.isControlled ){\n\t\t\t\t//if( operation.registerIndices.length > 1 ){\n\n\t\t\t\t\t// operation.gate = Q.Gate.PAULI_X\n\t\t\t\t\t// why the F was this hardcoded in there?? what was i thinking?!\n\t\t\t\t\t// OH I KNOW !\n\t\t\t\t\t// that was from back when i represented this as \"C\" -- its own gate\n\t\t\t\t\t// rather than an X with multiple registers.\n\t\t\t\t\t// so now no need for this \"if\" block at all.\n\t\t\t\t\t// will remove in a few cycles.\n\t\t\t\t}\n\t\t\t\tU = operation.gate.matrix\n\t\t\t} \n\t\t\telse {\n\t\t\t\n\t\t\t\t// This is for Quantum Fourier Transforms (QFT). \n\t\t\t\t// Will have to come back to this at a later date!\n\t\t\t}\t\t\t\n\t\t\t// console.log( operation.gate.name, U.toTsv() )\n\n\n\n\n\n\t\t\t// Yikes. May need to separate registerIndices in to controls[] and targets[] ??\n\t\t\t// Works for now tho..... \n\n\t\t\tfor( let j = 0; j < operation.registerIndices.length - 1; j ++ ){\n\t\t\t\n\t\t\t\tU = Q.Circuit.controlled( U )\n\t\t\t\t// console.log( 'qubitIndex #', j, 'U = Q.Circuit.controlled( U )', U.toTsv() )\n\t\t\t}\n\n\n\t\t\t// We need to send a COPY of the registerIndices Array\n\t\t\t// to .expandMatrix()\n\t\t\t// otherwise it *may* modify the actual registerIndices Array\n\t\t\t// and wow -- tracking down that bug was painful!\n\n\t\t\tconst registerIndices = operation.registerIndices.slice()\n\n\n\t\t\tstate = Q.Circuit.expandMatrix( \n\n\t\t\t\tcircuit.bandwidth, \n\t\t\t\tU, \n\t\t\t\tregisterIndices\n\n\t\t\t).multiply( state )\n\n\n\n\n\t\t\toperationsCompleted ++\n\t\t\tconst progress = operationsCompleted / operationsTotal\n\n\n\t\t\t/* window.dispatchEvent( new CustomEvent( 'Q.Circuit.evaluate progressed', { detail: {\n\n\t\t\t\tcircuit,\n\t\t\t\tprogress,\n\t\t\t\toperationsCompleted,\n\t\t\t\toperationsTotal,\n\t\t\t\tmomentIndex: operation.momentIndex,\n\t\t\t\tregisterIndices: operation.registerIndices,\n\t\t\t\tgate: operation.gate.name,\n\t\t\t\tstate\n\n\t\t\t}})) */\n\n\n\t\t\t// console.log( `\\n\\nProgress ... ${ Math.round( operationsCompleted / operationsTotal * 100 )}%`)\n\t\t\t// console.log( 'Moment .....', operation.momentIndex )\n\t\t\t// console.log( 'Registers ..', JSON.stringify( operation.registerIndices ))\n\t\t\t// console.log( 'Gate .......', operation.gate.name )\n\t\t\t// console.log( 'Intermediate result:', state.toTsv() )\n\t\t\t// console.log( '\\n' )\n\t\t\t\n\n\t\t\treturn state\n\t\t\t\n\t\t}, state )\n\n\n\t\t// console.log( 'result matrix', matrix.toTsv() )\n\t\n\n\n\n\t\tconst outcomes = matrix.rows.reduce( function( outcomes, row, i ){\n\n\t\t\toutcomes.push({\n\n\t\t\t\tstate: '|'+ parseInt( i, 10 ).toString( 2 ).padStart( circuit.bandwidth, '0' ) +'⟩',\n\t\t\t\tprobability: Math.pow( row[ 0 ].absolute(), 2 )\n\t\t\t})\n\t\t\treturn outcomes\n\t\t\n\t\t}, [] )\n\n\n\n\t\tcircuit.needsEvaluation = false\n\t\tcircuit.matrix = matrix\n\t\tcircuit.results = outcomes\n\n\n\n\t\t/* window.dispatchEvent( new CustomEvent( 'Q.Circuit.evaluate completed', { detail: {\n\t\t// circuit.dispatchEvent( new CustomEvent( 'evaluation complete', { detail: {\n\n\t\t\tcircuit,\n\t\t\tresults: outcomes\n\n\t\t}})) */\n\n\n\n\t\t\n\n\t\treturn matrix\n\t}\n})\n\n\n\n\n\n\n\nObject.assign( Q.Circuit.prototype, {\n\n\tclone: function(){\n\n\t\tconst \n\t\toriginal = this,\n\t\tclone = original.copy()\n\n\t\tclone.qubits = original.qubits.slice()\n\t\tclone.results = original.results.slice()\n\t\tclone.needsEvaluation = original.needsEvaluation\n\t\t\n\t\treturn clone\n\t},\n\tevaluate$: function(){\n\n\t\tQ.Circuit.evaluate( this )\n\t\treturn this\n\t},\n\treport$: function( length ){\n\n\t\tif( this.needsEvaluation ) this.evaluate$()\n\t\tif( !Q.isUsefulInteger( length )) length = 20\n\t\t\n\t\tconst \n\t\tcircuit = this,\n\t\ttext = this.results.reduce( function( text, outcome, i ){\n\n\t\t\tconst\n\t\t\tprobabilityPositive = Math.round( outcome.probability * length ),\n\t\t\tprobabilityNegative = length - probabilityPositive\n\n\t\t\treturn text +'\\n'\n\t\t\t\t+ ( i + 1 ).toString().padStart( Math.ceil( Math.log10( Math.pow( 2, circuit.qubits.length ))), ' ' ) +' '\n\t\t\t\t+ outcome.state +' '\n\t\t\t\t+ ''.padStart( probabilityPositive, '█' )\n\t\t\t\t+ ''.padStart( probabilityNegative, '░' )\n\t\t\t\t+ Q.round( Math.round( 100 * outcome.probability ), 8 ).toString().padStart( 4, ' ' ) +'% chance'\n\n\t\t}, '' ) + '\\n'\n\t\treturn text\n\t},\n\ttry$: function(){\n\n\t\tif( this.needsEvaluation ) this.evaluate$()\n\n\t\t\n\t\t// We need to “stack” our probabilities from 0..1.\n\t\t\n\t\tconst outcomesStacked = new Array( this.results.length )\n\t\tthis.results.reduce( function( sum, outcome, i ){\n\n\t\t\tsum += outcome.probability\n\t\t\toutcomesStacked[ i ] = sum\n\t\t\treturn sum\n\t\t\n\t\t}, 0 )\n\t\t\n\n\t\t// Now we can pick a random number\n\t\t// and return the first outcome \n\t\t// with a probability equal to or greater than\n\t\t// that random number. \n\t\t\n\t\tconst \n\t\trandomNumber = Math.random(),\n\t\trandomIndex = outcomesStacked.findIndex( function( index ){\n\n\t\t\treturn randomNumber <= index\n\t\t})\n\t\t\n\n\t\t// Output that to the console\n\t\t// but return the random index\n\t\t// so we can pipe that to something else\n\t\t// should we want to :)\n\t\t\n\t\t// console.log( this.outcomes[ randomIndex ].state )\n\t\treturn randomIndex\n\t},\n\n\n\n\n\t ////////////////\n\t // //\n\t // Output //\n\t // //\n\t////////////////\n\n\n\t// This is absolutely required by toTable.\n\n\tsort$: function(){\n\n\n\t\t// Sort this circuit’s operations\n\t\t// primarily by momentIndex,\n\t\t// then by the first registerIndex.\n\n\t\tthis.operations.sort( function( a, b ){\n\n\t\t\tif( a.momentIndex === b.momentIndex ){\n\n\n\t\t\t\t// Note that we are NOT sorting registerIndices here!\n\t\t\t\t// We are merely asking which set of indices contain\n\t\t\t\t// the lowest register index.\n\t\t\t\t// If we instead sorted the registerIndices \n\t\t\t\t// we could confuse which qubit is the controller\n\t\t\t\t// and which is the controlled!\n\n\t\t\t\treturn Math.min( ...a.registerIndices ) - Math.min( b.registerIndices )\n\t\t\t}\n\t\t\telse {\n\n\t\t\t\treturn a.momentIndex - b.momentIndex\n\t\t\t}\n\t\t})\n\t\treturn this\n\t},\n\t\n\n\n\n\n\n\t ///////////////////\n\t // //\n\t // Exporters //\n\t // //\n\t///////////////////\n\n\n\t// Many export functions rely on toTable\n\t// and toTable itself absolutely relies on \n\t// a circuit’s operations to be SORTED correctly.\n\t// We could force circuit.sort$() here,\n\t// but then toTable would become toTable$\n\t// and every exporter that relies on it would \n\t// also become destructive.\n\n\ttoTable: function(){\n\n\t\tconst \n\t\ttable = new Array( this.timewidth ),\n\t\tcircuit = this\n\n\n\t\t// Sure, this is equal to table.length\n\t\t// but isn’t legibility and convenience everything?\n\n\t\ttable.timewidth = this.timewidth\n\t\t\n\n\t\t// Similarly, this should be equal to table[ 0 ].length\n\t\t// or really table[ i >= 0; i < table.length ].length,\n\t\t// but again, lowest cognitive hurdle is key ;)\n\n\t\ttable.bandwidth = this.bandwidth\n\t\t\n\n\t\t// First, let’s establish a “blank” table\n\t\t// that contains an identity operation\n\t\t// for each register during each moment.\n\n\t\ttable.fill( 0 ).forEach( function( element, index, array ){\n\n\t\t\tconst operations = new Array( circuit.bandwidth )\n\t\t\toperations.fill( 0 ).forEach( function( element, index, array ){\n\n\t\t\t\tarray[ index ] = {\n\n\t\t\t\t\tsymbol: 'I',\n\t\t\t\t\tsymbolDisplay: 'I',\n\t\t\t\t\tname: 'Identity',\n\t\t\t\t\tnameCss: 'identity',\n\t\t\t\t\tgateInputIndex: 0,\n\t\t\t\t\tbandwidth: 0,\n\t\t\t\t\tthisGateAmongMultiQubitGatesIndex: 0,\n\t\t\t\t\taSiblingIsAbove: false,\n\t\t\t\t\taSiblingIsBelow: false\n\t\t\t\t}\n\t\t\t})\n\t\t\tarray[ index ] = operations\n\t\t})\n\n\n\t\t// Now iterate through the circuit’s operations list\n\t\t// and note those operations in our table.\n\t\t// NOTE: This relies on operations being pre-sorted with .sort$()\n\t\t// prior to the .toTable() call.\n\t\t\n\t\tlet \n\t\tmomentIndex = 1,\n\t\tmultiRegisterOperationIndex = 0,\n\t\tgateTypesUsedThisMoment = {}\n\n\t\tthis.operations.forEach( function( operation, operationIndex, operations ){\n\n\n\t\t\t// We need to keep track of\n\t\t\t// how many multi-register operations\n\t\t\t// occur during this moment.\n\n\t\t\tif( momentIndex !== operation.momentIndex ){\n\n\t\t\t\ttable[ momentIndex ].gateTypesUsedThisMoment = gateTypesUsedThisMoment\n\t\t\t\tmomentIndex = operation.momentIndex\n\t\t\t\tmultiRegisterOperationIndex = 0\n\t\t\t\tgateTypesUsedThisMoment = {}\n\t\t\t}\n\t\t\tif( operation.registerIndices.length > 1 ){\n\n\t\t\t\ttable[ momentIndex - 1 ].multiRegisterOperationIndex = multiRegisterOperationIndex\n\t\t\t\tmultiRegisterOperationIndex ++\n\t\t\t}\n\t\t\tif( gateTypesUsedThisMoment[ operation.gate.symbol ] === undefined ){\n\n\t\t\t\tgateTypesUsedThisMoment[ operation.gate.symbol ] = 1\n\t\t\t}\n\t\t\telse gateTypesUsedThisMoment[ operation.gate.symbol ] ++\n\n\n\t\t\t// By default, an operation’s CSS name\n\t\t\t// is its regular name, all lowercase, \n\t\t\t// with all spaces replaced by hyphens.\n\n\t\t\tlet nameCss = operation.gate.name.toLowerCase().replace( /\\s+/g, '-' )\n\n\t\t\t\n\t\t\toperation.registerIndices.forEach( function( registerIndex, indexAmongSiblings ){\n\n\t\t\t\tlet isMultiRegisterOperation = false\n\t\t\t\tif( operation.registerIndices.length > 1 ){\n\n\t\t\t\t\tisMultiRegisterOperation = true\n\t\t\t\t\tif(\tindexAmongSiblings === operation.registerIndices.length - 1 ){\n\n\t\t\t\t\t\tnameCss = 'target'\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\n\t\t\t\t\t\tnameCss = 'control'\n\t\t\t\t\t}\n\n\t\t\t\t\t// May need to re-visit the code above in consideration of SWAPs.\n\n\t\t\t\t}\n\t\t\t\ttable[ operation.momentIndex - 1 ][ registerIndex - 1 ] = {\n\n\t\t\t\t\tsymbol: operation.gate.symbol,\n\t\t\t\t\tsymbolDisplay: operation.gate.symbol,\n\t\t\t\t\tname: operation.gate.name,\n\t\t\t\t\tnameCss,\n\t\t\t\t\toperationIndex,\n\t\t\t\t\tmomentIndex: operation.momentIndex,\n\t\t\t\t\tregisterIndex,\n\t\t\t\t\tisMultiRegisterOperation,\n\t\t\t\t\tmultiRegisterOperationIndex,\n\t\t\t\t\tgatesOfThisTypeNow: gateTypesUsedThisMoment[ operation.gate.symbol ],\n\t\t\t\t\tindexAmongSiblings,\n\t\t\t\t\tsiblingExistsAbove: Math.min( ...operation.registerIndices ) < registerIndex,\n\t\t\t\t\tsiblingExistsBelow: Math.max( ...operation.registerIndices ) > registerIndex\n\t\t\t\t}\n\t\t\t})\n\n/*\n\n\n++++++++++++++++++++++\n\nNon-fatal problem to solve here:\n\nPreviously we were concerned with “gates of this type used this moment”\nwhen we were thinking about CNOT as its own special gate.\nBut now that we treat CNOT as just connected X gates,\nwe now have situations \nwhere a moment can have one “CNOT” but also a stand-alone X gate\nand toTable will symbol the “CNOT” as X.0 \n(never X.1, because it’s the only multi-register gate that moment)\nbut still uses the symbol X.0 instead of just X\nbecause there’s another stand-alone X there tripping the logic!!!\n\n\n\n\n\n*/\n\n\n\t\t\t// if( operationIndex === operations.length - 1 ){\n\t\t\t\t\n\t\t\t\ttable[ momentIndex - 1 ].gateTypesUsedThisMoment = gateTypesUsedThisMoment\n\t\t\t// }\n\t\t})\n\n\n\n\n\n\n\n\n\n\n\n\t\ttable.forEach( function( moment, m ){\n\n\t\t\tmoment.forEach( function( operation, o ){\n\n\t\t\t\tif( operation.isMultiRegisterOperation ){\n\n\t\t\t\t\tif( moment.gateTypesUsedThisMoment[ operation.symbol ] > 1 ){\n\n\t\t\t\t\t\toperation.symbolDisplay = operation.symbol +'.'+ ( operation.gatesOfThisTypeNow - 1 )\n\t\t\t\t\t}\n\t\t\t\t\toperation.symbolDisplay += '#'+ operation.indexAmongSiblings\n\t\t\t\t}\n\t\t\t})\n\t\t})\n\n\n\t\t// Now we can easily read down each moment\n\t\t// and establish the moment’s character width.\n\t\t// Very useful for text-based diagrams ;)\n\n\t\ttable.forEach( function( moment ){\n\n\t\t\tconst maximumWidth = moment.reduce( function( maximumWidth, operation ){\n\n\t\t\t\treturn Math.max( maximumWidth, operation.symbolDisplay.length )\n\t\t\t\n\t\t\t}, 1 )\n\t\t\tmoment.maximumCharacterWidth = maximumWidth\n\t\t})\n\n\n\t\t// We can also do this for the table as a whole.\n\t\t\n\t\ttable.maximumCharacterWidth = table.reduce( function( maximumWidth, moment ){\n\n\t\t\treturn Math.max( maximumWidth, moment.maximumCharacterWidth )\n\t\t\n\t\t}, 1 )\n\n\n\t\t// I think we’re done here.\n\n\t\treturn table\n\t},\n\ttoText: function( makeAllMomentsEqualWidth ){\n\n\t\t`\n\t\tCreate a text representation of this circuit\n\t\tusing only common characters,\n\t\tie. no fancy box-drawing characters.\n\t\tThis is the complement of Circuit.fromText()\n\t\t`\n\n\t\tconst \n\t\ttable = this.toTable(),\n\t\toutput = new Array( table.bandwidth ).fill( '' )\n\n\t\tfor( let x = 0; x < table.timewidth; x ++ ){\n\n\t\t\tfor( let y = 0; y < table.bandwidth; y ++ ){\n\n\t\t\t\tlet cellString = table[ x ][ y ].symbolDisplay.padEnd( table[ x ].maximumCharacterWidth, '-' )\n\t\t\t\tif( makeAllMomentsEqualWidth && x < table.timewidth - 1 ){\n\n\t\t\t\t\tcellString = table[ x ][ y ].symbolDisplay.padEnd( table.maximumCharacterWidth, '-' )\n\t\t\t\t}\n\t\t\t\tif( x > 0 ) cellString = '-'+ cellString\n\t\t\t\toutput[ y ] += cellString\n\t\t\t}\n\t\t}\n\t\treturn '\\n'+ output.join( '\\n' )\n\t\t// return output.join( '\\n' )\n\t},\n\ttoDiagram: function( makeAllMomentsEqualWidth ){\n\n\t\t`\n\t\tCreate a text representation of this circuit\n\t\tusing fancy box-drawing characters.\n\t\t`\n\n\t\tconst \n\t\tscope = this,\n\t\ttable = this.toTable(),\n\t\toutput = new Array( table.bandwidth * 3 + 1 ).fill( '' )\n\n\t\toutput[ 0 ] = ' '\n\t\tscope.qubits.forEach( function( qubit, q ){\n\n\t\t\tconst y3 = q * 3\n\t\t\toutput[ y3 + 1 ] += ' '\n\t\t\toutput[ y3 + 2 ] += 'r'+ ( q + 1 ) +' |'+ qubit.beta.toText().trim() +'⟩─'\n\t\t\toutput[ y3 + 3 ] += ' '\n\t\t})\n\t\tfor( let x = 0; x < table.timewidth; x ++ ){\n\n\t\t\tconst padToLength = makeAllMomentsEqualWidth\n\t\t\t\t? table.maximumCharacterWidth\n\t\t\t\t: table[ x ].maximumCharacterWidth\n\n\t\t\toutput[ 0 ] += Q.centerText( 'm'+ ( x + 1 ), padToLength + 4 )\n\t\t\tfor( let y = 0; y < table.bandwidth; y ++ ){\n\n\t\t\t\tlet \n\t\t\t\toperation = table[ x ][ y ],\n\t\t\t\tfirst = '',\n\t\t\t\tsecond = '',\n\t\t\t\tthird = ''\n\n\t\t\t\tif( operation.symbol === 'I' ){\n\n\t\t\t\t\tfirst += ' '\n\t\t\t\t\tsecond += '──'\n\t\t\t\t\tthird += ' '\n\t\t\t\t\t\n\t\t\t\t\tfirst += ' '.padEnd( padToLength )\n\t\t\t\t\tsecond += Q.centerText( '○', padToLength, '─' )\n\t\t\t\t\tthird += ' '.padEnd( padToLength )\n\n\t\t\t\t\tfirst += ' '\n\t\t\t\t\tif( x < table.timewidth - 1 ) second += '──'\n\t\t\t\t\telse second += ' '\n\t\t\t\t\tthird += ' '\n\t\t\t\t}\n\t\t\t\telse {\n\n\t\t\t\t\tif( operation.isMultiRegisterOperation ){\n\n\t\t\t\t\t\tfirst += '╭─'\n\t\t\t\t\t\tthird += '╰─'\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\n\t\t\t\t\t\tfirst += '┌─'\n\t\t\t\t\t\tthird += '└─'\n\t\t\t\t\t}\n\t\t\t\t\tsecond += '┤ '\n\t\t\t\t\t\n\t\t\t\t\tfirst += '─'.padEnd( padToLength, '─' )\n\t\t\t\t\tsecond += Q.centerText( operation.symbolDisplay, padToLength )\n\t\t\t\t\tthird += '─'.padEnd( padToLength, '─' )\n\n\n\t\t\t\t\tif( operation.isMultiRegisterOperation ){\n\n\t\t\t\t\t\tfirst += '─╮'\n\t\t\t\t\t\tthird += '─╯'\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\n\t\t\t\t\t\tfirst += '─┐'\n\t\t\t\t\t\tthird += '─┘'\n\t\t\t\t\t}\n\t\t\t\t\tsecond += x < table.timewidth - 1 ? ' ├' : ' │'\n\n\t\t\t\t\tif( operation.isMultiRegisterOperation ){\n\n\t\t\t\t\t\tlet n = ( operation.multiRegisterOperationIndex * 2 ) % ( table[ x ].maximumCharacterWidth + 1 ) + 1\n\t\t\t\t\t\tif( operation.siblingExistsAbove ){\t\t\t\t\t\t\n\n\t\t\t\t\t\t\tfirst = first.substring( 0, n ) +'┴'+ first.substring( n + 1 )\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif( operation.siblingExistsBelow ){\n\n\t\t\t\t\t\t\tthird = third.substring( 0, n ) +'┬'+ third.substring( n + 1 )\n\t\t\t\t\t\t}\t\t\t\t\t\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst y3 = y * 3\t\t\t\t\n\t\t\t\toutput[ y3 + 1 ] += first\n\t\t\t\toutput[ y3 + 2 ] += second\n\t\t\t\toutput[ y3 + 3 ] += third\n\t\t\t}\n\t\t}\n\t\treturn '\\n'+ output.join( '\\n' )\n\t},\n\n\n\n\n\t// Oh yes my friends... WebGL is coming!\n\n\ttoShader: function(){\n\n\t},\n\ttoGoogleCirq: function(){\n/*\n\n\ncirq.GridQubit(4,5)\n\nhttps://cirq.readthedocs.io/en/stable/tutorial.html\n\n*/\n\t\tconst header = `import cirq`\n\n\t\treturn headers\n\t},\n\ttoAmazonBraket: function(){\n\n\t\tconst header = `import boto3\nfrom braket.aws import AwsQuantumSimulator, AwsQuantumSimulatorArns\nfrom braket.circuits import Circuit\n\naws_account_id = boto3.client(\"sts\").get_caller_identity()[\"Account\"]\ndevice = AwsQuantumSimulator(AwsQuantumSimulatorArns.QS1)\ns3_folder = (f\"braket-output-{aws_account_id}\", \"folder-name\")\n\n`\n\t\t//`qjs_circuit = Circuit().h(0).cnot(0,1)`\n\t\tlet circuit = this.operations.reduce( function( string, operation ){\n\n\t\t\tlet awsGate = operation.gate.AmazonBraketName !== undefined ?\n\t\t\t\toperation.gate.AmazonBraketName :\n\t\t\t\toperation.gate.symbol.substr( 0, 1 ).toLowerCase()\n\n\t\t\tif( operation.gate.symbol === 'X' && \n\t\t\t\toperation.registerIndices.length > 1 ){\n\n\t\t\t\tawsGate = 'cnot'\n\t\t\t}\n\t\t\tif( operation.gate.symbol === '*' ){\n\n\t\t\t\tawsGate = 'i'\n\t\t\t}\n\t\t\t\n\t\t\treturn string +'.'+ awsGate +'(' + \n\t\t\t\toperation.registerIndices.reduce( function( string, registerIndex, r ){\n\n\t\t\t\t\treturn string + (( r > 0 ) ? ',' : '' ) + ( registerIndex - 1 )\n\n\t\t\t\t}, '' ) + ')'\n\n\t\t}, 'qjs_circuit = Circuit()' )\n\t\tif( this.operations.length === 0 ) circuit += '.i(0)'// Quick fix to avoid an error here!\n\n\t\tconst footer = `\\n\\ntask = device.run(qjs_circuit, s3_folder, shots=100)\nprint(task.result().measurement_counts)`\n\t\treturn header + circuit + footer\n\t},\n\ttoLatex: function(){\n\n\t\t/*\n\n\t\t\\Qcircuit @C=1em @R=.7em {\n\t\t\t& \\ctrl{2} & \\targ & \\gate{U} & \\qw \\\\\n\t\t\t& \\qw & \\ctrl{-1} & \\qw & \\qw \\\\\n\t\t\t& \\targ & \\ctrl{-1} & \\ctrl{-2} & \\qw \\\\\n\t\t\t& \\qw & \\ctrl{-1} & \\qw & \\qw\n\t\t}\n\n\t\tNo \"&\"\" means it’s an input. So could also do this:\n\t\t\\Qcircuit @C=1.4em @R=1.2em {\n\n\t\t\ta & i \\\\\n\t\t\t1 & x\n\t\t}\n\t\t*/\n\n\t\treturn '\\\\Qcircuit @C=1.0em @R=0.7em {\\n' +\n\t\tthis.toTable()\n\t\t.reduce( function( array, moment, m ){\n\n\t\t\tmoment.forEach( function( operation, o, operations ){\n\n\t\t\t\tlet command = 'qw'\n\t\t\t\tif( operation.symbol !== 'I' ){\n\n\t\t\t\t\tif( operation.isMultiRegisterOperation ){\n\n\t\t\t\t\t\tif( operation.indexAmongSiblings === 0 ){\n\n\t\t\t\t\t\t\tif( operation.symbol === 'X' ) command = 'targ'\n\t\t\t\t\t\t\telse command = operation.symbol.toLowerCase()\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if( operation.indexAmongSiblings > 0 ) command = 'ctrl{?}'\n\t\t\t\t\t}\n\t\t\t\t\telse command = operation.symbol.toLowerCase()\n\t\t\t\t}\n\t\t\t\toperations[ o ].latexCommand = command\n\t\t\t})\n\t\t\tconst maximumCharacterWidth = moment.reduce( function( maximumCharacterWidth, operation ){\n\n\t\t\t\treturn Math.max( maximumCharacterWidth, operation.latexCommand.length )\n\t\t\t\n\t\t\t}, 0 )\n\t\t\tmoment.forEach( function( operation, o ){\n\n\t\t\t\tarray[ o ] += '& \\\\'+ operation.latexCommand.padEnd( maximumCharacterWidth ) +' '\n\t\t\t})\n\t\t\treturn array\n\n\t\t}, new Array( this.bandwidth ).fill( '\\n\\t' ))\n\t\t.join( '\\\\\\\\' ) + \n\t\t'\\n}'\n\t},\n\n\n\n\n\n\n\t //////////////\n\t // //\n\t // Edit //\n\t // //\n\t//////////////\n\n\n\tget: function( momentIndex, registerIndex ){\n\n\t\treturn this.operations.find( function( op ){\n\n\t\t\treturn op.momentIndex === momentIndex && \n\t\t\t\top.registerIndices.includes( registerIndex )\n\t\t})\n\t},\n\tclear$: function( momentIndex, registerIndices ){\n\n\t\tconst circuit = this\n\n\n\t\t// Validate our arguments.\n\t\t\n\t\tif( arguments.length !== 2 ) \n\t\t\tQ.warn( `Q.Circuit.clear$ expected 2 arguments but received ${ arguments.length }.` )\n\t\tif( Q.isUsefulInteger( momentIndex ) !== true )\n\t\t\treturn Q.error( `Q.Circuit attempted to clear an input on Circuit #${ circuit.index } using an invalid moment index:`, momentIndex )\n\t\tif( Q.isUsefulInteger( registerIndices )) registerIndices = [ registerIndices ]\n\t\tif( registerIndices instanceof Array !== true )\n\t\t\treturn Q.error( `Q.Circuit attempted to clear an input on Circuit #${ circuit.index } using an invalid register indices array:`, registerIndices )\n\n\n\t\t// Let’s find any operations \n\t\t// with a footprint at this moment index and one of these register indices\n\t\t// and collect not only their content, but their index in the operations array.\n\t\t// (We’ll need that index to splice the operations array later.)\n\n\t\tconst foundOperations = circuit.operations.reduce( function( filtered, operation, o ){\n\n\t\t\tif( operation.momentIndex === momentIndex && \n\t\t\t\toperation.registerIndices.some( function( registerIndex ){\n\n\t\t\t\t\treturn registerIndices.includes( registerIndex )\n\t\t\t\t})\n\t\t\t) filtered.push({\n\n\t\t\t\tindex: o,\n\t\t\t\tmomentIndex: operation.momentIndex,\n\t\t\t\tregisterIndices: operation.registerIndices,\n\t\t\t\tgate: operation.gate\n\t\t\t})\n\t\t\treturn filtered\n\n\t\t}, [] )\n\n\n\t\t// Because we held on to each found operation’s index\n\t\t// within the circuit’s operations array\n\t\t// we can now easily splice them out of the array.\n\n\t\tfoundOperations.reduce( function( deletionsSoFar, operation ){\n\n\t\t\tcircuit.operations.splice( operation.index - deletionsSoFar, 1 )\n\t\t\treturn deletionsSoFar + 1\n\n\t\t}, 0 )\n\n\n\t\t// IMPORTANT!\n\t\t// Operations must be sorted properly\n\t\t// for toTable to work reliably with\n\t\t// multi-register operations!!\n\t\t\t\t\n\t\tthis.sort$()\n\n\n\t\t// Let’s make history.\n\n\t\tif( foundOperations.length ){\n\n\t\t\tthis.history.record$({\n\n\t\t\t\tredo: {\n\t\t\t\t\t\n\t\t\t\t\tname: 'clear$',\n\t\t\t\t\tfunc: circuit.clear$,\t\t\t\t\n\t\t\t\t\targs: Array.from( arguments )\n\t\t\t\t},\n\t\t\t\tundo: foundOperations.reduce( function( undos, operation ){\n\n\t\t\t\t\tundos.push({\n\n\t\t\t\t\t\tname: 'set$',\n\t\t\t\t\t\tfunc: circuit.set$,\n\t\t\t\t\t\targs: [\n\n\t\t\t\t\t\t\toperation.gate,\n\t\t\t\t\t\t\toperation.momentIndex,\n\t\t\t\t\t\t\toperation.registerIndices\n\t\t\t\t\t\t]\n\t\t\t\t\t})\n\t\t\t\t\treturn undos\n\t\t\t\t\n\t\t\t\t}, [] )\n\t\t\t})\n\n\n\t\t\t// Let anyone listening, \n\t\t\t// including any circuit editor interfaces,\n\t\t\t// know about what we’ve just completed here.\n\n\t\t\tfoundOperations.forEach( function( operation ){\n\n\t\t\t\t/* window.dispatchEvent( new CustomEvent( \n\n\t\t\t\t\t'Q.Circuit.clear$', { detail: { \n\n\t\t\t\t\t\tcircuit,\n\t\t\t\t\t\tmomentIndex,\n\t\t\t\t\t\tregisterIndices: operation.registerIndices\n\t\t\t\t\t}}\n\t\t\t\t)) */\n\t\t\t})\n\t\t}\n\n\n\t\t// Enable that “fluent interface” method chaining :)\n\n\t\treturn circuit\n\t},\n\t\n\n\tsetProperty$: function( key, value ){\n\n\t\tthis[ key ] = value\n\t\treturn this\n\t},\n\tsetName$: function( name ){\n\n\t\tif( typeof name === 'function' ) name = name()\n\t\treturn this.setProperty$( 'name', name )\n\t},\n\n\n\tset$: function( gate, momentIndex, registerIndices ){\n\n\t\tconst circuit = this\n\n\n\t\t// Is this a valid gate?\n\n\t\tif( typeof gate === 'string' ) gate = Q.Gate.findBySymbol( gate )\n\t\tif( gate instanceof Q.Gate !== true ) return Q.error( `Q.Circuit attempted to add a gate to circuit #${ this.index } at moment #${ momentIndex } that is not a gate:`, gate )\n\n\n\t\t// Is this a valid moment index?\n\t\t\n\t\tif( Q.isUsefulNumber( momentIndex ) !== true ||\n\t\t\tNumber.isInteger( momentIndex ) !== true ||\n\t\t\tmomentIndex < 1 || momentIndex > this.timewidth ){\n\n\t\t\treturn Q.error( `Q.Circuit attempted to add a gate to circuit #${ this.index } at a moment index that is not valid:`, momentIndex )\n\t\t}\n\n\n\t\t// Are these valid register indices?\n\n\t\tif( typeof registerIndices === 'number' ) registerIndices = [ registerIndices ]\n\t\tif( registerIndices instanceof Array !== true ) return Q.error( `Q.Circuit attempted to add a gate to circuit #${ this.index } at moment #${ momentIndex } with an invalid register indices array:`, registerIndices )\n\t\tif( registerIndices.length === 0 ) return Q.error( `Q.Circuit attempted to add a gate to circuit #${ this.index } at moment #${ momentIndex } with an empty register indices array:`, registerIndices )\n\t\tif( registerIndices.reduce( function( accumulator, registerIndex ){\n\n\t\t\t// console.log(accumulator && \n\t\t\t// \tregisterIndex > 0 && \n\t\t\t// \tregisterIndex <= circuit.bandwidth)\n\t\t\treturn (\n\n\t\t\t\taccumulator && \n\t\t\t\tregisterIndex > 0 && \n\t\t\t\tregisterIndex <= circuit.bandwidth\n\t\t\t)\n\n\t\t}, false )){\n\n\t\t\treturn Q.warn( `Q.Circuit attempted to add a gate to circuit #${ this.index } at moment #${ momentIndex } with some out of range qubit indices:`, registerIndices )\n\t\t}\n\n\n\t\t// Ok, now we can check if this set$ command\n\t\t// is redundant.\n\n\t\tconst\n\t\tisRedundant = !!circuit.operations.find( function( operation ){\n\n\t\t\treturn (\n\n\t\t\t\tmomentIndex === operation.momentIndex &&\n\t\t\t\tgate === operation.gate &&\n\t\t\t\tregisterIndices.length === operation.registerIndices.length &&\n\t\t\t\tregisterIndices.every( val => operation.registerIndices.includes( val ))\n\t\t\t)\n\t\t})\n\n\n\t\t// If it’s NOT redundant \n\t\t// then we’re clear to proceed.\n\n\t\tif( isRedundant !== true ){\n\n\n\t\t\t// If there’s already an operation here,\n\t\t\t// we’d better get rid of it!\n\t\t\t// This will also entirely remove any multi-register operations\n\t\t\t// that happen to have a component at this moment / register.\n\t\t\t\n\t\t\tthis.clear$( momentIndex, registerIndices )\n\t\t\t\n\n\t\t\t// Finally. \n\t\t\t// Finally we can actually set this operation.\n\t\t\t// Aren’t you glad we handle all this for you?\n\n\t\t\tconst \n\t\t\tisControlled = registerIndices.length > 1 && gate !== Q.Gate.SWAP,\n\t\t\toperation = {\n\n\t\t\t\tgate,\n\t\t\t\tmomentIndex,\n\t\t\t\tregisterIndices,\n\t\t\t\tisControlled\n\t\t\t}\n\t\t\tthis.operations.push( operation )\n\n\t\t\t\n\t\t\t// IMPORTANT!\n\t\t\t// Operations must be sorted properly\n\t\t\t// for toTable to work reliably with\n\t\t\t// multi-register operations!!\n\t\t\t\n\t\t\tthis.sort$()\n\n\n\t\t\t// Let’s make history.\n\n\t\t\tthis.history.record$({\n\n\t\t\t\tredo: {\n\t\t\t\t\t\n\t\t\t\t\tname: 'set$',\n\t\t\t\t\tfunc: circuit.set$,\n\t\t\t\t\targs: Array.from( arguments )\n\t\t\t\t},\n\t\t\t\tundo: [{\n\n\t\t\t\t\tname: 'clear$',\n\t\t\t\t\tfunc: circuit.clear$,\n\t\t\t\t\targs: [ momentIndex, registerIndices ]\n\t\t\t\t}]\n\t\t\t})\n\n\t\t\t\n\t\t\t// Emit an event that we have set an operation\n\t\t\t// on this circuit.\n\n\t\t\t/* window.dispatchEvent( new CustomEvent( \n\n\t\t\t\t'Q.Circuit.set$', { detail: { \n\n\t\t\t\t\tcircuit,\n\t\t\t\t\toperation\n\t\t\t\t}}\n\t\t\t)) */\n\t\t}\n\t\treturn circuit\n\t},\n\n\n\n\n\tdetermineRanges: function( options ){\n\n\t\tif( options === undefined ) options = {}\n\t\tlet {\n\n\t\t\tqubitFirstIndex,\n\t\t\tqubitRange,\n\t\t\tqubitLastIndex,\n\t\t\tmomentFirstIndex,\n\t\t\tmomentRange,\n\t\t\tmomentLastIndex\n\n\t\t} = options\n\n\t\tif( typeof qubitFirstIndex !== 'number' ) qubitFirstIndex = 0\n\t\tif( typeof qubitLastIndex !== 'number' && typeof qubitRange !== 'number' ) qubitLastIndex = this.bandwidth\n\t\tif( typeof qubitLastIndex !== 'number' && typeof qubitRange === 'number' ) qubitLastIndex = qubitFirstIndex + qubitRange\n\t\telse if( typeof qubitLastIndex === 'number' && typeof qubitRange !== 'number' ) qubitRange = qubitLastIndex - qubitFirstIndex\n\t\telse return Q.error( `Q.Circuit attempted to copy a circuit but could not understand what qubits to copy.` )\n\n\t\tif( typeof momentFirstIndex !== 'number' ) momentFirstIndex = 0\n\t\tif( typeof momentLastIndex !== 'number' && typeof momentRange !== 'number' ) momentLastIndex = this.timewidth\n\t\tif( typeof momentLastIndex !== 'number' && typeof momentRange === 'number' ) momentLastIndex = momentFirstIndex + momentRange\n\t\telse if( typeof momentLastIndex === 'number' && typeof momentRange !== 'number' ) momentRange = momentLastIndex - momentFirstIndex\n\t\telse return Q.error( `Q.Circuit attempted to copy a circuit but could not understand what moments to copy.` )\n\n\t\tQ.log( 0.8, \n\t\t\n\t\t\t'\\nQ.Circuit copy operation:',\n\t\t\t'\\n\\n qubitFirstIndex', qubitFirstIndex,\n\t\t\t'\\n qubitLastIndex ', qubitLastIndex,\n\t\t\t'\\n qubitRange ', qubitRange,\n\t\t\t'\\n\\n momentFirstIndex', momentFirstIndex,\n\t\t\t'\\n momentLastIndex ', momentLastIndex,\n\t\t\t'\\n momentRange ', momentRange,\n\t\t\t'\\n\\n'\n\t\t)\n\n\t\treturn {\n\n\t\t\tqubitFirstIndex,\n\t\t\tqubitRange,\n\t\t\tqubitLastIndex,\n\t\t\tmomentFirstIndex,\n\t\t\tmomentRange,\n\t\t\tmomentLastIndex\n\t\t}\n\t},\n\n\n\tcopy: function( options, isACutOperation ){\n\n\t\tconst original = this\n\t\tlet {\n\n\t\t\tregisterFirstIndex,\n\t\t\tregisterRange,\n\t\t\tregisterLastIndex,\n\t\t\tmomentFirstIndex,\n\t\t\tmomentRange,\n\t\t\tmomentLastIndex\n\n\t\t} = this.determineRanges( options )\n\n\t\tconst copy = new Q.Circuit( registerRange, momentRange )\n\n\t\toriginal.operations\n\t\t.filter( function( operation ){\n\n\t\t\treturn ( operation.registerIndices.every( function( registerIndex ){\n\n\t\t\t\treturn (\n\n\t\t\t\t\toperation.momentIndex >= momentFirstIndex &&\n\t\t\t\t\toperation.momentIndex < momentLastIndex &&\n\t\t\t\t\toperation.registerIndex >= registerFirstIndex && \n\t\t\t\t\toperation.registerIndex < registerLastIndex\n\t\t\t\t)\n\t\t\t}))\n\t\t})\t\t\t\n\t\t.forEach( function( operation ){\n\n\t\t\tconst adjustedRegisterIndices = operation.registerIndices.map( function( registerIndex ){\n\n\t\t\t\treturn registerIndex - registerFirstIndex\n\t\t\t})\n\t\t\tcopy.set$(\n\n\t\t\t\toperation.gate, \n\t\t\t\t1 + m - momentFirstIndex, \n\t\t\t\tadjustedRegisterIndices\n\t\t\t)\n\t\t})\n\n\n\t\t// The cut$() operation just calls copy()\n\t\t// with the following boolean set to true.\n\t\t// If this is a cut we need to \n\t\t// replace all gates in this area with identity gates.\n\n\t\t// UPDATE !!!!\n\t\t// will come back to fix!!\n\t\t// with new style it's now just a matter of \n\t\t// splicing out these out of circuit.operations\n\n\n\t\t\n\t\tif( isACutOperation === true ){\n\n\t\t\t/*\n\t\t\tfor( let m = momentFirstIndex; m < momentLastIndex; m ++ ){\n\n\t\t\t\toriginal.moments[ m ] = new Array( original.bandwidth )\n\t\t\t\t.fill( 0 )\n\t\t\t\t.map( function( qubit, q ){\n\n\t\t\t\t\treturn { \n\n\t\t\t\t\t\tgate: Q.Gate.IDENTITY,\n\t\t\t\t\t\tregisterIndices: [ q ]\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t}*/\n\t\t}\n\t\treturn copy\n\t},\n\tcut$: function( options ){\n\n\t\treturn this.copy( options, true )\n\t},\n\n\n\n\n\n\n\n\t/*\n\n\n\n\n\tIf covers all moments for 1 or more qubits then \n\t1. go through each moment and remove those qubits\n\t2. remove hanging operations. (right?? don’t want them?)\n\n\n\n\n\t*/\n\n\tspliceCut$: function( options ){\n\n\t\tlet {\n\n\t\t\tqubitFirstIndex,\n\t\t\tqubitRange,\n\t\t\tqubitLastIndex,\n\t\t\tmomentFirstIndex,\n\t\t\tmomentRange,\n\t\t\tmomentLastIndex\n\n\t\t} = this.determineRanges( options )\n\n\n\t\t// Only three options are valid:\n\t\t// 1. Selection area covers ALL qubits for a series of moments.\n\t\t// 2. Selection area covers ALL moments for a seriies of qubits.\n\t\t// 3. Both of the above (splice the entire circuit).\n\n\t\tif( qubitRange !== this.bandwidth &&\n\t\t\tmomentRange !== this.timewidth ){\n\n\t\t\treturn Q.error( `Q.Circuit attempted to splice circuit #${this.index} by an area that did not include all qubits _or_ all moments.` )\n\t\t}\n\n\n\t\t// If the selection area covers all qubits for 1 or more moments\n\t\t// then splice the moments array.\n\t\t\t\n\t\tif( qubitRange === this.bandwidth ){\n\n\n\t\t\t// We cannot use Array.prototype.splice() for this\n\t\t\t// because we need a DEEP copy of the array\n\t\t\t// and splice() will only make a shallow copy.\n\t\t\t\n\t\t\tthis.moments = this.moments.reduce( function( accumulator, moment, m ){\n\n\t\t\t\tif( m < momentFirstIndex - 1 || m >= momentLastIndex - 1 ) accumulator.push( moment )\n\t\t\t\treturn accumulator\n\t\t\t\n\t\t\t}, [])\n\t\t\tthis.timewidth -= momentRange\n\n\t\t\t//@@ And how do we implement splicePaste$() here?\n\t\t}\n\n\n\t\t// If the selection area covers all moments for 1 or more qubits\n\t\t// then iterate over each moment and remove those qubits.\n\t\n\t\tif( momentRange === this.timewidth ){\n\n\n\t\t\t// First, let’s splice the inputs array.\n\n\t\t\tthis.inputs.splice( qubitFirstIndex, qubitRange )\n\t\t\t//@@ this.inputs.splice( qubitFirstIndex, qubitRange, qubitsToPaste?? )\n\t\t\t\n\n\t\t\t// Now we can make the proper adjustments\n\t\t\t// to each of our moments.\n\n\t\t\tthis.moments = this.moments.map( function( operations ){\n\n\t\t\t\t\n\t\t\t\t// Remove operations that pertain to the removed qubits.\n\t\t\t\t// Renumber the remaining operations’ qubitIndices.\n\t\t\t\t\n\t\t\t\treturn operations.reduce( function( accumulator, operation ){\n\n\t\t\t\t\tif( operation.qubitIndices.every( function( index ){\n\n\t\t\t\t\t\treturn index < qubitFirstIndex || index >= qubitLastIndex\n\t\t\t\t\t\n\t\t\t\t\t})) accumulator.push( operation )\n\t\t\t\t\treturn accumulator\n\t\t\t\t\n\t\t\t\t}, [])\n\t\t\t\t.map( function( operation ){\n\n\t\t\t\t\toperation.qubitIndices = operation.qubitIndices.map( function( index ){\n\n\t\t\t\t\t\treturn index >= qubitLastIndex ? index - qubitRange : index\n\t\t\t\t\t})\n\t\t\t\t\treturn operation\n\t\t\t\t})\n\t\t\t})\n\t\t\tthis.bandwidth -= qubitRange\n\t\t}\n\t\t\n\n\t\t// Final clean up.\n\n\t\tthis.removeHangingOperations$()\n\t\tthis.fillEmptyOperations$()\n\t\t\n\n\t\treturn this// Or should we return the cut area?!\n\t},\n\tsplicePaste$: function(){\n\n\n\t},\n\t\n\n\n\n\n\t// This is where “hanging operations” get interesting!\n\t// when you paste one circuit in to another\n\t// and that clipboard circuit has hanging operations\n\t// those can find a home in the circuit its being pasted in to!\n\n\n\tpaste$: function( other, atMoment = 0, atQubit = 0, shouldClean = true ){\n\n\t\tconst scope = this\n\t\tthis.timewidth = Math.max( this.timewidth, atMoment + other.timewidth )\n\t\tthis.bandwidth = Math.max( this.bandwidth, atQubit + other.bandwidth )\n\t\tthis.ensureMomentsAreReady$()\n\t\tthis.fillEmptyOperations$()\n\t\tother.moments.forEach( function( moment, m ){\n\n\t\t\tmoment.forEach( function( operation ){\n\n\t\t\t\t//console.log( 'past over w this:', m + atMoment, operation )\n\n\t\t\t\tscope.set$(\n\n\t\t\t\t\toperation.gate,\n\t\t\t\t\tm + atMoment + 1,\n\t\t\t\t\toperation.qubitIndices.map( function( qubitIndex ){\n\n\t\t\t\t\t\treturn qubitIndex + atQubit\n\t\t\t\t\t})\n\t\t\t\t)\n\t\t\t})\n\t\t})\n\t\tif( shouldClean ) this.removeHangingOperations$()\n\t\tthis.fillEmptyOperations$()\n\t\treturn this\n\t},\n\tpasteInsert$: function( other, atMoment, atQubit ){\n\n\t\t// if( other.alphandwidth !== this.bandwidth && \n\t\t// \tother.timewidth !== this.timewidth ) return Q.error( 'Q.Circuit attempted to pasteInsert Circuit A', other, 'in to circuit B', this, 'but neither their bandwidth or timewidth matches.' )\n\n\t\t\n\n\n\t\tif( shouldClean ) this.removeHangingOperations$()\n\t\tthis.fillEmptyOperations$()\t\t\n\t\treturn this\n\n\t},\n\texpand$: function(){\n\n\t\t// expand either bandwidth or timewidth, fill w identity\n\n\n\t\tthis.fillEmptyOperations$()\n\t\treturn thiis\n\t},\n\n\n\n\n\n\n\n\ttrim$: function( options ){\n\n\t\t`\n\t\tEdit this circuit by trimming off moments, qubits, or both.\n\t\tWe could have implemented trim$() as a wrapper around copy$(),\n\t\tsimilar to how cut$ is a wrapper around copy$().\n\t\tBut this operates on the existing circuit \n\t\tinstead of returning a new one and returning that.\n\t\t`\n\n\t\tlet {\n\n\t\t\tqubitFirstIndex,\n\t\t\tqubitRange,\n\t\t\tqubitLastIndex,\n\t\t\tmomentFirstIndex,\n\t\t\tmomentRange,\n\t\t\tmomentLastIndex\n\n\t\t} = this.determineRanges( options )\n\n\n\t\t// First, trim the moments down to desired size.\n\n\t\tthis.moments = this.moments.slice( momentFirstIndex, momentLastIndex )\n\t\tthis.timewidth = momentRange\n\n\n\t\t// Then, trim the bandwidth down.\n\n\t\tthis.inputs = this.inputs.slice( qubitFirstIndex, qubitLastIndex )\n\t\tthis.bandwidth = qubitRange\n\n\n\t\t// Finally, remove all gates where\n\t\t// gate’s qubit indices contain an index < qubitFirstIndex,\n\t\t// gate’s qubit indices contain an index > qubitLastIndex,\n\t\t// and fill those holes with Identity gates.\n\t\t\n\t\tthis.removeHangingOperations$()\n\t\tthis.fillEmptyOperations$()\n\n\t\treturn this\n\t}\n})\n\n\n\n\n\n\n\n// Against my predilection for verbose clarity...\n// I offer you super short convenience methods\n// that do NOT use the $ suffix to delcare they are destructive.\n// Don’t shoot your foot off.\n\nObject.entries( Q.Gate.constants ).forEach( function( entry ){\n\n\tconst \n\tgateConstantName = entry[ 0 ],\n\tgate = entry[ 1 ],\n\tset$ = function( momentIndex, registerIndexOrIndices ){\n\n\t\tthis.set$( gate, momentIndex, registerIndexOrIndices )\n\t\treturn this\n\t}\n\tQ.Circuit.prototype[ gateConstantName ] = set$\n\tQ.Circuit.prototype[ gate.symbol ] = set$\n\tQ.Circuit.prototype[ gate.symbol.toLowerCase() ] = set$\n})\n\n\n\n/*\nconst bells = [\n\n\n\t// Verbose without shortcuts.\n\n\tnew Q.Circuit( 2, 2 )\n\t\t.set$( Q.Gate.HADAMARD, 1, [ 1 ])\n\t\t.set$( Q.Gate.PAULI_X, 2, [ 1 , 2 ]),\n\n\tnew Q.Circuit( 2, 2 )\n\t\t.set$( Q.Gate.HADAMARD, 1, 1 )\n\t\t.set$( Q.Gate.PAULI_X, 2, [ 1 , 2 ]),\n\n\n\t// Uses Q.Gate.findBySymbol() to lookup gates.\n\n\tnew Q.Circuit( 2, 2 )\n\t\t.set$( 'H', 1, [ 1 ])\n\t\t.set$( 'X', 2, [ 1 , 2 ]),\n\n\tnew Q.Circuit( 2, 2 )\n\t\t.set$( 'H', 1, 1 )\n\t\t.set$( 'X', 2, [ 1 , 2 ]),\n\n\n\t// Convenience gate functions -- constant name.\n\n\tnew Q.Circuit( 2, 2 )\n\t\t.HADAMARD( 1, [ 1 ])\n\t\t.PAULI_X( 2, [ 1, 2 ]),\n\n\tnew Q.Circuit( 2, 2 )\n\t\t.HADAMARD( 1, 1 )\n\t\t.PAULI_X( 2, [ 1, 2 ]),\n\n\n\t// Convenience gate functions -- uppercase symbol.\n\n\tnew Q.Circuit( 2, 2 )\n\t\t.H( 1, [ 1 ])\n\t\t.X( 2, [ 1, 2 ]),\n\n\tnew Q.Circuit( 2, 2 )\n\t\t.H( 1, 1 )\n\t\t.X( 2, [ 1, 2 ]),\n\n\n\t// Convenience gate functions -- lowercase symbol.\n\n\tnew Q.Circuit( 2, 2 )\n\t\t.h( 1, [ 1 ])\n\t\t.x( 2, [ 1, 2 ]),\n\n\tnew Q.Circuit( 2, 2 )// Perhaps the closest to Braket style.\n\t\t.h( 1, 1 )\n\t\t.x( 2, [ 1, 2 ]),\n\n\n\t// Q function -- bandwidth / timewidth arguments.\n\n\tQ( 2, 2 )\n\t\t.h( 1, [ 1 ])\n\t\t.x( 2, [ 1, 2 ]),\n\n\tQ( 2, 2 )\n\t\t.h( 1, 1 )\n\t\t.x( 2, [ 1, 2 ]),\n\n\n\t// Q function -- text block argument\n\t// with operation symbols\n\t// and operation component IDs.\n\n\tQ`\n\t\tH-X.0#0\n\t\tI-X.0#1`,\n\n\t\n\t// Q function -- text block argument\n\t// using only component IDs\n\t// (ie. no operation symbols)\n\t// because the operation that the \n\t// components should belong to is NOT ambiguous.\n\t\n\tQ`\n\t\tH-X#0\n\t\tI-X#1`,\n\n\n\t// Q function -- text block argument\n\t// as above, but using only whitespace\n\t// to partition between moments.\n\n\tQ`\n\t\tH X#0\n\t\tI X#1`\t\n],\nbellsAreEqual = !!bells.reduce( function( a, b ){\n\n\treturn a.toText() === b.toText() ? a : NaN\n\n})\nif( bellsAreEqual ){\n\n\tconsole.log( `\\n\\nYES. All of ${ bells.length } our “Bell” circuits are equal.\\n\\n`, bells ) \n}\n*/\n\n\n\n\n\n\n\nQ.Circuit.createConstants(\n\n\t'BELL', Q`\n\n\t\tH X#0\n\t\tI X#1\n\t`,\t\n\t// 'GROVER', Q`\n\n\t// \tH X *#0 X#0 I X#0 I I I X#0 I I I X#0 I X H X I *#0\n\t// \tH X I X#1 *#0 X#1 *#0 X#0 I I I X#0 X I H X I I I I\n\t// \tH X I I I I I X#1 *#0 X#1 *#0 X#1 *#0 X#1 I *#0 X H X I\n\t// \tH X *#1 I *#1 I *#1 I *#1 I *#1 I *#1 I I *#1 X H X *#1\n\t// `\n\n\t//https://docs.microsoft.com/en-us/quantum/concepts/circuits?view=qsharp-preview\n\t// 'TELEPORT', Q.(`\n\t\t\n\t// \tI-I--H-M---v\n\t// \tH-C0-I-M-v-v\n\t// \tI-C1-I-I-X-Z-\n\t// `)\n)\n\n\nvar circuit = Q(tempVars(\"input\"));\n\nvar option = tempVars(\"option\");\n\nswitch(option) {\n case \"showcirq\":\n try { msg.reply(\"```\"+circuit.toDiagram()+\"```\")\n } catch { \n msg.reply(\"Fuck!\");\n }\n break;\n\n case \"evalcirq\":\n try { msg.reply(\"```\"+ circuit.report$()+\"```\")\n } catch {\n msg.reply(\"shit!!\");\n }\n break;\n\n default:\n break;\n} \n\n\n",
"storage": "0",
"varName": "",
"name": "Run Script"
}
]
},
{
"name": "quranomancy",
"permissions": "NONE",
"restriction": "1",
"_id": "EBVAr",
"actions": [
{
"behavior": "0",
"interpretation": "1",
"code": "function getRandomInt(max) {\n return Math.floor(Math.random() * Math.floor(max));\n}\n\nfunction myQuranomancy() {\n const Discord = require('discord.js');\n const chapNum = \"1\";\n const verCount = \"7\";\n \n var myRandSurah = getRandomInt(6235);\n\n\n const exampleEmbed = new Discord.MessageEmbed()\n\t .setColor('#0099ff')\n\t .setTitle('Quran Surah '+ quran[myRandSurah].surah_number + ' Verse '+ quran[myRandSurah].verse_number)\n\t .setAuthor('ATOR', 'https://i.imgur.com/RGt5nhd.jpg', 'https://discord.js.org')\n\t .setDescription(quran[myRandSurah].content)\n\t .setThumbnail('https://i.imgur.com/RGt5nhd.jpg')\n\t .setTimestamp()\n\t .setFooter('Do androids dream of electric sheep?', 'https://i.imgur.com/RGt5nhd.jpg');\n\n msg.channel.send(exampleEmbed);\n }\n\nconst quran = require('./quran_en.json');\nconst chapNum = \"1\";\nconst verCount = \"7\";\n\nmyQuranomancy();\n\n",
"storage": "0",
"varName": "",
"name": "Run Script"
}
]
},
{
"name": "say",
"permissions": "NONE",
"restriction": "1",
"_id": "wrqao",
"actions": [
{
"info": "1",
"infoIndex": "1",
"storage": "1",
"varName": "test",
"name": "Store Command Params"
},
{
"behavior": "0",
"interpretation": "1",
"code": "msg.channel.send(tempVars(\"test\"));",
"storage": "0",
"varName": "",
"name": "Run Script"
}
]
},
{
"name": "test",
"permissions": "NONE",
"restriction": "1",
"_id": "svyPR",
"actions": [
{
"behavior": "0",
"interpretation": "1",
"code": "const Discord = require('discord.js');\n\nlet Embed = new Discord.MessageEmbed()\n .setTitle()\n .setAuthor()\n .setColor()\n .addField()\n .setDescription()\n .setThumbnail()\n\nmsg.channel.send({embed: {\n color: 3447003,\n author: {\n name: client.user.username,\n icon_url: client.user.avatarURL\n },\n title: \"Here is a list of the commands that I support.\",\n description: \"```!atorhelp !ator !say !gem\\n!777 !qc !lisp !quranomancy\\n!liber220 !date``` \",\n fields: [{\n \"name\": \"!atorhelp\",\n \"value\": \"```\\nDisplays this message.\\n```\"\n },\n {\n \"name\": \"!ator\",\n \"value\": \"```\\nGeneral chatbot command.\\n\\n!ator <text>\\n```\\n\"\n },\n {\n \"name\": \"!gem\",\n \"value\": \"```\\nGematria related commands.\\n\\n[1] !gem heb <unicode Hebrew string> - Displays Hebrew gematria values of a string.\\n[2] !gem grk <unicode Greek string> - Displays Greek gematria values of a string.\\n[3] !gem naeq <English string> - Displays Naeq Aeon English Qabalah gematria of a string.\\n[4] !gem val <##>\\n```\"\n },\n {\n \"name\": \"!quranomancy\",\n \"value\": \"```\\nReturns random surah from the Quran.\\n```\"\n },\n {\n \"name\": \"!777\",\n \"value\": \"```\\nLiber 777 data tool.\\n\\n[1] !777 showcor <key>\\n[2] !777 showcol from <column>\\n[3] !777 keysearch <key><column>\\n```\"\n },\n {\n \"name\": \"!date\",\n \"value\": \"```\\nDisplays current Thelemic date\\n```\"\n },\n {\n \"name\": \"!qc\",\n \"value\": \"```\\nQuantum Computer. Evaluates and draws quantum circuits from text representations of quantum code.\\n\\n[1] !qc showcirq <text quantum circuit>\\n[2] !qc evalcirq <text quantum circuit>\\n```\\n\\n\"\n },\n {\n \"name\": \"!lisp\",\n \"value\": \"```\\nVery limited LISP interpreter.\\n\\n!lisp <code>\\n```\"\n },\n {\n \"name\": \"!say\",\n \"value\": \"```\\nI'll repeat whatever you type.\\n\\n!say <text>\\n```\"\n },\n {\n \"name\": \"!liber220\",\n \"value\": \"```\\nDisplays verses from Liber Al Vel Legis.\\n\\n[1] !liber220 bibliomancy\\n[2] !liber220 <chapter><verse>\\n```\\n\\n\"\n }]\n }});\n \n",
"storage": "0",
"varName": "",
"name": "Run Script"
}
]
},
{
"name": "777",
"permissions": "NONE",
"restriction": "1",
"_id": "tqiGn",
"actions": [
{
"member": "0",
"varName": "",
"info": "0",
"storage": "1",
"varName2": "member",
"name": "Store Member Info"
},
{
"info": "0",
"infoIndex": "1",
"storage": "1",
"varName": "subcommand",
"name": "Store Command Params"
},
{
"info": "0",
"infoIndex": "2",
"storage": "1",
"varName": "key",
"name": "Store Command Params"
},
{
"info": "1",
"infoIndex": "3",
"storage": "1",
"varName": "column",
"name": "Store Command Params"
},
{
"behavior": "0",
"interpretation": "1",
"code": "const myObj = require(\"./csvjson.json\");\n\nfunction myHelp() {\n\n// at the top of your file\nconst Discord = require('discord.js');\n\n// inside a command, event listener, etc.\nconst exampleEmbed = new Discord.MessageEmbed()\n\t.setColor('#0099ff')\n\t.setTitle('Liber777bot help')\n\t.setDescription('Here is a list of my commands.')\n\t.setThumbnail('https://i.imgur.com/aSPsqCP.jpg')\n\n \t.addField('showcol', '!777 showcol from <category> :: Returns data from a specific category.')\n .addField('showcor', '!777 showcor <key> :: Returns correspondences associated with a given key. ')\n .addField('keysearch', '!777 keysearch <key><category> :: Returns a single value from a category by provided key')\n\t\n .setTimestamp()\n\t.setFooter('Bots need love too.');\n\n msg.reply(exampleEmbed);\n}\n\nfunction myResults() {\n\n// at the top of your file\nconst Discord = require('discord.js');\n\n// inside a command, event listener, etc.\nconst exampleEmbed = new Discord.MessageEmbed()\n\t.setColor('#0099ff')\n\t.setTitle('Liber 777 Query results')\n\t.setDescription('I\\'m sending your results to you now.')\n\t.setThumbnail('https://i.imgur.com/aSPsqCP.jpg')\n\t.setTimestamp()\n\t.setFooter('Bots need love too.');\n\n msg.reply(exampleEmbed);\n}\n\n\nfunction myKeySearch(a, b) {\n// at the top of your file\nconst Discord = require('discord.js');\n\n// inside a command, event listener, etc.\nconst exampleEmbed = new Discord.MessageEmbed()\n\t.setColor('#0099ff')\n\t.setTitle('Liber 777 Query results')\n\t.setDescription(myObj[a][b])\n\t.setThumbnail('https://i.imgur.com/aSPsqCP.jpg')\n\t.setTimestamp()\n\t.setFooter('Bots need love too.');\n\n msg.reply(exampleEmbed); \n}\n\nfunction myShowCol(a) {\n\n // Using commonjs?\n const {table} = require('table');\n \n\n let output, data = new Array(11);\n let output2, data2 = new Array(11);\n let output3, data3 = new Array(11);\n let output4, data4 = new Array(5);\n\n\n for (var i = 0; i < data.length; i++) {\n data[i] = new Array(2);\n }\n\n for (var i = 0; i < data2.length; i++) {\n data2[i] = new Array(2);\n }\n\n for (var i = 0; i < data3.length; i++) {\n data3[i] = new Array(2);\n }\n\n for (var i = 0; i < data4.length; i++) {\n data4[i] = new Array(2);\n }\n \n data[0][0] = 'Keyscale';\n data[0][1] = a;\n\n for(var k = 0; k < 11; k++) {\n if(myObj[k.toString()][a] != \"\") {\n data[k][0] = k;\n data[k][1] = myObj[k.toString()][a]; \n }\n }\n\n data2[0][0] = 'Keyscale';\n data2[0][1] = a;\n\n var j = 11;\n for(var m = 1; m < 11; m++) {\n if(myObj[j.toString()][a] != \"\") {\n \n data2[m][0] = j;\n data2[m][1] = myObj[j.toString()][a]; \n j++;\n }\n }\n\n data3[0][0] = 'Keyscale';\n data3[0][1] = a;\n\n var q = 21;\n for(var m = 1; m < 11; m++) {\n if(myObj[q.toString()][a] != \"\") {\n \n data3[m][0] = q;\n data3[m][1] = myObj[q.toString()][a]; \n q++;\n }\n }\n\n data4[0][0] = 'Keyscale';\n data4[0][1] = a;\n var l = 31;\n for(var m = 1; m < 5; m++) {\n if(myObj[l.toString()][a] != \"\") {\n \n data4[m][0] = l;\n data4[m][1] = myObj[l.toString()][a]; \n l++;\n }\n }\n\n output = table(data);\n output2 = table(data2);\n output3 = table(data3);\n output4 = table(data4);\n\n msg.author.send('```\\n'+output+'\\n```');\n msg.author.send('```\\n'+output2+'\\n```');\n msg.author.send('```\\n'+output3+'\\n```');\n msg.author.send('```\\n'+output4+'\\n```'); \n}\n\nfunction myTestShowCor(a) {\n var myArray = Object.keys(myObj[a]);\n\n msg.author.send(\"**Correspondences of keyscale \"+a+ \"**\");\n\n const {table} = require('table');\n\n let output, data = new Array(5);\n\n for (var i = 0; i < data.length; i++) {\n data[i] = new Array(2);\n }\n \n var offset = 0;\n \n for(var i = 0; i < 6; i++) {\n offset = i * data.length;\n for(var m = 0; m < data.length; m++) {\n data[m][0] = myArray[offset];\n data[m][1] = myObj[a.toString()][myArray[offset]];\n offset++;\n }\n output = table(data);\n msg.author.send('```\\n'+output+'\\n```');\n } \n}\n\n\nfunction myShowCor(a) {\n var myArray = Object.keys(myObj[a]);\n\n msg.author.send(\"**Correspondences of keyscale \"+a+ \"**\");\n\n\n for(var i = 0; i < 30; i++) {\n msg.author.send(\">>> **[\" + myArray[i] + \"]**\\n\" + myObj[a.toString()][myArray[i]]+\"\\n\\n\");\n } \n}\n\nvar subc = { \"help\":0, \"keysearch\":1, \"showcol\":2, \"showcor\":3};\n \nvar x = tempVars(\"subcommand\");\nvar y = tempVars(\"key\");\nvar z = tempVars(\"column\");\n\nconst member = tempVars(\"member\");\n\nswitch(subc[x]) {\n case 0:\n myHelp();\n break;\n case 1:\n myKeysearch(y, z);\n break;\n\n case 2:\n if(y == \"from\") {\n myResults();\n myShowCol(z);\n }\n break;\n\n case 3:\n myResults();\n myTestShowCor(y);\n break;\n default:\n}",
"storage": "0",
"varName": "",
"name": "Run Script"
}
]
},
{
"name": "ator",
"permissions": "NONE",
"restriction": "1",
"_id": "rhJWf",
"actions": [
{
"info": "1",
"infoIndex": "1",
"storage": "1",
"varName": "mySay",
"name": "Store Command Params"
},
{
"storage": "3",
"varName": "lastReply",
"storage2": "3",
"varName2": "lastReply",
"name": "Transfer Variable"
},
{
"behavior": "0",
"interpretation": "1",
"code": "const cleverbot = require(\"cleverbot-free\");\n \n// Without context\n\ncleverbot(tempVars(\"mySay\"), [globalVars(\"lastSay\"), globalVars(\"lastReply\")]).then(response => { \tthis.storeValue(response, 3, \"lastReply\", cache); msg.reply(response)})\n \n//.then(response => msg.reply(response))\n //.then(response => await globalVars(\"lastReply\") = response)\n //.then(response => msg.reply(\"test\"))\n//cleverbot(\"Bad.\", [\"Hi.\", \"How are you?\"]).then(response => /*...*/);\n\n",
"storage": "3",
"varName": "lastReply",
"name": "Run Script"
},
{
"info": "1",
"infoIndex": "1",
"storage": "3",
"varName": "lastSay",
"name": "Store Command Params"
}
]
},
{
"name": "liber220",
"permissions": "NONE",
"restriction": "1",
"_id": "ypurc",
"actions": [
{
"info": "0",
"infoIndex": "1",
"storage": "1",
"varName": "chapter",
"name": "Store Command Params"
},
{
"info": "1",
"infoIndex": "2",
"storage": "1",
"varName": "verse",
"name": "Store Command Params"
},
{
"behavior": "0",
"interpretation": "1",
"code": "function getRandomInt(max) {\n return Math.floor(Math.random() * Math.floor(max));\n}\n\nfunction getResults(chapter, verse) {\n /* Embedded message information */\n const Discord = require('discord.js');\n\n var a = 0;\n\n if((chapter == \"I\")||(chapter == \"II\")||(chapter == \"III\")) {\n if(chapter == \"I\") {\n if((verse > 0) && (verse < 67 )) {\n a = 1;\n }\n }\n if(chapter == \"II\") {\n if((verse > 0) && (verse < 80 )) {\n a = 1;\n }\n }\n if(chapter == \"III\") {\n if((verse > 0) && (verse < 76 )) {\n a = 1;\n }\n } \n }\n if(a == 1) {\n const exampleEmbed = new Discord.MessageEmbed()\n\t .setColor('#0099ff')\n\t .setTitle('Liber Al Chapter '+chapter+ ' Verse '+verse)\n\t .setAuthor('ATOR', 'https://i.imgur.com/RGt5nhd.jpg', 'https://discord.js.org')\n\t .setDescription('\\\"'+liberAl[lookUpConvert[chapter]][verse]+'\\\"')\n\t .setThumbnail('https://i.imgur.com/RGt5nhd.jpg')\n\t .setTimestamp()\n\t .setFooter('Do androids dream of electric sheep?', 'https://i.imgur.com/RGt5nhd.jpg');\n\n msg.channel.send(exampleEmbed);\n }\n}\n\nfunction myBibliomancy() {\n var myRandChapter = getRandomInt(3);\n var myRandVerse;\n\n var myTrans = { 0:\"I\", 1:\"II\", 2:\"III\" };\n\n switch(myRandChapter) {\n case 0: \n myRandVerse = getRandomInt(66);\n break;\n\n case 1:\n myRandVerse = getRandomInt(79);\n break;\n\n case 2:\n myRandVerse = getRandomInt(75);\n break;\n }\n getResults(myTrans[myRandChapter], myRandVerse);\n //msg.channel.send(myChapter);\n\n}\n\nfunction displayHelp() {\n/* Embedded message information */\n const Discord = require('discord.js');\n\n const exampleEmbed = new Discord.MessageEmbed()\n\t.setColor('#0099ff')\n\t.setTitle('How to use liber220')\n\t.setAuthor('ATOR', 'https://i.imgur.com/RGt5nhd.jpg', 'https://discord.js.org')\n\t.setDescription('!liber220 <chapter><verse> or !liber220 bibliomancy')\n\t.setThumbnail('https://i.imgur.com/RGt5nhd.jpg')\n\n\t.setTimestamp()\n\t.setFooter('Do androids dream of electric sheep?', 'https://i.imgur.com/RGt5nhd.jpg');\n\n msg.channel.send(exampleEmbed);\n}\n\nconst liberAl = require('./liber220.json'); \nconst lookUpConvert = { \"I\":0, \"II\":1, \"III\":2 };\n\n/* var y = parseInt(temp); */\n\nvar a, b = 0;\nx = tempVars(\"chapter\");\n\n\n/* console logging */\nvar myTimeStamp = new Date().toLocaleString();\n\nconsole.log(\"[\"+myTimeStamp+\"] :: !liber220 \"+ tempVars(\"chapter\")+\" \"+tempVars(\"verse\"));\n\nfunction getResultsTest() {\n getResults(0,0);\n}\n\nswitch(x) {\n case \"help\":\n displayHelp();\n break;\n\n case \"bibliomancy\":\n myBibliomancy();\n break;\n\n default:\n x = tempVars(\"chapter\").toUpperCase();\n y = tempVars(\"verse\").replace(/[^0-9]*$/i,'');\n getResults(x, y);\n\n}\n\n\n\n",
"storage": "0",
"varName": "",
"name": "Run Script"
}
]
},
{
"name": "gem",
"permissions": "NONE",
"restriction": "1",
"_id": "OqtUh",
"actions": [
{
"info": "0",
"infoIndex": "1",
"storage": "1",
"varName": "cipher",
"name": "Store Command Params"
},
{
"info": "1",
"infoIndex": "2",
"storage": "1",
"varName": "myTest",
"name": "Store Command Params"
},
{
"behavior": "0",
"interpretation": "1",
"code": "/* Gematria function */\nfunction myGematria(myCipher, myWord) {\n var x = 0;\n\n for(var i = 0; i < myWord.length; i++) {\n x = x + parseInt(myCipher[myWord[i]]);\n }\n return x;\n}\n\nfunction gemResults() {\n\n/* Embedded message information */\nconst Discord = require('discord.js');\n\nconst exampleEmbed = new Discord.MessageEmbed()\n\t.setColor('#0099ff')\n\t.setTitle('Gematria Calculator')\n\t.setAuthor('ATOR', 'https://i.imgur.com/RGt5nhd.jpg', 'https://discord.js.org')\n\t.setDescription(cipherTitle[menu[option]])\n\t.setThumbnail('https://i.imgur.com/RGt5nhd.jpg')\n\t.addFields(\n\t\t{ name: cipherLinks[menu[option]][0] +'\\\"'+a+'\\\"'+' is', value: b },\n\t\t{ name: 'See corresponding words and phrases in the following links', value: '>>> [mysticalnet.com]\\n'+cipherLinks[menu[option]][1]+b+'\\n\\n[biblewheel.com]\\n'+cipherLinks[menu[option]][2]+b+'\\n\\n[wikipedia.com]\\n'+cipherLinks[menu[option]][3]+b+'_(number)'}\n )\n\t.setTimestamp()\n\t.setFooter('Do androids dream of electric sheep?', 'https://i.imgur.com/RGt5nhd.jpg');\n\n msg.channel.send(exampleEmbed);\n}\n\nfunction gemNumResults(a) {\n\n/* Embedded message information */\nconst Discord = require('discord.js');\n\nconst exampleEmbed = new Discord.MessageEmbed()\n\t.setColor('#0099ff')\n\t.setTitle('Gematria Calculator')\n\t.setAuthor('ATOR', 'https://i.imgur.com/RGt5nhd.jpg', 'https://discord.js.org')\n\t.setDescription(cipherTitle[menu[option]])\n\t.setThumbnail('https://i.imgur.com/RGt5nhd.jpg')\n\t.addFields(\n\t\t{ name: 'See corresponding words and phrases in the following links', value: '>>> [mysticalnet.com]\\n'+cipherLinks[1][1]+a+'\\n\\n[biblewheel.com]\\n'+cipherLinks[menu[option]][2]+a+'\\n\\n[wikipedia.com]\\n'+cipherLinks[menu[option]][3]+a+'_(number)'}\n )\n\t.setTimestamp()\n\t.setFooter('Do androids dream of electric sheep?', 'https://i.imgur.com/RGt5nhd.jpg');\n\n msg.channel.send(exampleEmbed);\n}\n\n/* usage function */\nfunction gemUsage() {\n\n /* Embedded message information */\nconst Discord = require('discord.js');\n\nconst exampleEmbed = new Discord.MessageEmbed()\n\t.setColor('#0099ff')\n\t.setTitle('How to use !gem')\n\t.setAuthor('ATOR', 'https://i.imgur.com/RGt5nhd.jpg', 'https://discord.js.org')\n\t.setDescription('!gem <gematria system><unicode string>')\n\t.setThumbnail('https://i.imgur.com/RGt5nhd.jpg')\n\t.addFields(\n\t\t{ name: 'naeq', value: '>>> !gem naeq <english string>' },\n { name: 'heb', value: '>>> !gem heb <unicode Hebrew string>' },\n { name: 'grk', value: '>>> !gem naeq <unicode Greek string without accents >' },\n { name: 'val', value: '>>> !gem val <number that you want to lookup>' },\n )\n\t.setTimestamp()\n\t.setFooter('Do androids dream of electric sheep?', 'https://i.imgur.com/RGt5nhd.jpg');\n\n msg.channel.send(exampleEmbed);\n}\n\n/* Cipher lookup tables */\nconst hebCipher = {\"א\":\"1\",\"ב\":\"2\",\"ג\":\"3\",\"ד\":\"4\",\"ה\":\"5\",\"ו\":\"6\",\"ז\":\"7\",\"ח\":\"8\",\"ט\":\"9\",\"י\":\"10\",\"כ\":\"20\",\"ל\":\"30\",\"מ\":\"40\",\"נ\":\"50\",\"ס\":\"60\",\"ע\":\"70\",\"פ\":\"80\",\"צ\":\"90\",\"ק\":\"100\",\"ר\":\"200\",\"ש\":\"300\",\"ת\":\"400\",\"ך\":\"500\",\"ם\":\"600\",\"ן\":\"700\",\"ף\":\"800\",\"ץ\":\"900\"};\nconst grkCipher = {\"\":\"0\",\"α\":\"1\",\"β\":\"2\",\"γ\":\"3\",\"δ\":\"4\",\"ε\":\"5\",\"ϛ\":\"6\",\"ζ\":\"7\",\"η\":\"8\",\"θ\":\"9\",\"ι\":\"10\",\"κ\":\"20\",\"λ\":\"30\",\"μ\":\"40\",\"ν\":\"50\",\"ξ\":\"60\",\"ο\":\"70\",\"π\":\"80\",\"ϙ\":\"90\",\"ρ\":\"100\",\"σ\":\"200\",\"ς\":\"200\",\"τ\":\"300\",\"υ\":\"400\",\"φ\":\"500\",\"χ\":\"600\",\"ψ\":\"700\",\"ω\":\"800\",\"ϡ\":\"900\", \"Α\":\"1\",\"Β\":\"2\",\"Γ\":\"3\",\"Δ\":\"4\",\"Ε\":\"5\",\"Ϛ\":\"6\",\"Ζ\":\"7\",\"Η\":\"8\",\"Θ\":\"9\",\"Ι\":\"10\",\"Κ\":\"20\",\"Λ\":\"30\",\"Μ\":\"40\",\"Ν\":\"50\",\"Ξ\":\"60\",\"Ο\":\"70\",\"Π\":\"80\",\"Ϙ\":\"90\",\"Ρ\":\"100\",\"Σ\":\"200\",\"Τ\":\"300\",\"Υ\":\"400\",\"Φ\":\"500\",\"Χ\":\"600\",\"Ψ\":\"700\",\"Ω\":\"800\",\"Ϡ\":\"900\"};\nconst naeqCipher = {\"a\":\"1\",\"b\":\"20\",\"c\":\"13\",\"d\":\"6\",\"e\":\"25\",\"f\":\"18\",\"g\":\"11\",\"h\":\"4\",\"i\":\"23\",\"j\":\"16\",\"k\":\"9\",\"l\":\"2\",\"m\":\"21\",\"n\":\"14\",\"o\":\"7\",\"p\":\"26\",\"q\":\"19\",\"r\":\"12\",\"s\":\"5\",\"t\":\"24\",\"u\":\"17\",\"v\":\"10\",\"w\":\"3\",\"x\":\"22\",\"y\":\"15\",\"z\":\"8\",\"A\":\"1\",\"B\":\"20\",\"C\":\"13\",\"D\":\"6\",\"E\":\"25\",\"F\":\"18\",\"G\":\"11\",\"H\":\"4\",\"I\":\"23\",\"J\":\"16\",\"K\":\"9\",\"L\":\"2\",\"M\":\"21\",\"N\":\"14\",\"O\":\"7\",\"P\":\"26\",\"Q\":\"19\",\"R\":\"12\",\"S\":\"5\",\"T\":\"24\",\"U\":\"17\",\"V\":\"10\",\"W\":\"3\",\"X\":\"22\",\"Y\":\"15\",\"Z\":\"8\"};\n\n/* cipher title list */\nconst cipherTitle = ['nuthin', 'NAEQ cipher', 'Hebrew cipher', 'Greek cipher', 'Numeric value lookup'];\n\n/* Cipher message and URLS */\nconst cipherLinks = [ \n ['defn','link1', 'link2', 'link3'],\n ['The NAEQ value of ','http://mysticalinternet.com/gematria/lookup.php?system=naeq&word=','https://www.biblewheel.com/GR/GR_Database.php?Gem_Num=', 'https://en.wikipedia.org/wiki/'],\n ['The Hebrew gematria value of ', 'http://mysticalinternet.com/gematria/lookup.php?system=hebrew&word=','https://www.biblewheel.com/GR/GR_Database.php?Gem_Num=', 'https://en.wikipedia.org/wiki/'],\n ['The Greek gematria value of ', 'http://mysticalinternet.com/gematria/lookup.php?system=greek&word=','https://www.biblewheel.com/GR/GR_Database.php?Gem_Num=', 'https://en.wikipedia.org/wiki/'],\n ['Correspondences ', 'http://mysticalinternet.com/gematria/lookup.php?system=greek&word=','https://www.biblewheel.com/GR/GR_Database.php?Gem_Num=', 'https://en.wikipedia.org/wiki/']\n];\n\n\nvar a;\nvar b;\n\n\n/* The menu object */\nvar menu = { \"help\":0, \"naeq\":1, \"heb\":2, \"grk\":3, \"val\":4};\n\n/* Menu option variable */\nvar option = tempVars(\"cipher\").toLowerCase(); \n\n/* console logging */\nvar myTimeStamp = new Date().toLocaleString();\n\nconsole.log(\"[\"+myTimeStamp+\"] :: !gem \"+ tempVars(\"cipher\")+\" \"+tempVars(\"myTest\"));\n\n/* menu switch */\nswitch(menu[option]) {\n case 0:\n gemUsage();\n break;\n\n case 1: /* NAEQ */\n a = tempVars(\"myTest\").replace(/[^a-z]/gi, '');\n b = myGematria(naeqCipher, a);\n gemResults();\n break;\n\n case 2: /* HEBREW */\n a = tempVars(\"myTest\").replace(/[^\\u05D0-\\u05EA]/gi, '');\n b = myGematria(hebCipher, a);\n gemResults();\n break;\n\n case 3: /* GREEK */\n a = tempVars(\"myTest\").replace(/[^\\u0391-\\u03C9\\u03DA\\u03DB]/gi, '');\n b = myGematria(grkCipher, a);\n gemResults();\n break;\n\n case 4: /* number lookup */\n a = tempVars(\"myTest\").replace(/[^0-9]*$/i,'');\n if(a != \"\") {\n b = gemNumResults(a);\n }\n else {\n msg.channel.send(\"Try using a numeric value with !gem val. For example :: !gem val 156\");\n }\n break;\n\n \n default:\n}\n\n",
"storage": "0",
"varName": "",
"name": "Run Script"
}
]
},
{
"name": "geomancy",
"permissions": "NONE",
"restriction": "1",
"_id": "smPVY",
"actions": []
},
{
"name": "atorhelp",
"permissions": "NONE",
"restriction": "1",
"_id": "gGSdX",
"actions": [
{
"behavior": "0",
"interpretation": "1",
"code": "const cleverbot = require(\"cleverbot-free\");\n \n// Without context\ncleverbot(\"Help\").then(response => msg.reply(response +\" Check your private messages!\"))\n\nconst Discord = require('discord.js');\n\nlet Embed = new Discord.MessageEmbed()\n .setTitle()\n .setAuthor()\n .setColor()\n .addField()\n .setDescription()\n .setThumbnail()\n\nmsg.author.send({embed: {\n color: 3447003,\n author: {\n name: client.user.username,\n icon_url: client.user.avatarURL\n },\n title: \"Here is a list of the commands that I support.\",\n description: \"```!rule !ator !say !gem\\n!777 !qc !lisp !quranomancy\\n!liber220 !date``` \",\n fields: [{\n \"name\": \"!rule\",\n \"value\": \"```\\nDisplays 1D Cellular Automata\\n\\n!rule <rule number>\\n```\"\n },\n {\n \"name\": \"!ator\",\n \"value\": \"```\\nGeneral chatbot command.\\n\\n!ator <text>\\n```\\n\"\n },\n {\n \"name\": \"!gem\",\n \"value\": \"```\\nGematria related commands.\\n\\n[1] !gem heb <unicode Hebrew string> - Displays Hebrew gematria values of a string.\\n[2] !gem grk <unicode Greek string> - Displays Greek gematria values of a string.\\n[3] !gem naeq <English string> - Displays Naeq Aeon English Qabalah gematria of a string.\\n[4] !gem val <##>\\n```\"\n },\n {\n \"name\": \"!quranomancy\",\n \"value\": \"```\\nReturns random surah from the Quran.\\n```\"\n },\n {\n \"name\": \"!777\",\n \"value\": \"```\\nLiber 777 data tool.\\n\\n[1] !777 showcor <key>\\n[2] !777 showcol from <column>\\n[3] !777 keysearch <key><column>\\n```\"\n },\n {\n \"name\": \"!date\",\n \"value\": \"```\\nDisplays current Thelemic date\\n```\"\n },\n {\n \"name\": \"!qc\",\n \"value\": \"```\\nQuantum Computer. Evaluates and draws quantum circuits from text representations of quantum code.\\n\\n[1] !qc showcirq <text quantum circuit>\\n[2] !qc evalcirq <text quantum circuit>\\n```\\n\\n\"\n },\n {\n \"name\": \"!lisp\",\n \"value\": \"```\\nVery limited LISP interpreter.\\n\\n!lisp <code>\\n```\"\n },\n {\n \"name\": \"!say\",\n \"value\": \"```\\nI'll repeat whatever you type.\\n\\n!say <text>\\n```\"\n },\n {\n \"name\": \"!liber220\",\n \"value\": \"```\\nDisplays verses from Liber Al Vel Legis.\\n\\n[1] !liber220 bibliomancy\\n[2] !liber220 <chapter><verse>\\n```\\n\\n\"\n }]\n }});\n \n",
"storage": "0",
"varName": "",
"name": "Run Script"
}
]
},
{
"name": "date",
"permissions": "NONE",
"restriction": "1",
"_id": "IxaME",
"actions": [
{
"behavior": "0",
"interpretation": "0",
"code": "/* console logging */\nvar myTimeStamp = new Date().toLocaleString();\n\nconsole.log(\"[\"+myTimeStamp+\"] :: !date\");\n\nconst fetch = require('node-fetch');\n\nfetch('http://thelema.tools/date_plain2.php')\n .then(res => res.text())\n .then(text => myDate(text.replace(/<[^>]*>?/gm, '')));\n\nfunction myDate(a) {\n\n/* Embedded message information */\n const Discord = require('discord.js');\n\n const exampleEmbed = new Discord.MessageEmbed()\n\t.setColor('#0099ff')\n\t.setTitle('Today\\'s Thelemic date')\n\t.setAuthor('ATOR', 'https://i.imgur.com/RGt5nhd.jpg', 'https://discord.js.org')\n\t.setDescription(a)\n\t.setThumbnail('https://i.imgur.com/RGt5nhd.jpg')\n\n\t.setTimestamp()\n\t.setFooter('Do androids dream of electric sheep?', 'https://i.imgur.com/RGt5nhd.jpg');\n\n msg.channel.send(exampleEmbed);\n}\n\n",
"storage": "0",
"varName": "",
"name": "Run Script"
}
]
}
]