<commit_before>// ConversionTools.cpp
// Copyright (c) 2009, Dan Heeks
// This program is released under the BSD license. See the file COPYING for details.
#include "stdafx.h"
#include "ConversionTools.h"
#include <BRepTools.hxx>
#include <BRepBuilderAPI_MakePolygon.hxx>
#include <BRepBuilderAPI_MakeShape.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepBuilderAPI_MakeWire.hxx>
#include <BRepBuilderAPI_MakeFace.hxx>
#include <BRepOffsetAPI_MakeOffset.hxx>
#include <BRepAdaptor_Curve.hxx>
#include <BRepTools_WireExplorer.hxx>
#include <TopTools_ListIteratorOfListOfShape.hxx>
#include "MarkedList.h"
#include "HLine.h"
#include "HArc.h"
#include "Wire.h"
#include "Face.h"
#include "Edge.h"
#include "Shape.h"
#include "Sketch.h"
#include "Group.h"

void GetConversionMenuTools(std::list<Tool*>* t_list){
	bool lines_or_arcs_in_marked_list = false;
	int sketches_in_marked_list = 0;
	bool group_in_marked_list = false;

	// check to see what types have been marked
	std::list<HeeksObj*>::const_iterator It;
	for(It = wxGetApp().m_marked_list->list().begin(); It != wxGetApp().m_marked_list->list().end(); It++){
		HeeksObj* object = *It;
		switch(object->GetType()){
			case LineType:
			case ArcType:
				lines_or_arcs_in_marked_list = true;
				break;
			case SketchType:
				sketches_in_marked_list++;
				break;
			case GroupType:
				group_in_marked_list = true;
				break;
		}
	}

	if(lines_or_arcs_in_marked_list)
	{
		t_list->push_back(new MakeLineArcsToSketch);
	}

	if(sketches_in_marked_list > 0){
		t_list->push_back(new ConvertSketchToFace);
	}

	if(sketches_in_marked_list > 1){
		t_list->push_back(new CombineSketches);
	}

	if(wxGetApp().m_marked_list->list().size() > 1)t_list->push_back(new GroupSelected);
	if(group_in_marked_list)t_list->push_back(new UngroupSelected);
}

bool ConvertLineArcsToWire2(const std::list<HeeksObj *> &list, TopoDS_Wire &wire)
{
	std::list<TopoDS_Edge> edges;
	std::list<HeeksObj*> list2;
	std::list<HeeksObj*>::const_iterator It;
	for(It = list.begin(); It != list.end(); It++){
		HeeksObj* object = *It;
		if(object->GetType() == SketchType){
			for(HeeksObj* child = object->GetFirstChild(); child; child = object->GetNextChild())
			{
				list2.push_back(child);
			}
		}
		else{
			list2.push_back(object);
		}
	}

	for(std::list<HeeksObj*>::iterator It = list2.begin(); It != list2.end(); It++){
		HeeksObj* object = *It;
		switch(object->GetType()){
			case LineType:
				{
					HLine* line = (HLine*)object;
					edges.push_back(BRepBuilderAPI_MakeEdge(line->A, line->B));
				}
				break;
			case ArcType:
				{
					HArc* arc = (HArc*)object;
					edges.push_back(BRepBuilderAPI_MakeEdge(arc->m_circle, arc->A, arc->B));
				}
				break;
		}
	}

	if(edges.size() > 0){
		BRepBuilderAPI_MakeWire wire_maker;
		std::list<TopoDS_Edge>::iterator It;
		for(It = edges.begin(); It != edges.end(); It++)
		{
			TopoDS_Edge &edge = *It;
			wire_maker.Add(edge);
		}

		wire = wire_maker.Wire();
		return true;
	}

	return false;
}

bool ConvertSketchToFace2(HeeksObj* object, TopoDS_Face& face)
{
	if(object->GetType() != SketchType)return false;
	std::list<HeeksObj*> line_arc_list;

	for(HeeksObj* child = object->GetFirstChild(); child; child = object->GetNextChild())
	{
		line_arc_list.push_back(child);
	}

	std::list<TopoDS_Edge> edges;
	for(std::list<HeeksObj*>::const_iterator It = line_arc_list.begin(); It != line_arc_list.end(); It++){
		HeeksObj* object = *It;
		switch(object->GetType()){
			case LineType:
				{
					HLine* line = (HLine*)object;
					edges.push_back(BRepBuilderAPI_MakeEdge(line->A, line->B));
				}
				break;
			case ArcType:
				{
					HArc* arc = (HArc*)object;
					edges.push_back(BRepBuilderAPI_MakeEdge(arc->m_circle, arc->A, arc->B));
				}
				break;
		}
	}

	if(edges.size() > 0){
		try
		{
			BRepBuilderAPI_MakeWire wire_maker;
			std::list<TopoDS_Edge>::iterator It;
			for(It = edges.begin(); It != edges.end(); It++)
			{
				TopoDS_Edge &edge = *It;
				wire_maker.Add(edge);
			}

			face = BRepBuilderAPI_MakeFace(wire_maker.Wire());
		}
		catch(...)
		{
			wxMessageBox(_("Fatal Error converting sketch to face"));
		}
		return true;
	}

	return false;
}

bool ConvertFaceToSketch2(const TopoDS_Face& face, HeeksObj* sketch)
{
	// given a face, this adds lines and arcs to the given sketch
	// loop through all the loops
	TopoDS_Wire outerWire=BRepTools::OuterWire(face);

	for (TopExp_Explorer expWire(face, TopAbs_WIRE); expWire.More(); expWire.Next())
	{
		const TopoDS_Shape &W = expWire.Current();
		bool is_outer = W.IsSame(outerWire) != 0;

		for(BRepTools_WireExplorer expEdge(TopoDS::Wire(W)); expEdge.More(); expEdge.Next())
		{
			const TopoDS_Shape &E = expEdge.Current();
			if(!ConvertEdgeToSketch2(TopoDS::Edge(E), sketch))return false;
		}
	}

	return true; // success
}

bool ConvertEdgeToSketch2(const TopoDS_Edge& edge, HeeksObj* sketch)
{
	// enum GeomAbs_CurveType
	// 0 - GeomAbs_Line
	// 1 - GeomAbs_Circle
	// 2 - GeomAbs_Ellipse
	// 3 - GeomAbs_Hyperbola
	// 4 - GeomAbs_Parabola
	// 5 - GeomAbs_BezierCurve
	// 6 - GeomAbs_BSplineCurve
	// 7 - GeomAbs_OtherCurve

	BRepAdaptor_Curve curve(edge);
	GeomAbs_CurveType curve_type = curve.GetType();

	switch(curve_type)
	{
		case GeomAbs_Line:
			// make a line
		{
			double uStart = curve.FirstParameter();
			double uEnd = curve.LastParameter();
			gp_Pnt PS;
			gp_Vec VS;
			curve.D1(uStart, PS, VS);
			gp_Pnt PE;
			gp_Vec VE;
			curve.D1(uEnd, PE, VE);
			HLine* new_object = new HLine(PS, PE, &wxGetApp().current_color);
			sketch->Add(new_object, NULL);
		}
		break;

		case GeomAbs_Circle:
			// make an arc
		{
			double uStart = curve.FirstParameter();
			double uEnd = curve.LastParameter();
			gp_Pnt PS;
			gp_Vec VS;
			curve.D1(uStart, PS, VS);
			gp_Pnt PE;
			gp_Vec VE;
			curve.D1(uEnd, PE, VE);
			gp_Circ circle = curve.Circle();
			HArc* new_object = new HArc(PS, PE, circle, &wxGetApp().current_color);
			sketch->Add(new_object, NULL);
		}
		break;

		default:
		{
			// to do
		}
		break;
	}

	return true;
}

void ConvertSketchToFace::Run(){
	std::list<HeeksObj*>::const_iterator It;
	for(It = wxGetApp().m_marked_list->list().begin(); It != wxGetApp().m_marked_list->list().end(); It++){
		HeeksObj* object = *It;
		if(object->GetType() == SketchType){
			TopoDS_Face face;
			if(ConvertSketchToFace2(object, face))
			{
				wxGetApp().AddUndoably(new CFace(face), NULL, NULL);
				wxGetApp().Repaint();
			}
		}
	}
}

void MakeLineArcsToSketch::Run(){
	std::list<HeeksObj*> objects_to_delete;

	CSketch* sketch = new CSketch();

	std::list<HeeksObj*>::const_iterator It;
	for(It = wxGetApp().m_marked_list->list().begin(); It != wxGetApp().m_marked_list->list().end(); It++){
		HeeksObj* object = *It;
		if(object->GetType() == LineType || object->GetType() == ArcType){
			HeeksObj* new_object = object->MakeACopy();
			objects_to_delete.push_back(object);
			sketch->Add(new_object, NULL);
		}
	}

	wxGetApp().AddUndoably(sketch, NULL, NULL);
	wxGetApp().DeleteUndoably(objects_to_delete);
}

void CombineSketches::Run(){
	CSketch* sketch1 = NULL;
	std::list<HeeksObj*>::const_iterator It;
	std::list<HeeksObj*> copy_of_marked_list = wxGetApp().m_marked_list->list();

	for(It = copy_of_marked_list.begin(); It != copy_of_marked_list.end(); It++){
		HeeksObj* object = *It;
		if(object->GetType() == SketchType){
			if(sketch1)
			{
				std::list<HeeksObj*> new_lines_and_arcs;
				for(HeeksObj* o = object->GetFirstChild(); o; o = object->GetNextChild())
				{
					new_lines_and_arcs.push_back(o->MakeACopy());
				}
				wxGetApp().DeleteUndoably(object);
				wxGetApp().AddUndoably(new_lines_and_arcs, sketch1);
			}
			else
			{
				sketch1 = (CSketch*)object;
			}
		}
	}

	wxGetApp().Repaint();
}

void GroupSelected::Run(){
	if(wxGetApp().m_marked_list->list().size() < 2)
	{
		return;
	}

	CGroup* new_group = new CGroup;
	std::list<HeeksObj*> copy_of_marked_list = wxGetApp().m_marked_list->list();

	wxGetApp().StartHistory();
	wxGetApp().DeleteUndoably(copy_of_marked_list);
	for(std::list<HeeksObj*>::const_iterator It = copy_of_marked_list.begin(); It != copy_of_marked_list.end(); It++){
		HeeksObj* object = *It;
		new_group->Add(object, NULL);
	}
	wxGetApp().AddUndoably(new_group, NULL, NULL);
	wxGetApp().EndHistory();
	wxGetApp().m_marked_list->Clear(true);
	wxGetApp().Repaint();
}

