<commit_before>// pc.cpp: posit components: show the sign/scale/regime/exponent/fraction components of standard posit configurations
//
// Copyright (C) 2017-2018 Stillwater Supercomputing, Inc.
//
// This file is part of the universal numbers project, which is released under an MIT Open Source license.

#include "common.hpp"

#include <posit>

// convert a floating point value to a specific posit configuration. Semantically, p = v, return reference to p
template<size_t nbits, size_t es, typename Ty>
sw::unum::posit<nbits, es> convert_to_posit(Ty rhs) {
	constexpr size_t fbits = std::numeric_limits<Ty>::digits - 1;

	using namespace std;
	using namespace sw::unum;

	value<fbits> v((Ty)rhs);
	posit<nbits, es> p;

	cout << setprecision(numeric_limits<Ty>::digits10) << v << "   input value\n";
	cout << "Test for ZERO\n";
	cout << components(v);
	if (v.iszero()) {
		p.setzero();
		cout << " input value is zero\n";
		cout << info_print(p);
		return p;
	}
	else {
		cout << " input value is NOT zero\n";
	}
	cout << "Test for NaR\n";
	cout << components(v);
	if (v.isnan() || v.isinf()) {
		p.setnar();
		cout << " input value is NaR\n";
		cout << info_print(p);
		return p;
	}
	else {
		cout << " input value is NOT NaR\n";
	}

	bool _sign = v.sign();
	int _scale = v.scale();
	sw::unum::bitblock<fbits> fraction_in = v.fraction();

	p.clear();
	cout << " construct the posit\n";
	// interpolation rule checks
	if (check_inward_projection_range<nbits, es>(_scale)) {    // regime dominated
															   // we are projecting to minpos/maxpos
		int k = calculate_unconstrained_k<nbits, es>(_scale);
		k < 0 ? p.set(minpos_pattern<nbits, es>(_sign)) : p.set(maxpos_pattern<nbits, es>(_sign));
		// we are done
		std::cout << "projection  rounding ";
	}
	else {
		constexpr size_t pt_len = nbits + 3 + es;
		bitblock<pt_len> pt_bits;
		bitblock<pt_len> regime;
		bitblock<pt_len> exponent;
		bitblock<pt_len> fraction;
		bitblock<pt_len> sticky_bit;
		bool s = _sign;
		int e = _scale;
		bool r = (e >= 0);

		unsigned run = (r ? 1 + (e >> es) : -(e >> es));
		regime.set(0, 1 ^ r);
		for (unsigned i = 1; i <= run; i++) regime.set(i, r);

		unsigned esval = e % (uint32_t(1) << es);
		exponent = convert_to_bitblock<pt_len>(esval);
		unsigned nf = (unsigned)std::max<int>(0, (nbits + 1) - (2 + run + es));

		// copy the most significant nf fraction bits into fraction
		unsigned lsb = nf <= fbits ? 0 : nf - fbits;
		for (unsigned i = lsb; i < nf; i++) fraction[i] = fraction_in[fbits - nf + i];
		cout << to_bit_string(fraction_in) << "  full fraction bits\n";

		int remaining_bits = fbits - 1 - nf;
		bool sb = false;
		if (remaining_bits > 0) {
			sb = anyAfter(fraction_in, fbits - 1 - nf);
			bitblock<fbits> sb_mask;
			//for (int i = 0; i < int(fbits) - 1 - nf; i++) sb_mask.set(i);
			for (int i = 0; i < remaining_bits; i++) sb_mask.set(i);
			cout << to_bit_string(sb_mask) << "  mask of remainder bits\n";
		}

		// construct the untruncated posit
		cout << to_bit_string(pt_bits) << "  unconstrained posit: length = nbits(" << nbits << ") + es(" << es << ") + 3 guard bits: " << pt_len << "\n";
		// pt    = BitOr[BitShiftLeft[reg, es + nf + 1], BitShiftLeft[esval, nf + 1], BitShiftLeft[fv, 1], sb];
		regime <<= es + nf + 1;
		cout << to_bit_string(regime) << "  runlength = " << run << endl;
		exponent <<= nf + 1;
		cout << to_bit_string(exponent) << "  exponent value = " << hex << esval << dec << endl;
		fraction <<= 1;
		cout << to_bit_string(fraction) << "  most significant " << nf << " fraction bits (nbits-1-run-es)\n";
		sticky_bit.set(0, sb);
		if (remaining_bits > 0) {
			cout << to_bit_string(sticky_bit) << "  sticky bit representing the truncated fraction bits\n";
		}
		else {
			cout << to_bit_string(sticky_bit) << "  sticky bit representing the fraction bits which are not truncated\n";
		}

		pt_bits |= regime;
		pt_bits |= exponent;
		pt_bits |= fraction;
		pt_bits |= sticky_bit;
		cout << to_bit_string(pt_bits) << "  unconstrained posit bits ";

		unsigned len = 1 + std::max<unsigned>((nbits + 1), (2 + run + es));
		cout << " length = " << len << endl;
		bool blast = pt_bits.test(len - nbits);
		bitblock<pt_len> blast_bb;
		blast_bb.set(len - nbits);
		cout << to_bit_string(blast_bb) << "  last bit mask\n";
		bool bafter = pt_bits.test(len - nbits - 1);
		bitblock<pt_len> bafter_bb;
		bafter_bb.set(len - nbits - 1);
		cout << to_bit_string(bafter_bb) << "  bit after last bit mask\n";
		bool bsticky = anyAfter(pt_bits, len - nbits - 1 - 1);
		bitblock<pt_len> bsticky_bb;
		for (int i = len - nbits - 2; i >= 0; --i) bsticky_bb.set(i);
		cout << to_bit_string(bsticky_bb) << "  sticky bit mask\n";

		bool rb = (blast & bafter) | (bafter & bsticky);
		cout << "rounding decision (blast & bafter) | (bafter & bsticky): " << (rb ? "round up" : "round down") << endl;

		bitblock<nbits> ptt;
		pt_bits <<= pt_len - len;
		cout << to_bit_string(pt_bits) << "  shifted posit\n";
		truncate(pt_bits, ptt);
		cout << to_bit_string(ptt) << "  truncated posit\n";
		if (rb) increment_bitset(ptt);
		cout << to_bit_string(ptt) << "  rounded posit\n";
		if (s) ptt = twos_complement(ptt);
		cout << to_bit_string(ptt) << "  final posit\n";
		p.set(ptt);
	}
	return p;
}

typedef std::numeric_limits< double > dbl;
const char* msg = "$ ./convert.exe 1.234567890 32\n\
1.23456789   input value\n\
Test for ZERO\n\
(+, 0, 0011110000001100101001000010100000111101111000011011) input value is NOT zero\n\
Test for NaR\n\
(+, 0, 0011110000001100101001000010100000111101111000011011) input value is NOT NaR\n\
construct the posit\n\
0011'1100'0000'1100'1010'0100'0010'1000'0011'1101'1110'0001'1011  full fraction bits\n\
0000'0000'0000'0000'0000'0000'0000'0111'1111'1111'1111'1111'1111  mask of remainder bits\n\
0'0000'0000'0000'0000'0000'0000'0000'0000'0000  unconstrained posit : length = nbits(32) + es(2) + 3 guard bits : 37\n\
0'0001'0000'0000'0000'0000'0000'0000'0000'0000  runlength = 1\n\
0'0000'0000'0000'0000'0000'0000'0000'0000'0000  exponent value = 0\n\
0'0000'0000'0111'1000'0001'1001'0100'1000'0100  most significant 28 fraction bits(nbits - 1 - run - es)\n\
0'0000'0000'0000'0000'0000'0000'0000'0000'0001  sticky bit representing the truncated fraction bits\n\
0'0001'0000'0111'1000'0001'1001'0100'1000'0101  unconstrained posit bits  length = 34\n\
0'0000'0000'0000'0000'0000'0000'0000'0000'0100  last bit mask\n\
0'0000'0000'0000'0000'0000'0000'0000'0000'0010  bit after last bit mask\n\
0'0000'0000'0000'0000'0000'0000'0000'0000'0001  sticky bit mask\n\
rounding decision(blast & bafter) | (bafter & bsticky) : round down\n\
0'1000'0011'1100'0000'1100'1010'0100'0010'1000  shifted posit\n\
0100'0001'1110'0000'0110'0101'0010'0001  truncated posit\n\
0100'0001'1110'0000'0110'0101'0010'0001  rounded posit\n\
0100'0001'1110'0000'0110'0101'0010'0001  final posit\n\
";

// receive a float and print its components
int main(int argc, char** argv)
try {
	using namespace std;
	using namespace sw::unum;

	if (argc != 3) {
		cerr << "Show the conversion of a float to a posit step-by-step." << endl;
	    cerr << "Usage: convert floating_point_value standard_posit_size(8/16/32/64/128/256)" << endl;
		cerr << "Example: convert -1.123456789e17 32" << endl;
		cerr <<  msg << endl;
		return EXIT_SUCCESS;  // signal successful completion for ctest
	}
	double d = atof(argv[1]);
	int size = atoi(argv[2]);
	posit<8, 0>  p8_0;
	posit<16, 1> p16_1;
	posit<32, 2> p32_2;
	posit<48, 2> p48_2;
	posit<64, 3> p64_3;
	posit<80, 3> p80_3;
	posit<96, 3> p96_3;
	posit<128, 4> p128_4;
	posit<256, 5> p256_5;

	//int precision = dbl::max_digits10;
	switch (size) {
	case 8:
		p8_0 = convert_to_posit<8, 0, double>(d);
		cout << color_print(p8_0);
		break;
	case 16:
		p16_1 = convert_to_posit<16, 1, double>(d);
		cout << color_print(p16_1);
		break;
	case 32:
		p32_2 = convert_to_posit<32, 2, double>(d);
		cout << color_print(p32_2);
		break;
	case 48:
		p48_2 = convert_to_posit<48, 2, double>(d);
		cout << color_print(p48_2);
		break;
	case 64:
		p64_3 = convert_to_posit<64, 3, double>(d);
		cout << color_print(p64_3);
		break;
	case 80:
		p80_3 = convert_to_posit<80, 3, double>(d);
		cout << color_print(p80_3);
		break;
	case 96:
		p96_3 = convert_to_posit<96, 3, double>(d);
		cout << color_print(p96_3);
		break;
	case 128:
		p128_4 = convert_to_posit<128, 4, double>(d);
		cout << color_print(p128_4);
		break;
	case 256:
		p256_5 = convert_to_posit<256, 5, double>(d);
		cout << color_print(p256_5);
		break;
	default:
		p32_2 = convert_to_posit<32, 2, double>(d);
		cout << color_print(p32_2);
		break;

	}

	return EXIT_SUCCESS;
}
catch (const char* const msg) {
	std::cerr << msg << std::endl;
	return EXIT_FAILURE;
}
catch (...) {
	std::cerr << "caught unknown exception" << std::endl;
	return EXIT_FAILURE;
}
<commit_msg>Replaces to_bitstring with to_binary.<commit_after>// pc.cpp: posit components: show the sign/scale/regime/exponent/fraction components of standard posit configurations
//
// Copyright (C) 2017-2018 Stillwater Supercomputing, Inc.
//
// This file is part of the universal numbers project, which is released under an MIT Open Source license.

#include "common.hpp"

#include <posit>

