make bitSet more comnpatible with Java implementation.

This commit is contained in:
Marty Kraimer
2013-10-31 06:03:51 -04:00
parent db10bed951
commit 0f17bd23c7
5 changed files with 189 additions and 75 deletions

View File

@@ -9,6 +9,7 @@
*/
#include "string.h"
#include "stdio.h"
#include <iostream>
#include <pv/bitSet.h>
#include <pv/lock.h>
#include <pv/serializeHelper.h>
@@ -199,6 +200,8 @@ namespace epics { namespace pvData {
}
BitSet& BitSet::operator&=(const BitSet& set) {
// Check for self-assignment!
if (this == &set) return *this;
while (wordsInUse > set.wordsInUse)
words[--wordsInUse] = 0;
@@ -213,76 +216,49 @@ namespace epics { namespace pvData {
}
BitSet& BitSet::operator|=(const BitSet& set) {
uint32 wordsInCommon;
// Check for self-assignment!
if (this == &set) return *this;
uint32 wordsInCommon = wordsInUse;
if(wordsInUse>set.wordsInUse) wordsInCommon = set.wordsInUse;
if (wordsInUse < set.wordsInUse) {
wordsInCommon = wordsInUse;
//ensureCapacity(set.wordsInUse);
//wordsInUse = set.wordsInUse;
ensureCapacity(set.wordsInUse);
wordsInUse = set.wordsInUse;
}
else
wordsInCommon = set.wordsInUse;
// Perform logical OR on words in common
uint32 i = 0;
for (; i < wordsInCommon; i++)
for (uint32 i =0; i < wordsInCommon; i++) {
words[i] |= set.words[i];
// TODO what to do if BitSets are not the same size !!!
}
// Copy any remaining words
for(uint32 i=wordsInCommon; i<set.wordsInUse; ++i) {
words[i] = set.words[i];
}
// recalculateWordsInUse() is not needed
return *this;
}
BitSet& BitSet::operator^=(const BitSet& set) {
uint32 wordsInCommon;
uint32 wordsInCommon = wordsInUse;
if(wordsInUse>set.wordsInUse) wordsInCommon = set.wordsInUse;
if (wordsInUse < set.wordsInUse) {
wordsInCommon = wordsInUse;
//ensureCapacity(set.wordsInUse);
//wordsInUse = set.wordsInUse;
ensureCapacity(set.wordsInUse);
wordsInUse = set.wordsInUse;
}
else
wordsInCommon = set.wordsInUse;
// Perform logical XOR on words in common
uint32 i = 0;
for (; i < wordsInCommon; i++)
// Perform logical OR on words in common
for (uint32 i =0; i < wordsInCommon; i++) {
words[i] ^= set.words[i];
// TODO what to do if BitSets are not the same size !!!
recalculateWordsInUse();
return *this;
}
BitSet& BitSet::operator-=(const BitSet& set) {
uint32 wordsInCommon;
if (wordsInUse < set.wordsInUse) {
wordsInCommon = wordsInUse;
//ensureCapacity(set.wordsInUse);
//wordsInUse = set.wordsInUse;
}
// Copy any remaining words
for(uint32 i=wordsInCommon; i<set.wordsInUse; ++i) {
words[i] = set.words[i];
}
else
wordsInCommon = set.wordsInUse;
// Perform logical (a & !b) on words in common
uint32 i = 0;
for (; i < wordsInCommon; i++)
words[i] &= ~set.words[i];
recalculateWordsInUse();
return *this;
}
BitSet& BitSet::operator=(const BitSet &set) {
// Check for self-assignment!
if (this == &set)
return *this;
if (this == &set) return *this;
// we ensure that words array size is adequate (and not wordsInUse to ensure capacity to the future)
if (wordsLength < set.wordsLength)

View File

@@ -45,7 +45,7 @@ namespace epics { namespace pvData {
class BitSet : public Serializable {
public:
POINTER_DEFINITIONS(BitSet);
static BitSet::shared_pointer create(uint32 nbits);
static BitSetPtr create(uint32 nbits);
/**
* Creates a new bit set. All bits are initially {@code false}.
*/
@@ -201,15 +201,6 @@ namespace epics { namespace pvData {
*/
BitSet& operator^=(const BitSet& set);
/**
* Clears all of the bits in this {@code BitSet} whose corresponding
* bit is set in the specified {@code BitSet}.
*
* @param set the {@code BitSet} with which to mask this
* {@code BitSet}
*/
BitSet& operator-=(const BitSet& set);
/**
* Assigment operator.
*/

View File

@@ -13,6 +13,9 @@ testTimer_SRCS += testTimer.cpp
PROD_HOST += testBitSet
testBitSet_SRCS += testBitSet.cpp
PROD_HOST += testOverrunBitSet
testOverrunBitSet_SRCS += testOverrunBitSet.cpp
PROD_HOST += testByteOrder
testByteOrder_SRCS += testByteOrder.cpp
@@ -22,6 +25,10 @@ testByteBuffer_SRCS += testByteBuffer.cpp
PROD_HOST += testBaseException
testBaseException_SRCS += testBaseException.cpp
TESTPROD += testSharedVector
testSharedVector_SRCS += testSharedVector.cpp
TESTS += testSharedVector
TESTPROD += testSerialization
testSerialization_SRCS += testSerialization.cpp
TESTS += testSerialization
@@ -39,10 +46,6 @@ TESTPROD += testTypeCast
testTypeCast_SRCS += testTypeCast.cpp
TESTS += testTypeCast
TESTPROD += testSharedVector
testSharedVector_SRCS += testSharedVector.cpp
TESTS += testSharedVector
TESTSCRIPTS_HOST += $(TESTS:%=%.t)
include $(TOP)/configure/RULES

View File

@@ -6,6 +6,7 @@
*/
/* Author: Matej Sekoranja Date: 2010.10.18 */
#include <iostream>
#include <stddef.h>
#include <stdlib.h>
#include <stddef.h>
@@ -96,12 +97,16 @@ void testOperators(FILE *fd) {
assert(b1 == b2);
// OR test
b1.set(65);
b1.set(106);
b2.set(65);
b2.set(106);
b2.set(105);
b1 |= b2;
std::string str; b1.toString(&str);
assert(str == "{1, 65, 105, 106}");
b1.clear();
b1 |= b2;
str.clear(); b1.toString(&str);
assert(str == "{1, 65, 105, 106}");
// AND test
b1.set(128);
@@ -112,15 +117,13 @@ void testOperators(FILE *fd) {
b1.set(128);
b1 ^= b2;
assert(b1.cardinality() == 1 && b1.get(128) == true);
// a AND (NOT b)
b2 -= b1;
str.clear(); b2.toString(&str);
assert(str == "{1, 105}");
b1.clear();
b2.clear();
b1.set(1);
b2 -= b1;
str.clear(); b2.toString(&str);
assert(b2.cardinality() == 1 && b2.get(105) == true);
b2.set(256);
b1 ^= b2;
assert(b1.cardinality() == 2 && b1.get(1) == true && b1.get(256) == true);
// assign
b1 = b2;

View File

@@ -0,0 +1,141 @@
/* testOverrunBitSet.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/* Author: Marty Kraimer Date: 2013.09.16 */
#include <iostream>
#include <stddef.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <stdio.h>
#include <epicsUnitTest.h>
#include <testMain.h>
#include <pv/bitSetUtil.h>
#include <pv/standardPVField.h>
#include <epicsAssert.h>
using namespace epics::pvData;
using std::cout;
using std::endl;
static StandardPVFieldPtr standardPVField = getStandardPVField();
void test()
{
String buffer;
String properties("alarm,timeStamp,display");
PVStructurePtr pvStructure = standardPVField->scalar(pvDouble,properties);
PVDoublePtr pvValue = pvStructure->getDoubleField("value");
uint32 valueOffset = pvValue->getFieldOffset();
PVStructurePtr pvAlarm = pvStructure->getStructureField("alarm");
PVIntPtr pvSeverity = pvAlarm->getIntField("severity");
PVStringPtr pvMessage = pvAlarm->getStringField("message");
uint32 severityOffset = pvSeverity->getFieldOffset();
uint32 messageOffset = pvMessage->getFieldOffset();
PVStructurePtr pvTimeStamp = pvStructure->getStructureField("timeStamp");
PVLongPtr pvSeconds = pvTimeStamp->getLongField("secondsPastEpoch");
PVIntPtr pvNanoSeconds = pvTimeStamp->getIntField("nanoSeconds");
PVIntPtr pvUserTag = pvTimeStamp->getIntField("userTag");
uint32 timeStampOffset = pvTimeStamp->getFieldOffset();
uint32 secondsOffset = pvSeconds->getFieldOffset();
uint32 nanoSecondsOffset = pvNanoSeconds->getFieldOffset();
uint32 userTagOffset = pvUserTag->getFieldOffset();
uint32 nfields = pvStructure->getNumberFields();
BitSetPtr changeBitSet = BitSet::create(nfields);
BitSetPtr userChangeBitSet = BitSet::create(nfields);
BitSetPtr userOverrunBitSet = BitSet::create(nfields);
pvValue->put(1.0); changeBitSet->set(valueOffset);
pvSeverity->put(2); changeBitSet->set(severityOffset);
pvMessage->put("error"); changeBitSet->set(messageOffset);
pvSeconds->put(1); changeBitSet->set(secondsOffset);
pvNanoSeconds->put(1000000); changeBitSet->set(nanoSecondsOffset);
pvUserTag->put(1); changeBitSet->set(userTagOffset);
userOverrunBitSet->or_and(*changeBitSet.get(),*userChangeBitSet.get());
(*userChangeBitSet)|=(*changeBitSet.get());
changeBitSet->clear();
pvValue->put(2.0); changeBitSet->set(valueOffset);
pvSeverity->put(0); changeBitSet->set(severityOffset);
pvMessage->put(""); changeBitSet->set(messageOffset);
pvSeconds->put(2); changeBitSet->set(secondsOffset);
pvNanoSeconds->put(0); changeBitSet->set(nanoSecondsOffset);
pvUserTag->put(0); changeBitSet->set(userTagOffset);
userOverrunBitSet->or_and(*changeBitSet.get(),*userChangeBitSet.get());
(*userChangeBitSet)|=(*changeBitSet.get());
testOk1(userChangeBitSet->cardinality()==6);
testOk1(userChangeBitSet->get(valueOffset));
testOk1(userChangeBitSet->get(severityOffset));
testOk1(userChangeBitSet->get(messageOffset));
testOk1(userChangeBitSet->get(secondsOffset));
testOk1(userChangeBitSet->get(nanoSecondsOffset));
testOk1(userChangeBitSet->get(userTagOffset));
testOk1(userOverrunBitSet->cardinality()==6);
testOk1(userOverrunBitSet->get(valueOffset));
testOk1(userOverrunBitSet->get(severityOffset));
testOk1(userOverrunBitSet->get(messageOffset));
testOk1(userOverrunBitSet->get(secondsOffset));
testOk1(userOverrunBitSet->get(nanoSecondsOffset));
testOk1(userOverrunBitSet->get(userTagOffset));
BitSetUtil::compress(userChangeBitSet,pvStructure);
BitSetUtil::compress(userOverrunBitSet,pvStructure);
testOk1(userChangeBitSet->cardinality()==4);
testOk1(userChangeBitSet->get(valueOffset));
testOk1(userChangeBitSet->get(severityOffset));
testOk1(userChangeBitSet->get(messageOffset));
testOk1(userChangeBitSet->get(timeStampOffset));
testOk1(userOverrunBitSet->cardinality()==4);
testOk1(userOverrunBitSet->get(valueOffset));
testOk1(userOverrunBitSet->get(severityOffset));
testOk1(userOverrunBitSet->get(messageOffset));
testOk1(userOverrunBitSet->get(timeStampOffset));
changeBitSet->clear();
userChangeBitSet->clear();
userOverrunBitSet->clear();
pvValue->put(1.0); changeBitSet->set(valueOffset);
pvSeconds->put(3); changeBitSet->set(secondsOffset);
pvNanoSeconds->put(0); changeBitSet->set(nanoSecondsOffset);
userOverrunBitSet->or_and(*changeBitSet.get(),*userChangeBitSet.get());
(*userChangeBitSet)|=(*changeBitSet.get());
testOk1(userChangeBitSet->cardinality()==3);
testOk1(userChangeBitSet->get(valueOffset));
testOk1(userChangeBitSet->get(secondsOffset));
testOk1(userChangeBitSet->get(nanoSecondsOffset));
testOk1(userOverrunBitSet->cardinality()==0);
changeBitSet->clear();
pvValue->put(2.0); changeBitSet->set(valueOffset);
userOverrunBitSet->or_and(*changeBitSet.get(),*userChangeBitSet.get());
(*userChangeBitSet)|=(*changeBitSet.get());
testOk1(userChangeBitSet->cardinality()==3);
testOk1(userChangeBitSet->get(valueOffset));
testOk1(userChangeBitSet->get(secondsOffset));
testOk1(userChangeBitSet->get(nanoSecondsOffset));
testOk1(userOverrunBitSet->cardinality()==1);
testOk1(userOverrunBitSet->get(valueOffset));
BitSetUtil::compress(userChangeBitSet,pvStructure);
BitSetUtil::compress(userOverrunBitSet,pvStructure);
testOk1(userChangeBitSet->cardinality()==3);
testOk1(userChangeBitSet->get(valueOffset));
testOk1(userChangeBitSet->get(secondsOffset));
testOk1(userChangeBitSet->get(nanoSecondsOffset));
testOk1(userOverrunBitSet->cardinality()==1);
testOk1(userOverrunBitSet->get(valueOffset));
}
MAIN(testOverrunBitSet`)
{
testPlan(41);
testDiag("Tests for changeBitSet and overrunBitSet");
test();
return testDone();
}