{
  Name = QObject::tr("p-MOSFET");
  BitmapFile = (char *) "pmosfet_sub";

  if(getNewOne) {
    MOSFET_sub* p = new MOSFET_sub();
    p->Props.first()->Value = "pfet";
    p->Props.next()->Value = "-1.0 V";
    p->recreate(0);
    return p;
  }
  return 0;
}

/***************************************************************************
                              mosfet_sub.cpp
                             ----------------
    begin                : Fri Jun 4 2004
    email                : example@nnthink.com
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *                                                                         *
 ***************************************************************************/

#include "mosfet_sub.h"

Basic_MOSFET::Basic_MOSFET()
{
  // these must be the first properties in the list !!!
  Props.append(new Property("Type", "nfet", false,
	QObject::tr("polarity")+" [nfet, pfet]"));
  Props.append(new Property("Vt0", "1.0 V", true,
	QObject::tr("zero-bias threshold voltage")));

  Props.append(new Property("Kp", "2e-5", true,
	QObject::tr("transconductance coefficient in A/V^2")));
  Props.append(new Property("Gamma", "0.0", false,
	QObject::tr("bulk threshold in sqrt(V)")));
  Props.append(new Property("Phi", "0.6 V", false,
	QObject::tr("surface potential")));
  Props.append(new Property("Lambda", "0.0", true,
	QObject::tr("channel-length modulation parameter in 1/V")));
  Props.append(new Property("Rd", "0.0 Ohm", false,
	QObject::tr("drain ohmic resistance")));
  Props.append(new Property("Rs", "0.0 Ohm", false,
	QObject::tr("source ohmic resistance")));
  Props.append(new Property("Rg", "0.0 Ohm", false,
	QObject::tr("gate ohmic resistance")));
  Props.append(new Property("Is", "1e-14 A", false,
	QObject::tr("bulk junction saturation current")));
  Props.append(new Property("N", "1.0", false,
	QObject::tr("bulk junction emission coefficient")));
  Props.append(new Property("W", "1 um", false,
	QObject::tr("channel width")));
  Props.append(new Property("L", "1 um", false,
	QObject::tr("channel length")));
  Props.append(new Property("Ld", "0.0", false,
	QObject::tr("lateral diffusion length")));
  Props.append(new Property("Tox", "0.1 um", false,
	QObject::tr("oxide thickness")));
  Props.append(new Property("Cgso", "0.0", false,
	QObject::tr("gate-source overlap capacitance per meter of "
		    "channel width in F/m")));
  Props.append(new Property("Cgdo", "0.0", false,
	QObject::tr("gate-drain overlap capacitance per meter of "
		    "channel width in F/m")));
  Props.append(new Property("Cgbo", "0.0", false,
	QObject::tr("gate-bulk overlap capacitance per meter of "
		    "channel length in F/m")));
  Props.append(new Property("Cbd", "0.0 F", false,
	QObject::tr("zero-bias bulk-drain junction capacitance")));
  Props.append(new Property("Cbs", "0.0 F", false,
	QObject::tr("zero-bias bulk-source junction capacitance")));
  Props.append(new Property("Pb", "0.8 V", false,
	QObject::tr("bulk junction potential")));
  Props.append(new Property("Mj", "0.5", false,
	QObject::tr("bulk junction bottom grading coefficient")));
  Props.append(new Property("Fc", "0.5", false,
	QObject::tr("bulk junction forward-bias depletion capacitance "
		    "coefficient")));
  Props.append(new Property("Cjsw", "0.0", false,
	QObject::tr("zero-bias bulk junction periphery capacitance per meter "
		    "of junction perimeter in F/m")));
  Props.append(new Property("Mjsw", "0.33", false,
	QObject::tr("bulk junction periphery grading coefficient")));
  Props.append(new Property("Tt", "0.0 ps", false,
	QObject::tr("bulk transit time")));
  Props.append(new Property("Nsub", "0.0", false,
	QObject::tr("substrate bulk doping density in 1/cm^3")));
  Props.append(new Property("Nss", "0.0", false,
	QObject::tr("surface state density in 1/cm^2")));
  Props.append(new Property("Tpg", "1", false,
	QObject::tr("gate material type: 0 = alumina; -1 = same as bulk; "
		    "1 = opposite to bulk")));
  Props.append(new Property("Uo", "600.0", false,
	QObject::tr("surface mobility in cm^2/Vs")));
  Props.append(new Property("Rsh", "0.0", false,
	QObject::tr("drain and source diffusion sheet resistance in "
		    "Ohms/square")));
  Props.append(new Property("Nrd", "1", false,
	QObject::tr("number of equivalent drain squares")));
  Props.append(new Property("Nrs", "1", false,
	QObject::tr("number of equivalent source squares")));
  Props.append(new Property("Cj", "0.0", false,
	QObject::tr("zero-bias bulk junction bottom capacitance per square "
		    "meter of junction area in F/m^2")));
  Props.append(new Property("Js", "0.0", false,
	QObject::tr("bulk junction saturation current per square "
		    "meter of junction area in A/m^2")));
  Props.append(new Property("Ad", "0.0", false,
	QObject::tr("drain diffusion area in m^2")));
  Props.append(new Property("As", "0.0", false,
	QObject::tr("source diffusion area in m^2")));
  Props.append(new Property("Pd", "0.0 m", false,
	QObject::tr("drain junction perimeter")));
  Props.append(new Property("Ps", "0.0 m", false,
	QObject::tr("source junction perimeter")));
  Props.append(new Property("Kf", "0.0", false,
	QObject::tr("flicker noise coefficient")));
  Props.append(new Property("Af", "1.0", false,
	QObject::tr("flicker noise exponent")));
  Props.append(new Property("Ffe", "1.0", false,
	QObject::tr("flicker noise frequency exponent")));
  Props.append(new Property("Temp", "26.85", false,
	QObject::tr("simulation temperature in degree Celsius")));
  Props.append(new Property("Tnom", "26.85", false,
	QObject::tr("parameter measurement temperature")));

  Name  = "T";
}

MOSFET_sub::MOSFET_sub()
{
  Description = QObject::tr("MOS field-effect transistor with substrate");
  createSymbol();
  tx = x2+4;
  ty = y1+4;
  Model = "MOSFET";
}

Component* MOSFET_sub::newOne()
{
  MOSFET_sub* p = new MOSFET_sub();
  p->Props.first()->Value = Props.first()->Value;
  p->Props.next()->Value = Props.next()->Value;
  p->recreate(0);
  return p;
}

Element* MOSFET_sub::info(QString& Name, char* &BitmapFile, bool getNewOne)
{
  Name = QObject::tr("n-MOSFET");
  BitmapFile = (char *) "nmosfet_sub";

  if(getNewOne)  return new MOSFET_sub();
  return 0;
}

Element* MOSFET_sub::info_p(QString& Name,
			char* &BitmapFile, bool getNewOne)

Element* MOSFET_sub::info_depl(QString& Name,
			char* &BitmapFile, bool getNewOne)
{
  Name = QObject::tr("depletion MOSFET");
  BitmapFile = (char *) "dmosfet_sub";

  if(getNewOne) {
    MOSFET_sub* p = new MOSFET_sub();
    p->Props.first();
    p->Props.next()->Value = "-1.0 V";
    p->recreate(0);
    return p;
  }
  return 0;
}

void MOSFET_sub::createSymbol()
{
  Lines.append(new Line(-14,-13,-14, 13,QPen(Qt::darkBlue,3)));
  Lines.append(new Line(-30,  0,-14,  0,QPen(Qt::darkBlue,2)));

  Lines.append(new Line(-10,-11,  0,-11,QPen(Qt::darkBlue,2)));
  Lines.append(new Line(  0,-11,  0,-30,QPen(Qt::darkBlue,2)));
  Lines.append(new Line(-10, 11,  0, 11,QPen(Qt::darkBlue,2)));
  Lines.append(new Line(  0, 11,  0, 30,QPen(Qt::darkBlue,2)));
  Lines.append(new Line(-10,  0, 20,  0,QPen(Qt::darkBlue,2)));

  Lines.append(new Line(-10,-16,-10, -7,QPen(Qt::darkBlue,3)));
  Lines.append(new Line(-10,  7,-10, 16,QPen(Qt::darkBlue,3)));

  Lines.append(new Line( -4, 24,  4, 20,QPen(Qt::darkBlue,2)));

  if(Props.first()->Value == "nfet") {
    Lines.append(new Line( -9,  0, -4, -5,QPen(Qt::darkBlue,2)));
    Lines.append(new Line( -9,  0, -4,  5,QPen(Qt::darkBlue,2)));
  }
  else {
    Lines.append(new Line( -1,  0, -6, -5,QPen(Qt::darkBlue,2)));
    Lines.append(new Line( -1,  0, -6,  5,QPen(Qt::darkBlue,2)));
  }

  if((Props.next()->Value.trimmed().at(0) == '-') ==
     (Props.first()->Value == "nfet"))
    Lines.append(new Line(-10, -8,-10,  8,QPen(Qt::darkBlue,3)));
  else
    Lines.append(new Line(-10, -4,-10,  4,QPen(Qt::darkBlue,3)));

  Ports.append(new Port(-30,  0));
  Ports.append(new Port(  0,-30));
  Ports.append(new Port(  0, 30));
  Ports.append(new Port( 20,  0));

  x1 = -30; y1 = -30;
  x2 =  30; y2 =  30;
}


{
  Name = QObject::tr("depletion MOSFET");

/***************************************************************************
                              mosfet_sub.cpp
                             ----------------
    begin                : Fri Jun 4 2004
    email                : example@nnthink.com
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *                                                                         *
 ***************************************************************************/

#include "mosfet_sub.h"

Basic_MOSFET::Basic_MOSFET()
{
  // these must be the first properties in the list !!!
  Props.append(new Property("Type", "nfet", false,
	QObject::tr("polarity")+" [nfet, pfet]"));
  Props.append(new Property("Vt0", "1.0 V", true,
	QObject::tr("zero-bias threshold voltage")));

  Props.append(new Property("Kp", "2e-5", true,
	QObject::tr("transconductance coefficient in A/V^2")));
  Props.append(new Property("Gamma", "0.0", false,
	QObject::tr("bulk threshold in sqrt(V)")));
  Props.append(new Property("Phi", "0.6 V", false,
	QObject::tr("surface potential")));
  Props.append(new Property("Lambda", "0.0", true,
	QObject::tr("channel-length modulation parameter in 1/V")));
  Props.append(new Property("Rd", "0.0 Ohm", false,
	QObject::tr("drain ohmic resistance")));
  Props.append(new Property("Rs", "0.0 Ohm", false,
	QObject::tr("source ohmic resistance")));
  Props.append(new Property("Rg", "0.0 Ohm", false,
	QObject::tr("gate ohmic resistance")));
  Props.append(new Property("Is", "1e-14 A", false,
	QObject::tr("bulk junction saturation current")));
  Props.append(new Property("N", "1.0", false,
	QObject::tr("bulk junction emission coefficient")));
  Props.append(new Property("W", "1 um", false,
	QObject::tr("channel width")));
  Props.append(new Property("L", "1 um", false,
	QObject::tr("channel length")));
  Props.append(new Property("Ld", "0.0", false,
	QObject::tr("lateral diffusion length")));
  Props.append(new Property("Tox", "0.1 um", false,
	QObject::tr("oxide thickness")));
  Props.append(new Property("Cgso", "0.0", false,
	QObject::tr("gate-source overlap capacitance per meter of "
		    "channel width in F/m")));
  Props.append(new Property("Cgdo", "0.0", false,
	QObject::tr("gate-drain overlap capacitance per meter of "
		    "channel width in F/m")));
  Props.append(new Property("Cgbo", "0.0", false,
	QObject::tr("gate-bulk overlap capacitance per meter of "
		    "channel length in F/m")));
  Props.append(new Property("Cbd", "0.0 F", false,
	QObject::tr("zero-bias bulk-drain junction capacitance")));
  Props.append(new Property("Cbs", "0.0 F", false,
	QObject::tr("zero-bias bulk-source junction capacitance")));
  Props.append(new Property("Pb", "0.8 V", false,
	QObject::tr("bulk junction potential")));
  Props.append(new Property("Mj", "0.5", false,
	QObject::tr("bulk junction bottom grading coefficient")));
  Props.append(new Property("Fc", "0.5", false,
	QObject::tr("bulk junction forward-bias depletion capacitance "
		    "coefficient")));
  Props.append(new Property("Cjsw", "0.0", false,
	QObject::tr("zero-bias bulk junction periphery capacitance per meter "
		    "of junction perimeter in F/m")));
  Props.append(new Property("Mjsw", "0.33", false,
	QObject::tr("bulk junction periphery grading coefficient")));
  Props.append(new Property("Tt", "0.0 ps", false,
	QObject::tr("bulk transit time")));
  Props.append(new Property("Nsub", "0.0", false,
	QObject::tr("substrate bulk doping density in 1/cm^3")));
  Props.append(new Property("Nss", "0.0", false,
	QObject::tr("surface state density in 1/cm^2")));
  Props.append(new Property("Tpg", "1", false,
	QObject::tr("gate material type: 0 = alumina; -1 = same as bulk; "
		    "1 = opposite to bulk")));
  Props.append(new Property("Uo", "600.0", false,
	QObject::tr("surface mobility in cm^2/Vs")));
  Props.append(new Property("Rsh", "0.0", false,
	QObject::tr("drain and source diffusion sheet resistance in "
		    "Ohms/square")));
  Props.append(new Property("Nrd", "1", false,
	QObject::tr("number of equivalent drain squares")));
  Props.append(new Property("Nrs", "1", false,
	QObject::tr("number of equivalent source squares")));
  Props.append(new Property("Cj", "0.0", false,
	QObject::tr("zero-bias bulk junction bottom capacitance per square "
		    "meter of junction area in F/m^2")));
  Props.append(new Property("Js", "0.0", false,
	QObject::tr("bulk junction saturation current per square "
		    "meter of junction area in A/m^2")));
  Props.append(new Property("Ad", "0.0", false,
	QObject::tr("drain diffusion area in m^2")));
  Props.append(new Property("As", "0.0", false,
	QObject::tr("source diffusion area in m^2")));
  Props.append(new Property("Pd", "0.0 m", false,
	QObject::tr("drain junction perimeter")));
  Props.append(new Property("Ps", "0.0 m", false,
	QObject::tr("source junction perimeter")));
  Props.append(new Property("Kf", "0.0", false,
	QObject::tr("flicker noise coefficient")));
  Props.append(new Property("Af", "1.0", false,
	QObject::tr("flicker noise exponent")));
  Props.append(new Property("Ffe", "1.0", false,
	QObject::tr("flicker noise frequency exponent")));
  Props.append(new Property("Temp", "26.85", false,
	QObject::tr("simulation temperature in degree Celsius")));
  Props.append(new Property("Tnom", "26.85", false,
	QObject::tr("parameter measurement temperature")));

  Name  = "T";
}

MOSFET_sub::MOSFET_sub()
{
  Description = QObject::tr("MOS field-effect transistor with substrate");
  createSymbol();
  tx = x2+4;
  ty = y1+4;
  Model = "MOSFET";
}

Component* MOSFET_sub::newOne()
{
  MOSFET_sub* p = new MOSFET_sub();
  p->Props.first()->Value = Props.first()->Value;
  p->Props.next()->Value = Props.next()->Value;
  p->recreate(0);
  return p;
}

Element* MOSFET_sub::info(QString& Name, char* &BitmapFile, bool getNewOne)
{
  Name = QObject::tr("n-MOSFET");
  BitmapFile = (char *) "nmosfet_sub";

  if(getNewOne)  return new MOSFET_sub();
  return 0;
}

Element* MOSFET_sub::info_p(QString& Name,
			char* &BitmapFile, bool getNewOne)
{
  Name = QObject::tr("p-MOSFET");
  BitmapFile = (char *) "pmosfet_sub";

  if(getNewOne) {
    MOSFET_sub* p = new MOSFET_sub();
    p->Props.first()->Value = "pfet";
    p->Props.next()->Value = "-1.0 V";
    p->recreate(0);
    return p;
  }
  return 0;
}

Element* MOSFET_sub::info_depl(QString& Name,
			char* &BitmapFile, bool getNewOne)

  BitmapFile = (char *) "dmosfet_sub";

  if(getNewOne) {
    MOSFET_sub* p = new MOSFET_sub();
    p->Props.first();
    p->Props.next()->Value = "-1.0 V";
    p->recreate(0);
    return p;
  }
  return 0;
}

