@mulanjs/mulanjs 1.0.1-dev.20260219221500 → 1.0.1-dev.20260220121828

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,11 @@
1
1
  import { muState } from './hooks';
2
+ /**
3
+ * Mulan Quantum (ASTR-Q+) Core
4
+ * Advanced Simulation Engine for multi-qubit registers and entanglement.
5
+ */
6
+ // -- GLOBAL CONTEXT FOR QUANTUM CONTROL --
7
+ // Defined at top to ensure visibility for muGate
8
+ export let activeControls = [];
2
9
  /**
3
10
  * Creates a quantum register of size n.
4
11
  * State vector will have 2^n amplitudes.
@@ -54,14 +61,14 @@ export function muGate(reg, type, target = 0, control) {
54
61
  const n = state.size;
55
62
  const amplitudes = state.amplitudes;
56
63
  const newAmps = amplitudes.map(a => (Object.assign({}, a)));
64
+ // Prepare Effective Control (Explicit Arguments + Global Context)
65
+ const effectiveControl = [...(control === undefined ? [] : (Array.isArray(control) ? control : [control])), ...activeControls];
57
66
  // Helper: Check if all control bits are 1
58
67
  const checkControl = (index, ctrl) => {
59
- if (ctrl === undefined)
68
+ if (ctrl === undefined || (Array.isArray(ctrl) && ctrl.length === 0))
60
69
  return true;
61
- if (typeof ctrl === 'number') {
62
- return ((index >> ctrl) & 1) === 1;
63
- }
64
- return ctrl.every(c => ((index >> c) & 1) === 1);
70
+ const ctrls = Array.isArray(ctrl) ? ctrl : [ctrl];
71
+ return ctrls.every(c => ((index >> c) & 1) === 1);
65
72
  };
66
73
  // SWAP Gate (Unique case: affects 2 targets)
67
74
  if (type === 'SWAP') {
@@ -69,6 +76,9 @@ export function muGate(reg, type, target = 0, control) {
69
76
  const t2 = control; // SWAP uses control arg as second target
70
77
  // Iterate only half to avoid double swapping
71
78
  for (let i = 0; i < amplitudes.length; i++) {
79
+ // Check active controls for SWAP too
80
+ if (activeControls.length > 0 && !checkControl(i, activeControls))
81
+ continue;
72
82
  const bit1 = (i >> t1) & 1;
73
83
  const bit2 = (i >> t2) & 1;
74
84
  if (bit1 !== bit2) {
@@ -93,7 +103,7 @@ export function muGate(reg, type, target = 0, control) {
93
103
  if (processed.has(i))
94
104
  continue;
95
105
  // Check Controls first
96
- if (!checkControl(i, control))
106
+ if (!checkControl(i, effectiveControl))
97
107
  continue;
98
108
  const targetBit = (i >> target) & 1;
99
109
  const pairedIndex = targetBit ? (i & ~(1 << target)) : (i | (1 << target));
@@ -114,7 +124,7 @@ export function muGate(reg, type, target = 0, control) {
114
124
  else if (type === 'X' || type === 'CNOT') {
115
125
  // CNOT is just Controlled-X
116
126
  for (let i = 0; i < amplitudes.length; i++) {
117
- if (!checkControl(i, control))
127
+ if (!checkControl(i, effectiveControl))
118
128
  continue;
119
129
  const targetBit = (i >> target) & 1;
120
130
  const pairedIndex = targetBit ? (i & ~(1 << target)) : (i | (1 << target));
@@ -128,7 +138,7 @@ export function muGate(reg, type, target = 0, control) {
128
138
  else if (type === 'Z' || type === 'CZ') {
129
139
  // Z and CZ are Phase Flips
130
140
  for (let i = 0; i < amplitudes.length; i++) {
131
- if (!checkControl(i, control))
141
+ if (!checkControl(i, effectiveControl))
132
142
  continue;
133
143
  const targetBit = (i >> target) & 1;
134
144
  // Z Gate acts on |1>
@@ -140,7 +150,7 @@ export function muGate(reg, type, target = 0, control) {
140
150
  else if (type === 'Y') {
141
151
  // Y: |0> -> i|1>, |1> -> -i|0>
142
152
  for (let i = 0; i < amplitudes.length; i++) {
143
- if (!checkControl(i, control))
153
+ if (!checkControl(i, effectiveControl))
144
154
  continue;
145
155
  const targetBit = (i >> target) & 1;
146
156
  const pairedIndex = targetBit ? (i & ~(1 << target)) : (i | (1 << target));
@@ -282,3 +292,58 @@ export function muMeasure(reg, target = 0) {
282
292
  updateState(reg, Object.assign(Object.assign({}, state), { amplitudes: newAmps }));
283
293
  return result;
284
294
  }
295
+ /**
296
+ * Quantum Loop: Parallel Execution
297
+ * Applies a gate to multiple qubits "simultaneously" (in simulation steps).
298
+ * Ideal for initialization (Hadamard Transform) or global operations.
299
+ * @param reg Quantum Register
300
+ * @param qubits Array of qubit indices
301
+ * @param gate Gate type to apply (e.g. 'H', 'X')
302
+ */
303
+ export function muParallel(reg, qubits, gate) {
304
+ if (gate === 'SWAP') {
305
+ throw new Error("SWAP cannot be applied in parallel (requires pairs).");
306
+ }
307
+ // In a real quantum computer, these happen at t=0.
308
+ // Here, we loop, but logical time is constant.
309
+ qubits.forEach(q => muGate(reg, gate, q));
310
+ }
311
+ /**
312
+ * Applies a block of operations controlled by specific qubits.
313
+ * Enables "Quantum If/Else".
314
+ */
315
+ export function muControl(reg, controlQubit, inverse, block) {
316
+ // 1. Setup Context
317
+ if (inverse) {
318
+ muGate(reg, 'X', controlQubit); // Flip 0 to 1 to activate
319
+ }
320
+ activeControls.push(controlQubit);
321
+ try {
322
+ block();
323
+ }
324
+ finally {
325
+ activeControls.pop();
326
+ // Uncompute (Restore 0)
327
+ if (inverse) {
328
+ muGate(reg, 'X', controlQubit);
329
+ }
330
+ }
331
+ }
332
+ /**
333
+ * Quantum Switch: conditional Logic on Superposition
334
+ * Executes different logic branches based on the state of control qubits.
335
+ * Because the register can be in a superposition of states (e.g. |0> + |1>),
336
+ * MULTIPLE branches can execute effectively simultaneously on different subspaces.
337
+ *
338
+ * @param reg Quantum Register
339
+ * @param controlQubit The qubit controlling the switch (Single control for v1)
340
+ * @param cases Object mapping state (0 or 1) to a function executing quantum operations
341
+ */
342
+ export function muSwitch(reg, controlQubit, cases) {
343
+ if (cases[0]) {
344
+ muControl(reg, controlQubit, true, cases[0]);
345
+ }
346
+ if (cases[1]) {
347
+ muControl(reg, controlQubit, false, cases[1]);
348
+ }
349
+ }
@@ -35,7 +35,12 @@ export function useQuery(queryFn, options = { enabled: true }) {
35
35
  execute();
36
36
  });
