Commit e9e47031 authored by Alvarez, Gonzalo's avatar Alvarez, Gonzalo
Browse files

QuasiCanonical: allow arithmetic of scalars

parent 8426ed8b
Loading
Loading
Loading
Loading
+35 −2
Original line number Diff line number Diff line
@@ -66,7 +66,7 @@ class CanonicalExpression {
	typedef typename ItemSpecType::AuxiliaryType AuxiliaryType;
	typedef typename Real<ComplexOrRealType>::Type RealType;
	typedef Vector<String>::Type VectorStringType;
	typedef PsimagLite::QuasiCanonical<ComplexOrRealType> QuasiCanonicalType;
	typedef QuasiCanonical<ComplexOrRealType> QuasiCanonicalType;

public:

@@ -104,6 +104,39 @@ public:
		return (ItemSpecType::isEmpty(result)) ? false : true;
	}

	template<typename T>
	static std::pair<bool, String> replaceAll(String str,
	                                          String label,
	                                          T value)
	{
		std::pair<bool, String> boolString(true, str);

		bool retFlag = false;
		while (boolString.first) {
			boolString = replaceOne(boolString.second, label, value);
			retFlag |= boolString.first;
		};

		return std::pair<bool, String>(retFlag, boolString.second);
	}

	template<typename T>
	static std::pair<bool, String> replaceOne(String str,
	                                          String label,
	                                          T value)
	{
		// find one occurrence
		size_t x = str.find(label);
		if (x == String::npos) return std::pair<bool, String>(false, str);

		String ret = (x == 0) ? "" : str.substr(0, x);
		ret += ttos(value);

		ret += str.substr(x + label.length(), str.length() - x - label.length());

		return std::pair<bool, String>(true, ret);
	}

