<commit_before>/*The MIT License (MIT)

 Copyright (c) 2014 Nathanaël Lécaudé
 https://github.com/natcl/Artnet, http://forum.pjrc.com/threads/24688-Artnet-to-OctoWS2811

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
 */

#include <ofxArtnetProtocol.h>

ofxArtnetProtocol::ofxArtnetProtocol() {}

void ofxArtnetProtocol::begin(const char* ip)
{
    bConnected = udpConnection.Create();
    if (!bConnected) {
        ofLogWarning("ofxArtnetProtocol") << "UDP socket creation failed!!";
        udpConnection.Close();
        return;
    }
    bConnected = udpConnection.Connect(ip, ART_NET_PORT);
    if (!bConnected) {
        ofLogWarning("ofxArtnetProtocol") << "UDP socket connection failed!!";
        udpConnection.Close();
        return;
    }
    udpConnection.SetNonBlocking(true);

    ofLogNotice("ofxArtnetProtocol") << "artnet is successfully connected to: "+ofToString(ip)+" / post: "+ofToString(ART_NET_PORT);

    for (size_t i=0; i<sizeof(ART_NET_ID); i++) {
        packet.id[i] = ART_NET_ID[i];
    }
    packet.opcode[0] = (char)((ART_DMX >> 0) & 0xFF);
    packet.opcode[1] = (char)((ART_DMX >> 8) & 0xFF);
    packet.sequence = 0;
    packet.universe[0] = packet.universe[1] = 0;
    packet.length[0] = ((512 >> 0) & 0xFF);
    packet.length[1] = ((512 >> 8) & 0xFF);
}

uint16_t ofxArtnetProtocol::read()
{
    if (!bConnected) return;

    int packetSize = udpConnection.Receive((char*)artnetPacket, MAX_BUFFER_ARTNET);

    if (packetSize <= MAX_BUFFER_ARTNET && packetSize > 0)
    {
        // Check that packetID is "Art-Net" else ignore
        for (size_t i = 0; i < 8; i++)
        {
            if (artnetPacket[i] != ART_NET_ID[i])
                return 0;
        }

        opcode = artnetPacket[8] | artnetPacket[9] << 8;

        if (opcode == ART_DMX)
        {
            sequence = artnetPacket[12];
            incomingUniverse = artnetPacket[14] | artnetPacket[15] << 8;
            dmxDataLength = artnetPacket[17] | artnetPacket[16] << 8;

            if (artDmxCallback) (*artDmxCallback)(incomingUniverse, dmxDataLength, sequence, artnetPacket + ART_DMX_START);
            return ART_DMX;
        }
        if (opcode == ART_POLL)
        {
            return ART_POLL;
        }
    }
    else
    {
        return 0;
    }
}

void ofxArtnetProtocol::setDmxData(uint8_t* data, uint16_t size)
{
    if (!bConnected) return;

    for (size_t i=0; i<size; i++) {
        setDmxData(i, data[i]);
    }
}

void ofxArtnetProtocol::setDmxData(uint16_t index, uint8_t data)
{
    if (!bConnected) return;

    packet.data[index] = (char)data;
}

void ofxArtnetProtocol::send(uint8_t* data, uint16_t universe, uint16_t size)
{
    if (!bConnected) return;

    static uint8_t seq = 0;
    packet.sequence = seq;
    packet.universe[0] = ((universe >> 0) & 0xFF);
    packet.universe[1] = ((universe >> 8) & 0xFF);
    packet.length[0] = ((size >> 0) & 0xFF);
    packet.length[1] = ((size >> 8) & 0xFF);
    setDmxData(data, size);

    for (size_t i=0; i<sizeof(packet.id); i++) {
        artnet_send_packet[i] = packet.id[i];
    }
    artnet_send_packet[8] = packet.opcode[0];
    artnet_send_packet[9] = packet.opcode[1];
    artnet_send_packet[10] = 0;
    artnet_send_packet[11] = 0;    // ProtVer (Art-Net Protocol Revision)
    artnet_send_packet[12] = seq;
    artnet_send_packet[13] = 0;                             // physical input port of DMX
    artnet_send_packet[14] = packet.universe[0];
    artnet_send_packet[15] = packet.universe[1];
    artnet_send_packet[16] = packet.length[1];
    artnet_send_packet[17] = packet.length[0];

    memcpy(artnet_send_packet+ART_DMX_START, packet.data, 512);

    udpConnection.Send((char*)artnet_send_packet, MAX_BUFFER_ARTNET);

    ++seq;
}

void ofxArtnetProtocol::printPacketHeader()
{
    if (!bConnected) return;

    printf("\npacket size = %d", packetSize);
    printf("\nopcode = %2x", opcode);
    printf("\nuniverse number = %d", incomingUniverse);
    printf("\ndata length = %d", dmxDataLength);
    printf("\nsequence n0. = %d", sequence);
}

void ofxArtnetProtocol::printPacketContent()
{
    if (!bConnected) return;

    for (uint16_t i = ART_DMX_START ; i < dmxDataLength ; i++){
        printf("%d ", artnetPacket[i]);
    }
    printf("\n\n");
}
<commit_msg>fix nothing returns<commit_after>/*The MIT License (MIT)

 Copyright (c) 2014 Nathanaël Lécaudé
 https://github.com/natcl/Artnet, http://forum.pjrc.com/threads/24688-Artnet-to-OctoWS2811

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
 */

#include <ofxArtnetProtocol.h>

ofxArtnetProtocol::ofxArtnetProtocol() {}

void ofxArtnetProtocol::begin(const char* ip)
{
    bConnected = udpConnection.Create();
    if (!bConnected) {
        ofLogWarning("ofxArtnetProtocol") << "UDP socket creation failed!!";
        udpConnection.Close();
        return;
    }
    bConnected = udpConnection.Connect(ip, ART_NET_PORT);
    if (!bConnected) {
        ofLogWarning("ofxArtnetProtocol") << "UDP socket connection failed!!";
        udpConnection.Close();
        return;
    }
    udpConnection.SetNonBlocking(true);

    ofLogNotice("ofxArtnetProtocol") << "artnet is successfully connected to: "+ofToString(ip)+" / post: "+ofToString(ART_NET_PORT);

    for (size_t i=0; i<sizeof(ART_NET_ID); i++) {
        packet.id[i] = ART_NET_ID[i];
    }
    packet.opcode[0] = (char)((ART_DMX >> 0) & 0xFF);
    packet.opcode[1] = (char)((ART_DMX >> 8) & 0xFF);
    packet.sequence = 0;
    packet.universe[0] = packet.universe[1] = 0;
    packet.length[0] = ((512 >> 0) & 0xFF);
    packet.length[1] = ((512 >> 8) & 0xFF);
}

uint16_t ofxArtnetProtocol::read()
{
    if (!bConnected) return 0;

    int packetSize = udpConnection.Receive((char*)artnetPacket, MAX_BUFFER_ARTNET);

    if (packetSize <= MAX_BUFFER_ARTNET && packetSize > 0)
    {
        // Check that packetID is "Art-Net" else ignore
        for (size_t i = 0; i < 8; i++)
        {
            if (artnetPacket[i] != ART_NET_ID[i])
                return 0;
        }

        opcode = artnetPacket[8] | artnetPacket[9] << 8;

        if (opcode == ART_DMX)
        {
            sequence = artnetPacket[12];
            incomingUniverse = artnetPacket[14] | artnetPacket[15] << 8;
            dmxDataLength = artnetPacket[17] | artnetPacket[16] << 8;

            if (artDmxCallback) (*artDmxCallback)(incomingUniverse, dmxDataLength, sequence, artnetPacket + ART_DMX_START);
            return ART_DMX;
        }
        if (opcode == ART_POLL)
        {
            return ART_POLL;
        }
    }
    else
    {
        return 0;
    }
}

void ofxArtnetProtocol::setDmxData(uint8_t* data, uint16_t size)
{
    if (!bConnected) return;

    for (size_t i=0; i<size; i++) {
        setDmxData(i, data[i]);
    }
}

void ofxArtnetProtocol::setDmxData(uint16_t index, uint8_t data)
{
    if (!bConnected) return;

    packet.data[index] = (char)data;
}

void ofxArtnetProtocol::send(uint8_t* data, uint16_t universe, uint16_t size)
{
    if (!bConnected) return;

    static uint8_t seq = 0;
    packet.sequence = seq;
    packet.universe[0] = ((universe >> 0) & 0xFF);
    packet.universe[1] = ((universe >> 8) & 0xFF);
    packet.length[0] = ((size >> 0) & 0xFF);
    packet.length[1] = ((size >> 8) & 0xFF);
    setDmxData(data, size);

    for (size_t i=0; i<sizeof(packet.id); i++) {
        artnet_send_packet[i] = packet.id[i];
    }
    artnet_send_packet[8] = packet.opcode[0];
    artnet_send_packet[9] = packet.opcode[1];
    artnet_send_packet[10] = 0;
    artnet_send_packet[11] = 0;    // ProtVer (Art-Net Protocol Revision)
    artnet_send_packet[12] = seq;
    artnet_send_packet[13] = 0;                             // physical input port of DMX
    artnet_send_packet[14] = packet.universe[0];
    artnet_send_packet[15] = packet.universe[1];
    artnet_send_packet[16] = packet.length[1];
    artnet_send_packet[17] = packet.length[0];

    memcpy(artnet_send_packet+ART_DMX_START, packet.data, 512);

    udpConnection.Send((char*)artnet_send_packet, MAX_BUFFER_ARTNET);

    ++seq;
}

void ofxArtnetProtocol::printPacketHeader()
{
    if (!bConnected) return;

    printf("\npacket size = %d", packetSize);
    printf("\nopcode = %2x", opcode);
    printf("\nuniverse number = %d", incomingUniverse);
    printf("\ndata length = %d", dmxDataLength);
    printf("\nsequence n0. = %d", sequence);
}

void ofxArtnetProtocol::printPacketContent()
{
    if (!bConnected) return;

    for (uint16_t i = ART_DMX_START ; i < dmxDataLength ; i++){
        printf("%d ", artnetPacket[i]);
    }
    printf("\n\n");
}
<|endoftext|>


<commit_before> /*
 *  Copyright 2007-2018 by the individuals mentioned in the source code history
 *
 *  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.
 */

#include "omxData.h"
#include <Eigen/Core>
// #include <Eigen/Dense>
#include "EnableWarnings.h"

struct omxWLSFitFunction : omxFitFunction {

	omxMatrix* expectedCov;
	omxMatrix* expectedMeans;
	omxMatrix* observedFlattened;
	omxMatrix* expectedFlattened;
	omxMatrix* weights;
	omxMatrix* P;
	omxMatrix* B;
	int numOrdinal;

	omxWLSFitFunction() :standardMeans(0), standardThresholds(0) {};
	virtual ~omxWLSFitFunction();
	virtual void init();
	virtual void compute(int ffcompute, FitContext *fc);
	virtual void populateAttr(SEXP algebra);

	// 'standard' prefix variables are temp space used by flattenDataToVector
	omxMatrix* standardCov;
	omxMatrix* standardMeans;
	omxMatrix* standardThresholds;
	void flattenDataToVector(omxMatrix* cov, omxMatrix* means, omxMatrix *thresholdMat,
				 std::vector< omxThresholdColumn > &thresholds, omxMatrix* vector);
};

void omxWLSFitFunction::flattenDataToVector(omxMatrix* cov, omxMatrix* means, omxMatrix *thresholdMat,
			 std::vector< omxThresholdColumn > &thresholds, omxMatrix* vector)
{
	EigenVectorAdaptor vec1(vector);
	normalToStdVector(cov, means, thresholdMat, numOrdinal, thresholds, vec1);
}

omxWLSFitFunction::~omxWLSFitFunction()
{
	if(OMX_DEBUG) {mxLog("Freeing WLS FitFunction.");}

	omxWLSFitFunction* owo = this;
	omxFreeMatrix(owo->observedFlattened);
	omxFreeMatrix(owo->expectedFlattened);
	omxFreeMatrix(owo->B);
	omxFreeMatrix(owo->P);
	omxFreeMatrix(owo->standardCov);
	omxFreeMatrix(owo->standardMeans);
	omxFreeMatrix(owo->standardThresholds);
}