void MOSFET_sub::createSymbol()
{
  Lines.append(new Line(-14,-13,-14, 13,QPen(Qt::darkBlue,3)));
  Lines.append(new Line(-30,  0,-14,  0,QPen(Qt::darkBlue,2)));

  Lines.append(new Line(-10,-11,  0,-11,QPen(Qt::darkBlue,2)));
  Lines.append(new Line(  0,-11,  0,-30,QPen(Qt::darkBlue,2)));
  Lines.append(new Line(-10, 11,  0, 11,QPen(Qt::darkBlue,2)));
  Lines.append(new Line(  0, 11,  0, 30,QPen(Qt::darkBlue,2)));
  Lines.append(new Line(-10,  0, 20,  0,QPen(Qt::darkBlue,2)));

  Lines.append(new Line(-10,-16,-10, -7,QPen(Qt::darkBlue,3)));
  Lines.append(new Line(-10,  7,-10, 16,QPen(Qt::darkBlue,3)));

  Lines.append(new Line( -4, 24,  4, 20,QPen(Qt::darkBlue,2)));

  if(Props.first()->Value == "nfet") {
    Lines.append(new Line( -9,  0, -4, -5,QPen(Qt::darkBlue,2)));
    Lines.append(new Line( -9,  0, -4,  5,QPen(Qt::darkBlue,2)));
  }
  else {
    Lines.append(new Line( -1,  0, -6, -5,QPen(Qt::darkBlue,2)));
    Lines.append(new Line( -1,  0, -6,  5,QPen(Qt::darkBlue,2)));
  }

  if((Props.next()->Value.trimmed().at(0) == '-') ==
     (Props.first()->Value == "nfet"))
    Lines.append(new Line(-10, -8,-10,  8,QPen(Qt::darkBlue,3)));
  else
    Lines.append(new Line(-10, -4,-10,  4,QPen(Qt::darkBlue,3)));

  Ports.append(new Port(-30,  0));
  Ports.append(new Port(  0,-30));
  Ports.append(new Port(  0, 30));
  Ports.append(new Port( 20,  0));

  x1 = -30; y1 = -30;
  x2 =  30; y2 =  30;
}


BitmapFile = (char *) "dmosfet_sub";

  if(getNewOne) {
    MOSFET_sub* p = new MOSFET_sub();
    p->Props.first();
    p->Props.next()->Value = "-1.0 V";
    p->recreate(0);
    return p;
  }

/***************************************************************************
                              mosfet_sub.cpp
                             ----------------
    begin                : Fri Jun 4 2004
    email                : example@nnthink.com
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *                                                                         *
 ***************************************************************************/

#include "mosfet_sub.h"

Basic_MOSFET::Basic_MOSFET()
{
  // these must be the first properties in the list !!!
  Props.append(new Property("Type", "nfet", false,
	QObject::tr("polarity")+" [nfet, pfet]"));
  Props.append(new Property("Vt0", "1.0 V", true,
	QObject::tr("zero-bias threshold voltage")));

  Props.append(new Property("Kp", "2e-5", true,
	QObject::tr("transconductance coefficient in A/V^2")));
  Props.append(new Property("Gamma", "0.0", false,
	QObject::tr("bulk threshold in sqrt(V)")));
  Props.append(new Property("Phi", "0.6 V", false,
	QObject::tr("surface potential")));
  Props.append(new Property("Lambda", "0.0", true,
	QObject::tr("channel-length modulation parameter in 1/V")));
  Props.append(new Property("Rd", "0.0 Ohm", false,
	QObject::tr("drain ohmic resistance")));
  Props.append(new Property("Rs", "0.0 Ohm", false,
	QObject::tr("source ohmic resistance")));
  Props.append(new Property("Rg", "0.0 Ohm", false,
	QObject::tr("gate ohmic resistance")));
  Props.append(new Property("Is", "1e-14 A", false,
	QObject::tr("bulk junction saturation current")));
  Props.append(new Property("N", "1.0", false,
	QObject::tr("bulk junction emission coefficient")));
  Props.append(new Property("W", "1 um", false,
	QObject::tr("channel width")));
  Props.append(new Property("L", "1 um", false,
	QObject::tr("channel length")));
  Props.append(new Property("Ld", "0.0", false,
	QObject::tr("lateral diffusion length")));
  Props.append(new Property("Tox", "0.1 um", false,
	QObject::tr("oxide thickness")));
  Props.append(new Property("Cgso", "0.0", false,
	QObject::tr("gate-source overlap capacitance per meter of "
		    "channel width in F/m")));
  Props.append(new Property("Cgdo", "0.0", false,
	QObject::tr("gate-drain overlap capacitance per meter of "
		    "channel width in F/m")));
  Props.append(new Property("Cgbo", "0.0", false,
	QObject::tr("gate-bulk overlap capacitance per meter of "
		    "channel length in F/m")));
  Props.append(new Property("Cbd", "0.0 F", false,
	QObject::tr("zero-bias bulk-drain junction capacitance")));
  Props.append(new Property("Cbs", "0.0 F", false,
	QObject::tr("zero-bias bulk-source junction capacitance")));
  Props.append(new Property("Pb", "0.8 V", false,
	QObject::tr("bulk junction potential")));
  Props.append(new Property("Mj", "0.5", false,
	QObject::tr("bulk junction bottom grading coefficient")));
  Props.append(new Property("Fc", "0.5", false,
	QObject::tr("bulk junction forward-bias depletion capacitance "
		    "coefficient")));
  Props.append(new Property("Cjsw", "0.0", false,
	QObject::tr("zero-bias bulk junction periphery capacitance per meter "
		    "of junction perimeter in F/m")));
  Props.append(new Property("Mjsw", "0.33", false,
	QObject::tr("bulk junction periphery grading coefficient")));
  Props.append(new Property("Tt", "0.0 ps", false,
	QObject::tr("bulk transit time")));
  Props.append(new Property("Nsub", "0.0", false,
	QObject::tr("substrate bulk doping density in 1/cm^3")));
  Props.append(new Property("Nss", "0.0", false,
	QObject::tr("surface state density in 1/cm^2")));
  Props.append(new Property("Tpg", "1", false,
	QObject::tr("gate material type: 0 = alumina; -1 = same as bulk; "
		    "1 = opposite to bulk")));
  Props.append(new Property("Uo", "600.0", false,
	QObject::tr("surface mobility in cm^2/Vs")));
  Props.append(new Property("Rsh", "0.0", false,
	QObject::tr("drain and source diffusion sheet resistance in "
		    "Ohms/square")));
  Props.append(new Property("Nrd", "1", false,
	QObject::tr("number of equivalent drain squares")));
  Props.append(new Property("Nrs", "1", false,
	QObject::tr("number of equivalent source squares")));
  Props.append(new Property("Cj", "0.0", false,
	QObject::tr("zero-bias bulk junction bottom capacitance per square "
		    "meter of junction area in F/m^2")));
  Props.append(new Property("Js", "0.0", false,
	QObject::tr("bulk junction saturation current per square "
		    "meter of junction area in A/m^2")));
  Props.append(new Property("Ad", "0.0", false,
	QObject::tr("drain diffusion area in m^2")));
  Props.append(new Property("As", "0.0", false,
	QObject::tr("source diffusion area in m^2")));
  Props.append(new Property("Pd", "0.0 m", false,
	QObject::tr("drain junction perimeter")));
  Props.append(new Property("Ps", "0.0 m", false,
	QObject::tr("source junction perimeter")));
  Props.append(new Property("Kf", "0.0", false,
	QObject::tr("flicker noise coefficient")));
  Props.append(new Property("Af", "1.0", false,
	QObject::tr("flicker noise exponent")));
  Props.append(new Property("Ffe", "1.0", false,
	QObject::tr("flicker noise frequency exponent")));
  Props.append(new Property("Temp", "26.85", false,
	QObject::tr("simulation temperature in degree Celsius")));
  Props.append(new Property("Tnom", "26.85", false,
	QObject::tr("parameter measurement temperature")));

  Name  = "T";
}

MOSFET_sub::MOSFET_sub()
{
  Description = QObject::tr("MOS field-effect transistor with substrate");
  createSymbol();
  tx = x2+4;
  ty = y1+4;
  Model = "MOSFET";
}

Component* MOSFET_sub::newOne()
{
  MOSFET_sub* p = new MOSFET_sub();
  p->Props.first()->Value = Props.first()->Value;
  p->Props.next()->Value = Props.next()->Value;
  p->recreate(0);
  return p;
}

Element* MOSFET_sub::info(QString& Name, char* &BitmapFile, bool getNewOne)
{
  Name = QObject::tr("n-MOSFET");
  BitmapFile = (char *) "nmosfet_sub";

  if(getNewOne)  return new MOSFET_sub();
  return 0;
}

Element* MOSFET_sub::info_p(QString& Name,
			char* &BitmapFile, bool getNewOne)
{
  Name = QObject::tr("p-MOSFET");
  BitmapFile = (char *) "pmosfet_sub";

  if(getNewOne) {
    MOSFET_sub* p = new MOSFET_sub();
    p->Props.first()->Value = "pfet";
    p->Props.next()->Value = "-1.0 V";
    p->recreate(0);
    return p;
  }
  return 0;
}

Element* MOSFET_sub::info_depl(QString& Name,
			char* &BitmapFile, bool getNewOne)
{
  Name = QObject::tr("depletion MOSFET");

  return 0;
}

void MOSFET_sub::createSymbol()
{
  Lines.append(new Line(-14,-13,-14, 13,QPen(Qt::darkBlue,3)));
  Lines.append(new Line(-30,  0,-14,  0,QPen(Qt::darkBlue,2)));

  Lines.append(new Line(-10,-11,  0,-11,QPen(Qt::darkBlue,2)));
  Lines.append(new Line(  0,-11,  0,-30,QPen(Qt::darkBlue,2)));
  Lines.append(new Line(-10, 11,  0, 11,QPen(Qt::darkBlue,2)));
  Lines.append(new Line(  0, 11,  0, 30,QPen(Qt::darkBlue,2)));
  Lines.append(new Line(-10,  0, 20,  0,QPen(Qt::darkBlue,2)));

  Lines.append(new Line(-10,-16,-10, -7,QPen(Qt::darkBlue,3)));
  Lines.append(new Line(-10,  7,-10, 16,QPen(Qt::darkBlue,3)));

  Lines.append(new Line( -4, 24,  4, 20,QPen(Qt::darkBlue,2)));

  if(Props.first()->Value == "nfet") {
    Lines.append(new Line( -9,  0, -4, -5,QPen(Qt::darkBlue,2)));
    Lines.append(new Line( -9,  0, -4,  5,QPen(Qt::darkBlue,2)));
  }
  else {
    Lines.append(new Line( -1,  0, -6, -5,QPen(Qt::darkBlue,2)));
    Lines.append(new Line( -1,  0, -6,  5,QPen(Qt::darkBlue,2)));
  }

  if((Props.next()->Value.trimmed().at(0) == '-') ==
     (Props.first()->Value == "nfet"))
    Lines.append(new Line(-10, -8,-10,  8,QPen(Qt::darkBlue,3)));
  else
    Lines.append(new Line(-10, -4,-10,  4,QPen(Qt::darkBlue,3)));

  Ports.append(new Port(-30,  0));
  Ports.append(new Port(  0,-30));
  Ports.append(new Port(  0, 30));
  Ports.append(new Port( 20,  0));

  x1 = -30; y1 = -30;
  x2 =  30; y2 =  30;
}


/***************************************************************************
                              mosfet_sub.cpp
                             ----------------
    begin                : Fri Jun 4 2004
    email                : example@nnthink.com
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *                                                                         *
 ***************************************************************************/

#include "mosfet_sub.h"