// convert a floating point value to a specific posit configuration. Semantically, p = v, return reference to p
template<size_t nbits, size_t es, typename Ty>
sw::unum::posit<nbits, es> convert_to_posit(Ty rhs) {
	constexpr size_t fbits = std::numeric_limits<Ty>::digits - 1;

	using namespace std;
	using namespace sw::unum;

	value<fbits> v((Ty)rhs);
	posit<nbits, es> p;

	cout << setprecision(numeric_limits<Ty>::digits10) << v << "   input value\n";
	cout << "Test for ZERO\n";
	cout << components(v);
	if (v.iszero()) {
		p.setzero();
		cout << " input value is zero\n";
		cout << info_print(p);
		return p;
	}
	else {
		cout << " input value is NOT zero\n";
	}
	cout << "Test for NaR\n";
	cout << components(v);
	if (v.isnan() || v.isinf()) {
		p.setnar();
		cout << " input value is NaR\n";
		cout << info_print(p);
		return p;
	}
	else {
		cout << " input value is NOT NaR\n";
	}

	bool _sign = v.sign();
	int _scale = v.scale();
	sw::unum::bitblock<fbits> fraction_in = v.fraction();

	p.clear();
	cout << " construct the posit\n";
	// interpolation rule checks
	if (check_inward_projection_range<nbits, es>(_scale)) {    // regime dominated
															   // we are projecting to minpos/maxpos
		int k = calculate_unconstrained_k<nbits, es>(_scale);
		k < 0 ? p.set(minpos_pattern<nbits, es>(_sign)) : p.set(maxpos_pattern<nbits, es>(_sign));
		// we are done
		std::cout << "projection  rounding ";
	}
	else {
		constexpr size_t pt_len = nbits + 3 + es;
		bitblock<pt_len> pt_bits;
		bitblock<pt_len> regime;
		bitblock<pt_len> exponent;
		bitblock<pt_len> fraction;
		bitblock<pt_len> sticky_bit;
		bool s = _sign;
		int e = _scale;
		bool r = (e >= 0);

		unsigned run = (r ? 1 + (e >> es) : -(e >> es));
		regime.set(0, 1 ^ r);
		for (unsigned i = 1; i <= run; i++) regime.set(i, r);

		unsigned esval = e % (uint32_t(1) << es);
		exponent = convert_to_bitblock<pt_len>(esval);
		unsigned nf = (unsigned)std::max<int>(0, (nbits + 1) - (2 + run + es));

		// copy the most significant nf fraction bits into fraction
		unsigned lsb = nf <= fbits ? 0 : nf - fbits;
		for (unsigned i = lsb; i < nf; i++) fraction[i] = fraction_in[fbits - nf + i];
		cout << to_binary(fraction_in) << "  full fraction bits\n";

		int remaining_bits = fbits - 1 - nf;
		bool sb = false;
		if (remaining_bits > 0) {
			sb = anyAfter(fraction_in, fbits - 1 - nf);
			bitblock<fbits> sb_mask;
			//for (int i = 0; i < int(fbits) - 1 - nf; i++) sb_mask.set(i);
			for (int i = 0; i < remaining_bits; i++) sb_mask.set(i);
			cout << to_binary(sb_mask) << "  mask of remainder bits\n";
		}

		// construct the untruncated posit
		cout << to_binary(pt_bits) << "  unconstrained posit: length = nbits(" << nbits << ") + es(" << es << ") + 3 guard bits: " << pt_len << "\n";
		// pt    = BitOr[BitShiftLeft[reg, es + nf + 1], BitShiftLeft[esval, nf + 1], BitShiftLeft[fv, 1], sb];
		regime <<= es + nf + 1;
		cout << to_binary(regime) << "  runlength = " << run << endl;
		exponent <<= nf + 1;
		cout << to_binary(exponent) << "  exponent value = " << hex << esval << dec << endl;
		fraction <<= 1;
		cout << to_binary(fraction) << "  most significant " << nf << " fraction bits (nbits-1-run-es)\n";
		sticky_bit.set(0, sb);
		if (remaining_bits > 0) {
			cout << to_binary(sticky_bit) << "  sticky bit representing the truncated fraction bits\n";
		}
		else {
			cout << to_binary(sticky_bit) << "  sticky bit representing the fraction bits which are not truncated\n";
		}

		pt_bits |= regime;
		pt_bits |= exponent;
		pt_bits |= fraction;
		pt_bits |= sticky_bit;
		cout << to_binary(pt_bits) << "  unconstrained posit bits ";

		unsigned len = 1 + std::max<unsigned>((nbits + 1), (2 + run + es));
		cout << " length = " << len << endl;
		bool blast = pt_bits.test(len - nbits);
		bitblock<pt_len> blast_bb;
		blast_bb.set(len - nbits);
		cout << to_binary(blast_bb) << "  last bit mask\n";
		bool bafter = pt_bits.test(len - nbits - 1);
		bitblock<pt_len> bafter_bb;
		bafter_bb.set(len - nbits - 1);
		cout << to_binary(bafter_bb) << "  bit after last bit mask\n";
		bool bsticky = anyAfter(pt_bits, len - nbits - 1 - 1);
		bitblock<pt_len> bsticky_bb;
		for (int i = len - nbits - 2; i >= 0; --i) bsticky_bb.set(i);
		cout << to_binary(bsticky_bb) << "  sticky bit mask\n";

		bool rb = (blast & bafter) | (bafter & bsticky);
		cout << "rounding decision (blast & bafter) | (bafter & bsticky): " << (rb ? "round up" : "round down") << endl;

		bitblock<nbits> ptt;
		pt_bits <<= pt_len - len;
		cout << to_binary(pt_bits) << "  shifted posit\n";
		truncate(pt_bits, ptt);
		cout << to_binary(ptt) << "  truncated posit\n";
		if (rb) increment_bitset(ptt);
		cout << to_binary(ptt) << "  rounded posit\n";
		if (s) ptt = twos_complement(ptt);
		cout << to_binary(ptt) << "  final posit\n";
		p.set(ptt);
	}
	return p;
}

typedef std::numeric_limits< double > dbl;
const char* msg = "$ ./convert.exe 1.234567890 32\n\
1.23456789   input value\n\
Test for ZERO\n\
(+, 0, 0011110000001100101001000010100000111101111000011011) input value is NOT zero\n\
Test for NaR\n\
(+, 0, 0011110000001100101001000010100000111101111000011011) input value is NOT NaR\n\
construct the posit\n\
0011'1100'0000'1100'1010'0100'0010'1000'0011'1101'1110'0001'1011  full fraction bits\n\
0000'0000'0000'0000'0000'0000'0000'0111'1111'1111'1111'1111'1111  mask of remainder bits\n\
0'0000'0000'0000'0000'0000'0000'0000'0000'0000  unconstrained posit : length = nbits(32) + es(2) + 3 guard bits : 37\n\
0'0001'0000'0000'0000'0000'0000'0000'0000'0000  runlength = 1\n\
0'0000'0000'0000'0000'0000'0000'0000'0000'0000  exponent value = 0\n\
0'0000'0000'0111'1000'0001'1001'0100'1000'0100  most significant 28 fraction bits(nbits - 1 - run - es)\n\
0'0000'0000'0000'0000'0000'0000'0000'0000'0001  sticky bit representing the truncated fraction bits\n\
0'0001'0000'0111'1000'0001'1001'0100'1000'0101  unconstrained posit bits  length = 34\n\
0'0000'0000'0000'0000'0000'0000'0000'0000'0100  last bit mask\n\
0'0000'0000'0000'0000'0000'0000'0000'0000'0010  bit after last bit mask\n\
0'0000'0000'0000'0000'0000'0000'0000'0000'0001  sticky bit mask\n\
rounding decision(blast & bafter) | (bafter & bsticky) : round down\n\
0'1000'0011'1100'0000'1100'1010'0100'0010'1000  shifted posit\n\
0100'0001'1110'0000'0110'0101'0010'0001  truncated posit\n\
0100'0001'1110'0000'0110'0101'0010'0001  rounded posit\n\
0100'0001'1110'0000'0110'0101'0010'0001  final posit\n\
";

// receive a float and print its components
int main(int argc, char** argv)
try {
	using namespace std;
	using namespace sw::unum;

	if (argc != 3) {
		cerr << "Show the conversion of a float to a posit step-by-step." << endl;
	    cerr << "Usage: convert floating_point_value standard_posit_size(8/16/32/64/128/256)" << endl;
		cerr << "Example: convert -1.123456789e17 32" << endl;
		cerr <<  msg << endl;
		return EXIT_SUCCESS;  // signal successful completion for ctest
	}
	double d = atof(argv[1]);
	int size = atoi(argv[2]);
	posit<8, 0>  p8_0;
	posit<16, 1> p16_1;
	posit<32, 2> p32_2;
	posit<48, 2> p48_2;
	posit<64, 3> p64_3;
	posit<80, 3> p80_3;
	posit<96, 3> p96_3;
	posit<128, 4> p128_4;
	posit<256, 5> p256_5;

	//int precision = dbl::max_digits10;
	switch (size) {
	case 8:
		p8_0 = convert_to_posit<8, 0, double>(d);
		cout << color_print(p8_0);
		break;
	case 16:
		p16_1 = convert_to_posit<16, 1, double>(d);
		cout << color_print(p16_1);
		break;
	case 32:
		p32_2 = convert_to_posit<32, 2, double>(d);
		cout << color_print(p32_2);
		break;
	case 48:
		p48_2 = convert_to_posit<48, 2, double>(d);
		cout << color_print(p48_2);
		break;
	case 64:
		p64_3 = convert_to_posit<64, 3, double>(d);
		cout << color_print(p64_3);
		break;
	case 80:
		p80_3 = convert_to_posit<80, 3, double>(d);
		cout << color_print(p80_3);
		break;
	case 96:
		p96_3 = convert_to_posit<96, 3, double>(d);
		cout << color_print(p96_3);
		break;
	case 128:
		p128_4 = convert_to_posit<128, 4, double>(d);
		cout << color_print(p128_4);
		break;
	case 256:
		p256_5 = convert_to_posit<256, 5, double>(d);
		cout << color_print(p256_5);
		break;
	default:
		p32_2 = convert_to_posit<32, 2, double>(d);
		cout << color_print(p32_2);
		break;

	}

	return EXIT_SUCCESS;
}
catch (const char* const msg) {
	std::cerr << msg << std::endl;
	return EXIT_FAILURE;
}
catch (...) {
	std::cerr << "caught unknown exception" << std::endl;
	return EXIT_FAILURE;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: DocumentTContext.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: hr $ $Date: 2007-06-27 16:20:13 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, 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., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_xmloff.hxx"

#ifndef _COM_SUN_STAR_XML_SAX_SAXPARSEEXCEPTION_HPP_
#include <com/sun/star/xml/sax/SAXParseException.hpp>
#endif
#ifndef _COM_SUN_STAR_XML_SAX_SAXEXCEPTION_HPP_
#include <com/sun/star/xml/sax/SAXException.hpp>
#endif
#ifndef _COM_SUN_STAR_XML_SAX_XDOCUMENTHANDLER_HPP_
#include <com/sun/star/xml/sax/XDocumentHandler.hpp>
#endif
#ifndef _COM_SUN_STAR_XML_SAX_XATTRIBUTELIST_HPP_
#include <com/sun/star/xml/sax/XAttributeList.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSETINFO_HPP_
#include <com/sun/star/beans/XPropertySetInfo.hpp>
#endif
#ifndef _XMLOFF_NMSPMAP_HXX
#include <xmloff/nmspmap.hxx>
#endif
#ifndef _XMLOFF_XMLTOKEN_HXX
#include <xmloff/xmltoken.hxx>
#endif
#ifndef _XMLOFF_XMLNMSPE_HXX
#include "xmlnmspe.hxx"
#endif

#ifndef _XMLOFF_TRANSFOERMERBASE_HXX
#include "TransformerBase.hxx"
#endif
#ifndef _XMLOFF_MUTABLEATTRLIST_HXX
#include "MutableAttrList.hxx"
#endif

#ifndef _XMLOFF_METATCONTEXT_HXX
#include "DocumentTContext.hxx"
#endif

using namespace ::rtl;
using namespace ::xmloff::token;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::xml::sax;
using namespace ::com::sun::star::beans;

TYPEINIT1( XMLDocumentTransformerContext, XMLTransformerContext );

XMLDocumentTransformerContext::XMLDocumentTransformerContext( XMLTransformerBase& rImp,
                                                const OUString& rQName ) :
    XMLTransformerContext( rImp, rQName )
{
}

XMLDocumentTransformerContext::~XMLDocumentTransformerContext()
{
}

void XMLDocumentTransformerContext::StartElement( const Reference< XAttributeList >& rAttrList )
{
    Reference< XAttributeList > xAttrList( rAttrList );

    sal_Bool bMimeFound = sal_False;
    OUString aClass;
    OUString aClassQName(
                    GetTransformer().GetNamespaceMap().GetQNameByKey(
                                XML_NAMESPACE_OFFICE, GetXMLToken(XML_CLASS ) ) );

    XMLMutableAttributeList *pMutableAttrList = 0;
    sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
    for( sal_Int16 i=0; i < nAttrCount; i++ )
    {
        const OUString& rAttrName = xAttrList->getNameByIndex( i );
        OUString aLocalName;
        sal_uInt16 nPrefix =
            GetTransformer().GetNamespaceMap().GetKeyByAttrName( rAttrName,
                                                                 &aLocalName );
        if( XML_NAMESPACE_OFFICE == nPrefix &&
            IsXMLToken( aLocalName, XML_MIMETYPE ) )
        {
            const OUString& rValue = xAttrList->getValueByIndex( i );
            OUString aTmp( RTL_CONSTASCII_USTRINGPARAM("application/vnd.oasis.openoffice.") );
            if( 0 == rValue.compareTo( aTmp, aTmp.getLength() ) )
            {
                aClass = rValue.copy( aTmp.getLength() );
            }
            else
            {
                aTmp = OUString( RTL_CONSTASCII_USTRINGPARAM("application/x-vnd.oasis.openoffice.") );
                if( 0 == rValue.compareTo( aTmp, aTmp.getLength() ) )
                    aClass = rValue.copy( aTmp.getLength() );
            }

            if( !pMutableAttrList )
            {
                pMutableAttrList = new XMLMutableAttributeList( xAttrList );
                xAttrList = pMutableAttrList;
            }
            pMutableAttrList->SetValueByIndex( i, aClass );
            pMutableAttrList->RenameAttributeByIndex(i, aClassQName );
            bMimeFound = sal_True;
            break;
        }
    }

    if( !bMimeFound )
    {
        const Reference< XPropertySet > rPropSet =
            GetTransformer().GetPropertySet();

        if( rPropSet.is() )
        {
            Reference< XPropertySetInfo > xPropSetInfo(
                rPropSet->getPropertySetInfo() );
            OUString aPropName(RTL_CONSTASCII_USTRINGPARAM("Class"));
            if( xPropSetInfo.is() && xPropSetInfo->hasPropertyByName( aPropName ) )
            {
                Any aAny = rPropSet->getPropertyValue( aPropName );
                aAny >>= aClass;
            }
        }

        if( aClass.getLength() )
        {
            if( !pMutableAttrList )
            {
                pMutableAttrList = new XMLMutableAttributeList( xAttrList );
                xAttrList = pMutableAttrList;
            }

            pMutableAttrList->AddAttribute( aClassQName, aClass );
        }
    }
    XMLTransformerContext::StartElement( xAttrList );
}
<commit_msg>INTEGRATION: CWS fsfixes07 (1.5.28); FILE MERGED 2007/07/26 11:44:32 fridrich_strba 1.5.28.2: removing the need of strlen call 2007/07/26 09:42:54 fridrich_strba 1.5.28.1: make flat xml import accept also :-) the valid ODF mimetypes<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: DocumentTContext.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: hr $ $Date: 2007-08-03 10:22:07 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, 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., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_xmloff.hxx"