void UngroupSelected::Run(){
	if(wxGetApp().m_marked_list->list().size() == 0)return;

	wxGetApp().StartHistory();
	std::list<HeeksObj*> copy_of_marked_list = wxGetApp().m_marked_list->list();
	for(std::list<HeeksObj*>::const_iterator It = copy_of_marked_list.begin(); It != copy_of_marked_list.end(); It++){
		HeeksObj* object = *It;
		if(object->GetType() == GroupType)
		{
			std::list<HeeksObj*> group_objects;
			for(HeeksObj* o = ((CGroup*)object)->GetFirstChild(); o; o = ((CGroup*)object)->GetNextChild())
			{
				group_objects.push_back(o);
			}
			for(std::list<HeeksObj*>::iterator It2 = group_objects.begin(); It2 != group_objects.end(); It2++){
				HeeksObj* o = *It2;
				wxGetApp().DeleteUndoably(o);
				wxGetApp().AddUndoably(o, NULL, NULL);
			}
			wxGetApp().DeleteUndoably(object);
		}
	}
	wxGetApp().EndHistory();

	wxGetApp().m_marked_list->Clear(true);
	wxGetApp().Repaint();
}
<commit_msg>removed the flickering on ungroup<commit_after>// ConversionTools.cpp
// Copyright (c) 2009, Dan Heeks
// This program is released under the BSD license. See the file COPYING for details.
#include "stdafx.h"
#include "ConversionTools.h"
#include <BRepTools.hxx>
#include <BRepBuilderAPI_MakePolygon.hxx>
#include <BRepBuilderAPI_MakeShape.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepBuilderAPI_MakeWire.hxx>
#include <BRepBuilderAPI_MakeFace.hxx>
#include <BRepOffsetAPI_MakeOffset.hxx>
#include <BRepAdaptor_Curve.hxx>
#include <BRepTools_WireExplorer.hxx>
#include <TopTools_ListIteratorOfListOfShape.hxx>
#include "MarkedList.h"
#include "HLine.h"
#include "HArc.h"
#include "Wire.h"
#include "Face.h"
#include "Edge.h"
#include "Shape.h"
#include "Sketch.h"
#include "Group.h"

void GetConversionMenuTools(std::list<Tool*>* t_list){
	bool lines_or_arcs_in_marked_list = false;
	int sketches_in_marked_list = 0;
	bool group_in_marked_list = false;

	// check to see what types have been marked
	std::list<HeeksObj*>::const_iterator It;
	for(It = wxGetApp().m_marked_list->list().begin(); It != wxGetApp().m_marked_list->list().end(); It++){
		HeeksObj* object = *It;
		switch(object->GetType()){
			case LineType:
			case ArcType:
				lines_or_arcs_in_marked_list = true;
				break;
			case SketchType:
				sketches_in_marked_list++;
				break;
			case GroupType:
				group_in_marked_list = true;
				break;
		}
	}

	if(lines_or_arcs_in_marked_list)
	{
		t_list->push_back(new MakeLineArcsToSketch);
	}

	if(sketches_in_marked_list > 0){
		t_list->push_back(new ConvertSketchToFace);
	}

	if(sketches_in_marked_list > 1){
		t_list->push_back(new CombineSketches);
	}

	if(wxGetApp().m_marked_list->list().size() > 1)t_list->push_back(new GroupSelected);
	if(group_in_marked_list)t_list->push_back(new UngroupSelected);
}

bool ConvertLineArcsToWire2(const std::list<HeeksObj *> &list, TopoDS_Wire &wire)
{
	std::list<TopoDS_Edge> edges;
	std::list<HeeksObj*> list2;
	std::list<HeeksObj*>::const_iterator It;
	for(It = list.begin(); It != list.end(); It++){
		HeeksObj* object = *It;
		if(object->GetType() == SketchType){
			for(HeeksObj* child = object->GetFirstChild(); child; child = object->GetNextChild())
			{
				list2.push_back(child);
			}
		}
		else{
			list2.push_back(object);
		}
	}

	for(std::list<HeeksObj*>::iterator It = list2.begin(); It != list2.end(); It++){
		HeeksObj* object = *It;
		switch(object->GetType()){
			case LineType:
				{
					HLine* line = (HLine*)object;
					edges.push_back(BRepBuilderAPI_MakeEdge(line->A, line->B));
				}
				break;
			case ArcType:
				{
					HArc* arc = (HArc*)object;
					edges.push_back(BRepBuilderAPI_MakeEdge(arc->m_circle, arc->A, arc->B));
				}
				break;
		}
	}

	if(edges.size() > 0){
		BRepBuilderAPI_MakeWire wire_maker;
		std::list<TopoDS_Edge>::iterator It;
		for(It = edges.begin(); It != edges.end(); It++)
		{
			TopoDS_Edge &edge = *It;
			wire_maker.Add(edge);
		}

		wire = wire_maker.Wire();
		return true;
	}

	return false;
}

bool ConvertSketchToFace2(HeeksObj* object, TopoDS_Face& face)
{
	if(object->GetType() != SketchType)return false;
	std::list<HeeksObj*> line_arc_list;

	for(HeeksObj* child = object->GetFirstChild(); child; child = object->GetNextChild())
	{
		line_arc_list.push_back(child);
	}

	std::list<TopoDS_Edge> edges;
	for(std::list<HeeksObj*>::const_iterator It = line_arc_list.begin(); It != line_arc_list.end(); It++){
		HeeksObj* object = *It;
		switch(object->GetType()){
			case LineType:
				{
					HLine* line = (HLine*)object;
					edges.push_back(BRepBuilderAPI_MakeEdge(line->A, line->B));
				}
				break;
			case ArcType:
				{
					HArc* arc = (HArc*)object;
					edges.push_back(BRepBuilderAPI_MakeEdge(arc->m_circle, arc->A, arc->B));
				}
				break;
		}
	}

	if(edges.size() > 0){
		try
		{
			BRepBuilderAPI_MakeWire wire_maker;
			std::list<TopoDS_Edge>::iterator It;
			for(It = edges.begin(); It != edges.end(); It++)
			{
				TopoDS_Edge &edge = *It;
				wire_maker.Add(edge);
			}

			face = BRepBuilderAPI_MakeFace(wire_maker.Wire());
		}
		catch(...)
		{
			wxMessageBox(_("Fatal Error converting sketch to face"));
		}
		return true;
	}

	return false;
}

bool ConvertFaceToSketch2(const TopoDS_Face& face, HeeksObj* sketch)
{
	// given a face, this adds lines and arcs to the given sketch
	// loop through all the loops
	TopoDS_Wire outerWire=BRepTools::OuterWire(face);

	for (TopExp_Explorer expWire(face, TopAbs_WIRE); expWire.More(); expWire.Next())
	{
		const TopoDS_Shape &W = expWire.Current();
		bool is_outer = W.IsSame(outerWire) != 0;

		for(BRepTools_WireExplorer expEdge(TopoDS::Wire(W)); expEdge.More(); expEdge.Next())
		{
			const TopoDS_Shape &E = expEdge.Current();
			if(!ConvertEdgeToSketch2(TopoDS::Edge(E), sketch))return false;
		}
	}

	return true; // success
}

bool ConvertEdgeToSketch2(const TopoDS_Edge& edge, HeeksObj* sketch)
{
	// enum GeomAbs_CurveType
	// 0 - GeomAbs_Line
	// 1 - GeomAbs_Circle
	// 2 - GeomAbs_Ellipse
	// 3 - GeomAbs_Hyperbola
	// 4 - GeomAbs_Parabola
	// 5 - GeomAbs_BezierCurve
	// 6 - GeomAbs_BSplineCurve
	// 7 - GeomAbs_OtherCurve

	BRepAdaptor_Curve curve(edge);
	GeomAbs_CurveType curve_type = curve.GetType();

	switch(curve_type)
	{
		case GeomAbs_Line:
			// make a line
		{
			double uStart = curve.FirstParameter();
			double uEnd = curve.LastParameter();
			gp_Pnt PS;
			gp_Vec VS;
			curve.D1(uStart, PS, VS);
			gp_Pnt PE;
			gp_Vec VE;
			curve.D1(uEnd, PE, VE);
			HLine* new_object = new HLine(PS, PE, &wxGetApp().current_color);
			sketch->Add(new_object, NULL);
		}
		break;

		case GeomAbs_Circle:
			// make an arc
		{
			double uStart = curve.FirstParameter();
			double uEnd = curve.LastParameter();
			gp_Pnt PS;
			gp_Vec VS;
			curve.D1(uStart, PS, VS);
			gp_Pnt PE;
			gp_Vec VE;
			curve.D1(uEnd, PE, VE);
			gp_Circ circle = curve.Circle();
			HArc* new_object = new HArc(PS, PE, circle, &wxGetApp().current_color);
			sketch->Add(new_object, NULL);
		}
		break;

		default:
		{
			// to do
		}
		break;
	}

	return true;
}

void ConvertSketchToFace::Run(){
	std::list<HeeksObj*>::const_iterator It;
	for(It = wxGetApp().m_marked_list->list().begin(); It != wxGetApp().m_marked_list->list().end(); It++){
		HeeksObj* object = *It;
		if(object->GetType() == SketchType){
			TopoDS_Face face;
			if(ConvertSketchToFace2(object, face))
			{
				wxGetApp().AddUndoably(new CFace(face), NULL, NULL);
				wxGetApp().Repaint();
			}
		}
	}
}

void MakeLineArcsToSketch::Run(){
	std::list<HeeksObj*> objects_to_delete;

	CSketch* sketch = new CSketch();

	std::list<HeeksObj*>::const_iterator It;
	for(It = wxGetApp().m_marked_list->list().begin(); It != wxGetApp().m_marked_list->list().end(); It++){
		HeeksObj* object = *It;
		if(object->GetType() == LineType || object->GetType() == ArcType){
			HeeksObj* new_object = object->MakeACopy();
			objects_to_delete.push_back(object);
			sketch->Add(new_object, NULL);
		}
	}

	wxGetApp().AddUndoably(sketch, NULL, NULL);
	wxGetApp().DeleteUndoably(objects_to_delete);
}

void CombineSketches::Run(){
	CSketch* sketch1 = NULL;
	std::list<HeeksObj*>::const_iterator It;
	std::list<HeeksObj*> copy_of_marked_list = wxGetApp().m_marked_list->list();

	for(It = copy_of_marked_list.begin(); It != copy_of_marked_list.end(); It++){
		HeeksObj* object = *It;
		if(object->GetType() == SketchType){
			if(sketch1)
			{
				std::list<HeeksObj*> new_lines_and_arcs;
				for(HeeksObj* o = object->GetFirstChild(); o; o = object->GetNextChild())
				{
					new_lines_and_arcs.push_back(o->MakeACopy());
				}
				wxGetApp().DeleteUndoably(object);
				wxGetApp().AddUndoably(new_lines_and_arcs, sketch1);
			}
			else
			{
				sketch1 = (CSketch*)object;
			}
		}
	}

	wxGetApp().Repaint();
}

void GroupSelected::Run(){
	if(wxGetApp().m_marked_list->list().size() < 2)
	{
		return;
	}

	CGroup* new_group = new CGroup;
	std::list<HeeksObj*> copy_of_marked_list = wxGetApp().m_marked_list->list();

	wxGetApp().StartHistory();
	wxGetApp().DeleteUndoably(copy_of_marked_list);
	for(std::list<HeeksObj*>::const_iterator It = copy_of_marked_list.begin(); It != copy_of_marked_list.end(); It++){
		HeeksObj* object = *It;
		new_group->Add(object, NULL);
	}
	wxGetApp().AddUndoably(new_group, NULL, NULL);
	wxGetApp().EndHistory();
	wxGetApp().m_marked_list->Clear(true);
	wxGetApp().Repaint();
}

