Skip to content

Latest commit

 

History

History
1028 lines (935 loc) · 50.8 KB

CHANGES.md

File metadata and controls

1028 lines (935 loc) · 50.8 KB

Pre-release

  • Breaking change: renamed ["qpp/qpp.h"] to ["qpp/qpp.hpp"]
  • New feature: implemented support for post-selection in ["qpp/classes/qengine.hpp"] and ["qpp/classes/qcircuit.hpp"]
  • Implemented qpp::QCircuit::
    • QCircuit& post_select() - destructive/non-destructive post-selection of single/multiple qudits in the Z basis
    • QCircuit& post_selectV() - destructive/non-destructive post-selection of single/multiple qudits in an arbitrary orthonormal basis
  • Implemented qpp::QEngineT<>::
    • bool get_ensure_post_selection() const - True if post-selection is enforced, false otherwise
    • QEngineT<>& set_ensure_post_selection() - Enforces post-selection (i.e., post-selection steps are repeated until success)
    • idx get_max_post_selection_reps() const - Maximum number of executions of a circuit post-selection step until success
    • QEngineT<>& set_max_post_selection_reps() - Sets the maximum number of executions of a circuit post-selection step until success
    • bool post_select_ok() const - True if post-selection was successful (or absent), false otherwise
  • Added ["examples/circuits/post_selection.cpp"] example
  • Refactored qpp::QCircuit::GateStep/MeasurementStep/NOPStep into separate files ["qpp/internal/classes/qcircuit_gate_step.hpp"], ["qpp/internal/classes/qcircuit_measurement_step.hpp"], and ["qpp/internal/classes/qcircuit_nop_step.hpp"], respectively
  • Refactored qpp::QCircuit::Resources into an independent class in a separate file ["qpp/internal/classes/qcircuit_resources.hpp"]
  • Refactored qpp::QCircuit::iterator class into an independent class, defined outside qpp::QCircuit in ["qpp/classes/qcircuit.hpp"]
  • Refactored qpp::internal::QEngineState and qpp::internal::QEngineStatistics in separate files, ["qpp/internal/classes/qengine_state.hpp"] and ["qpp/internal/classes/qengine_statistics.hpp"], respectively
  • API changes in ["qpp/classes/qcircuit.hpp"]
    • qpp::QCircuit::get_measured() -> qpp::QCircuit::get_measured_d()
    • qpp::QCircuit::get_non_measured() -> qpp::QCircuit::get_non_measured_d()
    • qpp::QCircuit::was_measured() -> qpp::QCircuit::was_measured_d()
  • API changes in ["qpp/classes/qengine.hpp"]
    • qpp::QEngineT<>::get_measured() -> qpp::QEngineT<>::get_measured_d()
    • qpp::QEngineT<>::get_non_measured() -> qpp::QEngineT<>::get_non_measured_d()
    • qpp::QEngineT<>::was_measured() -> qpp::QEngineT<>::was_measured_d()
  • Bugfix in qpp::internal::canonical_form(), the re-ordering is now stable, so qpp::QCircuit measurement probabilities are not displayed in reversed order w.r.t. target
  • Simplified MATLAB detection via CMake find_package() function. Users should only use -DQPP_MATLAB=ON when building with MATLAB support, all other MATLAB-related CMake flags have been removed.

Version 5.1 - 1 March 2024

  • Replaced ["CHANGES"] by ["CHANGES.md"], as we now use Markdown format to keep track of changes in new releases
  • Removed Eigen3, pybind11, and GoogleTest dependencies; if not detected, they are installed automatically as build dependencies by CMake
  • Bumped GoogleTest version to HEAD latest, as recommended by Google
  • Removed -DWITH_EXAMPLES and -DWITH_UNIT_TESTS CMake flags. Now both examples and unit_tests CMake targets are enabled.
  • Renamed ["qpp/classes/circuits/circuits.hpp"] to ["qpp/classes/qcircuit.hpp"]
  • Introduced ["qpp/classes/qcircuit_traits.hpp"] that implement circuit traits at compile-time
  • Renamed ["qpp/classes/circuits/engines.hpp"] to ["qpp/classes/qengine.hpp"], and refactored the latter into
    • ["qpp/classes/qbase_engine.hpp"] - base class for all engines
    • ["qpp/classes/qengine.hpp"] - ideal quantum engines
    • ["qpp/classes/qnoisy_engine.hpp"] - noisy quantum engines
  • Introduced ["qpp/classes/qengine_traits.hpp"] that implement engine traits at run-time. All engines are now deriving from it. The traits implements qpp::IQEngineTraits::
    • std::string traits_get_name() const - Engine's name
    • bool traits_is_noisy() const - Simulates noisy execution
    • bool traits_is_pure() const - Operates on pure states
  • API changes in ["qpp/classes/qengine.hpp"] and ["qpp/classes/qnoisy_engine.hpp"]
    • Enabled mixed-state engines by refactoring
      • qpp::QEngine -> template<typename T> qpp::QEngineT<T>
      • qpp::QNoisyEngine -> template<typename T> qpp::QNoisyEngineT<T> The template argument T is restricted to qpp::ket (pure state engines) and qpp::cmat (mixed states engines)
    • The following additional engines are now available
      • qpp::QEngine - pure state ideal engine, backwards compatibility
      • qpp::QKetEngine - same as qpp::QEngine
      • qpp::QDensityEngine - mixed state ideal engine
      • qpp::QNoisyEngine - pure state noisy engine, backwards compatibility
      • qpp::QKetNoisyEngine - same as qpp::QNoisyEngine
      • qpp::QDensityNoisyEngine - mixed state noisy engine
    • Renamed qpp::QEngineT<>::get_psi() -> qpp::QEngineT<>::get_state()
    • Removed qpp::QEngineT<>::is_noisy()
    • Added the new engines to pyqpp, which now defines the following factory functions for instantiating engines
      • pyqpp.QEngine() - pure state ideal engine, backwards compatibility
      • pyqpp.QKetEngine() - same as pyqpp.QEngine()
      • pyqpp.QDensityEngine() - mixed state ideal engine
      • pyqpp.QNoisyEngine() - pure state noisy engine, backwards compatibility
      • pyqpp.QKetNoisyEngine() - same as pyqpp.QNoisyEngine()
      • pyqpp.QDensityNoisyEngine() - mixed state noisy engine
    • Removed the default argument bool try_sampling = true in qpp::QEngineT<>::execute(idx reps = 1, bool try_sampling = true) -> qpp::QEngineT<>::execute(idx reps = 1) so now qpp::QEngineT<> will always try to sample from the output when the circuit is executed multiple times (i.e., when reps > 1)
  • Introduced no-op (dummy) quantum engines in ["qpp/classes/qdummy_engine.hpp"] that provides
    • template<typename T, typename QCT> qpp::QDummyEngine<T, QCT>
    • qpp::QKetDummyEngine - specialization of qpp::QDummyEngine<> with T = qpp::ket, QCT = qpp::QCircuit
    • qpp::QDensityDummyEngine - specialization of qpp::QDummyEngine<> with T=qpp::cmat, QCT=qpp::QCircuit
  • Introduced corresponding pyqpp.QKetDummyEngine and pyqpp.QDensityDummyEngine in pyqpp