void omxWLSFitFunction::compute(int want, FitContext *fc)
{
	auto *oo = this;
	auto *owo = this;
	if (want & (FF_COMPUTE_INITIAL_FIT | FF_COMPUTE_PREOPTIMIZE)) return;

	if(OMX_DEBUG) { mxLog("Beginning WLS Evaluation.");}
	// Requires: Data, means, covariances.

	double sum = 0.0;

	omxMatrix *eCov, *eMeans, *oFlat, *eFlat;

	/* Locals for readability.  Compiler should cut through this. */
	eCov		= owo->expectedCov;
	eMeans 		= owo->expectedMeans;
	auto &eThresh   = oo->expectation->getThresholdInfo();
	oFlat		= owo->observedFlattened;
	eFlat		= owo->expectedFlattened;
	int onei	= 1;

	/* Recompute and recopy */
	if(OMX_DEBUG) { mxLog("WLSFitFunction Computing expectation"); }
	omxExpectationCompute(fc, expectation, NULL);

	omxMatrix *expThresholdsMat = expectation->thresholdsMat;

	flattenDataToVector(eCov, eMeans, expThresholdsMat, eThresh, eFlat);

	omxCopyMatrix(B, oFlat);

	if(OMX_DEBUG) {omxPrintMatrix(eFlat, "....WLS Expected Vector: "); }
	omxDAXPY(-1.0, eFlat, B);
	//if(OMX_DEBUG) {omxPrintMatrix(B, "....WLS Observed - Expected Vector: "); }

	if(weights != NULL) {
		//if(OMX_DEBUG_ALGEBRA) {omxPrintMatrix(weights, "....WLS Weight Matrix: "); }
		omxDGEMV(TRUE, 1.0, weights, B, 0.0, P);
	} else {
		// ULS Case: Memcpy faster than dgemv.
		omxCopyMatrix(P, B);
		omxTransposeMatrix(P);
	}

	sum = F77_CALL(ddot)(&(P->cols), P->data, &onei, B->data, &onei);

	oo->matrix->data[0] = sum;

	if(OMX_DEBUG) { mxLog("WLSFitFunction value comes to: %f.", oo->matrix->data[0]); }

}

void omxWLSFitFunction::populateAttr(SEXP algebra)
{
	if(OMX_DEBUG) { mxLog("Populating WLS Attributes."); }

	omxWLSFitFunction *argStruct = this;
	omxMatrix *expCovInt = argStruct->expectedCov;	    		// Expected covariance
	omxMatrix *expMeanInt = argStruct->expectedMeans;			// Expected means
	omxMatrix *weightInt = argStruct->weights;			// Expected means

	SEXP expCovExt, expMeanExt, gradients;
	Rf_protect(expCovExt = Rf_allocMatrix(REALSXP, expCovInt->rows, expCovInt->cols));
	for(int row = 0; row < expCovInt->rows; row++)
		for(int col = 0; col < expCovInt->cols; col++)
			REAL(expCovExt)[col * expCovInt->rows + row] =
				omxMatrixElement(expCovInt, row, col);

	if (expMeanInt != NULL) {
		Rf_protect(expMeanExt = Rf_allocMatrix(REALSXP, expMeanInt->rows, expMeanInt->cols));
		for(int row = 0; row < expMeanInt->rows; row++)
			for(int col = 0; col < expMeanInt->cols; col++)
				REAL(expMeanExt)[col * expMeanInt->rows + row] =
					omxMatrixElement(expMeanInt, row, col);
	} else {
		Rf_protect(expMeanExt = Rf_allocMatrix(REALSXP, 0, 0));
	}

	if(OMX_DEBUG_ALGEBRA) {omxPrintMatrix(weightInt, "...WLS Weight Matrix: W"); }
	SEXP weightExt = NULL;
	if (weightInt) {
		Rf_protect(weightExt = Rf_allocMatrix(REALSXP, weightInt->rows, weightInt->cols));
		for(int row = 0; row < weightInt->rows; row++)
			for(int col = 0; col < weightInt->cols; col++)
				REAL(weightExt)[col * weightInt->rows + row] = weightInt->data[col * weightInt->rows + row];
	}

	if(0) {  /* TODO fix for new internal API
		int nLocs = Global->numFreeParams;
		double gradient[Global->numFreeParams];
		for(int loc = 0; loc < nLocs; loc++) {
			gradient[loc] = NA_REAL;
		}
		//oo->gradientFun(oo, gradient);
		Rf_protect(gradients = Rf_allocMatrix(REALSXP, 1, nLocs));

		for(int loc = 0; loc < nLocs; loc++)
			REAL(gradients)[loc] = gradient[loc];
		 */
	} else {
		Rf_protect(gradients = Rf_allocMatrix(REALSXP, 0, 0));
	}

	if(OMX_DEBUG) { mxLog("Installing populated WLS Attributes."); }
	Rf_setAttrib(algebra, Rf_install("expCov"), expCovExt);
	Rf_setAttrib(algebra, Rf_install("expMean"), expMeanExt);
	if (weightExt) Rf_setAttrib(algebra, Rf_install("weights"), weightExt);
	Rf_setAttrib(algebra, Rf_install("gradients"), gradients);

	ProtectedSEXP Rsat(Rf_ScalarReal(0));
	Rf_setAttrib(algebra, Rf_install("SaturatedLikelihood"), Rsat);
	//Rf_setAttrib(algebra, Rf_install("IndependenceLikelihood"), Rf_ScalarReal(0));
	ProtectedSEXP Rmisfit(Rf_ScalarReal(omxMatrixElement(matrix, 0, 0)));
	Rf_setAttrib(algebra, Rf_install("ADFMisfit"), Rmisfit);
}

omxFitFunction *omxInitWLSFitFunction()
{ return new omxWLSFitFunction; }

void omxWLSFitFunction::init()
{
	auto *oo = this;
	auto *newObj = this;

	omxState *currentState = oo->matrix->currentState;

	if (!oo->expectation) { Rf_error("%s requires an expectation", name()); }

	omxData* dataMat = oo->expectation->data;

	std::vector<int> exoPred;
	expectation->getExogenousPredictors(exoPred);

	if (dataMat->defVars.size() == exoPred.size()) {
		// OK
	} else if (dataMat->hasDefinitionVariables()) Rf_error("%s: def vars not implemented", oo->name());

	// For multiple threads, need to grab parent's info TODO
	dataMat->prepObsStats(currentState, oo->expectation->getDataColumnNames(), exoPred);

	auto &obsStat = dataMat->getSingleObsSummaryStats();
	//obsStat.log();
	omxMatrix *cov = obsStat.covMat;
	if (!cov) {
		omxRaiseErrorf("%s: an observed covariance matrix is required", name());
		return;
	}

	omxMatrix *means = obsStat.meansMat;
	omxMatrix *obsThresholdsMat = obsStat.thresholdMat;
	weights = obsStat.acovMat;
	std::vector< omxThresholdColumn > &oThresh = obsStat.thresholdCols;

	numOrdinal = oo->expectation->numOrdinal;
	auto &eThresh = oo->expectation->getThresholdInfo();

	if (eThresh.size() && !means) {
		omxRaiseError("Means are required when the data include ordinal measurements");
		return;
	}

	newObj->expectedCov = omxGetExpectationComponent(oo->expectation, "cov");
	newObj->expectedMeans = omxGetExpectationComponent(oo->expectation, "means");

	// Error Checking: Observed/Expected means must agree.
	// ^ is XOR: true when one is false and the other is not.
	if((newObj->expectedMeans == NULL) ^ (means == NULL)) {
		if(newObj->expectedMeans != NULL) {
			omxRaiseError("Observed means not detected, but an expected means matrix was specified.\n  If you  wish to model the means, you must provide observed means.\n");
			return;
		} else {
			omxRaiseError("Observed means were provided, but an expected means matrix was not specified.\n  If you provide observed means, you must specify a model for the means.\n");
			return;
		}
	}

	if((eThresh.size()==0) ^ (obsThresholdsMat==0)) {
		if (eThresh.size()) {
			omxRaiseError("Observed thresholds not detected, but an expected thresholds matrix was specified.\n   If you wish to model the thresholds, you must provide observed thresholds.\n ");
			return;
		} else {
			omxRaiseError("Observed thresholds were provided, but an expected thresholds matrix was not specified.\nIf you provide observed thresholds, you must specify a model for the thresholds.\n");
			return;
		}
	}

	if (obsThresholdsMat) {
		for(int i = 0; i < int(oThresh.size()); i++) {
			eThresh[i].numThresholds = oThresh[i].numThresholds;
		}
	}

	if (OMX_DEBUG) {
		mxLog("expected thresholds:");
		for (auto &th : eThresh) { th.log(); }
		mxLog("observed thresholds:");
		for (auto &th : oThresh) { th.log(); }
	}

	/* Error check weight matrix size */
	int ncol = cov->cols;
	int vectorSize = expectation->numSummaryStats();
	if(OMX_DEBUG) { mxLog("Intial WLSFitFunction vectorSize comes to: %d.", vectorSize); }

	if(weights) {
		if (weights->rows != weights->cols || weights->cols != vectorSize) {
			omxRaiseErrorf("Developer Error in WLS-based FitFunction object: WLS-based expectation specified an incorrectly-sized weight matrix (%d != %d).\nIf you are not developing a new expectation type, you should probably post this to the OpenMx forums.", vectorSize, weights->cols);
			return;
		}

		EigenMatrixAdaptor Eweight(weights);
		Eigen::MatrixXd offDiagW = Eweight.triangularView<Eigen::StrictlyUpper>();
		double offDiag = offDiagW.array().abs().sum();
		oo->units = offDiag > 0.0? FIT_UNITS_SQUARED_RESIDUAL_CHISQ : FIT_UNITS_SQUARED_RESIDUAL;
	} else {
		oo->units = FIT_UNITS_SQUARED_RESIDUAL;
	}

	// FIXME: More Rf_error checking for incoming Fit Functions

	/* Temporary storage for calculation */
	newObj->observedFlattened = omxInitMatrix(vectorSize, 1, TRUE, currentState);
	newObj->expectedFlattened = omxInitMatrix(vectorSize, 1, TRUE, currentState);
	newObj->P = omxInitMatrix(1, vectorSize, TRUE, currentState);
	newObj->B = omxInitMatrix(vectorSize, 1, TRUE, currentState);
	newObj->standardCov = omxInitMatrix(ncol, ncol, TRUE, currentState);
	if (oo->expectation->thresholdsMat) {
		newObj->standardThresholds = omxInitMatrix(oo->expectation->thresholdsMat->rows, oo->expectation->thresholdsMat->cols, TRUE, currentState);
	}
	if(means){
		newObj->standardMeans = omxInitMatrix(1, ncol, TRUE, currentState);
	}
	if (obsThresholdsMat && oo->expectation->thresholdsMat) {
		if (obsThresholdsMat->rows != oo->expectation->thresholdsMat->rows ||
		    obsThresholdsMat->cols != oo->expectation->thresholdsMat->cols) {
			omxRaiseError("Observed and expected threshold matrices must have the same number of rows and columns");
		}
	}

	flattenDataToVector(cov, means, obsThresholdsMat, oThresh, newObj->observedFlattened);
	if(OMX_DEBUG) {omxPrintMatrix(newObj->observedFlattened, "....WLS Observed Vector: "); }
	flattenDataToVector(newObj->expectedCov, newObj->expectedMeans, oo->expectation->thresholdsMat,
				eThresh, newObj->expectedFlattened);
}
<commit_msg>Remove deadcode<commit_after> /*
 *  Copyright 2007-2018 by the individuals mentioned in the source code history
 *
 *  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.
 */

#include "omxData.h"
#include <Eigen/Core>
// #include <Eigen/Dense>
#include "EnableWarnings.h"

struct omxWLSFitFunction : omxFitFunction {

	omxMatrix* expectedCov;
	omxMatrix* expectedMeans;
	omxMatrix* observedFlattened;
	omxMatrix* expectedFlattened;
	omxMatrix* weights;
	omxMatrix* P;
	omxMatrix* B;
	int numOrdinal;

	omxWLSFitFunction() {};
	virtual ~omxWLSFitFunction();
	virtual void init();
	virtual void compute(int ffcompute, FitContext *fc);
	virtual void populateAttr(SEXP algebra);

	void flattenDataToVector(omxMatrix* cov, omxMatrix* means, omxMatrix *thresholdMat,
				 std::vector< omxThresholdColumn > &thresholds, omxMatrix* vector);
};

void omxWLSFitFunction::flattenDataToVector(omxMatrix* cov, omxMatrix* means, omxMatrix *thresholdMat,
			 std::vector< omxThresholdColumn > &thresholds, omxMatrix* vector)
{
	EigenVectorAdaptor vec1(vector);
	normalToStdVector(cov, means, thresholdMat, numOrdinal, thresholds, vec1);
}

omxWLSFitFunction::~omxWLSFitFunction()
{
	if(OMX_DEBUG) {mxLog("Freeing WLS FitFunction.");}

	omxWLSFitFunction* owo = this;
	omxFreeMatrix(owo->observedFlattened);
	omxFreeMatrix(owo->expectedFlattened);
	omxFreeMatrix(owo->B);
	omxFreeMatrix(owo->P);
}

