<commit_before>#include "Core.hpp"
#include "midi.hpp"
#include "dsp/digital.hpp"
#include "dsp/filter.hpp"

#include <algorithm>

struct MIDIToCVInterface : Module {
	enum ParamIds {
		NUM_PARAMS
	};
	enum InputIds {
		NUM_INPUTS
	};
	enum OutputIds {
		CV_OUTPUT,
		GATE_OUTPUT,
		VELOCITY_OUTPUT,
		AFTERTOUCH_OUTPUT,
		PITCH_OUTPUT,
		MOD_OUTPUT,
		RETRIGGER_OUTPUT,
		CLOCK_1_OUTPUT,
		CLOCK_2_OUTPUT,
		START_OUTPUT,
		STOP_OUTPUT,
		CONTINUE_OUTPUT,
		NUM_OUTPUTS
	};
	enum LightIds {
		NUM_LIGHTS
	};

	MidiInputQueue midiInput;

	uint8_t mod = 0;
	ExponentialFilter modFilter;
	uint16_t pitch = 0;
	ExponentialFilter pitchFilter;
	PulseGenerator retriggerPulse;
	PulseGenerator clock1Pulse;
	PulseGenerator clock2Pulse;
	PulseGenerator startPulse;
	PulseGenerator stopPulse;
	PulseGenerator continuePulse;

	struct NoteData {
		uint8_t velocity = 0;
		uint8_t aftertouch = 0;
	};

	NoteData noteData[128];
	std::vector<uint8_t> heldNotes;
	uint8_t lastNote;
	bool pedal;
	bool gate;

	MIDIToCVInterface() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS), heldNotes(128) {
		onReset();
	}

	json_t *toJson() override {
		json_t *rootJ = json_object();
		json_object_set_new(rootJ, "midi", midiInput.toJson());
		return rootJ;
	}

	void fromJson(json_t *rootJ) override {
		json_t *midiJ = json_object_get(rootJ, "midi");
		if (midiJ)
			midiInput.fromJson(midiJ);
	}

	void onReset() override {
		heldNotes.clear();
		lastNote = 60;
		pedal = false;
		gate = false;
	}

	void pressNote(uint8_t note) {
		// Remove existing similar note
		auto it = std::find(heldNotes.begin(), heldNotes.end(), note);
		if (it != heldNotes.end())
			heldNotes.erase(it);
		// Push note
		heldNotes.push_back(note);
		lastNote = note;
		gate = true;
		retriggerPulse.trigger(1e-3);
	}

	void releaseNote(uint8_t note) {
		// Remove the note
		auto it = std::find(heldNotes.begin(), heldNotes.end(), note);
		if (it != heldNotes.end())
			heldNotes.erase(it);
		// Hold note if pedal is pressed
		if (pedal)
			return;
		// Set last note
		if (!heldNotes.empty()) {
			lastNote = heldNotes[heldNotes.size() - 1];
			gate = true;
		}
		else {
			gate = false;
		}
	}

	void pressPedal() {
		pedal = true;
	}

	void releasePedal() {
		pedal = false;
		releaseNote(255);
	}

	void step() override {
		MidiMessage msg;
		while (midiInput.shift(&msg)) {
			processMessage(msg);
		}
		float deltaTime = engineGetSampleTime();

		outputs[CV_OUTPUT].value = (lastNote - 60) / 12.f;
		outputs[GATE_OUTPUT].value = gate ? 10.f : 0.f;
		outputs[VELOCITY_OUTPUT].value = rescale(noteData[lastNote].velocity, 0, 127, 0.f, 10.f);

		outputs[AFTERTOUCH_OUTPUT].value = rescale(noteData[lastNote].aftertouch, 0, 127, 0.f, 10.f);
		pitchFilter.lambda = 100.f * deltaTime;
		outputs[PITCH_OUTPUT].value = pitchFilter.process(rescale(pitch, 0, 16384, -5.f, 5.f));
		modFilter.lambda = 100.f * deltaTime;
		outputs[MOD_OUTPUT].value = modFilter.process(rescale(mod, 0, 127, 0.f, 10.f));

		outputs[RETRIGGER_OUTPUT].value = retriggerPulse.process(deltaTime) ? 10.f : 0.f;
		outputs[CLOCK_1_OUTPUT].value = clock1Pulse.process(deltaTime) ? 10.f : 0.f;
		outputs[CLOCK_2_OUTPUT].value = clock2Pulse.process(deltaTime) ? 10.f : 0.f;

		outputs[START_OUTPUT].value = startPulse.process(deltaTime) ? 10.f : 0.f;
		outputs[STOP_OUTPUT].value = stopPulse.process(deltaTime) ? 10.f : 0.f;
		outputs[CONTINUE_OUTPUT].value = continuePulse.process(deltaTime) ? 10.f : 0.f;
	}

	void processMessage(MidiMessage msg) {
		// debug("MIDI: %01x %01x %02x %02x", msg.status(), msg.channel(), msg.note(), msg.value());

		switch (msg.status()) {
			// note off
			case 0x8: {
				releaseNote(msg.note());
			} break;
			// note on
			case 0x9: {
				if (msg.value() > 0) {
					noteData[msg.note()].velocity = msg.value();
					pressNote(msg.note());
				}
				else {
					// For some reason, some keyboards send a "note on" event with a velocity of 0 to signal that the key has been released.
					releaseNote(msg.note());
				}
			} break;
			// channel aftertouch
			case 0xa: {
				uint8_t note = msg.note();
				noteData[note].aftertouch = msg.value();
			} break;
			// cc
			case 0xb: {
				processCC(msg);
			} break;
			// pitch wheel
			case 0xe: {
				pitch = msg.value() * 128 + msg.note();
			} break;
			case 0xf: {
				processSystem(msg);
			} break;
			default: break;
		}
	}

	void processCC(MidiMessage msg) {
		switch (msg.note()) {
			// mod
			case 0x01: {
				mod = msg.value();
			} break;
			// sustain
			case 0x40: {
				if (msg.value() >= 64)
					pressPedal();
				else
					releasePedal();
			} break;
			default: break;
		}
	}

	void processSystem(MidiMessage msg) {
		switch (msg.channel()) {
			// Timing
			case 0x8: {
				// TODO
			} break;
			// Start
			case 0xa: {
				startPulse.trigger(1e-3);
			} break;
			// Continue
			case 0xb: {
				continuePulse.trigger(1e-3);
			} break;
			// Stop
			case 0xc: {
				stopPulse.trigger(1e-3);
			} break;
			default: break;
		}
	}
};

struct MIDIToCVInterfaceWidget : ModuleWidget {
	MIDIToCVInterfaceWidget(MIDIToCVInterface *module) : ModuleWidget(module) {
		setPanel(SVG::load(assetGlobal("res/Core/MIDIToCVInterface.svg")));

		addChild(Widget::create<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0)));
		addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0)));
		addChild(Widget::create<ScrewSilver>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
		addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));

		addOutput(Port::create<PJ301MPort>(mm2px(Vec(4.61505, 60.1445)), Port::OUTPUT, module, MIDIToCVInterface::CV_OUTPUT));
		addOutput(Port::create<PJ301MPort>(mm2px(Vec(16.214, 60.1445)), Port::OUTPUT, module, MIDIToCVInterface::GATE_OUTPUT));
		addOutput(Port::create<PJ301MPort>(mm2px(Vec(27.8143, 60.1445)), Port::OUTPUT, module, MIDIToCVInterface::VELOCITY_OUTPUT));
		addOutput(Port::create<PJ301MPort>(mm2px(Vec(4.61505, 76.1449)), Port::OUTPUT, module, MIDIToCVInterface::AFTERTOUCH_OUTPUT));
		addOutput(Port::create<PJ301MPort>(mm2px(Vec(16.214, 76.1449)), Port::OUTPUT, module, MIDIToCVInterface::PITCH_OUTPUT));
		addOutput(Port::create<PJ301MPort>(mm2px(Vec(27.8143, 76.1449)), Port::OUTPUT, module, MIDIToCVInterface::MOD_OUTPUT));
		addOutput(Port::create<PJ301MPort>(mm2px(Vec(4.61505, 92.1439)), Port::OUTPUT, module, MIDIToCVInterface::RETRIGGER_OUTPUT));
		addOutput(Port::create<PJ301MPort>(mm2px(Vec(16.214, 92.1439)), Port::OUTPUT, module, MIDIToCVInterface::CLOCK_1_OUTPUT));
		addOutput(Port::create<PJ301MPort>(mm2px(Vec(27.8143, 92.1439)), Port::OUTPUT, module, MIDIToCVInterface::CLOCK_2_OUTPUT));
		addOutput(Port::create<PJ301MPort>(mm2px(Vec(4.61505, 108.144)), Port::OUTPUT, module, MIDIToCVInterface::START_OUTPUT));
		addOutput(Port::create<PJ301MPort>(mm2px(Vec(16.214, 108.144)), Port::OUTPUT, module, MIDIToCVInterface::STOP_OUTPUT));
		addOutput(Port::create<PJ301MPort>(mm2px(Vec(27.8143, 108.144)), Port::OUTPUT, module, MIDIToCVInterface::CONTINUE_OUTPUT));

		MidiWidget *midiWidget = Widget::create<MidiWidget>(mm2px(Vec(3.41891, 14.8373)));
		midiWidget->box.size = mm2px(Vec(33.840, 28));
		midiWidget->midiIO = &module->midiInput;
		addChild(midiWidget);
	}
};

Model *modelMIDIToCVInterface = Model::create<MIDIToCVInterface, MIDIToCVInterfaceWidget>("Core", "MIDIToCVInterface", "MIDI-1", MIDI_TAG, EXTERNAL_TAG);
<commit_msg>MIDI-1: Add retrigger when key is lifted<commit_after>#include "Core.hpp"
#include "midi.hpp"
#include "dsp/digital.hpp"
#include "dsp/filter.hpp"

#include <algorithm>

struct MIDIToCVInterface : Module {
	enum ParamIds {
		NUM_PARAMS
	};
	enum InputIds {
		NUM_INPUTS
	};
	enum OutputIds {
		CV_OUTPUT,
		GATE_OUTPUT,
		VELOCITY_OUTPUT,
		AFTERTOUCH_OUTPUT,
		PITCH_OUTPUT,
		MOD_OUTPUT,
		RETRIGGER_OUTPUT,
		CLOCK_1_OUTPUT,
		CLOCK_2_OUTPUT,
		START_OUTPUT,
		STOP_OUTPUT,
		CONTINUE_OUTPUT,
		NUM_OUTPUTS
	};
	enum LightIds {
		NUM_LIGHTS
	};

	MidiInputQueue midiInput;

	uint8_t mod = 0;
	ExponentialFilter modFilter;
	uint16_t pitch = 0;
	ExponentialFilter pitchFilter;
	PulseGenerator retriggerPulse;
	PulseGenerator clock1Pulse;
	PulseGenerator clock2Pulse;
	PulseGenerator startPulse;
	PulseGenerator stopPulse;
	PulseGenerator continuePulse;

	struct NoteData {
		uint8_t velocity = 0;
		uint8_t aftertouch = 0;
	};

	NoteData noteData[128];
	std::vector<uint8_t> heldNotes;
	uint8_t lastNote;
	bool pedal;
	bool gate;