Version 5.0 - 10 January 2024

  • All header files are moved into ["include/qpp"], so to include the header one now must #include "qpp/qpp.h" (and similarly for other header files in the internal implementation). This change was made for the sake of making the include statements look uniform in both non-installed (compiling without having Quantum++ installed) and installed (compiling with Quantum++ installed headers) modes.
  • Refactored option-related types into a new header file ["qpp/options.hpp"]
  • qpp::disp() refactoring, formatting options are now passed via formatting option manipulator structures, all defined in ["qpp/options.hpp"]. See the ["examples"] directory for usage examples.
  • Implemented qpp::dirac() ["qpp/functions.hpp"] for converting states and matrices to Dirac notation, and the corresponding std::ostream manipulator qpp::disp() ["qpp/input_output.hpp"]. The type returned by qpp::dirac() is type-defed as qpp::dirac_t in ["qpp/types.hpp"]. Options are passed via the formatting option manipulator structure qpp::IOManipDiracOpts.
  • Implemented pyqpp.dirac() in pyqpp, see above.
  • Significant speedup in pyqpp's compilation time
  • Added support for two qubit rotations by pi/2 (Molmer-Sorensen two qubit gates).
  • API changes in ["qpp/classes/circuits/circuits.hpp"]
    • [qpp::QCircuit::]
      • add_circuit() -> compose_circuit()
      • match_circuit_left() -> couple_circuit_left()
      • match_circuit_right() -> couple_circuit_right()
  • Implemented ["qpp/classes/circuits/circuits.hpp"] control on another quantum circuit,
    • qpp::QCircuit::compose_CTRL_circuit() see GitHub Issue #165, and the corresponding standalone versions
    • qpp::compose_CTRL_circuit()
  • qpp::measure_seq() now returns results in the same order as the order in which the qubits are being measured
  • API changes in ["qpp/functions.hpp"], qpp::zket2dits() now returns std::optional<std::vector<idx>>
  • Bugfix in qpp::QCircuit::compose_circuit()

Version 4.3.4 - 14 August 2023

  • Docker update, see the ["docker"] directory
  • Fix in ["types.hpp"] for defaulting types when not using CMake

Version 4.3.3 - 8 August 2023

  • Minor bugfix in pyqpp ["setup.py"] that prevented pip install from remote
  • Bugfix in qpp::QEngine::execute() that prevented setting the initial state of the engine to a custom state

Version 4.3.2 - 12 June 2023

  • This is a maintenance release
  • Compiling errors fixed on SunOS/OpenIndiana

Version 4.3.1 - 5 June 2023

  • CMake dependent flag name changes. These flags can be used in standalone projects when configuring with CMake.
    • USE_OPENQASM2_SPECS -> QASMTOOLS_QASM2_SPECS
    • WITH_MATLAB -> QPP_MATLAB
    • WITH_OPENMP -> QPP_OPENMP
    • TYPE_BIGINT -> QPP_BIGINT
    • TYPE_FP -> QPP_FP
    • TYPE_IDX -> QPP_IDX
  • Compile-time error fix when using FP_TYPE="long double" with QASMTOOLS_QASM2_SPECS=ON

Version 4.3 - 26 May 2023

  • This is a maintenance release
  • Fixed pyqpp installation on Windows under MSVC
  • Migrated all continuous integration to GitHub actions
  • Minor updates in qasmtools

Version 4.2 - 13 May 2023

  • Quantum++ is now available on Homebrew (macOS/Linux), and can be installed with brew install quantum++
  • New types in ["types.hpp"]
    • realT - floating point type, replaces double in the source code
    • ubigint - unsigned big integer, defined in terms of bigint as using ubigint = std::make_unsigned<bigint>::type;
  • The fundamental types in ["types.hpp"] are now qpp::idx, qpp::bigint, and qpp::realT. They can be changed at compile time (see below). All other types are dependent on those, please do not change.
  • Added support for changing the underlying index type via the CMake property TYPE_IDX. Choices are default, short, int, long, long long, unsigned short, unsigned int, unsigned long, and unsigned long long. The default type is set in ["types.hpp"]. To change the underlying type with CMake, pass the variable -DTYPE_IDX to CMake, e.g., cmake -B build -DTYPE_IDX="unsigned long long".
  • Added support for changing the underlying big integer type via the CMake property TYPE_IDX. Choices are default, short, int, long, long long. The default type is set in ["types.hpp"]. To change the underlying type with CMake, pass the variable -DTYPE_BIGINT to CMake, e.g., cmake -B build -DTYPE_BIGINT="long long".
  • Added support for changing the underlying floating point type via the CMake property TYPE_FP. Choices are default, float, double, and long double. The default type is set in ["types.hpp"]. To change the underlying type with CMake, pass the variable -DTYPE_FP to CMake, e.g., cmake -B build -DTYPE_FP="long double".
  • Refactored the two instances of qpp::rand(a, b) ["random.hpp"] to a single template function
    template<typename T, std::enable_if...> qpp::rand(T a, T b)
    enabled only on arithmetic types by typename std::enable_if_t<std::is_arithmetic_v<T>>* = nullptr
  • Refactored qpp::randn(mean, sigma) ["random.hpp"] to a template function
     template<typename T, std::enable_if...> qpp::random(T a, T b)
    enabled only on arithmetic types by typename std::enable_if_t<std::is_arithmetic_v<T>>* = nullptr
  • CMake minimum required version bumped to 3.15