void omxWLSFitFunction::compute(int want, FitContext *fc)
{
	auto *oo = this;
	auto *owo = this;
	if (want & (FF_COMPUTE_INITIAL_FIT | FF_COMPUTE_PREOPTIMIZE)) return;

	if(OMX_DEBUG) { mxLog("Beginning WLS Evaluation.");}
	// Requires: Data, means, covariances.

	double sum = 0.0;

	omxMatrix *eCov, *eMeans, *oFlat, *eFlat;

	/* Locals for readability.  Compiler should cut through this. */
	eCov		= owo->expectedCov;
	eMeans 		= owo->expectedMeans;
	auto &eThresh   = oo->expectation->getThresholdInfo();
	oFlat		= owo->observedFlattened;
	eFlat		= owo->expectedFlattened;
	int onei	= 1;

	/* Recompute and recopy */
	if(OMX_DEBUG) { mxLog("WLSFitFunction Computing expectation"); }
	omxExpectationCompute(fc, expectation, NULL);

	omxMatrix *expThresholdsMat = expectation->thresholdsMat;

	flattenDataToVector(eCov, eMeans, expThresholdsMat, eThresh, eFlat);

	omxCopyMatrix(B, oFlat);

	if(OMX_DEBUG) {omxPrintMatrix(eFlat, "....WLS Expected Vector: "); }
	omxDAXPY(-1.0, eFlat, B);
	//if(OMX_DEBUG) {omxPrintMatrix(B, "....WLS Observed - Expected Vector: "); }

	if(weights != NULL) {
		//if(OMX_DEBUG_ALGEBRA) {omxPrintMatrix(weights, "....WLS Weight Matrix: "); }
		omxDGEMV(TRUE, 1.0, weights, B, 0.0, P);
	} else {
		// ULS Case: Memcpy faster than dgemv.
		omxCopyMatrix(P, B);
		omxTransposeMatrix(P);
	}

	sum = F77_CALL(ddot)(&(P->cols), P->data, &onei, B->data, &onei);

	oo->matrix->data[0] = sum;

	if(OMX_DEBUG) { mxLog("WLSFitFunction value comes to: %f.", oo->matrix->data[0]); }

}

void omxWLSFitFunction::populateAttr(SEXP algebra)
{
	if(OMX_DEBUG) { mxLog("Populating WLS Attributes."); }

	omxWLSFitFunction *argStruct = this;
	omxMatrix *expCovInt = argStruct->expectedCov;	    		// Expected covariance
	omxMatrix *expMeanInt = argStruct->expectedMeans;			// Expected means
	omxMatrix *weightInt = argStruct->weights;			// Expected means

	SEXP expCovExt, expMeanExt, gradients;
	Rf_protect(expCovExt = Rf_allocMatrix(REALSXP, expCovInt->rows, expCovInt->cols));
	for(int row = 0; row < expCovInt->rows; row++)
		for(int col = 0; col < expCovInt->cols; col++)
			REAL(expCovExt)[col * expCovInt->rows + row] =
				omxMatrixElement(expCovInt, row, col);

	if (expMeanInt != NULL) {
		Rf_protect(expMeanExt = Rf_allocMatrix(REALSXP, expMeanInt->rows, expMeanInt->cols));
		for(int row = 0; row < expMeanInt->rows; row++)
			for(int col = 0; col < expMeanInt->cols; col++)
				REAL(expMeanExt)[col * expMeanInt->rows + row] =
					omxMatrixElement(expMeanInt, row, col);
	} else {
		Rf_protect(expMeanExt = Rf_allocMatrix(REALSXP, 0, 0));
	}

	if(OMX_DEBUG_ALGEBRA) {omxPrintMatrix(weightInt, "...WLS Weight Matrix: W"); }
	SEXP weightExt = NULL;
	if (weightInt) {
		Rf_protect(weightExt = Rf_allocMatrix(REALSXP, weightInt->rows, weightInt->cols));
		for(int row = 0; row < weightInt->rows; row++)
			for(int col = 0; col < weightInt->cols; col++)
				REAL(weightExt)[col * weightInt->rows + row] = weightInt->data[col * weightInt->rows + row];
	}

	if(0) {  /* TODO fix for new internal API
		int nLocs = Global->numFreeParams;
		double gradient[Global->numFreeParams];
		for(int loc = 0; loc < nLocs; loc++) {
			gradient[loc] = NA_REAL;
		}
		//oo->gradientFun(oo, gradient);
		Rf_protect(gradients = Rf_allocMatrix(REALSXP, 1, nLocs));

		for(int loc = 0; loc < nLocs; loc++)
			REAL(gradients)[loc] = gradient[loc];
		 */
	} else {
		Rf_protect(gradients = Rf_allocMatrix(REALSXP, 0, 0));
	}

	if(OMX_DEBUG) { mxLog("Installing populated WLS Attributes."); }
	Rf_setAttrib(algebra, Rf_install("expCov"), expCovExt);
	Rf_setAttrib(algebra, Rf_install("expMean"), expMeanExt);
	if (weightExt) Rf_setAttrib(algebra, Rf_install("weights"), weightExt);
	Rf_setAttrib(algebra, Rf_install("gradients"), gradients);

	ProtectedSEXP Rsat(Rf_ScalarReal(0));
	Rf_setAttrib(algebra, Rf_install("SaturatedLikelihood"), Rsat);
	//Rf_setAttrib(algebra, Rf_install("IndependenceLikelihood"), Rf_ScalarReal(0));
	ProtectedSEXP Rmisfit(Rf_ScalarReal(omxMatrixElement(matrix, 0, 0)));
	Rf_setAttrib(algebra, Rf_install("ADFMisfit"), Rmisfit);
}

omxFitFunction *omxInitWLSFitFunction()
{ return new omxWLSFitFunction; }

void omxWLSFitFunction::init()
{
	auto *oo = this;
	auto *newObj = this;

	omxState *currentState = oo->matrix->currentState;

	if (!oo->expectation) { Rf_error("%s requires an expectation", name()); }

	omxData* dataMat = oo->expectation->data;

	std::vector<int> exoPred;
	expectation->getExogenousPredictors(exoPred);

	if (dataMat->defVars.size() == exoPred.size()) {
		// OK
	} else if (dataMat->hasDefinitionVariables()) Rf_error("%s: def vars not implemented", oo->name());

	// For multiple threads, need to grab parent's info TODO
	dataMat->prepObsStats(currentState, oo->expectation->getDataColumnNames(), exoPred);

	auto &obsStat = dataMat->getSingleObsSummaryStats();
	//obsStat.log();
	omxMatrix *cov = obsStat.covMat;
	if (!cov) {
		omxRaiseErrorf("%s: an observed covariance matrix is required", name());
		return;
	}

	omxMatrix *means = obsStat.meansMat;
	omxMatrix *obsThresholdsMat = obsStat.thresholdMat;
	weights = obsStat.acovMat;
	std::vector< omxThresholdColumn > &oThresh = obsStat.thresholdCols;

	numOrdinal = oo->expectation->numOrdinal;
	auto &eThresh = oo->expectation->getThresholdInfo();

	if (eThresh.size() && !means) {
		omxRaiseError("Means are required when the data include ordinal measurements");
		return;
	}

	newObj->expectedCov = omxGetExpectationComponent(oo->expectation, "cov");
	newObj->expectedMeans = omxGetExpectationComponent(oo->expectation, "means");

	// Error Checking: Observed/Expected means must agree.
	// ^ is XOR: true when one is false and the other is not.
	if((newObj->expectedMeans == NULL) ^ (means == NULL)) {
		if(newObj->expectedMeans != NULL) {
			omxRaiseError("Observed means not detected, but an expected means matrix was specified.\n  If you  wish to model the means, you must provide observed means.\n");
			return;
		} else {
			omxRaiseError("Observed means were provided, but an expected means matrix was not specified.\n  If you provide observed means, you must specify a model for the means.\n");
			return;
		}
	}

	if((eThresh.size()==0) ^ (obsThresholdsMat==0)) {
		if (eThresh.size()) {
			omxRaiseError("Observed thresholds not detected, but an expected thresholds matrix was specified.\n   If you wish to model the thresholds, you must provide observed thresholds.\n ");
			return;
		} else {
			omxRaiseError("Observed thresholds were provided, but an expected thresholds matrix was not specified.\nIf you provide observed thresholds, you must specify a model for the thresholds.\n");
			return;
		}
	}

	if (obsThresholdsMat) {
		for(int i = 0; i < int(oThresh.size()); i++) {
			eThresh[i].numThresholds = oThresh[i].numThresholds;
		}
	}

	if (OMX_DEBUG) {
		mxLog("expected thresholds:");
		for (auto &th : eThresh) { th.log(); }
		mxLog("observed thresholds:");
		for (auto &th : oThresh) { th.log(); }
	}

	/* Error check weight matrix size */
	int vectorSize = expectation->numSummaryStats();
	if(OMX_DEBUG) { mxLog("Intial WLSFitFunction vectorSize comes to: %d.", vectorSize); }

	if(weights) {
		if (weights->rows != weights->cols || weights->cols != vectorSize) {
			omxRaiseErrorf("Developer Error in WLS-based FitFunction object: WLS-based expectation specified an incorrectly-sized weight matrix (%d != %d).\nIf you are not developing a new expectation type, you should probably post this to the OpenMx forums.", vectorSize, weights->cols);
			return;
		}

		EigenMatrixAdaptor Eweight(weights);
		Eigen::MatrixXd offDiagW = Eweight.triangularView<Eigen::StrictlyUpper>();
		double offDiag = offDiagW.array().abs().sum();
		oo->units = offDiag > 0.0? FIT_UNITS_SQUARED_RESIDUAL_CHISQ : FIT_UNITS_SQUARED_RESIDUAL;
	} else {
		oo->units = FIT_UNITS_SQUARED_RESIDUAL;
	}

	// FIXME: More Rf_error checking for incoming Fit Functions

	/* Temporary storage for calculation */
	newObj->observedFlattened = omxInitMatrix(vectorSize, 1, TRUE, currentState);
	newObj->expectedFlattened = omxInitMatrix(vectorSize, 1, TRUE, currentState);
	newObj->P = omxInitMatrix(1, vectorSize, TRUE, currentState);
	newObj->B = omxInitMatrix(vectorSize, 1, TRUE, currentState);
	if (obsThresholdsMat && oo->expectation->thresholdsMat) {
		if (obsThresholdsMat->rows != oo->expectation->thresholdsMat->rows ||
		    obsThresholdsMat->cols != oo->expectation->thresholdsMat->cols) {
			omxRaiseError("Observed and expected threshold matrices must have the same number of rows and columns");
		}
	}

	flattenDataToVector(cov, means, obsThresholdsMat, oThresh, newObj->observedFlattened);
	if(OMX_DEBUG) {omxPrintMatrix(newObj->observedFlattened, "....WLS Observed Vector: "); }
	flattenDataToVector(newObj->expectedCov, newObj->expectedMeans, oo->expectation->thresholdsMat,
				eThresh, newObj->expectedFlattened);
}
<|endoftext|>


<commit_before>/////////////////////////////////////////////////////////////////////////////
// Original authors: SangGi Do(sanggido@unist.ac.kr), Mingyu Woo(mwoo@eng.ucsd.edu)
//          (respective Ph.D. advisors: Seokhyeong Kang, Andrew B. Kahng)
// Rewrite by James Cherry, Parallax Software, Inc.

// BSD 3-Clause License
//
// Copyright (c) 2019, James Cherry, Parallax Software, Inc.
// Copyright (c) 2018, SangGi Do and Mingyu Woo
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this
//   list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
//
// * Neither the name of the copyright holder nor the names of its
//   contributors may be used to endorse or promote products derived from
//   this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
///////////////////////////////////////////////////////////////////////////////

#include <cmath>
#include <limits>
#include "openroad/Error.hh"
#include "opendp/Opendp.h"