	MIDIToCVInterface() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS), heldNotes(128) {
		onReset();
	}

	json_t *toJson() override {
		json_t *rootJ = json_object();
		json_object_set_new(rootJ, "midi", midiInput.toJson());
		return rootJ;
	}

	void fromJson(json_t *rootJ) override {
		json_t *midiJ = json_object_get(rootJ, "midi");
		if (midiJ)
			midiInput.fromJson(midiJ);
	}

	void onReset() override {
		heldNotes.clear();
		lastNote = 60;
		pedal = false;
		gate = false;
	}

	void pressNote(uint8_t note) {
		// Remove existing similar note
		auto it = std::find(heldNotes.begin(), heldNotes.end(), note);
		if (it != heldNotes.end())
			heldNotes.erase(it);
		// Push note
		heldNotes.push_back(note);
		lastNote = note;
		gate = true;
		retriggerPulse.trigger(1e-3);
	}

	void releaseNote(uint8_t note) {
		// Remove the note
		auto it = std::find(heldNotes.begin(), heldNotes.end(), note);
		if (it != heldNotes.end())
			heldNotes.erase(it);
		// Hold note if pedal is pressed
		if (pedal)
			return;
		// Set last note
		if (!heldNotes.empty()) {
			lastNote = heldNotes[heldNotes.size() - 1];
			gate = true;
			retriggerPulse.trigger(1e-3);
		}
		else {
			gate = false;
		}
	}

	void pressPedal() {
		pedal = true;
	}

	void releasePedal() {
		pedal = false;
		releaseNote(255);
	}

	void step() override {
		MidiMessage msg;
		while (midiInput.shift(&msg)) {
			processMessage(msg);
		}
		float deltaTime = engineGetSampleTime();

		outputs[CV_OUTPUT].value = (lastNote - 60) / 12.f;
		outputs[GATE_OUTPUT].value = gate ? 10.f : 0.f;
		outputs[VELOCITY_OUTPUT].value = rescale(noteData[lastNote].velocity, 0, 127, 0.f, 10.f);

		outputs[AFTERTOUCH_OUTPUT].value = rescale(noteData[lastNote].aftertouch, 0, 127, 0.f, 10.f);
		pitchFilter.lambda = 100.f * deltaTime;
		outputs[PITCH_OUTPUT].value = pitchFilter.process(rescale(pitch, 0, 16384, -5.f, 5.f));
		modFilter.lambda = 100.f * deltaTime;
		outputs[MOD_OUTPUT].value = modFilter.process(rescale(mod, 0, 127, 0.f, 10.f));

		outputs[RETRIGGER_OUTPUT].value = retriggerPulse.process(deltaTime) ? 10.f : 0.f;
		outputs[CLOCK_1_OUTPUT].value = clock1Pulse.process(deltaTime) ? 10.f : 0.f;
		outputs[CLOCK_2_OUTPUT].value = clock2Pulse.process(deltaTime) ? 10.f : 0.f;

		outputs[START_OUTPUT].value = startPulse.process(deltaTime) ? 10.f : 0.f;
		outputs[STOP_OUTPUT].value = stopPulse.process(deltaTime) ? 10.f : 0.f;
		outputs[CONTINUE_OUTPUT].value = continuePulse.process(deltaTime) ? 10.f : 0.f;
	}

	void processMessage(MidiMessage msg) {
		// debug("MIDI: %01x %01x %02x %02x", msg.status(), msg.channel(), msg.note(), msg.value());

		switch (msg.status()) {
			// note off
			case 0x8: {
				releaseNote(msg.note());
			} break;
			// note on
			case 0x9: {
				if (msg.value() > 0) {
					noteData[msg.note()].velocity = msg.value();
					pressNote(msg.note());
				}
				else {
					// For some reason, some keyboards send a "note on" event with a velocity of 0 to signal that the key has been released.
					releaseNote(msg.note());
				}
			} break;
			// channel aftertouch
			case 0xa: {
				uint8_t note = msg.note();
				noteData[note].aftertouch = msg.value();
			} break;
			// cc
			case 0xb: {
				processCC(msg);
			} break;
			// pitch wheel
			case 0xe: {
				pitch = msg.value() * 128 + msg.note();
			} break;
			case 0xf: {
				processSystem(msg);
			} break;
			default: break;
		}
	}

	void processCC(MidiMessage msg) {
		switch (msg.note()) {
			// mod
			case 0x01: {
				mod = msg.value();
			} break;
			// sustain
			case 0x40: {
				if (msg.value() >= 64)
					pressPedal();
				else
					releasePedal();
			} break;
			default: break;
		}
	}

	void processSystem(MidiMessage msg) {
		switch (msg.channel()) {
			// Timing
			case 0x8: {
				// TODO
			} break;
			// Start
			case 0xa: {
				startPulse.trigger(1e-3);
			} break;
			// Continue
			case 0xb: {
				continuePulse.trigger(1e-3);
			} break;
			// Stop
			case 0xc: {
				stopPulse.trigger(1e-3);
			} break;
			default: break;
		}
	}
};

struct MIDIToCVInterfaceWidget : ModuleWidget {
	MIDIToCVInterfaceWidget(MIDIToCVInterface *module) : ModuleWidget(module) {
		setPanel(SVG::load(assetGlobal("res/Core/MIDIToCVInterface.svg")));

		addChild(Widget::create<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0)));
		addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0)));
		addChild(Widget::create<ScrewSilver>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
		addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));

		addOutput(Port::create<PJ301MPort>(mm2px(Vec(4.61505, 60.1445)), Port::OUTPUT, module, MIDIToCVInterface::CV_OUTPUT));
		addOutput(Port::create<PJ301MPort>(mm2px(Vec(16.214, 60.1445)), Port::OUTPUT, module, MIDIToCVInterface::GATE_OUTPUT));
		addOutput(Port::create<PJ301MPort>(mm2px(Vec(27.8143, 60.1445)), Port::OUTPUT, module, MIDIToCVInterface::VELOCITY_OUTPUT));
		addOutput(Port::create<PJ301MPort>(mm2px(Vec(4.61505, 76.1449)), Port::OUTPUT, module, MIDIToCVInterface::AFTERTOUCH_OUTPUT));
		addOutput(Port::create<PJ301MPort>(mm2px(Vec(16.214, 76.1449)), Port::OUTPUT, module, MIDIToCVInterface::PITCH_OUTPUT));
		addOutput(Port::create<PJ301MPort>(mm2px(Vec(27.8143, 76.1449)), Port::OUTPUT, module, MIDIToCVInterface::MOD_OUTPUT));
		addOutput(Port::create<PJ301MPort>(mm2px(Vec(4.61505, 92.1439)), Port::OUTPUT, module, MIDIToCVInterface::RETRIGGER_OUTPUT));
		addOutput(Port::create<PJ301MPort>(mm2px(Vec(16.214, 92.1439)), Port::OUTPUT, module, MIDIToCVInterface::CLOCK_1_OUTPUT));
		addOutput(Port::create<PJ301MPort>(mm2px(Vec(27.8143, 92.1439)), Port::OUTPUT, module, MIDIToCVInterface::CLOCK_2_OUTPUT));
		addOutput(Port::create<PJ301MPort>(mm2px(Vec(4.61505, 108.144)), Port::OUTPUT, module, MIDIToCVInterface::START_OUTPUT));
		addOutput(Port::create<PJ301MPort>(mm2px(Vec(16.214, 108.144)), Port::OUTPUT, module, MIDIToCVInterface::STOP_OUTPUT));
		addOutput(Port::create<PJ301MPort>(mm2px(Vec(27.8143, 108.144)), Port::OUTPUT, module, MIDIToCVInterface::CONTINUE_OUTPUT));

		MidiWidget *midiWidget = Widget::create<MidiWidget>(mm2px(Vec(3.41891, 14.8373)));
		midiWidget->box.size = mm2px(Vec(33.840, 28));
		midiWidget->midiIO = &module->midiInput;
		addChild(midiWidget);
	}
};

Model *modelMIDIToCVInterface = Model::create<MIDIToCVInterface, MIDIToCVInterfaceWidget>("Core", "MIDIToCVInterface", "MIDI-1", MIDI_TAG, EXTERNAL_TAG);
<|endoftext|>


<commit_before>/*
    Copyright (c) 2009 Stephen Kelly <steveire@gmail.com>

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

    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 Library General Public
    License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to the
    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
*/

#include "akonadibrowsermodel.h"

#include <kmime/kmime_message.h>

#include <kabc/addressee.h>
#include <kabc/contactgroup.h>

#include <kcal/incidence.h>
#include <kcal/event.h>

#include <boost/shared_ptr.hpp>

typedef boost::shared_ptr<KMime::Message> MessagePtr;
typedef boost::shared_ptr<KCal::Incidence> IncidencePtr;

class AkonadiBrowserModel::State
{
public:
  virtual ~State() {}
  QStringList m_collectionHeaders;
  QStringList m_itemHeaders;

  virtual QVariant getData( const Item &item, int column, int role ) const = 0;

};

class GenericState : public AkonadiBrowserModel::State
{
public:
  GenericState()
  {
    m_collectionHeaders << "Collection";
    m_itemHeaders << "Id" << "Remote Id" << "MimeType";
  }
  virtual ~GenericState() {}

  QVariant getData( const Item &item, int column, int role ) const
  {
    if (Qt::DisplayRole != role)
      return QVariant();

    switch (column)
    {
    case 0:
      return item.id();
    case 1:
      return item.remoteId();
    case 2:
      return item.mimeType();
    }
    return QVariant();
  }

};

class MailState : public AkonadiBrowserModel::State
{
public:
  MailState()
  {
    m_collectionHeaders << "Collection";
    m_itemHeaders << "Subject" << "Sender" << "Date";
  }
  virtual ~MailState() {}

  QVariant getData( const Item &item, int column, int role ) const
  {
    if (Qt::DisplayRole != role)
      return QVariant();

    if (!item.hasPayload<MessagePtr>())
    {
      return QVariant();
    }
    const MessagePtr mail = item.payload<MessagePtr>();

    switch (column)
    {
    case 0:
      return mail->subject()->asUnicodeString();
    case 1:
      return mail->from()->asUnicodeString();
    case 2:
      return mail->date()->asUnicodeString();
    }

    return QVariant();
  }

};

class ContactsState : public AkonadiBrowserModel::State
{
public:
  ContactsState()
  {
    m_collectionHeaders << "Collection";
    m_itemHeaders << "Given Name" << "Family Name" << "Email";
  }
  virtual ~ContactsState() {}

  QVariant getData( const Item &item, int column, int role ) const
  {
    if (Qt::DisplayRole != role)
      return QVariant();

    if ( !item.hasPayload<KABC::Addressee>() && !item.hasPayload<KABC::ContactGroup>() )
    {
      return QVariant();
    }

    if ( item.hasPayload<KABC::Addressee>() )
    {
      const KABC::Addressee addr = item.payload<KABC::Addressee>();

      switch (column)
      {
      case 0:
        return addr.givenName();
      case 1:
        return addr.familyName();
      case 2:
        return addr.preferredEmail();
      }
      return QVariant();
    }
    if ( item.hasPayload<KABC::ContactGroup>() ) {

      switch (column)
      {
      case 0:
        const KABC::ContactGroup group = item.payload<KABC::ContactGroup>();
        return group.name();
      }
      return QVariant();
    }
    return QVariant();
  }
};

class CalendarState : public AkonadiBrowserModel::State
{
public:
  CalendarState()
  {
    m_collectionHeaders << "Collection";
    m_itemHeaders << "Summary" << "DateTime start" << "DateTime End" << "Type";
  }
  virtual ~CalendarState() {}

  QVariant getData( const Item &item, int column, int role ) const
  {
    if (Qt::DisplayRole != role)
      return QVariant();

    if ( !item.hasPayload<IncidencePtr>() )
    {
      return QVariant();
    }
    const IncidencePtr incidence = item.payload<IncidencePtr>();
    switch (column)
    {
    case 0:
      return incidence->summary();
      break;
    case 1:
      return incidence->dtStart().toString();
      break;
    case 2:
      return incidence->dtEnd().toString();
      break;
    case 3:
      return incidence->type();
      break;
    default:
      break;
    }
    return QVariant();
  }
};

AkonadiBrowserModel::AkonadiBrowserModel( Session* session, ChangeRecorder* monitor, QObject* parent )
    : EntityTreeModel( session, monitor, parent ),
      m_itemDisplayMode( GenericMode )
{

  m_genericState = new GenericState();
  m_mailState = new MailState();
  m_contactsState = new ContactsState();
  m_calendarState = new CalendarState();

  m_currentState = m_genericState;
}

int AkonadiBrowserModel::columnCount(const QModelIndex& parent) const
{
  Q_UNUSED(parent);
  return qMax(m_currentState->m_collectionHeaders.size(), m_currentState->m_itemHeaders.size());
}

QVariant AkonadiBrowserModel::entityData( const Item &item, int column, int role ) const
{
  QVariant var = m_currentState->getData( item, column, role );
  if ( !var.isValid() )
  {
    if ( column < 1 )
      return EntityTreeModel::entityData( item, column, role );
    return QString();
  }

  return var;
}

QVariant AkonadiBrowserModel::entityData(const Akonadi::Collection& collection, int column, int role) const
{
  return Akonadi::EntityTreeModel::entityData( collection, column, role );
}

int AkonadiBrowserModel::entityColumnCount( HeaderGroup headerGroup ) const
{
  if ( ItemListHeaders == headerGroup )
  {
    return m_currentState->m_itemHeaders.size();
  }

  if ( CollectionTreeHeaders == headerGroup )
  {
    return m_currentState->m_collectionHeaders.size();
  }
  // Practically, this should never happen.
  return EntityTreeModel::entityColumnCount( headerGroup );
}

QVariant AkonadiBrowserModel::entityHeaderData( int section, Qt::Orientation orientation, int role, HeaderGroup headerGroup ) const
{
  if ( section < 0 )
    return QVariant();

  if ( orientation == Qt::Vertical )
     return EntityTreeModel::entityHeaderData( section, orientation, role, headerGroup );

  if ( headerGroup == EntityTreeModel::CollectionTreeHeaders )
  {
    if ( role == Qt::DisplayRole )
    {
      if ( section >= m_currentState->m_collectionHeaders.size() )
        return QVariant();
      return m_currentState->m_collectionHeaders.at( section );
    }
  } else if ( headerGroup == EntityTreeModel::ItemListHeaders )
  {
    if ( role == Qt::DisplayRole )
    {
      if ( section >= m_currentState->m_itemHeaders.size() )
        return QVariant();
      return m_currentState->m_itemHeaders.at( section );
    }
  }
  return EntityTreeModel::entityHeaderData( section, orientation, role, headerGroup );
}

AkonadiBrowserModel::ItemDisplayMode AkonadiBrowserModel::itemDisplayMode() const
{
  return m_itemDisplayMode;
}

void AkonadiBrowserModel::setItemDisplayMode( AkonadiBrowserModel::ItemDisplayMode itemDisplayMode )
{
  beginResetModel();
  m_itemDisplayMode = itemDisplayMode;
  switch (itemDisplayMode)
  {
  case MailMode:
    m_currentState = m_mailState;
    break;
  case ContactsMode:
    m_currentState = m_contactsState;
    break;
  case CalendarMode:
    m_currentState = m_calendarState;
    break;
  case GenericMode:
  default:
    m_currentState = m_genericState;
    break;
  }
  endResetModel();
}

void AkonadiBrowserModel::invalidatePersistentIndexes()
{
  QModelIndexList oldList = this->persistentIndexList();
  QModelIndexList newList;
  for (int i=0; i < oldList.size(); i++)
    newList << QModelIndex();
  this->changePersistentIndexList(oldList, newList);
}

void AkonadiBrowserModel::beginResetModel()
{
  QMetaObject::invokeMethod(this, "modelAboutToBeReset", Qt::DirectConnection);
}

