<commit_before>/*
 * KeyListOpsMethods.cpp
 *
 *  Created on: Feb 6, 2014
 *      Author: nek3d
 */

#include "KeyListOpsMethods.h"
#include <cmath>
#include <algorithm>
#include <limits.h>
#include "ParseTools.h" //to get the isNumeric function

KeyListOpsMethods::KeyListOpsMethods()
: _keyList(&_nullKeyList),
  _column(1),
  _nullVal("."),
  _delimStr(","),
  _iter(_nullKeyList.begin()),
  _nonNumErrFlag(false),
  _isBam(false)
{
}

KeyListOpsMethods::KeyListOpsMethods(RecordKeyVector *keyList, int column)
: _keyList(keyList),
  _column(column),
  _nullVal("."),
  _delimStr(","),
  _iter(keyList->begin())
{
}

KeyListOpsMethods::~KeyListOpsMethods() {

}

// return the total of the values in the vector
double KeyListOpsMethods::getSum() {
	if (empty()) return NAN;

	double theSum = 0.0;
	for (begin(); !end(); next()) {
		theSum += getColValNum();
	}
	return theSum;
}

// return the average value in the vector
double KeyListOpsMethods::getMean() {
	if (empty()) return NAN;

	return getSum() / (float)getCount();
}

 // return the standard deviation
double KeyListOpsMethods::getStddev() {
	if (empty()) return NAN;

	double avg = getMean();
	double squareDiffSum = 0.0;
	for (begin(); !end(); next()) {
		double val = getColValNum();
		double diff = val - avg;
		squareDiffSum += diff * diff;
	}
	return sqrt(squareDiffSum / (float)getCount());
}
// return the standard deviation
double KeyListOpsMethods::getSampleStddev() {
	if (empty()) return NAN;

	double avg = getMean();
	double squareDiffSum = 0.0;
	for (begin(); !end(); next()) {
		double val = getColValNum();
		double diff = val - avg;
		squareDiffSum += diff * diff;
	}
	return sqrt(squareDiffSum / ((float)getCount() - 1.0));
}

// return the median value in the vector
double KeyListOpsMethods::getMedian() {
	if (empty()) return NAN;

	//get sorted vector. if even number of elems, return middle val.
	//if odd, average of two.
	toArray(true, ASC);
	size_t count = getCount();
	if (count % 2) {
		//odd number of elements. Take middle one.
		return _numArray[count/2];
	} else {
		//even numnber of elements. Take average of middle 2.
		double sum = _numArray[count/2 -1] + _numArray[count/2];
		return sum / 2.0;
	}
}

// return the most common value in the vector
const string &KeyListOpsMethods::getMode() {
	if (empty()) return _nullVal;

	makeFreqMap();

	//now pass through the freq map and keep track of which key has the highest occurance.
	freqMapType::iterator maxIter = _freqMap.begin();
	int maxVal = 0;
	for (; _freqIter != _freqMap.end(); _freqIter++) {
		if (_freqIter->second > maxVal) {
			maxIter = _freqIter;
			maxVal = _freqIter->second;
		}
	}
	_retStr = maxIter->first;
	return _retStr;
}
// return the least common value in the vector
const string &KeyListOpsMethods::getAntiMode() {
	if (empty()) return _nullVal;

	makeFreqMap();

	//now pass through the freq map and keep track of which key has the highest occurance.
	freqMapType::iterator minIter = _freqMap.begin();
	int minVal = INT_MAX;
	for (; _freqIter != _freqMap.end(); _freqIter++) {
		if (_freqIter->second < minVal) {
			minIter = _freqIter;
			minVal = _freqIter->second;
		}
	}
	_retStr =  minIter->first;
	return _retStr;
}
// return the minimum element of the vector
double KeyListOpsMethods::getMin() {
	if (empty()) return NAN;

	begin();
	double minVal = getColValNum();
	for (; !end(); next()) {
		double currVal = getColValNum();
		minVal = (currVal < minVal) ? currVal : minVal;
	}
	return  minVal;
}

// return the maximum element of the vector
double KeyListOpsMethods::getMax() {
	if (empty()) return NAN;

	begin();
	double maxVal = getColValNum();
	for (; !end(); next()) {
		double currVal = getColValNum();
		maxVal = (currVal > maxVal) ? currVal : maxVal;
	}
	return maxVal;
}

// return the minimum absolute value of the vector
double KeyListOpsMethods::getAbsMin() {
	if (empty()) return NAN;

	begin();
	double minVal = abs(getColValNum());
	for (; !end(); next()) {
		double currVal = abs(getColValNum());
		minVal = (currVal < minVal) ? currVal : minVal;
	}
	return minVal;
}
// return the maximum absolute value of the vector
double KeyListOpsMethods::getAbsMax() {
	if (empty()) return NAN;

	begin();
	double maxVal = abs(getColValNum());
	for (; !end(); next()) {
		double currVal = abs(getColValNum());
		maxVal = (currVal > maxVal) ? currVal : maxVal;
	}
	return maxVal;
}
// return the count of element in the vector
uint32_t KeyListOpsMethods::getCount() {
	return _keyList->size();
}
// return a delimited list of the unique elements
const string &KeyListOpsMethods::getDistinct() {
	if (empty()) return _nullVal;
	// separated list of unique values. If something repeats, only report once.
	makeFreqMap();
	_retStr.clear();
	for (; _freqIter != _freqMap.end(); _freqIter++) {
		if (_freqIter != _freqMap.begin()) _retStr += _delimStr;
		_retStr.append(_freqIter->first);
	}
	return _retStr;
}

const string &KeyListOpsMethods::getDistinctOnly() {
	if (empty()) return _nullVal;
	// separated list of unique values. If something repeats, don't report.
	makeFreqMap();
	_retStr.clear();
	for (; _freqIter != _freqMap.end(); _freqIter++) {
		if (_freqIter->second > 1) continue;
		if (_freqIter != _freqMap.begin()) _retStr += _delimStr;
		_retStr.append(_freqIter->first);
	}
	return _retStr;
}

const string &KeyListOpsMethods::getDistinctSortNum(bool asc) {
	toArray(true, asc ? ASC : DESC);
	vector<double>::iterator endIter = std::unique(_numArray.begin(), _numArray.end());

	_retStr.clear();
	ostringstream s;
	for (vector<double>::iterator iter = _numArray.begin(); iter != endIter; iter++) {
		if (iter != _numArray.begin()) _retStr += _delimStr;
		s << *iter;
	}
	_retStr.append(s.str());
	return  _retStr;

}

// return a the count of _unique_ elements in the vector
uint32_t KeyListOpsMethods::getCountDistinct() {
	if (empty()) return 0;

	makeFreqMap();
	return _freqMap.size();
}

// return a delimiter-separated list of elements
const string &KeyListOpsMethods::getCollapse(const string &delimiter) {
	if (empty()) return _nullVal;

	//just put all items in one big separated list.
	_retStr.clear();
	int i=0;
	for (begin(); !end(); next()) {
		if (i > 0) _retStr += _delimStr;
		_retStr.append(getColVal());
		i++;
	}
	return _retStr;
}

// return a concatenation of all elements in the vector
const string &KeyListOpsMethods::getConcat() {
	if (empty()) return _nullVal;

	//like collapse but w/o commas. Just a true concat of all vals.
	//just swap out the delimChar with '' and call collapse, then
	//restore the delimChar.
	string oldDelimStr(_delimStr);
	_delimStr = "";
	getCollapse(); //this will store it's results in the _retStr method.
	_delimStr = oldDelimStr;
	return _retStr;
}

// return a histogram of values and their freqs. in desc. order of frequency
const string &KeyListOpsMethods::getFreqDesc() {
	if (empty()) return _nullVal;

	//for each uniq val, report # occurances, in desc order.
	makeFreqMap();
	//put freq map into multimap where key is the freq and val is the item. In other words, basically a reverse freq map.
	histDescType hist;
	for (; _freqIter != _freqMap.end(); _freqIter++) {
		hist.insert(pair<int, string>(_freqIter->second, _freqIter->first));
	}
	//now iterate through the reverse map we just made and output it's pairs in val:key format.
	_retStr.clear();
	ostringstream s;
	for (histDescType::iterator histIter = hist.begin(); histIter != hist.end(); histIter++) {
		if (histIter != hist.begin()) _retStr += _delimStr;
		s << histIter->second;
		s << ":";
		s << histIter->first;
	}
	_retStr.append(s.str());
	return _retStr;
}
// return a histogram of values and their freqs. in asc. order of frequency
const string &KeyListOpsMethods::getFreqAsc() {
	if (empty()) return _nullVal;

	//for each uniq val, report # occurances, in asc order.
	makeFreqMap();
	//put freq map into multimap where key is the freq and val is the item. In other words, basically a reverse freq map.
	histAscType hist;
	for (; _freqIter != _freqMap.end(); _freqIter++) {
		hist.insert(pair<int, string>(_freqIter->second, _freqIter->first));
//		hist[*(_freqIter->second)] = _freqIter->first;
	}
	//now iterate through the reverse map we just made and output it's pairs in val:key format.
	_retStr.clear();
	ostringstream s;
	for (histAscType::iterator histIter = hist.begin(); histIter != hist.end(); histIter++) {
		if (histIter != hist.begin()) _retStr += _delimStr;
		s << histIter->second;
		s << ":";
		s << histIter->first;
	}
	_retStr.append(s.str());
	return _retStr;
}
// return the first value in the list
const string &KeyListOpsMethods::getFirst() {
	if (empty()) return _nullVal;

	//just the first item.
	begin();
	return getColVal();
}
// return the last value in the list
const string &KeyListOpsMethods::getLast() {
	if (empty()) return _nullVal;

	//just the last item.
	begin();
	for (size_t i = 0; i < getCount() -1; i++) {
		next();
	}
	return getColVal();
}

const string &KeyListOpsMethods::getColVal() {
	const string &retVal = (*_iter)->getField(_column);
	if (_isBam && retVal.empty()) return _nullVal;
	return retVal;
}

double KeyListOpsMethods::getColValNum() {
	const string &strVal = (*_iter)->getField(_column);
	if (!isNumeric(strVal)) {
		_nonNumErrFlag = true;
		ostringstream s;
		_errMsg = " ***** WARNING: Non numeric value ";
		s << strVal;
		s << " in ";
		s << _column;
		s << ".";
		_errMsg.append(s.str());
		return NAN;
	}
	return atof(strVal.c_str());
}

void KeyListOpsMethods::toArray(bool useNum, SORT_TYPE sortVal) {

	//TBD: optimize performance with better memory management.
	if (useNum) {
		_numArray.resize(_keyList->size());
		int i=0;
		for (begin(); !end(); next()) {
			_numArray[i] = getColValNum();
			i++;
		}
	} else {
		_qsArray.resize(_keyList->size());
		int i=0;
		for (begin(); !end(); next()) {
			_qsArray[i] = getColVal();
			i++;
		}
	}
	if (sortVal != UNSORTED) {
		sortArray(useNum, sortVal == ASC);
	}
}

void KeyListOpsMethods::sortArray(bool useNum, bool ascOrder)
{
	if (useNum) {
		if (ascOrder) {
			sort(_numArray.begin(), _numArray.end(), less<double>());
		} else {
			sort(_numArray.begin(), _numArray.end(), greater<double>());
		}
	} else {
		if (ascOrder) {
			sort(_qsArray.begin(), _qsArray.end(), less<string>());
		} else {
			sort(_qsArray.begin(), _qsArray.end(), greater<string>());
		}
	}
}

void KeyListOpsMethods::makeFreqMap() {
	_freqMap.clear();

	//make a map of values to their number of times occuring.
	for (begin(); !end(); next()) {
		_freqMap[getColVal()]++;
	}
	_freqIter = _freqMap.begin();
}
<commit_msg>fix for issue #425<commit_after>/*
 * KeyListOpsMethods.cpp
 *
 *  Created on: Feb 6, 2014
 *      Author: nek3d
 */

