Пример #1
0
	IMatrix INodeLight::GetProjectionMatrix(int i)
	{
		IMatrix invRot;
		//Spot
		/*invRot = GetRotationMatrix4x4();
		invRot.Inv(invRot);*/
		//Omni
		if (i==0)
		{
			invRot.MakeIdentity();
			invRot=AngleYToMatrix4x4(0);
		}else if (i==1)
		{
			invRot=AngleYToMatrix4x4(I_PIE);
		}else if (i==2)
		{
			invRot=AngleYToMatrix4x4(I_PIE/2.0);
		}else if (i==3)
		{
			invRot=AngleYToMatrix4x4(-I_PIE/2.0);
		}else if (i==4)
		{
			invRot=AngleXToMatrix4x4(I_PIE/2.0);
		}else if (i==5)
		{
			invRot=AngleXToMatrix4x4(-I_PIE/2.0);
		}
		IMatrix mat = GetPerspectiveMatrix(90,1,m_fRadius,0.01)*invRot*TranslationToMatrix(-GetPosition());
		return mat;
	}
Пример #2
0
boolean OpenViBEToolkit::Tools::ColorGradient::format(CString& rString, const IMatrix& rColorGradient)
{
	if(rColorGradient.getDimensionCount() != 2)
	{
		return false;
	}

	if(rColorGradient.getDimensionSize(0) != 4)
	{
		return false;
	}

	std::string l_sSeparator("  ");
	l_sSeparator[0]=OV_Value_EnumeratedStringSeparator;

	std::string l_sResult;
	for(uint32 i=0; i<rColorGradient.getDimensionSize(1); i++)
	{
		char l_sBuffer[1024];
		sprintf(
			l_sBuffer,
			"%.0lf:%i,%i,%i",
			rColorGradient[i*4],
			(int)rColorGradient[i*4+1],
			(int)rColorGradient[i*4+2],
			(int)rColorGradient[i*4+3]);
		l_sResult+=(i==0?"":l_sSeparator);
		l_sResult+=l_sBuffer;
	}

	rString=l_sResult.c_str();
	return true;
}
Пример #3
0
bool IMatrix::Dot(IMatrix b,IMatrix &res)
{
	IMatrix temp;
	if (Width==b.Height)
	{
		int resW = b.Width;
		int resH = Height;

		temp.SetSize(resW,resH);

		double val;
		for (int i=0;i<resW;i++)
		{
			for (int j=0;j<resH;j++)	
			{
				val=0;
				for (int k=0;k<Width;k++)
				{
					val+=GetValue(k,j)*b.GetValue(i,k);
				}
				temp.SetValue(i,j,val);
			}
		}
		res=temp;
		return true;
	}
	return false;
}
Пример #4
0
bool CMessageWithData::setValueIMatrix(const CString &key, const IMatrix &valueIn) {

    CMatrix *l_pMatrix = new CMatrix();
    // we copy 'manually' since we do not have access to the toolkit functions
    const uint32 l_ui32DimensionCount = valueIn.getDimensionCount();
    l_pMatrix->setDimensionCount(l_ui32DimensionCount);
    for (uint32 i=0; i<l_ui32DimensionCount; i++)
    {
        const uint32 l_ui32DimensionSize = valueIn.getDimensionSize(i);
        l_pMatrix->setDimensionSize(i,l_ui32DimensionSize);
        for (uint32 j=0; j<l_ui32DimensionSize; j++)
        {
            const char* l_cLabel = valueIn.getDimensionLabel(i,j);
            l_pMatrix->setDimensionLabel(i,j,l_cLabel);
        }
    }

    float64* l_pBuffer = l_pMatrix->getBuffer();
    for (uint32 i=0; i<valueIn.getBufferElementCount(); i++)
    {
        l_pBuffer[i] = valueIn.getBuffer()[i];
    }

    m_oMatrices[key] = l_pMatrix;

    return true;
}
Пример #5
0
 inline HMatrix() : gm(0) {
  int gms = 2;
  IArray r(gms, 1);
  gm.reserve(gms);
  gm.push_back(r); 
  r[gms - 1] = -1;
  gm.push_back(r); 
 }
	itpp::mat convert(const IMatrix& rMatrix)
	{
		itpp::mat l_oResult(
			rMatrix.getDimensionSize(1),
			rMatrix.getDimensionSize(0));
		System::Memory::copy(l_oResult._data(), rMatrix.getBuffer(), rMatrix.getBufferElementCount()*sizeof(float64));
		return l_oResult.transpose();
	}