void AkonadiBrowserModel::endResetModel()
{
  invalidatePersistentIndexes();
  QMetaObject::invokeMethod(this, "modelReset", Qt::DirectConnection);
}

<commit_msg>Rename internal virtual to make grep happier.<commit_after>/*
    Copyright (c) 2009 Stephen Kelly <steveire@gmail.com>

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

    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 Library General Public
    License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to the
    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
*/

#include "akonadibrowsermodel.h"

#include <kmime/kmime_message.h>

#include <kabc/addressee.h>
#include <kabc/contactgroup.h>

#include <kcal/incidence.h>
#include <kcal/event.h>

#include <boost/shared_ptr.hpp>

typedef boost::shared_ptr<KMime::Message> MessagePtr;
typedef boost::shared_ptr<KCal::Incidence> IncidencePtr;

class AkonadiBrowserModel::State
{
public:
  virtual ~State() {}
  QStringList m_collectionHeaders;
  QStringList m_itemHeaders;

  virtual QVariant entityData( const Item &item, int column, int role ) const = 0;

};

class GenericState : public AkonadiBrowserModel::State
{
public:
  GenericState()
  {
    m_collectionHeaders << "Collection";
    m_itemHeaders << "Id" << "Remote Id" << "MimeType";
  }
  virtual ~GenericState() {}

  QVariant entityData( const Item &item, int column, int role ) const
  {
    if (Qt::DisplayRole != role)
      return QVariant();

    switch (column)
    {
    case 0:
      return item.id();
    case 1:
      return item.remoteId();
    case 2:
      return item.mimeType();
    }
    return QVariant();
  }

};

class MailState : public AkonadiBrowserModel::State
{
public:
  MailState()
  {
    m_collectionHeaders << "Collection";
    m_itemHeaders << "Subject" << "Sender" << "Date";
  }
  virtual ~MailState() {}

  QVariant entityData( const Item &item, int column, int role ) const
  {
    if (Qt::DisplayRole != role)
      return QVariant();

    if (!item.hasPayload<MessagePtr>())
    {
      return QVariant();
    }
    const MessagePtr mail = item.payload<MessagePtr>();

    switch (column)
    {
    case 0:
      return mail->subject()->asUnicodeString();
    case 1:
      return mail->from()->asUnicodeString();
    case 2:
      return mail->date()->asUnicodeString();
    }

    return QVariant();
  }

};

class ContactsState : public AkonadiBrowserModel::State
{
public:
  ContactsState()
  {
    m_collectionHeaders << "Collection";
    m_itemHeaders << "Given Name" << "Family Name" << "Email";
  }
  virtual ~ContactsState() {}

  QVariant entityData( const Item &item, int column, int role ) const
  {
    if (Qt::DisplayRole != role)
      return QVariant();

    if ( !item.hasPayload<KABC::Addressee>() && !item.hasPayload<KABC::ContactGroup>() )
    {
      return QVariant();
    }

    if ( item.hasPayload<KABC::Addressee>() )
    {
      const KABC::Addressee addr = item.payload<KABC::Addressee>();

      switch (column)
      {
      case 0:
        return addr.givenName();
      case 1:
        return addr.familyName();
      case 2:
        return addr.preferredEmail();
      }
      return QVariant();
    }
    if ( item.hasPayload<KABC::ContactGroup>() ) {

      switch (column)
      {
      case 0:
        const KABC::ContactGroup group = item.payload<KABC::ContactGroup>();
        return group.name();
      }
      return QVariant();
    }
    return QVariant();
  }
};

class CalendarState : public AkonadiBrowserModel::State
{
public:
  CalendarState()
  {
    m_collectionHeaders << "Collection";
    m_itemHeaders << "Summary" << "DateTime start" << "DateTime End" << "Type";
  }
  virtual ~CalendarState() {}

  QVariant entityData( const Item &item, int column, int role ) const
  {
    if (Qt::DisplayRole != role)
      return QVariant();

    if ( !item.hasPayload<IncidencePtr>() )
    {
      return QVariant();
    }
    const IncidencePtr incidence = item.payload<IncidencePtr>();
    switch (column)
    {
    case 0:
      return incidence->summary();
      break;
    case 1:
      return incidence->dtStart().toString();
      break;
    case 2:
      return incidence->dtEnd().toString();
      break;
    case 3:
      return incidence->type();
      break;
    default:
      break;
    }
    return QVariant();
  }
};

AkonadiBrowserModel::AkonadiBrowserModel( Session* session, ChangeRecorder* monitor, QObject* parent )
    : EntityTreeModel( session, monitor, parent ),
      m_itemDisplayMode( GenericMode )
{

  m_genericState = new GenericState();
  m_mailState = new MailState();
  m_contactsState = new ContactsState();
  m_calendarState = new CalendarState();

  m_currentState = m_genericState;
}

int AkonadiBrowserModel::columnCount(const QModelIndex& parent) const
{
  Q_UNUSED(parent);
  return qMax(m_currentState->m_collectionHeaders.size(), m_currentState->m_itemHeaders.size());
}

QVariant AkonadiBrowserModel::entityData( const Item &item, int column, int role ) const
{
  QVariant var = m_currentState->entityData( item, column, role );
  if ( !var.isValid() )
  {
    if ( column < 1 )
      return EntityTreeModel::entityData( item, column, role );
    return QString();
  }

  return var;
}

QVariant AkonadiBrowserModel::entityData(const Akonadi::Collection& collection, int column, int role) const
{
  return Akonadi::EntityTreeModel::entityData( collection, column, role );
}

int AkonadiBrowserModel::entityColumnCount( HeaderGroup headerGroup ) const
{
  if ( ItemListHeaders == headerGroup )
  {
    return m_currentState->m_itemHeaders.size();
  }

  if ( CollectionTreeHeaders == headerGroup )
  {
    return m_currentState->m_collectionHeaders.size();
  }
  // Practically, this should never happen.
  return EntityTreeModel::entityColumnCount( headerGroup );
}

QVariant AkonadiBrowserModel::entityHeaderData( int section, Qt::Orientation orientation, int role, HeaderGroup headerGroup ) const
{
  if ( section < 0 )
    return QVariant();

  if ( orientation == Qt::Vertical )
     return EntityTreeModel::entityHeaderData( section, orientation, role, headerGroup );

  if ( headerGroup == EntityTreeModel::CollectionTreeHeaders )
  {
    if ( role == Qt::DisplayRole )
    {
      if ( section >= m_currentState->m_collectionHeaders.size() )
        return QVariant();
      return m_currentState->m_collectionHeaders.at( section );
    }
  } else if ( headerGroup == EntityTreeModel::ItemListHeaders )
  {
    if ( role == Qt::DisplayRole )
    {
      if ( section >= m_currentState->m_itemHeaders.size() )
        return QVariant();
      return m_currentState->m_itemHeaders.at( section );
    }
  }
  return EntityTreeModel::entityHeaderData( section, orientation, role, headerGroup );
}

AkonadiBrowserModel::ItemDisplayMode AkonadiBrowserModel::itemDisplayMode() const
{
  return m_itemDisplayMode;
}

void AkonadiBrowserModel::setItemDisplayMode( AkonadiBrowserModel::ItemDisplayMode itemDisplayMode )
{
  beginResetModel();
  m_itemDisplayMode = itemDisplayMode;
  switch (itemDisplayMode)
  {
  case MailMode:
    m_currentState = m_mailState;
    break;
  case ContactsMode:
    m_currentState = m_contactsState;
    break;
  case CalendarMode:
    m_currentState = m_calendarState;
    break;
  case GenericMode:
  default:
    m_currentState = m_genericState;
    break;
  }
  endResetModel();
}

void AkonadiBrowserModel::invalidatePersistentIndexes()
{
  QModelIndexList oldList = this->persistentIndexList();
  QModelIndexList newList;
  for (int i=0; i < oldList.size(); i++)
    newList << QModelIndex();
  this->changePersistentIndexList(oldList, newList);
}

void AkonadiBrowserModel::beginResetModel()
{
  QMetaObject::invokeMethod(this, "modelAboutToBeReset", Qt::DirectConnection);
}

void AkonadiBrowserModel::endResetModel()
{
  invalidatePersistentIndexes();
  QMetaObject::invokeMethod(this, "modelReset", Qt::DirectConnection);
}

<|endoftext|>


<commit_before>// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "platform/assert.h"
#include "platform/utils.h"
#include "vm/unit_test.h"