void UngroupSelected::Run(){
	if(wxGetApp().m_marked_list->list().size() == 0)return;

	wxGetApp().StartHistory();
	std::list<HeeksObj*> copy_of_marked_list = wxGetApp().m_marked_list->list();
	std::list<HeeksObj*> to_remove;
	std::list<HeeksObj*> to_add;
	for(std::list<HeeksObj*>::const_iterator It = copy_of_marked_list.begin(); It != copy_of_marked_list.end(); It++){
		HeeksObj* object = *It;
		if(object->GetType() == GroupType)
		{
			for(HeeksObj* o = ((CGroup*)object)->GetFirstChild(); o; o = ((CGroup*)object)->GetNextChild())
			{
				to_add.push_back(o);
				to_remove.push_back(o);
			}
			to_remove.push_back(object);
		}
	}
	wxGetApp().DeleteUndoably(to_remove);
	wxGetApp().AddUndoably(to_add, NULL);
	wxGetApp().EndHistory();

	wxGetApp().m_marked_list->Clear(true);
	wxGetApp().Repaint();
}
<|endoftext|>


<commit_before>
#include "res_tracker.h"

#include "event_manager.h"

namespace cyclus {

ResTracker::ResTracker(Context* ctx, Resource* r)
  : tracked_(true),
    res_(r),
    ctx_(ctx),
    parent1_(0),
    parent2_(0) { }

void ResTracker::DontTrack() {
  tracked_ = false;
}

void ResTracker::Create() {
  if (!tracked_) {
    return;
  }

  Record();
}

void ResTracker::Modify() {
  if (!tracked_) {
    return;
  }

  parent1_ = res_->id();
  parent2_ = 0;
  Record();
}

void ResTracker::Extract(ResTracker* removed) {
  if (!tracked_) {
    return;
  }

  parent1_ = res_->id();
  parent2_ = 0;
  Record();

  removed->tracked_ = tracked_;
  removed->parent1_ = res_->id();
  removed->parent2_ = 0;
  removed->Record();
}

void ResTracker::Absorb(ResTracker* absorbed) {
  if (!tracked_) {
    return;
  }

  parent1_ = res_->id();
  parent2_ = absorbed->res_->id();
  Record();
}

void ResTracker::Record() {
  res_->BumpId();
  ctx_->NewEvent("ResourceHeritage")
  ->AddVal("ID", res_->id())
  ->AddVal("Type", res_->type())
  ->AddVal("Quantity", res_->quantity())
  ->AddVal("units", res_->units())
  ->AddVal("StateId", res_->state_id())
  ->AddVal("Parent1", parent1_)
  ->AddVal("Parent2", parent2_)
  ->Record();

  res_->Record(ctx_);
}

} // namespace cyclus
<commit_msg>fixed resource table name<commit_after>
#include "res_tracker.h"

#include "event_manager.h"

namespace cyclus {

ResTracker::ResTracker(Context* ctx, Resource* r)
  : tracked_(true),
    res_(r),
    ctx_(ctx),
    parent1_(0),
    parent2_(0) { }

void ResTracker::DontTrack() {
  tracked_ = false;
}

void ResTracker::Create() {
  if (!tracked_) {
    return;
  }

  Record();
}

void ResTracker::Modify() {
  if (!tracked_) {
    return;
  }

  parent1_ = res_->id();
  parent2_ = 0;
  Record();
}

void ResTracker::Extract(ResTracker* removed) {
  if (!tracked_) {
    return;
  }

  parent1_ = res_->id();
  parent2_ = 0;
  Record();

  removed->tracked_ = tracked_;
  removed->parent1_ = res_->id();
  removed->parent2_ = 0;
  removed->Record();
}

void ResTracker::Absorb(ResTracker* absorbed) {
  if (!tracked_) {
    return;
  }

  parent1_ = res_->id();
  parent2_ = absorbed->res_->id();
  Record();
}

void ResTracker::Record() {
  res_->BumpId();
  ctx_->NewEvent("Resources")
  ->AddVal("ID", res_->id())
  ->AddVal("Type", res_->type())
  ->AddVal("Quantity", res_->quantity())
  ->AddVal("units", res_->units())
  ->AddVal("StateId", res_->state_id())
  ->AddVal("Parent1", parent1_)
  ->AddVal("Parent2", parent2_)
  ->Record();

  res_->Record(ctx_);
}

} // namespace cyclus
<|endoftext|>