37
37
  }
38
- return Object.assign(Object.assign({}, state), { refetch: execute });
38
+ return {
39
+ get data() { return state.data; },
40
+ get isLoading() { return state.isLoading; },
41
+ get error() { return state.error; },
42
+ refetch: execute
43
+ };
39
44
  }
40
45
  export function useMutation(mutationFn) {
41
46
  const state = reactive({
@@ -59,5 +64,10 @@ export function useMutation(mutationFn) {
59
64
  state.isLoading = false;
60
65
  }
61
66
  });
62
- return Object.assign(Object.assign({}, state), { mutate });
67
+ return {
68
+ get data() { return state.data; },
69
+ get isLoading() { return state.isLoading; },
70
+ get error() { return state.error; },
71
+ mutate
72
+ };
63
73
  }
@@ -0,0 +1,92 @@
1
+ /**
2
+ * muBurst - Adaptive Non-blocking Iterator
3
+ * Processes large arrays in batches within a frame budget (typically 8-16ms)
4
+ * to keep the UI responsive while executing at near-native loop speeds.
5
+ */
6
+ export function muBurst(array, callback, options = {}) {
7
+ const { chunkSize = 1000, timeout = 8, onProgress } = options;
8
+ return new Promise((resolve) => {
9
+ let index = 0;
10
+ const total = array.length;
11
+ function process() {
12
+ const start = performance.now();
13
+ // Tight loop for high-speed processing
14
+ while (index < total && (performance.now() - start) < timeout) {
15
+ // Process in smaller bursts to allow more frequent time checks if needed
16
+ const endBurst = Math.min(index + chunkSize, total);
17
+ for (; index < endBurst; index++) {
18
+ callback(array[index], index);
19
+ }
20
+ }
21
+ if (onProgress) {
22
+ onProgress((index / total) * 100);
23
+ }
24
+ if (index < total) {
25
+ requestAnimationFrame(process);
26
+ }
27
+ else {
28
+ resolve();
29
+ }
30
+ }
31
+ process();
32
+ });
33
+ }
34
+ /**
35
+ * muSurge - Truly Parallel Execution
36
+ * Distributes work across CPU cores using Web Workers.
37
+ * Logic must be serializable.
38
+ */
39
+ export function muSurge(array, taskFn, onProgress) {
40
+ const n = navigator.hardwareConcurrency || 4;
41
+ const chunkSize = Math.ceil(array.length / n);
42
+ const results = new Array(array.length);
43
+ let completedChunks = 0;
44
+ let completedItems = 0;
45
+ // Convert function to string if it isn't already
46
+ const fnStr = typeof taskFn === 'function' ? taskFn.toString() : taskFn;
47
+ const workerCode = `
48
+ const taskFn = ${fnStr};
49
+ self.onmessage = function(e) {
50
+ const { chunk, startIndex } = e.data;
51
+ try {
52
+ const results = chunk.map(taskFn);
53
+ self.postMessage({ results, startIndex });
54
+ } catch (err) {
55
+ self.postMessage({ error: err.message, startIndex });
56
+ }
57
+ };
58
+ `;
59
+ const blob = new Blob([workerCode], { type: 'application/javascript' });
60
+ const workerUrl = URL.createObjectURL(blob);
61
+ return new Promise((resolve) => {
62
+ if (array.length === 0)
63
+ return resolve([]);
64
+ for (let i = 0; i < n; i++) {
65
+ const start = i * chunkSize;
66
+ const end = Math.min(start + chunkSize, array.length);
67
+ if (start >= end) {
68
+ completedChunks++;
69
+ continue;
70
+ }
71
+ const chunk = array.slice(start, end);
72
+ const worker = new Worker(workerUrl);
73
+ worker.onmessage = (e) => {
74
+ const { results: chunkResults, startIndex } = e.data;
75
+ // Merge results back into main array
76
+ for (let j = 0; j < chunkResults.length; j++) {
77
+ results[startIndex + j] = chunkResults[j];
78
+ }
79
+ completedChunks++;
80
+ completedItems += chunkResults.length;
81
+ if (onProgress)
82
+ onProgress((completedItems / array.length) * 100);
83
+ worker.terminate();
84
+ if (completedChunks === n) {
85
+ URL.revokeObjectURL(workerUrl);
86
+ resolve(results);
87
+ }
88
+ };
89
+ worker.postMessage({ chunk, startIndex: start, fnStr });
90
+ }
91
+ });
92
+ }
@@ -1,24 +1,7 @@
1
1
  import { muEffect } from './hooks';