Basic_MOSFET::Basic_MOSFET()
{
  // these must be the first properties in the list !!!
  Props.append(new Property("Type", "nfet", false,
	QObject::tr("polarity")+" [nfet, pfet]"));
  Props.append(new Property("Vt0", "1.0 V", true,
	QObject::tr("zero-bias threshold voltage")));

  Props.append(new Property("Kp", "2e-5", true,
	QObject::tr("transconductance coefficient in A/V^2")));
  Props.append(new Property("Gamma", "0.0", false,
	QObject::tr("bulk threshold in sqrt(V)")));
  Props.append(new Property("Phi", "0.6 V", false,
	QObject::tr("surface potential")));
  Props.append(new Property("Lambda", "0.0", true,
	QObject::tr("channel-length modulation parameter in 1/V")));
  Props.append(new Property("Rd", "0.0 Ohm", false,
	QObject::tr("drain ohmic resistance")));
  Props.append(new Property("Rs", "0.0 Ohm", false,
	QObject::tr("source ohmic resistance")));
  Props.append(new Property("Rg", "0.0 Ohm", false,
	QObject::tr("gate ohmic resistance")));
  Props.append(new Property("Is", "1e-14 A", false,
	QObject::tr("bulk junction saturation current")));
  Props.append(new Property("N", "1.0", false,
	QObject::tr("bulk junction emission coefficient")));
  Props.append(new Property("W", "1 um", false,
	QObject::tr("channel width")));
  Props.append(new Property("L", "1 um", false,
	QObject::tr("channel length")));
  Props.append(new Property("Ld", "0.0", false,
	QObject::tr("lateral diffusion length")));
  Props.append(new Property("Tox", "0.1 um", false,
	QObject::tr("oxide thickness")));
  Props.append(new Property("Cgso", "0.0", false,
	QObject::tr("gate-source overlap capacitance per meter of "
		    "channel width in F/m")));
  Props.append(new Property("Cgdo", "0.0", false,
	QObject::tr("gate-drain overlap capacitance per meter of "
		    "channel width in F/m")));
  Props.append(new Property("Cgbo", "0.0", false,
	QObject::tr("gate-bulk overlap capacitance per meter of "
		    "channel length in F/m")));
  Props.append(new Property("Cbd", "0.0 F", false,
	QObject::tr("zero-bias bulk-drain junction capacitance")));
  Props.append(new Property("Cbs", "0.0 F", false,
	QObject::tr("zero-bias bulk-source junction capacitance")));
  Props.append(new Property("Pb", "0.8 V", false,
	QObject::tr("bulk junction potential")));
  Props.append(new Property("Mj", "0.5", false,
	QObject::tr("bulk junction bottom grading coefficient")));
  Props.append(new Property("Fc", "0.5", false,
	QObject::tr("bulk junction forward-bias depletion capacitance "
		    "coefficient")));
  Props.append(new Property("Cjsw", "0.0", false,
	QObject::tr("zero-bias bulk junction periphery capacitance per meter "
		    "of junction perimeter in F/m")));
  Props.append(new Property("Mjsw", "0.33", false,
	QObject::tr("bulk junction periphery grading coefficient")));
  Props.append(new Property("Tt", "0.0 ps", false,
	QObject::tr("bulk transit time")));
  Props.append(new Property("Nsub", "0.0", false,
	QObject::tr("substrate bulk doping density in 1/cm^3")));
  Props.append(new Property("Nss", "0.0", false,
	QObject::tr("surface state density in 1/cm^2")));
  Props.append(new Property("Tpg", "1", false,
	QObject::tr("gate material type: 0 = alumina; -1 = same as bulk; "
		    "1 = opposite to bulk")));
  Props.append(new Property("Uo", "600.0", false,
	QObject::tr("surface mobility in cm^2/Vs")));
  Props.append(new Property("Rsh", "0.0", false,
	QObject::tr("drain and source diffusion sheet resistance in "
		    "Ohms/square")));
  Props.append(new Property("Nrd", "1", false,
	QObject::tr("number of equivalent drain squares")));
  Props.append(new Property("Nrs", "1", false,
	QObject::tr("number of equivalent source squares")));
  Props.append(new Property("Cj", "0.0", false,
	QObject::tr("zero-bias bulk junction bottom capacitance per square "
		    "meter of junction area in F/m^2")));
  Props.append(new Property("Js", "0.0", false,
	QObject::tr("bulk junction saturation current per square "
		    "meter of junction area in A/m^2")));
  Props.append(new Property("Ad", "0.0", false,
	QObject::tr("drain diffusion area in m^2")));
  Props.append(new Property("As", "0.0", false,
	QObject::tr("source diffusion area in m^2")));
  Props.append(new Property("Pd", "0.0 m", false,
	QObject::tr("drain junction perimeter")));
  Props.append(new Property("Ps", "0.0 m", false,
	QObject::tr("source junction perimeter")));
  Props.append(new Property("Kf", "0.0", false,
	QObject::tr("flicker noise coefficient")));
  Props.append(new Property("Af", "1.0", false,
	QObject::tr("flicker noise exponent")));
  Props.append(new Property("Ffe", "1.0", false,
	QObject::tr("flicker noise frequency exponent")));
  Props.append(new Property("Temp", "26.85", false,
	QObject::tr("simulation temperature in degree Celsius")));
  Props.append(new Property("Tnom", "26.85", false,
	QObject::tr("parameter measurement temperature")));

  Name  = "T";
}

MOSFET_sub::MOSFET_sub()
{
  Description = QObject::tr("MOS field-effect transistor with substrate");
  createSymbol();
  tx = x2+4;
  ty = y1+4;
  Model = "MOSFET";
}

Component* MOSFET_sub::newOne()
{
  MOSFET_sub* p = new MOSFET_sub();
  p->Props.first()->Value = Props.first()->Value;
  p->Props.next()->Value = Props.next()->Value;
  p->recreate(0);
  return p;
}

Element* MOSFET_sub::info(QString& Name, char* &BitmapFile, bool getNewOne)
{
  Name = QObject::tr("n-MOSFET");
  BitmapFile = (char *) "nmosfet_sub";

  if(getNewOne)  return new MOSFET_sub();
  return 0;
}

Element* MOSFET_sub::info_p(QString& Name,
			char* &BitmapFile, bool getNewOne)
{
  Name = QObject::tr("p-MOSFET");
  BitmapFile = (char *) "pmosfet_sub";

  if(getNewOne) {
    MOSFET_sub* p = new MOSFET_sub();
    p->Props.first()->Value = "pfet";
    p->Props.next()->Value = "-1.0 V";
    p->recreate(0);
    return p;
  }
  return 0;
}