<commit_before>/*
  Copyright (c) 2011 Timothy Lovorn

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

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

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

#include "CritTempSpectrum.hh"

LambdaInput::LambdaInput(const CritTempState& _st, double _kx, double _ky,
                         double _kz, double _lambdaMinus) :
    st(_st), kx(_kx), ky(_ky), kz(_kz), lambdaMinus(_lambdaMinus) { }

InnerPiInput::InnerPiInput(const CritTempState& _st, double _omega,
                           double _kx, double _ky) :
    st(_st), omega(_omega), kx(_kx), ky(_ky) { }

PiOutput::PiOutput(double _xx, double _xy, double _yy) :
    xx(_xx), xy(_xy), yy(_yy) { }

double CritTempSpectrum::epsilon(const CritTempState& st, double kx,
                                 double ky) {
    return epsilonBar(st, kx, ky) - st.getEpsilonMin();
}

double CritTempSpectrum::epsilonBar(const CritTempState& st, double kx,
                                    double ky) {
    const CritTempEnvironment& env = st.env;
    const double sx = sin(kx);
    const double sy = sin(ky);
    return 2.0 * env.th * ((sx + sy) * (sx + sy) - 1.0)
         + 4.0 * (st.getD1() * env.t0 - env.thp) * sx * sy;
}

double CritTempSpectrum::xi(const CritTempState& st, double kx, double ky) {
    return epsilon(st, kx, ky) - st.getMu();
}

double CritTempSpectrum::fermi(const CritTempState& st, double energy) {
    return 1.0 / (exp(st.getBc() * energy) + 1.0);
}

double CritTempSpectrum::bose(const CritTempState& st, double energy) {
    return 1.0 / (exp(st.getBc() * energy) - 1.0);
}

double CritTempSpectrum::innerX1(const CritTempState& st, double kx,
                                 double ky) {
    return fermi(st, xi(st, kx, ky));
}

double CritTempSpectrum::innerD1(const CritTempState& st, double kx,
                                 double ky) {
    return -sin(kx) * sin(ky) * fermi(st, xi(st, kx, ky));
}

double CritTempSpectrum::innerMu(const CritTempState& st, double kx,
                                 double ky) {
    const double sin_part = sin(kx) - sin(ky);
    return sin_part * sin_part * tanh(st.getBc() * xi(st, kx, ky) / 2.0) /
           xi(st, kx, ky);
}

double CritTempSpectrum::innerPiCommon(const InnerPiInput& ipi,
                                       double qx, double qy) {
    const CritTempState st = ipi.st;
    double xiPlus = xi(st, qx + ipi.kx / 2, qy + ipi.ky / 2);
    double xiMinus = xi(st, qx - ipi.kx / 2, qy - ipi.ky / 2);
    double common = -(tanh(st.getBc() * xiPlus / 2) + tanh(st.getBc()
        * xiMinus / 2)) / (ipi.omega - xiPlus - xiMinus);
    return common;
}

double CritTempSpectrum::innerPiXX(const InnerPiInput& ipi,
                                   double qx, double qy) {
    double common = innerPiCommon(ipi, qx, qy);
    return sin(qx) * sin(qx) * common;
}

double CritTempSpectrum::innerPiXY(const InnerPiInput& ipi,
                                   double qx, double qy) {
    double common = innerPiCommon(ipi, qx, qy);
    return sin(qx) * sin(qy) * common;
}

double CritTempSpectrum::innerPiYY(const InnerPiInput& ipi,
                                   double qx, double qy) {
    double common = innerPiCommon(ipi, qx, qy);
    return sin(qy) * sin(qy) * common;
}

double CritTempSpectrum::getLambda(double omega, void *params) {
    LambdaInput *lin = (LambdaInput*)params;
    const CritTempState& st = lin->st;
    double kx = lin->kx, ky = lin->ky, kz = lin->kz;

    double ex = 2 * (st.env.t0 * cos(ky) + st.env.tz * cos(kz)),
           ey = 2 * (st.env.t0 * cos(kx) + st.env.tz * cos(kz));
    PiOutput Pi = getPi(st, omega, kx, ky);
    double firstTerm = (ex * Pi.xx + ey * Pi.yy) / 2 - 1;
    double secondTerm = sqrt(pow((ex * Pi.xx - ey * Pi.yy), 2.0) / 4
        + ex * ey * pow(Pi.xy, 2.0));

    if (lin->lambdaMinus) {
        return firstTerm - secondTerm;
    } else {
        return firstTerm + secondTerm;
    }
}

PiOutput CritTempSpectrum::getPi(const CritTempState& st, double omega,
                                 double kx, double ky) {
    InnerPiInput ipi(st, omega, kx, ky);
    double piXX = BZone::average<InnerPiInput>(st, ipi, innerPiXX);
    double piXY = BZone::average<InnerPiInput>(st, ipi, innerPiXY);
    double piYY = BZone::average<InnerPiInput>(st, ipi, innerPiYY);
    PiOutput out(piXX, piXY, piYY);
    return out;
}

double CritTempSpectrum::nuFunction(double y, void *params) {
    return sqrt(y) / (exp(y) - 1);
}

double CritTempSpectrum::getNu(const CritTempState& st) {
    OmegaCoeffs ocs = getOmegaCoeffs(st);
    Integrator integrator(&nuFunction, NULL, 1e-6, 1e-6);
    double integral = integrator.doIntegral(0.0, -2 * st.getMu() * st.getBc(),
                                            st.env.errorLog);
    st.env.debugLog.printf("integral = %e\n"
                           "planar = %e cross = %e perp = %e\n", integral,
                           ocs.planar, ocs.cross, ocs.perp);
    double coeffPart = sqrt((ocs.planar + ocs.cross / 2.0) *
                            (ocs.planar - ocs.cross / 2.0) * ocs.perp);
    return integral / (4 * pow(M_PI, 2.0) * coeffPart);
}

OmegaCoeffs CritTempSpectrum::getOmegaCoeffs(const CritTempState& st) {
    double small_k = 0.05, sks = small_k * small_k;
    OmegaCoeffs ocs;
    ocs.planar = omegaExact(st, small_k, 0.0, 0.0) / sks;
    ocs.perp = omegaExact(st, 0.0, 0.0, small_k) / sks;
    ocs.cross = omegaExact(st, small_k, small_k, 0.0) / sks - 2 * ocs.planar;
    return ocs;
}

double CritTempSpectrum::omegaApprox(const OmegaCoeffs& oc,
                                     double kx, double ky, double kz) {
    return oc.planar * (kx * kx + ky * ky) + oc.perp * kz * kz
         + oc.cross * kx * ky;
}

double CritTempSpectrum::omegaExact(const CritTempState& st,
                                    double kx, double ky, double kz) {
    LambdaInput lin(st, kx, ky, kz, true);
    RootFinder rf(&CritTempSpectrum::getLambda, &lin, 1.0, 0.0, 100.0,
                  1e-6);
    const RootData& rootData = rf.findRoot();
    if (!rootData.converged) {
        st.env.errorLog.printf("Failed to find root of Lambda at"
                               " k = (%f, %f, %f)\n", kx, ky, kz);
        return -1;
    }
    return rootData.root;
}
<commit_msg>adding debug messages<commit_after>/*
  Copyright (c) 2011 Timothy Lovorn

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

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

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

#include "CritTempSpectrum.hh"

LambdaInput::LambdaInput(const CritTempState& _st, double _kx, double _ky,
                         double _kz, double _lambdaMinus) :
    st(_st), kx(_kx), ky(_ky), kz(_kz), lambdaMinus(_lambdaMinus) { }

InnerPiInput::InnerPiInput(const CritTempState& _st, double _omega,
                           double _kx, double _ky) :
    st(_st), omega(_omega), kx(_kx), ky(_ky) { }

PiOutput::PiOutput(double _xx, double _xy, double _yy) :
    xx(_xx), xy(_xy), yy(_yy) { }

double CritTempSpectrum::epsilon(const CritTempState& st, double kx,
                                 double ky) {
    return epsilonBar(st, kx, ky) - st.getEpsilonMin();
}

double CritTempSpectrum::epsilonBar(const CritTempState& st, double kx,
                                    double ky) {
    const CritTempEnvironment& env = st.env;
    const double sx = sin(kx);
    const double sy = sin(ky);
    return 2.0 * env.th * ((sx + sy) * (sx + sy) - 1.0)
         + 4.0 * (st.getD1() * env.t0 - env.thp) * sx * sy;
}

double CritTempSpectrum::xi(const CritTempState& st, double kx, double ky) {
    return epsilon(st, kx, ky) - st.getMu();
}

double CritTempSpectrum::fermi(const CritTempState& st, double energy) {
    return 1.0 / (exp(st.getBc() * energy) + 1.0);
}

double CritTempSpectrum::bose(const CritTempState& st, double energy) {
    return 1.0 / (exp(st.getBc() * energy) - 1.0);
}

double CritTempSpectrum::innerX1(const CritTempState& st, double kx,
                                 double ky) {
    return fermi(st, xi(st, kx, ky));
}

double CritTempSpectrum::innerD1(const CritTempState& st, double kx,
                                 double ky) {
    return -sin(kx) * sin(ky) * fermi(st, xi(st, kx, ky));
}

double CritTempSpectrum::innerMu(const CritTempState& st, double kx,
                                 double ky) {
    const double sin_part = sin(kx) - sin(ky);
    return sin_part * sin_part * tanh(st.getBc() * xi(st, kx, ky) / 2.0) /
           xi(st, kx, ky);
}

double CritTempSpectrum::innerPiCommon(const InnerPiInput& ipi,
                                       double qx, double qy) {
    const CritTempState st = ipi.st;
    double xiPlus = xi(st, qx + ipi.kx / 2, qy + ipi.ky / 2);
    double xiMinus = xi(st, qx - ipi.kx / 2, qy - ipi.ky / 2);
    double common = -(tanh(st.getBc() * xiPlus / 2) + tanh(st.getBc()
        * xiMinus / 2)) / (ipi.omega - xiPlus - xiMinus);
    return common;
}

double CritTempSpectrum::innerPiXX(const InnerPiInput& ipi,
                                   double qx, double qy) {
    double common = innerPiCommon(ipi, qx, qy);
    return sin(qx) * sin(qx) * common;
}

double CritTempSpectrum::innerPiXY(const InnerPiInput& ipi,
                                   double qx, double qy) {
    double common = innerPiCommon(ipi, qx, qy);
    return sin(qx) * sin(qy) * common;
}

double CritTempSpectrum::innerPiYY(const InnerPiInput& ipi,
                                   double qx, double qy) {
    double common = innerPiCommon(ipi, qx, qy);
    return sin(qy) * sin(qy) * common;
}

double CritTempSpectrum::getLambda(double omega, void *params) {
    LambdaInput *lin = (LambdaInput*)params;
    const CritTempState& st = lin->st;
    double kx = lin->kx, ky = lin->ky, kz = lin->kz;

    double ex = 2 * (st.env.t0 * cos(ky) + st.env.tz * cos(kz)),
           ey = 2 * (st.env.t0 * cos(kx) + st.env.tz * cos(kz));
    PiOutput Pi = getPi(st, omega, kx, ky);
    double firstTerm = (ex * Pi.xx + ey * Pi.yy) / 2 - 1;
    double secondTerm = sqrt(pow((ex * Pi.xx - ey * Pi.yy), 2.0) / 4
        + ex * ey * pow(Pi.xy, 2.0));

    st.env.debugLog.printf("at (kx = %e, ky = %e, kz = %e), omega = %e:\n"
                           "Lambda first = %e, second = %e\n", kx, ky, kz,
                           omega, firstTerm, secondTerm);
    if (lin->lambdaMinus) {
        return firstTerm - secondTerm;
    } else {
        return firstTerm + secondTerm;
    }
}

PiOutput CritTempSpectrum::getPi(const CritTempState& st, double omega,
                                 double kx, double ky) {
    InnerPiInput ipi(st, omega, kx, ky);
    double piXX = BZone::average<InnerPiInput>(st, ipi, innerPiXX);
    double piXY = BZone::average<InnerPiInput>(st, ipi, innerPiXY);
    double piYY = BZone::average<InnerPiInput>(st, ipi, innerPiYY);
    PiOutput out(piXX, piXY, piYY);
    return out;
}

double CritTempSpectrum::nuFunction(double y, void *params) {
    return sqrt(y) / (exp(y) - 1);
}

double CritTempSpectrum::getNu(const CritTempState& st) {
    OmegaCoeffs ocs = getOmegaCoeffs(st);
    Integrator integrator(&nuFunction, NULL, 1e-6, 1e-6);
    double integral = integrator.doIntegral(0.0, -2 * st.getMu() * st.getBc(),
                                            st.env.errorLog);
    st.env.debugLog.printf("integral = %e\n"
                           "planar = %e cross = %e perp = %e\n", integral,
                           ocs.planar, ocs.cross, ocs.perp);
    double coeffPart = sqrt((ocs.planar + ocs.cross / 2.0) *
                            (ocs.planar - ocs.cross / 2.0) * ocs.perp);
    return integral / (4 * pow(M_PI, 2.0) * coeffPart);
}

OmegaCoeffs CritTempSpectrum::getOmegaCoeffs(const CritTempState& st) {
    double small_k = 0.05, sks = small_k * small_k;
    OmegaCoeffs ocs;
    ocs.planar = omegaExact(st, small_k, 0.0, 0.0) / sks;
    ocs.perp = omegaExact(st, 0.0, 0.0, small_k) / sks;
    ocs.cross = omegaExact(st, small_k, small_k, 0.0) / sks - 2 * ocs.planar;
    return ocs;
}

double CritTempSpectrum::omegaApprox(const OmegaCoeffs& oc,
                                     double kx, double ky, double kz) {
    return oc.planar * (kx * kx + ky * ky) + oc.perp * kz * kz
         + oc.cross * kx * ky;
}

double CritTempSpectrum::omegaExact(const CritTempState& st,
                                    double kx, double ky, double kz) {
    LambdaInput lin(st, kx, ky, kz, true);
    RootFinder rf(&CritTempSpectrum::getLambda, &lin, 0.05, 0.0, 100.0,
                  1e-6);
    const RootData& rootData = rf.findRoot();
    if (!rootData.converged) {
        st.env.errorLog.printf("Failed to find root of Lambda at"
                               " k = (%f, %f, %f)\n", kx, ky, kz);
        return -1;
    }
    return rootData.root;
}
<|endoftext|>


<commit_before>#include "MacauPrior.h"

#include <SmurffCpp/IO/MatrixIO.h>
#include <SmurffCpp/IO/GenericIO.h>

#include <SmurffCpp/Utils/Distribution.h>
#include <SmurffCpp/Utils/Error.h>

#include <SmurffCpp/Utils/linop.h>

#include <ios>

using namespace smurff;

MacauPrior::MacauPrior()
   : NormalPrior()
{
}

MacauPrior::MacauPrior(std::shared_ptr<BaseSession> session, uint32_t mode)
   : NormalPrior(session, mode, "MacauPrior")
{
   beta_precision = SideInfoConfig::BETA_PRECISION_DEFAULT_VALUE;
   tol = SideInfoConfig::TOL_DEFAULT_VALUE;

   enable_beta_precision_sampling = Config::ENABLE_BETA_PRECISION_SAMPLING_DEFAULT_VALUE;
}

MacauPrior::~MacauPrior()
{
}

void MacauPrior::init()
{
   NormalPrior::init();

   THROWERROR_ASSERT_MSG(Features->rows() == num_cols(), "Number of rows in train must be equal to number of rows in features");

   if (use_FtF)
   {
      std::uint64_t dim = Features->cols();
      FtF_plus_beta.resize(dim, dim);
      Features->At_mul_A(FtF_plus_beta);
      FtF_plus_beta.diagonal().array() += beta_precision;
   }

   Uhat.resize(this->num_latent(), Features->rows());
   Uhat.setZero();

   beta.resize(this->num_latent(), Features->cols());
   beta.setZero();
}

void MacauPrior::update_prior()
{
   // residual (Uhat is later overwritten):
   Uhat.noalias() = U() - Uhat;
   Eigen::MatrixXd BBt = smurff::linop::A_mul_At_combo(beta);

   // sampling Gaussian
   std::tie(this->mu, this->Lambda) = CondNormalWishart(Uhat, this->mu0, this->b0, this->WI + beta_precision * BBt, this->df + beta.cols());
   sample_beta();
   Features->compute_uhat(Uhat, beta);

   if (enable_beta_precision_sampling)
   {
      double old_beta = beta_precision;
      beta_precision = sample_beta_precision(beta, this->Lambda, beta_precision_nu0, beta_precision_mu0);
      FtF_plus_beta.diagonal().array() += beta_precision - old_beta;
   }
}

const Eigen::VectorXd MacauPrior::getMu(int n) const
{
   return this->mu + Uhat.col(n);
}

void MacauPrior::compute_Ft_y_omp(Eigen::MatrixXd& Ft_y)
{
   const int num_feat = beta.cols();

   // Ft_y = (U .- mu + Normal(0, Lambda^-1)) * F + std::sqrt(beta_precision) * Normal(0, Lambda^-1)
   // Ft_y is [ D x F ] matrix
   HyperU = (U() + MvNormal_prec(Lambda, num_cols())).colwise() - mu;

   Ft_y = Features->A_mul_B(HyperU);
   HyperU2 = MvNormal_prec(Lambda, num_feat);

   #pragma omp parallel for schedule(static)
   for (int f = 0; f < num_feat; f++)
   {
      for (int d = 0; d < num_latent(); d++)
      {
         Ft_y(d, f) += std::sqrt(beta_precision) * HyperU2(d, f);
      }
   }
}

void MacauPrior::sample_beta()
{
   if (use_FtF)
      sample_beta_direct();
   else
      sample_beta_cg();
}

void MacauPrior::addSideInfo(const std::shared_ptr<ISideInfo>& side_info_a, double beta_precision_a, double tolerance_a, bool direct_a, bool enable_beta_precision_sampling_a, bool throw_on_cholesky_error_a)
{
   //FIXME: remove old code

   // old code

   // side information
   Features = side_info_a;
   beta_precision = beta_precision_a;
   tol = tolerance_a;
   use_FtF = direct_a;
   enable_beta_precision_sampling = enable_beta_precision_sampling_a;
   throw_on_cholesky_error = throw_on_cholesky_error_a;

   // new code

   // side information
   side_info_values.push_back(side_info_a);
   beta_precision_values.push_back(beta_precision_a);
   tol_values.push_back(tolerance_a);
   direct_values.push_back(direct_a);
   enable_beta_precision_sampling_values.push_back(enable_beta_precision_sampling_a);
   throw_on_cholesky_error_values.push_back(throw_on_cholesky_error_a);

   // other code

   // Hyper-prior for beta_precision (mean 1.0, var of 1e+3):
   beta_precision_mu0 = 1.0;
   beta_precision_nu0 = 1e-3;
}

void MacauPrior::save(std::shared_ptr<const StepFile> sf) const
{
   NormalPrior::save(sf);

   std::string path = sf->getLinkMatrixFileName(m_mode);
   smurff::matrix_io::eigen::write_matrix(path, this->beta);
}

void MacauPrior::restore(std::shared_ptr<const StepFile> sf)
{
   NormalPrior::restore(sf);

   std::string path = sf->getLinkMatrixFileName(m_mode);

   THROWERROR_FILE_NOT_EXIST(path);

   smurff::matrix_io::eigen::read_matrix(path, this->beta);
}

std::ostream& MacauPrior::info(std::ostream &os, std::string indent)
{
   NormalPrior::info(os, indent);
   os << indent << " SideInfo: ";
   Features->print(os);
   os << indent << " Method: ";
   if (use_FtF)
   {
      os << "Cholesky Decomposition";
      double needs_gb = (double)Features->cols() / 1024. * (double)Features->cols() / 1024. / 1024.;
      if (needs_gb > 1.0) os << " (needing " << needs_gb << " GB of memory)";
      os << std::endl;
   } else {
      os << "CG Solver" << std::endl;
      os << indent << "  with tolerance: " << std::scientific << tol << std::fixed << std::endl;
   }
   os << indent << " BetaPrecision: " << beta_precision << std::endl;
   return os;
}

std::ostream& MacauPrior::status(std::ostream &os, std::string indent) const
{
   os << indent << m_name << ": " << std::endl;
   indent += "  ";
   os << indent << "FtF_plus_beta          = " << FtF_plus_beta.norm() << std::endl;
   os << indent << "HyperU       = " << HyperU.norm() << std::endl;
   os << indent << "HyperU2      = " << HyperU2.norm() << std::endl;
   os << indent << "Beta         = " << beta.norm() << std::endl;
   os << indent << "beta_precision  = " << beta_precision << std::endl;
   os << indent << "Ft_y         = " << Ft_y.norm() << std::endl;
   return os;
}

// direct method
void MacauPrior::sample_beta_direct()
{
    this->compute_Ft_y_omp(Ft_y);
    beta = FtF_plus_beta.llt().solve(Ft_y.transpose()).transpose();
}

std::pair<double, double> MacauPrior::posterior_beta_precision(Eigen::MatrixXd & beta, Eigen::MatrixXd & Lambda_u, double nu, double mu)
{
   const int D = beta.rows();
   Eigen::MatrixXd BB(D, D);
   smurff::linop::A_mul_At_combo(BB, beta);
   double nux = nu + beta.rows() * beta.cols();
   double mux = mu * nux / (nu + mu * (BB.selfadjointView<Eigen::Lower>() * Lambda_u).trace());
   double b = nux / 2;
   double c = 2 * mux / nux;
   return std::make_pair(b, c);
}

double MacauPrior::sample_beta_precision(Eigen::MatrixXd & beta, Eigen::MatrixXd & Lambda_u, double nu, double mu)
{
   auto gamma_post = posterior_beta_precision(beta, Lambda_u, nu, mu);
   return rgamma(gamma_post.first, gamma_post.second);
}

void MacauPrior::sample_beta_cg()
{
    Eigen::MatrixXd Ft_y;
    this->compute_Ft_y_omp(Ft_y);

    blockcg_iter = Features->solve_blockcg(beta, beta_precision, Ft_y, tol, 32, 8, throw_on_cholesky_error);
}
<commit_msg>print block cg number of iters<commit_after>#include "MacauPrior.h"

#include <SmurffCpp/IO/MatrixIO.h>
#include <SmurffCpp/IO/GenericIO.h>

#include <SmurffCpp/Utils/Distribution.h>
#include <SmurffCpp/Utils/Error.h>

#include <SmurffCpp/Utils/linop.h>

#include <ios>

using namespace smurff;

MacauPrior::MacauPrior()
   : NormalPrior()
{
}

MacauPrior::MacauPrior(std::shared_ptr<BaseSession> session, uint32_t mode)
   : NormalPrior(session, mode, "MacauPrior")
{
   beta_precision = SideInfoConfig::BETA_PRECISION_DEFAULT_VALUE;
   tol = SideInfoConfig::TOL_DEFAULT_VALUE;

   enable_beta_precision_sampling = Config::ENABLE_BETA_PRECISION_SAMPLING_DEFAULT_VALUE;
}

MacauPrior::~MacauPrior()
{
}

void MacauPrior::init()
{
   NormalPrior::init();

   THROWERROR_ASSERT_MSG(Features->rows() == num_cols(), "Number of rows in train must be equal to number of rows in features");

   if (use_FtF)
   {
      std::uint64_t dim = Features->cols();
      FtF_plus_beta.resize(dim, dim);
      Features->At_mul_A(FtF_plus_beta);
      FtF_plus_beta.diagonal().array() += beta_precision;
   }

   Uhat.resize(this->num_latent(), Features->rows());
   Uhat.setZero();

   beta.resize(this->num_latent(), Features->cols());
   beta.setZero();
}

void MacauPrior::update_prior()
{
   // residual (Uhat is later overwritten):
   Uhat.noalias() = U() - Uhat;
   Eigen::MatrixXd BBt = smurff::linop::A_mul_At_combo(beta);

   // sampling Gaussian
   std::tie(this->mu, this->Lambda) = CondNormalWishart(Uhat, this->mu0, this->b0, this->WI + beta_precision * BBt, this->df + beta.cols());
   sample_beta();
   Features->compute_uhat(Uhat, beta);

   if (enable_beta_precision_sampling)
   {
      double old_beta = beta_precision;
      beta_precision = sample_beta_precision(beta, this->Lambda, beta_precision_nu0, beta_precision_mu0);
      FtF_plus_beta.diagonal().array() += beta_precision - old_beta;
   }
}

const Eigen::VectorXd MacauPrior::getMu(int n) const
{
   return this->mu + Uhat.col(n);
}

void MacauPrior::compute_Ft_y_omp(Eigen::MatrixXd& Ft_y)
{
   const int num_feat = beta.cols();

   // Ft_y = (U .- mu + Normal(0, Lambda^-1)) * F + std::sqrt(beta_precision) * Normal(0, Lambda^-1)
   // Ft_y is [ D x F ] matrix
   HyperU = (U() + MvNormal_prec(Lambda, num_cols())).colwise() - mu;

   Ft_y = Features->A_mul_B(HyperU);
   HyperU2 = MvNormal_prec(Lambda, num_feat);

   #pragma omp parallel for schedule(static)
   for (int f = 0; f < num_feat; f++)
   {
      for (int d = 0; d < num_latent(); d++)
      {
         Ft_y(d, f) += std::sqrt(beta_precision) * HyperU2(d, f);
      }
   }
}

void MacauPrior::sample_beta()
{
   if (use_FtF)
      sample_beta_direct();
   else
      sample_beta_cg();
}

void MacauPrior::addSideInfo(const std::shared_ptr<ISideInfo>& side_info_a, double beta_precision_a, double tolerance_a, bool direct_a, bool enable_beta_precision_sampling_a, bool throw_on_cholesky_error_a)
{
   //FIXME: remove old code

   // old code

   // side information
   Features = side_info_a;
   beta_precision = beta_precision_a;
   tol = tolerance_a;
   use_FtF = direct_a;
   enable_beta_precision_sampling = enable_beta_precision_sampling_a;
   throw_on_cholesky_error = throw_on_cholesky_error_a;

   // new code

   // side information
   side_info_values.push_back(side_info_a);
   beta_precision_values.push_back(beta_precision_a);
   tol_values.push_back(tolerance_a);
   direct_values.push_back(direct_a);
   enable_beta_precision_sampling_values.push_back(enable_beta_precision_sampling_a);
   throw_on_cholesky_error_values.push_back(throw_on_cholesky_error_a);

   // other code

   // Hyper-prior for beta_precision (mean 1.0, var of 1e+3):
   beta_precision_mu0 = 1.0;
   beta_precision_nu0 = 1e-3;
}

void MacauPrior::save(std::shared_ptr<const StepFile> sf) const
{
   NormalPrior::save(sf);

   std::string path = sf->getLinkMatrixFileName(m_mode);
   smurff::matrix_io::eigen::write_matrix(path, this->beta);
}

void MacauPrior::restore(std::shared_ptr<const StepFile> sf)
{
   NormalPrior::restore(sf);

   std::string path = sf->getLinkMatrixFileName(m_mode);

   THROWERROR_FILE_NOT_EXIST(path);

   smurff::matrix_io::eigen::read_matrix(path, this->beta);
}

std::ostream& MacauPrior::info(std::ostream &os, std::string indent)
{
   NormalPrior::info(os, indent);
   os << indent << " SideInfo: ";
   Features->print(os);
   os << indent << " Method: ";
   if (use_FtF)
   {
      os << "Cholesky Decomposition";
      double needs_gb = (double)Features->cols() / 1024. * (double)Features->cols() / 1024. / 1024.;
      if (needs_gb > 1.0) os << " (needing " << needs_gb << " GB of memory)";
      os << std::endl;
   } else {
      os << "CG Solver" << std::endl;
      os << indent << "  with tolerance: " << std::scientific << tol << std::fixed << std::endl;
   }
   os << indent << " BetaPrecision: " << beta_precision << std::endl;
   return os;
}

std::ostream& MacauPrior::status(std::ostream &os, std::string indent) const
{
   os << indent << m_name << ": " << std::endl;
   indent += "  ";
   os << indent << "blockcg iter = " << blockcg_iter << std::endl;
   os << indent << "FtF_plus_beta= " << FtF_plus_beta.norm() << std::endl;
   os << indent << "HyperU       = " << HyperU.norm() << std::endl;
   os << indent << "HyperU2      = " << HyperU2.norm() << std::endl;
   os << indent << "Beta         = " << beta.norm() << std::endl;
   os << indent << "beta_precision  = " << beta_precision << std::endl;
   os << indent << "Ft_y         = " << Ft_y.norm() << std::endl;
   return os;
}

// direct method
void MacauPrior::sample_beta_direct()
{
    this->compute_Ft_y_omp(Ft_y);
    beta = FtF_plus_beta.llt().solve(Ft_y.transpose()).transpose();
}

std::pair<double, double> MacauPrior::posterior_beta_precision(Eigen::MatrixXd & beta, Eigen::MatrixXd & Lambda_u, double nu, double mu)
{
   const int D = beta.rows();
   Eigen::MatrixXd BB(D, D);
   smurff::linop::A_mul_At_combo(BB, beta);
   double nux = nu + beta.rows() * beta.cols();
   double mux = mu * nux / (nu + mu * (BB.selfadjointView<Eigen::Lower>() * Lambda_u).trace());
   double b = nux / 2;
   double c = 2 * mux / nux;
   return std::make_pair(b, c);
}

double MacauPrior::sample_beta_precision(Eigen::MatrixXd & beta, Eigen::MatrixXd & Lambda_u, double nu, double mu)
{
   auto gamma_post = posterior_beta_precision(beta, Lambda_u, nu, mu);
   return rgamma(gamma_post.first, gamma_post.second);
}

void MacauPrior::sample_beta_cg()
{
    Eigen::MatrixXd Ft_y;
    this->compute_Ft_y_omp(Ft_y);

    blockcg_iter = Features->solve_blockcg(beta, beta_precision, Ft_y, tol, 32, 8, throw_on_cholesky_error);
}
<|endoftext|>


<commit_before>//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.

#include <cassert>
#include <vector>
#include <set>
#include <unordered_map>

#include "llvm/IR/DataLayout.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Module.h"
#include "llvm/Pass.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/TypeBuilder.h"
#if (LLVM_VERSION_MINOR >= 5)
  #include "llvm/IR/InstIterator.h"
#else
  #include "llvm/Support/InstIterator.h"
#endif
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include <llvm/IR/DebugInfoMetadata.h>

using namespace llvm;

class DeleteUndefined : public ModulePass {
  Function *_vms = nullptr; // verifier_make_symbolic function
  Type *_size_t_Ty = nullptr; // type of size_t
  bool _nosym; // do not use symbolic values when replacing

  std::unordered_map<llvm::Type *, llvm::GlobalVariable *> added_globals;

  // add global of given type and initialize it in may as nondeterministic
  GlobalVariable *getGlobalNondet(llvm::Type *, llvm::Module *);
  Function *get_verifier_make_symbolic(llvm::Module *);
  Type *get_size_t(llvm::Module *);

  //void replaceCall(CallInst *CI, Module *M);
  void defineFunction(Module *M, Function *F);
protected:
  DeleteUndefined(char id) : ModulePass(id), _nosym(true) {}

public:
  static char ID;

  DeleteUndefined() : ModulePass(ID), _nosym(false) {}

  virtual bool runOnModule(Module& M) override;
  bool runOnFunction(Function &F);
};

static RegisterPass<DeleteUndefined> DLTU("delete-undefined",
                                          "delete calls to undefined functions, "
                                          "possible return value is made symbolic");
char DeleteUndefined::ID;

class DeleteUndefinedNoSym : public DeleteUndefined {
  public:
    static char ID;

    DeleteUndefinedNoSym() : DeleteUndefined(ID) {}
};

static RegisterPass<DeleteUndefinedNoSym> DLTUNS("delete-undefined-nosym",
                                          "delete calls to undefined functions, "
                                          "possible return value is made 0");
char DeleteUndefinedNoSym::ID;

static const char *leave_calls[] = {
  "__assert_fail",
  "abort",
  "klee_make_symbolic",
  "klee_assume",
  "klee_abort",
  "klee_silent_exit",
  "klee_report_error",
  "klee_warning_once",
  "klee_int",
  "exit",
  "_exit",
  "malloc",
  "calloc",
  "realloc",
  "free",
  "memset",
  "memcmp",
  "memcpy",
  "memmove",
  "kzalloc",
  "__errno_location",
  NULL
};

static bool array_match(const StringRef &name, const char **array)
{
  for (const char **curr = array; *curr; curr++)
    if (name.equals(*curr))
      return true;
  return false;
}

bool DeleteUndefined::runOnModule(Module& M) {
    M.materializeAll();

    // delete/replace the calls in the rest of functions
    bool modified = false;
    for (auto& F : M.getFunctionList())
      modified |= runOnFunction(F);

    return modified;
}

/** Clone metadata from one instruction to another
 * @param i1 the first instruction
 * @param i2 the second instruction without any metadata
*/
static void CloneMetadata(const llvm::Instruction *i1, llvm::Instruction *i2)
{
    if (!i1->hasMetadata())
        return;

    assert(!i2->hasMetadata());
    llvm::SmallVector< std::pair< unsigned, llvm::MDNode * >, 2> mds;
    i1->getAllMetadata(mds);

    for (const auto& it : mds) {
        i2->setMetadata(it.first, it.second->clone().release());
    }
}