#include "KeyListOpsMethods.h"
#include <cmath>
#include <algorithm>
#include <limits.h>
#include "ParseTools.h" //to get the isNumeric function

KeyListOpsMethods::KeyListOpsMethods()
: _keyList(&_nullKeyList),
  _column(1),
  _nullVal("."),
  _delimStr(","),
  _iter(_nullKeyList.begin()),
  _nonNumErrFlag(false),
  _isBam(false)
{
}

KeyListOpsMethods::KeyListOpsMethods(RecordKeyVector *keyList, int column)
: _keyList(keyList),
  _column(column),
  _nullVal("."),
  _delimStr(","),
  _iter(keyList->begin())
{
}

KeyListOpsMethods::~KeyListOpsMethods() {

}

// return the total of the values in the vector
double KeyListOpsMethods::getSum() {
	if (empty()) return NAN;

	double theSum = 0.0;
	for (begin(); !end(); next()) {
		theSum += getColValNum();
	}
	return theSum;
}

// return the average value in the vector
double KeyListOpsMethods::getMean() {
	if (empty()) return NAN;

	return getSum() / (float)getCount();
}

 // return the standard deviation
double KeyListOpsMethods::getStddev() {
	if (empty()) return NAN;

	double avg = getMean();
	double squareDiffSum = 0.0;
	for (begin(); !end(); next()) {
		double val = getColValNum();
		double diff = val - avg;
		squareDiffSum += diff * diff;
	}
	return sqrt(squareDiffSum / (float)getCount());
}
// return the standard deviation
double KeyListOpsMethods::getSampleStddev() {
	if (empty()) return NAN;

	double avg = getMean();
	double squareDiffSum = 0.0;
	for (begin(); !end(); next()) {
		double val = getColValNum();
		double diff = val - avg;
		squareDiffSum += diff * diff;
	}
	return sqrt(squareDiffSum / ((float)getCount() - 1.0));
}

// return the median value in the vector
double KeyListOpsMethods::getMedian() {
	if (empty()) return NAN;

	//get sorted vector. if even number of elems, return middle val.
	//if odd, average of two.
	toArray(true, ASC);
	size_t count = getCount();
	if (count % 2) {
		//odd number of elements. Take middle one.
		return _numArray[count/2];
	} else {
		//even numnber of elements. Take average of middle 2.
		double sum = _numArray[count/2 -1] + _numArray[count/2];
		return sum / 2.0;
	}
}

// return the most common value in the vector
const string &KeyListOpsMethods::getMode() {
	if (empty()) return _nullVal;

	makeFreqMap();

	//now pass through the freq map and keep track of which key has the highest occurance.
	freqMapType::iterator maxIter = _freqMap.begin();
	int maxVal = 0;
	for (; _freqIter != _freqMap.end(); _freqIter++) {
		if (_freqIter->second > maxVal) {
			maxIter = _freqIter;
			maxVal = _freqIter->second;
		}
	}
	_retStr = maxIter->first;
	return _retStr;
}
// return the least common value in the vector
const string &KeyListOpsMethods::getAntiMode() {
	if (empty()) return _nullVal;

	makeFreqMap();

	//now pass through the freq map and keep track of which key has the highest occurance.
	freqMapType::iterator minIter = _freqMap.begin();
	int minVal = INT_MAX;
	for (; _freqIter != _freqMap.end(); _freqIter++) {
		if (_freqIter->second < minVal) {
			minIter = _freqIter;
			minVal = _freqIter->second;
		}
	}
	_retStr =  minIter->first;
	return _retStr;
}
// return the minimum element of the vector
double KeyListOpsMethods::getMin() {
	if (empty()) return NAN;

	begin();
	double minVal = getColValNum();
	for (; !end(); next()) {
		double currVal = getColValNum();
		minVal = (currVal < minVal) ? currVal : minVal;
	}
	return  minVal;
}

// return the maximum element of the vector
double KeyListOpsMethods::getMax() {
	if (empty()) return NAN;

	begin();
	double maxVal = getColValNum();
	for (; !end(); next()) {
		double currVal = getColValNum();
		maxVal = (currVal > maxVal) ? currVal : maxVal;
	}
	return maxVal;
}

// return the minimum absolute value of the vector
double KeyListOpsMethods::getAbsMin() {
	if (empty()) return NAN;

	begin();
	double minVal = abs(getColValNum());
	for (; !end(); next()) {
		double currVal = abs(getColValNum());
		minVal = (currVal < minVal) ? currVal : minVal;
	}
	return minVal;
}
// return the maximum absolute value of the vector
double KeyListOpsMethods::getAbsMax() {
	if (empty()) return NAN;

	begin();
	double maxVal = abs(getColValNum());
	for (; !end(); next()) {
		double currVal = abs(getColValNum());
		maxVal = (currVal > maxVal) ? currVal : maxVal;
	}
	return maxVal;
}
// return the count of element in the vector
uint32_t KeyListOpsMethods::getCount() {
	return _keyList->size();
}
// return a delimited list of the unique elements
const string &KeyListOpsMethods::getDistinct() {
	if (empty()) return _nullVal;
	// separated list of unique values. If something repeats, only report once.
	makeFreqMap();
	_retStr.clear();
	for (; _freqIter != _freqMap.end(); _freqIter++) {
		if (_freqIter != _freqMap.begin()) _retStr += _delimStr;
		_retStr.append(_freqIter->first);
	}
	return _retStr;
}

const string &KeyListOpsMethods::getDistinctOnly() {
	if (empty()) return _nullVal;
	// separated list of unique values. If something repeats, don't report.
	makeFreqMap();
	_retStr.clear();
	for (; _freqIter != _freqMap.end(); _freqIter++) {
		if (_freqIter->second > 1) continue;
		if (_freqIter != _freqMap.begin()) _retStr += _delimStr;
		_retStr.append(_freqIter->first);
	}
	return _retStr;
}

const string &KeyListOpsMethods::getDistinctSortNum(bool asc) {
	if (empty()) return _nullVal;

	toArray(true, asc ? ASC : DESC);
	vector<double>::iterator endIter = std::unique(_numArray.begin(), _numArray.end());

	_retStr.clear();
	ostringstream s;
	for (vector<double>::iterator iter = _numArray.begin(); iter != endIter; iter++) {
		if (iter != _numArray.begin()) _retStr += _delimStr;
		s << *iter;
	}
	_retStr.append(s.str());
	return  _retStr;

}

// return a the count of _unique_ elements in the vector
uint32_t KeyListOpsMethods::getCountDistinct() {
	if (empty()) return 0;

	makeFreqMap();
	return _freqMap.size();
}

// return a delimiter-separated list of elements
const string &KeyListOpsMethods::getCollapse(const string &delimiter) {
	if (empty()) return _nullVal;

	//just put all items in one big separated list.
	_retStr.clear();
	int i=0;
	for (begin(); !end(); next()) {
		if (i > 0) _retStr += _delimStr;
		_retStr.append(getColVal());
		i++;
	}
	return _retStr;
}

// return a concatenation of all elements in the vector
const string &KeyListOpsMethods::getConcat() {
	if (empty()) return _nullVal;

	//like collapse but w/o commas. Just a true concat of all vals.
	//just swap out the delimChar with '' and call collapse, then
	//restore the delimChar.
	string oldDelimStr(_delimStr);
	_delimStr = "";
	getCollapse(); //this will store it's results in the _retStr method.
	_delimStr = oldDelimStr;
	return _retStr;
}

// return a histogram of values and their freqs. in desc. order of frequency
const string &KeyListOpsMethods::getFreqDesc() {
	if (empty()) return _nullVal;

	//for each uniq val, report # occurances, in desc order.
	makeFreqMap();
	//put freq map into multimap where key is the freq and val is the item. In other words, basically a reverse freq map.
	histDescType hist;
	for (; _freqIter != _freqMap.end(); _freqIter++) {
		hist.insert(pair<int, string>(_freqIter->second, _freqIter->first));
	}
	//now iterate through the reverse map we just made and output it's pairs in val:key format.
	_retStr.clear();
	ostringstream s;
	for (histDescType::iterator histIter = hist.begin(); histIter != hist.end(); histIter++) {
		if (histIter != hist.begin()) _retStr += _delimStr;
		s << histIter->second;
		s << ":";
		s << histIter->first;
	}
	_retStr.append(s.str());
	return _retStr;
}
// return a histogram of values and their freqs. in asc. order of frequency
const string &KeyListOpsMethods::getFreqAsc() {
	if (empty()) return _nullVal;

	//for each uniq val, report # occurances, in asc order.
	makeFreqMap();
	//put freq map into multimap where key is the freq and val is the item. In other words, basically a reverse freq map.
	histAscType hist;
	for (; _freqIter != _freqMap.end(); _freqIter++) {
		hist.insert(pair<int, string>(_freqIter->second, _freqIter->first));
//		hist[*(_freqIter->second)] = _freqIter->first;
	}
	//now iterate through the reverse map we just made and output it's pairs in val:key format.
	_retStr.clear();
	ostringstream s;
	for (histAscType::iterator histIter = hist.begin(); histIter != hist.end(); histIter++) {
		if (histIter != hist.begin()) _retStr += _delimStr;
		s << histIter->second;
		s << ":";
		s << histIter->first;
	}
	_retStr.append(s.str());
	return _retStr;
}
// return the first value in the list
const string &KeyListOpsMethods::getFirst() {
	if (empty()) return _nullVal;

	//just the first item.
	begin();
	return getColVal();
}
// return the last value in the list
const string &KeyListOpsMethods::getLast() {
	if (empty()) return _nullVal;

	//just the last item.
	begin();
	for (size_t i = 0; i < getCount() -1; i++) {
		next();
	}
	return getColVal();
}

const string &KeyListOpsMethods::getColVal() {
	const string &retVal = (*_iter)->getField(_column);
	if (_isBam && retVal.empty()) return _nullVal;
	return retVal;
}

double KeyListOpsMethods::getColValNum() {
	const string &strVal = (*_iter)->getField(_column);
	if (!isNumeric(strVal)) {
		_nonNumErrFlag = true;
		ostringstream s;
		_errMsg = " ***** WARNING: Non numeric value ";
		s << strVal;
		s << " in ";
		s << _column;
		s << ".";
		_errMsg.append(s.str());
		return NAN;
	}
	return atof(strVal.c_str());
}

void KeyListOpsMethods::toArray(bool useNum, SORT_TYPE sortVal) {

	//TBD: optimize performance with better memory management.
	if (useNum) {
		_numArray.resize(_keyList->size());
		int i=0;
		for (begin(); !end(); next()) {
			_numArray[i] = getColValNum();
			i++;
		}
	} else {
		_qsArray.resize(_keyList->size());
		int i=0;
		for (begin(); !end(); next()) {
			_qsArray[i] = getColVal();
			i++;
		}
	}
	if (sortVal != UNSORTED) {
		sortArray(useNum, sortVal == ASC);
	}
}

void KeyListOpsMethods::sortArray(bool useNum, bool ascOrder)
{
	if (useNum) {
		if (ascOrder) {
			sort(_numArray.begin(), _numArray.end(), less<double>());
		} else {
			sort(_numArray.begin(), _numArray.end(), greater<double>());
		}
	} else {
		if (ascOrder) {
			sort(_qsArray.begin(), _qsArray.end(), less<string>());
		} else {
			sort(_qsArray.begin(), _qsArray.end(), greater<string>());
		}
	}
}

void KeyListOpsMethods::makeFreqMap() {
	_freqMap.clear();

	//make a map of values to their number of times occuring.
	for (begin(); !end(); next()) {
		_freqMap[getColVal()]++;
	}
	_freqIter = _freqMap.begin();
}
<|endoftext|>