namespace dart {

UNIT_TEST_CASE(Minimum) {
  EXPECT_EQ(0, Utils::Minimum(0, 1));
  EXPECT_EQ(0, Utils::Minimum(1, 0));

  EXPECT_EQ(1, Utils::Minimum(1, 2));
  EXPECT_EQ(1, Utils::Minimum(2, 1));

  EXPECT_EQ(-1, Utils::Minimum(-1, 1));
  EXPECT_EQ(-1, Utils::Minimum(1, -1));

  EXPECT_EQ(-2, Utils::Minimum(-1, -2));
  EXPECT_EQ(-2, Utils::Minimum(-2, -1));
}

UNIT_TEST_CASE(Maximum) {
  EXPECT_EQ(1, Utils::Maximum(0, 1));
  EXPECT_EQ(1, Utils::Maximum(1, 0));

  EXPECT_EQ(2, Utils::Maximum(1, 2));
  EXPECT_EQ(2, Utils::Maximum(2, 1));

  EXPECT_EQ(1, Utils::Maximum(-1, 1));
  EXPECT_EQ(1, Utils::Maximum(1, -1));

  EXPECT_EQ(-1, Utils::Maximum(-1, -2));
  EXPECT_EQ(-1, Utils::Maximum(-2, -1));
}

UNIT_TEST_CASE(IsPowerOfTwo) {
  EXPECT(!Utils::IsPowerOfTwo(0));
  EXPECT(Utils::IsPowerOfTwo(1));
  EXPECT(Utils::IsPowerOfTwo(2));
  EXPECT(!Utils::IsPowerOfTwo(3));
  EXPECT(Utils::IsPowerOfTwo(4));
  EXPECT(Utils::IsPowerOfTwo(256));

  EXPECT(!Utils::IsPowerOfTwo(-1));
  EXPECT(!Utils::IsPowerOfTwo(-2));
}

UNIT_TEST_CASE(ShiftForPowerOfTwo) {
  EXPECT_EQ(1, Utils::ShiftForPowerOfTwo(2));
  EXPECT_EQ(2, Utils::ShiftForPowerOfTwo(4));
  EXPECT_EQ(8, Utils::ShiftForPowerOfTwo(256));
}

UNIT_TEST_CASE(IsAligned) {
  EXPECT(Utils::IsAligned(0, 1));
  EXPECT(Utils::IsAligned(1, 1));

  EXPECT(Utils::IsAligned(0, 2));
  EXPECT(!Utils::IsAligned(1, 2));
  EXPECT(Utils::IsAligned(2, 2));

  EXPECT(Utils::IsAligned(32, 8));
  EXPECT(!Utils::IsAligned(33, 8));
  EXPECT(Utils::IsAligned(40, 8));
}

UNIT_TEST_CASE(RoundDown) {
  EXPECT_EQ(0, Utils::RoundDown(22, 32));
  EXPECT_EQ(32, Utils::RoundDown(33, 32));
  EXPECT_EQ(32, Utils::RoundDown(63, 32));
  uword* address = reinterpret_cast<uword*>(63);
  uword* rounddown_address = reinterpret_cast<uword*>(32);
  EXPECT_EQ(rounddown_address, Utils::RoundDown(address, 32));
}

UNIT_TEST_CASE(RoundUp) {
  EXPECT_EQ(32, Utils::RoundUp(22, 32));
  EXPECT_EQ(64, Utils::RoundUp(33, 32));
  EXPECT_EQ(64, Utils::RoundUp(63, 32));
  uword* address = reinterpret_cast<uword*>(63);
  uword* roundup_address = reinterpret_cast<uword*>(64);
  EXPECT_EQ(roundup_address, Utils::RoundUp(address, 32));
}

UNIT_TEST_CASE(RoundUpToPowerOfTwo) {
  EXPECT_EQ(0U, Utils::RoundUpToPowerOfTwo(0));
  EXPECT_EQ(1U, Utils::RoundUpToPowerOfTwo(1));
  EXPECT_EQ(2U, Utils::RoundUpToPowerOfTwo(2));
  EXPECT_EQ(4U, Utils::RoundUpToPowerOfTwo(3));
  EXPECT_EQ(4U, Utils::RoundUpToPowerOfTwo(4));
  EXPECT_EQ(8U, Utils::RoundUpToPowerOfTwo(5));
  EXPECT_EQ(8U, Utils::RoundUpToPowerOfTwo(7));
  EXPECT_EQ(16U, Utils::RoundUpToPowerOfTwo(9));
  EXPECT_EQ(16U, Utils::RoundUpToPowerOfTwo(16));
  EXPECT_EQ(0x10000000U, Utils::RoundUpToPowerOfTwo(0x08765432));
}

UNIT_TEST_CASE(CountOneBits) {
  EXPECT_EQ(0, Utils::CountOneBits(0));
  EXPECT_EQ(1, Utils::CountOneBits(0x00000010));
  EXPECT_EQ(1, Utils::CountOneBits(0x00010000));
  EXPECT_EQ(1, Utils::CountOneBits(0x10000000));
  EXPECT_EQ(4, Utils::CountOneBits(0x10101010));
  EXPECT_EQ(8, Utils::CountOneBits(0x03030303));
  EXPECT_EQ(32, Utils::CountOneBits(0xFFFFFFFF));
}

UNIT_TEST_CASE(CountZeros) {
  EXPECT_EQ(0, Utils::CountTrailingZeros(0x1));
  EXPECT_EQ(kBitsPerWord - 1, Utils::CountLeadingZeros(0x1));
  EXPECT_EQ(1, Utils::CountTrailingZeros(0x2));
  EXPECT_EQ(kBitsPerWord - 2, Utils::CountLeadingZeros(0x2));
  EXPECT_EQ(0, Utils::CountTrailingZeros(0x3));
  EXPECT_EQ(kBitsPerWord - 2, Utils::CountLeadingZeros(0x3));
  EXPECT_EQ(2, Utils::CountTrailingZeros(0x4));
  EXPECT_EQ(kBitsPerWord - 2, Utils::CountLeadingZeros(0x4));
  EXPECT_EQ(0, Utils::CountTrailingZeros(kUwordMax));
  EXPECT_EQ(0, Utils::CountLeadingZeros(kUwordMax));
  static const uword kTopBit = static_cast<uword>(1) << (kBitsPerWord - 1);
  EXPECT_EQ(kBitsPerWord - 1, Utils::CountTrailingZeros(kTopBit));
  EXPECT_EQ(0, Utils::CountLeadingZeros(kTopBit));
}

UNIT_TEST_CASE(IsInt) {
  EXPECT(Utils::IsInt(8, 16));
  EXPECT(Utils::IsInt(8, 127));
  EXPECT(Utils::IsInt(8, -128));
  EXPECT(!Utils::IsInt(8, 255));
  EXPECT(Utils::IsInt(16, 16));
  EXPECT(!Utils::IsInt(16, 65535));
  EXPECT(Utils::IsInt(16, 32767));
  EXPECT(Utils::IsInt(16, -32768));
  EXPECT(Utils::IsInt(32, 16LL));
  EXPECT(Utils::IsInt(32, 2147483647LL));
  EXPECT(Utils::IsInt(32, -2147483648LL));
  EXPECT(!Utils::IsInt(32, 4294967295LL));
}

UNIT_TEST_CASE(IsUint) {
  EXPECT(Utils::IsUint(8, 16));
  EXPECT(Utils::IsUint(8, 0));
  EXPECT(Utils::IsUint(8, 255));
  EXPECT(!Utils::IsUint(8, 256));
  EXPECT(Utils::IsUint(16, 16));
  EXPECT(Utils::IsUint(16, 0));
  EXPECT(Utils::IsUint(16, 65535));
  EXPECT(!Utils::IsUint(16, 65536));
  EXPECT(Utils::IsUint(32, 16LL));
  EXPECT(Utils::IsUint(32, 0LL));
  EXPECT(Utils::IsUint(32, 4294967295LL));
  EXPECT(!Utils::IsUint(32, 4294967296LL));
}

UNIT_TEST_CASE(IsAbsoluteUint) {
  EXPECT(Utils::IsAbsoluteUint(8, 16));
  EXPECT(Utils::IsAbsoluteUint(8, 0));
  EXPECT(Utils::IsAbsoluteUint(8, -128));
  EXPECT(Utils::IsAbsoluteUint(8, 255));
  EXPECT(!Utils::IsAbsoluteUint(8, 256));
  EXPECT(Utils::IsAbsoluteUint(16, 16));
  EXPECT(Utils::IsAbsoluteUint(16, 0));
  EXPECT(Utils::IsAbsoluteUint(16, 65535));
  EXPECT(Utils::IsAbsoluteUint(16, -32768));
  EXPECT(!Utils::IsAbsoluteUint(16, 65536));
  EXPECT(Utils::IsAbsoluteUint(32, 16LL));
  EXPECT(Utils::IsAbsoluteUint(32, 0LL));
  EXPECT(Utils::IsAbsoluteUint(32, -2147483648LL));
  EXPECT(Utils::IsAbsoluteUint(32, 4294967295LL));
  EXPECT(!Utils::IsAbsoluteUint(32, 4294967296LL));
}

UNIT_TEST_CASE(LowBits) {
  EXPECT_EQ(0xff00, Utils::Low16Bits(0xffff00));
  EXPECT_EQ(0xff, Utils::High16Bits(0xffff00));
  EXPECT_EQ(0xff00, Utils::Low32Bits(0xff0000ff00LL));
  EXPECT_EQ(0xff, Utils::High32Bits(0xff0000ff00LL));
  EXPECT_EQ(0x00ff0000ff00LL, Utils::LowHighTo64Bits(0xff00, 0x00ff));
}

UNIT_TEST_CASE(Endianity) {
  uint16_t value16be = Utils::HostToBigEndian16(0xf1);
  EXPECT_EQ(0x0, reinterpret_cast<uint8_t*>(&value16be)[0]);
  EXPECT_EQ(0xf1, reinterpret_cast<uint8_t*>(&value16be)[1]);

  uint16_t value16le = Utils::HostToLittleEndian16(0xf1);
  EXPECT_EQ(0xf1, reinterpret_cast<uint8_t*>(&value16le)[0]);
  EXPECT_EQ(0x0, reinterpret_cast<uint8_t*>(&value16le)[1]);

  uint32_t value32be = Utils::HostToBigEndian32(0xf1f2);
  EXPECT_EQ(0x0, reinterpret_cast<uint8_t*>(&value32be)[0]);
  EXPECT_EQ(0x0, reinterpret_cast<uint8_t*>(&value32be)[1]);
  EXPECT_EQ(0xf1, reinterpret_cast<uint8_t*>(&value32be)[2]);
  EXPECT_EQ(0xf2, reinterpret_cast<uint8_t*>(&value32be)[3]);

  uint32_t value32le = Utils::HostToLittleEndian32(0xf1f2);
  EXPECT_EQ(0xf2, reinterpret_cast<uint8_t*>(&value32le)[0]);
  EXPECT_EQ(0xf1, reinterpret_cast<uint8_t*>(&value32le)[1]);
  EXPECT_EQ(0x0, reinterpret_cast<uint8_t*>(&value32le)[2]);
  EXPECT_EQ(0x0, reinterpret_cast<uint8_t*>(&value32le)[3]);

  uint64_t value64be = Utils::HostToBigEndian64(0xf1f2f3f4);
  EXPECT_EQ(0x0, reinterpret_cast<uint8_t*>(&value64be)[0]);
  EXPECT_EQ(0x0, reinterpret_cast<uint8_t*>(&value64be)[1]);
  EXPECT_EQ(0x0, reinterpret_cast<uint8_t*>(&value64be)[2]);
  EXPECT_EQ(0x0, reinterpret_cast<uint8_t*>(&value64be)[3]);
  EXPECT_EQ(0xf1, reinterpret_cast<uint8_t*>(&value64be)[4]);
  EXPECT_EQ(0xf2, reinterpret_cast<uint8_t*>(&value64be)[5]);
  EXPECT_EQ(0xf3, reinterpret_cast<uint8_t*>(&value64be)[6]);
  EXPECT_EQ(0xf4, reinterpret_cast<uint8_t*>(&value64be)[7]);

  uint64_t value64le = Utils::HostToLittleEndian64(0xf1f2f3f4);
  EXPECT_EQ(0xf4, reinterpret_cast<uint8_t*>(&value64le)[0]);
  EXPECT_EQ(0xf3, reinterpret_cast<uint8_t*>(&value64le)[1]);
  EXPECT_EQ(0xf2, reinterpret_cast<uint8_t*>(&value64le)[2]);
  EXPECT_EQ(0xf1, reinterpret_cast<uint8_t*>(&value64le)[3]);
  EXPECT_EQ(0x0, reinterpret_cast<uint8_t*>(&value64le)[4]);
  EXPECT_EQ(0x0, reinterpret_cast<uint8_t*>(&value64le)[5]);
  EXPECT_EQ(0x0, reinterpret_cast<uint8_t*>(&value64le)[6]);
  EXPECT_EQ(0x0, reinterpret_cast<uint8_t*>(&value64le)[7]);
}

UNIT_TEST_CASE(DoublesBitEqual) {
  EXPECT(Utils::DoublesBitEqual(1.0, 1.0));
  EXPECT(!Utils::DoublesBitEqual(1.0, -1.0));
  EXPECT(Utils::DoublesBitEqual(0.0, 0.0));
  EXPECT(!Utils::DoublesBitEqual(0.0, -0.0));
  EXPECT(Utils::DoublesBitEqual(NAN, NAN));
}

}  // namespace dart
<commit_msg>Fix typo in unit test.<commit_after>// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "platform/assert.h"
#include "platform/utils.h"
#include "vm/unit_test.h"