#ifndef _COM_SUN_STAR_XML_SAX_SAXPARSEEXCEPTION_HPP_
#include <com/sun/star/xml/sax/SAXParseException.hpp>
#endif
#ifndef _COM_SUN_STAR_XML_SAX_SAXEXCEPTION_HPP_
#include <com/sun/star/xml/sax/SAXException.hpp>
#endif
#ifndef _COM_SUN_STAR_XML_SAX_XDOCUMENTHANDLER_HPP_
#include <com/sun/star/xml/sax/XDocumentHandler.hpp>
#endif
#ifndef _COM_SUN_STAR_XML_SAX_XATTRIBUTELIST_HPP_
#include <com/sun/star/xml/sax/XAttributeList.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSETINFO_HPP_
#include <com/sun/star/beans/XPropertySetInfo.hpp>
#endif
#ifndef _XMLOFF_NMSPMAP_HXX
#include <xmloff/nmspmap.hxx>
#endif
#ifndef _XMLOFF_XMLTOKEN_HXX
#include <xmloff/xmltoken.hxx>
#endif
#ifndef _XMLOFF_XMLNMSPE_HXX
#include "xmlnmspe.hxx"
#endif

#ifndef _XMLOFF_TRANSFOERMERBASE_HXX
#include "TransformerBase.hxx"
#endif
#ifndef _XMLOFF_MUTABLEATTRLIST_HXX
#include "MutableAttrList.hxx"
#endif

#ifndef _XMLOFF_METATCONTEXT_HXX
#include "DocumentTContext.hxx"
#endif

using namespace ::rtl;
using namespace ::xmloff::token;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::xml::sax;
using namespace ::com::sun::star::beans;

TYPEINIT1( XMLDocumentTransformerContext, XMLTransformerContext );

XMLDocumentTransformerContext::XMLDocumentTransformerContext( XMLTransformerBase& rImp,
                                                const OUString& rQName ) :
    XMLTransformerContext( rImp, rQName )
{
}

XMLDocumentTransformerContext::~XMLDocumentTransformerContext()
{
}

void XMLDocumentTransformerContext::StartElement( const Reference< XAttributeList >& rAttrList )
{
    Reference< XAttributeList > xAttrList( rAttrList );

    sal_Bool bMimeFound = sal_False;
    OUString aClass;
    OUString aClassQName(
                    GetTransformer().GetNamespaceMap().GetQNameByKey(
                                XML_NAMESPACE_OFFICE, GetXMLToken(XML_CLASS ) ) );

    XMLMutableAttributeList *pMutableAttrList = 0;
    sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
    for( sal_Int16 i=0; i < nAttrCount; i++ )
    {
        const OUString& rAttrName = xAttrList->getNameByIndex( i );
        OUString aLocalName;
        sal_uInt16 nPrefix =
            GetTransformer().GetNamespaceMap().GetKeyByAttrName( rAttrName,
                                                                 &aLocalName );
        if( XML_NAMESPACE_OFFICE == nPrefix &&
            IsXMLToken( aLocalName, XML_MIMETYPE ) )
        {
            const OUString& rValue = xAttrList->getValueByIndex( i );
            static const char * aTmp[] =
            {
                "application/vnd.oasis.openoffice.",
                "application/x-vnd.oasis.openoffice.",
                "application/vnd.oasis.opendocument.",
                "application/x-vnd.oasis.document.",
                NULL
            };
            for (int k=0; aTmp[k]; k++)
            {
                ::rtl::OUString sTmpString = ::rtl::OUString::createFromAscii(aTmp[k]);
                if( rValue.matchAsciiL( aTmp[k], sTmpString.getLength() ) )
                {
                    aClass = rValue.copy( sTmpString.getLength() );
                    break;
                }
            }

            if( !pMutableAttrList )
            {
                pMutableAttrList = new XMLMutableAttributeList( xAttrList );
                xAttrList = pMutableAttrList;
            }
            pMutableAttrList->SetValueByIndex( i, aClass );
            pMutableAttrList->RenameAttributeByIndex(i, aClassQName );
            bMimeFound = sal_True;
            break;
        }
    }

    if( !bMimeFound )
    {
        const Reference< XPropertySet > rPropSet =
            GetTransformer().GetPropertySet();

        if( rPropSet.is() )
        {
            Reference< XPropertySetInfo > xPropSetInfo(
                rPropSet->getPropertySetInfo() );
            OUString aPropName(RTL_CONSTASCII_USTRINGPARAM("Class"));
            if( xPropSetInfo.is() && xPropSetInfo->hasPropertyByName( aPropName ) )
            {
                Any aAny = rPropSet->getPropertyValue( aPropName );
                aAny >>= aClass;
            }
        }

        if( aClass.getLength() )
        {
            if( !pMutableAttrList )
            {
                pMutableAttrList = new XMLMutableAttributeList( xAttrList );
                xAttrList = pMutableAttrList;
            }

            pMutableAttrList->AddAttribute( aClassQName, aClass );
        }
    }
    XMLTransformerContext::StartElement( xAttrList );
}
<|endoftext|>


<commit_before>// Copyright 2019 The Souper Authors. All rights reserved.
//
// 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.

// This file contains auxiliary tool that prints the number of times each
// instruction occurs in LHS / RHS. The instructions are ordered according to
// the enum in Inst.h
// Output: first line is number of occurrences of each
// instruction on the LHS, second is same for RHS

#include "souper/Parser/Parser.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include <iostream>
#include <unistd.h>

using namespace souper;
using namespace llvm;

void countHelper(Inst *I, std::set<Inst *> &Visited,
                 std::map<int, int> &Result) {
  if (!Visited.insert(I).second)
    return;

  ++Result[I->K];

  for (auto Op : I->Ops)
    countHelper(Op, Visited, Result);
}

void instCount(Inst *I, std::map<int, int> &Result) {
  std::set<Inst *> Visited;
  return countHelper(I, Visited, Result);
}

int main(int argc, char **argv) {
  if (argc != 2)
    std::cerr << "Please specify input file!" << '\n';

  auto MB = MemoryBuffer::getFileOrSTDIN(argv[1]);

  if (MB) {
    InstContext IC;
    std::string ErrStr;
    std::vector<ParsedReplacement> Reps;
    std::vector<ReplacementContext> Contexts;
    Reps = ParseReplacements(IC, MB.get()->getBufferIdentifier(),
                             MB.get()->getBuffer(), ErrStr);
    if (!ErrStr.empty()) {
      llvm::errs() << ErrStr << '\n';
      return 1;
    }

    std::map<int, int> LHSResult;
    std::map<int, int> RHSResult;

    for (const auto &R : Reps) {
      instCount(R.Mapping.LHS, LHSResult);
      instCount(R.Mapping.RHS, RHSResult);

      for (const auto &PC : R.PCs) {
        instCount(PC.LHS, LHSResult);
        instCount(PC.RHS, RHSResult);
      }

      for (const auto &BPC : R.BPCs) {
        instCount(BPC.PC.LHS, LHSResult);
        instCount(BPC.PC.RHS, RHSResult);
      }
    }

    for (Inst::Kind i = Inst::Const; i <= Inst::None;
         i = static_cast<Inst::Kind>(static_cast<int>(i) + 1))
      std::cout << LHSResult[i] << (i != Inst::None ? "," : "");
    std::cout << std::endl;

    for (Inst::Kind i = Inst::Const; i <= Inst::None;
         i = static_cast<Inst::Kind>(static_cast<int>(i) + 1))
      std::cout << RHSResult[i] << (i != Inst::None ? "," : "");
    std::cout << std::endl;
  }
  else {
    std::cerr << MB.getError().message() << '\n';
  }
  return 0;
}
<commit_msg>Add -diff option to instruction counter<commit_after>// Copyright 2019 The Souper Authors. All rights reserved.
//
// 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.

// This file contains auxiliary tool that prints the number of times each
// instruction occurs in LHS / RHS. The instructions are ordered according to
// the enum in Inst.h
// Output: first line is number of occurrences of each
// instruction on the LHS, second is same for RHS.
// The other option is to print the difference between LHS and RHS.

#include "souper/Parser/Parser.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include <iostream>
#include <unistd.h>

using namespace souper;
using namespace llvm;

void countHelper(Inst *I, std::set<Inst *> &Visited,
                 std::map<int, int> &Result) {
  if (!Visited.insert(I).second)
    return;

  ++Result[I->K];

  for (auto Op : I->Ops)
    countHelper(Op, Visited, Result);
}

void instCount(Inst *I, std::map<int, int> &Result) {
  std::set<Inst *> Visited;
  return countHelper(I, Visited, Result);
}

int main(int argc, char **argv) {
  bool DumpDiff = false;
  int DiffArgPos = 2;
  if (argc < 2)
    std::cerr << "Please specify input file!" << '\n';

  if (DiffArgPos < argc && strcmp(argv[DiffArgPos], "-diff") == 0)
    DumpDiff = true;

  auto MB = MemoryBuffer::getFileOrSTDIN(argv[1]);

  if (MB) {
    InstContext IC;
    std::string ErrStr;
    std::vector<ParsedReplacement> Reps;
    std::vector<ReplacementContext> Contexts;
    Reps = ParseReplacements(IC, MB.get()->getBufferIdentifier(),
                             MB.get()->getBuffer(), ErrStr);
    if (!ErrStr.empty()) {
      llvm::errs() << ErrStr << '\n';
      return 1;
    }

    std::map<int, int> LHSResult;
    std::map<int, int> RHSResult;

    for (const auto &R : Reps) {
      instCount(R.Mapping.LHS, LHSResult);
      instCount(R.Mapping.RHS, RHSResult);
    }

    if (!DumpDiff) {
      for (Inst::Kind i = Inst::Const; i <= Inst::None;
           i = static_cast<Inst::Kind>(static_cast<int>(i) + 1))
        std::cout << LHSResult[i] << (i != Inst::None ? "," : "");
      std::cout << std::endl;

      for (Inst::Kind i = Inst::Const; i <= Inst::None;
           i = static_cast<Inst::Kind>(static_cast<int>(i) + 1))
        std::cout << RHSResult[i] << (i != Inst::None ? "," : "");
      std::cout << std::endl;
    }
    else {
      for (Inst::Kind i = Inst::Const; i <= Inst::None;
           i = static_cast<Inst::Kind>(static_cast<int>(i) + 1))
        std::cout << (LHSResult[i] - RHSResult[i]) << (i != Inst::None ? "," : "");
      std::cout << std::endl;
    }
  }
  else {
    std::cerr << MB.getError().message() << '\n';
  }
  return 0;
}
<|endoftext|>