Пример #7
0
IMatrix IMatrix::Transpose()
{
	IMatrix res;
	res.SetSize(Height,Width);
	for (int i=0;i<Width;i++)
		for (int j=0;j<Height;j++)
			res[j][i]=(*this)[i][j];

	return IMatrix(res);
}
Пример #8
0
RowChecksumMatrix<T>::RowChecksumMatrix(IMatrix<T>& M) :
Matrix<T>(M.getData(), M.getM(), M.getN() + 1),
matrix(M),
rowSummationVector(*(new Vector<TYPE_SUM>(this->getM(), false))),
dataAllocation(true) {
	for(int i = 1; i <= this->getM(); i++) {
		rowSummationVector(i) = 0;
		rowSummationVector(i) = computeRowSum(i);
	}
}
Пример #9
0
template <class T1, class T2, class T3> void CalculatorNaiveAdd(IMatrix<T1>& Res, const IMatrix<T2>& A, const IMatrix<T3>& B) {
	// Vérifications
	if(!(A.getM() == B.getM() && A.getM() == Res.getM()
		 && A.getN() == B.getN() && A.getN() == Res.getN())) throw domain_error("addition impossible");

	for(int i = 1; i <= Res.getM(); i++){
		for(int j = 1; j <= Res.getN(); j++) {
			Res(i, j) = A(i, j).toTypeSum() + B(i, j).toTypeSum();
		}
	}
}
Пример #10
0
boolean OpenViBEToolkit::Tools::Matrix::isContentValid(const IMatrix& rSourceMatrix, const boolean bCheckNotANumber, const boolean bCheckInfinity)
{
	const float64* l_pBuffer=rSourceMatrix.getBuffer();
	const float64* l_pBufferEnd=rSourceMatrix.getBuffer()+rSourceMatrix.getBufferElementCount();
	while(l_pBuffer!=l_pBufferEnd)
	{
		if(bCheckNotANumber && isnan(*l_pBuffer)) return false;
		if(bCheckInfinity && isinf(*l_pBuffer)) return false;
		l_pBuffer++;
	}
	return true;
}
Пример #11
0
boolean OpenViBEToolkit::Tools::Matrix::isContentSimilar(const IMatrix& rSourceMatrix1, const IMatrix& rSourceMatrix2)
{
	if(&rSourceMatrix1==&rSourceMatrix2)
	{
		return true;
	}

	if(rSourceMatrix1.getBufferElementCount() != rSourceMatrix2.getBufferElementCount())
	{
		return false;
	}

	return ::memcmp(rSourceMatrix1.getBuffer(), rSourceMatrix2.getBuffer(), rSourceMatrix1.getBufferElementCount()*sizeof(float64)) == 0;
}
Пример #12
0
inline int KronProd(const IMatrix &im1, const IMatrix &im2, IMatrix &om) {
 int sim1 = im1.size(), sim2 = im2.size(), som = sim1 * sim2;
 om.clear();
 om.reserve(som);
 for(int i = 0; i < som; ++i) {
  IArray r(0);
  r.reserve(som);
  for(int j = 0; j < som; ++j) {
   r.push_back(im1[i % sim1][j % sim1] * im2[i / sim1][j / sim1]);
  }
  om.push_back(r);
 }
 return som;
}
Пример #13
0
boolean OpenViBEToolkit::Tools::ColorGradient::parse(IMatrix& rColorGradient, const CString& rString)
{
	std::string l_sString(rString.toASCIIString());
	std::string::size_type l_iStart=0;
	std::string::size_type l_iEnd;

	std::map < float64, SColor > l_vColorGradient;

	do
	{
		l_iEnd=l_sString.find(OV_Value_EnumeratedStringSeparator, l_iStart);
		if(l_iEnd==std::string::npos)
		{
			l_iEnd=l_sString.length();
		}

		std::string l_sColor;
		l_sColor.assign(l_sString, l_iStart, l_iEnd-l_iStart);

		int p,r,g,b;
		if(sscanf(l_sColor.c_str(), "%i:%i,%i,%i", &p, &r, &g, &b) == 4)
		{
			SColor l_oColor;
			l_oColor.fPercent=p;
			l_oColor.fRed=r;
			l_oColor.fGreen=g;
			l_oColor.fBlue=b;
			l_vColorGradient[l_oColor.fPercent]=l_oColor;
		}

		l_iStart=l_iEnd+1;
	}
	while(l_iStart<l_sString.length());

	rColorGradient.setDimensionCount(2);
	rColorGradient.setDimensionSize(0, 4);
	rColorGradient.setDimensionSize(1, l_vColorGradient.size());

	uint32 i=0;
	std::map < float64, SColor > ::const_iterator it;
	for(it=l_vColorGradient.begin(); it!=l_vColorGradient.end(); it++, i++)
	{
		rColorGradient[i*4  ]=it->second.fPercent;
		rColorGradient[i*4+1]=it->second.fRed;
		rColorGradient[i*4+2]=it->second.fGreen;
		rColorGradient[i*4+3]=it->second.fBlue;
	}

	return true;
}
Пример #14
0
int Matrix<T>::distance(const IMatrix<T>& M) const {
	// Vérifications
	if(getM() != M.getM() || getN() != M.getN()) throw domain_error("calcul de la distance impossible");

	int n = 0;

	for(int i = 1; i <= getM(); i++){
		for(int j = 1; j <= getN(); j++){
			if(!equal((*this)(i, j).toDouble(), M(i, j).toDouble(), EPS1, EPS0)) n++;
		}
	}

	return n;
}
Пример #15
0
inline void TransposeMatrix(const IMatrix &mat, IMatrix &res) {
 int rows = mat.size();
 res.clear();
 if(rows > 0) {
  int cols = mat[0].size();
  res.reserve(cols);
  IArray row(rows);
  for(int i = 0; i < cols; ++i) {
   for(int j = 0; j < rows; ++j) {
    row[j] = mat[j][i];
   }
   res.push_back(row);
  }
 }
}
Пример #16
0
bool IMatrix::Inv(IMatrix &res) // Inversion avec la reduction de Gauss Jordan
{
	if (Width!=Height)
		return false;

	IMatrix temp(Width*2,Height);
	for (int i=0;i<Width;i++)
		for (int j=0;j<Height;j++)
			temp[i][j]=GetValue(i,j);

	for (int i=0;i<Width;i++)
		for (int j=0;j<Height;j++)
			if (i==j)
				temp[i+Width][j]=1;
			else
				temp[i+Width][j]=0;

	IMatrix temp2;
	temp2 = temp.GaussJordan(true);	
	temp=temp2;
	temp2.SetSize(Width,Height);
	
	for (int i=0;i<Width;i++)
		for (int j=0;j<Height;j++)
			temp2[i][j]=temp[i+Width][j];

	res.SetSize(Width,Width);
	res=temp2;

	return true;
}
Пример #17
0
 inline void GenHadMat(const int &size, IMatrix &r) const {
  r = gm;
  for(int i = r.size(); i < size;) {
   IMatrix t(0);
   i = KronProd(r, gm, t);
   r = t; 
  }
 }