namespace opendp {

using std::cerr;
using std::cout;
using std::endl;
using std::max;
using std::min;
using std::abs;
using std::pair;
using std::round;
using std::numeric_limits;

using ord::error;

void Opendp::fixed_cell_assign() {
  for(Cell &cell : cells_) {
    if(isFixed(&cell)) {
      int y_start = gridY(&cell);
      int y_end = gridEndY(&cell);
      int x_start = gridPaddedX(&cell);
      int x_end = gridPaddedEndX(&cell);

      int y_start_rf = 0;
      int y_end_rf = gridEndY();
      int x_start_rf = 0;
      int x_end_rf = gridEndX();

      y_start = max(y_start, y_start_rf);
      y_end = min(y_end, y_end_rf);
      x_start = max(x_start, x_start_rf);
      x_end = min(x_end, x_end_rf);

#ifdef ODP_DEBUG
      cout << "FixedCellAssign: cell_name : "
           << cell.name() << endl;
      cout << "FixedCellAssign: y_start : " << y_start << endl;
      cout << "FixedCellAssign: y_end   : " << y_end << endl;
      cout << "FixedCellAssign: x_start : " << x_start << endl;
      cout << "FixedCellAssign: x_end   : " << x_end << endl;
#endif
      for(int j = y_start; j < y_end; j++) {
        for(int k = x_start; k < x_end; k++) {
          grid_[j][k].cell = &cell;
          grid_[j][k].util = 1.0;
        }
      }
    }
  }
}

void Opendp::group_cell_region_assign() {
  for(Group& group : groups_) {
    int64_t site_count = 0;
    for(int j = 0; j < row_count_; j++) {
      for(int k = 0; k < row_site_count_; k++) {
	if(grid_[j][k].is_valid
	   && grid_[j][k].group_ == &group)
	  site_count++;
      }
    }
    int64_t area = site_count * site_width_ * row_height_;

    int64_t cell_area = 0;
    for(Cell* cell : group.siblings) {
      cell_area += cell->area();
    }
    group.util = static_cast<double>(cell_area) / area;
  }
}

void Opendp::group_pixel_assign2() {
  for(int i = 0; i < row_count_; i++) {
    for(int j = 0; j < row_site_count_; j++) {
      adsRect grid2;
      grid2.init(j * site_width_, i * row_height_,
		(j + 1) * site_width_, (i + 1) * row_height_);
      for(Group& group : groups_) {
        for(adsRect &rect : group.regions) {
	  if(!check_inside(grid2, rect) &&
             check_overlap(grid2, rect)) {
            grid_[i][j].util = 0.0;
            grid_[i][j].cell = &dummy_cell_;
            grid_[i][j].is_valid = false;
          }
        }
      }
    }
  }
}

void Opendp::group_pixel_assign() {
  for(int i = 0; i < row_count_; i++) {
    for(int j = 0; j < row_site_count_; j++) {
      grid_[i][j].util = 0.0;
    }
  }

  for(Group& group : groups_) {
    for(adsRect &rect : group.regions) {
      int row_start = divCeil(rect.yMin(), row_height_);
      int row_end = divFloor(rect.yMax(), row_height_);

      for(int k = row_start; k < row_end; k++) {
        int col_start = divCeil(rect.xMin(), site_width_);
        int col_end = divFloor(rect.xMax(), site_width_);

        for(int l = col_start; l < col_end; l++) {
          grid_[k][l].util += 1.0;
        }
        if(rect.xMin() % site_width_ != 0) {
          grid_[k][col_start].util -=
	    (rect.xMin() % site_width_) / static_cast<double>(site_width_);
        }
        if(rect.xMax() % site_width_ != 0) {
          grid_[k][col_end - 1].util -=
	    // magic number alert
	    ((200 - rect.xMax()) % site_width_) / static_cast<double>(site_width_);
        }
      }
    }
    for(adsRect& rect : group.regions) {
      int row_start = divCeil(rect.yMin(), row_height_);
      int row_end = divFloor(rect.yMax(), row_height_);

      for(int k = row_start; k < row_end; k++) {
        int col_start = divCeil(rect.xMin(), site_width_);
        int col_end = divFloor(rect.xMax(), site_width_);

        // Assign group to each pixel.
        for(int l = col_start; l < col_end; l++) {
          if(abs(grid_[k][l].util - 1.0) < 1e-6) {
            grid_[k][l].group_ = &group;
	    grid_[k][l].is_valid = true;
            grid_[k][l].util = 1.0;
	  }
          else if(grid_[k][l].util > 0 && grid_[k][l].util < 1) {
            grid_[k][l].cell = &dummy_cell_;
            grid_[k][l].util = 0.0;
            grid_[k][l].is_valid = false;
          }
        }
      }
    }
  }
}

void Opendp::erase_pixel(Cell* cell) {
  if(!(isFixed(cell) || !cell->is_placed_)) {
    int x_step = gridPaddedWidth(cell);
    int y_step = gridHeight(cell);
    for(int i = gridY(cell); i < gridY(cell) + y_step; i++) {
      for(int j = gridPaddedX(cell); j < gridPaddedX(cell) + x_step; j++) {
	grid_[i][j].cell = nullptr;
	grid_[i][j].util = 0;
      }
    }
    cell->x_ = 0;
    cell->y_ = 0;
    cell->is_placed_ = false;
    cell->hold_ = false;
  }
}

void Opendp::paint_pixel(Cell* cell, int grid_x, int grid_y) {
  assert(!cell->is_placed_);
  int x_step = gridPaddedWidth(cell);
  int y_step = gridHeight(cell);

  setGridPaddedLoc(cell, grid_x, grid_y);
  cell->is_placed_ = true;

#ifdef ODP_DEBUG
  cout << "paint cell : " << cell->name() << endl;
  cout << "x_ - y_ : " << cell->x_ << " - "
       << cell->y_ << endl;
  cout << "x_step - y_step : " << x_step << " - " << y_step << endl;
  cout << "grid_x - grid_y : " << grid_x << " - " << grid_y << endl;
#endif

  for(int i = grid_y; i < grid_y + y_step; i++) {
    for(int j = grid_x; j < grid_x + x_step; j++) {
      if(grid_[i][j].cell != nullptr) {
        error("Cannot paint grid because it is already occupied.");
      }
      else {
        grid_[i][j].cell = cell;
        grid_[i][j].util = 1.0;
      }
    }
  }
  if(max_cell_height_ > 1) {
    if(y_step % 2 == 1) {
      if(rowTopPower(grid_y) != topPower(cell))
        cell->orient_ = dbOrientType::MX;
      else
        cell->orient_ = dbOrientType::R0;
    }
  }
  else {
    cell->orient_ = rowOrient(grid_y);
  }
}

}  // namespace opendp
<commit_msg>opendp group_pixel_assign remove mysterious 200<commit_after>/////////////////////////////////////////////////////////////////////////////
// Original authors: SangGi Do(sanggido@unist.ac.kr), Mingyu Woo(mwoo@eng.ucsd.edu)
//          (respective Ph.D. advisors: Seokhyeong Kang, Andrew B. Kahng)
// Rewrite by James Cherry, Parallax Software, Inc.

// BSD 3-Clause License
//
// Copyright (c) 2019, James Cherry, Parallax Software, Inc.
// Copyright (c) 2018, SangGi Do and Mingyu Woo
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this
//   list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
//
// * Neither the name of the copyright holder nor the names of its
//   contributors may be used to endorse or promote products derived from
//   this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
///////////////////////////////////////////////////////////////////////////////

#include <cmath>
#include <limits>
#include "openroad/Error.hh"
#include "opendp/Opendp.h"

namespace opendp {

using std::cerr;
using std::cout;
using std::endl;
using std::max;
using std::min;
using std::abs;
using std::pair;
using std::round;
using std::numeric_limits;

using ord::error;

void Opendp::fixed_cell_assign() {
  for(Cell &cell : cells_) {
    if(isFixed(&cell)) {
      int y_start = gridY(&cell);
      int y_end = gridEndY(&cell);
      int x_start = gridPaddedX(&cell);
      int x_end = gridPaddedEndX(&cell);

      int y_start_rf = 0;
      int y_end_rf = gridEndY();
      int x_start_rf = 0;
      int x_end_rf = gridEndX();

      y_start = max(y_start, y_start_rf);
      y_end = min(y_end, y_end_rf);
      x_start = max(x_start, x_start_rf);
      x_end = min(x_end, x_end_rf);

#ifdef ODP_DEBUG
      cout << "FixedCellAssign: cell_name : "
           << cell.name() << endl;
      cout << "FixedCellAssign: y_start : " << y_start << endl;
      cout << "FixedCellAssign: y_end   : " << y_end << endl;
      cout << "FixedCellAssign: x_start : " << x_start << endl;
      cout << "FixedCellAssign: x_end   : " << x_end << endl;
#endif
      for(int j = y_start; j < y_end; j++) {
        for(int k = x_start; k < x_end; k++) {
          grid_[j][k].cell = &cell;
          grid_[j][k].util = 1.0;
        }
      }
    }
  }
}

void Opendp::group_cell_region_assign() {
  for(Group& group : groups_) {
    int64_t site_count = 0;
    for(int j = 0; j < row_count_; j++) {
      for(int k = 0; k < row_site_count_; k++) {
	if(grid_[j][k].is_valid
	   && grid_[j][k].group_ == &group)
	  site_count++;
      }
    }
    int64_t area = site_count * site_width_ * row_height_;

    int64_t cell_area = 0;
    for(Cell* cell : group.siblings) {
      cell_area += cell->area();
    }
    group.util = static_cast<double>(cell_area) / area;
  }
}

void Opendp::group_pixel_assign2() {
  for(int i = 0; i < row_count_; i++) {
    for(int j = 0; j < row_site_count_; j++) {
      adsRect grid2;
      grid2.init(j * site_width_, i * row_height_,
		(j + 1) * site_width_, (i + 1) * row_height_);
      for(Group& group : groups_) {
        for(adsRect &rect : group.regions) {
	  if(!check_inside(grid2, rect) &&
             check_overlap(grid2, rect)) {
            grid_[i][j].util = 0.0;
            grid_[i][j].cell = &dummy_cell_;
            grid_[i][j].is_valid = false;
          }
        }
      }
    }
  }
}

void Opendp::group_pixel_assign() {
  for(int i = 0; i < row_count_; i++) {
    for(int j = 0; j < row_site_count_; j++) {
      grid_[i][j].util = 0.0;
    }
  }

  for(Group& group : groups_) {
    for(adsRect &rect : group.regions) {
      int row_start = divCeil(rect.yMin(), row_height_);
      int row_end = divFloor(rect.yMax(), row_height_);

      for(int k = row_start; k < row_end; k++) {
        int col_start = divCeil(rect.xMin(), site_width_);
        int col_end = divFloor(rect.xMax(), site_width_);

        for(int l = col_start; l < col_end; l++) {
          grid_[k][l].util += 1.0;
        }
        if(rect.xMin() % site_width_ != 0) {
          grid_[k][col_start].util -=
	    (rect.xMin() % site_width_) / static_cast<double>(site_width_);
        }
        if(rect.xMax() % site_width_ != 0) {
          grid_[k][col_end - 1].util -=
	    ((site_width_ - rect.xMax()) % site_width_) / static_cast<double>(site_width_);
        }
      }
    }
    for(adsRect& rect : group.regions) {
      int row_start = divCeil(rect.yMin(), row_height_);
      int row_end = divFloor(rect.yMax(), row_height_);

      for(int k = row_start; k < row_end; k++) {
        int col_start = divCeil(rect.xMin(), site_width_);
        int col_end = divFloor(rect.xMax(), site_width_);

        // Assign group to each pixel.
        for(int l = col_start; l < col_end; l++) {
          if(abs(grid_[k][l].util - 1.0) < 1e-6) {
            grid_[k][l].group_ = &group;
	    grid_[k][l].is_valid = true;
            grid_[k][l].util = 1.0;
	  }
          else if(grid_[k][l].util > 0 && grid_[k][l].util < 1) {
            grid_[k][l].cell = &dummy_cell_;
            grid_[k][l].util = 0.0;
            grid_[k][l].is_valid = false;
          }
        }
      }
    }
  }
}

void Opendp::erase_pixel(Cell* cell) {
  if(!(isFixed(cell) || !cell->is_placed_)) {
    int x_step = gridPaddedWidth(cell);
    int y_step = gridHeight(cell);
    for(int i = gridY(cell); i < gridY(cell) + y_step; i++) {
      for(int j = gridPaddedX(cell); j < gridPaddedX(cell) + x_step; j++) {
	grid_[i][j].cell = nullptr;
	grid_[i][j].util = 0;
      }
    }
    cell->x_ = 0;
    cell->y_ = 0;
    cell->is_placed_ = false;
    cell->hold_ = false;
  }
}

void Opendp::paint_pixel(Cell* cell, int grid_x, int grid_y) {
  assert(!cell->is_placed_);
  int x_step = gridPaddedWidth(cell);
  int y_step = gridHeight(cell);

  setGridPaddedLoc(cell, grid_x, grid_y);
  cell->is_placed_ = true;

#ifdef ODP_DEBUG
  cout << "paint cell : " << cell->name() << endl;
  cout << "x_ - y_ : " << cell->x_ << " - "
       << cell->y_ << endl;
  cout << "x_step - y_step : " << x_step << " - " << y_step << endl;
  cout << "grid_x - grid_y : " << grid_x << " - " << grid_y << endl;
#endif

  for(int i = grid_y; i < grid_y + y_step; i++) {
    for(int j = grid_x; j < grid_x + x_step; j++) {
      if(grid_[i][j].cell != nullptr) {
        error("Cannot paint grid because it is already occupied.");
      }
      else {
        grid_[i][j].cell = cell;
        grid_[i][j].util = 1.0;
      }
    }
  }
  if(max_cell_height_ > 1) {
    if(y_step % 2 == 1) {
      if(rowTopPower(grid_y) != topPower(cell))
        cell->orient_ = dbOrientType::MX;
      else
        cell->orient_ = dbOrientType::R0;
    }
  }
  else {
    cell->orient_ = rowOrient(grid_y);
  }
}

}  // namespace opendp
<|endoftext|>