static void CallAddMetadata(CallInst *CI, Instruction *I)
{
  if (const DISubprogram *DS = I->getParent()->getParent()->getSubprogram()) {
    // no metadata? then it is going to be the instrumentation
    // of alloca or such at the beggining of function,
    // so just add debug loc of the beginning of the function
    CI->setDebugLoc(DebugLoc::get(DS->getLine(), 0, DS));
  }
}

Function *DeleteUndefined::get_verifier_make_symbolic(llvm::Module *M)
{
  if (_vms)
    return _vms;

  LLVMContext& Ctx = M->getContext();
  //void verifier_make_symbolic(void *addr, size_t nbytes, const char *name);
  Constant *C = M->getOrInsertFunction("__VERIFIER_make_symbolic",
                                       Type::getVoidTy(Ctx),
                                       Type::getInt8PtrTy(Ctx), // addr
                                       get_size_t(M),   // nbytes
                                       Type::getInt8PtrTy(Ctx), // name
                                       nullptr);
  _vms = cast<Function>(C);
  return _vms;
}

Type *DeleteUndefined::get_size_t(llvm::Module *M)
{
  if (_size_t_Ty)
    return _size_t_Ty;

  std::unique_ptr<DataLayout> DL
    = std::unique_ptr<DataLayout>(new DataLayout(M->getDataLayout()));
  LLVMContext& Ctx = M->getContext();

  if (DL->getPointerSizeInBits() > 32)
    _size_t_Ty = Type::getInt64Ty(Ctx);
  else
    _size_t_Ty = Type::getInt32Ty(Ctx);

  return _size_t_Ty;
}