<commit_before>#include <sirius.h>

void test_gemm(int M, int N, int K, mdarray<double_complex, 2>& c)
{
    sirius::Timer t("test_gemm");

    mdarray<double_complex, 2> a(M, K);
    mdarray<double_complex, 2> b(K, N);

    for (int j = 0; j < K; j++)
    {
        for (int i = 0; i < N; i++) a(i, j) = type_wrapper<double_complex>::random();
    }
    for (int j = 0; j < N; j++)
    {
        for (int i = 0; i < K; i++) b(i, j) = type_wrapper<double_complex>::random();
    }

    printf("testing zgemm with M, N, K = %i, %i, %i\n", M, N, K);
    sirius::Timer t1("gemm_only");
    blas<cpu>::gemm(0, 0, M, N, K, a.ptr(), a.ld(), b.ptr(), b.ld(), c.ptr(), c.ld());
    t1.stop();
    printf("execution time (sec) : %12.6f\n", t1.value());
    printf("performance (GFlops) : %12.6f\n", 8e-9 * M * N * K / t1.value());
}

int main(int argn, char **argv)
{
    if (argn != 4)
    {
        printf("Usage: %s M N K\n", argv[0]);
        exit(0);
    }
    int M, N, K;
    std::istringstream(argv[1]) >> M;
    std::istringstream(argv[2]) >> N;
    std::istringstream(argv[3]) >> K;

    bool init_cublas = (argn == 1) ? true : false;
    Platform::initialize(true, init_cublas);

    //== mdarray<double_complex, 2> a(2000, 2000);
    //== mdarray<double_complex, 2> b(2000, 2000);
    //== mdarray<double_complex, 2> c(2000, 2000);

    //== a.allocate_on_device();
    //== b.allocate_on_device();
    //== c.allocate_on_device();
    //==
    //== double_complex zone(1, 0);
    //== double_complex zzero(0, 0);

    //== sirius::Timer t("zgemm", false);
    //== t.start();
    //== for (int i = 0; i < 10; i++)
    //== {
    //==     blas<gpu>::gemm(0, 0, 2000, 2000, 2000, &zone, a.get_ptr_device(), a.ld(), b.get_ptr_device(), b.ld(),
    //==                     &zzero, c.get_ptr_device(), c.ld());
    //== }
    //== c.copy_to_host();
    //== std::cout << "after zgemm" << std::endl;
    //== t.stop();

    mdarray<double_complex, 2> c(M, N);
    for (int j = 0; j < N; j++)
    {
        for (int i = 0; i < M; i++) c(i, j) = complex_zero;
    }
    test_gemm(M, N, K, c);

    //sirius::Timer::print();

    Platform::finalize();
}
<commit_msg>update of test_zgemm.cpp<commit_after>#include <sirius.h>

void test_gemm(int M, int N, int K, mdarray<double_complex, 2>& c)
{
    sirius::Timer t("test_gemm");

    mdarray<double_complex, 2> a(M, K);
    mdarray<double_complex, 2> b(K, N);

    for (int j = 0; j < K; j++)
    {
        for (int i = 0; i < N; i++) a(i, j) = type_wrapper<double_complex>::random();
    }
    for (int j = 0; j < N; j++)
    {
        for (int i = 0; i < K; i++) b(i, j) = type_wrapper<double_complex>::random();
    }

    printf("testing serial zgemm with M, N, K = %i, %i, %i\n", M, N, K);
    sirius::Timer t1("gemm_only");
    blas<cpu>::gemm(0, 0, M, N, K, a.ptr(), a.ld(), b.ptr(), b.ld(), c.ptr(), c.ld());
    t1.stop();
    printf("execution time (sec) : %12.6f\n", t1.value());
    printf("performance (GFlops) : %12.6f\n", 8e-9 * M * N * K / t1.value());
}

#ifdef _SCALAPACK_
void test_pgemm(int M, int N, int K, int nrow, int ncol)
{
    int context = linalg<scalapack>::create_blacs_context(MPI_COMM_WORLD);
    Cblacs_gridinit(&context, "C", nrow, ncol);

    dmatrix<double_complex> a(M, K, context);
    dmatrix<double_complex> b(K, N, context);
    dmatrix<double_complex> c(M, N, context);
    c.zero();

    for (int ic = 0; ic < a.num_cols_local(); ic++)
    {
        for (int ir = 0; ir < a.num_rows_local(); ir++) a(ir, ic) = type_wrapper<double_complex>::random();
    }
    for (int ic = 0; ic < b.num_cols_local(); ic++)
    {
        for (int ir = 0; ir < b.num_rows_local(); ir++) b(ir, ic) = type_wrapper<double_complex>::random();
    }

    if (Platform::mpi_rank() == 0)
    {
        printf("testing serial zgemm with M, N, K = %i, %i, %i\n", M, N, K);
    }
    sirius::Timer t1("gemm_only");
    blas<cpu>::gemm(0, 0, M, N, K, complex_one, a, b, complex_zero, c);
    t1.stop();
    if (Platform::mpi_rank() == 0)
    {
        printf("execution time (sec) : %12.6f\n", t1.value());
        printf("performance (GFlops) : %12.6f\n", 8e-9 * M * N * K / t1.value() / nrow / ncol);
    }

    linalg<scalapack>::free_blacs_context(context);
}
#endif

int main(int argn, char **argv)
{
    cmd_args args;
    args.register_key("--M=", "{int} M");
    args.register_key("--N=", "{int} N");
    args.register_key("--K=", "{int} K");
    args.register_key("--nrow=", "{int} number of row MPI ranks");
    args.register_key("--ncol=", "{int} number of column MPI ranks");
    args.register_key("--bs=", "{int} cyclic block size");

    args.parse_args(argn, argv);
    if (argn == 1)
    {
        printf("Usage: %s [options]\n", argv[0]);
        args.print_help();
        exit(0);
    }

    int nrow = 1;
    int ncol = 1;

    if (args.exist("nrow")) nrow = args.value<int>("nrow");
    if (args.exist("ncol")) ncol = args.value<int>("ncol");

    int M = args.value<int>("M");
    int N = args.value<int>("N");
    int K = args.value<int>("K");

    Platform::initialize(true);

    if (nrow * ncol == 1)
    {
        mdarray<double_complex, 2> c(M, N);
        for (int j = 0; j < N; j++)
        {
            for (int i = 0; i < M; i++) c(i, j) = complex_zero;
        }
        test_gemm(M, N, K, c);
    }
    else
    {
        #ifdef _SCALAPACK_
        int bs = args.value<int>("bs");
        linalg<scalapack>::set_cyclic_block_size(bs);
        splindex<block_cyclic>::set_cyclic_block_size(bs);
        test_pgemm(M, N, K, nrow, ncol);
        #else
        terminate(__FILE__, __LINE__, "not compiled with ScaLAPACK support");
        #endif
    }

    Platform::finalize();
}
<|endoftext|>


<commit_before>/** \file    add_isbns_or_issns_to_articles.cc
 *  \brief   A tool for adding missing ISBN's (field 020$a) or ISSN's (field 773$x)to articles entries,
 *           in MARC-21 data.
 *  \author  Dr. Johannes Ruscheinski
 */

/*
    Copyright (C) 2015-2018, Library of the University of Tübingen

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as
    published by the Free Software Foundation, either version 3 of the
    License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <fstream>
#include <iostream>
#include <memory>
#include <unordered_map>
#include <cstdlib>
#include <cstring>
#include "MARC.h"
#include "MiscUtil.h"
#include "StringUtil.h"
#include "util.h"

namespace {

[[noreturn]] void Usage() {
    std::cerr << "Usage: " << progname << " master_marc_input marc_output\n";
    std::cerr << "  Adds host/parent/journal ISBNs and ISSNs to article entries found in the\n";
    std::cerr << "  master_marc_input and writes this augmented file as marc_output.  The ISBNs and ISSNs are\n";
    std::cerr << "  extracted from superior entries found in master_marc_input.\n";
    std::exit(EXIT_FAILURE);
}

void PopulateParentIdToISBNAndISSNMap(
    MARC::Reader * const marc_reader,
    std::unordered_map<std::string, std::string> * const parent_id_to_isbn_and_issn_map)
{
    LOG_INFO("Starting extraction of ISBN's and ISSN's.");

    unsigned count(0), extracted_isbn_count(0), extracted_issn_count(0);
    std::string err_msg;
    while (const MARC::Record record = marc_reader->read()) {
        ++count;

        if (not record.isSerial() and not record.isMonograph())
            continue;

        // Try to see if we have an ISBN:
        const auto field_020(record.findTag("020"));
        if (field_020 != record.end()) {
            const std::string isbn(field_020->getFirstSubfieldWithCode('a'));
            if (not isbn.empty()) {
                (*parent_id_to_isbn_and_issn_map)[record.getControlNumber()] = isbn;
                ++extracted_isbn_count;
                continue;
            }
        } else
            continue;

        std::string issn;
        // 1. First try to get an ISSN from 029$a, (according to the BSZ's PICA-to-MARC mapping
        // documentation this contains the "authorised" ISSN) but only if the indicators are correct:
        for (const auto &_029_field : record.getTagRange("029")) {
            const auto subfields(_029_field.getSubfields());

            // We only want fields with indicators 'x' and 'a':
            if (_029_field.getIndicator1() != 'x' or _029_field.getIndicator2() != 'a')
                continue;

            issn = subfields.getFirstSubfieldWithCode('a');
            if (not issn.empty()) {
                (*parent_id_to_isbn_and_issn_map)[record.getControlNumber()] = issn;
                ++extracted_issn_count;
            }
        }

        // 2. If we don't already have an ISSN check 022$a as a last resort:
        if (issn.empty()) {
            const auto field_022(record.findTag("022"));
            if (field_022 != record.end()) {
                issn = field_022->getFirstSubfieldWithCode('a');
                if (not issn.empty()) {
                    (*parent_id_to_isbn_and_issn_map)[record.getControlNumber()] = issn;
                    ++extracted_issn_count;
                }
            }
        }
    }

    if (not err_msg.empty())
        LOG_ERROR(err_msg);

    LOG_INFO("Read " + std::to_string(count) + " records.");
    LOG_INFO("Extracted " + std::to_string(extracted_isbn_count) + " ISBNs.");
    LOG_INFO("Extracted " + std::to_string(extracted_issn_count) + " ISSNs.");
}

void AddMissingISBNsOrISSNsToArticleEntries(MARC::Reader * const marc_reader,
                                            MARC::Writer * const marc_writer, const std::unordered_map<std::string,
                                            std::string> &parent_id_to_isbn_and_issn_map)
{
    LOG_INFO("Starting augmentation of article entries.");

    unsigned count(0), isbns_added(0), issns_added(0), missing_host_record_ctrl_num_count(0),
             missing_isbn_or_issn_count(0);
    while (MARC::Record record = marc_reader->read()) {
        ++count;

        if (not record.isArticle()) {
            marc_writer->write(record);
            continue;
        }

        const auto _773_field(record.findTag("773"));
        if (_773_field == record.end()) {
            marc_writer->write(record);
            continue;
        }

        auto subfields(_773_field->getSubfields());
        if (subfields.hasSubfield('x')) {
            marc_writer->write(record);
            continue;
        }

        if (not subfields.hasSubfield('w')) {       // Record control number of Host Item Entry.
            marc_writer->write(record);
            ++missing_host_record_ctrl_num_count;
            continue;
        }

        std::string host_id(subfields.getFirstSubfieldWithCode('w'));
        if (StringUtil::StartsWith(host_id, "(DE-576)"))
            host_id = host_id.substr(8);
        const auto &parent_isbn_or_issn_iter(parent_id_to_isbn_and_issn_map.find(host_id));
        if (parent_isbn_or_issn_iter == parent_id_to_isbn_and_issn_map.end()) {
            marc_writer->write(record);
            ++missing_isbn_or_issn_count;
            continue;
        }

        if (MiscUtil::IsPossibleISSN(parent_isbn_or_issn_iter->second)) {
            subfields.addSubfield('x', parent_isbn_or_issn_iter->second);
            _773_field->setContents(subfields, _773_field->getIndicator1(), _773_field->getIndicator2());
            ++issns_added;
        } else { // Deal with ISBNs.
            auto _020_field(record.findTag("020"));
            if (_020_field == record.end()) {
                record.insertField("020", { { 'a', parent_isbn_or_issn_iter->second } });
                ++isbns_added;
            } else if (_020_field->getFirstSubfieldWithCode('a').empty()) {
                _020_field->appendSubfield('a', parent_isbn_or_issn_iter->second);
                ++isbns_added;
            }
        }
        marc_writer->write(record);
    }

    if (verbose) {
        std::cout << ::progname << ": Read " << count << " records.\n";
        std::cout << ::progname << ": Added ISBN's to " << isbns_added << " article record(s).\n";
        std::cout << ::progname << ": Added ISSN's to " << issns_added << " article record(s).\n";
        std::cout << ::progname << ": " << missing_host_record_ctrl_num_count
                 << " articles had missing host record control number(s).\n";
        std::cout << ::progname << ": For " << missing_isbn_or_issn_count << " articles no host ISBN nor ISSN was found.\n";
    }
}

} // unnamed namespace

int Main(int argc, char **argv) {
    if (argc < 3)
        Usage();

    const std::string marc_input_filename(argv[1]);
    const std::string marc_output_filename(argv[2]);
    if (unlikely(marc_input_filename == marc_output_filename))
        LOG_ERROR("Master input file name equals output file name!");

    auto marc_reader(MARC::Reader::Factory(marc_input_filename));
    auto marc_writer(MARC::Writer::Factory(marc_output_filename));

    std::unordered_map<std::string, std::string> parent_id_to_isbn_and_issn_map;
    PopulateParentIdToISBNAndISSNMap(marc_reader.get(), &parent_id_to_isbn_and_issn_map);
    marc_reader->rewind();

    AddMissingISBNsOrISSNsToArticleEntries(marc_reader.get(), marc_writer.get(),
                                           parent_id_to_isbn_and_issn_map);

    return EXIT_SUCCESS;
}
<commit_msg>Fix compile error<commit_after>/** \file    add_isbns_or_issns_to_articles.cc
 *  \brief   A tool for adding missing ISBN's (field 020$a) or ISSN's (field 773$x)to articles entries,
 *           in MARC-21 data.
 *  \author  Dr. Johannes Ruscheinski
 */