Version 4.1 - 2 May 2023

  • Implemented ["classes/circuits/circuits.hpp"]
    • qpp::qpe_circuit() - Quantum phase estimation circuit
    • qpp::QCircuit::has_measurements() - True if the quantum circuit description contains measurement steps, false otherwise
    • qpp::QCircuit::removes_qudits() - True if the quantum circuit description contains any operations/measurements that remove qudits, false otherwise
  • Added new exception class ["classes/exception.hpp"]:
    • qpp::exception::NotFound - Element not found
  • Implemented ["pyqpp/qpp_wrapper.cpp"] (pyqpp Python wrapper)
    • set_prng_seed() - sets the seed of the PRNG to a specific value, or, if invoked with no argument, to a random value
  • Migrated pyqpp installation method to ["pyproject.toml"]
  • Extensive code refactoring, transitioned qpp::QCircuit logic to std::visit() over std::variant
  • API changes in ["classes/circuits/circuits.hpp"], all functions with name and shift defaulted empty/zeroed arguments are now wrapped in std::optional<>, as well as some qpp::QCircuit getters, i.e., have the signature qpp::QCircuit:::
    • get_gate_count(std::optional<cmat> U = std::nullopt)
    • get_gate_depth(std::optional<cmat> U = std::nullopt)
    • get_measurement_count(std::optional<cmat> V = std::nullopt)
    • get_measurement_depth(std::optional<cmat> V = std::nullopt) In addition, std::optional<> is also added as arguments to the free functions:
    • qpp::random_circuit_count()
    • qpp::random_circuit_depth()
  • API changes in ["classes/circuits/circuits.hpp"], more std::optional<>, updated the following qpp::QCircuit member functions signatures to qpp::QCircuit:::
    • add_circuit(QCircuit other, bigint pos_qudit, std::optional<idx> pos_dit = std::nullopt)
    • match_circuit_left(QCircuit other, const std::vector<idx>& target, std::optional<idx> pos_dit = std::nullopt)
    • match_circuit_right(QCircuit other, const std::vector<idx>& target, std::optional<idx> pos_dit = std::nullopt)
    • add_circuit(QCircuit qc1, const QCircuit& qc2, bigint pos_qudit, std::optional<idx> pos_dit = std::nullopt)
    • match_circuit_left(QCircuit qc1, const QCircuit& qc2, const std::vector<idx>& target, std::optional<idx> pos_dit = std::nullopt)
    • match_circuit_right(QCircuit qc1, const QCircuit& qc2, const std::vector<idx>& target, std::optional<idx> pos_dit = std::nullopt)
  • API changes in ["classes/circuits/circuits.hpp"], renamed qpp::QCircuit:::
    • was_measured(idx i) -> was_measured(idx i)
    • get_measured_nd(idx i) -> was_measured_nd(idx i)
  • API changes in ["classes/circuits/engines.hpp"], renamed qpp::QEngine:::
    • was_measured(idx i) -> was_measured(idx i)
    • get_measured_nd(idx i) -> was_measured_nd(idx i)
  • API changes in ["classes/reversible.hpp"], qpp::BitCircuit::count/depth getters now wrap their gate name argument in std::optional<>, i.e., have the signature qpp::BitCircuit:::
    • get_gate_count(std::optional<std::string> name = std::nullopt)
    • get_gate_depth(std::optional<std::string> name = std::nullopt)
  • API changes in ["functions.hpp"], qpp::n2multiidx() and qpp::multiidx2n() now take their argument underlying type (number, array) as template (must be an integral type)
  • Removed qpp::QCircuit::is_non_CTRL()
  • Refactored pyqpp, organized the source code in separate ["src"]/["include"] directory structure that mirrors the qpp source code structure

Version 4.0.1 - 2 April 2023

  • This is a maintenance release with minor changes
  • Updated pybind11 to version 2.10.4
  • Bugfix in qpp::QFT()/TFQ() when applied to density matrices