// add global of given type and initialize it in may as nondeterministic
// FIXME: use the same variables as in InitializeUninitialized
GlobalVariable *DeleteUndefined::getGlobalNondet(llvm::Type *Ty, llvm::Module *M)
{
  auto it = added_globals.find(Ty);
  if (it != added_globals.end())
    return it->second;

  LLVMContext& Ctx = M->getContext();
  GlobalVariable *G = new GlobalVariable(*M, Ty, false /* constant */,
                                         GlobalValue::PrivateLinkage,
                                         /* initializer */
                                         Constant::getNullValue(Ty),
                                         "nondet_gl_undef");

  added_globals.emplace(Ty, G);

  // insert initialization of the new global variable
  // at the beginning of main
  Function *vms = get_verifier_make_symbolic(M);
  CastInst *CastI = CastInst::CreatePointerCast(G, Type::getInt8PtrTy(Ctx));

  std::vector<Value *> args;
  //XXX: we should not build the new DL every time
  std::unique_ptr<DataLayout> DL
    = std::unique_ptr<DataLayout>(new DataLayout(M->getDataLayout()));

  args.push_back(CastI);
  args.push_back(ConstantInt::get(get_size_t(M), DL->getTypeAllocSize(Ty)));
  Constant *name = ConstantDataArray::getString(Ctx, "nondet");
  GlobalVariable *nameG = new GlobalVariable(*M, name->getType(), true /*constant */,
                                             GlobalVariable::PrivateLinkage, name);
  args.push_back(ConstantExpr::getPointerCast(nameG, Type::getInt8PtrTy(Ctx)));
  CallInst *CI = CallInst::Create(vms, args);

  Function *main = M->getFunction("main");
  assert(main && "Do not have main");
  BasicBlock& block = main->getBasicBlockList().front();
  // there must be some instruction, otherwise we would not be calling
  // this function
  Instruction& I = *(block.begin());
  CastI->insertBefore(&I);
  CI->insertBefore(&I);

  // add metadata due to the inliner pass
  CallAddMetadata(CI, &I);
  //CloneMetadata(&I, CastI);

  return G;
}

/*
void DeleteUndefined::replaceCall(CallInst *CI, Module *M)
{
  LLVMContext& Ctx = M->getContext();
  Type *Ty = CI->getType();
  // we checked for this before
  assert(!Ty->isVoidTy());
  // what to do in this case?
  assert(Ty->isSized());

  LoadInst *LI = new LoadInst(getGlobalNondet(Ty, M));
  LI->insertBefore(CI);
  CI->replaceAllUsesWith(LI);
}
*/

void DeleteUndefined::defineFunction(Module *M, Function *F)
{
  assert(F->size() == 0);
  assert(!F->getReturnType()->isVoidTy());

  LLVMContext& Ctx = M->getContext();
  BasicBlock *block = BasicBlock::Create(Ctx, "entry", F);
  if (_nosym) {
    // replace the return value with 0, since we don't want
    // to use the symbolic value
    ReturnInst::Create(Ctx, Constant::getNullValue(F->getReturnType()), block);
  } else {
    LoadInst *LI = new LoadInst(getGlobalNondet(F->getReturnType(), M),
                                "ret_from_undef", block);
    ReturnInst::Create(Ctx, LI, block);
  }

  F->setLinkage(GlobalValue::LinkageTypes::InternalLinkage);
}

bool DeleteUndefined::runOnFunction(Function &F)
{
  // static set for the calls that we removed, so that
  // we can print those call only once
  static std::set<const llvm::Value *> removed_calls;
  Module *M = F.getParent();

  if (F.getName().startswith("__VERIFIER_"))
    return false;

  if (array_match(F.getName(), leave_calls))
    return false;

  if (F.empty() && !F.getReturnType()->isVoidTy()) {
    errs() << "Defining function " << F.getName() << " as symbolic\n";
    defineFunction(M, &F);
    return true;
  }

  // nothing to do here...
  if (F.empty())
    return false;

  // if the function is defined, just delete the calls to undefined
  // functions that does not return anything (if it does return anything,
  // it was/will be fixed in defineFunction()
  bool modified = false;
  for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E;) {
    Instruction *ins = &*I;
    ++I;
    if (CallInst *CI = dyn_cast<CallInst>(ins)) {
      if (CI->isInlineAsm())
        continue;

      Value *val = CI->getCalledValue()->stripPointerCasts();
      Function *callee = dyn_cast<Function>(val);
      // if this is intrinsic call or a call via a function pointer,
      // let it be
      // XXX: do we handle the function pointers correctly? What if there
      // is only a declaration of a function and it is taken to pointer
      // and then called? We do not define it in this case...
      if (!callee || callee->isIntrinsic())
        continue;

      // here we continue only with undefined function that return nothing,
      // becuase the functions that return something were/will be
      // defined in defineFunction()
      if (!callee->getReturnType()->isVoidTy())
        continue;

      assert(callee->hasName());
      StringRef name = callee->getName();

      // if this is __VERIFIER_* call, keep it
      if (name.startswith("__VERIFIER_"))
        continue;

      if (array_match(name, leave_calls))
        continue;

      if (callee->isDeclaration()) {
        if (removed_calls.insert(callee).second)
            errs() << "Removed calls to '" << name << "' (function is undefined)\n";

        // remove the call
        assert(CI->getType()->isVoidTy());
        CI->eraseFromParent();
        modified = true;
      }
    }
  }
  return modified;
}