<commit_before>#include <assert.h>
#include <cstdio>
#include <cstring>

#include <set>

#ifndef HAVE_LLVM
#error "This code needs LLVM enabled"
#endif

#include "../git-version.h"

#include <llvm/IR/Verifier.h>
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Module.h>
#include <llvm/IR/Instructions.h>
#include <llvm/Support/SourceMgr.h>
#include <llvm/Support/raw_os_ostream.h>
#include <llvm/IRReader/IRReader.h>
#include <llvm/Bitcode/ReaderWriter.h>

#include <iostream>
#include <fstream>
#include "llvm/LLVMDependenceGraph.h"
#include "llvm/PointsTo.h"
#include "llvm/DefUse.h"
#include "llvm/Slicer.h"
#include "Utils.h"

using namespace dg;
using llvm::errs;

static bool slice(llvm::Module *M, const char *slicing_criterion)
{
    debug::TimeMeasure tm;
    LLVMDependenceGraph d;
    std::set<LLVMNode *> gatheredCallsites;

    d.gatherCallsites(slicing_criterion, &gatheredCallsites);

    // build the graph
    d.build(&*M);

    // verify if the graph is built correctly
    // FIXME - do it optionally (command line argument)
    if (!d.verify())
        errs() << "ERR: verifying failed\n";

    if (gatheredCallsites.empty()) {
        if (strcmp(slicing_criterion, "ret") == 0)
            gatheredCallsites.insert(d.getExit());
        else {
            errs() << "Did not find slicing criterion: " << slicing_criterion << "\n";
            return false;
        }
    }

    analysis::LLVMPointsToAnalysis PTA(&d);

    tm.start();
    PTA.run();
    tm.stop();
    tm.report("INFO: Points-to analysis took");

    // we might added some new functions
    // so verify once again
    if (!d.verify())
        errs() << "ERR: verifying failed\n";

    analysis::LLVMDefUseAnalysis DUA(&d);

    tm.start();
    DUA.run();  // compute reaching definitions
    tm.stop();
    tm.report("INFO: Reaching defs analysis took");

    tm.start();
    DUA.addDefUseEdges(); // add def-use edges according that
    tm.stop();
    tm.report("INFO: Adding Def-Use edges took");

    tm.start();
    // add post-dominator frontiers
    d.computePostDominators(true);
    tm.stop();
    tm.report("INFO: computing post-dominator frontiers took");

    LLVMSlicer slicer;
    uint32_t slid = 0;

    tm.start();
    for (LLVMNode *start : gatheredCallsites)
        slid = slicer.mark(start, slid);

    slicer.slice(&d, nullptr, slid);

    tm.stop();
    tm.report("INFO: Slicing took");

    auto st = slicer.getStatistics();
    errs() << "INFO: Sliced away " << st.second
           << " from " << st.first << " nodes\n";

    return true;
}

static void remove_unused_from_module(llvm::Module *M)
{
    using namespace llvm;
    llvm::StringRef main("main");

    // when erasing while iterating the slicer crashes
    // so set the to be erased values into container
    // and then erase them
    std::set<Function *> funs;
    std::set<GlobalVariable *> globals;

    for (auto I = M->begin(), E = M->end(); I != E; ++I) {
        Function *func = &*I;
        if (func->hasNUses(0) && !func->getName().equals(main))
            funs.insert(func);
    }

    for (auto I = M->global_begin(), E = M->global_end(); I != E; ++I) {
        GlobalVariable *gv = &*I;
        if (gv->hasNUses(0))
            globals.insert(gv);
    }

    for (Function *f : funs)
        f->eraseFromParent();
    for (GlobalVariable *gv : globals)
        gv->eraseFromParent();
}

static bool verify_module(llvm::Module *M)
{
    // the verifyModule function returns false if there
    // are no errors
    return !llvm::verifyModule(*M, &errs());
}

static bool write_module(llvm::Module *M, const char *module_name)
{
    // compose name
    std::string fl(module_name);
    fl.replace(fl.end() - 3, fl.end(), ".sliced");

    // open stream to write to
    std::ofstream ofs(fl);
    llvm::raw_os_ostream output(ofs);

    // write the module
    errs() << "INFO: saving sliced module to: " << fl.c_str() << "\n";
    llvm::WriteBitcodeToFile(M, output);

    return true;
}

int main(int argc, char *argv[])
{
    llvm::LLVMContext context;
    llvm::SMDiagnostic SMD;
    std::unique_ptr<llvm::Module> M;

    const char *slicing_criterion = NULL;
    const char *module = NULL;

    // parse options
    for (int i = 1; i < argc; ++i) {
        if (strcmp(argv[i], "-v") == 0
            || strcmp(argv[i], "-version") == 0) {
            errs() << GIT_VERSION << "\n";
            exit(0);
        } else if (strcmp(argv[i], "-c") == 0
            || strcmp(argv[i], "-crit") == 0
            || strcmp(argv[i], "-slice") == 0){
            slicing_criterion = argv[++i];
        } else {
            module = argv[i];
        }
    }

    if (!slicing_criterion || !module) {
        errs() << "Usage: % [-c|-crit|-slice] func_call module\n";
        return 1;
    }

    M = llvm::parseIRFile(module, SMD, context);
    if (!M) {
        SMD.print(argv[0], errs());
        return 1;
    }

    if (!slice(&*M, slicing_criterion)) {
        errs() << "ERR: Slicing failed\n";
        return 1;
    }

    remove_unused_from_module(&*M);

    if (!verify_module(&*M)) {
        errs() << "ERR: Verifying module failed, the IR is not valid\n";
        errs() << "INFO: Saving anyway so that you can check it\n";
    }

    if (!write_module(&*M, module)) {
        errs() << "Saving sliced module failed\n";
        return 1;
    }

    return 0;
}
<commit_msg>llvm-slicer: check for criterion after points-to analysis<commit_after>#include <assert.h>
#include <cstdio>
#include <cstring>

#include <set>

#ifndef HAVE_LLVM
#error "This code needs LLVM enabled"
#endif

#include "../git-version.h"

#include <llvm/IR/Verifier.h>
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Module.h>
#include <llvm/IR/Instructions.h>
#include <llvm/Support/SourceMgr.h>
#include <llvm/Support/raw_os_ostream.h>
#include <llvm/IRReader/IRReader.h>
#include <llvm/Bitcode/ReaderWriter.h>

#include <iostream>
#include <fstream>
#include "llvm/LLVMDependenceGraph.h"
#include "llvm/PointsTo.h"
#include "llvm/DefUse.h"
#include "llvm/Slicer.h"
#include "Utils.h"

using namespace dg;
using llvm::errs;

static bool slice(llvm::Module *M, const char *slicing_criterion)
{
    debug::TimeMeasure tm;
    LLVMDependenceGraph d;
    std::set<LLVMNode *> gatheredCallsites;

    d.gatherCallsites(slicing_criterion, &gatheredCallsites);

    // build the graph
    d.build(&*M);

    // verify if the graph is built correctly
    // FIXME - do it optionally (command line argument)
    if (!d.verify())
        errs() << "ERR: verifying failed\n";

    analysis::LLVMPointsToAnalysis PTA(&d);

    tm.start();
    PTA.run();
    tm.stop();
    tm.report("INFO: Points-to analysis took");

    // we might added some new functions
    // so verify once again
    if (!d.verify())
        errs() << "ERR: verifying failed\n";

    // check for slicing criterion here, because
    // we might have built new subgraphs that contain
    // it during points-to analysis
    if (gatheredCallsites.empty()) {
        if (strcmp(slicing_criterion, "ret") == 0)
            gatheredCallsites.insert(d.getExit());
        else {
            errs() << "Did not find slicing criterion: "
                   << slicing_criterion << "\n";
            return false;
        }
    }

    analysis::LLVMDefUseAnalysis DUA(&d);

    tm.start();
    DUA.run();  // compute reaching definitions
    tm.stop();
    tm.report("INFO: Reaching defs analysis took");

    tm.start();
    DUA.addDefUseEdges(); // add def-use edges according that
    tm.stop();
    tm.report("INFO: Adding Def-Use edges took");

    tm.start();
    // add post-dominator frontiers
    d.computePostDominators(true);
    tm.stop();
    tm.report("INFO: computing post-dominator frontiers took");

    LLVMSlicer slicer;
    uint32_t slid = 0;

    tm.start();
    for (LLVMNode *start : gatheredCallsites)
        slid = slicer.mark(start, slid);

    slicer.slice(&d, nullptr, slid);

    tm.stop();
    tm.report("INFO: Slicing took");

    auto st = slicer.getStatistics();
    errs() << "INFO: Sliced away " << st.second
           << " from " << st.first << " nodes\n";

    return true;
}

static void remove_unused_from_module(llvm::Module *M)
{
    using namespace llvm;
    llvm::StringRef main("main");

    // when erasing while iterating the slicer crashes
    // so set the to be erased values into container
    // and then erase them
    std::set<Function *> funs;
    std::set<GlobalVariable *> globals;

    for (auto I = M->begin(), E = M->end(); I != E; ++I) {
        Function *func = &*I;
        if (func->hasNUses(0) && !func->getName().equals(main))
            funs.insert(func);
    }

    for (auto I = M->global_begin(), E = M->global_end(); I != E; ++I) {
        GlobalVariable *gv = &*I;
        if (gv->hasNUses(0))
            globals.insert(gv);
    }

    for (Function *f : funs)
        f->eraseFromParent();
    for (GlobalVariable *gv : globals)
        gv->eraseFromParent();
}

static bool verify_module(llvm::Module *M)
{
    // the verifyModule function returns false if there
    // are no errors
    return !llvm::verifyModule(*M, &errs());
}

static bool write_module(llvm::Module *M, const char *module_name)
{
    // compose name
    std::string fl(module_name);
    fl.replace(fl.end() - 3, fl.end(), ".sliced");

    // open stream to write to
    std::ofstream ofs(fl);
    llvm::raw_os_ostream output(ofs);

    // write the module
    errs() << "INFO: saving sliced module to: " << fl.c_str() << "\n";
    llvm::WriteBitcodeToFile(M, output);

    return true;
}

int main(int argc, char *argv[])
{
    llvm::LLVMContext context;
    llvm::SMDiagnostic SMD;
    std::unique_ptr<llvm::Module> M;

    const char *slicing_criterion = NULL;
    const char *module = NULL;

    // parse options
    for (int i = 1; i < argc; ++i) {
        if (strcmp(argv[i], "-v") == 0
            || strcmp(argv[i], "-version") == 0) {
            errs() << GIT_VERSION << "\n";
            exit(0);
        } else if (strcmp(argv[i], "-c") == 0
            || strcmp(argv[i], "-crit") == 0
            || strcmp(argv[i], "-slice") == 0){
            slicing_criterion = argv[++i];
        } else {
            module = argv[i];
        }
    }

    if (!slicing_criterion || !module) {
        errs() << "Usage: % [-c|-crit|-slice] func_call module\n";
        return 1;
    }

    M = llvm::parseIRFile(module, SMD, context);
    if (!M) {
        SMD.print(argv[0], errs());
        return 1;
    }

    if (!slice(&*M, slicing_criterion)) {
        errs() << "ERR: Slicing failed\n";
        return 1;
    }

    remove_unused_from_module(&*M);

    if (!verify_module(&*M)) {
        errs() << "ERR: Verifying module failed, the IR is not valid\n";
        errs() << "INFO: Saving anyway so that you can check it\n";
    }

    if (!write_module(&*M, module)) {
        errs() << "Saving sliced module failed\n";
        return 1;
    }

    return 0;
}
<|endoftext|>


<commit_before>// exposes the glob function to node.

// int
// glob(const char *restrict pattern, int flags,
//     int (*errfunc)(const char *epath, int errno), glob_t *restrict pglob);

#include <v8.h>
#include <glob.h>
#include <node.h>

using namespace std;
using namespace node;
using namespace v8;

#include "glob_constants.h"