<commit_before>/******************************************************************************\

          This file is part of the C! library.  A.K.A the cbang library.

              Copyright (c) 2003-2014, Cauldron Development LLC
                 Copyright (c) 2003-2014, Stanford University
                             All rights reserved.

        The C! library 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 2.1 of
        the License, or (at your option) any later version.

        The C! library 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 for more details.

        You should have received a copy of the GNU Lesser General Public
        License along with the C! library.  If not, see
        <http://www.gnu.org/licenses/>.

        In addition, BSD licensing may be granted on a case by case basis
        by written permission from at least one of the copyright holders.
        You may request written permission by emailing the authors.

                For information regarding this software email:
                               Joseph Coffland
                        joseph@cauldrondevelopment.com

\******************************************************************************/

#include "Version.h"

#include <cbang/Exception.h>
#include <cbang/String.h>

#include <vector>

using namespace std;
using namespace cb;

namespace {
  uint8_t parseVersionPart(const std::string &part) {
    if (part.empty()) THROW("Invalid version string, part is empty");
    if (part.find_first_not_of("0") == string::npos) return 0;
    return String::parseU8(String::trimLeft(part, "0"));
  }
}

Version::Version(const string &s) {
  if (s.find_first_not_of("1234567890. ") != string::npos)
    THROWS("Invalid character in version string: " << s);

  vector<string> parts;
  String::tokenize(s, parts, ".");

  switch (parts.size()) {
  case 1: *this = Version(String::parseU32(parts[0])); break;

  case 2:
    getMajor() = parseVersionPart(parts[0]);
    getMinor() = parseVersionPart(parts[1]);
    break;

  case 3:
    getMajor() = parseVersionPart(parts[0]);
    getMinor() = parseVersionPart(parts[1]);
    getRevision() = parseVersionPart(parts[2]);
    break;

  default: THROWS("Error parsing version string: " << s);
  }
}

int Version::compare(const Version &v) const {
  if (getMajor() != v.getMajor()) return getMajor() - v.getMajor();
  if (getMinor() != v.getMinor()) return getMinor() - v.getMinor();
  return getRevision() - v.getRevision();
}
<commit_msg>Revised Version parsing<commit_after>/******************************************************************************\

          This file is part of the C! library.  A.K.A the cbang library.

              Copyright (c) 2003-2014, Cauldron Development LLC
                 Copyright (c) 2003-2014, Stanford University
                             All rights reserved.

        The C! library 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 2.1 of
        the License, or (at your option) any later version.

        The C! library 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 for more details.

        You should have received a copy of the GNU Lesser General Public
        License along with the C! library.  If not, see
        <http://www.gnu.org/licenses/>.

        In addition, BSD licensing may be granted on a case by case basis
        by written permission from at least one of the copyright holders.
        You may request written permission by emailing the authors.

                For information regarding this software email:
                               Joseph Coffland
                        joseph@cauldrondevelopment.com

\******************************************************************************/

#include "Version.h"

#include <cbang/Exception.h>
#include <cbang/String.h>

#include <vector>

using namespace std;
using namespace cb;

namespace {
  uint8_t parseVersionPart(const std::string &part) {
    if (part.empty()) THROW("Invalid version string, part is empty");
    if (part.find_first_not_of("0") == string::npos) return 0;
    return String::parseU8(String::trimLeft(part, "0"));
  }
}

Version::Version(const string &s) {
  if (s.find_first_not_of("1234567890. ") != string::npos)
    THROWS("Invalid character in version string: " << s);

  vector<string> parts;
  String::tokenize(s, parts, ".");

  if (parts.empty() || 3 < parts.size())
    THROWS("Error parsing version string: '" << s << "'");

  getMajor() = parseVersionPart(parts[0]);
  if (1 < parts.size()) getMinor() = parseVersionPart(parts[1]);
  if (2 < parts.size()) getRevision() = parseVersionPart(parts[2]);
}