private:

	bool procCanonicalTerm(AssignAndDestroyType& assignAndDestroy,
+122 −0
Original line number Diff line number Diff line
@@ -9,9 +9,131 @@
#include "Stack.h"
#include "../loki/TypeTraits.h"
#include <cmath>
#include "CmplxOrReal.h"

namespace PsimagLite {

template<typename ComplexOrRealType, bool isComplex = IsComplexNumber<ComplexOrRealType>::True>
class IsAnumberPossiblyComplex {};

template<typename ComplexOrRealType>
class IsAnumberPossiblyComplex<ComplexOrRealType, false> {

public:

	enum class ComplexParensOrI {PARENS, i}; // , AUTO

	IsAnumberPossiblyComplex(String str, ComplexParensOrI = ComplexParensOrI::PARENS)
	    : flag_(isAfloat(str)), value_(0)
	{
		if (flag_) value_ = PsimagLite::atof(str.c_str());
	}

	bool operator()() const { return flag_; }

	ComplexOrRealType value() const { return value_; }

private:

	bool flag_;
	ComplexOrRealType value_;
};

template<typename ComplexOrRealType>
class IsAnumberPossiblyComplex<ComplexOrRealType, true> {

public:

	typedef typename Real<ComplexOrRealType>::Type RealType;
	typedef Vector<String>::Type VectorStringType;

	enum class ComplexParensOrI { PARENS, i}; // , AUTO

	IsAnumberPossiblyComplex(String str, ComplexParensOrI mode = ComplexParensOrI::PARENS)
	    : flag_(false), value_(0)
	{
		if (mode == ComplexParensOrI::PARENS) {
			maybeComplexNumberWithParens(str);
		} else {
			value_ = strToRealOrImag(str);
			flag_ = true;
		}
 	}

	bool operator()() const { return flag_; }

	ComplexOrRealType value() const { return value_; }

private:

	void maybeComplexNumberWithParens(String str)
	{
		// (a, b) or (a,b)
		SizeType l = str.length();
		if (l < 5) {
			seeIfItsAfloat(str);
			return;
		}

		if (str[0] != '(') {
			seeIfItsAfloat(str);
			return;
		}

		String buffer;
		String realPart;
		String imagPart;
		for (SizeType i = 1; i < l; ++i) {
			if (str[i] == ',') {
				realPart = buffer;
				buffer = "";
			} else if (str[i] == ')') {
				imagPart = buffer;
				buffer = "";
			} else if (str[i] != ' ') {
				buffer += str[i];
			} else {
				flag_ = false;
				return;
			}
		}

		flag_ = (isAfloat(realPart) && isAfloat(imagPart));
		if (!flag_) return;
		value_ = ComplexOrRealType(PsimagLite::atof(realPart), PsimagLite::atof(imagPart));
	}

	void seeIfItsAfloat(String str)
	{
		flag_ = isAfloat(str);
		if (!flag_) return;
		value_ = PsimagLite::atof(str);
	}

	static ComplexOrRealType pureRealOrPureImag(String t)
	{
		static const bool isComplex = IsComplexNumber<ComplexOrRealType>::True;
		CpmlxOrReal<RealType, (isComplex) ? 1 : 0> cmplxOrReal(t);
		return cmplxOrReal.value();
	}

	static ComplexOrRealType strToRealOrImag(String content)
	{
		VectorStringType terms;
		split(terms, content, "+");
		ComplexOrRealType sum = 0;
		const SizeType n = terms.size();
		for (SizeType i = 0; i < n; ++i) {
			sum += pureRealOrPureImag(terms[i]);
		}

		return sum;
	}

	bool flag_;
	ComplexOrRealType value_;
};

template<typename ComplexOrRealType>
struct PrepassData {
	typedef typename PsimagLite::Vector<ComplexOrRealType>::Type VectorType;
+0 −84
Original line number Diff line number Diff line
@@ -133,90 +133,6 @@ private:
	String microArch_;
};

template<typename ComplexOrRealType, bool isComplex = IsComplexNumber<ComplexOrRealType>::True>
class IsAnumberPossiblyComplex {};


template<typename ComplexOrRealType>
class IsAnumberPossiblyComplex<ComplexOrRealType, false> {
public:

	IsAnumberPossiblyComplex(String str)
	    : flag_(isAfloat(str)), value_(0)
	{
		if (flag_) value_ = PsimagLite::atof(str.c_str());
	}

	bool operator()() const { return flag_; }

	ComplexOrRealType value() const { return value_; }

private:

	bool flag_;
	ComplexOrRealType value_;
};

template<typename ComplexOrRealType>
class IsAnumberPossiblyComplex<ComplexOrRealType, true> {

public:

	IsAnumberPossiblyComplex(String str)
	    : flag_(false), value_(0)
	{
		// (a, b) or (a,b)
		SizeType l = str.length();
		if (l < 5) {
			seeIfItsAfloat(str);
			return;
		}

		if (str[0] != '(') {
			seeIfItsAfloat(str);
			return;
		}

		String buffer;
		String realPart;
		String imagPart;
		for (SizeType i = 1; i < l; ++i) {
			if (str[i] == ',') {
				realPart = buffer;
				buffer = "";
			} else if (str[i] == ')') {
				imagPart = buffer;
				buffer = "";
			} else if (str[i] != ' ') {
				buffer += str[i];
			} else {
				flag_ = false;
				return;
			}
		}

		flag_ = (isAfloat(realPart) && isAfloat(imagPart));
		if (!flag_) return;
		value_ = ComplexOrRealType(PsimagLite::atof(realPart), PsimagLite::atof(imagPart));
 	}

	bool operator()() const { return flag_; }

	ComplexOrRealType value() const { return value_; }

private:

	void seeIfItsAfloat(String str)
	{
		flag_ = isAfloat(str);
		if (!flag_) return;
		value_ = PsimagLite::atof(str);
	}

	bool flag_;
	ComplexOrRealType value_;
};

} // namespace PsimagLite

void err(PsimagLite::String);
+16 −19
Original line number Diff line number Diff line
@@ -2,7 +2,7 @@
#define QUASICANONICAL_H
#include "Vector.h"
#include "PsimagLite.h"
#include "CmplxOrReal.h"
#include "ExpressionCalculator.h"

namespace PsimagLite {

@@ -67,8 +67,9 @@ public:

		const SizeType nscalars = ats_.size();
		cachedValues_.resize(nscalars);
		for (SizeType i = 0; i < nscalars; ++i)
			cachedValues_[i] = strToRealOrImag(ats_[i]);
		for (SizeType i = 0; i < nscalars; ++i) {
			cachedValues_[i] = simpleArithmetics(ats_[i]);
		}
	}

	SizeType numberOfTerms() const { return terms_.size(); }
@@ -87,7 +88,7 @@ public:
			return -1;

		String snumber = str.substr(1, len - 2);
		SizeType number = PsimagLite::atoi(snumber);
		SizeType number = atoi(snumber);
		if (number >= ats_.size())
			return -1;
		return number;
@@ -139,24 +140,20 @@ public:

private:

	static ComplexOrRealType pureRealOrPureImag(String t)
	ComplexOrRealType simpleArithmetics(String str)
	{
		static const bool isComplex = IsComplexNumber<ComplexOrRealType>::True;
		CpmlxOrReal<RealType, (isComplex) ? 1 : 0> cmplxOrReal(t);
		return cmplxOrReal.value();
	}
		typedef ExpressionCalculator<ComplexOrRealType> ExpressionCalculatorType;
		typedef PrepassData<ComplexOrRealType> PrepassDataType;

	static ComplexOrRealType strToRealOrImag(String content)
	{
		VectorStringType terms;
		split(terms, content, "+");
		ComplexOrRealType sum = 0;
		const SizeType n = terms.size();
		for (SizeType i = 0; i < n; ++i) {
			sum += pureRealOrPureImag(terms[i]);
		}
		typename ExpressionCalculatorType::VectorStringType ve;
		split(ve, str, ":");

		PrepassDataType pd("pi", {M_PI});

		ExpressionPrepass<PrepassDataType>::prepass(ve, pd);

		return sum;
		ExpressionCalculatorType ec(ve);
		return ec();
	}

	String str_;