static Handle<String>
GlobError (int er) {
  switch (er) {
    case GLOB_ABORTED: return String::New("GLOB_ABORTED"); break;
    case GLOB_NOMATCH: return String::New("GLOB_NOMATCH"); break;
    case GLOB_NOSPACE: return String::New("GLOB_NOSPACE"); break;
  }

  return String::New("undefined glob error");
}

static Handle<Value> Throw (int);
static Handle<Value> Throw (const char*);
static Handle<Value> Throw (Handle<String>);

static Handle<Value>
Throw (int msg) {
  return Throw(GlobError(msg));
}
static Handle<Value>
Throw (const char* msg) {
  return Throw(String::New(msg));
}
static Handle<Value>
Throw (Handle<String> msg) {
  ThrowException(Exception::Error(msg));
}

// async EIO globbing
struct glob_request {
  Persistent<Function> cb;
  glob_t *g;
  int retval;
  int flags;
  char *pattern;
};
static int EIO_Glob (eio_req *req) {
  glob_request *gr = (glob_request *)req->data;
  gr->retval = glob(gr->pattern, gr->flags, NULL, gr->g);
  return 0;
}
static int EIO_GlobAfter (eio_req *req) {
  HandleScope scope;
  ev_unref(EV_DEFAULT_UC);
  glob_request *gr = (glob_request *)req->data;
  glob_t *g = gr->g;

  Local<Value> argv[2];
  if (gr->retval != 0) {
    argv[0] = Exception::Error(GlobError(gr->retval));
  } else {
    Local<Array> pathv = Array::New(g->gl_pathc);
    for (int i = 0; i < g->gl_pathc; i ++) {
      pathv->Set(Integer::New(i), String::New(g->gl_pathv[i]));
    }
    argv[0] = Local<Value>::New(Null());
    argv[1] = pathv;
  }

  TryCatch try_catch;
  gr->cb->Call(Context::GetCurrent()->Global(), 2, argv);
  if (try_catch.HasCaught()) {
    FatalException(try_catch);
  }
  // fprintf(stderr, "EIO_GlobAfter about to free\n");
  gr->cb.Dispose();
  globfree(g);
  free(gr);
  // fprintf(stderr, "EIO_GlobAfter freed\n");
  return 0;
}
static Handle<Value> GlobAsync (const Arguments& args) {
  HandleScope scope;
  const char *usage = "usage: glob(pattern, flags, cb)";

  if (args.Length() != 3) {
    Throw(usage);
  }

  String::Utf8Value pattern(args[0]);
  int flags = args[1]->Int32Value();
  Local<Function> cb = Local<Function>::Cast(args[2]);

  glob_request *gr = (glob_request *)malloc(sizeof(glob_request));
  gr->cb = Persistent<Function>::New(cb);
  gr->pattern = *pattern;
  gr->flags = flags;
  gr->g = new glob_t;
  eio_custom(EIO_Glob, EIO_PRI_DEFAULT, EIO_GlobAfter, gr);
  ev_ref(EV_DEFAULT_UC);

  return Undefined();
}

// synchronous globbing.
static Handle<Value> GlobSync (const Arguments& args) {
  HandleScope scope;
  const char * usage = "usage: globSync(pattern, flags)";
  if (args.Length() != 2) {
    return Throw(usage);
  }

  String::Utf8Value pattern(args[0]);

  int flags = args[1]->Int32Value();

  glob_t g;
  int retval = glob(*pattern, flags, NULL, &g);

  if (retval != 0) {
    globfree(&g);
    return Throw(retval);
  }

  // create a JS array
  // loop through the g.gl_pathv adding JS strings to the JS array.
  // then return the JS array.
  Handle<Array> pathv = Array::New(g.gl_pathc);
  for (int i = 0; i < g.gl_pathc; i ++) {
    pathv->Set(Integer::New(i), String::New(g.gl_pathv[i]));
  }

  globfree(&g);
  return scope.Close(pathv);
}

extern "C" void
init (Handle<Object> target)
{
  HandleScope scope;
  GlobConstants(target);
  NODE_SET_METHOD(target, "glob", GlobAsync);
  NODE_SET_METHOD(target, "globSync", GlobSync);
}

<commit_msg>Avoid segfaults!  Hooray!<commit_after>// exposes the glob function to node.

// int
// glob(const char *restrict pattern, int flags,
//     int (*errfunc)(const char *epath, int errno), glob_t *restrict pglob);

#include <v8.h>
#include <glob.h>
#include <node.h>
#include <string.h>

using namespace std;
using namespace node;
using namespace v8;

#include "glob_constants.h"

static Handle<String>
GlobError (int er) {
  switch (er) {
    case GLOB_ABORTED: return String::New("GLOB_ABORTED"); break;
    case GLOB_NOMATCH: return String::New("GLOB_NOMATCH"); break;
    case GLOB_NOSPACE: return String::New("GLOB_NOSPACE"); break;
  }

  return String::New("undefined glob error");
}

static Handle<Value> Throw (int);
static Handle<Value> Throw (const char*);
static Handle<Value> Throw (Handle<String>);

static Handle<Value>
Throw (int msg) {
  return Throw(GlobError(msg));
}
static Handle<Value>
Throw (const char* msg) {
  return Throw(String::New(msg));
}
static Handle<Value>
Throw (Handle<String> msg) {
  ThrowException(Exception::Error(msg));
}

// async EIO globbing
struct glob_request {
  Persistent<Function> cb;
  glob_t *g;
  int retval;
  int flags;
  char pattern[1];
};
static int EIO_Glob (eio_req *req) {
  glob_request *gr = (glob_request *)req->data;
  gr->retval = glob(gr->pattern, gr->flags, NULL, gr->g);
  return 0;
}
static int EIO_GlobAfter (eio_req *req) {
  HandleScope scope;
  ev_unref(EV_DEFAULT_UC);
  glob_request *gr = (glob_request *)req->data;
  glob_t *g = gr->g;

  Local<Value> argv[2];
  if (gr->retval != 0) {
    argv[0] = Exception::Error(GlobError(gr->retval));
    argv[1] = String::New(gr->pattern);
  } else {
    Local<Array> pathv = Array::New(g->gl_pathc);
    for (int i = 0; i < g->gl_pathc; i ++) {
      pathv->Set(Integer::New(i), String::New(g->gl_pathv[i]));
    }
    argv[0] = Local<Value>::New(Null());
    argv[1] = pathv;
  }

  TryCatch try_catch;
  gr->cb->Call(Context::GetCurrent()->Global(), 2, argv);
  if (try_catch.HasCaught()) {
    FatalException(try_catch);
  }
  // fprintf(stderr, "EIO_GlobAfter about to free\n");
  gr->cb.Dispose();
  globfree(g);
  free(gr);
  // fprintf(stderr, "EIO_GlobAfter freed\n");
  return 0;
}
static Handle<Value> GlobAsync (const Arguments& args) {
  HandleScope scope;
  const char *usage = "usage: glob(pattern, flags, cb)";

  if (args.Length() != 3) {
    Throw(usage);
  }

  String::Utf8Value pattern(args[0]);

  int flags = args[1]->Int32Value();
  Local<Function> cb = Local<Function>::Cast(args[2]);

  glob_request *gr = (glob_request *)
    calloc(1, sizeof(struct glob_request) + pattern.length() + 1);

  gr->cb = Persistent<Function>::New(cb);
  strncpy(gr->pattern, *pattern, pattern.length() + 1);
  gr->flags = flags;
  gr->g = new glob_t;
  eio_custom(EIO_Glob, EIO_PRI_DEFAULT, EIO_GlobAfter, gr);
  ev_ref(EV_DEFAULT_UC);

  return Undefined();
}

// synchronous globbing.
static Handle<Value> GlobSync (const Arguments& args) {
  HandleScope scope;
  const char * usage = "usage: globSync(pattern, flags)";
  if (args.Length() != 2) {
    return Throw(usage);
  }

  String::Utf8Value pattern(args[0]);

  int flags = args[1]->Int32Value();

  glob_t g;
  int retval = glob(*pattern, flags, NULL, &g);

  if (retval != 0) {
    globfree(&g);
    return Throw(retval);
  }

  // create a JS array
  // loop through the g.gl_pathv adding JS strings to the JS array.
  // then return the JS array.
  Handle<Array> pathv = Array::New(g.gl_pathc);
  for (int i = 0; i < g.gl_pathc; i ++) {
    pathv->Set(Integer::New(i), String::New(g.gl_pathv[i]));
  }

  globfree(&g);
  return scope.Close(pathv);
}

extern "C" void
init (Handle<Object> target)
{
  HandleScope scope;
  GlobConstants(target);
  NODE_SET_METHOD(target, "glob", GlobAsync);
  NODE_SET_METHOD(target, "globSync", GlobSync);
}

<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
/// @brief debugging helpers
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2014 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// 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.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Jan Steemann
/// @author Copyright 2014, ArangoDB GmbH, Cologne, Germany
/// @author Copyright 2011-2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

#include "Basics/Common.h"
#include "Basics/locks.h"
#include "Basics/logging.h"

#ifdef TRI_ENABLE_MAINTAINER_MODE
#if HAVE_BACKTRACE
#ifdef _WIN32
#include <DbgHelp.h>
#else
#include <execinfo.h>
#include <cxxabi.h>
#endif
#endif
#endif

// -----------------------------------------------------------------------------
// --SECTION--                                                 private variables
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief a global string containing the currently registered failure points
/// the string is a comma-separated list of point names
////////////////////////////////////////////////////////////////////////////////

static char* FailurePoints;

////////////////////////////////////////////////////////////////////////////////
/// @brief a read-write lock for thread-safe access to the failure-points list
////////////////////////////////////////////////////////////////////////////////

TRI_read_write_lock_t FailurePointsLock;

#ifdef TRI_ENABLE_FAILURE_TESTS

// -----------------------------------------------------------------------------
// --SECTION--                                                 private functions
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief make a delimited value from a string, so we can unambigiously
/// search for it (e.g. searching for just "foo" would find "foo" and "foobar",
/// so we'll be putting the value inside some delimiter: ",foo,")
////////////////////////////////////////////////////////////////////////////////

static char* MakeValue (char const* value) {
  if (value == nullptr || strlen(value) == 0) {
    return nullptr;
  }

  char* delimited = static_cast<char*>(TRI_Allocate(TRI_CORE_MEM_ZONE, strlen(value) + 3, false));

  if (delimited != nullptr) {
    memcpy(delimited + 1, value, strlen(value));
    delimited[0] = ',';
    delimited[strlen(value) + 1] = ',';
    delimited[strlen(value) + 2] = '\0';
  }

  return delimited;
}

// -----------------------------------------------------------------------------
// --SECTION--                                                  public functions
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief cause a segmentation violation
/// this is used for crash and recovery tests
////////////////////////////////////////////////////////////////////////////////

void TRI_SegfaultDebugging (char const* message) {
  LOG_WARNING("%s: summon Baal!", message);
  // make sure the latest log messages are flushed
  TRI_ShutdownLogging(true);

  // and now crash
#ifndef __APPLE__
  // on MacOS, the following statement makes the server hang but not crash
  *((char*) -1) = '!';
#endif

  // ensure the process is terminated
  abort();
}

////////////////////////////////////////////////////////////////////////////////
/// @brief check whether we should fail at a specific failure point
////////////////////////////////////////////////////////////////////////////////