<commit_msg>do not try make intrinsic functions symbolic<commit_after>//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.

#include <cassert>
#include <vector>
#include <set>
#include <unordered_map>

#include "llvm/IR/DataLayout.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Module.h"
#include "llvm/Pass.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/TypeBuilder.h"
#if (LLVM_VERSION_MINOR >= 5)
  #include "llvm/IR/InstIterator.h"
#else
  #include "llvm/Support/InstIterator.h"
#endif
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include <llvm/IR/DebugInfoMetadata.h>

using namespace llvm;

class DeleteUndefined : public ModulePass {
  Function *_vms = nullptr; // verifier_make_symbolic function
  Type *_size_t_Ty = nullptr; // type of size_t
  bool _nosym; // do not use symbolic values when replacing

  std::unordered_map<llvm::Type *, llvm::GlobalVariable *> added_globals;

  // add global of given type and initialize it in may as nondeterministic
  GlobalVariable *getGlobalNondet(llvm::Type *, llvm::Module *);
  Function *get_verifier_make_symbolic(llvm::Module *);
  Type *get_size_t(llvm::Module *);

  //void replaceCall(CallInst *CI, Module *M);
  void defineFunction(Module *M, Function *F);
protected:
  DeleteUndefined(char id) : ModulePass(id), _nosym(true) {}

public:
  static char ID;

  DeleteUndefined() : ModulePass(ID), _nosym(false) {}

  virtual bool runOnModule(Module& M) override;
  bool runOnFunction(Function &F);
};

static RegisterPass<DeleteUndefined> DLTU("delete-undefined",
                                          "delete calls to undefined functions, "
                                          "possible return value is made symbolic");
char DeleteUndefined::ID;

class DeleteUndefinedNoSym : public DeleteUndefined {
  public:
    static char ID;

    DeleteUndefinedNoSym() : DeleteUndefined(ID) {}
};

static RegisterPass<DeleteUndefinedNoSym> DLTUNS("delete-undefined-nosym",
                                          "delete calls to undefined functions, "
                                          "possible return value is made 0");
char DeleteUndefinedNoSym::ID;

static const char *leave_calls[] = {
  "__assert_fail",
  "abort",
  "klee_make_symbolic",
  "klee_assume",
  "klee_abort",
  "klee_silent_exit",
  "klee_report_error",
  "klee_warning_once",
  "klee_int",
  "exit",
  "_exit",
  "malloc",
  "calloc",
  "realloc",
  "free",
  "memset",
  "memcmp",
  "memcpy",
  "memmove",
  "kzalloc",
  "__errno_location",
  NULL
};

static bool array_match(const StringRef &name, const char **array)
{
  for (const char **curr = array; *curr; curr++)
    if (name.equals(*curr))
      return true;
  return false;
}

bool DeleteUndefined::runOnModule(Module& M) {
    M.materializeAll();

    // delete/replace the calls in the rest of functions
    bool modified = false;
    for (auto& F : M.getFunctionList()) {
      if (F.isIntrinsic())
        continue;

      modified |= runOnFunction(F);
    }

    return modified;
}

/** Clone metadata from one instruction to another
 * @param i1 the first instruction
 * @param i2 the second instruction without any metadata
*/
static void CloneMetadata(const llvm::Instruction *i1, llvm::Instruction *i2)
{
    if (!i1->hasMetadata())
        return;

    assert(!i2->hasMetadata());
    llvm::SmallVector< std::pair< unsigned, llvm::MDNode * >, 2> mds;
    i1->getAllMetadata(mds);

    for (const auto& it : mds) {
        i2->setMetadata(it.first, it.second->clone().release());
    }
}

static void CallAddMetadata(CallInst *CI, Instruction *I)
{
  if (const DISubprogram *DS = I->getParent()->getParent()->getSubprogram()) {
    // no metadata? then it is going to be the instrumentation
    // of alloca or such at the beggining of function,
    // so just add debug loc of the beginning of the function
    CI->setDebugLoc(DebugLoc::get(DS->getLine(), 0, DS));
  }
}

Function *DeleteUndefined::get_verifier_make_symbolic(llvm::Module *M)
{
  if (_vms)
    return _vms;

  LLVMContext& Ctx = M->getContext();
  //void verifier_make_symbolic(void *addr, size_t nbytes, const char *name);
  Constant *C = M->getOrInsertFunction("__VERIFIER_make_symbolic",
                                       Type::getVoidTy(Ctx),
                                       Type::getInt8PtrTy(Ctx), // addr
                                       get_size_t(M),   // nbytes
                                       Type::getInt8PtrTy(Ctx), // name
                                       nullptr);
  _vms = cast<Function>(C);
  return _vms;
}

Type *DeleteUndefined::get_size_t(llvm::Module *M)
{
  if (_size_t_Ty)
    return _size_t_Ty;

  std::unique_ptr<DataLayout> DL
    = std::unique_ptr<DataLayout>(new DataLayout(M->getDataLayout()));
  LLVMContext& Ctx = M->getContext();

  if (DL->getPointerSizeInBits() > 32)
    _size_t_Ty = Type::getInt64Ty(Ctx);
  else
    _size_t_Ty = Type::getInt32Ty(Ctx);

  return _size_t_Ty;
}

// add global of given type and initialize it in may as nondeterministic
// FIXME: use the same variables as in InitializeUninitialized
GlobalVariable *DeleteUndefined::getGlobalNondet(llvm::Type *Ty, llvm::Module *M)
{
  auto it = added_globals.find(Ty);
  if (it != added_globals.end())
    return it->second;

  LLVMContext& Ctx = M->getContext();
  GlobalVariable *G = new GlobalVariable(*M, Ty, false /* constant */,
                                         GlobalValue::PrivateLinkage,
                                         /* initializer */
                                         Constant::getNullValue(Ty),
                                         "nondet_gl_undef");

  added_globals.emplace(Ty, G);

  // insert initialization of the new global variable
  // at the beginning of main
  Function *vms = get_verifier_make_symbolic(M);
  CastInst *CastI = CastInst::CreatePointerCast(G, Type::getInt8PtrTy(Ctx));

  std::vector<Value *> args;
  //XXX: we should not build the new DL every time
  std::unique_ptr<DataLayout> DL
    = std::unique_ptr<DataLayout>(new DataLayout(M->getDataLayout()));

  args.push_back(CastI);
  args.push_back(ConstantInt::get(get_size_t(M), DL->getTypeAllocSize(Ty)));
  Constant *name = ConstantDataArray::getString(Ctx, "nondet");
  GlobalVariable *nameG = new GlobalVariable(*M, name->getType(), true /*constant */,
                                             GlobalVariable::PrivateLinkage, name);
  args.push_back(ConstantExpr::getPointerCast(nameG, Type::getInt8PtrTy(Ctx)));
  CallInst *CI = CallInst::Create(vms, args);

  Function *main = M->getFunction("main");
  assert(main && "Do not have main");
  BasicBlock& block = main->getBasicBlockList().front();
  // there must be some instruction, otherwise we would not be calling
  // this function
  Instruction& I = *(block.begin());
  CastI->insertBefore(&I);
  CI->insertBefore(&I);

  // add metadata due to the inliner pass
  CallAddMetadata(CI, &I);
  //CloneMetadata(&I, CastI);

  return G;
}

/*
void DeleteUndefined::replaceCall(CallInst *CI, Module *M)
{
  LLVMContext& Ctx = M->getContext();
  Type *Ty = CI->getType();
  // we checked for this before
  assert(!Ty->isVoidTy());
  // what to do in this case?
  assert(Ty->isSized());

  LoadInst *LI = new LoadInst(getGlobalNondet(Ty, M));
  LI->insertBefore(CI);
  CI->replaceAllUsesWith(LI);
}
*/

void DeleteUndefined::defineFunction(Module *M, Function *F)
{
  assert(F->size() == 0);
  assert(!F->getReturnType()->isVoidTy());

  LLVMContext& Ctx = M->getContext();
  BasicBlock *block = BasicBlock::Create(Ctx, "entry", F);
  if (_nosym) {
    // replace the return value with 0, since we don't want
    // to use the symbolic value
    ReturnInst::Create(Ctx, Constant::getNullValue(F->getReturnType()), block);
  } else {
    LoadInst *LI = new LoadInst(getGlobalNondet(F->getReturnType(), M),
                                "ret_from_undef", block);
    ReturnInst::Create(Ctx, LI, block);
  }

  F->setLinkage(GlobalValue::LinkageTypes::InternalLinkage);
}

bool DeleteUndefined::runOnFunction(Function &F)
{
  // static set for the calls that we removed, so that
  // we can print those call only once
  static std::set<const llvm::Value *> removed_calls;
  Module *M = F.getParent();

  if (F.getName().startswith("__VERIFIER_"))
    return false;

  if (array_match(F.getName(), leave_calls))
    return false;

  if (F.empty() && !F.getReturnType()->isVoidTy()) {
    errs() << "Defining function " << F.getName() << " as symbolic\n";
    defineFunction(M, &F);
    return true;
  }

  // nothing to do here...
  if (F.empty())
    return false;

  // if the function is defined, just delete the calls to undefined
  // functions that does not return anything (if it does return anything,
  // it was/will be fixed in defineFunction()
  bool modified = false;
  for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E;) {
    Instruction *ins = &*I;
    ++I;
    if (CallInst *CI = dyn_cast<CallInst>(ins)) {
      if (CI->isInlineAsm())
        continue;

      Value *val = CI->getCalledValue()->stripPointerCasts();
      Function *callee = dyn_cast<Function>(val);
      // if this is intrinsic call or a call via a function pointer,
      // let it be
      // XXX: do we handle the function pointers correctly? What if there
      // is only a declaration of a function and it is taken to pointer
      // and then called? We do not define it in this case...
      if (!callee || callee->isIntrinsic())
        continue;

      // here we continue only with undefined function that return nothing,
      // becuase the functions that return something were/will be
      // defined in defineFunction()
      if (!callee->getReturnType()->isVoidTy())
        continue;

      assert(callee->hasName());
      StringRef name = callee->getName();

      // if this is __VERIFIER_* call, keep it
      if (name.startswith("__VERIFIER_"))
        continue;

      if (array_match(name, leave_calls))
        continue;

      if (callee->isDeclaration()) {
        if (removed_calls.insert(callee).second)
            errs() << "Removed calls to '" << name << "' (function is undefined)\n";

        // remove the call
        assert(CI->getType()->isVoidTy());
        CI->eraseFromParent();
        modified = true;
      }
    }
  }
  return modified;
}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: impgrf.hxx,v $
 *
 *  $Revision: 1.1.1.1 $
 *
 *  last change: $Author: hr $ $Date: 2000-09-18 17:00:57 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef _SVX_IMPGRF_HXX
#define _SVX_IMPGRF_HXX

// include ---------------------------------------------------------------

#ifndef _FILTER_HXX //autogen
#include <svtools/filter.hxx>
#endif

#ifndef _BUTTON_HXX //autogen
#include <vcl/button.hxx>
#endif

#ifndef _IODLG_HXX
#include <sfx2/iodlg.hxx>
#endif

// forward ---------------------------------------------------------------

class  SvxGraphicHdl_Impl;
class  SfxObjectShell;
struct SvxImportGraphicRes_Impl;
class  SvxGraphicPrevWin_Impl;
class  SfxMedium;