namespace dart {

UNIT_TEST_CASE(Minimum) {
  EXPECT_EQ(0, Utils::Minimum(0, 1));
  EXPECT_EQ(0, Utils::Minimum(1, 0));

  EXPECT_EQ(1, Utils::Minimum(1, 2));
  EXPECT_EQ(1, Utils::Minimum(2, 1));

  EXPECT_EQ(-1, Utils::Minimum(-1, 1));
  EXPECT_EQ(-1, Utils::Minimum(1, -1));

  EXPECT_EQ(-2, Utils::Minimum(-1, -2));
  EXPECT_EQ(-2, Utils::Minimum(-2, -1));
}

UNIT_TEST_CASE(Maximum) {
  EXPECT_EQ(1, Utils::Maximum(0, 1));
  EXPECT_EQ(1, Utils::Maximum(1, 0));

  EXPECT_EQ(2, Utils::Maximum(1, 2));
  EXPECT_EQ(2, Utils::Maximum(2, 1));

  EXPECT_EQ(1, Utils::Maximum(-1, 1));
  EXPECT_EQ(1, Utils::Maximum(1, -1));

  EXPECT_EQ(-1, Utils::Maximum(-1, -2));
  EXPECT_EQ(-1, Utils::Maximum(-2, -1));
}

UNIT_TEST_CASE(IsPowerOfTwo) {
  EXPECT(!Utils::IsPowerOfTwo(0));
  EXPECT(Utils::IsPowerOfTwo(1));
  EXPECT(Utils::IsPowerOfTwo(2));
  EXPECT(!Utils::IsPowerOfTwo(3));
  EXPECT(Utils::IsPowerOfTwo(4));
  EXPECT(Utils::IsPowerOfTwo(256));

  EXPECT(!Utils::IsPowerOfTwo(-1));
  EXPECT(!Utils::IsPowerOfTwo(-2));
}

UNIT_TEST_CASE(ShiftForPowerOfTwo) {
  EXPECT_EQ(1, Utils::ShiftForPowerOfTwo(2));
  EXPECT_EQ(2, Utils::ShiftForPowerOfTwo(4));
  EXPECT_EQ(8, Utils::ShiftForPowerOfTwo(256));
}

UNIT_TEST_CASE(IsAligned) {
  EXPECT(Utils::IsAligned(0, 1));
  EXPECT(Utils::IsAligned(1, 1));

  EXPECT(Utils::IsAligned(0, 2));
  EXPECT(!Utils::IsAligned(1, 2));
  EXPECT(Utils::IsAligned(2, 2));

  EXPECT(Utils::IsAligned(32, 8));
  EXPECT(!Utils::IsAligned(33, 8));
  EXPECT(Utils::IsAligned(40, 8));
}

UNIT_TEST_CASE(RoundDown) {
  EXPECT_EQ(0, Utils::RoundDown(22, 32));
  EXPECT_EQ(32, Utils::RoundDown(33, 32));
  EXPECT_EQ(32, Utils::RoundDown(63, 32));
  uword* address = reinterpret_cast<uword*>(63);
  uword* rounddown_address = reinterpret_cast<uword*>(32);
  EXPECT_EQ(rounddown_address, Utils::RoundDown(address, 32));
}

UNIT_TEST_CASE(RoundUp) {
  EXPECT_EQ(32, Utils::RoundUp(22, 32));
  EXPECT_EQ(64, Utils::RoundUp(33, 32));
  EXPECT_EQ(64, Utils::RoundUp(63, 32));
  uword* address = reinterpret_cast<uword*>(63);
  uword* roundup_address = reinterpret_cast<uword*>(64);
  EXPECT_EQ(roundup_address, Utils::RoundUp(address, 32));
}

UNIT_TEST_CASE(RoundUpToPowerOfTwo) {
  EXPECT_EQ(0U, Utils::RoundUpToPowerOfTwo(0));
  EXPECT_EQ(1U, Utils::RoundUpToPowerOfTwo(1));
  EXPECT_EQ(2U, Utils::RoundUpToPowerOfTwo(2));
  EXPECT_EQ(4U, Utils::RoundUpToPowerOfTwo(3));
  EXPECT_EQ(4U, Utils::RoundUpToPowerOfTwo(4));
  EXPECT_EQ(8U, Utils::RoundUpToPowerOfTwo(5));
  EXPECT_EQ(8U, Utils::RoundUpToPowerOfTwo(7));
  EXPECT_EQ(16U, Utils::RoundUpToPowerOfTwo(9));
  EXPECT_EQ(16U, Utils::RoundUpToPowerOfTwo(16));
  EXPECT_EQ(0x10000000U, Utils::RoundUpToPowerOfTwo(0x08765432));
}

UNIT_TEST_CASE(CountOneBits) {
  EXPECT_EQ(0, Utils::CountOneBits(0));
  EXPECT_EQ(1, Utils::CountOneBits(0x00000010));
  EXPECT_EQ(1, Utils::CountOneBits(0x00010000));
  EXPECT_EQ(1, Utils::CountOneBits(0x10000000));
  EXPECT_EQ(4, Utils::CountOneBits(0x10101010));
  EXPECT_EQ(8, Utils::CountOneBits(0x03030303));
  EXPECT_EQ(32, Utils::CountOneBits(0xFFFFFFFF));
}

UNIT_TEST_CASE(CountZeros) {
  EXPECT_EQ(0, Utils::CountTrailingZeros(0x1));
  EXPECT_EQ(kBitsPerWord - 1, Utils::CountLeadingZeros(0x1));
  EXPECT_EQ(1, Utils::CountTrailingZeros(0x2));
  EXPECT_EQ(kBitsPerWord - 2, Utils::CountLeadingZeros(0x2));
  EXPECT_EQ(0, Utils::CountTrailingZeros(0x3));
  EXPECT_EQ(kBitsPerWord - 2, Utils::CountLeadingZeros(0x3));
  EXPECT_EQ(2, Utils::CountTrailingZeros(0x4));
  EXPECT_EQ(kBitsPerWord - 3, Utils::CountLeadingZeros(0x4));
  EXPECT_EQ(0, Utils::CountTrailingZeros(kUwordMax));
  EXPECT_EQ(0, Utils::CountLeadingZeros(kUwordMax));
  static const uword kTopBit = static_cast<uword>(1) << (kBitsPerWord - 1);
  EXPECT_EQ(kBitsPerWord - 1, Utils::CountTrailingZeros(kTopBit));
  EXPECT_EQ(0, Utils::CountLeadingZeros(kTopBit));
}

UNIT_TEST_CASE(IsInt) {
  EXPECT(Utils::IsInt(8, 16));
  EXPECT(Utils::IsInt(8, 127));
  EXPECT(Utils::IsInt(8, -128));
  EXPECT(!Utils::IsInt(8, 255));
  EXPECT(Utils::IsInt(16, 16));
  EXPECT(!Utils::IsInt(16, 65535));
  EXPECT(Utils::IsInt(16, 32767));
  EXPECT(Utils::IsInt(16, -32768));
  EXPECT(Utils::IsInt(32, 16LL));
  EXPECT(Utils::IsInt(32, 2147483647LL));
  EXPECT(Utils::IsInt(32, -2147483648LL));
  EXPECT(!Utils::IsInt(32, 4294967295LL));
}

UNIT_TEST_CASE(IsUint) {
  EXPECT(Utils::IsUint(8, 16));
  EXPECT(Utils::IsUint(8, 0));
  EXPECT(Utils::IsUint(8, 255));
  EXPECT(!Utils::IsUint(8, 256));
  EXPECT(Utils::IsUint(16, 16));
  EXPECT(Utils::IsUint(16, 0));
  EXPECT(Utils::IsUint(16, 65535));
  EXPECT(!Utils::IsUint(16, 65536));
  EXPECT(Utils::IsUint(32, 16LL));
  EXPECT(Utils::IsUint(32, 0LL));
  EXPECT(Utils::IsUint(32, 4294967295LL));
  EXPECT(!Utils::IsUint(32, 4294967296LL));
}

UNIT_TEST_CASE(IsAbsoluteUint) {
  EXPECT(Utils::IsAbsoluteUint(8, 16));
  EXPECT(Utils::IsAbsoluteUint(8, 0));
  EXPECT(Utils::IsAbsoluteUint(8, -128));
  EXPECT(Utils::IsAbsoluteUint(8, 255));
  EXPECT(!Utils::IsAbsoluteUint(8, 256));
  EXPECT(Utils::IsAbsoluteUint(16, 16));
  EXPECT(Utils::IsAbsoluteUint(16, 0));
  EXPECT(Utils::IsAbsoluteUint(16, 65535));
  EXPECT(Utils::IsAbsoluteUint(16, -32768));
  EXPECT(!Utils::IsAbsoluteUint(16, 65536));
  EXPECT(Utils::IsAbsoluteUint(32, 16LL));
  EXPECT(Utils::IsAbsoluteUint(32, 0LL));
  EXPECT(Utils::IsAbsoluteUint(32, -2147483648LL));
  EXPECT(Utils::IsAbsoluteUint(32, 4294967295LL));
  EXPECT(!Utils::IsAbsoluteUint(32, 4294967296LL));
}

UNIT_TEST_CASE(LowBits) {
  EXPECT_EQ(0xff00, Utils::Low16Bits(0xffff00));
  EXPECT_EQ(0xff, Utils::High16Bits(0xffff00));
  EXPECT_EQ(0xff00, Utils::Low32Bits(0xff0000ff00LL));
  EXPECT_EQ(0xff, Utils::High32Bits(0xff0000ff00LL));
  EXPECT_EQ(0x00ff0000ff00LL, Utils::LowHighTo64Bits(0xff00, 0x00ff));
}

UNIT_TEST_CASE(Endianity) {
  uint16_t value16be = Utils::HostToBigEndian16(0xf1);
  EXPECT_EQ(0x0, reinterpret_cast<uint8_t*>(&value16be)[0]);
  EXPECT_EQ(0xf1, reinterpret_cast<uint8_t*>(&value16be)[1]);

  uint16_t value16le = Utils::HostToLittleEndian16(0xf1);
  EXPECT_EQ(0xf1, reinterpret_cast<uint8_t*>(&value16le)[0]);
  EXPECT_EQ(0x0, reinterpret_cast<uint8_t*>(&value16le)[1]);

  uint32_t value32be = Utils::HostToBigEndian32(0xf1f2);
  EXPECT_EQ(0x0, reinterpret_cast<uint8_t*>(&value32be)[0]);
  EXPECT_EQ(0x0, reinterpret_cast<uint8_t*>(&value32be)[1]);
  EXPECT_EQ(0xf1, reinterpret_cast<uint8_t*>(&value32be)[2]);
  EXPECT_EQ(0xf2, reinterpret_cast<uint8_t*>(&value32be)[3]);

  uint32_t value32le = Utils::HostToLittleEndian32(0xf1f2);
  EXPECT_EQ(0xf2, reinterpret_cast<uint8_t*>(&value32le)[0]);
  EXPECT_EQ(0xf1, reinterpret_cast<uint8_t*>(&value32le)[1]);
  EXPECT_EQ(0x0, reinterpret_cast<uint8_t*>(&value32le)[2]);
  EXPECT_EQ(0x0, reinterpret_cast<uint8_t*>(&value32le)[3]);

  uint64_t value64be = Utils::HostToBigEndian64(0xf1f2f3f4);
  EXPECT_EQ(0x0, reinterpret_cast<uint8_t*>(&value64be)[0]);
  EXPECT_EQ(0x0, reinterpret_cast<uint8_t*>(&value64be)[1]);
  EXPECT_EQ(0x0, reinterpret_cast<uint8_t*>(&value64be)[2]);
  EXPECT_EQ(0x0, reinterpret_cast<uint8_t*>(&value64be)[3]);
  EXPECT_EQ(0xf1, reinterpret_cast<uint8_t*>(&value64be)[4]);
  EXPECT_EQ(0xf2, reinterpret_cast<uint8_t*>(&value64be)[5]);
  EXPECT_EQ(0xf3, reinterpret_cast<uint8_t*>(&value64be)[6]);
  EXPECT_EQ(0xf4, reinterpret_cast<uint8_t*>(&value64be)[7]);

  uint64_t value64le = Utils::HostToLittleEndian64(0xf1f2f3f4);
  EXPECT_EQ(0xf4, reinterpret_cast<uint8_t*>(&value64le)[0]);
  EXPECT_EQ(0xf3, reinterpret_cast<uint8_t*>(&value64le)[1]);
  EXPECT_EQ(0xf2, reinterpret_cast<uint8_t*>(&value64le)[2]);
  EXPECT_EQ(0xf1, reinterpret_cast<uint8_t*>(&value64le)[3]);
  EXPECT_EQ(0x0, reinterpret_cast<uint8_t*>(&value64le)[4]);
  EXPECT_EQ(0x0, reinterpret_cast<uint8_t*>(&value64le)[5]);
  EXPECT_EQ(0x0, reinterpret_cast<uint8_t*>(&value64le)[6]);
  EXPECT_EQ(0x0, reinterpret_cast<uint8_t*>(&value64le)[7]);
}

UNIT_TEST_CASE(DoublesBitEqual) {
  EXPECT(Utils::DoublesBitEqual(1.0, 1.0));
  EXPECT(!Utils::DoublesBitEqual(1.0, -1.0));
  EXPECT(Utils::DoublesBitEqual(0.0, 0.0));
  EXPECT(!Utils::DoublesBitEqual(0.0, -0.0));
  EXPECT(Utils::DoublesBitEqual(NAN, NAN));
}

}  // namespace dart
<|endoftext|>


<commit_before>#ifndef RADIUMENGINE_TRIANGLEMESH_HPP
#define RADIUMENGINE_TRIANGLEMESH_HPP

#include <Core/RaCore.hpp>
#include <Core/Math/LinearAlgebra.hpp>
#include <Core/Containers/VectorArray.hpp>
#include <Core/Mesh/MeshTypes.hpp>

namespace Ra
{
    namespace Core
    {
        /// A very basic structure representing a triangle mesh which stores the bare minimum :
        /// vertices, faces and normals. See MeshUtils for geometric functions operating on a mesh.
        struct TriangleMesh
        {
            /// Create an empty mesh.
            inline TriangleMesh() {}
            /// Copy constructor and assignment operator
            TriangleMesh( const TriangleMesh& ) = default;
            TriangleMesh& operator= ( const TriangleMesh& ) = default;

            /// Erases all data, making the mesh empty.
            inline void clear();

            /// Appends another mesh to this one.
            inline void append( const TriangleMesh& other );

            VectorArray<Vector3>  m_vertices;
            VectorArray<Vector3>  m_normals;
            VectorArray<Triangle> m_triangles;
        };
    }
}

#include <Core/Mesh/TriangleMesh.inl>

#endif //RADIUMENGINE_TRIANGLEMESH_HPP
<commit_msg>Add aligned operator<commit_after>#ifndef RADIUMENGINE_TRIANGLEMESH_HPP
#define RADIUMENGINE_TRIANGLEMESH_HPP

#include <Core/RaCore.hpp>
#include <Core/Math/LinearAlgebra.hpp>
#include <Core/Containers/VectorArray.hpp>
#include <Core/Mesh/MeshTypes.hpp>

namespace Ra
{
    namespace Core
    {
        /// A very basic structure representing a triangle mesh which stores the bare minimum :
        /// vertices, faces and normals. See MeshUtils for geometric functions operating on a mesh.
        struct TriangleMesh
        {
            /// Create an empty mesh.
            inline TriangleMesh() {}
            /// Copy constructor and assignment operator
            TriangleMesh( const TriangleMesh& ) = default;
            TriangleMesh& operator= ( const TriangleMesh& ) = default;

            /// Erases all data, making the mesh empty.
            inline void clear();

            /// Appends another mesh to this one.
            inline void append( const TriangleMesh& other );

            VectorArray<Vector3>  m_vertices;
            VectorArray<Vector3>  m_normals;
            VectorArray<Triangle> m_triangles;

        public:
            EIGEN_MAKE_ALIGNED_OPERATOR_NEW
        };
    }
}

#include <Core/Mesh/TriangleMesh.inl>

#endif //RADIUMENGINE_TRIANGLEMESH_HPP
<|endoftext|>


<commit_before>/*************************************************************************
 *
 * 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: macro.hxx,v $
 * $Revision: 1.14 $
 *
 * 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 _RTL_MACRO_HXX
#define _RTL_MACRO_HXX

#include <rtl/bootstrap.h>
#include <rtl/ustring.hxx>
#include <osl/endian.h>

#if defined WIN32
#define THIS_OS "Windows"
#elif defined OS2
#define THIS_OS "OS/2"
#elif defined SOLARIS
#define THIS_OS "Solaris"
#elif defined LINUX
#define THIS_OS "Linux"
#elif defined MACOSX
#define THIS_OS "MacOSX"
#elif defined NETBSD
#define THIS_OS "NetBSD"
#elif defined FREEBSD
#define THIS_OS "FreeBSD"
#elif defined IRIX
#define THIS_OS "Irix"
#endif

#if ! defined THIS_OS
#error "unknown OS -- insert your OS identifier above"
this is inserted for the case that the preprocessor ignores error
#endif

#if defined INTEL
#    define THIS_ARCH "x86"
#elif defined POWERPC64
#    define THIS_ARCH "PowerPC_64"
#elif defined POWERPC
#    define THIS_ARCH "PowerPC"
#elif defined S390X
#    define THIS_ARCH "S390x"
#elif defined S390
#    define THIS_ARCH "S390"
#elif defined SPARC
#    define THIS_ARCH "SPARC"
#elif defined SPARC64
#    define THIS_ARCH "SPARC64"
#elif defined IRIX
#    define THIS_ARCH "MIPS"
#elif defined X86_64
#    define THIS_ARCH "X86_64"
#elif defined MIPS
#    ifdef OSL_BIGENDIAN
#        define THIS_ARCH "MIPS_EB"
#    else
#        define THIS_ARCH "MIPS_EL"
#    endif
#elif defined ARM
#    ifdef __ARM_EABI__
#        define THIS_ARCH "ARM_EABI"
#    else
#        define THIS_ARCH "ARM_OABI"
#    endif
#elif defined IA64
#    define THIS_ARCH "IA64"
#elif defined M68K
#    define THIS_ARCH "M68K"
#endif

#if ! defined THIS_ARCH
#error "unknown ARCH -- insert your ARCH identifier above"
this is inserted for the case that the preprocessor ignores error
#endif

#endif

<commit_msg>INTEGRATION: CWS os2port03 (1.7.6); FILE MERGED 2008/07/16 12:26:23 obr 1.7.6.3: RESYNC: (1.8-1.14); FILE MERGED 2008/01/15 13:57:41 obr 1.7.6.2: RESYNC: (1.7-1.8); FILE MERGED 2008/01/14 17:01:01 ydario 1.7.6.1: remove slash from macro.hxx, it is used as path separator. Issue number:i85203 Submitted by:ydario<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: macro.hxx,v $
 * $Revision: 1.15 $
 *
 * 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 _RTL_MACRO_HXX
#define _RTL_MACRO_HXX

#include <rtl/bootstrap.h>
#include <rtl/ustring.hxx>
#include <osl/endian.h>

#if defined WIN32
#define THIS_OS "Windows"
#elif defined OS2
#define THIS_OS "OS2"
#elif defined SOLARIS
#define THIS_OS "Solaris"
#elif defined LINUX
#define THIS_OS "Linux"
#elif defined MACOSX
#define THIS_OS "MacOSX"
#elif defined NETBSD
#define THIS_OS "NetBSD"
#elif defined FREEBSD
#define THIS_OS "FreeBSD"
#elif defined IRIX
#define THIS_OS "Irix"
#endif

#if ! defined THIS_OS
#error "unknown OS -- insert your OS identifier above"
this is inserted for the case that the preprocessor ignores error
#endif

#if defined INTEL
#    define THIS_ARCH "x86"
#elif defined POWERPC64
#    define THIS_ARCH "PowerPC_64"
#elif defined POWERPC
#    define THIS_ARCH "PowerPC"
#elif defined S390X
#    define THIS_ARCH "S390x"
#elif defined S390
#    define THIS_ARCH "S390"
#elif defined SPARC
#    define THIS_ARCH "SPARC"
#elif defined SPARC64
#    define THIS_ARCH "SPARC64"
#elif defined IRIX
#    define THIS_ARCH "MIPS"
#elif defined X86_64
#    define THIS_ARCH "X86_64"
#elif defined MIPS
#    ifdef OSL_BIGENDIAN
#        define THIS_ARCH "MIPS_EB"
#    else
#        define THIS_ARCH "MIPS_EL"
#    endif
#elif defined ARM
#    ifdef __ARM_EABI__
#        define THIS_ARCH "ARM_EABI"
#    else
#        define THIS_ARCH "ARM_OABI"
#    endif
#elif defined IA64
#    define THIS_ARCH "IA64"
#elif defined M68K
#    define THIS_ARCH "M68K"
#endif

#if ! defined THIS_ARCH
#error "unknown ARCH -- insert your ARCH identifier above"
this is inserted for the case that the preprocessor ignores error
#endif

#endif

<|endoftext|>


<commit_before>/* -*-  mode: c++; c-default-style: "google"; indent-tabs-mode: nil -*- */

