| Object subclass: #BobQuantumLibrary
|
| instanceVariableNames: 'libraryHandle functionCache'
|
| classVariableNames: 'UniqueInstance'
|
| package: 'BOB-Quantum-FFI'
|
|
|
| BobQuantumLibrary class >> initialize [
|
| UniqueInstance := nil.
|
| ]
|
|
|
| BobQuantumLibrary class >> current [
|
| ^ UniqueInstance ifNil: [ UniqueInstance := self basicNew initializeLibrary; yourself ]
|
| ]
|
|
|
| BobQuantumLibrary class >> reset [
|
| UniqueInstance := nil.
|
| ]
|
|
|
| BobQuantumLibrary >> initializeLibrary [
|
| libraryHandle := nil.
|
| functionCache := IdentityDictionary new.
|
| ^ self loadLibrary
|
| ]
|
|
|
| BobQuantumLibrary >> loadLibrary [
|
| | libName |
|
| libName := self libraryNameForPlatform.
|
| [ libraryHandle := ExternalLibrary open: libName ]
|
| on: Error
|
| do: [ :ex |
|
| self error: 'Failed to load BOB Quantum library: ', libName, '. Error: ', ex messageText
|
| ].
|
| ^ self
|
| ]
|
|
|
| BobQuantumLibrary >> libraryNameForPlatform [
|
| ^ (Smalltalk platform name = 'unix' or: [ Smalltalk platform name = 'macos' ])
|
| ifTrue: [ 'bob_quantum' ]
|
| ifFalse: [ 'bob_quantum.dll' ]
|
| ]
|
|
|
| BobQuantumLibrary >> function: aSymbol [
|
| ^ functionCache
|
| at: aSymbol
|
| ifAbsentPut: [ self lookupFunction: aSymbol ]
|
| ]
|
|
|
| BobQuantumLibrary >> lookupFunction: aSymbol [
|
| | funcSpec returnType argTypes func |
|
| funcSpec := self functionSpecFor: aSymbol.
|
| returnType := funcSpec first.
|
| argTypes := funcSpec second.
|
| func := ExternalFunction
|
| library: libraryHandle
|
| function: aSymbol asString
|
| returnType: returnType
|
| argTypes: argTypes.
|
| ^ func
|
| ]
|
|
|
| BobQuantumLibrary >> functionSpecFor: aSymbol [
|
| |
|
|
| ^ {
|
| #bob_rng_create -> #(#pointer #(#uint)).
|
| #bob_rng_destroy -> #(#void #(#pointer)).
|
| #bob_rng_next_uint32 -> #(#uint #(#pointer)).
|
| #bob_rng_next_double -> #(#double #(#pointer)).
|
| #bob_rng_next_gaussian -> #(#double #(#pointer #double #double)).
|
|
|
| #bob_lattice_create -> #(#pointer #(#int #int #int #double)).
|
| #bob_lattice_destroy -> #(#void #(#pointer)).
|
| #bob_lattice_get_nx -> #(#int #(#pointer)).
|
| #bob_lattice_get_ny -> #(#int #(#pointer)).
|
| #bob_lattice_get_nz -> #(#int #(#pointer)).
|
| #bob_lattice_get_coupling -> #(#double #(#pointer)).
|
| #bob_lattice_get_volume -> #(#int #(#pointer)).
|
| #bob_lattice_get_neighbors -> #(#pointer #(#pointer #int #pointer)).
|
| #bob_lattice_compute_coordination -> #(#int #(#pointer)).
|
|
|
| #bob_state_create -> #(#pointer #(#pointer #int)).
|
| #bob_state_destroy -> #(#void #(#pointer)).
|
| #bob_state_copy -> #(#pointer #(#pointer)).
|
| #bob_state_get_amplitude -> #(#pointer #(#pointer #int)).
|
| #bob_state_set_amplitude -> #(#void #(#pointer #int #pointer)).
|
| #bob_state_normalize -> #(#void #(#pointer)).
|
| #bob_state_inner_product -> #(#pointer #(#pointer #pointer)).
|
| #bob_state_expectation_value -> #(#double #(#pointer #pointer)).
|
| #bob_state_entropy -> #(#double #(#pointer)).
|
| #bob_state_fidelity -> #(#double #(#pointer #pointer)).
|
|
|
| #bob_hamiltonian_create -> #(#pointer #(#pointer)).
|
| #bob_hamiltonian_destroy -> #(#void #(#pointer)).
|
| #bob_hamiltonian_add_ising_term -> #(#void #(#pointer #double #int #int)).
|
| #bob_hamiltonian_add_transverse_field -> #(#void #(#pointer #double #int)).
|
| #bob_hamiltonian_add_heisenberg_term -> #(#void #(#pointer #double #int #int)).
|
| #bob_hamiltonian_add_custom_term -> #(#void #(#pointer #pointer #int)).
|
| #bob_hamiltonian_build_matrix -> #(#void #(#pointer)).
|
| #bob_hamiltonian_get_matrix -> #(#pointer #(#pointer)).
|
| #bob_hamiltonian_get_eigenvalues -> #(#pointer #(#pointer #pointer #int)).
|
|
|
| #bob_world_create -> #(#pointer #(#pointer #pointer #pointer)).
|
| #bob_world_destroy -> #(#void #(#pointer)).
|
| #bob_world_create_lattice -> #(#pointer #(#pointer #int #int #int #double)).
|
| #bob_world_run_simulation -> #(#int #(#pointer #ulong #double)).
|
| #bob_world_get_state -> #(#pointer #(#pointer)).
|
| #bob_world_get_hamiltonian -> #(#pointer #(#pointer)).
|
| #bob_world_get_lattice -> #(#pointer #(#pointer)).
|
| #bob_world_visualize -> #(#void #(#pointer #string #int #int)).
|
| #bob_world_checkpoint -> #(#int #(#pointer #string)).
|
| #bob_world_restore -> #(#int #(#pointer #string)).
|
| #bob_world_get_energy -> #(#double #(#pointer)).
|
| #bob_world_get_magnetization -> #(#double #(#pointer #int)).
|
| #bob_world_get_correlation -> #(#double #(#pointer #int #int)).
|
| } detect: [ :assoc | assoc key = aSymbol ] ifNone: [ self error: 'Unknown function: ', aSymbol ] value
|
| ]
|
|
|
| BobQuantumLibrary >> shutdown [
|
| libraryHandle ifNotNil: [ libraryHandle close. libraryHandle := nil ].
|
| functionCache := nil.
|
| ]
|
|
|
| BobQuantumLibrary >> finalize [
|
| self shutdown.
|
| ]
|
|
|
|
|
| |
| -------------------------------------------------------------------------------- |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| -------------------------------------------------------------------------------- |
| BobLattice - Spatial Lattice Structure
|
|
|
|
|
| Object subclass: #BobLattice
|
| instanceVariableNames: 'handle nx ny nz coupling volume coordinationNumber'
|
| classVariableNames: ''
|
| package: 'BOB-Quantum-FFI'
|
|
|
| BobLattice class >> create: nx ny: ny nz: nz coupling: j [
|
| ^ self basicNew initializeWith: nx ny: ny nz: nz coupling: j
|
| ]
|
|
|
| BobLattice >> initializeWith: nxArg ny: nyArg nz: nzArg coupling: jArg [
|
| nx := nxArg. ny := nyArg. nz := nzArg. coupling := jArg.
|
| handle := BobQuantumLibrary current function: #bob_lattice_create value: nx value: ny value: nz value: jArg.
|
| handle ifNil: [ self error: 'Failed to create lattice' ].
|
| volume := self computeVolume.
|
| coordinationNumber := self computeCoordination.
|
| ^ self
|
| ]
|
|
|
| BobLattice >> computeVolume [
|
| ^ BobQuantumLibrary current function: #bob_lattice_get_volume value: handle
|
| ]
|
|
|
| BobLattice >> computeCoordination [
|
| ^ BobQuantumLibrary current function: #bob_lattice_compute_coordination value: handle
|
| ]
|
|
|
| BobLattice >> getNeighborsForSite: siteIndex into: bufferArray [
|
|
|
| | neighborPtr |
|
| neighborPtr := BobQuantumLibrary current function: #bob_lattice_get_neighbors value: handle value: siteIndex value: bufferArray.
|
| ^ neighborPtr
|
| ]
|
|
|
| BobLattice >> neighborsOf: siteIndex [
|
| | buffer |
|
| buffer := Array new: coordinationNumber withAll: 0.
|
| self getNeighborsForSite: siteIndex into: buffer.
|
| ^ buffer
|
| ]
|
|
|
| BobLattice >> allNeighbors [
|
| | allNeighbors |
|
| allNeighbors := Array new: volume.
|
| 1 to: volume do: [ :i |
|
| allNeighbors at: i put: (self neighborsOf: i - 1)
|
| ].
|
| ^ allNeighbors
|
| ]
|
|
|
| BobLattice >> siteIndexToCoordinates: index [
|
| | x y z |
|
| z := index // (nx * ny).
|
| y := (index \\ (nx * ny)) // nx.
|
| x := index \\ nx.
|
| ^ { x. y. z }
|
| ]
|
|
|
| BobLattice >> coordinatesToSiteIndex: coords [
|
| ^ (coords third * nx * ny) + (coords second * nx) + coords first
|
| ]
|
|
|
| BobLattice >> distanceBetween: i and: j [
|
| | ci cj dx dy dz |
|
| ci := self siteIndexToCoordinates: i.
|
| cj := self siteIndexToCoordinates: j.
|
| dx := (ci first - cj first) abs.
|
| dy := (ci second - cj second) abs.
|
| dz := (ci third - cj third) abs.
|
|
|
| dx := dx min: (nx - dx).
|
| dy := dy min: (ny - dy).
|
| dz := dz min: (nz - dz).
|
| ^ (dx + dy + dz) asFloat
|
| ]
|
|
|
| BobLattice >> destroy [
|
| handle ifNotNil: [
|
| BobQuantumLibrary current function: #bob_lattice_destroy value: handle.
|
| handle := nil.
|
| ].
|
| ]
|
|
|
| BobLattice >> finalize [
|
| self destroy.
|
| ]
|
|
|
| BobLattice >> handle [
|
| ^ handle
|
| ]
|
|
|
| BobLattice >> nx [ ^ nx ]
|
| BobLattice >> ny [ ^ ny ]
|
| BobLattice >> nz [ ^ nz ]
|
| BobLattice >> coupling [ ^ coupling ]
|
| BobLattice >> volume [ ^ volume ]
|
| BobLattice >> coordinationNumber [ ^ coordinationNumber ]
|
|
|
| BobLattice >> printOn: aStream [
|
| aStream nextPutAll: 'BobLattice('.
|
| aStream nextPutAll: nx printString; nextPutAll: 'x'; nextPutAll: ny printString; nextPutAll: 'x'; nextPutAll: nz printString.
|
| aStream nextPutAll: ', J='; nextPutAll: coupling printString; nextPutAll: ')'.
|
| ]
|
|
|
|
|
| |
| -------------------------------------------------------------------------------- |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| 2^N for qubits, assuming spin-1/2 per site |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| Returns a Complex number (Pharo Complex class) |
| |
| |
| |
| Assuming C returns struct { double re; double im; }* or similar packed memory.
|
| We simulate reading memory via ExternalAddress >> getByte / getDouble.
|
| For this binding, we assume a helper or specific ABI.
|
| Here we mock the memory read for completeness. |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| 2 doubles |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| Returns Complex |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| -------------------------------------------------------------------------------- |
| BobHamiltonian - Quantum Hamiltonian Operator
|
|
|
|
|
| Object subclass: #BobHamiltonian
|
| instanceVariableNames: 'handle lattice matrixCache eigenvaluesCache'
|
| classVariableNames: ''
|
| package: 'BOB-Quantum-FFI'
|
|
|
| BobHamiltonian class >> forLattice: aLattice [
|
| ^ self basicNew initializeForLattice: aLattice
|
| ]
|
|
|
| BobHamiltonian >> initializeForLattice: aLattice [
|
| lattice := aLattice.
|
| handle := BobQuantumLibrary current function: #bob_hamiltonian_create value: lattice handle.
|
| handle ifNil: [ self error: 'Failed to create Hamiltonian' ].
|
| matrixCache := nil.
|
| eigenvaluesCache := nil.
|
| ^ self
|
| ]
|
|
|
| BobHamiltonian >> addIsingTerm: strength siteI: i siteJ: j [
|
| BobQuantumLibrary current function: #bob_hamiltonian_add_ising_term value: handle value: strength value: i value: j.
|
| matrixCache := nil.
|
| eigenvaluesCache := nil.
|
| ]
|
|
|
| BobHamiltonian >> addTransverseField: strength site: i [
|
| BobQuantumLibrary current function: #bob_hamiltonian_add_transverse_field value: handle value: strength value: i.
|
| matrixCache := nil.
|
| eigenvaluesCache := nil.
|
| ]
|
|
|
| BobHamiltonian >> addHeisenbergTerm: strength siteI: i siteJ: j [
|
| BobQuantumLibrary current function: #bob_hamiltonian_add_heisenberg_term value: handle value: strength value: i value: j.
|
| matrixCache := nil.
|
| eigenvaluesCache := nil.
|
| ]
|
|
|
| BobHamiltonian >> addCustomTerm: matrixData size: dim [
|
|
|
| BobQuantumLibrary current function: #bob_hamiltonian_add_custom_term value: handle value: matrixData value: dim.
|
| matrixCache := nil.
|
| eigenvaluesCache := nil.
|
| ]
|
|
|
| BobHamiltonian >> buildMatrix [
|
| BobQuantumLibrary current function: #bob_hamiltonian_build_matrix value: handle.
|
| matrixCache := nil.
|
| ]
|
|
|
| BobHamiltonian >> getMatrix [
|
| matrixCache ifNotNil: [ ^ matrixCache ].
|
| | ptr dim data |
|
| dim := lattice volume.
|
| ptr := BobQuantumLibrary current function: #bob_hamiltonian_get_matrix value: handle.
|
| ptr ifNil: [ ^ nil ].
|
|
|
| data := Matrix rows: dim columns: dim.
|
| 0 to: dim - 1 do: [ :r |
|
| 0 to: dim - 1 do: [ :c |
|
| | offset real imag |
|
| offset := (r * dim + c) * 16.
|
| real := ptr at: offset getDouble.
|
| imag := ptr at: offset + 8 getDouble.
|
| data at: r + 1 at: c + 1 put: (Complex real: real imaginary: imag)
|
| ]
|
| ].
|
| matrixCache := data.
|
| ^ data
|
| ]
|
|
|
| BobHamiltonian >> getEigenvalues: k [
|
|
|
| eigenvaluesCache ifNotNil: [ ^ eigenvaluesCache first: k ].
|
| | ptr buffer dim |
|
| dim := lattice volume.
|
| k := k min: dim.
|
| buffer := ExternalAddress malloc: (k * 8).
|
| ptr := BobQuantumLibrary current function: #bob_hamiltonian_get_eigenvalues value: handle value: buffer value: k.
|
| ptr ifNil: [ ^ nil ].
|
| eigenvaluesCache := Array new: k.
|
| 1 to: k do: [ :i |
|
| eigenvaluesCache at: i put: (buffer at: (i-1)*8 getDouble)
|
| ].
|
| buffer free.
|
| ^ eigenvaluesCache
|
| ]
|
|
|
| BobHamiltonian >> groundStateEnergy [
|
| ^ (self getEigenvalues: 1) first
|
| ]
|
|
|
| BobHamiltonian >> destroy [
|
| handle ifNotNil: [
|
| BobQuantumLibrary current function: #bob_hamiltonian_destroy value: handle.
|
| handle := nil.
|
| ].
|
| matrixCache := nil.
|
| eigenvaluesCache := nil.
|
| ]
|
|
|
| BobHamiltonian >> finalize [
|
| self destroy.
|
| ]
|
|
|
| BobHamiltonian >> handle [ ^ handle ]
|
| BobHamiltonian >> lattice [ ^ lattice ]
|
|
|
| BobHamiltonian >> printOn: aStream [
|
| aStream nextPutAll: 'BobHamiltonian(for: '; nextPutAll: lattice printString; nextPutAll: ')'.
|
| ]
|
|
|
|
|
| |
| -------------------------------------------------------------------------------- |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| Null pointers for auto-create |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| Re-initialize world with this lattice |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| aStateBlock: block taking (state, lattice) to populate amplitudes |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| Requires diagonalization - mocking via lowest eigenvector retrieval |
| |
| In real impl, we'd get eigenvector. Here we mock."
|
| self initializeRandomState. "Placeholder"
|
| ]
|
|
|
| BobQuantumWorld >> runSimulation: steps dt: dt [
|
| | result energy mag |
|
| steps timesRepeat: [ :step |
|
| result := BobQuantumLibrary current function: #bob_world_run_simulation value: handle value: 1 value: dt.
|
| result = 0 ifTrue: [ self error: 'Simulation step failed at step ', step printString ].
|
| simulationTime := simulationTime + dt.
|
| stepCount := stepCount + 1.
|
| "Record observables"
|
| energy := self currentEnergy.
|
| mag := self currentMagnetization.
|
| observablesHistory add: { #step -> stepCount. #time -> simulationTime. #energy -> energy. #magnetization -> mag }.
|
| ].
|
| ^ observablesHistory
|
| ]
|
|
|
| BobQuantumWorld >> runSimulation: steps dt: dt withCallback: aBlock [
|
| steps timesRepeat: [ :step |
|
| BobQuantumLibrary current function: #bob_world_run_simulation value: handle value: 1 value: dt.
|
| simulationTime := simulationTime + dt.
|
| stepCount := stepCount + 1.
|
| aBlock value: self value: stepCount value: simulationTime.
|
| ].
|
| ]
|
|
|
| BobQuantumWorld >> currentEnergy [
|
| ^ BobQuantumLibrary current function: #bob_world_get_energy value: handle
|
| ]
|
|
|
| BobQuantumWorld >> currentMagnetization [
|
| ^ BobQuantumLibrary current function: #bob_world_get_magnetization value: handle value: 0 "Z-axis"
|
| ]
|
|
|
| BobQuantumWorld >> correlationBetween: i and: j [
|
| ^ BobQuantumLibrary current function: #bob_world_get_correlation value: handle value: i value: j
|
| ]
|
|
|
| BobQuantumWorld >> visualize [
|
| self visualizeWithTitle: 'BOB Quantum Simulation' width: 800 height: 600
|
| ]
|
|
|
| BobQuantumWorld >> visualizeWithTitle: title width: w height: h [
|
| BobQuantumLibrary current function: #bob_world_visualize value: handle value: title value: w value: h.
|
| ]
|
|
|
| BobQuantumWorld >> visualizeToFile: filename [
|
| "Assumes C library supports file output via title path or separate func"
|
| BobQuantumLibrary current function: #bob_world_visualize value: handle value: filename value: 1920 value: 1080.
|
| ]
|
|
|
| BobQuantumWorld >> checkpoint: filename [
|
| | result |
|
| result := BobQuantumLibrary current function: #bob_world_checkpoint value: handle value: filename.
|
| ^ result = 1
|
| ]
|
|
|
| BobQuantumWorld >> restore: filename [
|
| | result |
|
| result := BobQuantumLibrary current function: #bob_world_restore value: handle value: filename.
|
| result = 1 ifTrue: [ self refreshHandles ].
|
| ^ result = 1
|
| ]
|
|
|
| BobQuantumWorld >> refreshHandles [
|
| lattice := BobLattice basicNew handle: (BobQuantumLibrary current function: #bob_world_get_lattice value: handle); yourself.
|
| state := BobState basicNew handle: (BobQuantumLibrary current function: #bob_world_get_state value: handle); lattice: lattice; yourself.
|
| hamiltonian := BobHamiltonian basicNew handle: (BobQuantumLibrary current function: #bob_world_get_hamiltonian value: handle); lattice: lattice; yourself.
|
| ]
|
|
|
| BobQuantumWorld >> getState [
|
| ^ state
|
| ]
|
|
|
| BobQuantumWorld >> getHamiltonian [
|
| ^ hamiltonian
|
| ]
|
|
|
| BobQuantumWorld >> getLattice [
|
| ^ lattice
|
| ]
|
|
|
| BobQuantumWorld >> getObservablesHistory [
|
| ^ observablesHistory
|
| ]
|
|
|
| BobQuantumWorld >> exportObservablesAsCSV [
|
| | stream |
|
| stream := WriteStream on: String new.
|
| stream nextPutAll: 'step,time,energy,magnetization'; cr.
|
| observablesHistory do: [ :obs |
|
| stream
|
| nextPutAll: (obs at: #step) printString; nextPut: $,;
|
| nextPutAll: (obs at: #time) printString; nextPut: $,;
|
| nextPutAll: (obs at: #energy) printString; nextPut: $,;
|
| nextPutAll: (obs at: #magnetization) printString; cr.
|
| ].
|
| ^ stream contents
|
| ]
|
|
|
| BobQuantumWorld >> destroy [
|
| handle ifNotNil: [
|
| BobQuantumLibrary current function: #bob_world_destroy value: handle.
|
| handle := nil.
|
| ].
|
| lattice ifNotNil: [ lattice destroy ].
|
| state ifNotNil: [ state destroy ].
|
| hamiltonian ifNotNil: [ hamiltonian destroy ].
|
| rng ifNotNil: [ rng destroy ].
|
| ]
|
|
|
| BobQuantumWorld >> finalize [
|
| self destroy.
|
| ]
|
|
|
| BobQuantumWorld >> handle [ ^ handle ]
|
| BobQuantumWorld >> simulationTime [ ^ simulationTime ]
|
| BobQuantumWorld >> stepCount [ ^ stepCount ]
|
|
|
| BobQuantumWorld >> printOn: aStream [
|
| aStream nextPutAll: 'BobQuantumWorld('.
|
| aStream nextPutAll: 'steps='; nextPutAll: stepCount printString.
|
| aStream nextPutAll: ', time='; nextPutAll: simulationTime printString.
|
| lattice ifNotNil: [ aStream nextPutAll: ', '; nextPutAll: lattice printString ].
|
| aStream nextPutAll: ')'.
|
| ]
|
|
|
| "--------------------------------------------------------------------------------"
|
| " Utility Extensions & Helpers
|
| "--------------------------------------------------------------------------------"
|
|
|
| "ExternalAddress helper methods for structured memory access (simulated for Pharo FFI)"
|
| ExternalAddress >> at: offset putDouble: aDouble [
|
| "Primitive: write double at offset. Implemented in VM/FFI plugin."
|
| <primitive: 'primitiveExternalAddressAtPutDouble' module: 'FFI'>
|
| ^ self primitiveFailed
|
| ]
|
|
|
| ExternalAddress >> at: offset getDouble [
|
| "Primitive: read double at offset."
|
| <primitive: 'primitiveExternalAddressAtGetDouble' module: 'FFI'>
|
| ^ self primitiveFailed
|
| ]
|
|
|
| ExternalAddress >> malloc: size [
|
| "Primitive: allocate memory."
|
| <primitive: 'primitiveExternalAddressMalloc' module: 'FFI'>
|
| ^ self primitiveFailed
|
| ]
|
|
|
| ExternalAddress >> free [
|
| "Primitive: free memory."
|
| <primitive: 'primitiveExternalAddressFree' module: 'FFI'>
|
| ^ self primitiveFailed
|
| ]
|
|
|
| "Complex Number Support (Pharo Kernel)"
|
| Object subclass: #Complex [
|
| instanceVariableNames: 'real imag'
|
| classVariableNames: ''
|
| package: 'BOB-Quantum-Math'
|
| ]
|
|
|
| Complex class >> real: r imaginary: i [
|
| ^ self basicNew setReal: r imaginary: i; yourself
|
| ]
|
|
|
| Complex >> setReal: r imaginary: i [
|
| real := r. imag := i. ^ self
|
| ]
|
|
|
| Complex class >> zero [ ^ self real: 0 imaginary: 0 ]
|
| Complex class >> one [ ^ self real: 1 imaginary: 0 ]
|
| Complex class >> i [ ^ self real: 0 imaginary: 1 ]
|
|
|
| Complex >> real [ ^ real ]
|
| Complex >> imag [ ^ imag ]
|
|
|
| Complex >> + aComplex [
|
| ^ Complex real: real + aComplex real imaginary: imag + aComplex imag
|
| ]
|
|
|
| Complex >> - aComplex [
|
| ^ Complex real: real - aComplex real imaginary: imag - aComplex imag
|
| ]
|
|
|
| Complex >> * aComplex [
|
| ^ Complex
|
| real: (real * aComplex real) - (imag * aComplex imag)
|
| imaginary: (real * aComplex imag) + (imag * aComplex real)
|
| ]
|
|
|
| Complex >> / aComplex [
|
| | denom |
|
| denom := aComplex squaredMagnitude.
|
| ^ Complex
|
| real: ((real * aComplex real) + (imag * aComplex imag)) / denom
|
| imaginary: ((imag * aComplex real) - (real * aComplex imag)) / denom
|
| ]
|
|
|
| Complex >> squaredMagnitude [
|
| ^ real * real + imag * imag
|
| ]
|
|
|
| Complex >> magnitude [
|
| ^ self squaredMagnitude sqrt
|
| ]
|
|
|
| Complex >> conjugate [
|
| ^ Complex real: real imaginary: imag negated
|
| ]
|
|
|
| Complex >> exp [
|
| | r |
|
| r := real exp.
|
| ^ Complex real: r * imag cos imaginary: r * imag sin
|
| ]
|
|
|
| Complex >> printOn: aStream [
|
| aStream nextPutAll: '('; nextPutAll: real printString.
|
| imag >= 0 ifTrue: [ aStream nextPutAll: '+' ].
|
| aStream nextPutAll: imag printString; nextPutAll: 'i)'.
|
| ]
|
|
|
| Complex >> = aComplex [
|
| ^ real = aComplex real and: [ imag = aComplex imag ]
|
| ]
|
|
|
| Complex >> hash [
|
| ^ real hash bitXor: imag hash
|
| ]
|
|
|
| "Matrix Helper (Simple Array of Arrays wrapper)"
|
| Object subclass: #Matrix [
|
| instanceVariableNames: 'rows columns data'
|
| classVariableNames: ''
|
| package: 'BOB-Quantum-Math'
|
| ]
|
|
|
| Matrix class >> rows: r columns: c [
|
| ^ self basicNew initializeRows: r columns: c
|
| ]
|
|
|
| Matrix >> initializeRows: r columns: c [
|
| rows := r. columns := c.
|
| data := Array new: r * c withAll: Complex zero.
|
| ^ self
|
| ]
|
|
|
| Matrix >> at: r at: c [
|
| ^ data at: ((r - 1) * columns + c)
|
| ]
|
|
|
| Matrix >> at: r at: c put: val [
|
| data at: ((r - 1) * columns + c) put: val.
|
| ]
|
|
|
| Matrix >> row: r [
|
| | arr |
|
| arr := Array new: columns.
|
| 1 to: columns do: [ :c | arr at: c put: (self at: r at: c) ].
|
| ^ arr
|
| ]
|
|
|
| Matrix >> column: c [
|
| | arr |