/*
    Copyright (C) 2015-2018, Library of the University of Tübingen

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as
    published by the Free Software Foundation, either version 3 of the
    License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <fstream>
#include <iostream>
#include <memory>
#include <unordered_map>
#include <cstdlib>
#include <cstring>
#include "MARC.h"
#include "MiscUtil.h"
#include "StringUtil.h"
#include "util.h"

namespace {

[[noreturn]] void Usage() {
    std::cerr << "Usage: " << progname << " master_marc_input marc_output\n";
    std::cerr << "  Adds host/parent/journal ISBNs and ISSNs to article entries found in the\n";
    std::cerr << "  master_marc_input and writes this augmented file as marc_output.  The ISBNs and ISSNs are\n";
    std::cerr << "  extracted from superior entries found in master_marc_input.\n";
    std::exit(EXIT_FAILURE);
}

void PopulateParentIdToISBNAndISSNMap(
    MARC::Reader * const marc_reader,
    std::unordered_map<std::string, std::string> * const parent_id_to_isbn_and_issn_map)
{
    LOG_INFO("Starting extraction of ISBN's and ISSN's.");

    unsigned count(0), extracted_isbn_count(0), extracted_issn_count(0);
    std::string err_msg;
    while (const MARC::Record record = marc_reader->read()) {
        ++count;

        if (not record.isSerial() and not record.isMonograph())
            continue;

        // Try to see if we have an ISBN:
        const auto field_020(record.findTag("020"));
        if (field_020 != record.end()) {
            const std::string isbn(field_020->getFirstSubfieldWithCode('a'));
            if (not isbn.empty()) {
                (*parent_id_to_isbn_and_issn_map)[record.getControlNumber()] = isbn;
                ++extracted_isbn_count;
                continue;
            }
        } else
            continue;

        std::string issn;
        // 1. First try to get an ISSN from 029$a, (according to the BSZ's PICA-to-MARC mapping
        // documentation this contains the "authorised" ISSN) but only if the indicators are correct:
        for (const auto &_029_field : record.getTagRange("029")) {
            const auto subfields(_029_field.getSubfields());

            // We only want fields with indicators 'x' and 'a':
            if (_029_field.getIndicator1() != 'x' or _029_field.getIndicator2() != 'a')
                continue;

            issn = subfields.getFirstSubfieldWithCode('a');
            if (not issn.empty()) {
                (*parent_id_to_isbn_and_issn_map)[record.getControlNumber()] = issn;
                ++extracted_issn_count;
            }
        }

        // 2. If we don't already have an ISSN check 022$a as a last resort:
        if (issn.empty()) {
            const auto field_022(record.findTag("022"));
            if (field_022 != record.end()) {
                issn = field_022->getFirstSubfieldWithCode('a');
                if (not issn.empty()) {
                    (*parent_id_to_isbn_and_issn_map)[record.getControlNumber()] = issn;
                    ++extracted_issn_count;
                }
            }
        }
    }

    if (not err_msg.empty())
        LOG_ERROR(err_msg);

    LOG_INFO("Read " + std::to_string(count) + " records.");
    LOG_INFO("Extracted " + std::to_string(extracted_isbn_count) + " ISBNs.");
    LOG_INFO("Extracted " + std::to_string(extracted_issn_count) + " ISSNs.");
}

void AddMissingISBNsOrISSNsToArticleEntries(MARC::Reader * const marc_reader,
                                            MARC::Writer * const marc_writer, const std::unordered_map<std::string,
                                            std::string> &parent_id_to_isbn_and_issn_map)
{
    LOG_INFO("Starting augmentation of article entries.");

    unsigned count(0), isbns_added(0), issns_added(0), missing_host_record_ctrl_num_count(0),
             missing_isbn_or_issn_count(0);
    while (MARC::Record record = marc_reader->read()) {
        ++count;

        if (not record.isArticle()) {
            marc_writer->write(record);
            continue;
        }

        const auto _773_field(record.findTag("773"));
        if (_773_field == record.end()) {
            marc_writer->write(record);
            continue;
        }

        auto subfields(_773_field->getSubfields());
        if (subfields.hasSubfield('x')) {
            marc_writer->write(record);
            continue;
        }

        if (not subfields.hasSubfield('w')) {       // Record control number of Host Item Entry.
            marc_writer->write(record);
            ++missing_host_record_ctrl_num_count;
            continue;
        }

        std::string host_id(subfields.getFirstSubfieldWithCode('w'));
        if (StringUtil::StartsWith(host_id, "(DE-576)"))
            host_id = host_id.substr(8);
        const auto &parent_isbn_or_issn_iter(parent_id_to_isbn_and_issn_map.find(host_id));
        if (parent_isbn_or_issn_iter == parent_id_to_isbn_and_issn_map.end()) {
            marc_writer->write(record);
            ++missing_isbn_or_issn_count;
            continue;
        }

        if (MiscUtil::IsPossibleISSN(parent_isbn_or_issn_iter->second)) {
            subfields.addSubfield('x', parent_isbn_or_issn_iter->second);
            _773_field->setContents(subfields, _773_field->getIndicator1(), _773_field->getIndicator2());
            ++issns_added;
        } else { // Deal with ISBNs.
            auto _020_field(record.findTag("020"));
            if (_020_field == record.end()) {
                record.insertField("020", { { 'a', parent_isbn_or_issn_iter->second } });
                ++isbns_added;
            } else if (_020_field->getFirstSubfieldWithCode('a').empty()) {
                _020_field->appendSubfield('a', parent_isbn_or_issn_iter->second);
                ++isbns_added;
            }
        }
        marc_writer->write(record);
    }

    LOG_INFO("Read " + std::to_string(count) + " records.");
    LOG_INFO("Added ISBN's to " + std::to_string(isbns_added) + " article record(s).");
    LOG_INFO("Added ISSN's to " + std::to_string(issns_added) + " article record(s).");
    LOG_INFO(std::to_string(missing_host_record_ctrl_num_count) +
             " articles had missing host record control number(s).");
    LOG_INFO("For " + std::to_string(missing_isbn_or_issn_count) + " articles no host ISBN nor ISSN was found.");
}

} // unnamed namespace

int Main(int argc, char **argv) {
    if (argc < 3)
        Usage();

    const std::string marc_input_filename(argv[1]);
    const std::string marc_output_filename(argv[2]);
    if (unlikely(marc_input_filename == marc_output_filename))
        LOG_ERROR("Master input file name equals output file name!");

    auto marc_reader(MARC::Reader::Factory(marc_input_filename));
    auto marc_writer(MARC::Writer::Factory(marc_output_filename));

    std::unordered_map<std::string, std::string> parent_id_to_isbn_and_issn_map;
    PopulateParentIdToISBNAndISSNMap(marc_reader.get(), &parent_id_to_isbn_and_issn_map);
    marc_reader->rewind();

    AddMissingISBNsOrISSNsToArticleEntries(marc_reader.get(), marc_writer.get(),
                                           parent_id_to_isbn_and_issn_map);

    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2001,2004 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * $Id$
 */

// ---------------------------------------------------------------------------
//  Includes
// ---------------------------------------------------------------------------
#include <xercesc/util/XMLBigInteger.hpp>
#include <xercesc/util/XMLString.hpp>
#include <xercesc/util/NumberFormatException.hpp>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/util/TransService.hpp>
#include <xercesc/util/XMLUniDefs.hpp>
#include <xercesc/util/Janitor.hpp>
#include <xercesc/util/XMLChar.hpp>

XERCES_CPP_NAMESPACE_BEGIN

XMLCh* XMLBigInteger::getCanonicalRepresentation(const XMLCh*         const rawData
                                               ,       MemoryManager* const memMgr
                                               ,       bool                 isNonPositiveInteger)
{
    try
    {
        XMLCh* retBuf = (XMLCh*) memMgr->allocate( (XMLString::stringLen(rawData) + 2) * sizeof(XMLCh));
        ArrayJanitor<XMLCh> jan(retBuf, memMgr);
        int    sign = 0;

        XMLBigInteger::parseBigInteger(rawData, retBuf, sign);

        if (sign == 0)
        {
            if (isNonPositiveInteger)
            {
                retBuf[0] = chDash;
                retBuf[1] = chDigit_0;
                retBuf[2] = chNull;
            }
            else
            {
                retBuf[0] = chDigit_0;
                retBuf[1] = chNull;
            }
        }
        else if (sign == -1)
        {
            XMLCh* retBuffer = (XMLCh*) memMgr->allocate( (XMLString::stringLen(retBuf) + 2) * sizeof(XMLCh));
            retBuffer[0] = chDash;
            XMLString::copyString(&(retBuffer[1]), retBuf);
            return retBuffer;
        }

        jan.release();
        return retBuf;

    }
    catch (const NumberFormatException&)
    {
        return 0;
    }

}

/***
   *
   *  Leading and trailing whitespaces are allowed, and trimmed
   *
   *  Only one and either of (+,-) after the leading whitespace, before
   *  any other characters are allowed, and trimmed
   *
   *  Leading zero, after leading whitespace, (+|-), before any other
   *  characters are allowed, and trimmed
   *
   *  '.' NOT allowed

   *  return status: void
   *  ret_buf: w/o leading and/or trailing whitespace
   *           w/o '+' and '-'
   *           w/o leading zero
   *
   *  see XMLString::parseInt();
   *      XMLString::textToBin();
   *
   *  "    +000203456"            "203456"
   *  "    -000203456"            "203456"
   *
***/

