2017.01.05
Contents

The QWQNG.QNG ActiveX control requires Windows Vista or later.

QNG hardware is accessed using the QWQNG.QNG ActiveX control. As such, it is widely supported among different Windows environments and languages. If you do not find a basic example suitable for your particular environment, consult your developers guide on how to use ActiveX controls.

The quickest way to get started is by looking at the properties for reading random numbers from the QNG device and trying the example code given for each property. The properties for reading random numbers from the device are RandInt32, RandUniform, RandNormal, and RandBytes. The example code is meant to concisely demonstrate the use of the QWQNG.QNG ActiveX methods and properties and thus does not adhere to best coding practices, such as exception/error handling, etc.

The QWQNG.QNG ActiveX control version 3.5 is drop-in compatible with client applications that were designed for previous versions of the ActiveX control.

QNG hardware constantly reports hardware run-time test results. If run-time test results appear questionable, the QWQNG.QNG ActiveX control immediately shuts down the hardware and reports the exception. See the section on Runtime Testing for more information.

The QWQNG.QNG control provides custom HRESULT codes on every method or property call. HRESULT codes provide exception/error detail. If any error condition is detected, the hardware device will be shut down and the appropriate HRESULT code will be passed to the caller. The HRESULT error code will persist until a Reset() call is issued. The Reset() call will attempt to restart the hardware and clear the error code. See the section on Error Handling for examples and more information.

During a programming session, a programming environment typically sets the Ambient Properties for an ActiveX control to design mode. In design mode the QWQNG.QNG control will return default values for RandInt32 (123456789), RandUniform (0.123456789), RandNormal (1.23456789) and RandBytes (1234567890123...). If the QWQNG.QNG control returns these values at run-time, please make sure the User Mode Ambient Property is set to TRUE at run-time. This should normally not be an issue, however.

Contact ComScire via email, phone, or mail regarding any support issues. Please visit our website to obtain our latest support contact information.

http://ComScire.com