bool TRI_ShouldFailDebugging (char const* value) {
  char* found = nullptr;

  // try without the lock first (to speed things up)
  if (FailurePoints == nullptr) {
    return false;
  }

  TRI_ReadLockReadWriteLock(&FailurePointsLock);

  if (FailurePoints != nullptr) {
    char* checkValue = MakeValue(value);

    if (checkValue != nullptr) {
      found = strstr(FailurePoints, checkValue);
      TRI_Free(TRI_CORE_MEM_ZONE, checkValue);
    }
  }

  TRI_ReadUnlockReadWriteLock(&FailurePointsLock);

  return (found != nullptr);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief add a failure point
////////////////////////////////////////////////////////////////////////////////

void TRI_AddFailurePointDebugging (char const* value) {
  char* found;
  char* checkValue;

  checkValue = MakeValue(value);

  if (checkValue == nullptr) {
    return;
  }

  TRI_WriteLockReadWriteLock(&FailurePointsLock);

  if (FailurePoints == nullptr) {
    found = nullptr;
  }
  else {
    found = strstr(FailurePoints, checkValue);
  }

  if (found == nullptr) {
    // not yet found. so add it
    char* copy;
    size_t n;

    LOG_WARNING("activating intentional failure point '%s'. the server will misbehave!", value);
    n = strlen(checkValue);

    if (FailurePoints == nullptr) {
      copy = static_cast<char*>(TRI_Allocate(TRI_CORE_MEM_ZONE, n + 1, false));

      if (copy == nullptr) {
        TRI_WriteUnlockReadWriteLock(&FailurePointsLock);
        TRI_Free(TRI_CORE_MEM_ZONE, checkValue);
        return;
      }

      memcpy(copy, checkValue, n);
      copy[n] = '\0';
    }
    else {
      copy = static_cast<char*>(TRI_Allocate(TRI_CORE_MEM_ZONE, n + strlen(FailurePoints), false));

      if (copy == nullptr) {
        TRI_WriteUnlockReadWriteLock(&FailurePointsLock);
        TRI_Free(TRI_CORE_MEM_ZONE, checkValue);
        return;
      }

      memcpy(copy, FailurePoints, strlen(FailurePoints));
      memcpy(copy + strlen(FailurePoints) - 1, checkValue, n);
      copy[strlen(FailurePoints) + n - 1] = '\0';
    }

    FailurePoints = copy;
  }

  TRI_WriteUnlockReadWriteLock(&FailurePointsLock);
  TRI_Free(TRI_CORE_MEM_ZONE, checkValue);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief remove a failure points
////////////////////////////////////////////////////////////////////////////////

void TRI_RemoveFailurePointDebugging (char const* value) {
  char* checkValue;

  TRI_WriteLockReadWriteLock(&FailurePointsLock);

  if (FailurePoints == nullptr) {
    TRI_WriteUnlockReadWriteLock(&FailurePointsLock);
    return;
  }

  checkValue = MakeValue(value);

  if (checkValue != nullptr) {
    char* found;
    char* copy;
    size_t n;

    found = strstr(FailurePoints, checkValue);

    if (found == nullptr) {
      TRI_WriteUnlockReadWriteLock(&FailurePointsLock);
      TRI_Free(TRI_CORE_MEM_ZONE, checkValue);
      return;
    }

    if (strlen(FailurePoints) - strlen(checkValue) <= 2) {
      TRI_Free(TRI_CORE_MEM_ZONE, FailurePoints);
      FailurePoints = nullptr;

      TRI_WriteUnlockReadWriteLock(&FailurePointsLock);
      TRI_Free(TRI_CORE_MEM_ZONE, checkValue);
      return;
    }

    copy = static_cast<char*>(TRI_Allocate(TRI_CORE_MEM_ZONE, strlen(FailurePoints) - strlen(checkValue) + 2, false));

    if (copy == nullptr) {
      TRI_WriteUnlockReadWriteLock(&FailurePointsLock);
      TRI_Free(TRI_CORE_MEM_ZONE, checkValue);
      return;
    }

    // copy start of string
    n = found - FailurePoints;
    memcpy(copy, FailurePoints, n);

    // copy remainder of string
    memcpy(copy + n, found + strlen(checkValue) - 1, strlen(FailurePoints) - strlen(checkValue) - n + 1);

    copy[strlen(FailurePoints) - strlen(checkValue) + 1] = '\0';
    TRI_Free(TRI_CORE_MEM_ZONE, FailurePoints);
    FailurePoints = copy;

    TRI_WriteUnlockReadWriteLock(&FailurePointsLock);
    TRI_Free(TRI_CORE_MEM_ZONE, checkValue);
  }
}

////////////////////////////////////////////////////////////////////////////////
/// @brief clear all failure points
////////////////////////////////////////////////////////////////////////////////

void TRI_ClearFailurePointsDebugging () {
  TRI_WriteLockReadWriteLock(&FailurePointsLock);

  if (FailurePoints != nullptr) {
    TRI_Free(TRI_CORE_MEM_ZONE, FailurePoints);
  }

  FailurePoints = nullptr;

  TRI_WriteUnlockReadWriteLock(&FailurePointsLock);
}

#endif

////////////////////////////////////////////////////////////////////////////////
/// @brief initialise the debugging
////////////////////////////////////////////////////////////////////////////////

void TRI_InitialiseDebugging () {
  FailurePoints = nullptr;
  TRI_InitReadWriteLock(&FailurePointsLock);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief shutdown the debugging
////////////////////////////////////////////////////////////////////////////////

void TRI_ShutdownDebugging () {
  if (FailurePoints != nullptr) {
    TRI_Free(TRI_CORE_MEM_ZONE, FailurePoints);
  }

  FailurePoints = nullptr;

  TRI_DestroyReadWriteLock(&FailurePointsLock);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief appends a backtrace to the string provided
////////////////////////////////////////////////////////////////////////////////

void TRI_GetBacktrace (std::string& btstr) {
#if HAVE_BACKTRACE
#ifdef _WIN32
  void         * stack[100];
  unsigned short frames;
  SYMBOL_INFO  * symbol;
  HANDLE         process;

  process = GetCurrentProcess();

  SymInitialize(process, nullptr, true);

  frames               = CaptureStackBackTrace(0, 100, stack, nullptr);
  symbol               = (SYMBOL_INFO*) calloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char), 1);

  if (symbol == nullptr) {
    // cannot allocate memory
    return;
  }

  symbol->MaxNameLen   = 255;
  symbol->SizeOfStruct = sizeof(SYMBOL_INFO);

  for (unsigned int i = 0; i < frames; i++) {
    char address[64];
    SymFromAddr(process, (DWORD64) stack[i], 0, symbol);

    snprintf(address, sizeof(address), "0x%0X", symbol->Address);
    btstr += std::to_string(frames - i - 1) + std::string(": ") + symbol->Name + std::string(" [") + address + std::string("]\n");
  }

  TRI_SystemFree(symbol);

#else
  void* stack_frames[50];
  size_t size, i;
  char** strings;

  size = backtrace(stack_frames, sizeof(stack_frames) / sizeof(void*));
  strings = backtrace_symbols(stack_frames, size);
  for (i = 0; i < size; i++) {
    std::stringstream ss;
    if (strings != nullptr) {
      char *mangled_name = nullptr, *offset_begin = nullptr, *offset_end = nullptr;

      // find parantheses and +address offset surrounding mangled name
      for (char *p = strings[i]; *p; ++p) {
        if (*p == '(') {
          mangled_name = p;
        }
        else if (*p == '+') {
          offset_begin = p;
        }
        else if (*p == ')') {
          offset_end = p;
          break;
        }
      }

      // if the line could be processed, attempt to demangle the symbol
      if (mangled_name && offset_begin && offset_end &&
          mangled_name < offset_begin) {
        *mangled_name++ = '\0';
        *offset_begin++ = '\0';
        *offset_end++ = '\0';
        int status = 0;
        char * demangled_name = abi::__cxa_demangle(mangled_name, 0, 0, &status);

        if (demangled_name != nullptr) {
          if (status == 0) {
            ss << stack_frames[i];
            btstr +=  strings[i] +
              std::string("() [") +
              ss.str() +
              std::string("] ") +
              demangled_name +
              std::string("\n");
          }
          else {
            btstr += strings[i] +
              std::string("\n");
          }
          TRI_SystemFree(demangled_name);
        }
      }
      else {
        btstr += strings[i] +
          std::string("\n");
      }
    }
    else {
      ss << stack_frames[i];
      btstr += ss.str() +
        std::string("\n");
    }
  }
  if (strings != nullptr) {
    TRI_SystemFree(strings);
  }
#endif
#endif
}

////////////////////////////////////////////////////////////////////////////////
/// @brief prints a backtrace on stderr
////////////////////////////////////////////////////////////////////////////////

void TRI_PrintBacktrace () {
#if HAVE_BACKTRACE
  std::string out;
  TRI_GetBacktrace(out);
  fprintf(stderr, "%s", out.c_str());
#endif
}

// -----------------------------------------------------------------------------
// --SECTION--                                                       END-OF-FILE
// -----------------------------------------------------------------------------

// Local Variables:
// mode: outline-minor
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @page\\|// --SECTION--\\|/// @\\}"
// End:
<commit_msg>Namespace demangling for macos X - todo make this work.<commit_after>////////////////////////////////////////////////////////////////////////////////
/// @brief debugging helpers
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2014 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// 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.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Jan Steemann
/// @author Copyright 2014, ArangoDB GmbH, Cologne, Germany
/// @author Copyright 2011-2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

#include "Basics/Common.h"
#include "Basics/locks.h"
#include "Basics/logging.h"

#ifdef TRI_ENABLE_MAINTAINER_MODE
#if HAVE_BACKTRACE
#ifdef _WIN32
#include <DbgHelp.h>
#else
#include <execinfo.h>
#include <cxxabi.h>
#endif
#endif
#endif

// -----------------------------------------------------------------------------
// --SECTION--                                                 private variables
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief a global string containing the currently registered failure points
/// the string is a comma-separated list of point names
////////////////////////////////////////////////////////////////////////////////

static char* FailurePoints;

////////////////////////////////////////////////////////////////////////////////
/// @brief a read-write lock for thread-safe access to the failure-points list
////////////////////////////////////////////////////////////////////////////////

TRI_read_write_lock_t FailurePointsLock;

#ifdef TRI_ENABLE_FAILURE_TESTS

// -----------------------------------------------------------------------------
// --SECTION--                                                 private functions
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief make a delimited value from a string, so we can unambigiously
/// search for it (e.g. searching for just "foo" would find "foo" and "foobar",
/// so we'll be putting the value inside some delimiter: ",foo,")
////////////////////////////////////////////////////////////////////////////////

static char* MakeValue (char const* value) {
  if (value == nullptr || strlen(value) == 0) {
    return nullptr;
  }

  char* delimited = static_cast<char*>(TRI_Allocate(TRI_CORE_MEM_ZONE, strlen(value) + 3, false));

  if (delimited != nullptr) {
    memcpy(delimited + 1, value, strlen(value));
    delimited[0] = ',';
    delimited[strlen(value) + 1] = ',';
    delimited[strlen(value) + 2] = '\0';
  }

  return delimited;
}

// -----------------------------------------------------------------------------
// --SECTION--                                                  public functions
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief cause a segmentation violation
/// this is used for crash and recovery tests
////////////////////////////////////////////////////////////////////////////////

void TRI_SegfaultDebugging (char const* message) {
  LOG_WARNING("%s: summon Baal!", message);
  // make sure the latest log messages are flushed
  TRI_ShutdownLogging(true);

  // and now crash
#ifndef __APPLE__
  // on MacOS, the following statement makes the server hang but not crash
  *((char*) -1) = '!';
#endif

  // ensure the process is terminated
  abort();
}

////////////////////////////////////////////////////////////////////////////////
/// @brief check whether we should fail at a specific failure point
////////////////////////////////////////////////////////////////////////////////

bool TRI_ShouldFailDebugging (char const* value) {
  char* found = nullptr;

  // try without the lock first (to speed things up)
  if (FailurePoints == nullptr) {
    return false;
  }

  TRI_ReadLockReadWriteLock(&FailurePointsLock);

  if (FailurePoints != nullptr) {
    char* checkValue = MakeValue(value);

    if (checkValue != nullptr) {
      found = strstr(FailurePoints, checkValue);
      TRI_Free(TRI_CORE_MEM_ZONE, checkValue);
    }
  }

  TRI_ReadUnlockReadWriteLock(&FailurePointsLock);

  return (found != nullptr);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief add a failure point
////////////////////////////////////////////////////////////////////////////////

void TRI_AddFailurePointDebugging (char const* value) {
  char* found;
  char* checkValue;

  checkValue = MakeValue(value);

  if (checkValue == nullptr) {
    return;
  }

  TRI_WriteLockReadWriteLock(&FailurePointsLock);

  if (FailurePoints == nullptr) {
    found = nullptr;
  }
  else {
    found = strstr(FailurePoints, checkValue);
  }

  if (found == nullptr) {
    // not yet found. so add it
    char* copy;
    size_t n;

    LOG_WARNING("activating intentional failure point '%s'. the server will misbehave!", value);
    n = strlen(checkValue);

    if (FailurePoints == nullptr) {
      copy = static_cast<char*>(TRI_Allocate(TRI_CORE_MEM_ZONE, n + 1, false));

      if (copy == nullptr) {
        TRI_WriteUnlockReadWriteLock(&FailurePointsLock);
        TRI_Free(TRI_CORE_MEM_ZONE, checkValue);
        return;
      }

      memcpy(copy, checkValue, n);
      copy[n] = '\0';
    }
    else {
      copy = static_cast<char*>(TRI_Allocate(TRI_CORE_MEM_ZONE, n + strlen(FailurePoints), false));

      if (copy == nullptr) {
        TRI_WriteUnlockReadWriteLock(&FailurePointsLock);
        TRI_Free(TRI_CORE_MEM_ZONE, checkValue);
        return;
      }

      memcpy(copy, FailurePoints, strlen(FailurePoints));
      memcpy(copy + strlen(FailurePoints) - 1, checkValue, n);
      copy[strlen(FailurePoints) + n - 1] = '\0';
    }

    FailurePoints = copy;
  }

  TRI_WriteUnlockReadWriteLock(&FailurePointsLock);
  TRI_Free(TRI_CORE_MEM_ZONE, checkValue);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief remove a failure points
////////////////////////////////////////////////////////////////////////////////

void TRI_RemoveFailurePointDebugging (char const* value) {
  char* checkValue;

  TRI_WriteLockReadWriteLock(&FailurePointsLock);

  if (FailurePoints == nullptr) {
    TRI_WriteUnlockReadWriteLock(&FailurePointsLock);
    return;
  }

  checkValue = MakeValue(value);

  if (checkValue != nullptr) {
    char* found;
    char* copy;
    size_t n;

    found = strstr(FailurePoints, checkValue);

    if (found == nullptr) {
      TRI_WriteUnlockReadWriteLock(&FailurePointsLock);
      TRI_Free(TRI_CORE_MEM_ZONE, checkValue);
      return;
    }

    if (strlen(FailurePoints) - strlen(checkValue) <= 2) {
      TRI_Free(TRI_CORE_MEM_ZONE, FailurePoints);
      FailurePoints = nullptr;

      TRI_WriteUnlockReadWriteLock(&FailurePointsLock);
      TRI_Free(TRI_CORE_MEM_ZONE, checkValue);
      return;
    }

    copy = static_cast<char*>(TRI_Allocate(TRI_CORE_MEM_ZONE, strlen(FailurePoints) - strlen(checkValue) + 2, false));

    if (copy == nullptr) {
      TRI_WriteUnlockReadWriteLock(&FailurePointsLock);
      TRI_Free(TRI_CORE_MEM_ZONE, checkValue);
      return;
    }

    // copy start of string
    n = found - FailurePoints;
    memcpy(copy, FailurePoints, n);

    // copy remainder of string
    memcpy(copy + n, found + strlen(checkValue) - 1, strlen(FailurePoints) - strlen(checkValue) - n + 1);

    copy[strlen(FailurePoints) - strlen(checkValue) + 1] = '\0';
    TRI_Free(TRI_CORE_MEM_ZONE, FailurePoints);
    FailurePoints = copy;

    TRI_WriteUnlockReadWriteLock(&FailurePointsLock);
    TRI_Free(TRI_CORE_MEM_ZONE, checkValue);
  }
}

////////////////////////////////////////////////////////////////////////////////
/// @brief clear all failure points
////////////////////////////////////////////////////////////////////////////////

void TRI_ClearFailurePointsDebugging () {
  TRI_WriteLockReadWriteLock(&FailurePointsLock);

  if (FailurePoints != nullptr) {
    TRI_Free(TRI_CORE_MEM_ZONE, FailurePoints);
  }

  FailurePoints = nullptr;

  TRI_WriteUnlockReadWriteLock(&FailurePointsLock);
}

#endif

////////////////////////////////////////////////////////////////////////////////
/// @brief initialise the debugging
////////////////////////////////////////////////////////////////////////////////

void TRI_InitialiseDebugging () {
  FailurePoints = nullptr;
  TRI_InitReadWriteLock(&FailurePointsLock);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief shutdown the debugging
////////////////////////////////////////////////////////////////////////////////

void TRI_ShutdownDebugging () {
  if (FailurePoints != nullptr) {
    TRI_Free(TRI_CORE_MEM_ZONE, FailurePoints);
  }

  FailurePoints = nullptr;

  TRI_DestroyReadWriteLock(&FailurePointsLock);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief appends a backtrace to the string provided
////////////////////////////////////////////////////////////////////////////////

void TRI_GetBacktrace (std::string& btstr) {
#if HAVE_BACKTRACE
#ifdef _WIN32
  void         * stack[100];
  unsigned short frames;
  SYMBOL_INFO  * symbol;
  HANDLE         process;

  process = GetCurrentProcess();

  SymInitialize(process, nullptr, true);

  frames               = CaptureStackBackTrace(0, 100, stack, nullptr);
  symbol               = (SYMBOL_INFO*) calloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char), 1);

  if (symbol == nullptr) {
    // cannot allocate memory
    return;
  }

  symbol->MaxNameLen   = 255;
  symbol->SizeOfStruct = sizeof(SYMBOL_INFO);

  for (unsigned int i = 0; i < frames; i++) {
    char address[64];
    SymFromAddr(process, (DWORD64) stack[i], 0, symbol);

    snprintf(address, sizeof(address), "0x%0X", symbol->Address);
    btstr += std::to_string(frames - i - 1) + std::string(": ") + symbol->Name + std::string(" [") + address + std::string("]\n");
  }

  TRI_SystemFree(symbol);

#else
  void* stack_frames[50];
  size_t size, i;
  char** strings;

  size = backtrace(stack_frames, sizeof(stack_frames) / sizeof(void*));
  strings = backtrace_symbols(stack_frames, size);
  for (i = 0; i < size; i++) {
    std::stringstream ss;
    if (strings != nullptr) {
      char *mangled_name = nullptr, *offset_begin = nullptr, *offset_end = nullptr;

      // find parantheses and +address offset surrounding mangled name
      for (char *p = strings[i]; *p; ++p) {
        if (*p == '(') {
          mangled_name = p;
        }
        else if (*p == '+') {
          offset_begin = p;
        }
        else if (*p == ')') {
          offset_end = p;
          break;
        }
      }
      // TODO: osx demangling works a little bit different.
      // http://oroboro.com/stack-trace-on-crash/
      // says it should look like that:
      //#ifdef DARWIN
      //      // OSX style stack trace
      //      for ( char *p = symbollist[i]; *p; ++p )
      //      {
      //         if (( *p == '_' ) && ( *(p-1) == ' ' ))
      //            begin_name = p-1;
      //         else if ( *p == '+' )
      //            begin_offset = p-1;
      //      }
      //
      //      if ( begin_name && begin_offset && ( begin_name < begin_offset ))
      //      {
      //         *begin_name++ = '\0';
      //         *begin_offset++ = '\0';
      //
      //         // mangled name is now in [begin_name, begin_offset) and caller
      //         // offset in [begin_offset, end_offset). now apply
      //         // __cxa_demangle():
      //         int status;
      //         char* ret = abi::__cxa_demangle( begin_name, &funcname[0],
      //                                          &funcnamesize, &status );
      //         if ( status == 0 )
      //         {
      //            funcname = ret; // use possibly realloc()-ed string
      //            fprintf( out, "  %-30s %-40s %s\n",
      //                     symbollist[i], funcname, begin_offset );
      //         } else {
      //            // demangling failed. Output function name as a C function with
      //            // no arguments.
      //            fprintf( out, "  %-30s %-38s() %s\n",
      //                     symbollist[i], begin_name, begin_offset );
      //         }
      //
      //#else // !DARWIN - but is posix
      // if the line could be processed, attempt to demangle the symbol
      if (mangled_name && offset_begin && offset_end &&
          mangled_name < offset_begin) {
        *mangled_name++ = '\0';
        *offset_begin++ = '\0';
        *offset_end++ = '\0';
        int status = 0;
        char * demangled_name = abi::__cxa_demangle(mangled_name, 0, 0, &status);

        if (demangled_name != nullptr) {
          if (status == 0) {
            ss << stack_frames[i];
            btstr +=  strings[i] +
              std::string("() [") +
              ss.str() +
              std::string("] ") +
              demangled_name +
              std::string("\n");
          }
          else {
            btstr += strings[i] +
              std::string("\n");
          }
          TRI_SystemFree(demangled_name);
        }
      }
      else {
        btstr += strings[i] +
          std::string("\n");
      }
    }
    else {
      ss << stack_frames[i];
      btstr += ss.str() +
        std::string("\n");
    }
  }
  if (strings != nullptr) {
    TRI_SystemFree(strings);
  }
#endif
#endif
}

////////////////////////////////////////////////////////////////////////////////
/// @brief prints a backtrace on stderr
////////////////////////////////////////////////////////////////////////////////

void TRI_PrintBacktrace () {
#if HAVE_BACKTRACE
  std::string out;
  TRI_GetBacktrace(out);
  fprintf(stderr, "%s", out.c_str());
#endif
}

// -----------------------------------------------------------------------------
// --SECTION--                                                       END-OF-FILE
// -----------------------------------------------------------------------------

// Local Variables:
// mode: outline-minor
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @page\\|// --SECTION--\\|/// @\\}"
// End:
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2015 - The CM Authors <legal@clickmatcher.com>
 *   All Rights Reserved.
 *
 * This file is CONFIDENTIAL -- Distribution or duplication of this material or
 * the information contained herein is strictly forbidden unless prior written
 * permission is obtained.
 */
#include "demoQueryServlet.h"

using namespace fnord;
namespace cm {

void demoQueryServlet::handleHTTPRequest(
      RefPtr<http::HTTPRequestStream> req_stream,
      RefPtr<http::HTTPResponseStream> res_stream) {

  http::HTTPSSEStream sse_stream(req_stream, res_stream);
  sse_stream.start();

  for (int i = 0; i < 100; i++) {
    sse_stream.sendEvent("ping pong");
    usleep(1000);
  }

  sse_stream.finish();
}

}
<commit_msg>bad request if no txid parameter is set<commit_after>/**
 * Copyright (c) 2015 - The CM Authors <legal@clickmatcher.com>
 *   All Rights Reserved.
 *
 * This file is CONFIDENTIAL -- Distribution or duplication of this material or
 * the information contained herein is strictly forbidden unless prior written
 * permission is obtained.
 */
#include <fnord-base/inspect.h>
#include "demoQueryServlet.h"

using namespace fnord;
namespace cm {

void demoQueryServlet::handleHTTPRequest(
      RefPtr<http::HTTPRequestStream> req_stream,
      RefPtr<http::HTTPResponseStream> res_stream) {

  const http::HTTPRequest& req(req_stream->request());
  URI uri(req.uri());
  const URI::ParamList& params(uri.queryParams());
  String txid;

  if (!uri.getParam(params, "txid", &txid)) {
    http::HTTPResponse res;
    Buffer body;
    body.append("error: missing ?txid=... parameter");
    req_stream->readBody();
    res.populateFromRequest(req);
    res.setStatus(http::kStatusBadRequest);
    res.addBody(body.data(), body.size());
    res_stream->writeResponse(res);
    return;
  }

  fnord::iputs("Uri: $0", txid);

  http::HTTPSSEStream sse_stream(req_stream, res_stream);
  sse_stream.start();
  for (int i = 0; i < 100; i++) {
    sse_stream.sendEvent("ping pong");
    usleep(1000);
  }

  sse_stream.finish();
}

}
<|endoftext|>


<commit_before>/******************************************************************************
 *
 * fci.cpp
 *
 * This program loads basis functions and nuclear field information to
 * form a Hamiltonian and compute its eigenvalues.
 *
 * JDWhitfield
 * Dartmouth, 2016-2017
 *
 *
 *      This program is free software: you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License as published by
 *      the Free Software Foundation, either version 2 of the License, or
 *      (at your option) any later version.
 *
 *      This program is distributed in the hope that it will be useful,
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *      GNU General Public License for more details.
 *
 *      You should have received a copy of the GNU General Public License
 *      along with this program.  If not, see http://www.gnu.org/licenses/.
 *
 *****************************************************************************/

#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#include<fstream>
#include<assert.h>
#include<iomanip>
#include<random>
#include<chrono>
#include<algorithm>
#include"parser.h"
#include"ci_matrix.h"
#include"libint_interface.h"

int
main(int argc, char *argv[])
{
    using std::chrono::high_resolution_clock;

    std::cout.precision(10);
    std::cout << std::scientific;

    int debug=2;

    //timing variables
    //std::chrono::system_clock::time_point start_time;
    std::chrono::duration<double> time_elapsed;

    // ****************************
    // * Parse commandline inputs *
    // ****************************
    if (argc > 1)
    {
	    if(!strcmp(argv[1],"-h"))
	    {
            std::cout << "fci [basis_func] [nuc_field]";
            std::cout << "\n\tDefault files are used when called with no parameters.\n\n";
		    return 0;
	    }
    }

    const auto basis_fname=(argc>1) ? argv[1] : "basis_funcs";
    const auto nuc_fname  =(argc>2) ? argv[2] : "nuc_field";

    // ****************************
    // * Output files             *
    // ****************************
    std::fstream fonebody;
    fonebody.open("ham_ov.dat");

	    /*
	     * Format ham_ov.dat-
	     * number of basis
	     * Ov matrix
	     * Core Hamiltonian matrix
	     * Nuclear Repulsion
	     */

    // ****************************
    // * Parse data files         *
    // ****************************
    libint2::BasisSet shells = parse_basisfile(basis_fname);

    if(debug)
    {
        printf("Basis set\n");
        for( auto s : shells)
            std::cout << s << "\n";
    }

    //number of spin orbitals in the basis set
    int M=2*shells.nbf();

    fonebody << M << "\n";

    //number of electrons
    int N=-99;

    /*
    //number of 2e- integrals
    int m=(M/2) - 1;
    int nints=term4(m,m,m,m)+1;
    */

    auto atoms = parse_nucfile(nuc_fname,N);

    if(N==-99)
    {
        std::cout << "Nelec not set\n";
        throw;
    }

    Matrix S, h;
    std::vector<double> AOInts;

    //FCI matrix dimension
    int D=nchoosek(M,N);

    //libints
    auto start_time = high_resolution_clock::now();
    Matrix hT,hV;
    get_libints(shells,atoms,S,hV,hT,AOInts);
    h=hT+hV;
    time_elapsed=(high_resolution_clock::now()-start_time);
    std::cout << "Took " << time_elapsed.count() << " seconds to get AO Ints\n";

    if(debug)
    {
        std::cout << "S\n" << S << "\n\n";
        fonebody  << S << "\n";
        std::cout << "h\n" << h << "\n\n";
        fonebody  << h << "\n";
        std::cout << "AO 2body integrals (chemist's notation)\n";
        for(auto p=0; p!=M/2; p++) //unique integral labels, looping scheme from libint
            for(auto q=0; q<=p; q++)
                for(auto r=0; r<=p; r++)
                    for(auto s=0; s<= (p==r ? q : r) ; s++)
                        if(std::abs(AOInts[term4(p,q,r,s)]) > 1e-5)
				std::cout << term4(p,q,r,s) << ": ["
					  << p << q << "|" << r << s << "] = " << AOInts[term4(p,q,r,s)] << std::endl;
                            //printf("%i: [%i%i|%i%i] = %12.10lf\n",
                             //       term4(p,q,r,s),p,q,r,s,AOInts[term4(p,q,r,s)]);
    }

    Matrix h2;
    std::vector<double> MOInts;
    if(Matrix(S).isIdentity(1e-9))
    {
        //nothing changes if S is the identity matrix
        h2=h;
        MOInts=AOInts;
        std::cout<<"We don't need to orthogonalize\n";
    }
    else
    {// *     ORTHOGONALIZATION    *

        /***********************************************************/
        // Transformation matricies
        //
        //Basis transform to an orthogonal space
        //C = C(W) = XW for any WW^\dag =\id
        //

        Eigen::SelfAdjointEigenSolver<Matrix> Eigensystem(S);
        Matrix s=Matrix(Eigensystem.eigenvalues());
        //check which eigenvalues are non-trivial to avoid linear dependence
        //then compute s^{-1/2}
        Matrix shalf;
        shalf.resize(M/2,M/2);    // set size
        shalf.fill(0);            // make sure all elements are zero
        //make sure its a column vector
        if(s.rows()<s.cols())
            s.transposeInPlace();

        for(int j=0; j<s.rows(); j++)
        {
            if(std::abs(s(j,0))>1e-6)
                shalf(j,j)=1/sqrt(s(j,0));
            else
                shalf(j,j)=0;
        }

        //orthogonalization transform
        //Here we're just using W=\id
        Matrix C;
        bool CANONICAL=true;
        if(CANONICAL)
            C=Matrix(Eigensystem.eigenvectors()*shalf);
        else
            C=Matrix(Eigensystem.eigenvectors()*shalf*Eigensystem.eigenvectors().adjoint());

        //time the transformations
        start_time = high_resolution_clock::now();

        h2       =Matrix(C.adjoint())*h*C;   //One-body transform
        MOInts   = transform4(M,C,AOInts);//two-body transform

        time_elapsed = high_resolution_clock::now() - start_time;
        std::cout << "Transformation to (canonical) orthogonal basis took " << time_elapsed.count() << "ms \n";

    }

    if(debug)
    {
        std::cout << "h\n";
        std::cout << h2 << "\n\n";
        std::cout << "Orthogonalized Integrals\n";
        for(auto m : MOInts)
            std::cout << m << "\n";
    }

    //LAPACK
    start_time=high_resolution_clock::now();

    double* w=ci_eigenvals(M,N,MOInts,h2,debug);

    time_elapsed = std::chrono::high_resolution_clock::now() - start_time;
    std::cout << "Making matrix and getting eigenvalues took " << time_elapsed.count()
              << "s to get eigenvalues.\n";

    std::cout << "\nEigenvalues( "<< D << " ) :\n --------- \n";

    std::cout.precision(10);
    std::cout << std::scientific;
    for(int i=0; i<D; i++)
        std::cout << w[i]  << "\n";

    // ****************************
    // * Close output files       *
    // ****************************

    fonebody.close();

    return 0;
}
<commit_msg>Made requested file generation (first draft)<commit_after>/******************************************************************************
 *
 * fci.cpp
 *
 * This program loads basis functions and nuclear field information to
 * form a Hamiltonian and compute its eigenvalues.
 *
 * JDWhitfield
 * Dartmouth, 2016-2017
 *
 *
 *      This program is free software: you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License as published by
 *      the Free Software Foundation, either version 2 of the License, or
 *      (at your option) any later version.
 *
 *      This program is distributed in the hope that it will be useful,
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *      GNU General Public License for more details.
 *
 *      You should have received a copy of the GNU General Public License
 *      along with this program.  If not, see http://www.gnu.org/licenses/.
 *
 *****************************************************************************/

#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#include<fstream>
#include<assert.h>
#include<iomanip>
#include<random>
#include<chrono>
#include<algorithm>
#include"parser.h"
#include"ci_matrix.h"
#include"libint_interface.h"

int
main(int argc, char *argv[])
{
    using std::chrono::high_resolution_clock;

    std::cout.precision(10);
    std::cout << std::scientific;

    int debug=2;

    //timing variables
    //std::chrono::system_clock::time_point start_time;
    std::chrono::duration<double> time_elapsed;

    // ****************************
    // * Parse commandline inputs *
    // ****************************
    if (argc > 1)
    {
	    if(!strcmp(argv[1],"-h"))
	    {
            std::cout << "fci [basis_func] [nuc_field]";
            std::cout << "\n\tDefault files are used when called with no parameters.\n\n";
		    return 0;
	    }
    }

    const auto basis_fname=(argc>1) ? argv[1] : "basis_funcs";
    const auto nuc_fname  =(argc>2) ? argv[2] : "nuc_field";

    // ****************************
    // * Output files             *
    // ****************************
    std::fstream fonebody;
    fonebody.open("ham_ov.dat");

   /*
     Format ham_ov.dat-
     number of basis
     Ov matrix
     Core Hamiltonian matrix
     Nuclear Repulsion
    */

    std::fstream ftwobody;
    ftwobody.open("2_ele.dat");
    /*
     Format 2_ele.dat-
     number of reduced integral
     i,j,k,l, ee(i,j,k,l)
    */

    // ****************************
    // * Parse data files         *
    // ****************************
    libint2::BasisSet shells = parse_basisfile(basis_fname);

    if(debug)
    {
        printf("Basis set\n");
        for( auto s : shells)
            std::cout << s << "\n";
    }

    //number of spin orbitals in the basis set
    int M=2*shells.nbf();

    fonebody << M << "\n";

    //number of electrons
    int N=-99;

    /*
    //number of 2e- integrals
    int m=(M/2) - 1;
    int nints=term4(m,m,m,m)+1;
    */

    auto atoms = parse_nucfile(nuc_fname,N);

    if(N==-99)
    {
        std::cout << "Nelec not set\n";
        throw;
    }

    Matrix S, h;
    std::vector<double> AOInts;

    //FCI matrix dimension
    int D=nchoosek(M,N);

    //libints
    auto start_time = high_resolution_clock::now();
    Matrix hT,hV;
    get_libints(shells,atoms,S,hV,hT,AOInts);
    h=hT+hV;
    time_elapsed=(high_resolution_clock::now()-start_time);
    std::cout << "Took " << time_elapsed.count() << " seconds to get AO Ints\n";

    if(debug)
    {
        std::cout << "S\n" << S << "\n\n";
        fonebody  << S << "\n";
        std::cout << "h\n" << h << "\n\n";
        fonebody  << h << "\n";
        std::cout << "AO 2body integrals (chemist's notation)\n";
        ftwobody  << "AO 2body integrals (chemist's notation)\n";
        for(auto p=0; p!=M/2; p++) //unique integral labels, looping scheme from libint
            for(auto q=0; q<=p; q++)
                for(auto r=0; r<=p; r++)
                    for(auto s=0; s<= (p==r ? q : r) ; s++)
                        if(std::abs(AOInts[term4(p,q,r,s)]) > 1e-5)
			{
				std::cout << term4(p,q,r,s) << ": ["
					  << p << q << "|" << r << s << "] = " << AOInts[term4(p,q,r,s)] << std::endl;

 			        ftwobody << p << "," << q << "," << r << "," << s << "," << AOInts[term4(p,q,r,s)] << std::endl;
			}
    }

    Matrix h2;
    std::vector<double> MOInts;
    if(Matrix(S).isIdentity(1e-9))
    {
        //nothing changes if S is the identity matrix
        h2=h;
        MOInts=AOInts;
        std::cout<<"We don't need to orthogonalize\n";
    }
    else
    {// *     ORTHOGONALIZATION    *

        /***********************************************************/
        // Transformation matricies
        //
        //Basis transform to an orthogonal space
        //C = C(W) = XW for any WW^\dag =\id
        //

        Eigen::SelfAdjointEigenSolver<Matrix> Eigensystem(S);
        Matrix s=Matrix(Eigensystem.eigenvalues());
        //check which eigenvalues are non-trivial to avoid linear dependence
        //then compute s^{-1/2}
        Matrix shalf;
        shalf.resize(M/2,M/2);    // set size
        shalf.fill(0);            // make sure all elements are zero
        //make sure its a column vector
        if(s.rows()<s.cols())
            s.transposeInPlace();

        for(int j=0; j<s.rows(); j++)
        {
            if(std::abs(s(j,0))>1e-6)
                shalf(j,j)=1/sqrt(s(j,0));
            else
                shalf(j,j)=0;
        }

        //orthogonalization transform
        //Here we're just using W=\id
        Matrix C;
        bool CANONICAL=true;
        if(CANONICAL)
            C=Matrix(Eigensystem.eigenvectors()*shalf);
        else
            C=Matrix(Eigensystem.eigenvectors()*shalf*Eigensystem.eigenvectors().adjoint());

        //time the transformations
        start_time = high_resolution_clock::now();

        h2       =Matrix(C.adjoint())*h*C;   //One-body transform
        MOInts   = transform4(M,C,AOInts);//two-body transform

        time_elapsed = high_resolution_clock::now() - start_time;
        std::cout << "Transformation to (canonical) orthogonal basis took " << time_elapsed.count() << "ms \n";

    }

    if(debug)
    {
        std::cout << "h\n";
        std::cout << h2 << "\n\n";
        std::cout << "Orthogonalized Integrals\n";
        for(auto m : MOInts)
            std::cout << m << "\n";
    }

    //LAPACK
    start_time=high_resolution_clock::now();

    double* w=ci_eigenvals(M,N,MOInts,h2,debug);

    time_elapsed = std::chrono::high_resolution_clock::now() - start_time;
    std::cout << "Making matrix and getting eigenvalues took " << time_elapsed.count()
              << "s to get eigenvalues.\n";

    std::cout << "\nEigenvalues( "<< D << " ) :\n --------- \n";

    std::cout.precision(10);
    std::cout << std::scientific;
    for(int i=0; i<D; i++)
        std::cout << w[i]  << "\n";

    // ****************************
    // * Close output files       *
    // ****************************

    fonebody.close();

    return 0;
}
<|endoftext|>