/*
  Authors: Ethan Coon (ecoon@lanl.gov)
*/

#include "MatrixMFD.hh"
#include "MatrixMFD_Factory.hh"
#include "Function.hh"
#include "FunctionFactory.hh"

#include "implicit_snow_distribution_evaluator.hh"

namespace Amanzi {
namespace Flow {
namespace FlowRelations {

ImplicitSnowDistributionEvaluator::ImplicitSnowDistributionEvaluator(Teuchos::ParameterList& plist) :
    SecondaryVariableFieldEvaluator(plist),
    assembled_(false) {
  my_key_ = plist_.get<std::string>("precipitation snow field", "precipitation_snow");

  // depenedencies
  mesh_name_ = plist_.get<std::string>("domain name", "surface");
  if (mesh_name_ == "domain") {
    cell_vol_key_ = "cell_volume";
  } else {
    cell_vol_key_ = mesh_name_+std::string("_cell_volume");
  }
  dependencies_.insert(cell_vol_key_);

  elev_key_ = plist_.get<std::string>("elevation key", "elevation");
  dependencies_.insert(elev_key_);
  slope_key_ = plist_.get<std::string>("slope key", "slope_magnitude");
  dependencies_.insert(slope_key_);
  pd_key_ = plist_.get<std::string>("ponded depth key", "ponded_depth");
  dependencies_.insert(pd_key_);
  snow_height_key_ = plist_.get<std::string>("snow height key", "snow_depth");
  dependencies_.insert(snow_height_key_);

  // constant parameters
  kL_ = plist_.get<double>("snow distribution length");
  kdx_ = plist_.get<double>("characteristic horizontal grid size", 0.25);
  ktmax_ = plist_.get<double>("faux integration time", 86400.);
  kS_ = plist_.get<double>("characteristic slope", 1.);
  kCFL_ = plist_.get<double>("Courant number", 1.);
  kSWE_conv_ = plist_.get<double>("SWE-to-snow conversion ratio", 10.);
  tol_ = plist_.get<double>("solver tolerance", 1.e-2);
  max_it_ = plist_.get<int>("max iterations", 10);

  FunctionFactory fac;
  precip_func_ = Teuchos::rcp(fac.Create(plist_.sublist("precipitation function")));
}

ImplicitSnowDistributionEvaluator::ImplicitSnowDistributionEvaluator(const ImplicitSnowDistributionEvaluator& other) :
    SecondaryVariableFieldEvaluator(other),
    elev_key_(other.elev_key_),
    slope_key_(other.slope_key_),
    pd_key_(other.pd_key_),
    snow_height_key_(other.snow_height_key_),
    cell_vol_key_(other.cell_vol_key_),
    precip_func_(other.precip_func_),
    kL_(other.kL_),
    kdx_(other.kdx_),
    ktmax_(other.ktmax_),
    kS_(other.kS_),
    kCFL_(other.kCFL_),
    kSWE_conv_(other.kSWE_conv_),
    tol_(other.tol_),
    max_it_(other.max_it_),
    assembled_(other.assembled_),
    mesh_name_(other.mesh_name_),
    matrix_(other.matrix_) {}

void ImplicitSnowDistributionEvaluator::EvaluateField_(const Teuchos::Ptr<State>& S,
        const Teuchos::Ptr<CompositeVector>& result) {
  Teuchos::OSTab tab = vo_->getOSTab();

  if (!assembled_) AssembleOperator_(S);

  double time = S->time();
  double Qe = (*precip_func_)(&time);
  double dt_sim = *S->GetScalarData("dt");

  // NOTE: snow precip comes in SWE, must convert it to snow depth!
  if (Qe * dt_sim * kSWE_conv_ > 0.) {
    // determine scaling of flow

    const double kV = kL_/ktmax_;
    double dt = kCFL_ * kdx_ / kV;

    const double kh0 = Qe * ktmax_ * kSWE_conv_;
    const double nm = std::pow(kh0, 1./3) * std::sqrt(kS_) / kV;

    int nsteps = std::ceil(ktmax_ / dt);
    dt = ktmax_ / nsteps;

    // scale report
    if (vo_->os_OK(Teuchos::VERB_HIGH)) {
      *vo_->os() << "Snow Distribution: taking " << nsteps << " steps of size " << dt
                 << " s for travel length " << kL_ << " m." << std::endl
                 << "  L     = " << kL_ << std::endl
                 << "  t_max = " << ktmax_ << std::endl
                 << "  V     = " << kV << std::endl
                 << "  Q     = " << kV*kh0 << std::endl
                 << "  -------" << std::endl
                 << "  h0    = " << kh0 << std::endl
                 << "  nm    = " << nm << std::endl
                 << "  V(man)= " << std::pow(kh0,1./3) * std::sqrt(kS_) / nm << std::endl
                 << "  -------" << std::endl;
    }

    // Gather mesh entities
    Teuchos::RCP<const AmanziMesh::Mesh> mesh = S->GetMesh(mesh_name_);
    int nfaces = mesh->num_entities(AmanziMesh::FACE, AmanziMesh::OWNED);
    int ncells = mesh->num_entities(AmanziMesh::CELL, AmanziMesh::OWNED);
    int nfaces_g = mesh->num_entities(AmanziMesh::FACE, AmanziMesh::USED);

    // Gather null boundary conditions (no flux of snow into or out of domain)
    std::vector<Operators::MatrixBC> bc_markers(nfaces_g, Operators::MATRIX_BC_NULL);
    std::vector<double> bc_values(nfaces_g, 0.0);

    // Create temporary work space
    // -- not necessarily ghosted workspace
    Teuchos::RCP<CompositeVector> residual = Teuchos::rcp(new CompositeVector(*result));
    Teuchos::RCP<CompositeVector> result_prev = Teuchos::rcp(new CompositeVector(*result));
    Teuchos::RCP<CompositeVector> dresult = Teuchos::rcp(new CompositeVector(*result));

    // -- necessarily ghosted workspace
    CompositeVectorSpace ghosted_space(result->Map());
    ghosted_space.SetGhosted();
    Teuchos::RCP<CompositeVector> hz = Teuchos::rcp(new CompositeVector(ghosted_space));
    Teuchos::RCP<CompositeVector> Krel_c = Teuchos::rcp(new CompositeVector(ghosted_space));

    CompositeVectorSpace Krel_f_space;
    Krel_f_space.SetMesh(mesh)->SetGhosted()->SetComponent("face",AmanziMesh::FACE,1);
    Teuchos::RCP<CompositeVector> Krel_uw = Teuchos::rcp(new CompositeVector(Krel_f_space));

    // Gather dependencies
    // NOTE: this is incorrect approximation... should be | sqrt( grad( z+h_pd ) ) |
    const Epetra_MultiVector& slope = *S->GetFieldData(slope_key_)->ViewComponent("cell",false);
    const Epetra_MultiVector& cv = *S->GetFieldData(cell_vol_key_)->ViewComponent("cell",false);
    Teuchos::RCP<const CompositeVector> elev = S->GetFieldData(elev_key_);
    Teuchos::RCP<const CompositeVector> pd = S->GetFieldData(pd_key_);
    Teuchos::RCP<const CompositeVector> snow_height = S->GetFieldData(snow_height_key_);

    // initialize and begin timestep loop
    result->PutScalar(Qe * ktmax_ * kSWE_conv_);
    for (int istep=0; istep!=nsteps; ++istep) {
      if (vo_->os_OK(Teuchos::VERB_HIGH))
        *vo_->os() << "Snow distribution inner timestep " << istep << " with size " << dt << std::endl
                   << "   Qe*t_total =" << std::endl;

      *result_prev = *result;
      double norm0 = 0.;
      bool done = false;
      int ncycle = 0;
      while(!done) {
        // update snow potential, z + h_pd + h_s + Qe*dt
        *hz = *result;
        hz->Update(1., *elev, 1., *pd, 1.);
        hz->Update(1., *snow_height, 1.);

        if (vo_->os_OK(Teuchos::VERB_EXTREME)) {
          *vo_->os() << "  z + h_pd + h_s potential = " << std::endl;
          hz->Print(*vo_->os());
        }

        // update Krel
        {
          Epetra_MultiVector& Krel_c_vec = *Krel_c->ViewComponent("cell",false);
          const Epetra_MultiVector& result_c = *result->ViewComponent("cell",false);
          for (int c=0; c!=ncells; ++c) {
            Krel_c_vec[0][c] = std::pow(std::max(result_c[0][c],0.), 4./3)
              / (std::sqrt(std::max(slope[0][c], 1.e-6)) * nm);
          }
        }

        // communicate and upwind
        Krel_c->ScatterMasterToGhosted();
        hz->ScatterMasterToGhosted();
        {
          Epetra_MultiVector& Krel_uw_vec = *Krel_uw->ViewComponent("face",false);
          const Epetra_MultiVector& Krel_c_vec = *Krel_c->ViewComponent("cell",true);
          const Epetra_MultiVector& hz_c = *hz->ViewComponent("cell",true);
          for (int f=0; f!=nfaces; ++f) {
            AmanziMesh::Entity_ID_List cells;
            mesh->face_get_cells(f,AmanziMesh::USED,&cells);
            if (cells.size() == 1) {
            Krel_uw_vec[0][f] = Krel_c_vec[0][cells[0]];
            } else {
              if (hz_c[0][cells[0]] > hz_c[0][cells[1]]) {
                Krel_uw_vec[0][f] = Krel_c_vec[0][cells[0]];
              } else {
                Krel_uw_vec[0][f] = Krel_c_vec[0][cells[1]];
              }
            }
          }
        }

        // Re-assemble
        Krel_uw->ScatterMasterToGhosted();
        matrix_->CreateMFDstiffnessMatrices(Krel_uw.ptr());
        matrix_->CreateMFDrhsVectors();
        matrix_->ApplyBoundaryConditions(bc_markers, bc_values);
        matrix_->AssembleGlobalMatrices();

        // Apply the operator to get div flux
        matrix_->ComputeNegativeResidual(*hz, residual.ptr());
        if (vo_->os_OK(Teuchos::VERB_EXTREME)) {
          *vo_->os() << "  DIFFUSION RESIDUAL = " << std::endl;
          residual->Print(*vo_->os());
        }

        // Accumulation
        {
          Epetra_MultiVector& residual_c = *residual->ViewComponent("cell",false);
          const Epetra_MultiVector& result_prev_c = *result_prev->ViewComponent("cell",false);
          const Epetra_MultiVector& result_c = *result->ViewComponent("cell",false);
          unsigned int ncells = residual_c.MyLength();
          for (unsigned int c=0; c!=ncells; ++c) {
            residual_c[0][c] += (result_c[0][c] - result_prev_c[0][c]) * cv[0][c] / dt;
          }
        }
        if (vo_->os_OK(Teuchos::VERB_EXTREME)) {
          *vo_->os() << "  ACCUMULATION RESIDUAL = " << std::endl;
          residual->Print(*vo_->os());
        }

        double norm = 0.;
        residual->NormInf(&norm);
        if (ncycle == 0) norm0 = norm;
        ncycle++;
        if (vo_->os_OK(Teuchos::VERB_HIGH)) {
          *vo_->os() << "  inner iterate " << ncycle << " has error norm " << norm << std::endl;
        }
        if (vo_->os_OK(Teuchos::VERB_EXTREME)) {
          residual->Print(*vo_->os());
        }

        if ((norm0 == 0.) || (norm / norm0 < tol_) || (ncycle > max_it_)) {
          done = true;
          continue;
        }

        // Apply the preconditioner
        matrix_->CreateMFDstiffnessMatrices(Krel_uw.ptr());
        matrix_->CreateMFDrhsVectors();
        matrix_->ApplyBoundaryConditions(bc_markers, bc_values);
        {
          std::vector<double>& Acc_cells = matrix_->Acc_cells();
          unsigned int ncells = Acc_cells.size();
          for (unsigned int c=0; c!=ncells; ++c) {
            Acc_cells[c] += cv[0][c] / dt;
          }
        }
        matrix_->AssembleGlobalMatrices();
        matrix_->ComputeSchurComplement(bc_markers, bc_values);
        matrix_->UpdatePreconditioner();

        dresult->PutScalar(0.);
        matrix_linsolve_->ApplyInverse(*residual, *dresult);
        if (vo_->os_OK(Teuchos::VERB_EXTREME)) {
          *vo_->os() << "  precon'd update = " << std::endl;
          dresult->Print(*vo_->os());
        }

        // Update
        result->Update(-1., *dresult, 1.);
        if (vo_->os_OK(Teuchos::VERB_EXTREME)) {
          *vo_->os() << "  new snow depth = " << std::endl;
          result->Print(*vo_->os());
        }
      }
    }

    // get Q back
    result->Scale(1./(ktmax_ * kSWE_conv_));
  } else {
    result->PutScalar(0.);
  }
}

// This is hopefully never called?
void ImplicitSnowDistributionEvaluator::EvaluateFieldPartialDerivative_(const Teuchos::Ptr<State>& S,
        Key wrt_key, const Teuchos::Ptr<CompositeVector>& results) {
  ASSERT(0);
}

void
ImplicitSnowDistributionEvaluator::AssembleOperator_(const Teuchos::Ptr<State>& S) {
  Teuchos::RCP<const AmanziMesh::Mesh> mesh = S->GetMesh(mesh_name_);
  matrix_ = Operators::CreateMatrixMFD(plist_.sublist("Diffusion"), mesh);

  matrix_->set_symmetric(true);
  matrix_->SymbolicAssembleGlobalMatrices();
  matrix_->CreateMFDmassMatrices(Teuchos::null);
  matrix_->InitPreconditioner();

  AmanziSolvers::LinearOperatorFactory<CompositeMatrix,CompositeVector,CompositeVectorSpace> fac;
  matrix_linsolve_ = fac.Create(plist_.sublist("Diffusion Solver"), matrix_);
}

} //namespace
} //namespace
} //namespace
<commit_msg>tweaks to debugging of snow distribution<commit_after>/* -*-  mode: c++; c-default-style: "google"; indent-tabs-mode: nil -*- */