Пример #18
0
void baricentricne() {
    IMatrix *a = new Matrix(3, 3);
    IMatrix *r = new Matrix(3, 1);
    
    int x;
    printf("Unos trokuta\n");
    for(int i = 0; i < 3; ++i) {
        printf("Tocka %d: ", i);
        for(int j = 0; j < 3; ++j) {
            scanf("%d", &x);
            a->set(i, j, x);
        }
        printf("\n");
    }
    
    printf("T = ");
    for(int j = 0; j < 3; ++j) {
        scanf("%d", &x);
        r->set(j, 0, x);
    }
    printf("\n");
    
    IMatrix *v = a->nInvert()->nMultiply(r);
    
    printf("Baricentricne koordinate tocke T s obzirom na trokut su:\n");
    printf("%s", v->toString().c_str());
    
}
Пример #19
0
boolean OpenViBEToolkit::Tools::Matrix::copyContent(IMatrix& rDestinationMatrix, const IMatrix& rSourceMatrix)
{
	if(&rDestinationMatrix==&rSourceMatrix)
	{
		return true;
	}

	uint32 l_ui32SourceElementCount=rSourceMatrix.getBufferElementCount();
	uint32 l_ui32DestinationElementCount=rDestinationMatrix.getBufferElementCount();
	if(l_ui32DestinationElementCount != l_ui32SourceElementCount)
	{
		return false;
	}
	const float64* l_pSourceBuffer=rSourceMatrix.getBuffer();
	float64* l_pDestinationBuffer=rDestinationMatrix.getBuffer();
	System::Memory::copy(l_pDestinationBuffer, l_pSourceBuffer, l_ui32SourceElementCount*sizeof(float64));
	return true;
}
Пример #20
0
inline void NegateMatrix(const IMatrix &im, IMatrix &om) {
 int is = im.size();
 om = im;
 for(int i = 0; i < is; ++i) {
  for(int j = 0; j < is; ++j) {
   om[i][j] *= -1; 
  }
 }
}
Пример #21
0
inline void MatrixProduct(const IMatrix &mat1, const IMatrix &mat2, IMatrix &res) {
 int rows1 = mat1.size(), rows2 = mat2.size();
 res.clear();
 if(rows1 > 0 && rows2 > 0) {
  int cols1 = mat1[0].size(), cols2 = mat2[0].size();
  if(cols1 == rows2 && cols2 > 0) {
   res.reserve(rows1);
   IArray row(cols2);
   for(int i = 0; i < rows1; ++i) {
    for(int j = 0; j < cols2; ++j) {
     row[j] = 0.;
     for(int k = 0; k < rows2; ++k) {
      row[j] += mat1[i][k] * mat2[k][j];
     }
    }
    res.push_back(row);
   }
  }
 }
}
Пример #22
0
/* +++++++++++++++++++++++ fonctions template  +++++++++++++++++++++++++++ */
template <class T1, class T2, class T3> void CalculatorNaiveMult(IMatrix<T1>& Res, const IMatrix<T2>& A, const IMatrix<T3>& B) {
	// Vérifications
	if(!(A.getN() == B.getM()
		 && Res.getM() == A.getM() && Res.getN() == B.getN())) throw domain_error("produit impossible");

    TYPE_SUM s;

	for(int i = 1; i <= Res.getM(); i++) {
		for(int j = 1; j <= Res.getN(); j++) {
			s = 0;
			for(int k = 1; k <= A.getN(); k++) {
				s += A(i, k).toTypeSum() * B(k, j).toTypeSum();
			}
			Res(i, j) = s;
		}
	}
}
Пример #23
0
bool IMatrix::Add(IMatrix b,IMatrix &res)
{
	IMatrix temp;
	if (Width==b.Width 
		&& Height==b.Height)
	{
		temp.SetSize(Width,Height);

		for (int i=0;i<Width;i++)
		{
			for (int j=0;j<Height;j++)	
			{
				//temp[i][j]=GetValue(i,j)+b.GetValue(i,j);
				temp.SetValue(i,j,GetValue(i,j)+b.GetValue(i,j));
			}
		}
		res=temp;
		return true;
	}
	return false;
}
Пример #24
0
boolean OpenViBEToolkit::Tools::Matrix::copyDescription(IMatrix& rDestinationMatrix, const IMatrix& rSourceMatrix)
{
	if(&rDestinationMatrix==&rSourceMatrix)
	{
		return true;
	}

	uint32 l_ui32DimensionCount=rSourceMatrix.getDimensionCount();
	uint32 l_ui32DimensionSize=0;
	if(!rDestinationMatrix.setDimensionCount(l_ui32DimensionCount))
	{
		return false;
	}
	for(uint32 i=0; i<l_ui32DimensionCount; i++)
	{
		l_ui32DimensionSize=rSourceMatrix.getDimensionSize(i);
		if(!rDestinationMatrix.setDimensionSize(i, l_ui32DimensionSize))
		{
			return false;
		}
		for(uint32 j=0; j<l_ui32DimensionSize; j++)
		{
			if(!rDestinationMatrix.setDimensionLabel(i, j, rSourceMatrix.getDimensionLabel(i, j)))
			{
				return false;
			}
		}
	}
	return true;
}
Пример #25
0
void CalculatorNaive<T>::transpose(IMatrix<T>& Res, const IMatrix<T>& A) const {
	// Vérifications
	if(!(A.getM() == Res.getN() && A.getN() == Res.getM())) throw domain_error("transposition impossible");

	for(int i = 1; i <= Res.getM(); i++){
		for(int j = 1; j <= Res.getN(); j++) Res(j, i) = A(i, j);
	}
}
Пример #26
0
template <class T1, class T2, class T3> void CalculatorNaiveMult(IMatrix<T1>& Res, const IMatrix<T2>& A, T3 x) {
	// Vérifications
	if(!(Res.getM() == A.getM() && Res.getN() == A.getN())) throw domain_error("produit impossible");

	for(int i = 1; i <= Res.getM(); i++){
		for(int j = 1; j<= Res.getN(); j++) {
			Res(i, j) = A(i, j).toTypeSum() * x;
		}
	}
}
Пример #27
0
boolean OpenViBEToolkit::Tools::Matrix::isDescriptionSimilar(const IMatrix& rSourceMatrix1, const IMatrix& rSourceMatrix2, const boolean bCheckLabels)
{
	if(&rSourceMatrix1==&rSourceMatrix2)
	{
		return true;
	}

	if(rSourceMatrix1.getDimensionCount() != rSourceMatrix2.getDimensionCount())
	{
		return false;
	}

	for(uint32 i=0; i<rSourceMatrix1.getDimensionCount(); i++)
	{
		if(rSourceMatrix1.getDimensionSize(i) != rSourceMatrix2.getDimensionSize(i))
		{
			return false;
		}
	}

	if(bCheckLabels)
	{
		for(uint32 i=0; i<rSourceMatrix1.getDimensionCount(); i++)
		{
			for(uint32 j=0; j<rSourceMatrix1.getDimensionSize(i); j++)
			{
				if(strcmp(rSourceMatrix1.getDimensionLabel(i, j), rSourceMatrix2.getDimensionLabel(i, j))!=0)
				{
					return false;
				}
			}
		}
	}

	return true;
}
Пример #28
0
void sustav() {
    IMatrix *a = new Matrix(3, 3);
    IMatrix *r = new Matrix(3, 1);
    
    int x;
    for(int i = 0; i < 3; ++i) {
        for(int j = 0; j < 3; ++j) {
            printf("(%d, %d) = ", i, j);
            scanf("%d", &x);
            printf("\n");
            a->set(i, j, x);
        }
        printf("r%d = ", i);
        scanf("%d", &x);
        printf("\n");
        r->set(i, 0, x);
    }
    
    IMatrix *v = a->nInvert()->nMultiply(r);
    
    printf("Rjesenje sustava je:\n");
    printf("%s", v->toString().c_str());

}
Пример #29
0
int main(int argc, char * const argv[]) {
  bool steps = false;
  string stepPrefix = "/tmp/steps";
  bool approximate = false;
  string approximationFilename;

  typedef uint8_t C;
  typedef ColorImage<C> ColorImage;
  typedef shared_ptr<ColorImage> ColorImageRef;
  typedef RGBPixel<C> RGBPixel;
  typedef GreyImage<C> GreyImage;
  typedef shared_ptr<GreyImage> GreyImageRef;
  typedef PenColor<C> PenColor;
  typedef Pen<C> Pen;
  typedef Carousel<C> Carousel;

  Carousel carousel;
  list< Output<Pen>* > outputs;
  int argn = 1;
  size_t equals = string::npos;
  Rotation rotation = None;
  int offsetX = 0, offsetY = 0;
  double scale = 1.0;
  bool dither = true;
  int threads = 1;

  for (; argn < argc && argv[argn][0] == '-' && strlen(argv[argn]) > 1; argn++) {
    string arg(argv[argn]);
    D(cerr << "arg[" << argn << "] == '" << arg << "'" << endl << flush);
    string penSpec;
    if (0 == arg.find("-pen")) {
      Pen pen;
      if (4 == arg.find("=")) {
        penSpec = arg.substr(5);
      } else {
        ++argn;
        if (!(argn < argc)) {
          cerr << "missing argument to '-pen'" << endl << flush;
          exit(1);
        }
        penSpec = argv[argn];
      }
      size_t start = 0;
      while (start != string::npos) {
        D(cerr << "start=" << start << endl << flush);
        size_t comma = penSpec.find(',', start);
        string part;
        if (comma != string::npos) {
          part = penSpec.substr(start, comma - start);
          start = comma + 1;
        } else {
          part = penSpec.substr(start);
          start = string::npos;
        }
        D(cerr << "part='" << part << "'" << endl << flush);

        if ((equals = part.find('=')) == string::npos) {
          cerr << "pen specification part '" << part << "' missing '='" << endl << flush;
          exit(1);
        } else {
          string name = part.substr(0, equals);
          string value = part.substr(equals + 1);
          D(cerr << "name='" << name << "', value='" << value << "'" << endl << flush);
          switch(name[0]) {
            case 'c': // colour
              pen.color() = PenColor::parse(value);
              break;

            case 'r': // radius
              pen.r() = getInt(value);
              break;

            case 'm': // minimum size that can be drawn
              pen.rMin() = getInt(value);
              break;

            case 'i': // HPGL Index
              pen.hpglIndex() = getInt(value);
              break;

            case 'a': // hatch angle
              pen.hatchAngle() = getDouble(value);
              break;

            case 'p': // hatch phase
              pen.hatchPhase() = getDouble(value);
              break;
          }
        }
      }

      // now add this pen to the carousel
      carousel.addPen(pen);
    } else if (0 == arg.find("-rotate")) {
      string rotationSpec;
      if (7 == arg.find("=")) {
        rotationSpec = arg.substr(8);
      } else {
        ++argn;
        if (!(argn < argc)) {
          cerr << "missing argument to '-rotate'" << endl << flush;
          exit(1);
        }
        rotationSpec = argv[argn];
      }

      switch (rotationSpec[0]) {
        case 'l':
        case 'L':
          rotation = Left;
          break;
        case 'r':
        case 'R':
          rotation = Right;
          break;
        case 'u':
        case 'U':
          rotation = UpsideDown;
          break;
        default:
          cerr << "unrecognized rotation '" << arg << "'" << endl << flush;
          exit(1);
      }
    } else if (0 == arg.find("-offset")) {
      string offset;
      if (7 == arg.find("=")) {
        offset = arg.substr(8);
      } else {
        ++argn;
        if (!(argn < argc)) {
          cerr << "missing argument to '-offset'" << endl << flush;
          exit(1);
        }
        offset = argv[argn];
      }
      size_t delim = offset.find_first_of("x,");
      if (delim == string::npos) {
        // no delimiter - offset both x & y by the same amount
        offsetX = offsetY = getInt(offset);
      } else {
        offsetX = getInt(offset.substr(0, delim));
        offsetY = getInt(offset.substr(delim+1));
      }
    } else if (0 == arg.find("-steps")) {
      steps = true;
      if (6 == arg.find("=")) {
        stepPrefix = arg.substr(7);
      }
    } else if (0 == arg.find("-approx")) {
      approximate = true;
      if (7 == arg.find("=")) {
        approximationFilename = arg.substr(8);
      } else {
        approximationFilename = "approximation.png";
      }
    } else if (0 == arg.find("-nodither")) {
      dither = false;
    } else if (0 == arg.find("-out")) {
      size_t eqPos;
      string outputFile;
      if (string::npos != (eqPos = arg.find("="))) {
        outputFile = arg.substr(eqPos + 1);
        arg = arg.substr(0, eqPos);
      } else {
        ++argn;
        if (!(argn < argc)) {
          cerr << "missing argument to '" << arg << "'" << endl << flush;
          exit(1);
        }
        outputFile = argv[argn];
      }
      string outputType = arg.substr(4);
      if (0 == outputType.length()) {
        outputType = "ha"; // HPGL, absolute coordinates
      }
      std::transform(outputType.begin(), outputType.end(), outputType.begin(), ::tolower);
      outputs.push_back(makeOutput<Pen>(outputType, outputFile));
    } else if (0 == arg.find("-scale")) {
      string scaleString;
      if (6 == arg.find("=")) {
        scaleString = arg.substr(7);
      } else {
        ++argn;
        if (!(argn < argc)) {
          cerr << "missing argument to '-scale'" << endl << flush;
          exit(1);
        }
        scaleString = argv[argn];
      }
      scale = getDouble(scaleString);
    } else if (0 == arg.find("-threads")) {
      string threadsArg;
      if (8 == arg.find("=")) {
        threadsArg = arg.substr(9);
      } else {
        ++argn;
        if (!(argn < argc)) {
          cerr << "missing argument to '-threads'" << endl << flush;
          exit(1);
        }
        threadsArg = argv[argn];
      }
      threads = getInt(threadsArg);
    } else {
      cerr << "Unrecognized argument '" << arg << "'" << endl << flush;
      exit(1);
    }
  }

  string inputFile;

  if (argn == argc - 1) {
    inputFile = argv[argn];
  } else if (argn == argc) {
    // default: is
    inputFile = "-";
  } else {
    cerr << "Extra arguments after input file '" << argv[argn] << "'!";
    cerr << endl << flush;
    exit(1);
  }

  // If there's no specified carousel, use a default one.
  if (carousel.size() == 0) {
    cerr << "No pens specified, using default carousel" << endl << flush;
    // populate the carousel with a default set of pens:
    // black, red, green blue, cyan, magenta, yellow, orange;
    // each at 0.35 mm diameter = 0.175 mm radius = 7 units radius
    Pen black(1.0, 1.0, 1.0, 3); black.hpglIndex() = 1; black.hatchAngle() = 1.0 / 25.0;
    Pen red(0.0, 1.0, 1.0, 3); red.hpglIndex() = 2; red.hatchAngle() = 4.0 / 25.0;
    Pen green(1.0, 0.0, 1.0, 3); green.hpglIndex() = 3; green.hatchAngle() = 7.0 / 25.0;
    Pen blue(1.0, 1.0, 0.0, 3); blue.hpglIndex() = 4; blue.hatchAngle() = 10.0 / 25.0;
    Pen orange(0.0, 0.5, 1.0, 3); orange.hpglIndex() = 8; orange.hatchAngle() = 13.0 / 25.0;
    Pen cyan(1.0, 0.0, 0.0, 3); cyan.hpglIndex() = 5; cyan.hatchAngle() = 16.0 / 25.0;
    Pen magenta(0.0, 1.0, 0.0, 3); magenta.hpglIndex() = 6; magenta.hatchAngle() = 19.0 / 25.0;
    Pen yellow(0.0, 0.0, 1.0, 3); yellow.hpglIndex() = 7; yellow.hatchAngle() = 22.0 / 25.0;

    // put the pens into the carousel in a suitable order
    carousel.addPen(black);
    carousel.addPen(orange);
    carousel.addPen(red);
    carousel.addPen(green);
    carousel.addPen(blue);
    carousel.addPen(cyan);
    carousel.addPen(magenta);
    carousel.addPen(yellow);
  }

  // if there's no output specified, use a default one.
  if (outputs.size() == 0) {
    cerr << "No output specified, writing HPGL to standard output" << endl << flush;
    outputs.push_back(new HPGLAbsoluteOutput<Pen>(cout));
  }

  FILE *f;
  if ("-" == inputFile) {
    cerr << "* Reading image from standard input" << endl << flush;
    f = stdin;
  } else {
    cerr << "* Reading image '" << inputFile << "'" << endl << flush;

    f = fopen(inputFile.c_str(), "r");
    if (f == NULL) {
      cerr << "unable to open input file '" << inputFile << "'!" << endl << flush;
      exit(1);
    }
  }
  ColorImageRef colored(ColorImage::readPng(f));
  if (scale != 1.0) {
    colored = scaleImage(colored, scale);
  }
  Approximator *approximator = NULL;

  if (approximate) {
    approximator = new Approximator(colored->width(), colored->height());
    approximator->approximation().copyRes(colored);
    RGBPixel whitePixel(1.0, 1.0, 1.0);
    approximator->approximation().setAll(whitePixel);
  }

  map<Pen, Chains> ditheredByPen;

  double dTheta = 1.0 / carousel.size();
  double theta = 0.1;

  PlotterPathExtractor extractor;
  shared_ptr<Workers> workers = make_shared<Workers>(threads);
  extractor.setOut(&cerr);
  extractor.setDither(dither);
  extractor.setWorkers(workers);
  Stepper *stepper;
  if (steps) {
    extractor.setStepper(stepper = new Stepper(stepPrefix));
  }
  if (approximate) {
    extractor.setApproximator(approximator);
  }

  int p = 0;
  for (Carousel::iterator c = carousel.begin(); c != carousel.end(); ++c) {
    const PenColor &color = *c;
    cerr << "- Separating out colour " << color << endl;
    GreyImageRef separated = colored->separateAndSubtract(color);
    if (steps) {
      cerr << "  . writing separation" << endl;
      separated->writePng(stepper->makeName("separation.png", color.unparse().c_str()));
    }

    if (approximate) {
      approximator->setPenColor(color);
    }

    list<Pen> &pens = carousel.pensWithColor(color);
    extractor.outlineHatchThinDither(separated, pens, ditheredByPen);

    ++p;
    theta += dTheta;
  }

  IMatrix transform = IMatrix::identity();

  cerr << "initial transform: " << transform << endl << flush;

  cerr << "offsetX = " << offsetX << ", offsetY = " << offsetY << endl << flush;
  if (offsetX != 0 || offsetY != 0) {
    transform = transform.concat(IMatrix::translate(offsetX, offsetY));
  }
  cerr << "after offset: " << transform << endl << flush;

  cerr << "rotation = " << rotation << endl << flush;
  if (rotation == Left) {
    transform = transform.concat(IMatrix::pageLeft(colored->width(), colored->height()));
  } else if (rotation == Right) {
    transform = transform.concat(IMatrix::pageRight(colored->width(), colored->height()));
  } else if (rotation == UpsideDown) {
    transform = transform.concat(IMatrix::pageUpsideDown(colored->width(), colored->height()));
  }
  cerr << "after rotation: " << transform << endl << flush;

  int maxX = numeric_limits<int>::min(), maxY = numeric_limits<int>::min();
  int minX = numeric_limits<int>::max(), minY = numeric_limits<int>::max();
  for (int x = 0; x < colored->width(); x += colored->width()-1) {
    for (int y = 0; y < colored->height(); y += colored->height()-1) {
      IPoint p(x, y);
      p.transform(transform);
      minX = min(p.x(), minX);
      maxX = max(p.x(), maxX);
      minY = min(p.y(), minY);
      maxY = max(p.y(), maxY);
    }
  }

  cerr << "minX = " << minX << ", minY = " << minY << ", maxX = " << maxX << ", maxY = " << maxY << endl << flush;

  // Finally, adjust for the top-to-bottom Y of our bitmaps
  // vs the bottom-to-top Y of our output devices
  IMatrix adjustment(1, 0, 0, -1, 0, colored->height());
  transform = transform.concat(adjustment);
  cerr << "after adjustment: " << transform << endl << flush;

  for (list< Output<Pen>* >::const_iterator outIter = outputs.begin();
       outIter != outputs.end(); ++outIter) {
    cerr << "Writing " << (**outIter) << endl << flush;
    (*outIter)->open();
    (*outIter)->beginPage(maxX + 1, maxY + 1);
  }

  for (map<Pen, Chains>::iterator di = ditheredByPen.begin(); di != ditheredByPen.end(); ++di) {
    const Pen &pen = di->first;
    Chains &dithered = di->second;

    if (transform != IMatrix::identity()) {
      cerr << "- applying transform " << transform << endl << flush;
      dithered.transform(transform);
    } else {
      cerr << "-  skipping identity transform " << transform << endl << flush;
    }

    for (list< Output<Pen>* >::const_iterator outIter = outputs.begin();
         outIter != outputs.end(); ++outIter) {
      (*outIter)->setPen(pen);
      (*outIter)->outputChains(dithered);
    }
  }

  for (list< Output<Pen>* >::const_iterator outIter = outputs.begin();
       outIter != outputs.end(); ++outIter) {
    (*outIter)->endPage();
    (*outIter)->close();
    delete (*outIter);
  }
  outputs.clear();

  if (approximate) {
    cerr << "    . drawing final approximation" << endl;
    approximator->approximation().writePng(approximationFilename.c_str());

    delete approximator;
    approximator = NULL;
  }
}
void CalculatorBlasLapack<T>::LU(IMatrix<T>& P, IMatrix<T>& L, IMatrix<T>& U, const IMatrix<T>& A) const {
	// Vérifications
	if(!(A.getM() == L.getM() && A.getN() == U.getN()
		 && A.getM() == A.getN())) throw domain_error("décomposition LU impossible");

	double a[A.getM() * A.getN()];
	int ipiv[A.getM()], piv[A.getM()], aux, m = A.getM(), info = 0;

	A.toDouble(a, false);

	if(blasLapackAdapter.dgetrf(&m, &m, a, &m, ipiv, &info)) throw domain_error("décomposition LU impossible");

	P.fromDouble(a, false);

	// construction de P à partir de ipiv
	for(int i = 1; i <= A.getM(); i++) {
		for(int j = 1; j <= A.getM(); j++) P(i, j) = 0;
		piv[i-1] = i;
	}
	for(int i = A.getM() - 1; i >= 0; i--) {
		aux = piv[ipiv[i] - 1];
		piv[ipiv[i] - 1] = piv[i];
		piv[i] = aux;
	}

	for(int i = 1; i <= A.getM(); i++) {
		P(i, piv[i-1]) = 1;

		for(int j = 1; j <= L.getN(); j++) {
			// L et U
			if(i > j) {
				L(i, j) = a[(j - 1) * A.getN() + (i - 1)];
				U(j, i) = a[(i - 1) * A.getN() + (j - 1)];
			} else if(i == j) {
				L(i, j) = 1;
				U(j, i) = a[(i - 1) * A.getN() + (j - 1)];
			} else {
				L(i, j) = 0;
				U(j, i) = 0;
			}
		}
	}
}