Element* MOSFET_sub::info_depl(QString& Name,
			char* &BitmapFile, bool getNewOne)
{
  Name = QObject::tr("depletion MOSFET");
  BitmapFile = (char *) "dmosfet_sub";

  if(getNewOne) {
    MOSFET_sub* p = new MOSFET_sub();
    p->Props.first();
    p->Props.next()->Value = "-1.0 V";
    p->recreate(0);
    return p;
  }

void MOSFET_sub::createSymbol()
{
  Lines.append(new Line(-14,-13,-14, 13,QPen(Qt::darkBlue,3)));
  Lines.append(new Line(-30,  0,-14,  0,QPen(Qt::darkBlue,2)));

  Lines.append(new Line(-10,-11,  0,-11,QPen(Qt::darkBlue,2)));
  Lines.append(new Line(  0,-11,  0,-30,QPen(Qt::darkBlue,2)));
  Lines.append(new Line(-10, 11,  0, 11,QPen(Qt::darkBlue,2)));
  Lines.append(new Line(  0, 11,  0, 30,QPen(Qt::darkBlue,2)));
  Lines.append(new Line(-10,  0, 20,  0,QPen(Qt::darkBlue,2)));

  Lines.append(new Line(-10,-16,-10, -7,QPen(Qt::darkBlue,3)));
  Lines.append(new Line(-10,  7,-10, 16,QPen(Qt::darkBlue,3)));

  Lines.append(new Line( -4, 24,  4, 20,QPen(Qt::darkBlue,2)));

  if(Props.first()->Value == "nfet") {
    Lines.append(new Line( -9,  0, -4, -5,QPen(Qt::darkBlue,2)));
    Lines.append(new Line( -9,  0, -4,  5,QPen(Qt::darkBlue,2)));
  }
  else {
    Lines.append(new Line( -1,  0, -6, -5,QPen(Qt::darkBlue,2)));
    Lines.append(new Line( -1,  0, -6,  5,QPen(Qt::darkBlue,2)));
  }

  if((Props.next()->Value.trimmed().at(0) == '-') ==
     (Props.first()->Value == "nfet"))
    Lines.append(new Line(-10, -8,-10,  8,QPen(Qt::darkBlue,3)));
  else
    Lines.append(new Line(-10, -4,-10,  4,QPen(Qt::darkBlue,3)));

  Ports.append(new Port(-30,  0));
  Ports.append(new Port(  0,-30));
  Ports.append(new Port(  0, 30));
  Ports.append(new Port( 20,  0));

  x1 = -30; y1 = -30;
  x2 =  30; y2 =  30;
}


/***************************************************************************
                              mosfet_sub.cpp
                             ----------------
    begin                : Fri Jun 4 2004
    email                : example@nnthink.com
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *                                                                         *
 ***************************************************************************/

#include "mosfet_sub.h"

Basic_MOSFET::Basic_MOSFET()
{
  // these must be the first properties in the list !!!
  Props.append(new Property("Type", "nfet", false,
	QObject::tr("polarity")+" [nfet, pfet]"));
  Props.append(new Property("Vt0", "1.0 V", true,
	QObject::tr("zero-bias threshold voltage")));

  Props.append(new Property("Kp", "2e-5", true,
	QObject::tr("transconductance coefficient in A/V^2")));
  Props.append(new Property("Gamma", "0.0", false,
	QObject::tr("bulk threshold in sqrt(V)")));
  Props.append(new Property("Phi", "0.6 V", false,
	QObject::tr("surface potential")));
  Props.append(new Property("Lambda", "0.0", true,
	QObject::tr("channel-length modulation parameter in 1/V")));
  Props.append(new Property("Rd", "0.0 Ohm", false,
	QObject::tr("drain ohmic resistance")));
  Props.append(new Property("Rs", "0.0 Ohm", false,
	QObject::tr("source ohmic resistance")));
  Props.append(new Property("Rg", "0.0 Ohm", false,
	QObject::tr("gate ohmic resistance")));
  Props.append(new Property("Is", "1e-14 A", false,
	QObject::tr("bulk junction saturation current")));
  Props.append(new Property("N", "1.0", false,
	QObject::tr("bulk junction emission coefficient")));
  Props.append(new Property("W", "1 um", false,
	QObject::tr("channel width")));
  Props.append(new Property("L", "1 um", false,
	QObject::tr("channel length")));
  Props.append(new Property("Ld", "0.0", false,
	QObject::tr("lateral diffusion length")));
  Props.append(new Property("Tox", "0.1 um", false,
	QObject::tr("oxide thickness")));
  Props.append(new Property("Cgso", "0.0", false,
	QObject::tr("gate-source overlap capacitance per meter of "
		    "channel width in F/m")));
  Props.append(new Property("Cgdo", "0.0", false,
	QObject::tr("gate-drain overlap capacitance per meter of "
		    "channel width in F/m")));
  Props.append(new Property("Cgbo", "0.0", false,
	QObject::tr("gate-bulk overlap capacitance per meter of "
		    "channel length in F/m")));
  Props.append(new Property("Cbd", "0.0 F", false,
	QObject::tr("zero-bias bulk-drain junction capacitance")));
  Props.append(new Property("Cbs", "0.0 F", false,
	QObject::tr("zero-bias bulk-source junction capacitance")));
  Props.append(new Property("Pb", "0.8 V", false,
	QObject::tr("bulk junction potential")));
  Props.append(new Property("Mj", "0.5", false,
	QObject::tr("bulk junction bottom grading coefficient")));
  Props.append(new Property("Fc", "0.5", false,
	QObject::tr("bulk junction forward-bias depletion capacitance "
		    "coefficient")));
  Props.append(new Property("Cjsw", "0.0", false,
	QObject::tr("zero-bias bulk junction periphery capacitance per meter "
		    "of junction perimeter in F/m")));
  Props.append(new Property("Mjsw", "0.33", false,
	QObject::tr("bulk junction periphery grading coefficient")));
  Props.append(new Property("Tt", "0.0 ps", false,
	QObject::tr("bulk transit time")));
  Props.append(new Property("Nsub", "0.0", false,
	QObject::tr("substrate bulk doping density in 1/cm^3")));
  Props.append(new Property("Nss", "0.0", false,
	QObject::tr("surface state density in 1/cm^2")));
  Props.append(new Property("Tpg", "1", false,
	QObject::tr("gate material type: 0 = alumina; -1 = same as bulk; "
		    "1 = opposite to bulk")));
  Props.append(new Property("Uo", "600.0", false,
	QObject::tr("surface mobility in cm^2/Vs")));
  Props.append(new Property("Rsh", "0.0", false,
	QObject::tr("drain and source diffusion sheet resistance in "
		    "Ohms/square")));
  Props.append(new Property("Nrd", "1", false,
	QObject::tr("number of equivalent drain squares")));
  Props.append(new Property("Nrs", "1", false,
	QObject::tr("number of equivalent source squares")));
  Props.append(new Property("Cj", "0.0", false,
	QObject::tr("zero-bias bulk junction bottom capacitance per square "
		    "meter of junction area in F/m^2")));
  Props.append(new Property("Js", "0.0", false,
	QObject::tr("bulk junction saturation current per square "
		    "meter of junction area in A/m^2")));
  Props.append(new Property("Ad", "0.0", false,
	QObject::tr("drain diffusion area in m^2")));
  Props.append(new Property("As", "0.0", false,
	QObject::tr("source diffusion area in m^2")));
  Props.append(new Property("Pd", "0.0 m", false,
	QObject::tr("drain junction perimeter")));
  Props.append(new Property("Ps", "0.0 m", false,
	QObject::tr("source junction perimeter")));
  Props.append(new Property("Kf", "0.0", false,
	QObject::tr("flicker noise coefficient")));
  Props.append(new Property("Af", "1.0", false,
	QObject::tr("flicker noise exponent")));
  Props.append(new Property("Ffe", "1.0", false,
	QObject::tr("flicker noise frequency exponent")));
  Props.append(new Property("Temp", "26.85", false,
	QObject::tr("simulation temperature in degree Celsius")));
  Props.append(new Property("Tnom", "26.85", false,
	QObject::tr("parameter measurement temperature")));

  Name  = "T";
}

MOSFET_sub::MOSFET_sub()
{
  Description = QObject::tr("MOS field-effect transistor with substrate");
  createSymbol();
  tx = x2+4;
  ty = y1+4;
  Model = "MOSFET";
}

Component* MOSFET_sub::newOne()
{
  MOSFET_sub* p = new MOSFET_sub();
  p->Props.first()->Value = Props.first()->Value;
  p->Props.next()->Value = Props.next()->Value;
  p->recreate(0);
  return p;
}

Element* MOSFET_sub::info(QString& Name, char* &BitmapFile, bool getNewOne)
{
  Name = QObject::tr("n-MOSFET");
  BitmapFile = (char *) "nmosfet_sub";

  if(getNewOne)  return new MOSFET_sub();
  return 0;
}

Element* MOSFET_sub::info_p(QString& Name,
			char* &BitmapFile, bool getNewOne)
{
  Name = QObject::tr("p-MOSFET");
  BitmapFile = (char *) "pmosfet_sub";

  if(getNewOne) {
    MOSFET_sub* p = new MOSFET_sub();
    p->Props.first()->Value = "pfet";
    p->Props.next()->Value = "-1.0 V";
    p->recreate(0);
    return p;
  }
  return 0;
}

Element* MOSFET_sub::info_depl(QString& Name,
			char* &BitmapFile, bool getNewOne)
{
  Name = QObject::tr("depletion MOSFET");
  BitmapFile = (char *) "dmosfet_sub";

  if(getNewOne) {
    MOSFET_sub* p = new MOSFET_sub();
    p->Props.first();
    p->Props.next()->Value = "-1.0 V";
    p->recreate(0);
    return p;
  }
  return 0

}

void MOSFET_sub::createSymbol()
{
  Lines.append(new Line(-14,-13,-14, 13,QPen(Qt::darkBlue,3)));
  Lines.append(new Line(-30,  0,-14,  0,QPen(Qt::darkBlue,2)));

  Lines.append(new Line(-10,-11,  0,-11,QPen(Qt::darkBlue,2)));
  Lines.append(new Line(  0,-11,  0,-30,QPen(Qt::darkBlue,2)));
  Lines.append(new Line(-10, 11,  0, 11,QPen(Qt::darkBlue,2)));
  Lines.append(new Line(  0, 11,  0, 30,QPen(Qt::darkBlue,2)));
  Lines.append(new Line(-10,  0, 20,  0,QPen(Qt::darkBlue,2)));

  Lines.append(new Line(-10,-16,-10, -7,QPen(Qt::darkBlue,3)));
  Lines.append(new Line(-10,  7,-10, 16,QPen(Qt::darkBlue,3)));

  Lines.append(new Line( -4, 24,  4, 20,QPen(Qt::darkBlue,2)));

  if(Props.first()->Value == "nfet") {
    Lines.append(new Line( -9,  0, -4, -5,QPen(Qt::darkBlue,2)));
    Lines.append(new Line( -9,  0, -4,  5,QPen(Qt::darkBlue,2)));
  }
  else {
    Lines.append(new Line( -1,  0, -6, -5,QPen(Qt::darkBlue,2)));
    Lines.append(new Line( -1,  0, -6,  5,QPen(Qt::darkBlue,2)));
  }

  if((Props.next()->Value.trimmed().at(0) == '-') ==
     (Props.first()->Value == "nfet"))
    Lines.append(new Line(-10, -8,-10,  8,QPen(Qt::darkBlue,3)));
  else
    Lines.append(new Line(-10, -4,-10,  4,QPen(Qt::darkBlue,3)));

  Ports.append(new Port(-30,  0));
  Ports.append(new Port(  0,-30));
  Ports.append(new Port(  0, 30));
  Ports.append(new Port( 20,  0));

  x1 = -30; y1 = -30;
  x2 =  30; y2 =  30;
}


/***************************************************************************
                              mosfet_sub.cpp
                             ----------------
    begin                : Fri Jun 4 2004
    email                : example@nnthink.com
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *                                                                         *
 ***************************************************************************/

#include "mosfet_sub.h"

Basic_MOSFET::Basic_MOSFET()
{
  // these must be the first properties in the list !!!
  Props.append(new Property("Type", "nfet", false,
	QObject::tr("polarity")+" [nfet, pfet]"));
  Props.append(new Property("Vt0", "1.0 V", true,
	QObject::tr("zero-bias threshold voltage")));

  Props.append(new Property("Kp", "2e-5", true,
	QObject::tr("transconductance coefficient in A/V^2")));
  Props.append(new Property("Gamma", "0.0", false,
	QObject::tr("bulk threshold in sqrt(V)")));
  Props.append(new Property("Phi", "0.6 V", false,
	QObject::tr("surface potential")));
  Props.append(new Property("Lambda", "0.0", true,
	QObject::tr("channel-length modulation parameter in 1/V")));
  Props.append(new Property("Rd", "0.0 Ohm", false,
	QObject::tr("drain ohmic resistance")));
  Props.append(new Property("Rs", "0.0 Ohm", false,
	QObject::tr("source ohmic resistance")));
  Props.append(new Property("Rg", "0.0 Ohm", false,
	QObject::tr("gate ohmic resistance")));
  Props.append(new Property("Is", "1e-14 A", false,
	QObject::tr("bulk junction saturation current")));
  Props.append(new Property("N", "1.0", false,
	QObject::tr("bulk junction emission coefficient")));
  Props.append(new Property("W", "1 um", false,
	QObject::tr("channel width")));
  Props.append(new Property("L", "1 um", false,
	QObject::tr("channel length")));
  Props.append(new Property("Ld", "0.0", false,
	QObject::tr("lateral diffusion length")));
  Props.append(new Property("Tox", "0.1 um", false,
	QObject::tr("oxide thickness")));
  Props.append(new Property("Cgso", "0.0", false,
	QObject::tr("gate-source overlap capacitance per meter of "
		    "channel width in F/m")));
  Props.append(new Property("Cgdo", "0.0", false,
	QObject::tr("gate-drain overlap capacitance per meter of "
		    "channel width in F/m")));
  Props.append(new Property("Cgbo", "0.0", false,
	QObject::tr("gate-bulk overlap capacitance per meter of "
		    "channel length in F/m")));
  Props.append(new Property("Cbd", "0.0 F", false,
	QObject::tr("zero-bias bulk-drain junction capacitance")));
  Props.append(new Property("Cbs", "0.0 F", false,
	QObject::tr("zero-bias bulk-source junction capacitance")));
  Props.append(new Property("Pb", "0.8 V", false,
	QObject::tr("bulk junction potential")));
  Props.append(new Property("Mj", "0.5", false,
	QObject::tr("bulk junction bottom grading coefficient")));
  Props.append(new Property("Fc", "0.5", false,
	QObject::tr("bulk junction forward-bias depletion capacitance "
		    "coefficient")));
  Props.append(new Property("Cjsw", "0.0", false,
	QObject::tr("zero-bias bulk junction periphery capacitance per meter "
		    "of junction perimeter in F/m")));
  Props.append(new Property("Mjsw", "0.33", false,
	QObject::tr("bulk junction periphery grading coefficient")));
  Props.append(new Property("Tt", "0.0 ps", false,
	QObject::tr("bulk transit time")));
  Props.append(new Property("Nsub", "0.0", false,
	QObject::tr("substrate bulk doping density in 1/cm^3")));
  Props.append(new Property("Nss", "0.0", false,
	QObject::tr("surface state density in 1/cm^2")));
  Props.append(new Property("Tpg", "1", false,
	QObject::tr("gate material type: 0 = alumina; -1 = same as bulk; "
		    "1 = opposite to bulk")));
  Props.append(new Property("Uo", "600.0", false,
	QObject::tr("surface mobility in cm^2/Vs")));
  Props.append(new Property("Rsh", "0.0", false,
	QObject::tr("drain and source diffusion sheet resistance in "
		    "Ohms/square")));
  Props.append(new Property("Nrd", "1", false,
	QObject::tr("number of equivalent drain squares")));
  Props.append(new Property("Nrs", "1", false,
	QObject::tr("number of equivalent source squares")));
  Props.append(new Property("Cj", "0.0", false,
	QObject::tr("zero-bias bulk junction bottom capacitance per square "
		    "meter of junction area in F/m^2")));
  Props.append(new Property("Js", "0.0", false,
	QObject::tr("bulk junction saturation current per square "
		    "meter of junction area in A/m^2")));
  Props.append(new Property("Ad", "0.0", false,
	QObject::tr("drain diffusion area in m^2")));
  Props.append(new Property("As", "0.0", false,
	QObject::tr("source diffusion area in m^2")));
  Props.append(new Property("Pd", "0.0 m", false,
	QObject::tr("drain junction perimeter")));
  Props.append(new Property("Ps", "0.0 m", false,
	QObject::tr("source junction perimeter")));
  Props.append(new Property("Kf", "0.0", false,
	QObject::tr("flicker noise coefficient")));
  Props.append(new Property("Af", "1.0", false,
	QObject::tr("flicker noise exponent")));
  Props.append(new Property("Ffe", "1.0", false,
	QObject::tr("flicker noise frequency exponent")));
  Props.append(new Property("Temp", "26.85", false,
	QObject::tr("simulation temperature in degree Celsius")));
  Props.append(new Property("Tnom", "26.85", false,
	QObject::tr("parameter measurement temperature")));

  Name  = "T";
}

MOSFET_sub::MOSFET_sub()
{
  Description = QObject::tr("MOS field-effect transistor with substrate");
  createSymbol();
  tx = x2+4;
  ty = y1+4;
  Model = "MOSFET";
}

Component* MOSFET_sub::newOne()
{
  MOSFET_sub* p = new MOSFET_sub();
  p->Props.first()->Value = Props.first()->Value;
  p->Props.next()->Value = Props.next()->Value;
  p->recreate(0);
  return p;
}

Element* MOSFET_sub::info(QString& Name, char* &BitmapFile, bool getNewOne)
{
  Name = QObject::tr("n-MOSFET");
  BitmapFile = (char *) "nmosfet_sub";

  return 0;
}

Element* MOSFET_sub::info_p(QString& Name,
			char* &BitmapFile, bool getNewOne)
{
  Name = QObject::tr("p-MOSFET");
  BitmapFile = (char *) "pmosfet_sub";

  if(getNewOne) {
    MOSFET_sub* p = new MOSFET_sub();
    p->Props.first()->Value = "pfet";
    p->Props.next()->Value = "-1.0 V";
    p->recreate(0);
    return p;
  }
  return 0;
}

Element* MOSFET_sub::info_depl(QString& Name,
			char* &BitmapFile, bool getNewOne)
{
  Name = QObject::tr("depletion MOSFET");
  BitmapFile = (char *) "dmosfet_sub";

  if(getNewOne) {
    MOSFET_sub* p = new MOSFET_sub();
    p->Props.first();
    p->Props.next()->Value = "-1.0 V";
    p->recreate(0);
    return p;
  }
  return 0;
}

void MOSFET_sub::createSymbol()
{
  Lines.append(new Line(-14,-13,-14, 13,QPen(Qt::darkBlue,3)));
  Lines.append(new Line(-30,  0,-14,  0,QPen(Qt::darkBlue,2)));

  Lines.append(new Line(-10,-11,  0,-11,QPen(Qt::darkBlue,2)));
  Lines.append(new Line(  0,-11,  0,-30,QPen(Qt::darkBlue,2)));
  Lines.append(new Line(-10, 11,  0, 11,QPen(Qt::darkBlue,2)));
  Lines.append(new Line(  0, 11,  0, 30,QPen(Qt::darkBlue,2)));
  Lines.append(new Line(-10,  0, 20,  0,QPen(Qt::darkBlue,2)));

  Lines.append(new Line(-10,-16,-10, -7,QPen(Qt::darkBlue,3)));
  Lines.append(new Line(-10,  7,-10, 16,QPen(Qt::darkBlue,3)));

  Lines.append(new Line( -4, 24,  4, 20,QPen(Qt::darkBlue,2)));

  if(Props.first()->Value == "nfet") {
    Lines.append(new Line( -9,  0, -4, -5,QPen(Qt::darkBlue,2)));
    Lines.append(new Line( -9,  0, -4,  5,QPen(Qt::darkBlue,2)));
  }
  else {
    Lines.append(new Line( -1,  0, -6, -5,QPen(Qt::darkBlue,2)));
    Lines.append(new Line( -1,  0, -6,  5,QPen(Qt::darkBlue,2)));
  }

  if((Props.next()->Value.trimmed().at(0) == '-') ==
     (Props.first()->Value == "nfet"))
    Lines.append(new Line(-10, -8,-10,  8,QPen(Qt::darkBlue,3)));
  else
    Lines.append(new Line(-10, -4,-10,  4,QPen(Qt::darkBlue,3)));

  Ports.append(new Port(-30,  0));
  Ports.append(new Port(  0,-30));
  Ports.append(new Port(  0, 30));
  Ports.append(new Port( 20,  0));

  x1 = -30; y1 = -30;
  x2 =  30; y2 =  30;
}


/***************************************************************************
                              mosfet_sub.cpp
                             ----------------
    begin                : Fri Jun 4 2004
    email                : example@nnthink.com
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *                                                                         *
 ***************************************************************************/

#include "mosfet_sub.h"

Basic_MOSFET::Basic_MOSFET()
{
  // these must be the first properties in the list !!!
  Props.append(new Property("Type", "nfet", false,
	QObject::tr("polarity")+" [nfet, pfet]"));
  Props.append(new Property("Vt0", "1.0 V", true,
	QObject::tr("zero-bias threshold voltage")));

  Props.append(new Property("Kp", "2e-5", true,
	QObject::tr("transconductance coefficient in A/V^2")));
  Props.append(new Property("Gamma", "0.0", false,
	QObject::tr("bulk threshold in sqrt(V)")));
  Props.append(new Property("Phi", "0.6 V", false,
	QObject::tr("surface potential")));
  Props.append(new Property("Lambda", "0.0", true,
	QObject::tr("channel-length modulation parameter in 1/V")));
  Props.append(new Property("Rd", "0.0 Ohm", false,
	QObject::tr("drain ohmic resistance")));
  Props.append(new Property("Rs", "0.0 Ohm", false,
	QObject::tr("source ohmic resistance")));
  Props.append(new Property("Rg", "0.0 Ohm", false,
	QObject::tr("gate ohmic resistance")));
  Props.append(new Property("Is", "1e-14 A", false,
	QObject::tr("bulk junction saturation current")));
  Props.append(new Property("N", "1.0", false,
	QObject::tr("bulk junction emission coefficient")));
  Props.append(new Property("W", "1 um", false,
	QObject::tr("channel width")));
  Props.append(new Property("L", "1 um", false

,
	QObject::tr("channel length")));
  Props.append(new Property("Ld", "0.0", false,
	QObject::tr("lateral diffusion length")));
  Props.append(new Property("Tox", "0.1 um", false,
	QObject::tr("oxide thickness")));
  Props.append(new Property("Cgso", "0.0", false,
	QObject::tr("gate-source overlap capacitance per meter of "
		    "channel width in F/m")));
  Props.append(new Property("Cgdo", "0.0", false,
	QObject::tr("gate-drain overlap capacitance per meter of "
		    "channel width in F/m")));
  Props.append(new Property("Cgbo", "0.0", false,
	QObject::tr("gate-bulk overlap capacitance per meter of "
		    "channel length in F/m")));
  Props.append(new Property("Cbd", "0.0 F", false,
	QObject::tr("zero-bias bulk-drain junction capacitance")));
  Props.append(new Property("Cbs", "0.0 F", false,
	QObject::tr("zero-bias bulk-source junction capacitance")));
  Props.append(new Property("Pb", "0.8 V", false,
	QObject::tr("bulk junction potential")));
  Props.append(new Property("Mj", "0.5", false,
	QObject::tr("bulk junction bottom grading coefficient")));
  Props.append(new Property("Fc", "0.5", false,
	QObject::tr("bulk junction forward-bias depletion capacitance "
		    "coefficient")));
  Props.append(new Property("Cjsw", "0.0", false,
	QObject::tr("zero-bias bulk junction periphery capacitance per meter "
		    "of junction perimeter in F/m")));
  Props.append(new Property("Mjsw", "0.33", false,
	QObject::tr("bulk junction periphery grading coefficient")));
  Props.append(new Property("Tt", "0.0 ps", false,
	QObject::tr("bulk transit time")));
  Props.append(new Property("Nsub", "0.0", false,
	QObject::tr("substrate bulk doping density in 1/cm^3")));
  Props.append(new Property("Nss", "0.0", false,
	QObject::tr("surface state density in 1/cm^2")));
  Props.append(new Property("Tpg", "1", false,
	QObject::tr("gate material type: 0 = alumina; -1 = same as bulk; "
		    "1 = opposite to bulk")));
  Props.append(new Property("Uo", "600.0", false,
	QObject::tr("surface mobility in cm^2/Vs")));
  Props.append(new Property("Rsh", "0.0", false,
	QObject::tr("drain and source diffusion sheet resistance in "
		    "Ohms/square")));
  Props.append(new Property("Nrd", "1", false,
	QObject::tr("number of equivalent drain squares")));
  Props.append(new Property("Nrs", "1", false,
	QObject::tr("number of equivalent source squares")));
  Props.append(new Property("Cj", "0.0", false,
	QObject::tr("zero-bias bulk junction bottom capacitance per square "
		    "meter of junction area in F/m^2")));
  Props.append(new Property("Js", "0.0", false,
	QObject::tr("bulk junction saturation current per square "
		    "meter of junction area in A/m^2")));
  Props.append(new Property("Ad", "0.0", false,
	QObject::tr("drain diffusion area in m^2")));
  Props.append(new Property("As", "0.0", false,
	QObject::tr("source diffusion area in m^2")));
  Props.append(new Property("Pd", "0.0 m", false,
	QObject::tr("drain junction perimeter")));
  Props.append(new Property("Ps", "0.0 m", false,
	QObject::tr("source junction perimeter")));
  Props.append(new Property("Kf", "0.0", false,
	QObject::tr("flicker noise coefficient")));
  Props.append(new Property("Af", "1.0", false,
	QObject::tr("flicker noise exponent")));
  Props.append(new Property("Ffe", "1.0", false,
	QObject::tr("flicker noise frequency exponent")));
  Props.append(new Property("Temp", "26.85", false,
	QObject::tr("simulation temperature in degree Celsius")));
  Props.append(new Property("Tnom", "26.85", false,
	QObject::tr("parameter measurement temperature")));

  Name  = "T";
}

MOSFET_sub::MOSFET_sub()
{
  Description = QObject::tr("MOS field-effect transistor with substrate");
  createSymbol();
  tx = x2+4;
  ty = y1+4;
  Model = "MOSFET";
}

Component* MOSFET_sub::newOne()
{
  MOSFET_sub* p = new MOSFET_sub();
  p->Props.first()->Value = Props.first()->Value;
  p->Props.next()->Value = Props.next()->Value;
  p->recreate(0);
  return p;
}

Element* MOSFET_sub::info(QString& Name, char* &BitmapFile, bool getNewOne)
{
  Name = QObject::tr("n-MOSFET");
  BitmapFile = (char *) "nmosfet_sub";

  if(getNewOne)  return new MOSFET_sub();
  return 0;
}

Element* MOSFET_sub::info_p(QString& Name,
			char* &BitmapFile, bool getNewOne)
{
  Name = QObject::tr("p-MOSFET");
  BitmapFile = (char *) "pmosfet_sub";

  if(getNewOne) {
    MOSFET_sub* p = new MOSFET_sub();
    p->Props.first()->Value = "pfet";
    p->Props.next()->Value = "-1.0 V";
    p->recreate(0);
    return p;
  }
  return 0;
}

Element* MOSFET_sub::info_depl(QString& Name,
			char* &BitmapFile, bool getNewOne)
{
  Name = QObject::tr("depletion MOSFET");
  BitmapFile = (char *) "dmosfet_sub";

  if(getNewOne) {
    MOSFET_sub* p = new MOSFET_sub();
    p->Props.first();
    p->Props.next()->Value = "-1.0 V";
    p->recreate(0);
    return p;
  }
  return 0;
}

void MOSFET_sub::createSymbol()
{
  Lines.append(new Line(-14,-13,-14, 13,QPen(Qt::darkBlue,3)));
  Lines.append(new Line(-30,  0,-14,  0,QPen(Qt::darkBlue,2)));

  Lines.append(new Line(-10,-11,  0,-11,QPen(Qt::darkBlue,2)));
  Lines.append(new Line(  0,-11,  0,-30,QPen(Qt::darkBlue,2)));
  Lines.append(new Line(-10, 11,  0, 11,QPen(Qt::darkBlue,2)));
  Lines.append(new Line(  0, 11,  0, 30,QPen(Qt::darkBlue,2)));
  Lines.append(new Line(-10,  0, 20,  0,QPen(Qt::darkBlue,2)));

  Lines.append(new Line(-10,-16,-10, -7,QPen(Qt::darkBlue,3)));
  Lines.append(new Line(-10,  7,-10, 16,QPen(Qt::darkBlue,3)));

  Lines.append(new Line( -4, 24,  4, 20,QPen(Qt::darkBlue,2)));

  if(Props.first()->Value == "nfet") {
    Lines.append(new Line( -9,  0, -4, -5,QPen(Qt::darkBlue,2)));
    Lines.append(new Line( -9,  0, -4,  5,QPen(Qt::darkBlue,2)));
  }
  else {
    Lines.append(new Line( -1,  0, -6, -5,QPen(Qt::darkBlue,2)));
    Lines.append(new Line( -1,  0, -6,  5,QPen(Qt::darkBlue,2)));
  }

  if((Props.next()->Value.trimmed().at(0) == '-') ==
     (Props.first()->Value == "nfet"))
    Lines.append(new Line(-10, -8,-10,  8,QPen(Qt::darkBlue,3)));
  else
    Lines.append(new Line(-10, -4,-10,  4,QPen(Qt::darkBlue,3)));

  Ports.append(new Port(-30,  0));
  Ports.append(new Port(  0,-30));
  Ports.append(new Port(  0, 30));
  Ports.append(new Port( 20,  0));

  x1 = -30; y1 = -30;
  x2 =  30; y2 =  30;
}


int Solution::hammingDistance(const vector<int> &A)

/*
Hamming distance between two non-negative integers is defined as the number of positions at which the corresponding bits are different.

For example,

HammingDistance(2, 7) = 2, as only the first and the third bit differs in the binary representation of 2 (010) and 7 (111).

Given an array of N non-negative integers, find the sum of hamming distances of all pairs of integers in the array.
Return the answer modulo 1000000007.

Example

Let f(x, y) be the hamming distance defined above.

A=[2, 4, 6]

We return,
f(2, 2) + f(2, 4) + f(2, 6) +
f(4, 2) + f(4, 4) + f(4, 6) +
f(6, 2) + f(6, 4) + f(6, 6) =

0 + 2 + 1
2 + 0 + 1
1 + 1 + 0 = 8

LINK: http://example.com
*/

#define MOD 1000000007

{
    int n=A.size();
    int bit[32];
    memset(bit,0,sizeof(bit));

    for(int i=0;i<n;i++)
    {
        for(int j=0;j<32;j++)
        {
            if((A[i]>>j)&1)
                bit[j]++;
        }
    }

    long long int ans = 0;

    for(int i=0;i<31;i++)
    {
        long long int a = bit[i], b = n-bit[i];
        ans += ((a%MOD)*(b%MOD))%MOD;
    }
    ans = (ans*2)%MOD;

    return ans;
}


{
    int n=A.size();
    int bit[32];
    memset(bit,0,sizeof(bit));

    for(int i=0;i<n;i++)
    {
        for(int j=0;j<32;j++)
        {
            if((A[i]>>j)&1)
                bit[j]++;
        }
    }

    long long int ans = 0;

    for(int i=0;i<31;i++)
    {
        long long int a = bit[i], b = n-bit[i];
        ans += ((a%MOD)*(b%MOD))%MOD;
    }
    ans = (ans*2)%MOD;

    return ans;
}

/*
Hamming distance between two non-negative integers is defined as the number of positions at which the corresponding bits are different.

For example,

HammingDistance(2, 7) = 2, as only the first and the third bit differs in the binary representation of 2 (010) and 7 (111).

Given an array of N non-negative integers, find the sum of hamming distances of all pairs of integers in the array.
Return the answer modulo 1000000007.

Example

Let f(x, y) be the hamming distance defined above.

A=[2, 4, 6]

We return,
f(2, 2) + f(2, 4) + f(2, 6) +
f(4, 2) + f(4, 4) + f(4, 6) +
f(6, 2) + f(6, 4) + f(6, 6) =

0 + 2 + 1
2 + 0 + 1
1 + 1 + 0 = 8

LINK: http://example.com
*/

#define MOD 1000000007

int Solution::hammingDistance(const vector<int> &A)


{
    int n=A.size();
    int bit[32];
    memset(bit,0,sizeof(bit));

    for(int i=0;i<n;i++)
    {
        for(int j=0;j<32;j++)
        {
            if((A[i]>>j)&1)
                bit[j]++;
        }
    }

    long long int ans = 0;

    for(int i=0;i<31;i++)
    {
        long long int a = bit[i], b = n-bit[i];
        ans += ((a%MOD)*(b%MOD))%MOD;
    }
    ans = (ans*2)%MOD;

    return ans;
}


for(int i=0;i<n;i++)
    {
        for(int j=0;j<32;j++)
        {
            if((A[i]>>j)&1)
                bit[j]++;
        }
    }

    long long int ans = 0;

    for(int i=0;i<31;i++)
    {
        long long int a = bit[i], b = n-bit[i];
        ans += ((a%MOD)*(b%MOD))%MOD;
    }

/*
Hamming distance between two non-negative integers is defined as the number of positions at which the corresponding bits are different.

For example,

HammingDistance(2, 7) = 2, as only the first and the third bit differs in the binary representation of 2 (010) and 7 (111).

Given an array of N non-negative integers, find the sum of hamming distances of all pairs of integers in the array.
Return the answer modulo 1000000007.

Example

Let f(x, y) be the hamming distance defined above.

A=[2, 4, 6]

We return,
f(2, 2) + f(2, 4) + f(2, 6) +
f(4, 2) + f(4, 4) + f(4, 6) +
f(6, 2) + f(6, 4) + f(6, 6) =

0 + 2 + 1
2 + 0 + 1
1 + 1 + 0 = 8

LINK: http://example.com
*/

#define MOD 1000000007

int Solution::hammingDistance(const vector<int> &A)
{
    int n=A.size();
    int bit[32];
    memset(bit,0,sizeof(bit));

    ans = (ans*2)%MOD;

    return ans;
}


/*
Hamming distance between two non-negative integers is defined as the number of positions at which the corresponding bits are different.

For example,

HammingDistance(2, 7) = 2, as only the first and the third bit differs in the binary representation of 2 (010) and 7 (111).

Given an array of N non-negative integers, find the sum of hamming distances of all pairs of integers in the array.
Return the answer modulo 1000000007.

Example

Let f(x, y) be the hamming distance defined above.

A=[2, 4, 6]

We return,
f(2, 2) + f(2, 4) + f(2, 6) +
f(4, 2) + f(4, 4) + f(4, 6) +
f(6, 2) + f(6, 4) + f(6, 6) =

0 + 2 + 1
2 + 0 + 1
1 + 1 + 0 = 8

LINK: http://example.com
*/

#define MOD 1000000007

int Solution::hammingDistance(const vector<int> &A)
{
    int n=A.size();
    int bit[32];
    memset(bit,0,sizeof(bit));

    for(int i=0;i<n;i++)
    {
        for(int j=0;j<32;j++)
        {
            if((A[i]>>j)&1)
                bit[j]++;
        }
    }

    long long int ans = 0;

    for(int i=0;i<31;i++)
    {
        long long int a = bit[i], b = n-bit[i];
        ans += ((a%MOD)*(b%MOD))%MOD;
    }


/*
Hamming distance between two non-negative integers is defined as the number of positions at which the corresponding bits are different.

For example,

HammingDistance(2, 7) = 2, as only the first and the third bit differs in the binary representation of 2 (010) and 7 (111).

Given an array of N non-negative integers, find the sum of hamming distances of all pairs of integers in the array.
Return the answer modulo 1000000007.

Example

Let f(x, y) be the hamming distance defined above.

A=[2, 4, 6]

We return,
f(2, 2) + f(2, 4) + f(2, 6) +
f(4, 2) + f(4, 4) + f(4, 6) +
f(6, 2) + f(6, 4) + f(6, 6) =

0 + 2 + 1
2 + 0 + 1
1 + 1 + 0 = 8

LINK: http://example.com
*/

#define MOD 1000000007

int Solution::hammingDistance(const vector<int> &A)
{
    int n=A.size();
    int bit[32];
    memset(bit,0,sizeof(bit));

    for(int i=0;i<n;i++)
    {
        for(int j=0;j<32;j++)
        {
            if((A[i]>>j)&1)
                bit[j]++;
        }
    }

    long long int ans = 0;

    for(int i=0;i<31;i++)
    {
        long long int a = bit[i], b = n-bit[i];
        ans += ((a%MOD)*(b%MOD))%MOD;
    }
    ans = (


/*
Hamming distance between two non-negative integers is defined as the number of positions at which the corresponding bits are different.

For example,

HammingDistance(2, 7) = 2, as only the first and the third bit differs in the binary representation of 2 (010) and 7 (111).

Given an array of N non-negative integers, find the sum of hamming distances of all pairs of integers in the array.
Return the answer modulo 1000000007.

Example

Let f(x, y) be the hamming distance defined above.

A=[2, 4, 6]

We return,
f(2, 2) + f(2, 4) + f(2, 6) +
f(4, 2) + f(4, 4) + f(4, 6) +
f(6, 2) + f(6, 4) + f(6, 6) =

0 + 2 + 1
2 + 0 + 1
1 + 1 + 0 = 8

LINK: http://example.com
*/

#define MOD 1000000007

int Solution::hammingDistance(const vector<int> &A)
{
    int n=A.size();
    int bit[32];
    memset(bit,0,sizeof(bit));

    for(int i=0;i<n;i++)
    {
        for(int j=0;j<32;j++)
        {

        }
    }

    long long int ans = 0;

    for(int i=0;i<31;i++)
    {
        long long int a = bit[i], b = n-bit[i];
        ans += ((a%MOD)*(b%MOD))%MOD;
    }
    ans = (ans*2)%MOD;

    return ans;
}


    long long int ans = 0;

    for(int i=0;i<31;i++)
    {
        long long int a = bit[i], b = n-bit[i];
        ans += ((a%MOD)*(b%MOD))%MOD;
    }
    ans = (ans*2)%MOD;

    return ans;
}


/*
Hamming distance between two non-negative integers is defined as the number of positions at which the corresponding bits are different.

For example,

HammingDistance(2, 7) = 2, as only the first and the third bit differs in the binary representation

of 2 (010) and 7 (111).

Given an array of N non-negative integers, find the sum of hamming distances of all pairs of integers in the array.
Return the answer modulo 1000000007.

Example

Let f(x, y) be the hamming distance defined above.

A=[2, 4, 6]

We return,
f(2, 2) + f(2, 4) + f(2, 6) +
f(4, 2) + f(4, 4) + f(4, 6) +
f(6, 2) + f(6, 4) + f(6, 6) =

0 + 2 + 1
2 + 0 + 1
1 + 1 + 0 = 8

LINK: http://example.com
*/

#define MOD 1000000007

int Solution::hammingDistance(const vector<int> &A)
{
    int n=A.size();
    int bit[32];
    memset(bit,0,sizeof(bit));

    for(int i=0;i<n;i++)
    {
        for(int j=0;j<32;j++)
        {
            if((A[i]>>j)&1)
                bit[j]++;
        }
    }

    long long int ans = 0;

    for(int i=0;i<31;i++)
    {
        long long int a = bit[i], b = n-bit[i];
        ans += ((a%MOD)*(b%MOD))%MOD;
    }
    ans = (ans*2)%MOD;

    return ans;
}


/*
 */

#include "NNPIAdapterContainer.h"

using namespace glow;

NNPIAdapterContainer::~NNPIAdapterContainer() {
  while (!hostResourceMap_.empty()) {
    freeHostResource(hostResourceMap_.begin()->first);
  }

  std::unique_lock<std::shared_timed_mutex> lock(mutex_);
  if (adapter_ != NNPI_INVALID_NNPIHANDLE) {
    LOG_NNPI_INF_IF_ERROR(nnpiAdapterDestroy(adapter_),
                          "Failed to destroy NNPI adapter");
    adapter_ = NNPI_INVALID_NNPIHANDLE;
  }
}

NNPIAdapter NNPIAdapterContainer::getHandle() {
  std::unique_lock<std::shared_timed_mutex> lock(mutex_);
  if (adapter_ == NNPI_INVALID_NNPIHANDLE) {
    LOG_NNPI_INF_IF_ERROR(nnpiAdapterCreate(nullptr, &adapter_),
                          "Failed to create NNPI Adapter");
  }
  return adapter_;
}

{
  CHECK(adapter_ != NNPI_INVALID_NNPIHANDLE);
  NNPIHostResource hostResource = NNPI_INVALID_NNPIHANDLE;
  NNPIResourceDesc desc;
  memset(&desc, 0, sizeof(desc));
  desc.dataType = NNPI_INF_PRECISION_UINT8;
  desc.layout = NNPI_INF_LAYOUT_NC;
  desc.numDims = 2;
  desc.dims[0] = resourceSize;
  desc.dims[1] = 1;

  LOG_NNPI_INF_IF_ERROR(nnpiHostResourceCreate(adapter_, &desc, &hostResource),
                        "Failed to create NNPI host resource");
  if (hostResource == NNPI_INVALID_NNPIHANDLE) {
    return nullptr;
  }

  void *hostPtr = nullptr;
  LOG_NNPI_INF_IF_ERROR(nnpiHostResourceLock(hostResource,
                                             NNPI_LOCKLESS_QUERY_ADDRESS,
                                             UINT32_MAX, &hostPtr),
                        "Failed to lock host resource");
  if (hostPtr == nullptr) {
    return nullptr;
  }

  {
    std::unique_lock<std::shared_timed_mutex> lock(mutex_);
    hostResourceMap_.insert({hostPtr, hostResource});
    return hostPtr;
  }
}

void NNPIAdapterContainer::freeHostResource(void *ptr) {
  std::unique_lock<std::shared_timed_mutex> lock(mutex_);
  if (hostResourceMap_.count(ptr)) {
    LOG_NNPI_INF_IF_ERROR(nnpiHostResourceDestroy(hostResourceMap_.at(ptr)),
                          "Failed to destroy NNPI host resource");
    hostResourceMap_.erase(ptr);
  }
}

NNPIHostResource NNPIAdapterContainer::getResourceForPtr(void *ptr) {
  std::shared_lock<std::shared_timed_mutex> lock(mutex_);
  auto it = hostResourceMap_.find(ptr);
  if (it == hostResourceMap_.end()) {
    return NNPI_INVALID_NNPIHANDLE;
  } else {
    return it->second;
  }
}


{
  std::shared_lock<std::shared_timed_mutex> lock(mutex_);
  auto it = hostResourceMap_.find(ptr);
  if (it == hostResourceMap_.end()) {
    return NNPI_INVALID_NNPIHANDLE;
  } else {
    return it->second;
  }
}

/*
 */

#include "NNPIAdapterContainer.h"

using namespace glow;

NNPIAdapterContainer::~NNPIAdapterContainer() {
  while (!hostResourceMap_.empty()) {
    freeHostResource(hostResourceMap_.begin()->first);
  }

  std::unique_lock<std::shared_timed_mutex> lock(mutex_);
  if (adapter_ != NNPI_INVALID_NNPIHANDLE) {
    LOG_NNPI_INF_IF_ERROR(nnpiAdapterDestroy(adapter_),
                          "Failed to destroy NNPI adapter");
    adapter_ = NNPI_INVALID_NNPIHANDLE;
  }
}

NNPIAdapter NNPIAdapterContainer::getHandle() {
  std::unique_lock<std::shared_timed_mutex> lock(mutex_);
  if (adapter_ == NNPI_INVALID_NNPIHANDLE) {
    LOG_NNPI_INF_IF_ERROR(nnpiAdapterCreate(nullptr, &adapter_),
                          "Failed to create NNPI Adapter");
  }
  return adapter_;
}

void *NNPIAdapterContainer::allocateHostResource(size_t resourceSize) {
  CHECK(adapter_ != NNPI_INVALID_NNPIHANDLE);
  NNPIHostResource hostResource = NNPI_INVALID_NNPIHANDLE;
  NNPIResourceDesc desc;
  memset(&desc, 0, sizeof(desc));
  desc.dataType = NNPI_INF_PRECISION_UINT8;
  desc.layout = NNPI_INF_LAYOUT_NC;
  desc.numDims = 2;
  desc.dims[0] = resourceSize;
  desc.dims[1] = 1;

  LOG_NNPI_INF_IF_ERROR(nnpiHostResourceCreate(adapter_, &desc, &hostResource),
                        "Failed to create NNPI host resource");
  if (hostResource == NNPI_INVALID_NNPIHANDLE) {
    return nullptr;
  }

  void *hostPtr = nullptr;
  LOG_NNPI_INF_IF_ERROR(nnpiHostResourceLock(hostResource,
                                             NNPI_LOCKLESS_QUERY_ADDRESS,
                                             UINT32_MAX, &hostPtr),
                        "Failed to lock host resource");
  if (hostPtr == nullptr) {
    return nullptr;
  }

  {
    std::unique_lock<std::shared_timed_mutex> lock(mutex_);
    hostResourceMap_.insert({hostPtr, hostResource});
    return hostPtr;
  }
}

void NNPIAdapterContainer::freeHostResource(void *ptr) {
  std::unique_lock<std::shared_timed_mutex> lock(mutex_);
  if (hostResourceMap_.count(ptr)) {
    LOG_NNPI_INF_IF_ERROR(nnpiHostResourceDestroy(hostResourceMap_.at(ptr)),
                          "Failed to destroy NNPI host resource");
    hostResourceMap_.erase(ptr);
  }
}

NNPIHostResource NNPIAdapterContainer::getResourceForPtr(void *ptr)


/*
 */

#include "NNPIAdapterContainer.h"

using namespace glow;

NNPIAdapterContainer::~NNPIAdapterContainer() {
  while (!hostResourceMap_.empty()) {
    freeHostResource(hostResourceMap_.begin()->first);
  }

  std::unique_lock<std::shared_timed_mutex> lock(mutex_);
  if (adapter_ != NNPI_INVALID_NNPIHANDLE) {
    LOG_NNPI_INF_IF_ERROR(nnpiAdapterDestroy(adapter_),
                          "Failed to destroy NNPI adapter");
    adapter_ = NNPI_INVALID_NNPIHANDLE;
  }
}

NNPIAdapter NNPIAdapterContainer::getHandle() {
  std::unique_lock<std::shared_timed_mutex> lock(mutex_);
  if (adapter_ == NNPI_INVALID_NNPIHANDLE) {
    LOG_NNPI_INF_IF_ERROR(nnpiAdapterCreate(nullptr, &adapter_),
                          "Failed to create NNPI Adapter");
  }
  return adapter_;
}

void *NNPIAdapterContainer::allocateHostResource(size_t resourceSize) {
  CHECK(adapter_ != NNPI_INVALID_NNPIHANDLE);
  NNPIHostResource hostResource = NNPI_INVALID_NNPIHANDLE;
  NNPIResourceDesc desc;
  memset(&desc, 0, sizeof(desc));
  desc.dataType = NNPI_INF_PRECISION_UINT8;
  desc.layout = NNPI_INF_LAYOUT_NC;
  desc.numDims = 2;
  desc.dims[0] = resourceSize;
  desc.dims[1] = 1;

  LOG_NNPI_INF_IF_ERROR(nnpiHostResourceCreate(adapter_, &desc, &hostResource),
                        "Failed to create NNPI host resource");
  if (hostResource == NNPI_INVALID_NNPIHANDLE) {
    return nullptr;
  }

  void *hostPtr = nullptr;
  LOG_NNPI_INF_IF_ERROR(nnpiHostResourceLock(hostResource,
                                             NNPI_LOCKLESS_QUERY_ADDRESS,
                                             UINT32_MAX, &hostPtr),
                        "Failed to lock host resource");
  if (hostPtr == nullptr) {
    return nullptr;
  }

  {
    std::unique_lock<std::shared_timed_mutex> lock(mutex_);
    hostResourceMap_.insert({hostPtr, hostResource});
    return hostPtr;
  }
}

void NNPIAdapterContainer::freeHostResource(void *ptr)

  if (hostResourceMap_.count(ptr)) {
    LOG_NNPI_INF_IF_ERROR(nnpiHostResourceDestroy(hostResourceMap_.at(ptr)),
                          "Failed to destroy NNPI host resource");
    hostResourceMap_.erase(ptr);
  }
}

NNPIHostResource NNPIAdapterContainer::getResourceForPtr(void *ptr) {
  std::shared_lock<std::shared_timed_mutex> lock(mutex_);
  auto it = hostResourceMap_.find(ptr);
  if (it == hostResourceMap_.end()) {
    return NNPI_INVALID_NNPIHANDLE;
  } else {
    return it->second;
  }
}


if (hostResourceMap_.count(ptr)) {
    LOG_NNPI_INF_IF_ERROR(nnpiHostResourceDestroy(hostResourceMap_.at(ptr)),
                          "Failed to destroy NNPI host resource");
    hostResourceMap_.erase(ptr);
  }

/*
 */

#include "NNPIAdapterContainer.h"

using namespace glow;

NNPIAdapterContainer::~NNPIAdapterContainer() {
  while (!hostResourceMap_.empty()) {
    freeHostResource(hostResourceMap_.begin()->first);
  }

  std::unique_lock<std::shared_timed_mutex> lock(mutex_);
  if (adapter_ != NNPI_INVALID_NNPIHANDLE) {
    LOG_NNPI_INF_IF_ERROR(nnpiAdapterDestroy(adapter_),
                          "Failed to destroy NNPI adapter");
    adapter_ = NNPI_INVALID_NNPIHANDLE;
  }
}

NNPIAdapter NNPIAdapterContainer::getHandle() {
  std::unique_lock<std::shared_timed_mutex> lock(mutex_);
  if (adapter_ == NNPI_INVALID_NNPIHANDLE) {
    LOG_NNPI_INF_IF_ERROR(nnpiAdapterCreate(nullptr, &adapter_),
                          "Failed to create NNPI Adapter");
  }
  return adapter_;
}

void *NNPIAdapterContainer::allocateHostResource(size_t resourceSize) {
  CHECK(adapter_ != NNPI_INVALID_NNPIHANDLE);
  NNPIHostResource hostResource = NNPI_INVALID_NNPIHANDLE;
  NNPIResourceDesc desc;
  memset(&desc, 0, sizeof(desc));
  desc.dataType = NNPI_INF_PRECISION_UINT8;
  desc.layout = NNPI_INF_LAYOUT_NC;
  desc.numDims = 2;
  desc.dims[0] = resourceSize;
  desc.dims[1] = 1;

  LOG_NNPI_INF_IF_ERROR(nnpiHostResourceCreate(adapter_, &desc, &hostResource),
                        "Failed to create NNPI host resource");
  if (hostResource == NNPI_INVALID_NNPIHANDLE) {
    return nullptr;
  }

  void *hostPtr = nullptr;
  LOG_NNPI_INF_IF_ERROR(nnpiHostResourceLock(hostResource,
                                             NNPI_LOCKLESS_QUERY_ADDRESS,
                                             UINT32_MAX, &hostPtr),
                        "Failed to lock host resource");
  if (hostPtr == nullptr) {
    return nullptr;
  }

  {
    std::unique_lock<std::shared_timed_mutex> lock(mutex_);
    hostResourceMap_.insert({hostPtr, hostResource});
    return hostPtr;
  }
}

void NNPIAdapterContainer::freeHostResource(void *ptr) {
  std::unique_lock<std::shared_timed_mutex> lock(mutex_);

}

NNPIHostResource NNPIAdapterContainer::getResourceForPtr(void *ptr) {
  std::shared_lock<std::shared_timed_mutex> lock(mutex_);
  auto it = hostResourceMap_.find(ptr);
  if (it == hostResourceMap_.end()) {
    return NNPI_INVALID_NNPIHANDLE;
  } else {
    return it->second;
  }
}


/*
 */

#include "NNPIAdapterContainer.h"

using namespace glow;

NNPIAdapterContainer::~NNPIAdapterContainer() {
  while (!hostResourceMap_.empty()) {
    freeHostResource(hostResourceMap_.begin()->first);
  }

  std::unique_lock<std::shared_timed_mutex> lock(mutex_);
  if (adapter_ != NNPI_INVALID_NNPIHANDLE) {
    LOG_NNPI_INF_IF_ERROR(nnpiAdapterDestroy(adapter_),
                          "Failed to destroy NNPI adapter");
    adapter_ = NNPI_INVALID_NNPIHANDLE;
  }
}

NNPIAdapter NNPIAdapterContainer::getHandle() {
  std::unique_lock<std::shared_timed_mutex> lock(mutex_);
  if (adapter_ == NNPI_INVALID_NNPIHANDLE) {
    LOG_NNPI_INF_IF_ERROR(nnpiAdapterCreate(nullptr, &adapter_),
                          "Failed to create NNPI Adapter");
  }
  return adapter_;
}

void *NNPIAdapterContainer::allocateHostResource(size_t resourceSize) {
  CHECK(adapter_ != NNPI_INVALID_NNPIHANDLE);
  NNPIHostResource hostResource = NNPI_INVALID_NNPIHANDLE;
  NNPIResourceDesc desc;
  memset(&desc, 0, sizeof(desc));
  desc.dataType = NNPI_INF_PRECISION_UINT8;
  desc.layout = NNPI_INF_LAYOUT_NC;
  desc.numDims = 2;
  desc.dims[0] = resourceSize;
  desc.dims[1] = 1;

  LOG_NNPI_INF_IF_ERROR(nnpiHostResourceCreate(adapter_, &desc, &hostResource),
                        "Failed to create NNPI host resource");
  if (hostResource == NNPI_INVALID_NNPIHANDLE) {
    return nullptr;
  }

  void *hostPtr = nullptr;
  LOG_NNPI_INF_IF_ERROR(nnpiHostResourceLock(hostResource,
                                             NNPI_LOCKLESS_QUERY_ADDRESS,
                                             UINT32_MAX, &hostPtr),
                        "Failed to lock host resource");
  if (hostPtr == nullptr) {
    return nullptr;
  }

  {
    std::unique_lock<std::shared_timed_mutex> lock(mutex_);
    hostResourceMap_.insert({hostPtr, hostResource});
    return hostPtr;
  }
}

void NNPIAdapterContainer::freeHostResource(void *ptr) {
  std::unique_lock<std::shared_timed_mutex> lock(mutex_);
  if (hostResourceMap_.count(ptr)) {
    LOG_NNPI_INF_IF_ERROR(nnpiHostResourceDestroy(hostResourceMap_.at(ptr)),
                          "Failed to destroy NNPI host resource");
    hostResourceMap_.erase(ptr);
  }

NNPIHostResource NNPIAdapterContainer::getResourceForPtr(void *ptr) {
  std::shared_lock<std::shared_timed_mutex> lock(mutex_);
  auto it = hostResourceMap_.find(ptr);
  if (it == hostResourceMap_.end()) {
    return NNPI_INVALID_NNPIHANDLE;
  } else {
    return it->second;
  }
}


/*
 */

#include "NNPIAdapterContainer.h"

using namespace glow;

NNPIAdapterContainer::~NNPIAdapterContainer() {
  while (!hostResourceMap_.empty()) {
    freeHostResource(hostResourceMap_.begin()->first);
  }

  std::unique_lock<std::shared_timed_mutex> lock(mutex_);
  if (adapter_ != NNPI_INVALID_NNPIHANDLE) {
    LOG_NNPI_INF_IF_ERROR(nnpiAdapterDestroy(adapter_),
                          "Failed to destroy NNPI adapter");
    adapter_ = NNPI_INVALID_NNPIHANDLE;
  }
}

NNPIAdapter NNPIAdapterContainer::getHandle() {
  std::unique_lock<std::shared_timed_mutex> lock(mutex_);
  if (adapter_ == NNPI_INVALID_NNPIHANDLE) {
    LOG_NNPI_INF_IF_ERROR(nnpiAdapterCreate(nullptr, &adapter_),
                          "Failed to create NNPI Adapter");
  }
  return adapter_;
}

void *NNPIAdapterContainer::allocateHostResource(size_t resourceSize) {
  CHECK(adapt

  NNPIHostResource hostResource = NNPI_INVALID_NNPIHANDLE;
  NNPIResourceDesc desc;
  memset(&desc, 0, sizeof(desc));
  desc.dataType = NNPI_INF_PRECISION_UINT8;
  desc.layout = NNPI_INF_LAYOUT_NC;
  desc.numDims = 2;
  desc.dims[0] = resourceSize;
  desc.dims[1] = 1;

  LOG_NNPI_INF_IF_ERROR(nnpiHostResourceCreate(adapter_, &desc, &hostResource),
                        "Failed to create NNPI host resource");
  if (hostResource == NNPI_INVALID_NNPIHANDLE) {
    return nullptr;
  }

  void *hostPtr = nullptr;
  LOG_NNPI_INF_IF_ERROR(nnpiHostResourceLock(hostResource,
                                             NNPI_LOCKLESS_QUERY_ADDRESS,
                                             UINT32_MAX, &hostPtr),
                        "Failed to lock host resource");
  if (hostPtr == nullptr) {
    return nullptr;
  }

  {
    std::unique_lock<std::shared_timed_mutex> lock(mutex_);
    hostResourceMap_.insert({hostPtr, hostResource});
    return hostPtr;
  }
}

void NNPIAdapterContainer::freeHostResource(void *ptr) {
  std::unique_lock<std::shared_timed_mutex> lock(mutex_);
  if (hostResourceMap_.count(ptr)) {
    LOG_NNPI_INF_IF_ERROR(nnpiHostResourceDestroy(hostResourceMap_.at(ptr)),
                          "Failed to destroy NNPI host resource");
    hostResourceMap_.erase(ptr);
  }
}

NNPIHostResource NNPIAdapterContainer::getResourceForPtr(void *ptr) {
  std::shared_lock<std::shared_timed_mutex> lock(mutex_);
  auto it = hostResourceMap_.find(ptr);
  if (it == hostResourceMap_.end()) {
    return NNPI_INVALID_NNPIHANDLE;
  } else {
    return it->second;
  }
}


if (hostResource == NNPI_INVALID_NNPIHANDLE) {
    return nullptr;
  }

/*
 */

#include "NNPIAdapterContainer.h"

using namespace glow;

NNPIAdapterContainer::~NNPIAdapterContainer() {
  while (!hostResourceMap_.empty()) {
    freeHostResource(hostResourceMap_.begin()->first);
  }

  std::unique_lock<std::shared_timed_mutex> lock(mutex_);
  if (adapter_ != NNPI_INVALID_NNPIHANDLE) {
    LOG_NNPI_INF_IF_ERROR(nnpiAdapterDestroy(adapter_),
                          "Failed to destroy NNPI adapter");
    adapter_ = NNPI_INVALID_NNPIHANDLE;
  }
}

NNPIAdapter NNPIAdapterContainer::getHandle() {
  std::unique_lock<std::shared_timed_mutex> lock(mutex_);
  if (adapter_ == NNPI_INVALID_NNPIHANDLE) {
    LOG_NNPI_INF_IF_ERROR(nnpiAdapterCreate(nullptr, &adapter_),
                          "Failed to create NNPI Adapter");
  }
  return adapter_;
}

void *NNPIAdapterContainer::allocateHostResource(size_t resourceSize) {
  CHECK(adapter_ != NNPI_INVALID_NNPIHANDLE);
  NNPIHostResource hostResource = NNPI_INVALID_NNPIHANDLE;
  NNPIResourceDesc desc;
  memset(&desc, 0, sizeof(desc));
  desc.dataType = NNPI_INF_PRECISION_UINT8;
  desc.layout = NNPI_INF_LAYOUT_NC;
  desc.numDims = 2;
  desc.dims[0] = resourceSize;
  desc.dims[1] = 1;

  LOG_NNPI_INF_IF_ERROR(nnpiHostResourceCreate(adapter_, &desc, &hostResource),
                        "Failed to create NNPI host resource");

  void *hostPtr = nullptr;
  LOG_NNPI_INF_IF_ERROR(nnpiHostResourceLock(hostResource,
                                             NNPI_LOCKLESS_QUERY_ADDRESS,
                                             UINT32_MAX, &hostPtr),
                        "Failed to lock host resource");
  if (hostPtr == nullptr) {
    return nullptr;
  }

  {
    std::unique_lock<std::shared_timed_mutex> lock(mutex_);
    hostResourceMap_.insert({hostPtr, hostResource});
    return hostPtr;
  }
}

void NNPIAdapterContainer::freeHostResource(void *ptr) {
  std::unique_lock<std::shared_timed_mutex> lock(mutex_);
  if (hostResourceMap_.count(ptr)) {
    LOG_NNPI_INF_IF_ERROR(nnpiHostResourceDestroy(hostResourceMap_.at(ptr)),
                          "Failed to destroy NNPI host resource");
    hostResourceMap_.erase(ptr);
  }
}

NNPIHostResource NNPIAdapterContainer::getResourceForPtr(void *ptr) {
  std::shared_lock<std::shared_timed_mutex> lock(mutex_);
  auto it = hostResourceMap_.find(ptr);
  if (it == hostResourceMap_.end()) {
    return NNPI_INVALID_NNPIHANDLE;
  } else {
    return it->second;
  }
}


while (!hostResourceMap_.empty()) {
    freeHostResource(hostResourceMap_.begin()->first);
  }

/*
 */

#include "NNPIAdapterContainer.h"

using namespace glow;

NNPIAdapterContainer::~NNPIAdapterContainer() {

  std::unique_lock<std::shared_timed_mutex> lock(mutex_);
  if (adapter_ != NNPI_INVALID_NNPIHANDLE) {
    LOG_NNPI_INF_IF_ERROR(nnpiAdapterDestroy(adapter_),
                          "Failed to destroy NNPI adapter");
    adapter_ = NNPI_INVALID_NNPIHANDLE;
  }
}

NNPIAdapter NNPIAdapterContainer::getHandle() {
  std::unique_lock<std::shared_timed_mutex> lock(mutex_);
  if (adapter_ == NNPI_INVALID_NNPIHANDLE) {
    LOG_NNPI_INF_IF_ERROR(nnpiAdapterCreate(nullptr, &adapter_),
                          "Failed to create NNPI Adapter");
  }
  return adapter_;
}

void *NNPIAdapterContainer::allocateHostResource(size_t resourceSize) {
  CHECK(adapter_ != NNPI_INVALID_NNPIHANDLE);
  NNPIHostResource hostResource = NNPI_INVALID_NNPIHANDLE;
  NNPIResourceDesc desc;
  memset(&desc, 0, sizeof(desc));
  desc.dataType = NNPI_INF_PRECISION_UINT8;
  desc.layout = NNPI_INF_LAYOUT_NC;
  desc.numDims = 2;
  desc.dims[0] = resourceSize;
  desc.dims[1] = 1;

  LOG_NNPI_INF_IF_ERROR(nnpiHostResourceCreate(adapter_, &desc, &hostResource),
                        "Failed to create NNPI host resource");
  if (hostResource == NNPI_INVALID_NNPIHANDLE) {
    return nullptr;
  }

  void *hostPtr = nullptr;
  LOG_NNPI_INF_IF_ERROR(nnpiHostResourceLock(hostResource,
                                             NNPI_LOCKLESS_QUERY_ADDRESS,
                                             UINT32_MAX, &hostPtr),
                        "Failed to lock host resource");
  if (hostPtr == nullptr) {
    return nullptr;
  }

  {
    std::unique_lock<std::shared_timed_mutex> lock(mutex_);
    hostResourceMap_.insert({hostPtr, hostResource});
    return hostPtr;
  }
}

void NNPIAdapterContainer::freeHostResource(void *ptr) {
  std::unique_lock<std::shared_timed_mutex> lock(mutex_);
  if (hostResourceMap_.count(ptr)) {
    LOG_NNPI_INF_IF_ERROR(nnpiHostResourceDestroy(hostResourceMap_.at(ptr)),
                          "Failed to destroy NNPI host resource");
    hostResourceMap_.erase(ptr);
  }
}

NNPIHostResource NNPIAdapterContainer::getResourceForPtr(void *ptr) {
  std::shared_lock<std::shared_timed_mutex> lock(mutex_);
  auto it = hostResourceMap_.find(ptr);
  if (it == hostResourceMap_.end()) {
    return NNPI_INVALID_NNPIHANDLE;
  } else {
    return it->second;
  }
}


/*
 */

#include "NNPIAdapterContainer.h"

using namespace glow;

NNPIAdapterContainer::~NNPIAdapterContainer() {
  while (!hostResourceMap_.empty()) {
    freeHostResource(hostResourceMap_.begin()->first);
  }

  std::unique_lock<std::shared_timed_mutex> lock(mutex_);
  if (adapter_ != NNPI_INVALID_NNPIHANDLE) {
    LOG_NNPI_INF_IF_ERROR(nnpiAdapterDestroy(adapter_),
                          "Failed to destroy NNPI a

dapter");
    adapter_ = NNPI_INVALID_NNPIHANDLE;
  }
}

NNPIAdapter NNPIAdapterContainer::getHandle() {
  std::unique_lock<std::shared_timed_mutex> lock(mutex_);
  if (adapter_ == NNPI_INVALID_NNPIHANDLE) {
    LOG_NNPI_INF_IF_ERROR(nnpiAdapterCreate(nullptr, &adapter_),
                          "Failed to create NNPI Adapter");
  }
  return adapter_;
}

void *NNPIAdapterContainer::allocateHostResource(size_t resourceSize) {
  CHECK(adapter_ != NNPI_INVALID_NNPIHANDLE);
  NNPIHostResource hostResource = NNPI_INVALID_NNPIHANDLE;
  NNPIResourceDesc desc;
  memset(&desc, 0, sizeof(desc));
  desc.dataType = NNPI_INF_PRECISION_UINT8;
  desc.layout = NNPI_INF_LAYOUT_NC;
  desc.numDims = 2;
  desc.dims[0] = resourceSize;
  desc.dims[1] = 1;

  LOG_NNPI_INF_IF_ERROR(nnpiHostResourceCreate(adapter_, &desc, &hostResource),
                        "Failed to create NNPI host resource");
  if (hostResource == NNPI_INVALID_NNPIHANDLE) {
    return nullptr;
  }

  void *hostPtr = nullptr;
  LOG_NNPI_INF_IF_ERROR(nnpiHostResourceLock(hostResource,
                                             NNPI_LOCKLESS_QUERY_ADDRESS,
                                             UINT32_MAX, &hostPtr),
                        "Failed to lock host resource");
  if (hostPtr == nullptr) {
    return nullptr;
  }

  {
    std::unique_lock<std::shared_timed_mutex> lock(mutex_);
    hostResourceMap_.insert({hostPtr, hostResource});
    return hostPtr;
  }
}

void NNPIAdapterContainer::freeHostResource(void *ptr) {
  std::unique_lock<std::shared_timed_mutex> lock(mutex_);
  if (hostResourceMap_.count(ptr)) {
    LOG_NNPI_INF_IF_ERROR(nnpiHostResourceDestroy(hostResourceMap_.at(ptr)),
                          "Failed to destroy NNPI host resource");
    hostResourceMap_.erase(ptr);
  }
}

NNPIHostResource NNPIAdapterContainer::getResourceForPtr(void *ptr) {
  std::shared_lock<std::shared_timed_mutex> lock(mutex_);
  auto it = hostResourceMap_.find(ptr);
  if (it == hostResourceMap_.end()) {
    return NNPI_INVALID_NNPIHANDLE;
  } else {
    return it->second;
  }
}


// Buffer.cpp: Implements the gl::Buffer class, representing storage of vertex and/or
// index data. Implements GL buffer objects and related functionality.

#include "libANGLE/Buffer.h"
#include "libANGLE/renderer/BufferImpl.h"
#include "libANGLE/renderer/Renderer.h"

namespace gl
{

Buffer::Buffer(rx::BufferImpl *impl, GLuint id)
    : RefCountObject(id),
      mBuffer(impl),
      mUsage(GL_STATIC_DRAW),
      mSize(0),
      mAccessFlags(0),
      mAccess(GL_WRITE_ONLY_OES),
      mMapped(GL_FALSE),
      mMapPointer(NULL),
      mMapOffset(0),
      mMapLength(0)
{
}

Buffer::~Buffer()
{
    SafeDelete(mBuffer);
}

Error Buffer::bufferData(const void *data, GLsizeiptr size, GLenum usage)
{
    gl::Error error = mBuffer->setData(data, size, usage);
    if (error.isError())
    {
        return error;
    }

    mIndexRangeCache.clear();
    mUsage = usage;
    mSize = size;

    return error;
}

Error Buffer::bufferSubData(const void *data, GLsizeiptr size, GLintptr offset)
{
    gl::Error error = mBuffer->setSubData(data, size, offset);
    if (error.isError())
    {
        return error;
    }

    mIndexRangeCache.invalidateRange(static_cast<unsigned int>(offset), static_cast<unsigned int>(size));

    return error;
}

Error Buffer::copyBufferSubData(Buffer* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size)
{
    gl::Error error = mBuffer->copySubData(source->getImplementation(), sourceOffset, destOffset, size);
    if (error.isError())
    {
        return error;
    }

    mIndexRangeCache.invalidateRange(static_cast<unsigned int>(destOffset), static_cast<unsigned int>(size));

    return error;
}

{
    ASSERT(!mMapped);

    Error error = mBuffer->map(access, &mMapPointer);
    if (error.isError())
    {
        mMapPointer = NULL;
        return error;
    }

    ASSERT(access == GL_WRITE_ONLY_OES);

    mMapped = GL_TRUE;
    mMapOffset = 0;
    mMapLength = mSize;
    mAccess = access;
    mAccessFlags = GL_MAP_WRITE_BIT;

    mIndexRangeCache.invalidateRange(0, static_cast<unsigned int>(mMapLength));

    return error;
}

Error Buffer::mapRange(GLintptr offset, GLsizeiptr length, GLbitfield access)
{
    ASSERT(!mMapped);
    ASSERT(offset + length <= mSize);

    Error error = mBuffer->mapRange(offset, length, access, &mMapPointer);
    if (error.isError())
    {
        mMapPointer = NULL;
        return error;
    }

    mMapped = GL_TRUE;
    mMapOffset = static_cast<GLint64>(offset);
    mMapLength = static_cast<GLint64>(length);
    mAccess = GL_WRITE_ONLY_OES;
    mAccessFlags = access;

    // The OES_mapbuffer extension states that GL_WRITE_ONLY_OES is the only valid
    // value for GL_BUFFER_ACCESS_OES because it was written against ES2.  Since there is
    // no update for ES3 and the GL_READ_ONLY and GL_READ_WRITE enums don't exist for ES,
    // we cannot properly set GL_BUFFER_ACCESS_OES when glMapBufferRange is called.

    if ((access & GL_MAP_WRITE_BIT) > 0)
    {
        mIndexRangeCache.invalidateRange(static_cast<unsigned int>(offset), static_cast<unsigned int>(length));
    }

    return error;
}

Error Buffer::unmap(GLboolean *result)
{
    ASSERT(mMapped);

    Error error = mBuffer->unmap(result);
    if (error.isError())
    {
        *result = GL_FALSE;
        return error;
    }

    mMapped = GL_FALSE;
    mMapPointer = NULL;
    mMapOffset = 0;
    mMapLength = 0;
    mAccess = GL_WRITE_ONLY_OES;
    mAccessFlags = 0;

    return error;
}

}


{
    gl::Error error = mBuffer->setData(data, size, usage);
    if (error.isError())
    {
        return error;
    }

    mIndexRangeCache.clear();
    mUsage = usage;
    mSize = size;

    return error;
}

// Buffer.cpp: Implements the gl::Buffer class, representing storage of vertex and/or
// index data. Implements GL buffer objects and related functionality.

#include "libANGLE/Buffer.h"
#include "libANGLE/renderer/BufferImpl.h"
#include "libANGLE/renderer/Renderer.h"

namespace gl
{

Buffer::Buffer(rx::BufferImpl *impl, GLuint id)
    : RefCountObject(id),
      mBuffer(impl),
      mUsage(GL_STATIC_DRAW),
      mSize(0),
      mAccessFlags(0),
      mAccess(GL_WRITE_ONLY_OES),
      mMapped(GL_FALSE),
      mMapPointer(NULL),
      mMapOffset(0),
      mMapLength(0)
{
}

Buffer::~Buffer()
{
    SafeDelete(mBuffer);
}

Error Buffer::bufferData(const void *data, GLsizeiptr size, GLenum usage)

Error Buffer::bufferSubData(const void *data, GLsizeiptr size, GLintptr offset)
{
    gl::Error error = mBuffer->setSubData(data, size, offset);
    if (error.isError())
    {
        return error;
    }

    mIndexRangeCache.invalidateRange(static_cast<unsigned int>(offset), static_cast<unsigned int>(size));

    return error;
}

Error Buffer::copyBufferSubData(Buffer* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size)
{
    gl::Error error = mBuffer->copySubData(source->getImplementation(), sourceOffset, destOffset, size);
    if (error.isError())
    {
        return error;
    }

    mIndexRangeCache.invalidateRange(static_cast<unsigned int>(destOffset), static_cast<unsigned int>(size));

    return error;
}

Error Buffer::map(GLenum access)
{
    ASSERT(!mMapped);

    Error error = mBuffer->map(access, &mMapPointer);
    if (error.isError())
    {
        mMapPointer = NULL;
        return error;
    }

    ASSERT(access == GL_WRITE_ONLY_OES);

    mMapped = GL_TRUE;
    mMapOffset = 0;
    mMapLength = mSize;
    mAccess = access;
    mAccessFlags = GL_MAP_WRITE_BIT;

    mIndexRangeCache.invalidateRange(0, static_cast<unsigned int>(mMapLength));

    return error;
}

Error Buffer::mapRange(GLintptr offset, GLsizeiptr length, GLbitfield access)
{
    ASSERT(!mMapped);
    ASSERT(offset + length <= mSize);

    Error error = mBuffer->mapRange(offset, length, access, &mMapPointer);
    if (error.isError())
    {
        mMapPointer = NULL;
        return error;
    }

    mMapped = GL_TRUE;
    mMapOffset = static_cast<GLint64>(offset);
    mMapLength = static_cast<GLint64>(length);
    mAccess = GL_WRITE_ONLY_OES;
    mAccessFlags = access;

    // The OES_mapbuffer extension states that GL_WRITE_ONLY_OES is the only valid
    // value for GL_BUFFER_ACCESS_OES because it was written against ES2.  Since there is
    // no update for ES3 and the GL_READ_ONLY and GL_READ_WRITE enums don't exist for ES,
    // we cannot properly set GL_BUFFER_ACCESS_OES when glMapBufferRange is called.

    if ((access & GL_MAP_WRITE_BIT) > 0)
    {
        mIndexRangeCache.invalidateRange(static_cast<unsigned int>(offset), static_cast<unsigned int>(length));
    }

    return error;
}

Error Buffer::unmap(GLboolean *result)
{
    ASSERT(mMapped);

    Error error = mBuffer->unmap(result);
    if (error.isError())
    {
        *result = GL_FALSE;
        return error;
    }

    mMapped = GL_FALSE;
    mMapPointer = NULL;
    mMapOffset = 0;
    mMapLength = 0;
    mAccess = GL_WRITE_ONLY_OES;
    mAccessFlags = 0;

    return error;
}

}


{
    ASSERT(mMapped);

    Error error = mBuffer->unmap(result);
    if (error.isError())
    {
        *result = GL_FALSE;
        return error;
    }

// Buffer.cpp: Implements the gl::Buffer class, representing storage of vertex and/or
// index data. Implements GL buffer objects and related functionality.

#include "libANGLE/Buffer.h"
#include "libANGLE/renderer/BufferImpl.h"
#include "libANGLE/renderer/Renderer.h"

namespace gl
{

Buffer::Buffer(rx::BufferImpl *impl, GLuint id)
    : RefCountObject(id),
      mBuffer(impl),
      mUsage(GL_STATIC_DRAW),
      mSize(0),
      mAccessFlags(0),
      mAccess(GL_WRITE_ONLY_OES),
      mMapped(GL_FALSE),
      mMapPointer(NULL),
      mMapOffset(0),
      mMapLength(0)
{
}

Buffer::~Buffer()
{
    SafeDelete(mBuffer);
}

Error Buffer::bufferData(const void *data, GLsizeiptr size, GLenum usage)
{
    gl::Error error = mBuffer->setData(data, size, usage);
    if (error.isError())
    {
        return error;
    }

    mIndexRangeCache.clear();
    mUsage = usage;
    mSize = size;

    return error;
}

Error Buffer::bufferSubData(const void *data, GLsizeiptr size, GLintptr offset)
{
    gl::Error error = mBuffer->setSubData(data, size, offset);
    if (error.isError())
    {
        return error;
    }

    mIndexRangeCache.invalidateRange(static_cast<unsigned int>(offset), static_cast<unsigned int>(size));

    return error;
}

Error Buffer::copyBufferSubData(Buffer* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size)
{
    gl::Error error = mBuffer->copySubData(source->getImplementation(), sourceOffset, destOffset, size);
    if (error.isError())
    {
        return error;
    }

    mIndexRangeCache.invalidateRange(static_cast<unsigned int>(destOffset), static_cast<unsigned int>(size));

    return error;
}

Error Buffer::map(GLenum access)
{
    ASSERT(!mMapped);

    Error error = mBuffer->map(access, &mMapPointer);
    if (error.isError())
    {
        mMapPointer = NULL;
        return error;
    }

    ASSERT(access == GL_WRITE_ONLY_OES);

    mMapped = GL_TRUE;
    mMapOffset = 0;
    mMapLength = mSize;
    mAccess = access;
    mAccessFlags = GL_MAP_WRITE_BIT;

    mIndexRangeCache.invalidateRange(0, static_cast<unsigned int>(mMapLength));

    return error;
}

Error Buffer::mapRange(GLintptr offset, GLsizeiptr length, GLbitfield access)
{
    ASSERT(!mMapped);
    ASSERT(offset + length <= mSize);

    Error error = mBuffer->mapRange(offset, length, access, &mMapPointer);
    if (error.isError())
    {
        mMapPointer = NULL;
        return error;
    }

    mMapped = GL_TRUE;
    mMapOffset = static_cast<GLint64>(offset);
    mMapLength = static_cast<GLint64>(length);
    mAccess = GL_WRITE_ONLY_OES;
    mAccessFlags = access;

    // The OES_mapbuffer extension states that GL_WRITE_ONLY_OES is the only valid
    // value for GL_BUFFER_ACCESS_OES because it was written against ES2.  Since there is
    // no update for ES3 and the GL_READ_ONLY and GL_READ_WRITE enums don't exist for ES,
    // we cannot properly set GL_BUFFER_ACCESS_OES when glMapBufferRange is called.

    if ((access & GL_MAP_WRITE_BIT) > 0)
    {
        mIndexRangeCache.invalidateRange(static_cast<unsigned int>(offset), static_cast<unsigned int>(length));
    }

    return error;
}

Error Buffer::unmap(GLboolean *result)

    mMapped = GL_FALSE;
    mMapPointer = NULL;
    mMapOffset = 0;
    mMapLength = 0;
    mAccess = GL_WRITE_ONLY_OES;
    mAccessFlags = 0;

    return error;
}

}