/*
  Authors: Ethan Coon (ecoon@lanl.gov)
*/

#include "MatrixMFD.hh"
#include "MatrixMFD_Factory.hh"
#include "Function.hh"
#include "FunctionFactory.hh"

#include "implicit_snow_distribution_evaluator.hh"

namespace Amanzi {
namespace Flow {
namespace FlowRelations {

ImplicitSnowDistributionEvaluator::ImplicitSnowDistributionEvaluator(Teuchos::ParameterList& plist) :
    SecondaryVariableFieldEvaluator(plist),
    assembled_(false) {
  my_key_ = plist_.get<std::string>("precipitation snow field", "precipitation_snow");

  // depenedencies
  mesh_name_ = plist_.get<std::string>("domain name", "surface");
  if (mesh_name_ == "domain") {
    cell_vol_key_ = "cell_volume";
  } else {
    cell_vol_key_ = mesh_name_+std::string("_cell_volume");
  }
  dependencies_.insert(cell_vol_key_);

  elev_key_ = plist_.get<std::string>("elevation key", "elevation");
  dependencies_.insert(elev_key_);
  slope_key_ = plist_.get<std::string>("slope key", "slope_magnitude");
  dependencies_.insert(slope_key_);
  pd_key_ = plist_.get<std::string>("ponded depth key", "ponded_depth");
  dependencies_.insert(pd_key_);
  snow_height_key_ = plist_.get<std::string>("snow height key", "snow_depth");
  dependencies_.insert(snow_height_key_);

  // constant parameters
  kL_ = plist_.get<double>("snow distribution length");
  kdx_ = plist_.get<double>("characteristic horizontal grid size", 0.25);
  ktmax_ = plist_.get<double>("faux integration time", 86400.);
  kS_ = plist_.get<double>("characteristic slope", 1.);
  kCFL_ = plist_.get<double>("Courant number", 1.);
  kSWE_conv_ = plist_.get<double>("SWE-to-snow conversion ratio", 10.);
  tol_ = plist_.get<double>("solver tolerance", 1.e-2);
  max_it_ = plist_.get<int>("max iterations", 10);

  FunctionFactory fac;
  precip_func_ = Teuchos::rcp(fac.Create(plist_.sublist("precipitation function")));
}

ImplicitSnowDistributionEvaluator::ImplicitSnowDistributionEvaluator(const ImplicitSnowDistributionEvaluator& other) :
    SecondaryVariableFieldEvaluator(other),
    elev_key_(other.elev_key_),
    slope_key_(other.slope_key_),
    pd_key_(other.pd_key_),
    snow_height_key_(other.snow_height_key_),
    cell_vol_key_(other.cell_vol_key_),
    precip_func_(other.precip_func_),
    kL_(other.kL_),
    kdx_(other.kdx_),
    ktmax_(other.ktmax_),
    kS_(other.kS_),
    kCFL_(other.kCFL_),
    kSWE_conv_(other.kSWE_conv_),
    tol_(other.tol_),
    max_it_(other.max_it_),
    assembled_(other.assembled_),
    mesh_name_(other.mesh_name_),
    matrix_(other.matrix_) {}

void ImplicitSnowDistributionEvaluator::EvaluateField_(const Teuchos::Ptr<State>& S,
        const Teuchos::Ptr<CompositeVector>& result) {
  Teuchos::OSTab tab = vo_->getOSTab();

  if (!assembled_) AssembleOperator_(S);

  double time = S->time();
  double Qe = (*precip_func_)(&time);
  double dt_sim = *S->GetScalarData("dt");

  // NOTE: snow precip comes in SWE, must convert it to snow depth!
  if (Qe * dt_sim * kSWE_conv_ > 0.) {
    // determine scaling of flow

    const double kV = kL_/ktmax_;
    double dt = kCFL_ * kdx_ / kV;

    const double kh0 = Qe * ktmax_ * kSWE_conv_;
    const double nm = std::pow(kh0, 1./3) * std::sqrt(kS_) / kV;

    int nsteps = std::ceil(ktmax_ / dt);
    dt = ktmax_ / nsteps;

    // scale report
    if (vo_->os_OK(Teuchos::VERB_MEDIUM)) {
      *vo_->os() << "Snow Distribution: taking " << nsteps << " steps of size " << dt
                 << " s for travel length " << kL_ << " m." << std::endl
                 << "  L     = " << kL_ << std::endl
                 << "  t_max = " << ktmax_ << std::endl
                 << "  V     = " << kV << std::endl
                 << "  Q     = " << kV*kh0 << std::endl
                 << "  -------" << std::endl
                 << "  h0    = " << kh0 << std::endl
                 << "  nm    = " << nm << std::endl
                 << "  V(man)= " << std::pow(kh0,1./3) * std::sqrt(kS_) / nm << std::endl
                 << "  -------" << std::endl;
    }

    // Gather mesh entities
    Teuchos::RCP<const AmanziMesh::Mesh> mesh = S->GetMesh(mesh_name_);
    int nfaces = mesh->num_entities(AmanziMesh::FACE, AmanziMesh::OWNED);
    int ncells = mesh->num_entities(AmanziMesh::CELL, AmanziMesh::OWNED);
    int nfaces_g = mesh->num_entities(AmanziMesh::FACE, AmanziMesh::USED);

    // Gather null boundary conditions (no flux of snow into or out of domain)
    std::vector<Operators::MatrixBC> bc_markers(nfaces_g, Operators::MATRIX_BC_NULL);
    std::vector<double> bc_values(nfaces_g, 0.0);

    // Create temporary work space
    // -- not necessarily ghosted workspace
    Teuchos::RCP<CompositeVector> residual = Teuchos::rcp(new CompositeVector(*result));
    Teuchos::RCP<CompositeVector> result_prev = Teuchos::rcp(new CompositeVector(*result));
    Teuchos::RCP<CompositeVector> dresult = Teuchos::rcp(new CompositeVector(*result));

    // -- necessarily ghosted workspace
    CompositeVectorSpace ghosted_space(result->Map());
    ghosted_space.SetGhosted();
    Teuchos::RCP<CompositeVector> hz = Teuchos::rcp(new CompositeVector(ghosted_space));
    Teuchos::RCP<CompositeVector> Krel_c = Teuchos::rcp(new CompositeVector(ghosted_space));

    CompositeVectorSpace Krel_f_space;
    Krel_f_space.SetMesh(mesh)->SetGhosted()->SetComponent("face",AmanziMesh::FACE,1);
    Teuchos::RCP<CompositeVector> Krel_uw = Teuchos::rcp(new CompositeVector(Krel_f_space));

    // Gather dependencies
    // NOTE: this is incorrect approximation... should be | sqrt( grad( z+h_pd ) ) |
    const Epetra_MultiVector& slope = *S->GetFieldData(slope_key_)->ViewComponent("cell",false);
    const Epetra_MultiVector& cv = *S->GetFieldData(cell_vol_key_)->ViewComponent("cell",false);
    Teuchos::RCP<const CompositeVector> elev = S->GetFieldData(elev_key_);
    Teuchos::RCP<const CompositeVector> pd = S->GetFieldData(pd_key_);
    Teuchos::RCP<const CompositeVector> snow_height = S->GetFieldData(snow_height_key_);

    // initialize and begin timestep loop
    result->PutScalar(Qe * ktmax_ * kSWE_conv_);
    for (int istep=0; istep!=nsteps; ++istep) {
      if (vo_->os_OK(Teuchos::VERB_HIGH))
        *vo_->os() << "Snow distribution inner timestep " << istep << " with size " << dt << std::endl
                   << "   Qe*t_total =" << std::endl;

      *result_prev = *result;
      double norm0 = 0.;
      bool done = false;
      int ncycle = 0;
      while(!done) {
        // update snow potential, z + h_pd + h_s + Qe*dt
        *hz = *result;
        hz->Update(1., *elev, 1., *pd, 1.);
        hz->Update(1., *snow_height, 1.);

        if (vo_->os_OK(Teuchos::VERB_EXTREME)) {
          *vo_->os() << "  z + h_pd + h_s potential = " << std::endl;
          hz->Print(*vo_->os());
        }

        // update Krel
        {
          Epetra_MultiVector& Krel_c_vec = *Krel_c->ViewComponent("cell",false);
          const Epetra_MultiVector& result_c = *result->ViewComponent("cell",false);
          for (int c=0; c!=ncells; ++c) {
            Krel_c_vec[0][c] = std::pow(std::max(result_c[0][c],0.), 4./3)
              / (std::sqrt(std::max(slope[0][c], 1.e-6)) * nm);
          }
        }

        // communicate and upwind
        Krel_c->ScatterMasterToGhosted();
        hz->ScatterMasterToGhosted();
        {
          Epetra_MultiVector& Krel_uw_vec = *Krel_uw->ViewComponent("face",false);
          const Epetra_MultiVector& Krel_c_vec = *Krel_c->ViewComponent("cell",true);
          const Epetra_MultiVector& hz_c = *hz->ViewComponent("cell",true);
          for (int f=0; f!=nfaces; ++f) {
            AmanziMesh::Entity_ID_List cells;
            mesh->face_get_cells(f,AmanziMesh::USED,&cells);
            if (cells.size() == 1) {
            Krel_uw_vec[0][f] = Krel_c_vec[0][cells[0]];
            } else {
              if (hz_c[0][cells[0]] > hz_c[0][cells[1]]) {
                Krel_uw_vec[0][f] = Krel_c_vec[0][cells[0]];
              } else {
                Krel_uw_vec[0][f] = Krel_c_vec[0][cells[1]];
              }
            }
          }
        }

        // Re-assemble
        Krel_uw->ScatterMasterToGhosted();
        matrix_->CreateMFDstiffnessMatrices(Krel_uw.ptr());
        matrix_->CreateMFDrhsVectors();
        matrix_->ApplyBoundaryConditions(bc_markers, bc_values);
        matrix_->AssembleGlobalMatrices();

        // Apply the operator to get div flux
        matrix_->ComputeNegativeResidual(*hz, residual.ptr());
        if (vo_->os_OK(Teuchos::VERB_EXTREME)) {
          *vo_->os() << "  DIFFUSION RESIDUAL = " << std::endl;
          residual->Print(*vo_->os());
        }

        // Accumulation
        {
          Epetra_MultiVector& residual_c = *residual->ViewComponent("cell",false);
          const Epetra_MultiVector& result_prev_c = *result_prev->ViewComponent("cell",false);
          const Epetra_MultiVector& result_c = *result->ViewComponent("cell",false);
          unsigned int ncells = residual_c.MyLength();
          for (unsigned int c=0; c!=ncells; ++c) {
            residual_c[0][c] += (result_c[0][c] - result_prev_c[0][c]) * cv[0][c] / dt;
          }
        }
        if (vo_->os_OK(Teuchos::VERB_EXTREME)) {
          *vo_->os() << "  ACCUMULATION RESIDUAL = " << std::endl;
          residual->Print(*vo_->os());
        }

        double norm = 0.;
        residual->NormInf(&norm);
        if (ncycle == 0) norm0 = norm;
        ncycle++;
        if (vo_->os_OK(Teuchos::VERB_HIGH)) {
          *vo_->os() << "  inner iterate " << ncycle << " has error norm " << norm << std::endl;
        }
        if (vo_->os_OK(Teuchos::VERB_EXTREME)) {
          residual->Print(*vo_->os());
        }

        if ((norm0 == 0.) || (norm / norm0 < tol_) || (ncycle > max_it_)) {
          done = true;
          continue;
        }

        // Apply the preconditioner
        matrix_->CreateMFDstiffnessMatrices(Krel_uw.ptr());
        matrix_->CreateMFDrhsVectors();
        matrix_->ApplyBoundaryConditions(bc_markers, bc_values);
        {
          std::vector<double>& Acc_cells = matrix_->Acc_cells();
          unsigned int ncells = Acc_cells.size();
          for (unsigned int c=0; c!=ncells; ++c) {
            Acc_cells[c] += cv[0][c] / dt;
          }
        }
        matrix_->AssembleGlobalMatrices();
        matrix_->ComputeSchurComplement(bc_markers, bc_values);
        matrix_->UpdatePreconditioner();

        dresult->PutScalar(0.);
        matrix_linsolve_->ApplyInverse(*residual, *dresult);
        if (vo_->os_OK(Teuchos::VERB_EXTREME)) {
          *vo_->os() << "  precon'd update = " << std::endl;
          dresult->Print(*vo_->os());
        }

        // Update
        result->Update(-1., *dresult, 1.);
        if (vo_->os_OK(Teuchos::VERB_EXTREME)) {
          *vo_->os() << "  new snow depth = " << std::endl;
          result->Print(*vo_->os());
        }
      }
    }

    // get Q back
    result->Scale(1./(ktmax_ * kSWE_conv_));
  } else {
    result->PutScalar(0.);
  }
}

// This is hopefully never called?
void ImplicitSnowDistributionEvaluator::EvaluateFieldPartialDerivative_(const Teuchos::Ptr<State>& S,
        Key wrt_key, const Teuchos::Ptr<CompositeVector>& results) {
  ASSERT(0);
}

void
ImplicitSnowDistributionEvaluator::AssembleOperator_(const Teuchos::Ptr<State>& S) {
  Teuchos::RCP<const AmanziMesh::Mesh> mesh = S->GetMesh(mesh_name_);
  matrix_ = Operators::CreateMatrixMFD(plist_.sublist("Diffusion"), mesh);

  matrix_->set_symmetric(true);
  matrix_->SymbolicAssembleGlobalMatrices();
  matrix_->CreateMFDmassMatrices(Teuchos::null);
  matrix_->InitPreconditioner();

  AmanziSolvers::LinearOperatorFactory<CompositeMatrix,CompositeVector,CompositeVectorSpace> fac;
  matrix_linsolve_ = fac.Create(plist_.sublist("Diffusion Solver"), matrix_);
}

} //namespace
} //namespace
} //namespace
<|endoftext|>