Version 4.0 - 20 March 2023

  • Major performance improvement in qpp::QEngine::execute(), which now takes a second default argument bool try_sampling = true; if possible, the engine will sample from the output of the circuit instead of executing the measurement steps.
  • API changes in ["classes/circuits/circuits.hpp"], renamed:
    • qpp::QCircuit::gate_joint() -> qpp::QCircuit::gate()
    • qpp::QCircuit::CTRL_joint() -> qpp::QCircuit::CTRL()
    • qpp::QCircuit::cCTRL_joint() -> qpp::QCircuit::cCTRL()
    • qpp::QCircuit::CTRL() -> qpp::QCircuit::CTRL_fan()
    • qpp::QCircuit::cCTRL() -> qpp::QCircuit::cCTRL_fan()
    • qpp::QCircuit::measureZ() -> qpp::QCircuit::measure()
  • API changes in qpp::QCircuit::measure() for multiple qudits, now the results are stored sequentially (instead as a decimal representation of the multi-index)
  • API changes in qpp::measure_seq(), now, as part of its return tuple, returns the full list of outcome probabilities
  • API changes for
    • qpp::QCircuit::get_gate_count()
    • qpp::QCircuit::get_gate_depth()
    • qpp::QCircuit::get_measurement_count()
    • qpp::QCircuit::get_measurement_depth() so now the old std::string overloads take instead a qpp::cmat as an argument
  • API changes for
    • qpp::Q[Noisy]Circuit::execute() removed bool reset_stats = true parameter as it was confusing, suffices to invoke Q[Noisy]Engine::reset(bool reset_stats = true) for resetting the measurement statistics; added bool try_sampling = true argument, see above
  • Noise is now added before measurements as well when running with a qpp::QNoisyEngine<>
  • Implemented ["classes/circuits/circuits.hpp"]:
    • qpp::QCircuit::measure_all() - measures all remaining available qudits
  • Implemented the random qpp::QCircuit free function generators in ["classes/circuits/circuits.hpp"]:
    • qpp::random_circuit_count() - random QCircuit w.r.t. gate count
    • qpp::random_circuit_depth() - random QCircuit w.r.t. gate depth
  • Implemented ["classes/gates.hpp"]:
    • qpp::Gates::GATE() - constructs the matrix representation of a multi-partite gate that acts on a subsystem
  • Implemented ["operations.hpp"]:
    • qpp::applyCTRL_fan() - applies CTRL-CTRL-...-CTRL-U-U-...-U
  • Implemented ["instruments.hpp"]:
    • qpp::sample() - samples from a quantum state. Use this function whenever you are not interested in the output quantum state, but interested only in statistics; it is significantly faster than its qpp::measure()-type functions.
  • Added copy/deepcopy support for all pyqpp classes:
    • QCircuit, QEngine, QNoisyEngine<>, Dynamic_Bitset, Bit_circuit
  • Added context to exception throwing, so now it is obvious which argument triggers an exception
  • EIGEN3_INSTALL_DIR can now be set as an OS environment variable (in addition to a CMake variable). If both are set, then the CMake variable trumps. If none are set, the system tries to detect the location of the Eigen3 library automatically.
  • Marked high-performance functions with the custom attribute [[qpp::critical]] and functions that use parallelization with the custom attribute [[qpp::parallel]]. Since C++17, unknown attributes are supposed to be ignored by the compiler (and one can use this technique to define custom attributes). Warnings are explicitly disabled for Clang/GCC/MSVC/Intel. If your compiler emits a warning, please disable it with the corresponding #pragma directive at the beginning of ["qpp.h"]
  • Added from-string constructor for qpp::Bit_circuit and qpp::Dynamic_bitset
  • When building with CMake, the new QPP_VERSION_NUM (numeric) and QPP_VERSION_STR (string) preprocessor definitions are automatically injected in the code
  • Added initializer lists overloads for qpp::prod() and qpp::sum() in ["functions.h"]:
    • qpp::prod(const std::initializer_list<T>&)
    • qpp::sum(const std::initializer_list<T>&)
  • Enhanced qpp::prod() and qpp::sum() to allow list of matrices
  • Bugfix in qpp::measure() [#132]
  • Bugfix in QCircuit::CTRL [#130]
  • Bumped GoogleTest version to 1.12.1

Version 3.1 - 11 January 2022

  • Added pyqpp, a Python wrapper around Quantum++. See pyqpp documentation for more details.
  • Minor update of Shor's algorithm example ["examples/shor.cpp"]
  • Renamed ["examples/qasm/qasm.cpp"] to ["examples/qasm/qpp_qasm.cpp"]
  • Due to phase discrepancies, by default the parser now uses Qiskit definitions (which are also the usual ones used in QC textbooks). To switch to standard OpenQASM 2.0 gate definitions, configure the project with cmake -DUSE_OPENQASM2_SPECS=ON.
  • Implemented qpp::QCircuit methods:
    • get_dirty_dits() - vector of used classical dits in the circuit (by either cCTRL or measurements)
    • get_dirty_qudits() - vector of used qudits in the circuit
    • was_measured_nd() - vector of qudits that were measured non-destructively
    • get_measurement_dits() - vector of classical dits that participated in measurements
    • is_measurement_dit() - whether a classical dit participated in a measurement
  • Changed the ordering of bits in qpp::Bit_circuit::display(), so that the zero-th bit (top bit) is now the leftmost bit in the textual representation. That is, qpp::Bit_circuit assumes big-endian order.
  • Bugfixes

Version 3.0 - 5 October 2021

  • Major release, bumped up C++ standard to C++17
  • Decoupled the OpenQASM parser from the main codebase. A hard copy of qasmtools (https://github.com/softwareQinc/qasmtools) is now common to both staq and Quantum++, and by default uses standard OpenQASM 2.0 gate definitions. To switch to Qiskit definitions (which are also the usual ones used in QC textbooks), configure the project with cmake -DUSE_QISKIT_SPECS=ON.
  • Refactored qpp::internal::Singleton ["internal/classes/singleton.hpp"] so that qpp::internal::Singleton::get_instance() returns a thread local instance whenever the compiler supports thread_local. For more fine-grained control, one can use
    • qpp::internal::Singleton::get_no_thread_local_instance()
    • qpp::internal::Singleton::get_thread_local_instance()
  • Added qpp::schmidt() ["entanglement.hpp"] and improved the performance of singular value decomposition, thanks @antoine-bussy (https://github.com/antoine-bussy)

Version 2.7 - 1 August 2021

  • Added installation support and auto package detection via CMake find_package(qpp REQUIRED)
  • Simplified installation instructions ["INSTALL.md"]
  • Added an almost complete BB84 example ["examples/bb84.cpp"], does not include error correction and privacy amplification
  • Added CircleCI continuous integration
  • CMake minimum required version bumped to 3.12 for automatic unit tests detection by CMake and other CMake-related "good practices"
  • Unit testing and examples are now separate CMake targets, one needs to explicitly type make unit_testing and/or make examples to build the unit testing suite and/or the examples, respectively
  • Simplified unit testing, now one can run tests with ctest or make test (after explicitly built with make unit_testing). Use GTEST_COLOR=1 ARGS="-V" make test or GTEST_COLOR=1 ctest -V for coloured verbose testing output.
  • Fixed minor inadvertence in OpenQASM crz implementation, see GitHub Issue #99
  • Changed the signature of qpp::cwise() ["functions.hpp"] so it takes the scalar argument by value (and not constant reference as before). This avoids an internal compiler error (ICE) triggered when compiling ["examples/functor.cpp"] in MinGW.
  • Removed <iostream> implicit dependencies ["qpp.h"]
  • Added optional context to qpp::Exception ["classes/exception.hpp"]
  • Made qpp::QCircuit default-constructible ["classes/circuits/circuits.hpp"] so it constructs by default a 1-qubit circuit with no classical bits
  • qpp::QEngine::reset() now accepts a default argument bool reset_stats = true and cleans the engine's statistics by default ["classes/circuits/engines.hpp"]
  • Renamed ["examples/qasm/qasm1.cpp"] and ["examples/qasm/qasm2.cpp"] to ["examples/qasm/qasm_teleport_minimal.cpp"] and ["examples/qasm/qasm.cpp"]; the latter executes an arbitrary OpenQASM program read from the standard input or from a file (if specified)
  • Added the aggregate qpp::QCircuit::Resources ["classes/circuits/circuits.hpp"] class for quantum circuit resource estimations. It derives from qpp::IDisplay and qpp::IJSON, so one can display instances of it as text or in JSON format.
  • Implemented qpp::QCircuit::get_resources() which returns an instance of qpp::QCircuit::Resources
  • Renamed ["examples/circuits/quantum_phase_estimation.cpp"] to ["examples/circuits/qpe_circuit.cpp"]
  • Added ["examples/qasm/coin_flip.qasm"] coin flipping OpenQASM example that can be run, e.g., with qasm < coin_flip.qasm [number of reps]
  • qpp::measure() deducts the input state type (qpp::ket or qpp::cmat) and returns accordingly a set of kets or density matrices in its return tuple, thanks @anoine-bussy
  • Implemented qpp::QCircuit::match_circuit_left() and qpp::QCircuit::match_circuit_right(), that match circuit qudits in arbitrary order
  • Implemented qpp::zket2dits ["functions.h"] which extracts the dits from a normalized multi-partite pure state in the computational basis. Behaves like the inverse of qpp::mket().
  • Removed cmath_cygwin.patch as the problem was fixed since 2016.
  • Minor refactorings, code simplifications and bugfixes
  • Removed Travis CI

Version 2.6 - 9 January 2021

  • Added Quantum Phase Estimation low-level API example in ["examples/qpe.cpp"], courtesy of @ryanhill1, see GitHub Pull Request #91
  • Added Quantum Phase Estimation high-level API example in ["examples/circuits/quantum_phase_estimation.cpp"], thanks @DevelopDaily for the suggestion, GitHub Issue #96
  • qpp::load() and qpp::save() ["input_output.hpp"] now use C++ I/O streams instead of file names, and load/save in text format (instead of binary format), while preserving the required precision. The old load/save functions that use binary files for I/O are now moved to the qpp::obsolete namespace and are deprecated.
  • Minor API changes: ["MATLAB/matlab.hpp"] qpp::saveMATLAB() -> qpp::save_MATLAB() qpp::loadMATLAB() -> qpp::load_MATLAB() ["classes/circuits/circuits.hpp"] qpp::cCTRL_custom() -> qpp::cCTRL_joint() qpp::CTRL_custom() -> qpp::CTRL_joint() qpp::gate_custom() -> qpp::gate_joint()
  • Documentation improvements in ["classes/circuits/circuits.hpp"]
  • Updated Travis CI configuration

Version 2.5 - 28 November 2020

  • Significant improvements in qpp::QEngine::execute() for multiple runs
  • Changed all header extensions from .h to .hpp (except for qpp.h)
  • Automatic OpenMP detection by CMake
    • CMake minimum required version bumped to 3.9 (3.12 for macOS) for automatic OpenMP detection
    • OpenQASM bugfixes
    • Renamed master branch to main

Version 2.4 - 13 May 2020

  • Enabled documentation searching by setting SEARCHENGINE = ON in Doxyfile
  • Implemented the following static member functions qpp::QCircuit::
    • is_CTRL() - gate step is a controlled gate or not
    • is_cCTRL() - gate step is a classically-controlled gate or not
    • is_non_CTRL() - gate step is a non-controlled gate or not
  • Changed qpp::QCircuit::
    • is_clean() -> is_clean_qudit()
    • get_clean() -> get_clean_qudits()
  • Split qpp::QCircuit::remove_clean() into qpp::QCircuit::
    • remove_clean_qudit() - removes single clean qudit from quantum circuit description
    • remove_clean_qudits() - removes list of clean qudits from quantum circuit description
  • Implemented qpp::QCircuit::
    • is_clean_dit() - true if the classical dit is clean (not used), false otherwise
    • get_clean_dits() - list of clean classical dits
    • remove_clean_dit() - removes single clean classical dit from quantum circuit description
    • remove_clean_dits() - removes list of clean classical dits from quantum circuit description
  • Modified the signature of qpp::QCircuit::compress() to qpp::QCircuit::compress(bool compress_dits = false) so one can compress the clean classical dits as well
  • Removed the measured/non-measured qudits from qpp::QCircuit::display() and qpp::QEngine::display() since they make the output very large for quantum circuit descriptions with many qudits; kept them in the corresponding qpp::QCircuit::to_JSON() and qpp::QEngine::to_JSON() member functions
  • Implemented qpp::QEngine::set_dits() which sets all engine's classical dits at once

Version 2.3 - 2 May 2020

  • Added the following examples in the ["examples"] directory
    • qram.cpp - quantumly-accessible Random Access Memory over classical data
    • layouts.cpp - various physical qubit layouts
  • Implemented qpp::QCircuit::
    • bool operator==() const noexcept
    • bool operator!=() const noexcept for quantum circuits simple (in)equality testing
  • Implemented
    • qpp::super2kraus() - extracts a set of orthogonal (in the Hilbert-Schmidt norm) Kraus operators from a superoperator matrix ["operations.h"]
    • qpp::bernoulli() - generates Bernoulli-p random booleans ["random.h"]
  • Kraus-related functions on full systems (not subsystems) now support input and output spaces of different dimensions, i.e., can now use non-square Kraus operators. All other Kraus-related functions for which the Kraus operators act on subsystems continue to require square Kraus operators.
  • Bugfix in qpp::QCircuit::add_circuit()
  • Fixed all Doxygen warnings (except spurious ones)

Version 2.2 - 14 April 2020

  • Updated Google Test to version 1.10.0
  • Removed the Visual Studio solution (since it can be automatically generated by CMake), as we prefer to use CMake uniformly across all platforms
  • Implemented
    • qpp::qRAM() - quantumly-accessible Random Access Memory over classical data (qRAM) ["operations.h"]
  • Added the new type qpp::qram for representing qRAM data ["types.h"]
  • Thanks to @DevelopDaily (#72), implemented qpp::QCircuit::
    • is_clean() - true if the qudit is clean (not used), false otherwise
    • get_clean() - list of clean qudits
    • remove_clean() - removes single/list of clean qudits from quantum circuit description
    • compress() - removes unused qudits from quantum circuit description
  • More robust MATLAB integration, detects MATLAB automatically when the CMake flag -DWITH_MATLAB=ON is specified; if CMake cannot detect it automatically, pass the additional CMake flag -DMATLAB_INSTALL_DIR=/path/to/MATLAB to manually specify MATLAB's location
  • Updated MATLAB mx-API, detects MX_HAS_INTERLEAVED_COMPLEX for MATLAB versions >= R2018a, see MATLAB Support for Interleaved Complex, but also continues to work with older MATLAB versions < R2018a
  • Changed the CMake flag EIGEN3_INCLUDE_DIR to EIGEN3_INSTALL_DIR so it is consistent with the MATLAB_INSTALL_DIR CMake flag

Version 2.1 - 14 March 2020 (3.14.2020 Pi day release)

  • Migrated the repository to https://github.com/softwareQinc/qpp
  • Changed gate definitions in ["qasm/preprocessor.h"] so they agree with Qiskit, see #65 and #70
  • Minor API change in the QEngine::execute(), reset(), reset_stats(), now they all return a reference to *this
  • Added Bit_circuit::display() and Bit_circuit::to_JSON() in ["reversible.h"]
  • Added the option for shifted control gates in:
    • qpp::applyCTRL()
    • qpp::Gates::CTRL()
    • qpp::QCircuit::CTRL()
  • Implemented
    • qpp::States::j() const - |j⟩ computational basis state of a single qudit

Version 2.0 - 24 August 2019

  • Added support for OpenQASM via the interface ["qasm/qasm.h"] containing:
    • qpp::QCircuit qpp::qasm::read_from_file(const std::string& fname) - reads an OpenQASM file and returns the qpp::QCircuit representation
    • qpp::QCircuit qpp::qasm::read(std::ifstream& stream) - reads an input stream and returns the qpp::QCircuit representation
  • Added corresponding OpenQASM examples in the directory ["examples/circuits/qasm"]
  • Implemented qpp::QCircuit::
    • kron() - Kronecker product with another quantum circuit description
    • measureZ() - new overload that allows multiple targets at once
    • adjoint() - in place adjoint of quantum circuit description
    • kron() - in place Kronecker product with another quantum circuit description
  • Implemented the corresponding free functions as friends of qpp::QCircuit:
    • qpp::adjoint() - adjoint of quantum circuit description
    • qpp::kron() - Kronecker product between two quantum circuit descriptions
    • qpp::replicate() - replicates (repeats) a quantum circuit description
    • qpp::add_circuit() - adds two quantum circuit descriptions
  • Implemented qudit resetting and discarding functions qpp::QCircuit::
    • reset() - resets qudits in a quantum circuit description by measuring them non-destructively in the computational basis followed by shifting them back to the |0> state
    • discard() - discards qudits in a quantum circuit description by measuring them destructively and ignoring the result of the measurement
  • Implemented the corresponding free functions in ["instruments.h"]:
    • qpp::reset() - resets qudits in a multipartite state by measuring them non-destructively in the computational basis followed by shifting them back to the |0> state
    • qpp::discard() - discards qudits by measuring them destructively and ignoring the result of the measurement
  • Implemented qpp::QCircuit::set_name() - set the QCircuit name after construction
  • API change in qpp::QCircuit::cCTRL*(), now accepts an additional shift on the control dits
  • Split qpp::QCircuit::get_depth() into qpp::QCircuit::get_gate_depth() - gate depth and qpp::QCircuit::get_measurement_depth() - measurement depth for finer control over depth computations
  • Added support for non-destructive measurements in ["instruments.h"] by modifying the API for:
    • qpp::measure()
    • qpp::measure_seq()
  • Added ["classes/layouts.h"] header file for representing different physical qudit layouts. Implemented the class(es):
    • qpp::Lattice - qudits on a multi-dimensional orthogonal grid
    • qpp::PeriodicBoundaryLattice - qudits on a multi-dimensional orthogonal grid with periodic boundary conditions
  • Removed the documentation directory (["doc"]). To generate the documentation in HTML/LaTeX formats, run doxygen from the root of the project.

Version 1.3 - 25 July 2019

  • Minimum required CMake version is now 3.2
  • Added MSVC support for CMake
  • Updated Google Test to version 1.8.1
  • Added enum {RES, PROB, ST} in ["constants.h"] for using with std::get<> on the result of qpp::measure() etc.
  • Split the ["classes/circuits.h"] into ["classes/circuits/circuits.h"] and ["classes/circuits/engines.h"]
  • Added noisy quantum engine for non-correlated noise
  • Added noisy teleportation example (that uses a noisy quantum engine) in ["examples/circuits/noisy_teleport_qubit_circuit.cpp"]
  • Implemented qpp::QCircuit:::
    • QFT() - Quantum Fourier Transform
    • TFQ() - inverse Quantum Fourier Transform
    • get_gate_depth() - circuit gate depth
    • add_qudit() - adds qudit(s) on the fly
    • add_dit() - adds classical dit(s) on the fly
    • add_circuit() - adds a quantum circuit description to the current one
    • replicate() - replicates (repeats) the current quantum circuit description
  • Implemented qpp::Bit_circuit:::
    • get_gate_count() - classical reversible circuit gate count
    • get_depth() - classical reversible circuit gate depth

Version 1.2 - 10 February 2019

  • Added new function in ["functions.h"]:
    • qpp::normalize() - normalizes a state vector (ket or bra) or density matrix
  • Added new functions in ["number_theory.h"]:
  • Added new functions in ["operations.h"]:
    • qpp::TFQ() - inverse qudit quantum Fourier transform (includes qubit QFT as a special case) on an entire quantum state (state vector or density matrix)
    • qpp::applyTFQ() - apply the inverse qudit quantum Fourier transform on a subset of qudits of a state vector or density matrix
  • Added new member functions for qpp::Gates:
    • qpp::Gates::MODMUL() - quantum modular multiplication
  • Added Shor's algorithm example in ["examples/shor.cpp"]
  • Introduced the largest unsigned index qpp::idx_inf in ["constants.h"]
  • Added new exception classes in ["classes/exception.h"]:
    • qpp::exception::QuditAlreadyMeasured - self-explanatory
    • qpp::exception::Duplicates - thrown when a system such as a std::vector contains duplicates
    • qpp::exception::NotImplemented - code not yet implemented
    • qpp::exception::InvalidIterator - invalid iterator (not initialized, past end, etc.)
  • Added std::string qpp::Gates::get_name(const cmat&) function which returns the names of the most common (one, two and three) qubit gates
  • Added new header file ["classes/noise.h"] and corresponding classes for simulating quantum noise (e.g. depolarizing, dephasing etc.) and a corresponding simple example in ["examples/noise.cpp"]
  • Added new abstract class qpp::IJSON in ["classes/idisplay.h"] for very basic JSON serialization support, and corresponding qpp::QCircuit::to_JSON() and qpp::QEngine::to_JSON()
  • Added new classes in the new header file ["classes/circuits.h"] for simulating qudit quantum circuits:
    • qpp::QCircuit - Quantum circuit description, does not effectively perform any operations
    • qpp::QEngine - Quantum engine for simulation of quantum circuits
  • Added new circuit simulator examples in ["examples/circuits"]:
    • teleport_qubit_circuit.cpp - qubit teleportation circuit example
    • teleport_qudit_circuit.cpp - qudit teleportation circuit example
  • Removed qpp::eps constant from ["constants.h"], as one should simply use direct comparison with 0 when dealing with small doubles
  • Added support for hashing Eigen matrices/vectors/expressions via qpp::hash_eigen() in ["functions.h"]; code based on boost::hash_combine(), see https://www.boost.org/doc/libs/1_69_0/doc/html/hash/reference.html#boost.hash_combine

Version 1.1 - 26 November 2018

  • Added new functions in ["operations.h"]:
    • qpp::QFT() - qudit quantum Fourier transform (includes qubit QFT as a special case) on an entire quantum state (state vector or density matrix)
    • qpp::applyQFT() - apply the qudit quantum Fourier transform on a subset of qudits of a state vector or density matrix
  • Added Quantum Fourier transform example in ["examples/qft.cpp"]
  • Added new member functions for qpp::Gates:
    • qpp::Gates::RX() - rotation around X
    • qpp::Gates::RY() - rotation around Y
    • qpp::Gates::RZ() - rotation around Z
    • qpp::Gates.SWAPd() - qudit SWAP gate
  • Added a suite of stress tests in ["stress_tests"] (only for POSIX systems)
  • Added Qiskit and QuTiP stress tests in ["stress_tests/python"]

Version 1.0 - 3 July 2018

  • Added full support for reversible classical circuits, added ["classes/reversible.h"] header file that contains the following classes:
    • qpp::Dynamic_bitset - bitsets of variable length
    • qpp::Bit_circuit - classical reversible circuits
  • Added ["examples/reversible.cpp"] example
  • The path to MATLAB can now be specified in the CMake command line (not hard coded anymore), such as cmake .. -DWITH_MATLAB="/Applications/MATLAB_R2017b.app"
  • qpp::ket operator "" \_ket(), qpp::ket operator "" _bra() and qpp::ket operator "" _prj() are now inside the newly introduced inline namespace qpp::literals
  • Minor bugfix in qpp::Exception::what(), thanks Nick Lewycky for spotting it
  • Updated the Wiki

Version 1.0-rc4 - Release Candidate 4, 24 January 2018

  • Changed qpp::ket operator "" \_q() to qpp::ket operator "" \_ket()
  • Added qpp::bra operator "" \_bra() and qpp::cmat operator "" \_prj()
  • Updated documentation

Version 1.0-rc3 - Release Candidate 3, 21 January 2018

  • License change from GPL to MIT
  • Added Visual Studio 2017 solution
  • Added support for AppVeyor continuous integration
  • Added support for reversible classical circuits, via the following classes in ["experimental.h"]:
    • qpp::experimental::Dynamic_bitset - bitsets of variable length
    • qpp::experimental::Bit_circuit - classical reversible circuits
  • Added qpp::ket operator "" \_q() helper in ["functions.h"] for constructing multi-partite qubit kets
  • Added comprehensive Wiki instead of the quick starting guide

Version 1.0-rc2 - Release Candidate 2, 6 September 2017

  • Added serialization capabilities for the PRNG in qpp::RandomDevices from ["classes/random_devices.h"]:
    • qpp::RandomDevices::load() - loads the state of PRNG from a stream
    • qpp::RandomDevices::save() - saves the state of PRNG to a stream
  • Added a getter for qpp::RandomDevices::prng_ (now with private access):
    • qpp::RandomDevices::get_prng()
  • Eigen3 is detected automatically by CMake (if Eigen3 was installed via a package manager). If not, it can be specified manually by passing the -DEIGEN3_INCLUDE_DIR=/path/to/eigen3 flag to the CMake command line.

Version 1.0-rc1 - Release Candidate 1, 11 November 2016

  • Slight performance improvements (lambda workers do not capture by value anymore)
  • API change in ["classes/exception.h"]: now all Quantum++ exceptions have their own type, being derived from the base exception class qpp::exception::Exception. All exception classes are now in their separate namespace qpp::exception.

Version 1.0.0-beta4 - 2 November 2016

  • Added new functions in ["classes/states.h"]:
    • qpp::States::zero() - zero state of n qudits
    • qpp::States::one() - one state of n qudits
    • qpp::States::jn() - |jj...j> state of n qudits
    • qpp::States::plus() - plus state of n qubits
    • qpp::States::minus() - minus state of n qubits
  • Corrected qpp::is_matrix_expression<> type trait so now it works fine Thanks to @davidhigh https://stackoverflow.com/a/40293333/3093378
  • Bugfix in qpp::cor()
  • Renamed qpp::loadMATLABmatrix() and saveMATLABmatrix() to qpp::loadMATLAB() and qpp::saveMATLAB(), respectively. Slightly changed their implementation so now one can load/save any Eigen type, similarly to qpp::load() and qpp::save().
  • Almost full code coverage via unit testing

Version 1.0.0-beta3 - 22 October 2016

  • Added support for Travis CI continuous integration
  • Added new functions in ["classes/states.h"]:
    • qpp::States::mes() - maximally entangled state of 2 qudits
  • Added new functions in ["random.h"]:
    • qpp::randprob() - random probability vector uniformly distributed over the probability simplex

Version 1.0.0-beta2 - 13 October 2016

  • Updated to GoogleTest 1.8.0 for unit testing
  • Added d = 2 overloads for all functions that take a list of dimensions as one of their arguments
  • Additional code sanitizing and unit testing

Version 1.0.0-beta1 - 10 October 2016

  • GoogleMock 1.7.0 is now included in the project for portable unit testing (see the README.md file for more details)
  • Removed the qpp::ubigint type so there is no more danger of mixing signed and unsigned types. All related functions now use qpp::bigint.
  • Fixed overflow bug in qpp::powm() when numbers were very large
  • qpp::isprime() is now based on the Miller-Rabin primality test
  • qpp::rand(Type a, Type b) family of functions now throw if b > a for integer types or when a == b for floating-point types
  • Added new functions in ["number_theory.h"]:
    • qpp::randprime() - random prime number generator
    • qpp::modmul() - modular multiplication that avoids overflows
  • Additional unit testing, added unit testing skeleton for all codebase

Version 0.8.8.2 - 3 October 2016

  • This is a bugfix release
  • Compile-time bugfix in qpp::measure_seq() due to trying to modify a const copy, which should have been non-const

Version 0.8.8 - 30 September 2016

  • Added OpenMP support for clang >= 3.7 in CmakeLists.txt
  • Required minimum CMake version is now 3.0
  • Added more unit testing, ["number_theory.h"] is now fully tested
  • Split unit testing into separate files according to the tested header file
  • Fixed typo in CMakeLists.txt which in effect disabled OpenMP for version 0.8.6. PLEASE use the CMakeLists.txt from the current version!
  • SFINAE for all functions that have STL-containers as parameters
  • Improved performance via removing unnecessary copy, see Issue #31, thanks @vasekp
  • Corrected code typo in qpp::internal::Singleton<T>, see Issue #35, thanks @titaschanda
  • Critical bugfix in qpp::lcm(const std::vector<bigint>&)
  • Critical bugfix in qpp::x2contfrac()
  • Added new functions in ["number_theory.h"]:
    • qpp::egcd() - extended greatest common divisor algorithm
    • qpp::modinv() - modular inverse of a mod p

Version 0.8.6 - 1 November 2015

  • Critical bugfix in qpp::applyCTRL(), which was failing before for control gates with 2 or more controls. Added unit test in ["unit_tests/testing.cpp"].
  • Removed ["macros.h"] preprocessor debug macros header added in v0.8.4

Version 0.8.4 - 14 October 2015

  • Added ["macros.h"] preprocessor debug macros header, containing:
    • PRINT(x) - std::cout << (x)
    • PRINTLN(x) - std::cout << (x) << std::endl
    • ERROR(x) - std::cerr << (x)
    • ERRORLN(x) - std::cerr << (x) << std::endl
  • Added new functions in ["operations.h"]:
    • qpp::ip() - Generalized inner product
  • Modified qpp::measure() so that the output consists of pure states whenever the input is a pure state and the measurement operators are rank-one POVMs (technically rank-one Kraus operators). Includes basis measurements as a particular case.
  • Improved qpp::Timer<>, now both the duration and the clock's type can be specified as template parameters, defaulted to std::chrono::duration<double> and std::chrono::steady_clock, respectively

Version 0.8.2 - 20 May 2015

  • Added ["traits.h"] type traits header file with the following type traits:
    • qpp::is_iterable<> - checks for iterable STL-like containers
    • qpp::is_matrix_expression<> - checks for Eigen::MatrixBase<> expressions
    • qpp::is_complex<> - checks whether the type is std::complex<>
  • Added ["statistics.h"] header file containing the following new functions:
    • qpp::uniform() - uniform probability distribution vector
    • qpp::marginalX() - marginal distribution
    • qpp::marginalY() - marginal distribution
    • qpp::avg() - average
    • qpp::sigma() - standard deviation
    • qpp::cov() - covariance
    • qpp::cor() - correlation
    • qpp::var() - variance
  • Added new examples in the directory ["examples"]

Version 0.8 - 8 May 2015

  • Added new data type aliases in ["types.h"]:
    • bigint - Big integer, alias for long long int
    • ubigint - Non-negative big integer, alias for unsigned long long int
  • Added new overloads in ["random.h"]:
    • qpp::rand() - overloads for bigint and ubigint
  • Added new functions in ["number_theory.h"]:
    • qpp::modpow() - computes a^n mod p for non-negative integers
  • Added IDisplay as an abstract base class for enforcing the override of its member function:
    • std::ostream& IDisplay::display(std::ostream&) const in all derived classes. This latter function performs all of the stream extraction operator work, and it is invoked automatically by the friend std::ostream& operator<<(std::ostream&, const qpp::IDisplay&) defined inline in qpp::IDisplay. In other words, the extraction operator delegates the work to the virtual display() function. Finally, all classes that support stream extraction (qpp::IOManipEigen, qpp::IOManipPointer, qpp::IOManipRange, and qpp::Timer) now inherit from qpp::IDisplay.
  • Replaced std::basic_ostream<charT, traits> by std::ostream in all code, as using traits over-complicated the design and it was not worth it.
  • Marked final all classes that are not intended to be used as base classes.
  • Modified the CMakeLists.txt, which now:
    • supports only GCC and LLVM/Apple clang; otherwise, emits an error during the CMake running phase
    • adds -D_NO_THREAD_LOCAL definition for conditional compiling the source code without support for std::thread_local (if using e.g., LLVM/Apple clang with libc++, as libc++ does not yet support std::thread_local)
    • uses OpenMP only if the compiler is detected as GCC

Version 0.7 - 22 April 2015

  • Marked all non-template functions defined in headers as inline and all singletons as static since otherwise including ["qpp.h"] in separate compilation units led to linker errors due to duplicated symbols.

Version 0.6 - 16 April 2015

  • Reverted changes to qpp::internal::Singleton<T> (no need anymore for static void operator delete(void*)), but clients have to explicitly mark both constructor and destructor private.
  • Minor cosmetic changes.

Version 0.5 - 19 March 2015

  • Bugfix in class qpp::internal::Singleton<T> which allowed deleting the instance via a pointer. Now static void operator delete(void*) is marked private.

Version 0.4 - 8 March 2015

  • Added noexcept specification where suitable
  • Added the following exception types to the qpp::Exception::Type strong enumeration: NOT_QUBIT_MATRIX (replaces previous NOT_QUBIT_GATE), NOT_QUBIT_CVECTOR, NOT_QUBIT_RVECTOR and NOT_QUBIT_VECTOR
  • Added overloads of qpp::ptrace1(), qpp::ptrace2(), qpp::ptrace() and qpp::ptranspose() that allow a pure state input, as it was the case before with qpp::syspermute()
  • Added overloads of qpp::prod() and qpp::sum() for STL-like containers
  • Added new functions in ["functions.h"]:
    • qpp::complement() - computes the complement of a subsystem vector
    • qpp::rho2bloch() - qubit density matrix to Bloch vector
    • qpp::bloch2rho() - Bloch vector to qubit density matrix
  • Added new functions in ["instruments.h"]:
  • qpp::measure_seq() - measures subsystems sequentially
  • Removed support for the C-style random number engine, as it is not thread safe. Hence, Eigen::Matrix::Random() should not be used, use instead qpp::rand() functions.
  • Added support for unit testing via Google Mock/Google Test, see ["unit_tests/testing.cpp"]

Version 0.3 - 15 February 2015

  • Added qpp::internal::Singleton<T>::get_thread_local_instance()

Version 0.2 - 26 January 2015

  • Minor fixes
  • Added prime-number related functions in ["number_theory.h"]:
    • qpp::factors() - prime factors of positive integer
    • qpp::isprime() - primality test

Version 0.1 - 21 December 2014

  • First stable version, initial public release