void XMLBigInteger::parseBigInteger(const XMLCh* const toConvert
                                  , XMLCh* const retBuffer
                                  , int&   signValue
                                  , MemoryManager* const manager)
{
    // If no string, then its a failure
    if ((!toConvert) || (!*toConvert))
        ThrowXMLwithMemMgr(NumberFormatException, XMLExcepts::XMLNUM_emptyString, manager);

    //
    // Note: in Java's BigInteger, it seems any leading and/or trailing
    // whitespaces are not allowed. If this is the case, we may
    // need to skip the trimming below.
    //

    // Scan past any whitespace. If we hit the end, then return failure
    const XMLCh* startPtr = toConvert;
    while (XMLChar1_0::isWhitespace(*startPtr))
        startPtr++;

    if (!*startPtr)
        ThrowXMLwithMemMgr(NumberFormatException, XMLExcepts::XMLNUM_WSString, manager);

    // Start at the end and work back through any whitespace
    const XMLCh* endPtr = toConvert + XMLString::stringLen(toConvert);
    while (XMLChar1_0::isWhitespace(*(endPtr - 1)))
        endPtr--;

    //
    //  Work through what remains and convert each char to a digit.
    //  anything other than '
    //
    XMLCh* retPtr = retBuffer;
    signValue = 1;

    //
    // '+' or '-' is allowed only at the first position
    //
    if (*startPtr == chDash)
    {
        signValue = -1;
        startPtr++;
    }
    else if (*startPtr == chPlus)
    {
        // skip the '+'
        startPtr++;
    }

    // Scan past any leading zero.
    while (*startPtr == chDigit_0)
        startPtr++;

    if (startPtr >= endPtr)
    {
        signValue = 0;
        // containning zero, only zero, nothing but zero
        // it is a zero, indeed
        return;
    }

    while (startPtr < endPtr)
    {
        // If not valid decimal digit, then an error
        if ((*startPtr < chDigit_0) || (*startPtr > chDigit_9))
            ThrowXMLwithMemMgr(NumberFormatException, XMLExcepts::XMLNUM_Inv_chars, manager);

        // copy over
        *retPtr = *startPtr;
        retPtr++;
        startPtr++;
    }

    *retPtr = 0;   //terminated
    return;
}

/**
	 * Translates a string containing an optional minus sign followed by a
	 * sequence of one or more digits into a BigInteger.
	 * Any extraneous characters (including whitespace),
	 * inclusive, will result in a NumberFormatException.
 */

XMLBigInteger::XMLBigInteger(const XMLCh* const strValue,
                             MemoryManager* const manager)
: fSign(0)
, fMagnitude(0)
, fRawData(0)
, fMemoryManager(manager)
{
    if (!strValue)
        ThrowXMLwithMemMgr(NumberFormatException, XMLExcepts::XMLNUM_emptyString, fMemoryManager);

    XMLCh* ret_value = (XMLCh*) fMemoryManager->allocate
    (
       (XMLString::stringLen(strValue) + 1) * sizeof(XMLCh)
    );//new XMLCh[XMLString::stringLen(strValue)+1];
    ArrayJanitor<XMLCh> janName(ret_value, fMemoryManager);

    parseBigInteger(strValue, ret_value, fSign, fMemoryManager);

    if (fSign == 0)
        fMagnitude = XMLString::replicate(XMLUni::fgZeroLenString, fMemoryManager);
    else
        fMagnitude = XMLString::replicate(ret_value, fMemoryManager);

	fRawData = XMLString::replicate(strValue, fMemoryManager);
}

XMLBigInteger::~XMLBigInteger()
{
    fMemoryManager->deallocate(fMagnitude);//delete[] fMagnitude;
	if (fRawData)
		fMemoryManager->deallocate(fRawData);//delete[] fRawData;
}

XMLBigInteger::XMLBigInteger(const XMLBigInteger& toCopy)
: XMemory(toCopy)
, fSign(toCopy.fSign)
, fMagnitude(0)
, fRawData(0)
, fMemoryManager(toCopy.fMemoryManager)
{
    fMagnitude = XMLString::replicate(toCopy.fMagnitude, fMemoryManager);
	fRawData = XMLString::replicate(toCopy.fRawData, fMemoryManager);
}

/**
 * Returns -1, 0 or 1 as lValue is less than, equal to, or greater
 * than rValue.
*/
int  XMLBigInteger::compareValues(const XMLBigInteger* const lValue
                                , const XMLBigInteger* const rValue
                                , MemoryManager* const manager)
{
    if ((!lValue) || (!rValue) )
        ThrowXMLwithMemMgr(NumberFormatException, XMLExcepts::XMLNUM_null_ptr, manager);

    int lSign = lValue->getSign();
    int rSign = rValue->getSign();

    //
    // different sign
    //
    if (lSign != rSign)
        return(lSign > rSign ? 1 : -1);

    //
    // same sign
    //
    if (lSign == 0)    // optimization
        return 0;

    int lStrLen = XMLString::stringLen(lValue->fMagnitude);
    int rStrLen = XMLString::stringLen(rValue->fMagnitude);

    //
    // different length
    //
    if (lStrLen > rStrLen)
        return ( lSign > 0 ? 1 : -1 );
    else if (lStrLen < rStrLen)
        return ( lSign > 0 ? -1 : 1 );

    //
    // same length
    // XMLString::compareString() return > 0, 0 and <0
    // we need to convert it to 1, 0, and -1
    //
    int retVal = XMLString::compareString(lValue->fMagnitude, rValue->fMagnitude);

    if ( retVal > 0 )
    {
        return ( lSign > 0 ? 1 : -1 );
    }
    else if ( retVal < 0 )
    {
        return ( lSign > 0 ? -1 : 1 );
    }
    else
        return 0;

}

int XMLBigInteger::compareValues(const XMLCh*         const lString
                               , const int&                 lSign
                               , const XMLCh*         const rString
                               , const int&                 rSign
                               ,       MemoryManager* const manager)
{
    if ((!lString) || (!rString) )
        ThrowXMLwithMemMgr(NumberFormatException, XMLExcepts::XMLNUM_null_ptr, manager);

    //
    // different sign
    //
    if (lSign != rSign)
        return(lSign > rSign ? 1 : -1);

    //
    // same sign
    //
    if (lSign == 0)    // optimization
        return 0;

    int lStrLen = XMLString::stringLen(lString);
    int rStrLen = XMLString::stringLen(rString);

    //
    // different length
    //
    if (lStrLen > rStrLen)
        return ( lSign > 0 ? 1 : -1 );
    else if (lStrLen < rStrLen)
        return ( lSign > 0 ? -1 : 1 );

    //
    // same length
    // XMLString::compareString() return > 0, 0 and <0
    // we need to convert it to 1, 0, and -1
    //
    int retVal = XMLString::compareString(lString, rString);

    if ( retVal > 0 )
    {
        return ( lSign > 0 ? 1 : -1 );
    }
    else if ( retVal < 0 )
    {
        return ( lSign > 0 ? -1 : 1 );
    }
    else
        return 0;

}

/**
 * Shift the fMagnitude to the left
 */

void XMLBigInteger::multiply(const unsigned int byteToShift)
{
    if (byteToShift <= 0)
        return;

    int strLen = XMLString::stringLen(fMagnitude);
    XMLCh* tmp = (XMLCh*) fMemoryManager->allocate
    (
        (strLen + byteToShift + 1) * sizeof(XMLCh)
    );//new XMLCh[strLen+byteToShift+1];
    XMLString::moveChars(tmp, fMagnitude, strLen);

    unsigned int i = 0;
    for ( ; i < byteToShift; i++)
        tmp[strLen+i] = chDigit_0;

    tmp[strLen+i] = chNull;

    fMemoryManager->deallocate(fMagnitude);//delete[] fMagnitude;
    fMagnitude = tmp;
}

/**
 * Shift the fMagnitude to the right
 * by doing this, we lose precision.
 */
void XMLBigInteger::divide(const unsigned int byteToShift)
{
    if (byteToShift <= 0)
        return;

    int strLen = XMLString::stringLen(fMagnitude);
    XMLCh* tmp = (XMLCh*) fMemoryManager->allocate
    (
        (strLen - byteToShift + 1) * sizeof(XMLCh)
    );//new XMLCh[strLen-byteToShift+1];
    XMLString::moveChars(tmp, fMagnitude, strLen-byteToShift);

    tmp[strLen-byteToShift] = chNull;

    fMemoryManager->deallocate(fMagnitude);//delete[] fMagnitude;
    fMagnitude = tmp;
}

//
//
//
int XMLBigInteger::intValue() const
{
    unsigned int retVal;
    XMLString::textToBin(fMagnitude, retVal, fMemoryManager);
    return retVal * getSign();
}

XERCES_CPP_NAMESPACE_END
<commit_msg>Schema errata E2-27: don't have negative sign in front of zero.<commit_after>/*
 * Copyright 2001,2004 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * $Id$
 */

// ---------------------------------------------------------------------------
//  Includes
// ---------------------------------------------------------------------------
#include <xercesc/util/XMLBigInteger.hpp>
#include <xercesc/util/XMLString.hpp>
#include <xercesc/util/NumberFormatException.hpp>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/util/TransService.hpp>
#include <xercesc/util/XMLUniDefs.hpp>
#include <xercesc/util/Janitor.hpp>
#include <xercesc/util/XMLChar.hpp>

XERCES_CPP_NAMESPACE_BEGIN

XMLCh* XMLBigInteger::getCanonicalRepresentation(const XMLCh*         const rawData
                                               ,       MemoryManager* const memMgr
                                               ,       bool           /*      isNonPositiveInteger */)
{
    try
    {
        XMLCh* retBuf = (XMLCh*) memMgr->allocate( (XMLString::stringLen(rawData) + 2) * sizeof(XMLCh));
        ArrayJanitor<XMLCh> jan(retBuf, memMgr);
        int    sign = 0;

        XMLBigInteger::parseBigInteger(rawData, retBuf, sign);

        if (sign == 0)
        {
           retBuf[0] = chDigit_0;
           retBuf[1] = chNull;
        }
        else if (sign == -1)
        {
            XMLCh* retBuffer = (XMLCh*) memMgr->allocate( (XMLString::stringLen(retBuf) + 2) * sizeof(XMLCh));
            retBuffer[0] = chDash;
            XMLString::copyString(&(retBuffer[1]), retBuf);
            return retBuffer;
        }

        jan.release();
        return retBuf;

    }
    catch (const NumberFormatException&)
    {
        return 0;
    }

}

/***
   *
   *  Leading and trailing whitespaces are allowed, and trimmed
   *
   *  Only one and either of (+,-) after the leading whitespace, before
   *  any other characters are allowed, and trimmed
   *
   *  Leading zero, after leading whitespace, (+|-), before any other
   *  characters are allowed, and trimmed
   *
   *  '.' NOT allowed

   *  return status: void
   *  ret_buf: w/o leading and/or trailing whitespace
   *           w/o '+' and '-'
   *           w/o leading zero
   *
   *  see XMLString::parseInt();
   *      XMLString::textToBin();
   *
   *  "    +000203456"            "203456"
   *  "    -000203456"            "203456"
   *
***/