<commit_before>#include <cstdio> // sscanf
#include <cstdint>
#include <iostream>
#include <fstream>
#include <map>
#include <string>
#include <sstream>
#include <vector>

extern "C" {
	#include "../../src/ASSInspector.h"
}

struct DialogLine {
	int time;
	std::string line;
};

class ScriptWrapper {
		std::string headerBuffer;
		std::vector<DialogLine> lineBuffers;

	public:
		ScriptWrapper( void );
		void appendHeader( std::string line );
		std::string getHeader( void );
		std::vector<DialogLine> getLines( void );
		void appendDialogue( std::string line, int time );
};

ScriptWrapper::ScriptWrapper( void ) :
headerBuffer( "[Script Info]\n" ) {

}

void ScriptWrapper::appendHeader( std::string line ) {
	headerBuffer += line + "\n";
}

std::string ScriptWrapper::getHeader( void ) {
	return headerBuffer;
}

void ScriptWrapper::appendDialogue( std::string line, int time ) {
	lineBuffers.push_back( {time, line + '\n'} );
}

std::vector<DialogLine> ScriptWrapper::getLines( void ) {
	return lineBuffers;
}

// this should definitely all be one function it is so good
int main( int argc, char **argv ) {
	int width = 0, height = 0;

	if ( 2 > argc ) {
		std::cout << "Usage: " << argv[0] << " infile.ass" << std::endl;
		return 1;
	}

	std::fstream inAss( argv[1], std::ifstream::in );
	if ( inAss.fail( ) ) {
		std::cout << "Failed to open " << argv[1] << std::endl;
	}

	std::string line;
	std::getline( inAss, line );
	if ( "[Script Info]" != line ) {
		// BOM?
		if ( "[Script Info]" != line.substr( 3 ) ) {
			std::cout << "The input file, " << argv[1] << ", does not appear to be valid ASS." << std::endl;
			inAss.close( );
			return 1;
		}
	}

	ScriptWrapper wrapper;

	// This is pretty terrible.
	while ( true ) {
		std::getline( inAss, line );
		if ( '[' == line[0] ) {
			break;
		}
		switch ( line[0] ) {
			case 'S':
				if ( 0 == line.compare( 0, 22, "ScaledBorderAndShadow:" ) ) {
					wrapper.appendHeader( line );
				} else if ( 0 == line.compare( 0, 11, "ScriptType:" ) ) {
					wrapper.appendHeader( line );
				}
				break;
			case 'P':
				if ( 0 == line.compare( 0, 9, "PlayResX:" ) ) {
					std::stringstream converter( line.substr( 9 ) );
					converter >> width;
					wrapper.appendHeader( line );
				} else if ( 0 == line.compare( 0, 9, "PlayResY:" ) ) {
					std::stringstream converter( line.substr( 9 ) );
					converter >> height;
					wrapper.appendHeader( line );
				}
				break;
			case 'W':
				if ( 0 == line.compare( 0, 10, "WrapStyle:" ) ) {
					wrapper.appendHeader( line );
				}
				break;
		}
		if ( !inAss.good( ) ) {
			break;
		}
	}

	wrapper.appendHeader( "[V4+ Styles]" );

	while ( true ) {
		std::getline( inAss, line );
		switch ( line[0] ) {
			case 'S':
				if ( 0 == line.compare( 0, 6, "Style:" ) ) {
					wrapper.appendHeader( line );
				}
				break;
			case 'D':
				if ( 0 == line.compare( 0, 9, "Dialogue:" ) ) {
					int hours = 0, minutes = 0, seconds = 0, centiseconds = 0;
					sscanf( line.substr( 9 ).c_str( ), "%*d,%u:%u:%u.%u", &hours, &minutes, &seconds, &centiseconds );
					int milliseconds = 3600000*hours + 60000*minutes + 1000*seconds + 10*centiseconds;
					wrapper.appendDialogue( line, milliseconds );
				}
				break;
		}
		if ( !inAss.good( ) ) {
			break;
		}
	}

	inAss.close( );

	wrapper.appendHeader( "[Events]" );

	ASSI_State *state = assi_init( width, height, NULL, NULL );

	std::string header = wrapper.getHeader( );
	assi_setHeader( state, header.c_str( ), header.length( ) );

	std::map<uint32_t,int> hashes;
	std::map<uint32_t,int>::iterator match;

	int deleted = 0, kept = 0;
	int processed = 0;

	for ( const auto &pair : wrapper.getLines( ) ) {
		assi_setScript( state, pair.line.c_str( ), pair.line.length( ) );
		ASSI_Rect rect{ 0, 0, 0, 0, 0 };
		assi_calculateBounds( state, &rect, &pair.time, 1 );
		++processed;
		match = hashes.find( rect.hash );
		if ( hashes.end( ) != match ) {
			std::cout << "Line " << processed << ": duplicate hash found (line " << match->second << ")" << std::endl;
		} else {
			hashes[rect.hash] = processed;
		}
		if ( rect.w == 0 || rect.h == 0 ) {
			++deleted;
		} else {
			++kept;
		}
	}

	std::cout << "Deleted " << deleted << " lines out of " << processed << std::endl;

	assi_cleanup( state );
	return 0;
}
<commit_msg>C++ example: don't segfault if input file doesn't exist.<commit_after>#include <cstdio> // sscanf
#include <cstdint>
#include <iostream>
#include <fstream>
#include <map>
#include <string>
#include <sstream>
#include <vector>

extern "C" {
	#include "../../src/ASSInspector.h"
}

struct DialogLine {
	int time;
	std::string line;
};

class ScriptWrapper {
		std::string headerBuffer;
		std::vector<DialogLine> lineBuffers;

	public:
		ScriptWrapper( void );
		void appendHeader( std::string line );
		std::string getHeader( void );
		std::vector<DialogLine> getLines( void );
		void appendDialogue( std::string line, int time );
};

ScriptWrapper::ScriptWrapper( void ) :
headerBuffer( "[Script Info]\n" ) {

}

void ScriptWrapper::appendHeader( std::string line ) {
	headerBuffer += line + "\n";
}

std::string ScriptWrapper::getHeader( void ) {
	return headerBuffer;
}

void ScriptWrapper::appendDialogue( std::string line, int time ) {
	lineBuffers.push_back( {time, line + '\n'} );
}

std::vector<DialogLine> ScriptWrapper::getLines( void ) {
	return lineBuffers;
}

// this should definitely all be one function it is so good
int main( int argc, char **argv ) {
	int width = 0, height = 0;

	if ( 2 > argc ) {
		std::cout << "Usage: " << argv[0] << " infile.ass" << std::endl;
		return 1;
	}

	std::fstream inAss( argv[1], std::ifstream::in );
	if ( inAss.fail( ) ) {
		std::cout << "Failed to open " << argv[1] << std::endl;
		return 1;
	}

	std::string line;
	std::getline( inAss, line );
	if ( "[Script Info]" != line ) {
		// BOM?
		if ( "[Script Info]" != line.substr( 3 ) ) {
			std::cout << "The input file, " << argv[1] << ", does not appear to be valid ASS." << std::endl;
			inAss.close( );
			return 1;
		}
	}

	ScriptWrapper wrapper;

	// This is pretty terrible.
	while ( true ) {
		std::getline( inAss, line );
		if ( '[' == line[0] ) {
			break;
		}
		switch ( line[0] ) {
			case 'S':
				if ( 0 == line.compare( 0, 22, "ScaledBorderAndShadow:" ) ) {
					wrapper.appendHeader( line );
				} else if ( 0 == line.compare( 0, 11, "ScriptType:" ) ) {
					wrapper.appendHeader( line );
				}
				break;
			case 'P':
				if ( 0 == line.compare( 0, 9, "PlayResX:" ) ) {
					std::stringstream converter( line.substr( 9 ) );
					converter >> width;
					wrapper.appendHeader( line );
				} else if ( 0 == line.compare( 0, 9, "PlayResY:" ) ) {
					std::stringstream converter( line.substr( 9 ) );
					converter >> height;
					wrapper.appendHeader( line );
				}
				break;
			case 'W':
				if ( 0 == line.compare( 0, 10, "WrapStyle:" ) ) {
					wrapper.appendHeader( line );
				}
				break;
		}
		if ( !inAss.good( ) ) {
			break;
		}
	}

	wrapper.appendHeader( "[V4+ Styles]" );

	while ( true ) {
		std::getline( inAss, line );
		switch ( line[0] ) {
			case 'S':
				if ( 0 == line.compare( 0, 6, "Style:" ) ) {
					wrapper.appendHeader( line );
				}
				break;
			case 'D':
				if ( 0 == line.compare( 0, 9, "Dialogue:" ) ) {
					int hours = 0, minutes = 0, seconds = 0, centiseconds = 0;
					sscanf( line.substr( 9 ).c_str( ), "%*d,%u:%u:%u.%u", &hours, &minutes, &seconds, &centiseconds );
					int milliseconds = 3600000*hours + 60000*minutes + 1000*seconds + 10*centiseconds;
					wrapper.appendDialogue( line, milliseconds );
				}
				break;
		}
		if ( !inAss.good( ) ) {
			break;
		}
	}

	inAss.close( );

	wrapper.appendHeader( "[Events]" );

	ASSI_State *state = assi_init( width, height, NULL, NULL );

	std::string header = wrapper.getHeader( );
	assi_setHeader( state, header.c_str( ), header.length( ) );

	std::map<uint32_t,int> hashes;
	std::map<uint32_t,int>::iterator match;

	int deleted = 0, kept = 0;
	int processed = 0;

	for ( const auto &pair : wrapper.getLines( ) ) {
		assi_setScript( state, pair.line.c_str( ), pair.line.length( ) );
		ASSI_Rect rect{ 0, 0, 0, 0, 0 };
		assi_calculateBounds( state, &rect, &pair.time, 1 );
		++processed;
		match = hashes.find( rect.hash );
		if ( hashes.end( ) != match ) {
			std::cout << "Line " << processed << ": duplicate hash found (line " << match->second << ")" << std::endl;
		} else {
			hashes[rect.hash] = processed;
		}
		if ( rect.w == 0 || rect.h == 0 ) {
			++deleted;
		} else {
			++kept;
		}
	}

	std::cout << "Deleted " << deleted << " lines out of " << processed << std::endl;

	assi_cleanup( state );
	return 0;
}
<|endoftext|>