int Version::compare(const Version &v) const {
  if (getMajor() != v.getMajor()) return getMajor() - v.getMajor();
  if (getMinor() != v.getMinor()) return getMinor() - v.getMinor();
  return getRevision() - v.getRevision();
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 The Brave Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "atom/browser/importer/profile_writer.h"

#include <memory>
#include <set>
#include <string>
#include <utility>

#include "atom/browser/api/atom_api_app.h"
#include "atom/browser/api/atom_api_importer.h"
#include "atom/common/native_mate_converters/string16_converter.h"
#include "atom/common/native_mate_converters/value_converter.h"
#include "base/base64.h"
#include "base/strings/utf_string_conversions.h"
#include "brave/common/importer/imported_cookie_entry.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process_impl.h"
#include "chrome/browser/password_manager/password_store_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/common/importer/imported_bookmark_entry.h"
#include "components/autofill/core/browser/webdata/autofill_entry.h"
#include "components/autofill/core/common/password_form.h"
#include "components/keyed_service/core/service_access_type.h"
#include "components/password_manager/core/browser/password_manager.h"
#include "content/public/browser/browser_thread.h"

#if defined(OS_WIN)
#include "components/password_manager/core/browser/webdata/password_web_data_service_win.h"
#endif

namespace importer {
void ShowImportLockDialog(gfx::NativeWindow parent,
                          const base::Callback<void(bool)>& callback) {
  atom::api::App *app =
    static_cast<BrowserProcessImpl*>(g_browser_process)->app();
  if (app) {
    app->Emit("show-warning-dialog");
  }
  // TODO(darkdh): emit callback and let users have continue option without
  // restart anotehr import process
  content::BrowserThread::PostTask(
      content::BrowserThread::UI, FROM_HERE, base::Bind(callback, false));
}
}  // namespace importer

namespace atom {

ProfileWriter::ProfileWriter(Profile* profile) :
    ::ProfileWriter(profile),
    importer_(nullptr) {}

bool ProfileWriter::BookmarkModelIsLoaded() const {
  return true;
}

bool ProfileWriter::TemplateURLServiceIsLoaded() const {
  return true;
}

void ProfileWriter::AddPasswordForm(const autofill::PasswordForm& form) {
    Profile* active_profile = ProfileManager::GetActiveUserProfile();
    if (active_profile) {
      PasswordStoreFactory::GetForProfile(
          active_profile, ServiceAccessType::EXPLICIT_ACCESS)->AddLogin(form);
    }
}

#if defined(OS_WIN)
void ProfileWriter::AddIE7PasswordInfo(const IE7PasswordInfo& info) {
}
#endif

void ProfileWriter::AddHistoryPage(const history::URLRows& page,
                                   history::VisitSource visit_source) {
  if (importer_) {
    base::ListValue history_list;
    for (const history::URLRow& row : page) {
      base::DictionaryValue* history = new base::DictionaryValue();
      history->SetString("title", row.title());
      history->SetString("url", row.url().possibly_invalid_spec());
      history->SetInteger("visit_count", row.visit_count());
      history->SetInteger("last_visit", row.last_visit().ToDoubleT());
      history_list.Append(std::unique_ptr<base::DictionaryValue>(history));
    }
    importer_->Emit("add-history-page", history_list,
                    (unsigned int) visit_source);
  }
}

void ProfileWriter::AddHomepage(const GURL& home_page) {
  if (importer_) {
    importer_->Emit("add-homepage", home_page.possibly_invalid_spec());
  }
}

void ProfileWriter::AddBookmarks(
    const std::vector<ImportedBookmarkEntry>& bookmarks,
    const base::string16& top_level_folder_name) {
  if (bookmarks.empty())
    return;

  if (importer_) {
    base::ListValue imported_bookmarks;
    for (const ImportedBookmarkEntry& bookmark : bookmarks) {
      base::DictionaryValue* imported_bookmark = new base::DictionaryValue();
      imported_bookmark->SetBoolean("in_toolbar", bookmark.in_toolbar);
      imported_bookmark->SetBoolean("is_folder", bookmark.is_folder);
      imported_bookmark->SetString("url", bookmark.url.possibly_invalid_spec());
      imported_bookmark->SetString("title", bookmark.title);
      imported_bookmark->SetInteger("creation_time",
                                    bookmark.creation_time.ToDoubleT());
      auto paths = base::MakeUnique<base::ListValue>();
      for (const base::string16& path : bookmark.path) {
        paths->AppendString(path);
      }
      imported_bookmark->Set("path", std::move(paths));
      imported_bookmarks.Append(std::unique_ptr<base::DictionaryValue>(
                                    imported_bookmark));
    }
    importer_->Emit("add-bookmarks", imported_bookmarks, top_level_folder_name);
  }
}

void ProfileWriter::AddFavicons(
    const favicon_base::FaviconUsageDataList& favicons) {
  if (importer_) {
    base::ListValue imported_favicons;
    for (const favicon_base::FaviconUsageData& favicon : favicons) {
      base::DictionaryValue* imported_favicon = new base::DictionaryValue();
      imported_favicon->SetString("favicon_url",
                                  favicon.favicon_url.possibly_invalid_spec());
      std::string data_url;
      data_url.insert(data_url.end(), favicon.png_data.begin(),
                      favicon.png_data.end());
      base::Base64Encode(data_url, &data_url);
      data_url.insert(0, "data:image/png;base64,");
      imported_favicon->SetString("png_data", data_url);
      std::set<GURL>::iterator it;
      auto urls = base::MakeUnique<base::ListValue>();
      for (it = favicon.urls.begin(); it != favicon.urls.end(); ++it) {
        urls->AppendString(it->possibly_invalid_spec());
      }
      imported_favicon->Set("urls", std::move(urls));
      imported_favicons.Append(std::unique_ptr<base::DictionaryValue>(
                                  imported_favicon));
    }
    importer_->Emit("add-favicons", imported_favicons);
  }
}

void ProfileWriter::AddAutofillFormDataEntries(
    const std::vector<autofill::AutofillEntry>& autofill_entries) {
  if (importer_) {
    base::ListValue imported_autofill_entries;
    for (const autofill::AutofillEntry& autofill_entry : autofill_entries) {
      base::DictionaryValue* imported_autofill_entry =
        new base::DictionaryValue();
      imported_autofill_entry->SetString("name", autofill_entry.key().name());
      imported_autofill_entry->SetString("value", autofill_entry.key().value());
      imported_autofill_entries.Append(std::unique_ptr<base::DictionaryValue>(
                                          imported_autofill_entry));
    }
    importer_->Emit("add-autofill-form-data-entries",
                    imported_autofill_entries);
  }
}

void ProfileWriter::AddCookies(
    const std::vector<ImportedCookieEntry>& cookies) {
  if (importer_) {
    base::ListValue imported_cookies;
    for (const ImportedCookieEntry& cookie_entry : cookies) {
      base::DictionaryValue* cookie = new base::DictionaryValue();
      base::string16 url;
      if (cookie_entry.httponly) {
        url.append(base::UTF8ToUTF16("http://"));
        url.append(cookie_entry.host);
      } else {
        url.append(base::UTF8ToUTF16("https://"));
        url.append(cookie_entry.host);
      }
      cookie->SetString("url", url);
      cookie->SetString("domain", cookie_entry.domain);
      cookie->SetString("name", cookie_entry.name);
      cookie->SetString("value", cookie_entry.value);
      cookie->SetString("path", cookie_entry.path);
      cookie->SetInteger("expiry_date", cookie_entry.expiry_date.ToDoubleT());
      cookie->SetBoolean("secure", cookie_entry.secure);
      cookie->SetBoolean("httponly", cookie_entry.httponly);
      imported_cookies.Append(std::unique_ptr<base::DictionaryValue>(cookie));
    }
    importer_->Emit("add-cookies", imported_cookies);
  }
}

void ProfileWriter::Initialize(atom::api::Importer* importer) {
  importer_ = importer;
}

ProfileWriter::~ProfileWriter() {}

}  // namespace atom
<commit_msg>Fix secure cookies using http url<commit_after>// Copyright (c) 2017 The Brave Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "atom/browser/importer/profile_writer.h"

#include <memory>
#include <set>
#include <string>
#include <utility>

#include "atom/browser/api/atom_api_app.h"
#include "atom/browser/api/atom_api_importer.h"
#include "atom/common/native_mate_converters/string16_converter.h"
#include "atom/common/native_mate_converters/value_converter.h"
#include "base/base64.h"
#include "base/strings/utf_string_conversions.h"
#include "brave/common/importer/imported_cookie_entry.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process_impl.h"
#include "chrome/browser/password_manager/password_store_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/common/importer/imported_bookmark_entry.h"
#include "components/autofill/core/browser/webdata/autofill_entry.h"
#include "components/autofill/core/common/password_form.h"
#include "components/keyed_service/core/service_access_type.h"
#include "components/password_manager/core/browser/password_manager.h"
#include "content/public/browser/browser_thread.h"

#if defined(OS_WIN)
#include "components/password_manager/core/browser/webdata/password_web_data_service_win.h"
#endif

namespace importer {
void ShowImportLockDialog(gfx::NativeWindow parent,
                          const base::Callback<void(bool)>& callback) {
  atom::api::App *app =
    static_cast<BrowserProcessImpl*>(g_browser_process)->app();
  if (app) {
    app->Emit("show-warning-dialog");
  }
  // TODO(darkdh): emit callback and let users have continue option without
  // restart anotehr import process
  content::BrowserThread::PostTask(
      content::BrowserThread::UI, FROM_HERE, base::Bind(callback, false));
}
}  // namespace importer

namespace atom {

ProfileWriter::ProfileWriter(Profile* profile) :
    ::ProfileWriter(profile),
    importer_(nullptr) {}

bool ProfileWriter::BookmarkModelIsLoaded() const {
  return true;
}

bool ProfileWriter::TemplateURLServiceIsLoaded() const {
  return true;
}

void ProfileWriter::AddPasswordForm(const autofill::PasswordForm& form) {
    Profile* active_profile = ProfileManager::GetActiveUserProfile();
    if (active_profile) {
      PasswordStoreFactory::GetForProfile(
          active_profile, ServiceAccessType::EXPLICIT_ACCESS)->AddLogin(form);
    }
}

#if defined(OS_WIN)
void ProfileWriter::AddIE7PasswordInfo(const IE7PasswordInfo& info) {
}
#endif

void ProfileWriter::AddHistoryPage(const history::URLRows& page,
                                   history::VisitSource visit_source) {
  if (importer_) {
    base::ListValue history_list;
    for (const history::URLRow& row : page) {
      base::DictionaryValue* history = new base::DictionaryValue();
      history->SetString("title", row.title());
      history->SetString("url", row.url().possibly_invalid_spec());
      history->SetInteger("visit_count", row.visit_count());
      history->SetInteger("last_visit", row.last_visit().ToDoubleT());
      history_list.Append(std::unique_ptr<base::DictionaryValue>(history));
    }
    importer_->Emit("add-history-page", history_list,
                    (unsigned int) visit_source);
  }
}

void ProfileWriter::AddHomepage(const GURL& home_page) {
  if (importer_) {
    importer_->Emit("add-homepage", home_page.possibly_invalid_spec());
  }
}

void ProfileWriter::AddBookmarks(
    const std::vector<ImportedBookmarkEntry>& bookmarks,
    const base::string16& top_level_folder_name) {
  if (bookmarks.empty())
    return;

  if (importer_) {
    base::ListValue imported_bookmarks;
    for (const ImportedBookmarkEntry& bookmark : bookmarks) {
      base::DictionaryValue* imported_bookmark = new base::DictionaryValue();
      imported_bookmark->SetBoolean("in_toolbar", bookmark.in_toolbar);
      imported_bookmark->SetBoolean("is_folder", bookmark.is_folder);
      imported_bookmark->SetString("url", bookmark.url.possibly_invalid_spec());
      imported_bookmark->SetString("title", bookmark.title);
      imported_bookmark->SetInteger("creation_time",
                                    bookmark.creation_time.ToDoubleT());
      auto paths = base::MakeUnique<base::ListValue>();
      for (const base::string16& path : bookmark.path) {
        paths->AppendString(path);
      }
      imported_bookmark->Set("path", std::move(paths));
      imported_bookmarks.Append(std::unique_ptr<base::DictionaryValue>(
                                    imported_bookmark));
    }
    importer_->Emit("add-bookmarks", imported_bookmarks, top_level_folder_name);
  }
}

void ProfileWriter::AddFavicons(
    const favicon_base::FaviconUsageDataList& favicons) {
  if (importer_) {
    base::ListValue imported_favicons;
    for (const favicon_base::FaviconUsageData& favicon : favicons) {
      base::DictionaryValue* imported_favicon = new base::DictionaryValue();
      imported_favicon->SetString("favicon_url",
                                  favicon.favicon_url.possibly_invalid_spec());
      std::string data_url;
      data_url.insert(data_url.end(), favicon.png_data.begin(),
                      favicon.png_data.end());
      base::Base64Encode(data_url, &data_url);
      data_url.insert(0, "data:image/png;base64,");
      imported_favicon->SetString("png_data", data_url);
      std::set<GURL>::iterator it;
      auto urls = base::MakeUnique<base::ListValue>();
      for (it = favicon.urls.begin(); it != favicon.urls.end(); ++it) {
        urls->AppendString(it->possibly_invalid_spec());
      }
      imported_favicon->Set("urls", std::move(urls));
      imported_favicons.Append(std::unique_ptr<base::DictionaryValue>(
                                  imported_favicon));
    }
    importer_->Emit("add-favicons", imported_favicons);
  }
}

void ProfileWriter::AddAutofillFormDataEntries(
    const std::vector<autofill::AutofillEntry>& autofill_entries) {
  if (importer_) {
    base::ListValue imported_autofill_entries;
    for (const autofill::AutofillEntry& autofill_entry : autofill_entries) {
      base::DictionaryValue* imported_autofill_entry =
        new base::DictionaryValue();
      imported_autofill_entry->SetString("name", autofill_entry.key().name());
      imported_autofill_entry->SetString("value", autofill_entry.key().value());
      imported_autofill_entries.Append(std::unique_ptr<base::DictionaryValue>(
                                          imported_autofill_entry));
    }
    importer_->Emit("add-autofill-form-data-entries",
                    imported_autofill_entries);
  }
}

void ProfileWriter::AddCookies(
    const std::vector<ImportedCookieEntry>& cookies) {
  if (importer_) {
    base::ListValue imported_cookies;
    for (const ImportedCookieEntry& cookie_entry : cookies) {
      base::DictionaryValue* cookie = new base::DictionaryValue();
      base::string16 url;
      if (cookie_entry.secure) {
        url.append(base::UTF8ToUTF16("https://"));
        url.append(cookie_entry.host);
      } else {
        url.append(base::UTF8ToUTF16("http://"));
        url.append(cookie_entry.host);
      }
      cookie->SetString("url", url);
      cookie->SetString("domain", cookie_entry.domain);
      cookie->SetString("name", cookie_entry.name);
      cookie->SetString("value", cookie_entry.value);
      cookie->SetString("path", cookie_entry.path);
      cookie->SetInteger("expiry_date", cookie_entry.expiry_date.ToDoubleT());
      cookie->SetBoolean("secure", cookie_entry.secure);
      cookie->SetBoolean("httponly", cookie_entry.httponly);
      imported_cookies.Append(std::unique_ptr<base::DictionaryValue>(cookie));
    }
    importer_->Emit("add-cookies", imported_cookies);
  }
}

void ProfileWriter::Initialize(atom::api::Importer* importer) {
  importer_ = importer;
}

ProfileWriter::~ProfileWriter() {}

}  // namespace atom
<|endoftext|>


<commit_before>// Copyright 2019 Google LLC
//
// 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
//
//     https://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.

#include "dap/any.h"
#include "dap/typeof.h"
#include "dap/types.h"

#include "gmock/gmock.h"
#include "gtest/gtest.h"

namespace dap {

struct AnyTestObject {
  dap::integer i;
  dap::number n;
};

DAP_STRUCT_TYPEINFO(AnyTestObject,
                    "AnyTestObject",
                    DAP_FIELD(i, "i"),
                    DAP_FIELD(n, "n"));

}  // namespace dap

TEST(Any, EmptyConstruct) {
  dap::any any;
  ASSERT_TRUE(any.is<dap::null>());
  ASSERT_FALSE(any.is<dap::boolean>());
  ASSERT_FALSE(any.is<dap::integer>());
  ASSERT_FALSE(any.is<dap::number>());
  ASSERT_FALSE(any.is<dap::object>());
  ASSERT_FALSE(any.is<dap::string>());
  ASSERT_FALSE(any.is<dap::array<dap::integer>>());
  ASSERT_FALSE(any.is<dap::AnyTestObject>());
}

TEST(Any, Boolean) {
  dap::any any(dap::boolean(true));
  ASSERT_TRUE(any.is<dap::boolean>());
  ASSERT_EQ(any.get<dap::boolean>(), dap::boolean(true));
}

TEST(Any, Integer) {
  dap::any any(dap::integer(10));
  ASSERT_TRUE(any.is<dap::integer>());
  ASSERT_EQ(any.get<dap::integer>(), dap::integer(10));
}

TEST(Any, Number) {
  dap::any any(dap::number(123.0f));
  ASSERT_TRUE(any.is<dap::number>());
  ASSERT_EQ(any.get<dap::number>(), dap::number(123.0f));
}

TEST(Any, String) {
  dap::any any(dap::string("hello world"));
  ASSERT_TRUE(any.is<dap::string>());
  ASSERT_EQ(any.get<dap::string>(), dap::string("hello world"));
}

TEST(Any, Array) {
  using array = dap::array<dap::integer>;
  dap::any any(array({10, 20, 30}));
  ASSERT_TRUE(any.is<array>());
  ASSERT_EQ(any.get<array>(), array({10, 20, 30}));
}

TEST(Any, Object) {
  dap::object o;
  o["one"] = dap::integer(1);
  o["two"] = dap::integer(2);
  o["three"] = dap::integer(3);
  dap::any any(o);
  ASSERT_TRUE(any.is<dap::object>());
  if (any.is<dap::object>()) {
    auto got = any.get<dap::object>();
    ASSERT_EQ(got.size(), 3U);
    ASSERT_EQ(got.count("one"), 1U);
    ASSERT_EQ(got.count("two"), 1U);
    ASSERT_EQ(got.count("three"), 1U);
    ASSERT_TRUE(got["one"].is<dap::integer>());
    ASSERT_TRUE(got["two"].is<dap::integer>());
    ASSERT_TRUE(got["three"].is<dap::integer>());
    ASSERT_EQ(got["one"].get<dap::integer>(), dap::integer(1));
    ASSERT_EQ(got["two"].get<dap::integer>(), dap::integer(2));
    ASSERT_EQ(got["three"].get<dap::integer>(), dap::integer(3));
  }
}

TEST(Any, TestObject) {
  dap::any any(dap::AnyTestObject{5, 3.0});
  ASSERT_TRUE(any.is<dap::AnyTestObject>());
  ASSERT_EQ(any.get<dap::AnyTestObject>().i, 5);
  ASSERT_EQ(any.get<dap::AnyTestObject>().n, 3.0);
}

TEST(Any, Assign) {
  dap::any any;
  any = dap::integer(10);
  ASSERT_TRUE(any.is<dap::integer>());
  ASSERT_FALSE(any.is<dap::boolean>());
  ASSERT_FALSE(any.is<dap::AnyTestObject>());
  ASSERT_EQ(any.get<dap::integer>(), dap::integer(10));
  any = dap::boolean(true);
  ASSERT_FALSE(any.is<dap::integer>());
  ASSERT_TRUE(any.is<dap::boolean>());
  ASSERT_FALSE(any.is<dap::AnyTestObject>());
  ASSERT_EQ(any.get<dap::boolean>(), dap::boolean(true));
  any = dap::AnyTestObject{5, 3.0};
  ASSERT_FALSE(any.is<dap::integer>());
  ASSERT_FALSE(any.is<dap::boolean>());
  ASSERT_TRUE(any.is<dap::AnyTestObject>());
  ASSERT_EQ(any.get<dap::AnyTestObject>().i, 5);
  ASSERT_EQ(any.get<dap::AnyTestObject>().n, 3.0);
  any = dap::string("hello world");
  ASSERT_FALSE(any.is<dap::integer>());
  ASSERT_FALSE(any.is<dap::boolean>());
  ASSERT_FALSE(any.is<dap::AnyTestObject>());
  ASSERT_TRUE(any.is<dap::string>());
  ASSERT_EQ(any.get<dap::string>(), dap::string("hello world"));
}

TEST(Any, Reset) {
  dap::any any(dap::integer(10));
  ASSERT_TRUE(any.is<dap::integer>());
  any.reset();
  ASSERT_FALSE(any.is<dap::integer>());
}
<commit_msg>Add lots more tests for dap::any.<commit_after>// Copyright 2019 Google LLC
//
// 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
//
//     https://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.

#include "dap/any.h"
#include "dap/typeof.h"
#include "dap/types.h"

#include "gmock/gmock.h"
#include "gtest/gtest.h"

namespace dap {

struct AnyTestObject {
  dap::integer i;
  dap::number n;
};

DAP_STRUCT_TYPEINFO(AnyTestObject,
                    "AnyTestObject",
                    DAP_FIELD(i, "i"),
                    DAP_FIELD(n, "n"));

inline bool operator==(const AnyTestObject& a, const AnyTestObject& b) {
  return a.i == b.i && a.n == b.n;
}

}  // namespace dap

namespace {

template <typename T>
struct TestValue {};

template <>
struct TestValue<dap::integer> {
  static const dap::integer value;
};
template <>
struct TestValue<dap::boolean> {
  static const dap::boolean value;
};
template <>
struct TestValue<dap::number> {
  static const dap::number value;
};
template <>
struct TestValue<dap::string> {
  static const dap::string value;
};
template <>
struct TestValue<dap::array<dap::string>> {
  static const dap::array<dap::string> value;
};
template <>
struct TestValue<dap::AnyTestObject> {
  static const dap::AnyTestObject value;
};

const dap::integer TestValue<dap::integer>::value = 20;
const dap::boolean TestValue<dap::boolean>::value = true;
const dap::number TestValue<dap::number>::value = 123.45;
const dap::string TestValue<dap::string>::value = "hello world";
const dap::array<dap::string> TestValue<dap::array<dap::string>>::value = {
    "one", "two", "three"};
const dap::AnyTestObject TestValue<dap::AnyTestObject>::value = {10, 20.30};

}  // namespace

TEST(Any, EmptyConstruct) {
  dap::any any;
  ASSERT_TRUE(any.is<dap::null>());
  ASSERT_FALSE(any.is<dap::boolean>());
  ASSERT_FALSE(any.is<dap::integer>());
  ASSERT_FALSE(any.is<dap::number>());
  ASSERT_FALSE(any.is<dap::object>());
  ASSERT_FALSE(any.is<dap::string>());
  ASSERT_FALSE(any.is<dap::array<dap::integer>>());
  ASSERT_FALSE(any.is<dap::AnyTestObject>());
}

TEST(Any, Boolean) {
  dap::any any(dap::boolean(true));
  ASSERT_TRUE(any.is<dap::boolean>());
  ASSERT_EQ(any.get<dap::boolean>(), dap::boolean(true));
}

TEST(Any, Integer) {
  dap::any any(dap::integer(10));
  ASSERT_TRUE(any.is<dap::integer>());
  ASSERT_EQ(any.get<dap::integer>(), dap::integer(10));
}

TEST(Any, Number) {
  dap::any any(dap::number(123.0f));
  ASSERT_TRUE(any.is<dap::number>());
  ASSERT_EQ(any.get<dap::number>(), dap::number(123.0f));
}

TEST(Any, String) {
  dap::any any(dap::string("hello world"));
  ASSERT_TRUE(any.is<dap::string>());
  ASSERT_EQ(any.get<dap::string>(), dap::string("hello world"));
}

TEST(Any, Array) {
  using array = dap::array<dap::integer>;
  dap::any any(array({10, 20, 30}));
  ASSERT_TRUE(any.is<array>());
  ASSERT_EQ(any.get<array>(), array({10, 20, 30}));
}

TEST(Any, Object) {
  dap::object o;
  o["one"] = dap::integer(1);
  o["two"] = dap::integer(2);
  o["three"] = dap::integer(3);
  dap::any any(o);
  ASSERT_TRUE(any.is<dap::object>());
  if (any.is<dap::object>()) {
    auto got = any.get<dap::object>();
    ASSERT_EQ(got.size(), 3U);
    ASSERT_EQ(got.count("one"), 1U);
    ASSERT_EQ(got.count("two"), 1U);
    ASSERT_EQ(got.count("three"), 1U);
    ASSERT_TRUE(got["one"].is<dap::integer>());
    ASSERT_TRUE(got["two"].is<dap::integer>());
    ASSERT_TRUE(got["three"].is<dap::integer>());
    ASSERT_EQ(got["one"].get<dap::integer>(), dap::integer(1));
    ASSERT_EQ(got["two"].get<dap::integer>(), dap::integer(2));
    ASSERT_EQ(got["three"].get<dap::integer>(), dap::integer(3));
  }
}

TEST(Any, TestObject) {
  dap::any any(dap::AnyTestObject{5, 3.0});
  ASSERT_TRUE(any.is<dap::AnyTestObject>());
  ASSERT_EQ(any.get<dap::AnyTestObject>().i, 5);
  ASSERT_EQ(any.get<dap::AnyTestObject>().n, 3.0);
}

template <typename T>
class AnyT : public ::testing::Test {
 protected:
  void check(const dap::any& any, const T& expect) {
    ASSERT_EQ(any.is<dap::integer>(), (std::is_same<T, dap::integer>::value));
    ASSERT_EQ(any.is<dap::boolean>(), (std::is_same<T, dap::boolean>::value));
    ASSERT_EQ(any.is<dap::number>(), (std::is_same<T, dap::number>::value));
    ASSERT_EQ(any.is<dap::string>(), (std::is_same<T, dap::string>::value));
    ASSERT_EQ(any.is<dap::array<dap::string>>(),
              (std::is_same<T, dap::array<dap::string>>::value));
    ASSERT_EQ(any.is<dap::AnyTestObject>(),
              (std::is_same<T, dap::AnyTestObject>::value));

    ASSERT_EQ(any.get<T>(), expect);
  }
};
TYPED_TEST_SUITE_P(AnyT);

TYPED_TEST_P(AnyT, CopyConstruct) {
  auto val = TestValue<TypeParam>::value;
  dap::any any(val);
  this->check(any, val);
}

TYPED_TEST_P(AnyT, MoveConstruct) {
  auto val = TestValue<TypeParam>::value;
  dap::any any(std::move(val));
  this->check(any, val);
}

TYPED_TEST_P(AnyT, Assign) {
  auto val = TestValue<TypeParam>::value;
  dap::any any;
  any = val;
  this->check(any, val);
}

TYPED_TEST_P(AnyT, MoveAssign) {
  auto val = TestValue<TypeParam>::value;
  dap::any any;
  any = std::move(val);
  this->check(any, val);
}

TYPED_TEST_P(AnyT, RepeatedAssign) {
  dap::string str = "hello world";
  auto val = TestValue<TypeParam>::value;
  dap::any any;
  any = str;
  any = val;
  this->check(any, val);
}

TYPED_TEST_P(AnyT, RepeatedMoveAssign) {
  dap::string str = "hello world";
  auto val = TestValue<TypeParam>::value;
  dap::any any;
  any = std::move(str);
  any = std::move(val);
  this->check(any, val);
}

REGISTER_TYPED_TEST_SUITE_P(AnyT,
                            CopyConstruct,
                            MoveConstruct,
                            Assign,
                            MoveAssign,
                            RepeatedAssign,
                            RepeatedMoveAssign);

using AnyTypes = ::testing::Types<dap::integer,
                                  dap::boolean,
                                  dap::number,
                                  dap::string,
                                  dap::array<dap::string>,
                                  dap::AnyTestObject>;
INSTANTIATE_TYPED_TEST_SUITE_P(T, AnyT, AnyTypes);

TEST(Any, Reset) {
  dap::any any(dap::integer(10));
  ASSERT_TRUE(any.is<dap::integer>());
  any.reset();
  ASSERT_FALSE(any.is<dap::integer>());
}
<|endoftext|>


<commit_before>//-----------------------------------------------------------------------bl-
//--------------------------------------------------------------------------
//
// Planet - An atmospheric code for planetary bodies, adapted to Titan
//
// Copyright (C) 2013 The PECOS Development Team
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the Version 2.1 GNU Lesser General
// Public License as published by the Free Software Foundation.
//
// This library 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 for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc. 51 Franklin Street, Fifth Floor,
// Boston, MA  02110-1301  USA
//
//-----------------------------------------------------------------------el-

//Antioch
#include "antioch/vector_utils_decl.h"
#include "antioch/physical_constants.h"
#include "antioch/sigma_bin_converter.h"
#include "antioch/vector_utils.h"

//Planet
#include "planet/eddy_diffusion_evaluator.h"
#include "planet/planet_constants.h"

//C++
#include <vector>
#include <iostream>
#include <fstream>
#include <string>
#include <cmath>
#include <limits>

template<typename Scalar>
int check_test(Scalar theory, Scalar cal, const std::string &words)
{
  Scalar coeff = (std::numeric_limits<Scalar>::epsilon() > 1e-18L)?100.L:1000.L;
  const Scalar tol = std::numeric_limits<Scalar>::epsilon() * coeff;
  if(std::abs((theory-cal)/theory) < tol)return 0;
  std::cout << std::scientific << std::setprecision(20)
            << "failed test: " << words << "\n"
            << "theory: " << theory
            << "\ncalculated: " << cal
            << "\ndifference: " << std::abs((theory-cal)/cal)
            << "\ntolerance: " << tol << std::endl;
  return 1;
}

template<typename Scalar, typename VectorScalar = std::vector<Scalar> >
void read_temperature(VectorScalar &T0, VectorScalar &Tz, const std::string &file)
{
  T0.clear();
  Tz.clear();
  std::string line;
  std::ifstream temp(file);
  getline(temp,line);
  while(!temp.eof())
  {
     Scalar t,tz;
     temp >> t >> tz;
     if(temp.good())
     {
       T0.push_back(t);
       Tz.push_back(tz);
     }
  }
  temp.close();
  return;
}

template<typename Scalar>
Scalar barometry(const Scalar &zmin, const Scalar &z, const Scalar &T, const Scalar &Mm, const Scalar &botdens)
{
   return botdens * Antioch::ant_exp(-(z - zmin)/((Planet::Constants::Titan::radius<Scalar>() + z) * (Planet::Constants::Titan::radius<Scalar>() + zmin) * 1e3 *
                                             Antioch::Constants::Avogadro<Scalar>() * Planet::Constants::Universal::kb<Scalar>() * T /
                                                        (Planet::Constants::Universal::G<Scalar>() * Planet::Constants::Titan::mass<Scalar>() * Mm))
                              );
}

template <typename Scalar>
int tester(const std::string &input_T)
{
//description
  std::vector<std::string> neutrals;
  std::vector<std::string> ions;
  neutrals.push_back("N2");
  neutrals.push_back("CH4");
//ionic system contains neutral system
  ions = neutrals;
  ions.push_back("N2+");
  Scalar MN(14.008L), MC(12.011), MH(1.008L);
  Scalar MN2 = 2.L*MN , MCH4 = MC + 4.L*MH;
  std::vector<Scalar> Mm;
  Mm.push_back(MN2);
  Mm.push_back(MCH4);

//densities
  std::vector<Scalar> molar_frac;
  molar_frac.push_back(0.96L);
  molar_frac.push_back(0.04L);
  molar_frac.push_back(0.L);
  Scalar dens_tot(1e12L);

//hard sphere radius
  std::vector<Scalar> hard_sphere_radius;
  hard_sphere_radius.push_back(2.0675e-8L * 1e-2L); //N2  in cm -> m
  hard_sphere_radius.push_back(2.3482e-8L * 1e-2L); //CH4 in cm -> m

//zenith angle
//not needed

//photon flux
//not needed

////cross-section
//not needed

//altitudes
  Scalar zmin(600.L),zmax(1400.L),zstep(10.L);

//eddy
  Scalar K0(4.3e6L);//

/************************
 * first level
 ************************/

//neutrals
  Antioch::ChemicalMixture<Scalar> neutral_species(neutrals);

//ions
  Antioch::ChemicalMixture<Scalar> ionic_species(ions);

//chapman
//not needed

//binary diffusion
//not needed

/************************
 * second level
 ************************/

//temperature
  std::vector<Scalar> T0,Tz;
  read_temperature<Scalar>(T0,Tz,input_T);
  Planet::AtmosphericTemperature<Scalar, std::vector<Scalar> > temperature(Tz, T0);

//photon opacity
//not needed

//reaction sets
//not needed

/************************
 * third level
 ************************/

//atmospheric mixture
  Planet::AtmosphericMixture<Scalar,std::vector<Scalar>, std::vector<std::vector<Scalar> > > composition(neutral_species, ionic_species, temperature);
  composition.init_composition(molar_frac,dens_tot,zmin,zmax);

//kinetics evaluators
//not needed

/************************
 * fourth level
 ************************/

//photon evaluator
//not needed

//molecular diffusion
//not needed

//eddy diffusion
  Planet::EddyDiffusionEvaluator<Scalar,std::vector<Scalar>, std::vector<std::vector<Scalar> > > eddy_diff(composition,K0);

/************************
 * checks
 ************************/
  molar_frac.pop_back();

  Scalar mean_M;
  Antioch::set_zero(mean_M);
  for(unsigned int s = 0; s < molar_frac.size(); s++)
  {
    mean_M += molar_frac[s] * Mm[s];
  }
  mean_M *= 1e-3;//to kg

  int return_flag(0);

  for(Scalar z = zmin; z <= zmax; z += zstep)
  {
     Scalar nTot = barometry(zmin,z,temperature.neutral_temperature(z),mean_M,dens_tot);
     Scalar K = K0 * Antioch::ant_sqrt(dens_tot/nTot);
     return_flag = return_flag ||
                   check_test(K, eddy_diff.K(nTot), "eddy diffusion at altitude");
  }

  return return_flag;
}

int main(int argc, char** argv)
{
  // Check command line count.
  if( argc < 2 )
    {
      // TODO: Need more consistent error handling.
      std::cerr << "Error: Must specify input file." << std::endl;
      antioch_error();
    }

  return (tester<float>(std::string(argv[1])) ||
          tester<double>(std::string(argv[1])) ||
          tester<long double>(std::string(argv[1])));
}
<commit_msg>golden values and derivative<commit_after>//-----------------------------------------------------------------------bl-
//--------------------------------------------------------------------------
//
// Planet - An atmospheric code for planetary bodies, adapted to Titan
//
// Copyright (C) 2013 The PECOS Development Team
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the Version 2.1 GNU Lesser General
// Public License as published by the Free Software Foundation.
//
// This library 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 for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc. 51 Franklin Street, Fifth Floor,
// Boston, MA  02110-1301  USA
//
//-----------------------------------------------------------------------el-

//Antioch
#include "antioch/vector_utils_decl.h"
#include "antioch/physical_constants.h"
#include "antioch/sigma_bin_converter.h"
#include "antioch/vector_utils.h"

//Planet
#include "planet/eddy_diffusion_evaluator.h"
#include "planet/planet_constants.h"

//C++
#include <vector>
#include <iostream>
#include <fstream>
#include <string>
#include <cmath>
#include <limits>

template<typename Scalar>
int check_test(Scalar theory, Scalar cal, const std::string &words)
{
  Scalar coeff = (std::numeric_limits<Scalar>::epsilon() > 1e-18L)?10.L:20.L;
  const Scalar tol = std::numeric_limits<Scalar>::epsilon() * coeff;

  Scalar dist = (std::abs(theory) < tol)?std::abs(cal - theory):
                                         std::abs((theory-cal)/theory);

  if(dist < tol)return 0;
  std::cout << std::scientific << std::setprecision(20)
            << "failed test: " << words << "\n"
            << "theory: " << theory
            << "\ncalculated: " << cal
            << "\ndifference: " << std::abs((theory-cal)/cal)
            << "\ntolerance: " << tol << std::endl;
  return 1;
}

template<typename Scalar, typename VectorScalar = std::vector<Scalar> >
void read_temperature(VectorScalar &T0, VectorScalar &Tz, const std::string &file)
{
  T0.clear();
  Tz.clear();
  std::string line;
  std::ifstream temp(file);
  getline(temp,line);
  while(!temp.eof())
  {
     Scalar t,tz;
     temp >> t >> tz;
     if(temp.good())
     {
       T0.push_back(t);
       Tz.push_back(tz);
     }
  }
  temp.close();
  return;
}

template<typename Scalar>
Scalar barometry(const Scalar &zmin, const Scalar &z, const Scalar &T, const Scalar &Mm, const Scalar &botdens)
{
   return botdens * Antioch::ant_exp(-(z - zmin)/((Planet::Constants::Titan::radius<Scalar>() + z) * (Planet::Constants::Titan::radius<Scalar>() + zmin) * 1e3 *
                                             Antioch::Constants::Avogadro<Scalar>() * Planet::Constants::Universal::kb<Scalar>() * T /
                                                        (Planet::Constants::Universal::G<Scalar>() * Planet::Constants::Titan::mass<Scalar>() * Mm))
                              );
}

template <typename Scalar>
int tester(const std::string &input_T)
{

// we require an atmospheric mixture,
// which require a temperature and two
// chemical mixture

//description
  std::vector<std::string> neutrals;
  std::vector<std::string> ions;
  neutrals.push_back("N2");
  neutrals.push_back("CH4");
//ionic system contains neutral system
  ions = neutrals;
  ions.push_back("N2+");
  Scalar MN(14.008e-3L), MC(12.011e-3L), MH(1.008e-3L);
  Scalar MN2 = 2.L*MN , MCH4 = MC + 4.L*MH;
  std::vector<Scalar> Mm;
  Mm.push_back(MN2);
  Mm.push_back(MCH4);

//densities
  std::vector<Scalar> molar_frac;
  molar_frac.push_back(0.96L);
  molar_frac.push_back(0.04L);
  molar_frac.push_back(0.L);
  Scalar dens_tot(1e12L);

//altitudes
  Scalar zmin(600.L),zmax(1400.L),zstep(10.L);

//eddy
  Scalar K0(4.3e6L);//

//neutrals
  Antioch::ChemicalMixture<Scalar> neutral_species(neutrals);

//ions
  Antioch::ChemicalMixture<Scalar> ionic_species(ions);

//temperature
  std::vector<Scalar> T0,Tz;
  read_temperature<Scalar>(T0,Tz,input_T);
  Planet::AtmosphericTemperature<Scalar, std::vector<Scalar> > temperature(Tz, T0);

//atmospheric mixture
  Planet::AtmosphericMixture<Scalar,std::vector<Scalar>, std::vector<std::vector<Scalar> > > composition(neutral_species, ionic_species, temperature);
  composition.init_composition(molar_frac,dens_tot,zmin,zmax);

//eddy diffusion
  Planet::EddyDiffusionEvaluator<Scalar,std::vector<Scalar>, std::vector<std::vector<Scalar> > > eddy_diff(composition,K0);

/************************
 * checks
 ************************/
  molar_frac.pop_back();

  Scalar mean_M;
  Antioch::set_zero(mean_M);
  for(unsigned int s = 0; s < molar_frac.size(); s++)
  {
    mean_M += molar_frac[s] * Mm[s];
  }

  int return_flag(0);

// along lines
  for(Scalar z = zmin; z <= zmax; z += zstep)
  {
     std::stringstream walt;
     walt << z;

     Scalar T     = temperature.neutral_temperature(z);
     Scalar nTot  = barometry(zmin,z,T,mean_M,dens_tot);
     Scalar K     = K0 * Antioch::ant_sqrt(dens_tot/nTot);
     Scalar dK_dT = 0.L;
     Scalar dK_dn = - 0.5L * K / nTot;
     return_flag  = check_test(K, eddy_diff.K(nTot), "eddy diffusion at altitude " + walt.str()) ||
                    check_test(dK_dT, eddy_diff.K_deriv_T(T), "eddy diffusion derived by T at altitude " + walt.str()) ||
                    check_test(dK_dn, eddy_diff.K_deriv_ns(nTot), "eddy diffusion derived by n at altitude " + walt.str()) ||
                    return_flag;
  }

// golden values
  Scalar T    = 250.1L;
  Scalar ntot = 2.75e9L;
  Scalar K_theo     =  8.19977826751209391284227292513405759e7L;
  Scalar dK_theo_dT =  0.L;
  Scalar dK_theo_dn = -1.49086877591128980233495871366073774e-2L;

  return_flag  = check_test(K_theo, eddy_diff.K(ntot), "eddy diffusion") ||
                 check_test(dK_theo_dT, eddy_diff.K_deriv_T(T), "eddy diffusion derived by T") ||
                 check_test(dK_theo_dn, eddy_diff.K_deriv_ns(ntot), "eddy diffusion derived by n") ||
                 return_flag;

  return return_flag;
}

int main(int argc, char** argv)
{
  // Check command line count.
  if( argc < 2 )
    {
      // TODO: Need more consistent error handling.
      std::cerr << "Error: Must specify input file." << std::endl;
      antioch_error();
    }

  return (tester<float>(std::string(argv[1])) ||
          tester<double>(std::string(argv[1])) ||
          tester<long double>(std::string(argv[1])));
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2008-2013 The Communi Project
 *
 * This test is free, and not covered by the LGPL license. There is no
 * restriction applied to their modification, redistribution, using and so on.
 * You can study them, modify them, use them in your own program - either
 * completely or partially.
 */

#include "ircmessage.h"
#include "ircsession.h"
#include <QtTest/QtTest>
#include <QtCore/QTextCodec>

static const QByteArray MSG_32_5("Vestibulum eu libero eget metus.");
static const QByteArray MSG_64_9("Phasellus enim dui, sodales sed tincidunt quis, ultricies metus.");
static const QByteArray MSG_128_19("Ut porttitor volutpat tristique. Aenean semper ligula eget nulla condimentum tempor in quis felis. Sed sem diam, tincidunt amet.");
static const QByteArray MSG_256_37("Vestibulum quis lorem velit, a varius augue. Suspendisse risus augue, ultricies at convallis in, elementum in velit. Fusce fermentum congue augue sit amet dapibus. Fusce ultrices urna ut tortor laoreet a aliquet elit lobortis. Suspendisse volutpat posuere.");
static const QByteArray MSG_512_75("Nam leo risus, accumsan a sagittis eget, posuere eu velit. Morbi mattis auctor risus, vel consequat massa pulvinar nec. Proin aliquam convallis elit nec egestas. Pellentesque accumsan placerat augue, id volutpat nibh dictum vel. Aenean venenatis varius feugiat. Nullam molestie, ipsum id dignissim vulputate, eros urna vestibulum massa, in vehicula lacus nisi vitae risus. Ut nunc nunc, venenatis a mattis auctor, dictum et sem. Nulla posuere libero ut tortor elementum egestas. Aliquam egestas suscipit posuere.");

class tst_IrcMessage : public QObject
{
    Q_OBJECT

private slots:
    void testFromData_data();
    void testFromData();

    void testEncoding();
};

void tst_IrcMessage::testFromData_data()
{
    QTest::addColumn<QByteArray>("data");

    QTest::newRow("null") << QByteArray();
    QTest::newRow("empty") << QByteArray("");

    QTest::newRow("32 chars / 5 words") << MSG_32_5;
    QTest::newRow("64 chars / 9 words")  << MSG_64_9;
    QTest::newRow("128 chars / 19 words")  << MSG_128_19;
    QTest::newRow("256 chars / 37 words")  << MSG_256_37;
    QTest::newRow("512 chars / 75 words")  << MSG_512_75;

    QTest::newRow("32 chars / 5 words") << MSG_32_5;
    QTest::newRow("64 chars / 9 words")  << MSG_64_9;
    QTest::newRow("128 chars / 19 words")  << MSG_128_19;
    QTest::newRow("256 chars / 37 words")  << MSG_256_37;
    QTest::newRow("512 chars / 75 words")  << MSG_512_75;
}

void tst_IrcMessage::testFromData()
{
    QFETCH(QByteArray, data);

    IrcSession session;
    QBENCHMARK {
        IrcMessage::fromData(data, &session);
    }
}

void tst_IrcMessage::testEncoding()
{
    IrcSession session;
    IrcMessage message(&session);
    foreach (const QByteArray& codec, QTextCodec::availableCodecs()) {
        QBENCHMARK {
            message.setEncoding(codec);
        }
    }
}

QTEST_MAIN(tst_IrcMessage)

#include "tst_ircmessage.moc"
<commit_msg>Remove benchmarks/tst_IrcMessage::testEncoding()<commit_after>/*
 * Copyright (C) 2008-2013 The Communi Project
 *
 * This test is free, and not covered by the LGPL license. There is no
 * restriction applied to their modification, redistribution, using and so on.
 * You can study them, modify them, use them in your own program - either
 * completely or partially.
 */

#include "ircmessage.h"
#include "ircsession.h"
#include <QtTest/QtTest>

static const QByteArray MSG_32_5("Vestibulum eu libero eget metus.");
static const QByteArray MSG_64_9("Phasellus enim dui, sodales sed tincidunt quis, ultricies metus.");
static const QByteArray MSG_128_19("Ut porttitor volutpat tristique. Aenean semper ligula eget nulla condimentum tempor in quis felis. Sed sem diam, tincidunt amet.");
static const QByteArray MSG_256_37("Vestibulum quis lorem velit, a varius augue. Suspendisse risus augue, ultricies at convallis in, elementum in velit. Fusce fermentum congue augue sit amet dapibus. Fusce ultrices urna ut tortor laoreet a aliquet elit lobortis. Suspendisse volutpat posuere.");
static const QByteArray MSG_512_75("Nam leo risus, accumsan a sagittis eget, posuere eu velit. Morbi mattis auctor risus, vel consequat massa pulvinar nec. Proin aliquam convallis elit nec egestas. Pellentesque accumsan placerat augue, id volutpat nibh dictum vel. Aenean venenatis varius feugiat. Nullam molestie, ipsum id dignissim vulputate, eros urna vestibulum massa, in vehicula lacus nisi vitae risus. Ut nunc nunc, venenatis a mattis auctor, dictum et sem. Nulla posuere libero ut tortor elementum egestas. Aliquam egestas suscipit posuere.");

class tst_IrcMessage : public QObject
{
    Q_OBJECT

private slots:
    void testFromData_data();
    void testFromData();
};

void tst_IrcMessage::testFromData_data()
{
    QTest::addColumn<QByteArray>("data");

    QTest::newRow("null") << QByteArray();
    QTest::newRow("empty") << QByteArray("");

    QTest::newRow("32 chars / 5 words") << MSG_32_5;
    QTest::newRow("64 chars / 9 words")  << MSG_64_9;
    QTest::newRow("128 chars / 19 words")  << MSG_128_19;
    QTest::newRow("256 chars / 37 words")  << MSG_256_37;
    QTest::newRow("512 chars / 75 words")  << MSG_512_75;

    QTest::newRow("32 chars / 5 words") << MSG_32_5;
    QTest::newRow("64 chars / 9 words")  << MSG_64_9;
    QTest::newRow("128 chars / 19 words")  << MSG_128_19;
    QTest::newRow("256 chars / 37 words")  << MSG_256_37;
    QTest::newRow("512 chars / 75 words")  << MSG_512_75;
}

void tst_IrcMessage::testFromData()
{
    QFETCH(QByteArray, data);

    IrcSession session;
    QBENCHMARK {
        IrcMessage::fromData(data, &session);
    }
}

QTEST_MAIN(tst_IrcMessage)

#include "tst_ircmessage.moc"
<|endoftext|>