void XMLBigInteger::parseBigInteger(const XMLCh* const toConvert
                                  , XMLCh* const retBuffer
                                  , int&   signValue
                                  , MemoryManager* const manager)
{
    // If no string, then its a failure
    if ((!toConvert) || (!*toConvert))
        ThrowXMLwithMemMgr(NumberFormatException, XMLExcepts::XMLNUM_emptyString, manager);

    //
    // Note: in Java's BigInteger, it seems any leading and/or trailing
    // whitespaces are not allowed. If this is the case, we may
    // need to skip the trimming below.
    //

    // Scan past any whitespace. If we hit the end, then return failure
    const XMLCh* startPtr = toConvert;
    while (XMLChar1_0::isWhitespace(*startPtr))
        startPtr++;

    if (!*startPtr)
        ThrowXMLwithMemMgr(NumberFormatException, XMLExcepts::XMLNUM_WSString, manager);

    // Start at the end and work back through any whitespace
    const XMLCh* endPtr = toConvert + XMLString::stringLen(toConvert);
    while (XMLChar1_0::isWhitespace(*(endPtr - 1)))
        endPtr--;

    //
    //  Work through what remains and convert each char to a digit.
    //  anything other than '
    //
    XMLCh* retPtr = retBuffer;
    signValue = 1;

    //
    // '+' or '-' is allowed only at the first position
    //
    if (*startPtr == chDash)
    {
        signValue = -1;
        startPtr++;
    }
    else if (*startPtr == chPlus)
    {
        // skip the '+'
        startPtr++;
    }

    // Scan past any leading zero.
    while (*startPtr == chDigit_0)
        startPtr++;

    if (startPtr >= endPtr)
    {
        signValue = 0;
        // containning zero, only zero, nothing but zero
        // it is a zero, indeed
        return;
    }

    while (startPtr < endPtr)
    {
        // If not valid decimal digit, then an error
        if ((*startPtr < chDigit_0) || (*startPtr > chDigit_9))
            ThrowXMLwithMemMgr(NumberFormatException, XMLExcepts::XMLNUM_Inv_chars, manager);

        // copy over
        *retPtr = *startPtr;
        retPtr++;
        startPtr++;
    }

    *retPtr = 0;   //terminated
    return;
}

/**
	 * Translates a string containing an optional minus sign followed by a
	 * sequence of one or more digits into a BigInteger.
	 * Any extraneous characters (including whitespace),
	 * inclusive, will result in a NumberFormatException.
 */

XMLBigInteger::XMLBigInteger(const XMLCh* const strValue,
                             MemoryManager* const manager)
: fSign(0)
, fMagnitude(0)
, fRawData(0)
, fMemoryManager(manager)
{
    if (!strValue)
        ThrowXMLwithMemMgr(NumberFormatException, XMLExcepts::XMLNUM_emptyString, fMemoryManager);

    XMLCh* ret_value = (XMLCh*) fMemoryManager->allocate
    (
       (XMLString::stringLen(strValue) + 1) * sizeof(XMLCh)
    );//new XMLCh[XMLString::stringLen(strValue)+1];
    ArrayJanitor<XMLCh> janName(ret_value, fMemoryManager);

    parseBigInteger(strValue, ret_value, fSign, fMemoryManager);

    if (fSign == 0)
        fMagnitude = XMLString::replicate(XMLUni::fgZeroLenString, fMemoryManager);
    else
        fMagnitude = XMLString::replicate(ret_value, fMemoryManager);

	fRawData = XMLString::replicate(strValue, fMemoryManager);
}

XMLBigInteger::~XMLBigInteger()
{
    fMemoryManager->deallocate(fMagnitude);//delete[] fMagnitude;
	if (fRawData)
		fMemoryManager->deallocate(fRawData);//delete[] fRawData;
}

XMLBigInteger::XMLBigInteger(const XMLBigInteger& toCopy)
: XMemory(toCopy)
, fSign(toCopy.fSign)
, fMagnitude(0)
, fRawData(0)
, fMemoryManager(toCopy.fMemoryManager)
{
    fMagnitude = XMLString::replicate(toCopy.fMagnitude, fMemoryManager);
	fRawData = XMLString::replicate(toCopy.fRawData, fMemoryManager);
}

/**
 * Returns -1, 0 or 1 as lValue is less than, equal to, or greater
 * than rValue.
*/
int  XMLBigInteger::compareValues(const XMLBigInteger* const lValue
                                , const XMLBigInteger* const rValue
                                , MemoryManager* const manager)
{
    if ((!lValue) || (!rValue) )
        ThrowXMLwithMemMgr(NumberFormatException, XMLExcepts::XMLNUM_null_ptr, manager);

    int lSign = lValue->getSign();
    int rSign = rValue->getSign();

    //
    // different sign
    //
    if (lSign != rSign)
        return(lSign > rSign ? 1 : -1);

    //
    // same sign
    //
    if (lSign == 0)    // optimization
        return 0;

    int lStrLen = XMLString::stringLen(lValue->fMagnitude);
    int rStrLen = XMLString::stringLen(rValue->fMagnitude);

    //
    // different length
    //
    if (lStrLen > rStrLen)
        return ( lSign > 0 ? 1 : -1 );
    else if (lStrLen < rStrLen)
        return ( lSign > 0 ? -1 : 1 );

    //
    // same length
    // XMLString::compareString() return > 0, 0 and <0
    // we need to convert it to 1, 0, and -1
    //
    int retVal = XMLString::compareString(lValue->fMagnitude, rValue->fMagnitude);

    if ( retVal > 0 )
    {
        return ( lSign > 0 ? 1 : -1 );
    }
    else if ( retVal < 0 )
    {
        return ( lSign > 0 ? -1 : 1 );
    }
    else
        return 0;

}

int XMLBigInteger::compareValues(const XMLCh*         const lString
                               , const int&                 lSign
                               , const XMLCh*         const rString
                               , const int&                 rSign
                               ,       MemoryManager* const manager)
{
    if ((!lString) || (!rString) )
        ThrowXMLwithMemMgr(NumberFormatException, XMLExcepts::XMLNUM_null_ptr, manager);

    //
    // different sign
    //
    if (lSign != rSign)
        return(lSign > rSign ? 1 : -1);

    //
    // same sign
    //
    if (lSign == 0)    // optimization
        return 0;

    int lStrLen = XMLString::stringLen(lString);
    int rStrLen = XMLString::stringLen(rString);

    //
    // different length
    //
    if (lStrLen > rStrLen)
        return ( lSign > 0 ? 1 : -1 );
    else if (lStrLen < rStrLen)
        return ( lSign > 0 ? -1 : 1 );

    //
    // same length
    // XMLString::compareString() return > 0, 0 and <0
    // we need to convert it to 1, 0, and -1
    //
    int retVal = XMLString::compareString(lString, rString);

    if ( retVal > 0 )
    {
        return ( lSign > 0 ? 1 : -1 );
    }
    else if ( retVal < 0 )
    {
        return ( lSign > 0 ? -1 : 1 );
    }
    else
        return 0;

}

/**
 * Shift the fMagnitude to the left
 */

void XMLBigInteger::multiply(const unsigned int byteToShift)
{
    if (byteToShift <= 0)
        return;

    int strLen = XMLString::stringLen(fMagnitude);
    XMLCh* tmp = (XMLCh*) fMemoryManager->allocate
    (
        (strLen + byteToShift + 1) * sizeof(XMLCh)
    );//new XMLCh[strLen+byteToShift+1];
    XMLString::moveChars(tmp, fMagnitude, strLen);

    unsigned int i = 0;
    for ( ; i < byteToShift; i++)
        tmp[strLen+i] = chDigit_0;

    tmp[strLen+i] = chNull;

    fMemoryManager->deallocate(fMagnitude);//delete[] fMagnitude;
    fMagnitude = tmp;
}

/**
 * Shift the fMagnitude to the right
 * by doing this, we lose precision.
 */
void XMLBigInteger::divide(const unsigned int byteToShift)
{
    if (byteToShift <= 0)
        return;

    int strLen = XMLString::stringLen(fMagnitude);
    XMLCh* tmp = (XMLCh*) fMemoryManager->allocate
    (
        (strLen - byteToShift + 1) * sizeof(XMLCh)
    );//new XMLCh[strLen-byteToShift+1];
    XMLString::moveChars(tmp, fMagnitude, strLen-byteToShift);

    tmp[strLen-byteToShift] = chNull;

    fMemoryManager->deallocate(fMagnitude);//delete[] fMagnitude;
    fMagnitude = tmp;
}

//
//
//
int XMLBigInteger::intValue() const
{
    unsigned int retVal;
    XMLString::textToBin(fMagnitude, retVal, fMemoryManager);
    return retVal * getSign();
}

XERCES_CPP_NAMESPACE_END
<|endoftext|>


<commit_before>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2006-2010 Benoit Jacob <jacob.benoit.1@gmail.com>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// Alternatively, you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.

#include "main.h"

template<typename VectorType> void map_class_vector(const VectorType& m)
{
  typedef typename VectorType::Scalar Scalar;

  int size = m.size();

  // test Map.h
  Scalar* array1 = ei_aligned_new<Scalar>(size);
  Scalar* array2 = ei_aligned_new<Scalar>(size);
  Scalar* array3 = new Scalar[size+1];
  Scalar* array3unaligned = size_t(array3)%16 == 0 ? array3+1 : array3;

  Map<VectorType, Aligned>(array1, size) = VectorType::Random(size);
  Map<VectorType, Aligned>(array2, size) = Map<VectorType,Aligned>(array1, size);
  Map<VectorType>(array3unaligned, size) = Map<VectorType>(array1, size);
  VectorType ma1 = Map<VectorType, Aligned>(array1, size);
  VectorType ma2 = Map<VectorType, Aligned>(array2, size);
  VectorType ma3 = Map<VectorType>(array3unaligned, size);
  VERIFY_IS_EQUAL(ma1, ma2);
  VERIFY_IS_EQUAL(ma1, ma3);
  VERIFY_RAISES_ASSERT((Map<VectorType,Aligned>(array3unaligned, size)));

  ei_aligned_delete(array1, size);
  ei_aligned_delete(array2, size);
  delete[] array3;
}

template<typename MatrixType> void map_class_matrix(const MatrixType& m)
{
  typedef typename MatrixType::Scalar Scalar;

  int rows = m.rows(), cols = m.cols(), size = rows*cols;

  // test Map.h
  Scalar* array1 = ei_aligned_new<Scalar>(size);
  for(int i = 0; i < size; i++) array1[i] = Scalar(1);
  Scalar* array2 = ei_aligned_new<Scalar>(size);
  for(int i = 0; i < size; i++) array2[i] = Scalar(1);
  Scalar* array3 = new Scalar[size+1];
  for(int i = 0; i < size+1; i++) array3[i] = Scalar(1);
  Scalar* array3unaligned = size_t(array3)%16 == 0 ? array3+1 : array3;
  Map<MatrixType, Aligned>(array1, rows, cols) = MatrixType::Ones(rows,cols);
  Map<MatrixType>(array2, rows, cols) = Map<MatrixType>(array1, rows, cols);
  Map<MatrixType>(array3unaligned, rows, cols) = Map<MatrixType>(array1, rows, cols);
  MatrixType ma1 = Map<MatrixType>(array1, rows, cols);
  MatrixType ma2 = Map<MatrixType, Aligned>(array2, rows, cols);
  VERIFY_IS_EQUAL(ma1, ma2);
  MatrixType ma3 = Map<MatrixType>(array3unaligned, rows, cols);
  VERIFY_IS_EQUAL(ma1, ma3);

  ei_aligned_delete(array1, size);
  ei_aligned_delete(array2, size);
  delete[] array3;
}