HRESULT RandInt32([out, retval] LONG* pVal)
Random 32 bit integer as LONG (VT_I4)
RandInt32 is a COM property that returns a 32 bit random integer. Each RandInt32 integer contains 32 bits of entropy.
// #import directive using full path to "QWQNG.dll" #import "QWQNG.dll" no_namespace named_guids int main() { CoInitialize(NULL); IQNGPtr qng = 0; qng.CreateInstance(CLSID_QNG); int rand32 = qng->RandInt32; printf("%i\n", rand32); return 0; }
// requires reference to "ComScire QNG Control Library 3.5" using System; class Program { static void Main(string[] args) { QWQNG.QNG qng = new QWQNG.QNG(); int rand32 = qng.RandInt32; Console.WriteLine(rand32.ToString()); } }
# requires PyWin32 extensions import win32com.client qng = win32com.client.Dispatch("QWQNG.QNG") rand32 = qng.RandInt32 print rand32
HRESULT RandUniform([out, retval] DOUBLE* pVal)
Random uniform number [0,1) as DOUBLE (VT_R8)
RandUniform is a COM property that returns a double float that is randomly selected from a uniform distribution. Each RandUniform number contains 48 bits of entropy.
// #import directive using full path to "QWQNG.dll" #import "QWQNG.dll" no_namespace named_guids int main() { CoInitialize(NULL); IQNGPtr qng = 0; qng.CreateInstance(CLSID_QNG); double randuniform = qng->RandUniform; printf("%f\n", randuniform); return 0; }
// requires reference to "ComScire QNG Control Library 3.5" using System; class Program { static void Main(string[] args) { QWQNG.QNG qng = new QWQNG.QNG(); double randuniform = qng.RandUniform; Console.WriteLine(randuniform.ToString()); } }
# requires PyWin32 extensions import win32com.client qng = win32com.client.Dispatch("QWQNG.QNG") randuniform = qng.RandUniform print randuniform
HRESULT RandNormal([out, retval] DOUBLE* pVal)
Random normal number with mean zero and standard deviation one as DOUBLE (VT_R8)
RandNormal is a COM property that returns a double float that is randomly selected from a normal distribution. RandNormal numbers are produced by transforming uniform numbers, with 48 bits of entropy each, into normal numbers using the Box-Muller method.
// #import directive using full path to "QWQNG.dll" #import "QWQNG.dll" no_namespace named_guids int main() { CoInitialize(NULL); IQNGPtr qng = 0; qng.CreateInstance(CLSID_QNG); double randnormal = qng->RandNormal; printf("%f\n", randnormal); return 0; }
// requires reference to "ComScire QNG Control Library 3.5" using System; class Program { static void Main(string[] args) { QWQNG.QNG qng = new QWQNG.QNG(); double randnormal = qng.RandNormal; Console.WriteLine(randnormal.ToString()); } }
# requires PyWin32 extensions import win32com.client qng = win32com.client.Dispatch("QWQNG.QNG") randnormal = qng.RandNormal print randnormal
HRESULT RandBytes([in] LONG Length, [out, retval] VARIANT* pVal)
Length: Number of bytes to be returned from RandBytes. Must not exceed 8192 for generator output rate of 32 Mbps or less, 65536 for generator output rate of 64 or 128 Mbps.
Byte array as VARIANT SAFEARRAY of BYTES (VT_ARRAY of VT_U1)
RandBytes is a COM property that returns a byte array of random bytes. Each byte contains 8 bits of entropy. If Length exceeds maximum allowed requested bytes, the control will return the QNG_E_IO_ARRAY_OVERSIZED error code. For information on using Variant SAFEARRAY's, please consult documentation specific to your programming environment.
// #import directive using full path to "QWQNG.dll" #import "QWQNG.dll" no_namespace named_guids int main() { CoInitialize(NULL); IQNGPtr qng = 0; qng.CreateInstance(CLSID_QNG); _variant_t randvt = qng->RandBytes[10]; VARIANT randvariant = randvt.GetVARIANT(); int bytecount = randvariant.parray->rgsabound[0].cElements - randvariant.parray->rgsabound[0].lLbound; char* randbyte; SafeArrayAccessData(randvariant.parray, (void**)&randbyte); for (int i=0; i<bytecount; i++) { printf("%X ", (*randbyte)&0xff); randbyte++; } SafeArrayUnaccessData(randvariant.parray); printf ("\n"); return 0; }
// requires reference to "ComScire QNG Control Library 3.5" using System; class Program { static void Main(string[] args) { QWQNG.QNG qng = new QWQNG.QNG(); byte[] randbytes = (byte[])qng.get_RandBytes(10); foreach (byte b in randbytes) Console.Write("{0:X} ", b); Console.WriteLine(); } }
# requires PyWin32 extensions import win32com.client qng = win32com.client.Dispatch("QWQNG.QNG") randbytes = qng.RandBytes(10) print randbytes
HRESULT Clear(VOID)
Clear is a COM method that purges internal data buffers. If random data is not continuously consumed, random data will remain available in internal buffers. A call to Clear will remove "stale" data from the buffers.
// #import directive using full path to "QWQNG.dll" #import "QWQNG.dll" no_namespace named_guids int main() { CoInitialize(NULL); IQNGPtr qng = 0; qng.CreateInstance(CLSID_QNG); // clear random data sitting in internal buffers qng->Clear(); return 0; }
// requires reference to "ComScire QNG Control Library 3.5" using System; class Program { static void Main(string[] args) { QWQNG.QNG qng = new QWQNG.QNG(); // clear random data sitting in internal buffers qng.Clear(); } }
# requires PyWin32 extensions import win32com.client qng = win32com.client.Dispatch("QWQNG.QNG") # clear random data sitting in internal buffers qng.Clear()
HRESULT Reset(VOID)
Reset() is a COM method that clears the buffers and resets the hardware device.
// #import directive using full path to "QWQNG.dll" #import "QWQNG.dll" no_namespace named_guids int main() { CoInitialize(NULL); IQNGPtr qng = 0; qng.CreateInstance(CLSID_QNG); // attempt a complete hardware reset qng->Reset(); return 0; }
// requires reference to "ComScire QNG Control Library 3.5" using System; class Program { static void Main(string[] args) { QWQNG.QNG qng = new QWQNG.QNG(); // attempt a complete hardware reset qng.Reset(); } }
# requires PyWin32 extensions import win32com.client qng = win32com.client.Dispatch("QWQNG.QNG") # attempt a complete hardware reset qng.Reset()
HRESULT DeviceId([out, retval] BSTR* devId)
Serial number as a binary string.
DeviceId is a COM property that returns a the device serial number as a BSTR.
// #import directive using full path to "QWQNG.dll" #import "QWQNG.dll" no_namespace named_guids int main() { CoInitialize(NULL); IQNGPtr qng = 0; qng.CreateInstance(CLSID_QNG); BSTR deviceId = qng->DeviceId; printf("%S\n", deviceId); return 0; }
// requires reference to "ComScire QNG Control Library 3.5" using System; class Program { static void Main(string[] args) { QWQNG.QNG qng = new QWQNG.QNG(); string deviceId = qng.DeviceId; Console.WriteLine(deviceId); } }
# requires PyWin32 extensions import win32com.client qng = win32com.client.Dispatch("QWQNG.QNG") deviceId = qng.DeviceId print deviceId
HRESULT RuntimeInfo([out, retval] VARIANT* runtimeInfo)
Float array as VARIANT SAFEARRAY of 32 bit floating point numbers (VT_ARRAY of VT_R4)
RuntimeInfo is a COM property that returns a SAFEARRAY of 17 floating point numbers. The numbers indicate the internal runtime state. Assuming a zero index based array:
runtimeInfo[0]: General statistical status. A zero (0) indicates that all internal statistics
are within expected ranges and a minus one (-1) indicates an exception. runtimeInfo[1]: Entropy H(P) of final output channel. runtimeInfo[2]: Predictability value (P) of final output channel. runtimeInfo[3]: Bias of final output channel. runtimeInfo[4]: 1st order serial correlation of final output channel. runtimeInfo[5]: Entropy H(P) of 1st raw generator channel. runtimeInfo[6]: Predictability value (P) of 1st raw generator channel. runtimeInfo[7]: Bias of 1st raw generator channel. runtimeInfo[8]: 1st order serial correlation of 1st raw generator channel. runtimeInfo[9]: Entropy H(P) of 2nd raw generator channel. runtimeInfo[10]: Predictability value (P) of 2nd raw generator channel. runtimeInfo[11]: Bias of 2nd raw generator channel. runtimeInfo[12]: 1st order serial correlation of 2nd raw generator channel. runtimeInfo[13]: Entropy H(P) of 3rd raw generator channel. runtimeInfo[14]: Predictability value (P) of 3rd raw generator channel. runtimeInfo[15]: Bias of 3rd raw generator channel. runtimeInfo[16]: 1st order serial correlation of 3rd raw generator channel.
RuntimeInfo is not supported on devices prior to the model R2000KU.
// #import directive using full path to "QWQNG.dll" #import "QWQNG.dll" no_namespace named_guids int main() { CoInitialize(NULL); IQNGPtr qng = 0; qng.CreateInstance(CLSID_QNG); _variant_t randvt = qng->RuntimeInfo; VARIANT randvariant = randvt.GetVARIANT(); int infoCount = randvariant.parray->rgsabound[0].cElements - randvariant.parray->rgsabound[0].lLbound; float* runtimeInfo; SafeArrayAccessData(randvariant.parray, (void**)&runtimeInfo); for (int i=0; i<infoCount; i++) { printf("%02i: %1.6f ", i, *runtimeInfo); runtimeInfo++; } SafeArrayUnaccessData(randvariant.parray); printf ("\n"); return 0; }
// requires reference to "ComScire QNG Control Library 3.5" using System; class Program { static void Main(string[] args) { QWQNG.QNG qng = new QWQNG.QNG(); float[] runtimeInfo = (float[])qng.RuntimeInfo; for (int i=0; i<runtimeInfo.Length; i++) Console.Write("{0}: {1} ", i, runtimeInfo[i]); Console.WriteLine(); } }
# requires PyWin32 extensions import win32com.client qng = win32com.client.Dispatch("QWQNG.QNG") runtimeInfo = qng.runtimeInfo print runtimeInfo
HRESULT Diagnostics([in] LONG dxCode, [out, retval] VARIANT* dxInfo)
Byte array as VARIANT SAFEARRAY of BYTES (VT_ARRAY of VT_U1)
Diagnostics is a COM property that returns a SAFEARRAY of 128 bytes for a specified internal pre-output raw data channel on a specific level of processing. Diagnostics provides insight into three entropy combining levels of processing in Pure Quantum™ (PQ) generators. Each sucessive level, beginning with level 1, combines more entropy per bit towards the final output. The final output itself exceeds NIST defined full entropy without utilizing correction, whitening, or conditioning. Note that low-level pre-output data is not expected to look perfectly random. Therefore, data gathered from Diagnostics should never be used in random data consuming applications. The intention of Diagnostics is to allow measurements into the the pre-output generation levels to follow and confirm theoretical generation models. More information on Pure Quantum™ generation internals can be found in whitepapers published on the ComScire website. Diagnostics allows access to three levels of pre-output generation with three channels per level. The following lists corresponding hex Diagnostics codes (dxCode) for each level and channel:
Level 1, Channel 1: 0x10
Level 1, Channel 2: 0x11
Level 1, Channel 3: 0x12
Level 2, Channel 1: 0x13
Level 2, Channel 2: 0x14
Level 2, Channel 3: 0x15
Level 3, Channel 1: 0x16
Level 3, Channel 2: 0x17
Level 3, Channel 3: 0x18
Note that there may be other undocumented Diagnostics codes (dxCode). However, using these codes may produce unexpected outputs or results. Nonetheless, random data obtained through the random API calls (RandInt32, RandUniform, RandNormal, RandBytes) is entirely unaffected by Diagnostics calls. Diagnostics is not supported on devices prior to the Pure Quantum™ (PQ) models.
// #import directive using full path to "QWQNG.dll" #import "QWQNG.dll" no_namespace named_guids int main() { CoInitialize(NULL); IQNGPtr qng = 0; qng.CreateInstance(CLSID_QNG); // Level 2, Channel 3 dx data unsigned char controlWord = 0x15; _variant_t randvt = qng->Diagnostics(controlWord); VARIANT randvariant = randvt.GetVARIANT(); int byteCount = randvariant.parray->rgsabound[0].cElements - randvariant.parray->rgsabound[0].lLbound; unsigned char* dxData; SafeArrayAccessData(randvariant.parray, (void**)&dxData); for (int i=0; i<byteCount; i++) { printf("%02X ", *dxData); dxData++; } SafeArrayUnaccessData(randvariant.parray); printf ("\n"); return 0; }
// requires reference to "ComScire QNG Control Library 3.5" using System; class Program { static void Main(string[] args) { QWQNG.QNG qng = new QWQNG.QNG(); // Level 2, Channel 3 dx data byte controlWord = 0x15; byte[] dxData = (float[])qng.Diagnostics(controlWord); foreach (byte b in dxData) Console.Write("{0:X} ", b); Console.WriteLine(); } }
# requires PyWin32 extensions import win32com.client qng = win32com.client.Dispatch("QWQNG.QNG") # Level 2, Channel 3 dx data dxData = qng.Diagnostics(0x15) print dxData
The QWQNG.QNG ActiveX control returns a set of custom HRESULT error codes. Check your programming language/environment documentation to get more information on how to handle ActiveX errors or exceptions. All error conditions will persist until cleared by a succesful Reset method call.
QNG_S_OK 00044400h QNG device reports success. QNG_E_GENERAL_FAILURE 80044401h QNG general error. QNG_E_IO_ERROR 80044402h QNG I/O error. QNG_E_IO_TIMEOUT 80044403h QNG I/O request has timed out. QNG_E_IO_ARRAY_OVERSIZED 80044404h QNG read array size exceeds max size. QNG_E_STATS_EXCEPTION 80044406h QNG test statistics exception. QNG_E_STATS_UNSUPPORTED 80044407h QNG stats not supported with this device. QNG_E_DIAGX_UNSUPPORTED 80044408h QNG diagnostics not supported with this device. QNG_E_DEVICE_NOT_OPENED 8004440Ah QNG device not found or already in use. S_OK 00000000h No error occurred.
// #import directive using full path to "QWQNG.dll" #import "QWQNG.dll" no_namespace named_guids int main() { CoInitialize(NULL); IQNGPtr qng = 0; qng.CreateInstance(CLSID_QNG); try { // this will force a QNG_E_IO_ARRAY_OVERSIZED exception qng->RandBytes[8193]; } catch(_com_error& e) { // Get exception description as a char* _bstr_t bDsc = e.Description(); char* sDsc = (char*)bDsc; printf("Error %X - %s\n\n", e.Error(), sDsc); qng->Reset(); // attempting a reset to clear exception } return 0; }
// requires reference to "ComScire QNG Control Library 3.5" using System; using System.Runtime.InteropServices; class Program { static void Main(string[] args) { QWQNG.QNG qng = new QWQNG.QNG(); try { // this will force a QNG_E_IO_ARRAY_OVERSIZED exception qng.get_RandBytes(8193); } catch (COMException exception) { Console.WriteLine(exception.Message); qng.Reset(); // attempting a reset to clear exception } } }
# requires PyWin32 extensions import win32com.client import pythoncom qng = win32com.client.Dispatch("QWQNG.QNG") try: # this will force a QNG_E_IO_ARRAY_OVERSIZED exception qng.RandBytes(8193) except pythoncom.com_error, exception: print exception qng.Reset() # attempting a reset to clear exception
This algorithm uniformly selects a single number from a range of integers. It is equivalent to drawing a single number out of a bin that contains each number in the range from min-value to max-value. The maximum range length for this algorithm is 2^32, since 32 bit integers are assumed for randomizing. Note that exception and boundary conditions are not handled in the example code and should be added to production code.
(1) min_bound = least integer in number range (2) max_bound = greatest integer in number range (3) interval_len = max_bound - min_bound + 1 (4) int32_bound = 2^32 - (2^32 MODULO interval_len) (5) rand32 = new random 32 bit unsigned integer (6) IF rand32 > int32_bound THEN GOTO step 5 (7) return_val = min_bound + (rand32 MODULO interval_len)
def random_range(min_bound, max_bound): interval_len = max_bound - min_bound + 1 int32_bound = 2^32 - (2^32 % interval_len) rand32 = qng.RandInt32 while rand32 > int32_bound: rand32 = qng.RandInt32 return min_bound + (rand32 % interval_len)
This algorithm uniformly draws n number of elements out of a given set of elements. It is equivalent to randomly selecting and removing items from a fixed set bin one by one.
(1) input_set = input set (2) sample_count = desired sample set size (3) element_index = CALL Random Range algorithm WITH min_bound = 0 AND max_bound = sample set size - 1 (4) ADD input_set[element_index] TO sample_set (6) REMOVE input_set[element_index] FROM input_set (7) IF sample_set CONTAINS sample_count elements THEN RETURN sample_set ELSE GOTO Step (3) WITH reduced input_set
def random_sample(input_set, sample_count): sample_set = [] while (len(sample_set) != sample_count): element_index = random_range(0, len(input_set)-1) sample_set.append(input_set[element_index]) input_set.pop(element_index) return sample_set