// Funktionen ------------------------------------------------------------

// returnt einen static Graphic-Filter, wird einmalig angelegt,
// steht immer zur Verfuegung, DARF NIE geloescht werden!!!!
GraphicFilter* GetGrfFilter();
USHORT  FillFilter( GraphicFilter& rFilter );
int     LoadGraphic( const String& rPath, const String& rFilter,
                     Graphic& rGraphic,
                     GraphicFilter* pFilter = NULL,
                     USHORT* pDeterminedFormat = NULL );

// class SvxImportGraphicDialog ------------------------------------------
#ifndef SV_NODIALOG

#define ENABLE_STANDARD         ((USHORT)0x0001)    // Standard-Button
#define ENABLE_LINK             ((USHORT)0x0002)    // Verkn"upfungs-Box
#define ENABLE_STD_AND_LINK     (ENABLE_STANDARD | ENABLE_LINK)
#define ENABLE_PROPERTY         ((USHORT)0x0004)    // Eigenschaften-Button
#define ENABLE_ALL              ((USHORT)0x0007)    // alle
#define ENABLE_PROP_WITHOUTLINK ((USHORT)0x0008)    // Eigenschaften ohne Link
#define ENABLE_EMPTY_FILENAMES  ((USHORT)0x0010)    // Leere Dateinamen zulassen

class SvxImportGraphicDialog : public SfxFileDialog
{
public:
    SvxImportGraphicDialog( Window* pParent,
                            const String& rTitle,
                            const USHORT nEnable = ENABLE_STANDARD,
                            WinBits nWinBits = WB_OPEN | WB_3DLOOK );
    ~SvxImportGraphicDialog();

    short                   Execute();
    void                    SetPath( const String& rPath, BOOL bDir,
                                        BOOL bLink = FALSE );

    BOOL                    IsURL() const;
    BOOL                    AsLink() const
                                { return pLinkBox && pLinkBox->IsChecked(); }
    GraphicFilter&          GetFilter() { return *GetGrfFilter(); }
    SvxGraphicPrevWin_Impl& GetPreviewWindow() { return *pPrevWin; }

    void                    SetPreviewing( BOOL bPrev );
    BOOL                    IsPreviewing() const { return bPreviewing; }

    Link                    GetPropertyHdl() const { return aPropertyLink; }
    void                    SetPropertyHdl( const Link& rLink )
                                { aPropertyLink = rLink; }

    Graphic*                GetGraphic() const;
    String                  GetPath() const;

private:
friend class SvxGraphicPrevWin_Impl;

    SvxImportGraphicRes_Impl*   pResImpl;
    SvxGraphicPrevWin_Impl*     pPrevWin;

    SfxMedium*              pMedium;

    PushButton*             pStandardButton;
    PushButton*             pInternetButton;
    PushButton*             pPropertiesButton;
    PushButton*             pFilterButton;
    CheckBox*               pLinkBox;
    CheckBox*               pPreviewBox;

    Link                    aPropertyLink;
    String                  aStartPath;
    String                  aCurrPath;
    Timer                   aPrevTimer;
    BOOL                    bPreviewing;
    void                    FileSelect();
    long                    OK();
    void                    SetPath( const String& ); // just to make private

#ifdef _SVX_IMPGRF_CXX
    void                    Construct_Impl( const String &rTitle,
                                            USHORT nEnable );

    DECL_LINK( StandardHdl_Impl, Button * );
    DECL_LINK( PropertiesHdl_Impl, Button * );
    DECL_LINK( FilterHdl_Impl, Button * );
    DECL_LINK( PreviewHdl_Impl, Button * );
    DECL_LINK( TimeOutHdl_Impl, Timer * );
    DECL_LINK( FilterSelectHdl_Impl, void * );
    DECL_LINK( FileSelectHdl_Impl, void * );
#endif
};

#endif  // SV_NODIALOG

#endif

<commit_msg>#89176# Removed class SvxImportGraphicDialog()<commit_after>/*************************************************************************
 *
 *  $RCSfile: impgrf.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: dv $ $Date: 2001-07-09 14:48:29 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef _SVX_IMPGRF_HXX
#define _SVX_IMPGRF_HXX

// include ---------------------------------------------------------------

#ifndef _FILTER_HXX //autogen
#include <svtools/filter.hxx>
#endif

#ifndef _BUTTON_HXX //autogen
#include <vcl/button.hxx>
#endif

// Funktionen ------------------------------------------------------------

// returnt einen static Graphic-Filter, wird einmalig angelegt,
// steht immer zur Verfuegung, DARF NIE geloescht werden!!!!
GraphicFilter* GetGrfFilter();
USHORT  FillFilter( GraphicFilter& rFilter );
int     LoadGraphic( const String& rPath, const String& rFilter,
                     Graphic& rGraphic,
                     GraphicFilter* pFilter = NULL,
                     USHORT* pDeterminedFormat = NULL );

// class SvxImportGraphicDialog ------------------------------------------
#ifndef SV_NODIALOG

#define ENABLE_STANDARD         ((USHORT)0x0001)    // Standard-Button
#define ENABLE_LINK             ((USHORT)0x0002)    // Verkn"upfungs-Box
#define ENABLE_STD_AND_LINK     (ENABLE_STANDARD | ENABLE_LINK)
#define ENABLE_PROPERTY         ((USHORT)0x0004)    // Eigenschaften-Button
#define ENABLE_ALL              ((USHORT)0x0007)    // alle
#define ENABLE_PROP_WITHOUTLINK ((USHORT)0x0008)    // Eigenschaften ohne Link
#define ENABLE_EMPTY_FILENAMES  ((USHORT)0x0010)    // Leere Dateinamen zulassen

#endif  // SV_NODIALOG

#endif
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: fmtruby.hxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 01:53:02 $
 *
 *  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
 *
 ************************************************************************/
#ifndef _FMTRUBY_HXX
#define _FMTRUBY_HXX

#ifndef _STRING_HXX //autogen
#include <tools/string.hxx>
#endif
#ifndef _SFXPOOLITEM_HXX
#include <svtools/poolitem.hxx>
#endif

class SwTxtRuby;

class SwFmtRuby : public SfxPoolItem
{
    friend class SwTxtRuby;

    String sRubyTxt;                    // the ruby txt
    String sCharFmtName;                // name of the charformat
    SwTxtRuby* pTxtAttr;                // the TextAttribut
    USHORT nCharFmtId;                  // PoolId of the charformat
    USHORT nPosition;                   // Position of the Ruby-Character
    USHORT nAdjustment;                 // specific adjustment of the Ruby-Ch.

public:
    SwFmtRuby( const String& rRubyTxt );
    SwFmtRuby( const SwFmtRuby& rAttr );
    virtual ~SwFmtRuby();

    SwFmtRuby& operator=( const SwFmtRuby& rAttr );

    // "pure virtual Methoden" vom SfxPoolItem
    virtual int             operator==( const SfxPoolItem& ) const;
    virtual SfxPoolItem*    Clone( SfxItemPool* pPool = 0 ) const;

    virtual SfxItemPresentation GetPresentation( SfxItemPresentation ePres,
                                    SfxMapUnit eCoreMetric,
                                    SfxMapUnit ePresMetric,
                                    String &rText,
                                    const IntlWrapper* pIntl = 0 ) const;

    virtual BOOL            QueryValue( com::sun::star::uno::Any& rVal,
                                        BYTE nMemberId = 0 ) const;
    virtual BOOL            PutValue( const com::sun::star::uno::Any& rVal,
                                        BYTE nMemberId = 0 );

    const SwTxtRuby* GetTxtRuby() const         { return pTxtAttr; }
    SwTxtRuby* GetTxtRuby()                     { return pTxtAttr; }

    const String& GetText() const               { return sRubyTxt; }
    void SetText( const String& rTxt )          { sRubyTxt = rTxt; }

    const String& GetCharFmtName() const        { return sCharFmtName; }
    void SetCharFmtName( const String& rNm )    { sCharFmtName = rNm; }

    USHORT GetCharFmtId() const                 { return nCharFmtId; }
    void SetCharFmtId( USHORT nNew )            { nCharFmtId = nNew; }

    USHORT GetPosition() const                  { return nPosition; }
    void SetPosition( USHORT nNew )             { nPosition = nNew; }

    USHORT GetAdjustment() const                { return nAdjustment; }
    void SetAdjustment( USHORT nNew )           { nAdjustment = nNew; }
};

#endif

<commit_msg>INTEGRATION: CWS changefileheader (1.6.1202); FILE MERGED 2008/04/01 15:56:13 thb 1.6.1202.2: #i85898# Stripping all external header guards 2008/03/31 16:52:38 rt 1.6.1202.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: fmtruby.hxx,v $
 * $Revision: 1.7 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/
#ifndef _FMTRUBY_HXX
#define _FMTRUBY_HXX

#include <tools/string.hxx>
#include <svtools/poolitem.hxx>

class SwTxtRuby;

class SwFmtRuby : public SfxPoolItem
{
    friend class SwTxtRuby;

    String sRubyTxt;                    // the ruby txt
    String sCharFmtName;                // name of the charformat
    SwTxtRuby* pTxtAttr;                // the TextAttribut
    USHORT nCharFmtId;                  // PoolId of the charformat
    USHORT nPosition;                   // Position of the Ruby-Character
    USHORT nAdjustment;                 // specific adjustment of the Ruby-Ch.

public:
    SwFmtRuby( const String& rRubyTxt );
    SwFmtRuby( const SwFmtRuby& rAttr );
    virtual ~SwFmtRuby();

    SwFmtRuby& operator=( const SwFmtRuby& rAttr );

    // "pure virtual Methoden" vom SfxPoolItem
    virtual int             operator==( const SfxPoolItem& ) const;
    virtual SfxPoolItem*    Clone( SfxItemPool* pPool = 0 ) const;

    virtual SfxItemPresentation GetPresentation( SfxItemPresentation ePres,
                                    SfxMapUnit eCoreMetric,
                                    SfxMapUnit ePresMetric,
                                    String &rText,
                                    const IntlWrapper* pIntl = 0 ) const;

    virtual BOOL            QueryValue( com::sun::star::uno::Any& rVal,
                                        BYTE nMemberId = 0 ) const;
    virtual BOOL            PutValue( const com::sun::star::uno::Any& rVal,
                                        BYTE nMemberId = 0 );

    const SwTxtRuby* GetTxtRuby() const         { return pTxtAttr; }
    SwTxtRuby* GetTxtRuby()                     { return pTxtAttr; }

    const String& GetText() const               { return sRubyTxt; }
    void SetText( const String& rTxt )          { sRubyTxt = rTxt; }

    const String& GetCharFmtName() const        { return sCharFmtName; }
    void SetCharFmtName( const String& rNm )    { sCharFmtName = rNm; }

    USHORT GetCharFmtId() const                 { return nCharFmtId; }
    void SetCharFmtId( USHORT nNew )            { nCharFmtId = nNew; }

    USHORT GetPosition() const                  { return nPosition; }
    void SetPosition( USHORT nNew )             { nPosition = nNew; }

    USHORT GetAdjustment() const                { return nAdjustment; }
    void SetAdjustment( USHORT nNew )           { nAdjustment = nNew; }
};

#endif

<|endoftext|>