Skip to content

Commit

Permalink
MSVC Fix
Browse files Browse the repository at this point in the history
  • Loading branch information
eessmann committed Feb 18, 2025
1 parent 2525681 commit ffa7877
Show file tree
Hide file tree
Showing 10 changed files with 94 additions and 24 deletions.
10 changes: 8 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,12 @@ option(
)
message(STATUS "Deprecated API support is turned ${ENABLE_DEPRECATED_API}. Set ENABLE_DEPRECATED_API to modify.")

# Windows Specific Options
if(MSVC)
set(ENABLE_MULTITHREADING OFF)
set(BUILD_SHARED_LIBS OFF)
endif()

## Library

add_library(QuEST)
Expand All @@ -175,7 +181,7 @@ target_include_directories(QuEST
target_compile_features(QuEST
PUBLIC
c_std_11
cxx_std_17
cxx_std_20
)

# Turn on all compiler warnings
Expand Down Expand Up @@ -286,7 +292,7 @@ add_subdirectory(quest)
add_executable(min_example
examples/tutorials/min_example.cpp
)
target_link_libraries(min_example PUBLIC QuEST::QuEST)
target_link_libraries(min_example PRIVATE QuEST::QuEST)

install(TARGETS min_example
RUNTIME
Expand Down
12 changes: 8 additions & 4 deletions quest/include/matrices.h
Original file line number Diff line number Diff line change
Expand Up @@ -216,18 +216,19 @@ typedef struct {

static inline CompMatr1 getCompMatr1(qcomp** in) {

return (CompMatr1) {
CompMatr1 out = {
.numQubits = 1,
.numRows = 2,
.elems = {
{in[0][0], in[0][1]},
{in[1][0], in[1][1]}}
};
return out;
}

static inline CompMatr2 getCompMatr2(qcomp** in) {

return (CompMatr2) {
CompMatr2 out = {
.numQubits = 2,
.numRows = 4,
.elems = {
Expand All @@ -236,25 +237,28 @@ static inline CompMatr2 getCompMatr2(qcomp** in) {
{in[2][0], in[2][1], in[2][2], in[2][3]},
{in[3][0], in[3][1], in[3][2], in[3][3]}}
};
return out;
}


static inline DiagMatr1 getDiagMatr1(qcomp* in) {

return (DiagMatr1) {
DiagMatr1 out = {
.numQubits = 1,
.numElems = 2,
.elems = {in[0], in[1]}
};
return out;
}

static inline DiagMatr2 getDiagMatr2(qcomp* in) {

return (DiagMatr2) {
DiagMatr2 out = {
.numQubits = 2,
.numElems = 4,
.elems = {in[0], in[1], in[2], in[3]}
};
return out;
}


Expand Down
2 changes: 1 addition & 1 deletion quest/src/api/operations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* arbitrary matrices) upon Quregs, which can be
* statevectors or density matrices
*/

#define _USE_MATH_DEFINES
#include "quest/include/qureg.h"
#include "quest/include/matrices.h"
#include "quest/include/operations.h"
Expand Down
38 changes: 35 additions & 3 deletions quest/src/core/bitwise.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
#ifndef BITWISE_HPP
#define BITWISE_HPP

#ifdef _MSC_VER
#include <intrin.h>
#endif

#include "quest/include/types.h"

#include "quest/src/core/inliner.hpp"
Expand Down Expand Up @@ -105,9 +109,37 @@ INLINE qindex setBit(qindex number, int bitIndex, int bitValue) {


INLINE int getBitMaskParity(qindex mask) {

// this compiler extension may not be defined on all platforms
return __builtin_parityll(mask); // ll-suffix for 64 bit

// Try a builtin if on GCC/Clang and it is available
#if defined(__has_builtin)
#if __has_builtin(__builtin_parityll)
return __builtin_parityll(mask);
#endif
#elif defined(__GNUC__) || defined(__clang__)
// Older GCC/Clang typically have __builtin_parityll by default
return __builtin_parityll(mask);
#endif
// Use MSVC-specific popcount intrinsic if available
#ifdef _MSC_VER
return __popcnt64(mask) & 1;
#endif

// Fallback: a portable nibble-based trick for parity
//
// Explanation:
// - XOR the upper half into the lower half until you’re down to 4 bits.
// - Then use a 16-bit constant (0x6996) to map 4-bit values to their parity.
static_assert(sizeof(qindex) >= 4, "qindex must be at least 32 bits");
if constexpr (sizeof(qindex) >= 8) {
// If 64-bit, fold mask[63..32] into mask[31..0]
mask ^= (mask >> 32);
}
// Then fold mask[31..16] into mask[15..0], etc.
mask ^= (mask >> 16);
mask ^= (mask >> 8);
mask ^= (mask >> 4);
mask &= 0xF;
return (0x6996 >> mask) & 1;
}


Expand Down
3 changes: 2 additions & 1 deletion quest/src/core/localiser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1584,7 +1584,7 @@ void localiser_densmatr_oneQubitDamping(Qureg qureg, int qubit, qreal prob) {

CompMatr getCompMatrFromSuperOp(SuperOp op) {

return (CompMatr) {
CompMatr out = {
// superoperator acts on twice as many qubits
.numQubits = 2 * op.numQubits,
.numRows = op.numRows,
Expand All @@ -1596,6 +1596,7 @@ CompMatr getCompMatrFromSuperOp(SuperOp op) {
.cpuElems = op.cpuElems,
.gpuElemsFlat = op.gpuElemsFlat
};
return out;
}


Expand Down
43 changes: 33 additions & 10 deletions quest/src/core/printer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,13 @@
#include <iostream>
#include <iomanip>
#include <sstream>
#include <memory>
#include <vector>
#include <tuple>
#include <string>
#include <new>


using std::cout;
using std::endl;
using std::left;
Expand Down Expand Up @@ -144,19 +146,40 @@ void printer_setMaxNumPrintedSigFig(int numSigFigs) {
#define GET_STR(x) GET_STR_INTERNAL(x)


// type T can be anything in principle, although it's currently only used for qcomp
template<typename T>
string getTypeName(T) {
inline std::string demangleTypeName(const char* mangledName) {
#if defined(__GNUC__) || defined(__clang__)
int status = 0;

// get possibly-mangled type name
string name = typeid(T).name();
// __cxa_demangle returns a malloc'd string, so we wrap it in a unique_ptr
// for automatic cleanup. (The custom deleter calls free().)
std::unique_ptr<char, void(*)(void*)> demangled(
abi::__cxa_demangle(mangledName, nullptr, nullptr, &status),
std::free
);

if (status == 0 && demangled) {
return demangled.get();
} else {
// fall back to the mangled name
return mangledName;
}
#else
// e.g. MSVC or unknown compiler: no standard demangler
return mangledName;
#endif
}

// non-MSVC compilers can de-mangle
#ifdef DEMANGLE_TYPE
name = abi::__cxa_demangle(name.c_str(), nullptr, nullptr, nullptr);
#endif

return name;
// type T can be anything in principle, although it's currently only used for qcomp
template <typename T>
std::string getTypeName(T _unused) {
// For MSVC, typeid(T).name() typically returns something like "class Foo"
// or "struct Foo", but it's still not exactly "Foo".
// For GCC/Clang, you get a raw "mangled" name, e.g. "N3FooE".
const char* rawName = typeid(T).name();

// We'll try to demangle if we can:
return demangleTypeName(rawName);
}


Expand Down
6 changes: 4 additions & 2 deletions quest/src/core/validation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -986,7 +986,7 @@ namespace report {
/*
* INVALID INPUT RESPONSE BEHAVIOUR
*/

extern "C" {
// default C/C++ compatible error response is to simply exit in fail state
void default_invalidQuESTInputError(const char* msg, const char* func) {

Expand All @@ -1008,7 +1008,9 @@ void default_invalidQuESTInputError(const char* msg, const char* func) {
}

// enable default error response to be user-overriden as a weak symbol (even in C, and on Windows)
extern "C" {

// Always declare invalidQuESTInputError so the compiler sees it:
void invalidQuESTInputError(const char* msg, const char* func);

#ifndef _WIN32
#pragma weak invalidQuESTInputError
Expand Down
2 changes: 1 addition & 1 deletion tests/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
add_executable(tests
main.cpp
)
target_link_libraries(tests PUBLIC QuEST::QuEST Catch2::Catch2)
target_link_libraries(tests PRIVATE QuEST::QuEST Catch2::Catch2)

add_subdirectory(unit)
add_subdirectory(utils)
Expand Down
1 change: 1 addition & 0 deletions tests/utils/linalg.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#define _USE_MATH_DEFINES
#include "qvector.hpp"
#include "qmatrix.hpp"
#include "linalg.hpp"
Expand Down
1 change: 1 addition & 0 deletions tests/utils/random.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#define _USE_MATH_DEFINES
#include "qvector.hpp"
#include "qmatrix.hpp"
#include "macros.hpp"
Expand Down

0 comments on commit ffa7877

Please sign in to comment.