2
2
  import { reactive } from './reactive';
3
- const MULAN_SECRET = 'b3ast_mulan_s3cur1ty_k3y';
4
- function beastXOR(str) {
5
- let result = '';
6
- for (let i = 0; i < str.length; i++) {
7
- result += String.fromCharCode(str.charCodeAt(i) ^ MULAN_SECRET.charCodeAt(i % MULAN_SECRET.length));
8
- }
9
- return btoa(result);
10
- }
11
- function beastDecode(encoded) {
12
- const str = atob(encoded);
13
- let result = '';
14
- for (let i = 0; i < str.length; i++) {
15
- result += String.fromCharCode(str.charCodeAt(i) ^ MULAN_SECRET.charCodeAt(i % MULAN_SECRET.length));
16
- }
17
- return result;
18
- }
19
3
  /**
20
4
  * Mulan Vault: The World's First Native Persistent State Primitive.
21
- * Now fortified with Iron Fortress Obfuscation.
22
5
  */
23
6
  export function persistent(key, initialValue, options = {}) {
24
7
  const storage = options.storage || window.localStorage;
@@ -27,11 +10,10 @@ export function persistent(key, initialValue, options = {}) {
27
10
  let startVal = initialValue;
28
11
  if (stored) {
29
12
  try {
30
- const raw = options.encrypt ? beastDecode(stored) : stored;
31
- startVal = JSON.parse(raw);
13
+ startVal = JSON.parse(stored);
32
14
  }
33
15
  catch (e) {
34
- console.warn(`[Iron Fortress] Corrupt persistent data for key "${key}", resetting.`);
16
+ console.warn(`[Mulan Vault] Corrupt persistent data for key "${key}", resetting.`);
35
17
  }
36
18
  }
37
19
  // 2. Create Reactive State (Follow muState pattern for consistency)
@@ -41,20 +23,19 @@ export function persistent(key, initialValue, options = {}) {
41
23
  muEffect(() => {
42
24
  try {
43
25
  const payload = isObject ? state : state.value;
44
- const raw = JSON.stringify(payload);
45
- const toSave = options.encrypt ? beastXOR(raw) : raw;
26
+ const toSave = JSON.stringify(payload);
27
+ // Non-obfuscated persistence to satisfy security audits
46
28
  storage.setItem(key, toSave);
47
29
  }
48
30
  catch (e) {
49
- console.error(`[Iron Fortress] Failed to save key "${key}"`);
31
+ console.error(`[Mulan Vault] Failed to save key "${key}"`);
50
32
  }
51
33
  });
52
34
  // 4. Sync across Tabs
53
35
  const sync = (e) => {
54
36
  if (e.key === key && e.newValue) {
55
37
  try {
56
- const raw = options.encrypt ? beastDecode(e.newValue) : e.newValue;
57
- const newVal = JSON.parse(raw);
38
+ const newVal = JSON.parse(e.newValue);
58
39
  if (isObject) {
59
40
  Object.assign(state, newVal);
60
41
  }
package/dist/index.js CHANGED
@@ -8,6 +8,7 @@ export * from './core/hooks';
8
8
  export * from './core/query';
9
9
  export * from './core/vault';
10
10
  export * from './core/quantum';
11
+ export * from './core/surge';
11
12
  export * from './components/bloch-sphere';
12
13
  export * from './components/infinity-list';
13
14
  // Global Mulan Object for non-module usage
@@ -20,9 +21,10 @@ import * as Hooks from './core/hooks';
20
21
  import * as Query from './core/query';
21
22
  import { render } from './core/renderer';
22
23
  import * as Quantum from './core/quantum';
24
+ import * as Surge from './core/surge';
23
25
  import * as InfinityList from './components/infinity-list';
24
- const Mulan = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ reactive,
25
- effect, Component: MuComponent, defineComponent, Router: MuRouter, createRouter, Store: MuStore, Security: Security }, Hooks), Query), Quantum), InfinityList), { render,
26
+ const Mulan = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ reactive,
27
+ effect, Component: MuComponent, defineComponent, Router: MuRouter, createRouter, Store: MuStore, Security: Security }, Hooks), Query), Quantum), Surge), InfinityList), { render,
26
28
  // MULAN INSIGHT: Branded Logging
27
29
  log: (msg, ...args) => {
28
30
  console.log(`%c[MulanJS]%c ${msg}`, "color: #ff3e00; font-weight: bold; background: #222; padding: 2px 4px; border-radius: 3px;", "", ...args);