template<typename VectorType> void map_static_methods(const VectorType& m)
{
  typedef typename VectorType::Scalar Scalar;

  int size = m.size();

  // test Map.h
  Scalar* array1 = ei_aligned_new<Scalar>(size);
  Scalar* array2 = ei_aligned_new<Scalar>(size);
  Scalar* array3 = new Scalar[size+1];
  Scalar* array3unaligned = size_t(array3)%16 == 0 ? array3+1 : array3;

  VectorType::MapAligned(array1, size) = VectorType::Random(size);
  VectorType::Map(array2, size) = VectorType::Map(array1, size);
  VectorType::Map(array3unaligned, size) = VectorType::Map(array1, size);
  VectorType ma1 = VectorType::Map(array1, size);
  VectorType ma2 = VectorType::MapAligned(array2, size);
  VectorType ma3 = VectorType::Map(array3unaligned, size);
  VERIFY_IS_EQUAL(ma1, ma2);
  VERIFY_IS_EQUAL(ma1, ma3);

  ei_aligned_delete(array1, size);
  ei_aligned_delete(array2, size);
  delete[] array3;
}

void test_map()
{
  for(int i = 0; i < g_repeat; i++) {
    CALL_SUBTEST_1( map_class_vector(Matrix<float, 1, 1>()) );
    CALL_SUBTEST_2( map_class_vector(Vector4d()) );
    CALL_SUBTEST_3( map_class_vector(RowVector4f()) );
    CALL_SUBTEST_4( map_class_vector(VectorXcf(8)) );
    CALL_SUBTEST_5( map_class_vector(VectorXi(12)) );

    CALL_SUBTEST_1( map_class_matrix(Matrix<float, 1, 1>()) );
    CALL_SUBTEST_2( map_class_matrix(Matrix4d()) );
    CALL_SUBTEST_11( map_class_matrix(Matrix<float,3,5>()) );
    CALL_SUBTEST_4( map_class_matrix(MatrixXcf(ei_random<int>(1,10),ei_random<int>(1,10))) );
    CALL_SUBTEST_5( map_class_matrix(MatrixXi(ei_random<int>(1,10),ei_random<int>(1,10))) );

    CALL_SUBTEST_6( map_static_methods(Matrix<double, 1, 1>()) );
    CALL_SUBTEST_7( map_static_methods(Vector3f()) );
    CALL_SUBTEST_8( map_static_methods(RowVector3d()) );
    CALL_SUBTEST_9( map_static_methods(VectorXcd(8)) );
    CALL_SUBTEST_10( map_static_methods(VectorXf(12)) );
  }
}
<commit_msg>fix another warning<commit_after>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2006-2010 Benoit Jacob <jacob.benoit.1@gmail.com>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// Alternatively, you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.

#include "main.h"

template<typename VectorType> void map_class_vector(const VectorType& m)
{
  typedef typename VectorType::Scalar Scalar;

  int size = m.size();

  // test Map.h
  Scalar* array1 = ei_aligned_new<Scalar>(size);
  Scalar* array2 = ei_aligned_new<Scalar>(size);
  Scalar* array3 = new Scalar[size+1];
  Scalar* array3unaligned = size_t(array3)%16 == 0 ? array3+1 : array3;

  Map<VectorType, Aligned>(array1, size) = VectorType::Random(size);
  Map<VectorType, Aligned>(array2, size) = Map<VectorType,Aligned>(array1, size);
  Map<VectorType>(array3unaligned, size) = Map<VectorType>(array1, size);
  VectorType ma1 = Map<VectorType, Aligned>(array1, size);
  VectorType ma2 = Map<VectorType, Aligned>(array2, size);
  VectorType ma3 = Map<VectorType>(array3unaligned, size);
  VERIFY_IS_EQUAL(ma1, ma2);
  VERIFY_IS_EQUAL(ma1, ma3);
  VERIFY_RAISES_ASSERT((Map<VectorType,Aligned>(array3unaligned, size)))

  ei_aligned_delete(array1, size);
  ei_aligned_delete(array2, size);
  delete[] array3;
}

template<typename MatrixType> void map_class_matrix(const MatrixType& m)
{
  typedef typename MatrixType::Scalar Scalar;

  int rows = m.rows(), cols = m.cols(), size = rows*cols;

  // test Map.h
  Scalar* array1 = ei_aligned_new<Scalar>(size);
  for(int i = 0; i < size; i++) array1[i] = Scalar(1);
  Scalar* array2 = ei_aligned_new<Scalar>(size);
  for(int i = 0; i < size; i++) array2[i] = Scalar(1);
  Scalar* array3 = new Scalar[size+1];
  for(int i = 0; i < size+1; i++) array3[i] = Scalar(1);
  Scalar* array3unaligned = size_t(array3)%16 == 0 ? array3+1 : array3;
  Map<MatrixType, Aligned>(array1, rows, cols) = MatrixType::Ones(rows,cols);
  Map<MatrixType>(array2, rows, cols) = Map<MatrixType>(array1, rows, cols);
  Map<MatrixType>(array3unaligned, rows, cols) = Map<MatrixType>(array1, rows, cols);
  MatrixType ma1 = Map<MatrixType>(array1, rows, cols);
  MatrixType ma2 = Map<MatrixType, Aligned>(array2, rows, cols);
  VERIFY_IS_EQUAL(ma1, ma2);
  MatrixType ma3 = Map<MatrixType>(array3unaligned, rows, cols);
  VERIFY_IS_EQUAL(ma1, ma3);

  ei_aligned_delete(array1, size);
  ei_aligned_delete(array2, size);
  delete[] array3;
}

template<typename VectorType> void map_static_methods(const VectorType& m)
{
  typedef typename VectorType::Scalar Scalar;

  int size = m.size();

  // test Map.h
  Scalar* array1 = ei_aligned_new<Scalar>(size);
  Scalar* array2 = ei_aligned_new<Scalar>(size);
  Scalar* array3 = new Scalar[size+1];
  Scalar* array3unaligned = size_t(array3)%16 == 0 ? array3+1 : array3;

  VectorType::MapAligned(array1, size) = VectorType::Random(size);
  VectorType::Map(array2, size) = VectorType::Map(array1, size);
  VectorType::Map(array3unaligned, size) = VectorType::Map(array1, size);
  VectorType ma1 = VectorType::Map(array1, size);
  VectorType ma2 = VectorType::MapAligned(array2, size);
  VectorType ma3 = VectorType::Map(array3unaligned, size);
  VERIFY_IS_EQUAL(ma1, ma2);
  VERIFY_IS_EQUAL(ma1, ma3);

  ei_aligned_delete(array1, size);
  ei_aligned_delete(array2, size);
  delete[] array3;
}

void test_map()
{
  for(int i = 0; i < g_repeat; i++) {
    CALL_SUBTEST_1( map_class_vector(Matrix<float, 1, 1>()) );
    CALL_SUBTEST_2( map_class_vector(Vector4d()) );
    CALL_SUBTEST_3( map_class_vector(RowVector4f()) );
    CALL_SUBTEST_4( map_class_vector(VectorXcf(8)) );
    CALL_SUBTEST_5( map_class_vector(VectorXi(12)) );

    CALL_SUBTEST_1( map_class_matrix(Matrix<float, 1, 1>()) );
    CALL_SUBTEST_2( map_class_matrix(Matrix4d()) );
    CALL_SUBTEST_11( map_class_matrix(Matrix<float,3,5>()) );
    CALL_SUBTEST_4( map_class_matrix(MatrixXcf(ei_random<int>(1,10),ei_random<int>(1,10))) );
    CALL_SUBTEST_5( map_class_matrix(MatrixXi(ei_random<int>(1,10),ei_random<int>(1,10))) );

    CALL_SUBTEST_6( map_static_methods(Matrix<double, 1, 1>()) );
    CALL_SUBTEST_7( map_static_methods(Vector3f()) );
    CALL_SUBTEST_8( map_static_methods(RowVector3d()) );
    CALL_SUBTEST_9( map_static_methods(VectorXcd(8)) );
    CALL_SUBTEST_10( map_static_methods(VectorXf(12)) );
  }
}
<|endoftext|>


<commit_before>#include <memory>
#include <string>
#include <vector>
#include <unordered_set>
#include <unordered_map>
#include <map>
#include <utility>
#include <iomanip>
#include <sstream>
#include <CoreServices/CoreServices.h>
#include <sys/stat.h>
#include <errno.h>

#include "../worker_platform.h"
#include "../worker_thread.h"
#include "recent_file_cache.h"
#include "event_handler.h"
#include "flags.h"
#include "../../log.h"
#include "../../message.h"
#include "../../message_buffer.h"
#include "../../result.h"

using std::vector;
using std::ostream;
using std::string;
using std::ostringstream;
using std::endl;
using std::unique_ptr;
using std::move;
using std::pair;
using std::make_pair;
using std::unordered_set;
using std::unordered_map;
using std::dec;
using std::hex;

static void command_perform_helper(void *info);

static void event_stream_helper(
  ConstFSEventStreamRef event_stream,
  void *info,
  size_t num_events,
  void *event_paths,
  const FSEventStreamEventFlags *event_flags,
  const FSEventStreamEventId *event_ids);

struct Subscription {
  WorkerPlatform *platform;
  ChannelID channel;
  FSEventStreamRef event_stream;

  Subscription(WorkerPlatform *platform, ChannelID channel) : platform{platform}, channel{channel}, event_stream{NULL}
  {
    //
  }
};

class MacOSWorkerPlatform : public WorkerPlatform {
public:
  MacOSWorkerPlatform(WorkerThread *thread) :
    WorkerPlatform(thread),
    run_loop{nullptr},
    command_source{nullptr}
  {
    //
  };

  ~MacOSWorkerPlatform() override
  {
    if (command_source) CFRelease(command_source);
    if (run_loop) CFRelease(run_loop);
  }

  Result<> wake() override
  {
    if (!is_healthy()) return health_err_result();

    CFRunLoopSourceSignal(command_source);
    CFRunLoopWakeUp(run_loop);

    return ok_result();
  }

  Result<> listen() override
  {
    if (!is_healthy()) return health_err_result();

    run_loop = CFRunLoopGetCurrent();
    CFRetain(run_loop);

    CFRunLoopSourceContext command_context = {
      0, // version
      this, // info
      NULL, // retain
      NULL, // release
      NULL, // copyDescription
      NULL, // equal
      NULL, // hash
      NULL, // schedule
      NULL, // cancel
      command_perform_helper // perform
    };
    command_source = CFRunLoopSourceCreate(kCFAllocatorDefault, 1, &command_context);
    CFRunLoopAddSource(run_loop, command_source, kCFRunLoopDefaultMode);

    CFRunLoopRun();
    return ok_result();
  }

  Result<bool> handle_add_command(
    const CommandID command,
    const ChannelID channel,
    const string &root_path) override
  {
    if (!is_healthy()) return health_err_result().propagate<bool>();
    LOGGER << "Adding watcher for path " << root_path << " at channel " << channel << "." << endl;

    Subscription *subscription = new Subscription(this, channel);

    FSEventStreamContext stream_context = {
      0, // version
      subscription, // info
      NULL, // retain
      NULL, // release
      NULL // copyDescription
    };

    CFStringRef watch_root = CFStringCreateWithBytes(
      kCFAllocatorDefault,
      reinterpret_cast<const UInt8*>(root_path.c_str()),
      root_path.size(),
      kCFStringEncodingUTF8,
      false
    );
    if (watch_root == NULL) {
      string msg("Unable to allocate string for root path: ");
      msg += root_path;
      return Result<bool>::make_error(move(msg));
    }

    CFArrayRef watch_roots = CFArrayCreate(
      kCFAllocatorDefault,
      reinterpret_cast<const void**>(&watch_root),
      1,
      NULL
    );
    if (watch_roots == NULL) {
      string msg("Unable to allocate array for watch root: ");
      msg += root_path;
      CFRelease(watch_root);

      return Result<bool>::make_error(move(msg));
    }

    FSEventStreamRef event_stream = FSEventStreamCreate(
      kCFAllocatorDefault,
      event_stream_helper,
      &stream_context,
      watch_roots,
      kFSEventStreamEventIdSinceNow,
      LATENCY,
      kFSEventStreamCreateFlagNoDefer | kFSEventStreamCreateFlagFileEvents
    );
    subscription->event_stream = event_stream;

    subscriptions.insert(make_pair(channel, subscription));

    FSEventStreamScheduleWithRunLoop(event_stream, run_loop, kCFRunLoopDefaultMode);
    if (!FSEventStreamStart(event_stream)) {
      string msg("Unable start event stream for watch root: ");
      msg += root_path;

      CFRelease(watch_roots);
      CFRelease(watch_root);
      return Result<bool>::make_error(move(msg));
    }

    CFRelease(watch_roots);
    CFRelease(watch_root);
    return ok_result(true);
  }

  Result<bool> handle_remove_command(
    const CommandID,
    const ChannelID channel) override
  {
    if (!is_healthy()) return health_err_result().propagate<bool>();
    LOGGER << "Removing watcher for channel " << channel << "." << endl;

    auto maybe_subscription = subscriptions.find(channel);
    if (maybe_subscription == subscriptions.end()) {
      LOGGER << "No subscription for channel " << channel << "." << endl;
      return ok_result(true);
    }

    Subscription *subscription = maybe_subscription->second;
    subscriptions.erase(maybe_subscription);

    FSEventStreamStop(subscription->event_stream);
    FSEventStreamInvalidate(subscription->event_stream);
    FSEventStreamRelease(subscription->event_stream);

    delete subscription;
    return ok_result(true);
  }

  void handle_fs_event(
    ChannelID channel_id,
    ConstFSEventStreamRef event_stream,
    size_t num_events,
    void *event_paths,
    const FSEventStreamEventFlags *event_flags,
    const FSEventStreamEventId *event_ids)
  {
    char **paths = reinterpret_cast<char**>(event_paths);
    MessageBuffer buffer;
    ChannelMessageBuffer message_buffer(buffer, channel_id);

    LOGGER << "Filesystem event batch of size " << num_events << " received." << endl;
    message_buffer.reserve(num_events);

    EventHandler handler(message_buffer, cache);
    for (size_t i = 0; i < num_events; i++) {
      string event_path(paths[i]);
      handler.handle(event_path, event_flags[i]);
    }
    handler.flush();

    Result<> er = emit_all(message_buffer.begin(), message_buffer.end());
    if (er.is_error()) {
      LOGGER << "Unable to emit ack messages: " << er << "." << endl;
      return;
    }

    LOGGER << "Filesystem event batch of size " << num_events << " completed. "
      << plural(message_buffer.size(), "message") << " produced." << endl;

    cache.prune();
  }

private:
  CFRunLoopRef run_loop;
  CFRunLoopSourceRef command_source;

  unordered_map<ChannelID, Subscription*> subscriptions;
  RecentFileCache cache;
};

static void command_perform_helper(void *info)
{
  MacOSWorkerPlatform *platform = reinterpret_cast<MacOSWorkerPlatform*>(info);
  Result<> r = platform->handle_commands();
  if (r.is_error()) {
    LOGGER << "Unable to handle incoming commands: " << r << "." << endl;
  }
}

static void event_stream_helper(
  ConstFSEventStreamRef event_stream,
  void *info,
  size_t num_events,
  void *event_paths,
  const FSEventStreamEventFlags *event_flags,
  const FSEventStreamEventId *event_ids)
{
  Subscription *sub = reinterpret_cast<Subscription*>(info);
  MacOSWorkerPlatform *platform = static_cast<MacOSWorkerPlatform*>(sub->platform);

  platform->handle_fs_event(sub->channel, event_stream, num_events, event_paths, event_flags, event_ids);
}

unique_ptr<WorkerPlatform> WorkerPlatform::for_worker(WorkerThread *thread)
{
  return unique_ptr<WorkerPlatform>(new MacOSWorkerPlatform(thread));
}
<commit_msg>Fall back to the polling thread<commit_after>#include <memory>
#include <string>
#include <vector>
#include <unordered_set>
#include <unordered_map>
#include <map>
#include <utility>
#include <iomanip>
#include <sstream>
#include <CoreServices/CoreServices.h>
#include <sys/stat.h>
#include <errno.h>

#include "../worker_platform.h"
#include "../worker_thread.h"
#include "recent_file_cache.h"
#include "event_handler.h"
#include "flags.h"
#include "../../log.h"
#include "../../message.h"
#include "../../message_buffer.h"
#include "../../result.h"

using std::vector;
using std::ostream;
using std::string;
using std::ostringstream;
using std::endl;
using std::unique_ptr;
using std::move;
using std::pair;
using std::make_pair;
using std::unordered_set;
using std::unordered_map;
using std::dec;
using std::hex;

static void command_perform_helper(void *info);

static void event_stream_helper(
  ConstFSEventStreamRef event_stream,
  void *info,
  size_t num_events,
  void *event_paths,
  const FSEventStreamEventFlags *event_flags,
  const FSEventStreamEventId *event_ids);

struct Subscription {
  WorkerPlatform *platform;
  ChannelID channel;
  FSEventStreamRef event_stream;

  Subscription(WorkerPlatform *platform, ChannelID channel) : platform{platform}, channel{channel}, event_stream{NULL}
  {
    //
  }
};

class MacOSWorkerPlatform : public WorkerPlatform {
public:
  MacOSWorkerPlatform(WorkerThread *thread) :
    WorkerPlatform(thread),
    run_loop{nullptr},
    command_source{nullptr}
  {
    //
  };

  ~MacOSWorkerPlatform() override
  {
    if (command_source) CFRelease(command_source);
    if (run_loop) CFRelease(run_loop);
  }

  Result<> wake() override
  {
    if (!is_healthy()) return health_err_result();

    CFRunLoopSourceSignal(command_source);
    CFRunLoopWakeUp(run_loop);

    return ok_result();
  }

  Result<> listen() override
  {
    if (!is_healthy()) return health_err_result();

    run_loop = CFRunLoopGetCurrent();
    CFRetain(run_loop);

    CFRunLoopSourceContext command_context = {
      0, // version
      this, // info
      NULL, // retain
      NULL, // release
      NULL, // copyDescription
      NULL, // equal
      NULL, // hash
      NULL, // schedule
      NULL, // cancel
      command_perform_helper // perform
    };
    command_source = CFRunLoopSourceCreate(kCFAllocatorDefault, 1, &command_context);
    CFRunLoopAddSource(run_loop, command_source, kCFRunLoopDefaultMode);

    CFRunLoopRun();
    return ok_result();
  }

  Result<bool> handle_add_command(
    const CommandID command,
    const ChannelID channel,
    const string &root_path) override
  {
    if (!is_healthy()) return health_err_result().propagate<bool>();
    LOGGER << "Adding watcher for path " << root_path << " at channel " << channel << "." << endl;

    Subscription *subscription = new Subscription(this, channel);

    FSEventStreamContext stream_context = {
      0, // version
      subscription, // info
      NULL, // retain
      NULL, // release
      NULL // copyDescription
    };

    CFStringRef watch_root = CFStringCreateWithBytes(
      kCFAllocatorDefault,
      reinterpret_cast<const UInt8*>(root_path.c_str()),
      root_path.size(),
      kCFStringEncodingUTF8,
      false
    );
    if (watch_root == NULL) {
      string msg("Unable to allocate string for root path: ");
      msg += root_path;
      return Result<bool>::make_error(move(msg));
    }

    CFArrayRef watch_roots = CFArrayCreate(
      kCFAllocatorDefault,
      reinterpret_cast<const void**>(&watch_root),
      1,
      NULL
    );
    if (watch_roots == NULL) {
      string msg("Unable to allocate array for watch root: ");
      msg += root_path;
      CFRelease(watch_root);

      return Result<bool>::make_error(move(msg));
    }

    FSEventStreamRef event_stream = FSEventStreamCreate(
      kCFAllocatorDefault,
      event_stream_helper,
      &stream_context,
      watch_roots,
      kFSEventStreamEventIdSinceNow,
      LATENCY,
      kFSEventStreamCreateFlagNoDefer | kFSEventStreamCreateFlagFileEvents
    );
    subscription->event_stream = event_stream;

    subscriptions.insert(make_pair(channel, subscription));

    FSEventStreamScheduleWithRunLoop(event_stream, run_loop, kCFRunLoopDefaultMode);
    if (!FSEventStreamStart(event_stream)) {
      LOGGER << "Falling back to polling for watch root " << root_path << "." << endl;

      CFRelease(watch_roots);
      CFRelease(watch_root);

      // Emit an Add command for the polling thread to pick up
      emit(Message(CommandPayload(COMMAND_ADD, command, move(root_path), channel)));
      return ok_result(false);
    }

    CFRelease(watch_roots);
    CFRelease(watch_root);
    return ok_result(true);
  }

  Result<bool> handle_remove_command(
    const CommandID,
    const ChannelID channel) override
  {
    if (!is_healthy()) return health_err_result().propagate<bool>();
    LOGGER << "Removing watcher for channel " << channel << "." << endl;

    auto maybe_subscription = subscriptions.find(channel);
    if (maybe_subscription == subscriptions.end()) {
      LOGGER << "No subscription for channel " << channel << "." << endl;
      return ok_result(true);
    }

    Subscription *subscription = maybe_subscription->second;
    subscriptions.erase(maybe_subscription);

    FSEventStreamStop(subscription->event_stream);
    FSEventStreamInvalidate(subscription->event_stream);
    FSEventStreamRelease(subscription->event_stream);

    delete subscription;
    return ok_result(true);
  }

  void handle_fs_event(
    ChannelID channel_id,
    ConstFSEventStreamRef event_stream,
    size_t num_events,
    void *event_paths,
    const FSEventStreamEventFlags *event_flags,
    const FSEventStreamEventId *event_ids)
  {
    char **paths = reinterpret_cast<char**>(event_paths);
    MessageBuffer buffer;
    ChannelMessageBuffer message_buffer(buffer, channel_id);

    LOGGER << "Filesystem event batch of size " << num_events << " received." << endl;
    message_buffer.reserve(num_events);

    EventHandler handler(message_buffer, cache);
    for (size_t i = 0; i < num_events; i++) {
      string event_path(paths[i]);
      handler.handle(event_path, event_flags[i]);
    }
    handler.flush();

    Result<> er = emit_all(message_buffer.begin(), message_buffer.end());
    if (er.is_error()) {
      LOGGER << "Unable to emit ack messages: " << er << "." << endl;
      return;
    }

    LOGGER << "Filesystem event batch of size " << num_events << " completed. "
      << plural(message_buffer.size(), "message") << " produced." << endl;

    cache.prune();
  }

private:
  CFRunLoopRef run_loop;
  CFRunLoopSourceRef command_source;

  unordered_map<ChannelID, Subscription*> subscriptions;
  RecentFileCache cache;
};

static void command_perform_helper(void *info)
{
  MacOSWorkerPlatform *platform = reinterpret_cast<MacOSWorkerPlatform*>(info);
  Result<> r = platform->handle_commands();
  if (r.is_error()) {
    LOGGER << "Unable to handle incoming commands: " << r << "." << endl;
  }
}

static void event_stream_helper(
  ConstFSEventStreamRef event_stream,
  void *info,
  size_t num_events,
  void *event_paths,
  const FSEventStreamEventFlags *event_flags,
  const FSEventStreamEventId *event_ids)
{
  Subscription *sub = reinterpret_cast<Subscription*>(info);
  MacOSWorkerPlatform *platform = static_cast<MacOSWorkerPlatform*>(sub->platform);

  platform->handle_fs_event(sub->channel, event_stream, num_events, event_paths, event_flags, event_ids);
}

unique_ptr<WorkerPlatform> WorkerPlatform::for_worker(WorkerThread *thread)
{
  return unique_ptr<WorkerPlatform>(new MacOSWorkerPlatform(thread));
}
<|endoftext|>