matrixSetup.h 14.8 KB
Newer Older
Pierre Kraemer's avatar
Pierre Kraemer committed
1 2 3
/*******************************************************************************
* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps  *
* version 0.1                                                                  *
4
* Copyright (C) 2009-2012, IGG Team, LSIIT, University of Strasbourg           *
Pierre Kraemer's avatar
Pierre Kraemer committed
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
*                                                                              *
* This library is free software; you can redistribute it and/or modify it      *
* under the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation; either version 2.1 of the License, or (at your     *
* option) any later version.                                                   *
*                                                                              *
* This library is distributed in the hope that it will be useful, but WITHOUT  *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or        *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License  *
* for more details.                                                            *
*                                                                              *
* You should have received a copy of the GNU Lesser General Public License     *
* along with this library; if not, write to the Free Software Foundation,      *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.           *
*                                                                              *
20
* Web site: http://cgogn.unistra.fr/                                           *
Pierre Kraemer's avatar
Pierre Kraemer committed
21 22 23 24
* Contact information: cgogn@unistra.fr                                        *
*                                                                              *
*******************************************************************************/

25 26
#ifndef __LINEAR_SOLVING_MATRIX_SETUP__
#define __LINEAR_SOLVING_MATRIX_SETUP__
Pierre Kraemer's avatar
Pierre Kraemer committed
27 28 29 30 31 32 33

namespace CGoGN
{

namespace LinearSolving
{

34 35 36 37 38 39 40 41 42
template <typename CoeffType>
struct Coeff
{
	unsigned int index;
	CoeffType value;
	Coeff(unsigned int i, CoeffType v) : index(i), value(v)
	{}
} ;

43 44 45 46
/*******************************************************************************
 * EQUALITY MATRIX : right-hand-side SCALAR
 *******************************************************************************/

47
template<typename PFP, typename ATTR_TYPE>
Pierre Kraemer's avatar
Pierre Kraemer committed
48 49
class FunctorEquality_PerVertexWeight_Scalar : public FunctorType
{
Pierre Kraemer's avatar
Pierre Kraemer committed
50 51
	typedef typename PFP::MAP::IMPL MAP_IMPL;

Pierre Kraemer's avatar
Pierre Kraemer committed
52
protected:
Pierre Kraemer's avatar
Pierre Kraemer committed
53 54 55
	const VertexAttribute<unsigned int, MAP_IMPL>& indexTable ;
	const VertexAttribute<ATTR_TYPE, MAP_IMPL>& attrTable ;
	const VertexAttribute<typename PFP::REAL, MAP_IMPL>& weightTable ;
Pierre Kraemer's avatar
Pierre Kraemer committed
56 57 58

public:
	FunctorEquality_PerVertexWeight_Scalar(
Pierre Kraemer's avatar
Pierre Kraemer committed
59 60 61
		const VertexAttribute<unsigned int, MAP_IMPL>& index,
		const VertexAttribute<ATTR_TYPE, MAP_IMPL>& attr,
		const VertexAttribute<typename PFP::REAL, MAP_IMPL>& weight
62
	) :	indexTable(index), attrTable(attr), weightTable(weight)
Pierre Kraemer's avatar
Pierre Kraemer committed
63 64 65 66
	{}

	bool operator()(Dart d)
	{
67 68 69 70 71
		nlRowParameterd(NL_RIGHT_HAND_SIDE, attrTable[d]) ;
		nlRowParameterd(NL_ROW_SCALING, weightTable[d]) ;
		nlBegin(NL_ROW) ;
		nlCoefficient(indexTable[d], 1) ;
		nlEnd(NL_ROW) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
72 73 74 75
		return false ;
	}
} ;

76
template<typename PFP, typename ATTR_TYPE>
Pierre Kraemer's avatar
Pierre Kraemer committed
77
class FunctorEquality_UniformWeight_Scalar : public FunctorType
Pierre Kraemer's avatar
Pierre Kraemer committed
78
{
Pierre Kraemer's avatar
Pierre Kraemer committed
79 80
	typedef typename PFP::MAP::IMPL MAP_IMPL;

Pierre Kraemer's avatar
Pierre Kraemer committed
81
protected:
Pierre Kraemer's avatar
Pierre Kraemer committed
82 83
	const VertexAttribute<unsigned int, MAP_IMPL>& indexTable ;
	const VertexAttribute<ATTR_TYPE, MAP_IMPL>& attrTable ;
84 85 86
	float weight ;

public:
Pierre Kraemer's avatar
Pierre Kraemer committed
87
	FunctorEquality_UniformWeight_Scalar(
Pierre Kraemer's avatar
Pierre Kraemer committed
88 89
		const VertexAttribute<unsigned int, MAP_IMPL>& index,
		const VertexAttribute<ATTR_TYPE, MAP_IMPL>& attr,
90
		float w
91
	) :	indexTable(index), attrTable(attr), weight(w)
92 93 94 95
	{}

	bool operator()(Dart d)
	{
96 97 98 99 100
		nlRowParameterd(NL_RIGHT_HAND_SIDE, attrTable[d]) ;
		nlRowParameterd(NL_ROW_SCALING, weight) ;
		nlBegin(NL_ROW) ;
		nlCoefficient(indexTable[d], 1) ;
		nlEnd(NL_ROW) ;
101 102 103 104 105 106 107 108
		return false ;
	}
} ;

/*******************************************************************************
 * EQUALITY MATRIX : right-hand-side VECTOR + coordinate
 *******************************************************************************/

109
template<typename PFP, typename ATTR_TYPE>
Pierre Kraemer's avatar
Pierre Kraemer committed
110 111
class FunctorEquality_PerVertexWeight_Vector : public FunctorType
{
Pierre Kraemer's avatar
Pierre Kraemer committed
112 113
	typedef typename PFP::MAP::IMPL MAP_IMPL;

Pierre Kraemer's avatar
Pierre Kraemer committed
114
protected:
Pierre Kraemer's avatar
Pierre Kraemer committed
115 116 117
	const VertexAttribute<unsigned int, MAP_IMPL>& indexTable ;
	const VertexAttribute<ATTR_TYPE, MAP_IMPL>& attrTable ;
	const VertexAttribute<typename PFP::REAL, MAP_IMPL>& weightTable ;
Pierre Kraemer's avatar
Pierre Kraemer committed
118 119 120 121
	unsigned int coord ;

public:
	FunctorEquality_PerVertexWeight_Vector(
Pierre Kraemer's avatar
Pierre Kraemer committed
122 123 124
		const VertexAttribute<unsigned int, MAP_IMPL>& index,
		const VertexAttribute<ATTR_TYPE, MAP_IMPL>& attr,
		const VertexAttribute<typename PFP::REAL, MAP_IMPL>& weight,
Pierre Kraemer's avatar
Pierre Kraemer committed
125
		unsigned int c
126
	) :	indexTable(index), attrTable(attr), weightTable(weight), coord(c)
Pierre Kraemer's avatar
Pierre Kraemer committed
127 128 129 130
	{}

	bool operator()(Dart d)
	{
131 132 133 134 135
		nlRowParameterd(NL_RIGHT_HAND_SIDE, (attrTable[d])[coord]) ;
		nlRowParameterd(NL_ROW_SCALING, weightTable[d]) ;
		nlBegin(NL_ROW) ;
		nlCoefficient(indexTable[d], 1) ;
		nlEnd(NL_ROW) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
136 137 138 139
		return false ;
	}
} ;

140
template<typename PFP, typename ATTR_TYPE>
Pierre Kraemer's avatar
Pierre Kraemer committed
141
class FunctorEquality_UniformWeight_Vector : public FunctorType
142
{
Pierre Kraemer's avatar
Pierre Kraemer committed
143 144
	typedef typename PFP::MAP::IMPL MAP_IMPL;

145
protected:
Pierre Kraemer's avatar
Pierre Kraemer committed
146 147
	const VertexAttribute<unsigned int, MAP_IMPL>& indexTable ;
	const VertexAttribute<ATTR_TYPE, MAP_IMPL>& attrTable ;
Pierre Kraemer's avatar
Pierre Kraemer committed
148
	float weight ;
149 150 151
	unsigned int coord ;

public:
Pierre Kraemer's avatar
Pierre Kraemer committed
152
	FunctorEquality_UniformWeight_Vector(
Pierre Kraemer's avatar
Pierre Kraemer committed
153 154
		const VertexAttribute<unsigned int, MAP_IMPL>& index,
		const VertexAttribute<ATTR_TYPE, MAP_IMPL>& attr,
155 156
		float w,
		unsigned int c
157
	) :	indexTable(index), attrTable(attr), weight(w), coord(c)
158 159 160 161
	{}

	bool operator()(Dart d)
	{
162 163 164 165 166
		nlRowParameterd(NL_RIGHT_HAND_SIDE, (attrTable[d])[coord]) ;
		nlRowParameterd(NL_ROW_SCALING, weight) ;
		nlBegin(NL_ROW) ;
		nlCoefficient(indexTable[d], 1) ;
		nlEnd(NL_ROW) ;
167 168 169 170 171 172 173 174
		return false ;
	}
} ;

/*******************************************************************************
 * LAPLACIAN TOPO MATRIX : right-hand-side 0
 *******************************************************************************/

175
template<typename PFP>
176 177
class FunctorLaplacianTopo : public FunctorMap<typename PFP::MAP>
{
Pierre Kraemer's avatar
Pierre Kraemer committed
178
	typedef typename PFP::MAP MAP ;
Pierre Kraemer's avatar
Pierre Kraemer committed
179
	typedef typename PFP::MAP::IMPL MAP_IMPL;
180
	typedef typename PFP::REAL REAL ;
Pierre Kraemer's avatar
Pierre Kraemer committed
181

Pierre Kraemer's avatar
Pierre Kraemer committed
182 183 184 185
protected:
	const VertexAttribute<unsigned int, MAP_IMPL>& indexTable ;

public:
186 187
	FunctorLaplacianTopo(
		MAP& m,
Pierre Kraemer's avatar
Pierre Kraemer committed
188
		const VertexAttribute<unsigned int, MAP_IMPL>& index
189
	) :	FunctorMap<MAP>(m), indexTable(index)
Pierre Kraemer's avatar
Pierre Kraemer committed
190
	{}
191

Pierre Kraemer's avatar
Pierre Kraemer committed
192 193
	bool operator()(Dart d)
	{
194 195
		nlRowParameterd(NL_RIGHT_HAND_SIDE, 0) ;
		nlBegin(NL_ROW);
196
		REAL aii = 0 ;
Pierre Kraemer's avatar
Pierre Kraemer committed
197
		Traversor2VE<MAP> t(this->m_map, d) ;
198
		for(Dart it = t.begin(); it != t.end(); it = t.next())
199 200 201
		{
			REAL aij = 1 ;
			aii += aij ;
202
			nlCoefficient(indexTable[this->m_map.phi1(it)], aij) ;
203
		}
204 205
		nlCoefficient(indexTable[d], -aii) ;
		nlEnd(NL_ROW) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
206 207 208 209
		return false ;
	}
} ;

210 211 212 213
/*******************************************************************************
 * LAPLACIAN TOPO MATRIX : right-hand-side SCALAR
 *******************************************************************************/

214
template<typename PFP, typename ATTR_TYPE>
215
class FunctorLaplacianTopoRHS_Scalar : public FunctorMap<typename PFP::MAP>
Pierre Kraemer's avatar
Pierre Kraemer committed
216
{
217
	typedef typename PFP::MAP MAP ;
Pierre Kraemer's avatar
Pierre Kraemer committed
218
	typedef typename PFP::MAP::IMPL MAP_IMPL;
219 220
	typedef typename PFP::REAL REAL ;

Pierre Kraemer's avatar
Pierre Kraemer committed
221 222 223 224 225
protected:
	const VertexAttribute<unsigned int, MAP_IMPL>& indexTable ;
	const VertexAttribute<ATTR_TYPE, MAP_IMPL>& attrTable ;

public:
226 227
	FunctorLaplacianTopoRHS_Scalar(
		MAP& m,
Pierre Kraemer's avatar
Pierre Kraemer committed
228 229
		const VertexAttribute<unsigned int, MAP_IMPL>& index,
		const VertexAttribute<ATTR_TYPE, MAP_IMPL>& attr
230
	) :	FunctorMap<MAP>(m), indexTable(index), attrTable(attr)
231 232 233 234
	{}

	bool operator()(Dart d)
	{
235 236 237 238
		std::vector<Coeff<REAL> > coeffs ;
		coeffs.reserve(12) ;

		REAL norm2 = 0 ;
239
		REAL aii = 0 ;
Pierre Kraemer's avatar
Pierre Kraemer committed
240
		Traversor2VE<MAP> t(this->m_map, d) ;
241
		for(Dart it = t.begin(); it != t.end(); it = t.next())
242 243 244
		{
			REAL aij = 1 ;
			aii += aij ;
245 246
			coeffs.push_back(Coeff<REAL>(indexTable[this->m_map.phi1(it)], aij)) ;
			norm2 += aij * aij ;
247
		}
248 249 250 251 252 253 254 255 256
		coeffs.push_back(Coeff<REAL>(indexTable[d], -aii)) ;
		norm2 += aii * aii ;

		nlRowParameterd(NL_RIGHT_HAND_SIDE, attrTable[d] * sqrt(norm2)) ;
		nlBegin(NL_ROW);
		for(unsigned int i = 0; i < coeffs.size(); ++i)
			nlCoefficient(coeffs[i].index, coeffs[i].value) ;
		nlEnd(NL_ROW) ;

257 258 259 260 261 262 263 264
		return false ;
	}
} ;

/*******************************************************************************
 * LAPLACIAN TOPO MATRIX : right-hand-side VECTOR + coordinate
 *******************************************************************************/

265
template<typename PFP, typename ATTR_TYPE>
266 267
class FunctorLaplacianTopoRHS_Vector : public FunctorMap<typename PFP::MAP>
{
Pierre Kraemer's avatar
Pierre Kraemer committed
268 269 270 271
	typedef typename PFP::MAP MAP ;
	typedef typename PFP::MAP::IMPL MAP_IMPL;
	typedef typename PFP::REAL REAL ;

272
protected:
Pierre Kraemer's avatar
Pierre Kraemer committed
273 274
	const VertexAttribute<unsigned int, MAP_IMPL>& indexTable ;
	const VertexAttribute<ATTR_TYPE, MAP_IMPL>& attrTable ;
Pierre Kraemer's avatar
Pierre Kraemer committed
275 276 277
	unsigned int coord ;

public:
278 279
	FunctorLaplacianTopoRHS_Vector(
		MAP& m,
Pierre Kraemer's avatar
Pierre Kraemer committed
280 281
		const VertexAttribute<unsigned int, MAP_IMPL>& index,
		const VertexAttribute<ATTR_TYPE, MAP_IMPL>& attr,
282
		unsigned int c
283
	) :	FunctorMap<MAP>(m), indexTable(index), attrTable(attr), coord(c)
Pierre Kraemer's avatar
Pierre Kraemer committed
284
	{}
285

Pierre Kraemer's avatar
Pierre Kraemer committed
286 287
	bool operator()(Dart d)
	{
288 289 290 291
		std::vector<Coeff<REAL> > coeffs ;
		coeffs.reserve(12) ;

		REAL norm2 = 0 ;
292
		REAL aii = 0 ;
Pierre Kraemer's avatar
Pierre Kraemer committed
293
		Traversor2VE<MAP> t(this->m_map, d) ;
294
		for(Dart it = t.begin(); it != t.end(); it = t.next())
295 296 297
		{
			REAL aij = 1 ;
			aii += aij ;
298 299
			coeffs.push_back(Coeff<REAL>(indexTable[this->m_map.phi1(it)], aij)) ;
			norm2 += aij * aij ;
300
		}
301 302 303 304 305 306 307 308 309
		coeffs.push_back(Coeff<REAL>(indexTable[d], -aii)) ;
		norm2 += aii * aii ;

		nlRowParameterd(NL_RIGHT_HAND_SIDE, (attrTable[d])[coord] * sqrt(norm2)) ;
		nlBegin(NL_ROW);
		for(unsigned int i = 0; i < coeffs.size(); ++i)
			nlCoefficient(coeffs[i].index, coeffs[i].value) ;
		nlEnd(NL_ROW) ;

Pierre Kraemer's avatar
Pierre Kraemer committed
310 311 312 313
		return false ;
	}
} ;

314 315 316 317
/*******************************************************************************
 * LAPLACIAN COTAN MATRIX : right-hand-side 0
 *******************************************************************************/

318
template<typename PFP>
319
class FunctorLaplacianCotan : public FunctorMap<typename PFP::MAP>
Pierre Kraemer's avatar
Pierre Kraemer committed
320
{
321
	typedef typename PFP::MAP MAP ;
Pierre Kraemer's avatar
Pierre Kraemer committed
322
	typedef typename PFP::MAP::IMPL MAP_IMPL;
323 324
	typedef typename PFP::REAL REAL ;

Pierre Kraemer's avatar
Pierre Kraemer committed
325 326 327 328 329 330
protected:
	const VertexAttribute<unsigned int, MAP_IMPL>& indexTable ;
	const EdgeAttribute<typename PFP::REAL, MAP_IMPL>& edgeWeight ;
	const VertexAttribute<typename PFP::REAL, MAP_IMPL>& vertexArea ;

public:
331 332
	FunctorLaplacianCotan(
		MAP& m,
Pierre Kraemer's avatar
Pierre Kraemer committed
333 334 335
		const VertexAttribute<unsigned int, MAP_IMPL>& index,
		const EdgeAttribute<typename PFP::REAL, MAP_IMPL>& eWeight,
		const VertexAttribute<typename PFP::REAL, MAP_IMPL>& vArea
336
	) :	FunctorMap<MAP>(m), indexTable(index), edgeWeight(eWeight), vertexArea(vArea)
337
	{}
Pierre Kraemer's avatar
Pierre Kraemer committed
338

339 340
	bool operator()(Dart d)
	{
341 342
		nlRowParameterd(NL_RIGHT_HAND_SIDE, 0) ;
		nlBegin(NL_ROW);
343 344
		REAL vArea = vertexArea[d] ;
		REAL aii = 0 ;
Pierre Kraemer's avatar
Pierre Kraemer committed
345
		Traversor2VE<MAP> t(this->m_map, d) ;
346
		for(Dart it = t.begin(); it != t.end(); it = t.next())
347 348 349
		{
			REAL aij = edgeWeight[it] / vArea ;
			aii += aij ;
350 351 352 353 354
			nlCoefficient(indexTable[this->m_map.phi1(it)], aij) ;
		}
		nlCoefficient(indexTable[d], -aii) ;
		nlEnd(NL_ROW) ;

355 356 357 358 359 360 361 362
		return false ;
	}
} ;

/*******************************************************************************
 * LAPLACIAN COTAN MATRIX : right-hand-side SCALAR
 *******************************************************************************/

363
template<typename PFP, typename ATTR_TYPE>
364
class FunctorLaplacianCotanRHS_Scalar : public FunctorMap<typename PFP::MAP>
Pierre Kraemer's avatar
Pierre Kraemer committed
365
{
366
	typedef typename PFP::MAP MAP ;
Pierre Kraemer's avatar
Pierre Kraemer committed
367
	typedef typename PFP::MAP::IMPL MAP_IMPL;
368 369
	typedef typename PFP::REAL REAL ;

Pierre Kraemer's avatar
Pierre Kraemer committed
370 371 372 373 374 375 376
protected:
	const VertexAttribute<unsigned int, MAP_IMPL>& indexTable ;
	const EdgeAttribute<typename PFP::REAL, MAP_IMPL>& edgeWeight ;
	const VertexAttribute<typename PFP::REAL, MAP_IMPL>& vertexArea ;
	const VertexAttribute<ATTR_TYPE, MAP_IMPL>& attrTable ;

public:
377 378
	FunctorLaplacianCotanRHS_Scalar(
		MAP& m,
Pierre Kraemer's avatar
Pierre Kraemer committed
379 380 381 382
		const VertexAttribute<unsigned int, MAP_IMPL>& index,
		const EdgeAttribute<typename PFP::REAL, MAP_IMPL>& eWeight,
		const VertexAttribute<typename PFP::REAL, MAP_IMPL>& vArea,
		const VertexAttribute<ATTR_TYPE, MAP_IMPL>& attr
383
	) :	FunctorMap<MAP>(m), indexTable(index), edgeWeight(eWeight), vertexArea(vArea), attrTable(attr)
384 385 386 387
	{}

	bool operator()(Dart d)
	{
388 389 390
		std::vector<Coeff<REAL> > coeffs ;
		coeffs.reserve(12) ;

391
		REAL vArea = vertexArea[d] ;
392
		REAL norm2 = 0 ;
393
		REAL aii = 0 ;
Pierre Kraemer's avatar
Pierre Kraemer committed
394
		Traversor2VE<MAP> t(this->m_map, d) ;
395
		for(Dart it = t.begin(); it != t.end(); it = t.next())
396 397 398
		{
			REAL aij = edgeWeight[it] / vArea ;
			aii += aij ;
399 400
			coeffs.push_back(Coeff<REAL>(indexTable[this->m_map.phi1(it)], aij)) ;
			norm2 += aij * aij ;
401
		}
402 403 404 405 406 407 408 409 410
		coeffs.push_back(Coeff<REAL>(indexTable[d], -aii)) ;
		norm2 += aii * aii ;

		nlRowParameterd(NL_RIGHT_HAND_SIDE, attrTable[d] * sqrt(norm2)) ;
		nlBegin(NL_ROW);
		for(unsigned int i = 0; i < coeffs.size(); ++i)
			nlCoefficient(coeffs[i].index, coeffs[i].value) ;
		nlEnd(NL_ROW) ;

411 412 413 414 415 416 417 418
		return false ;
	}
} ;

/*******************************************************************************
 * LAPLACIAN COTAN MATRIX : right-hand-side VECTOR + coordinate
 *******************************************************************************/

419
template<typename PFP, typename ATTR_TYPE>
420 421
class FunctorLaplacianCotanRHS_Vector : public FunctorMap<typename PFP::MAP>
{
Pierre Kraemer's avatar
Pierre Kraemer committed
422 423 424 425
	typedef typename PFP::MAP MAP ;
	typedef typename PFP::MAP::IMPL MAP_IMPL;
	typedef typename PFP::REAL REAL ;

426
protected:
Pierre Kraemer's avatar
Pierre Kraemer committed
427 428 429 430
	const VertexAttribute<unsigned int, MAP_IMPL>& indexTable ;
	const EdgeAttribute<typename PFP::REAL, MAP_IMPL>& edgeWeight ;
	const VertexAttribute<typename PFP::REAL, MAP_IMPL>& vertexArea ;
	const VertexAttribute<ATTR_TYPE, MAP_IMPL>& attrTable ;
431 432 433 434 435
	unsigned int coord ;

public:
	FunctorLaplacianCotanRHS_Vector(
		MAP& m,
Pierre Kraemer's avatar
Pierre Kraemer committed
436 437 438 439
		const VertexAttribute<unsigned int, MAP_IMPL>& index,
		const EdgeAttribute<typename PFP::REAL, MAP_IMPL>& eWeight,
		const VertexAttribute<typename PFP::REAL, MAP_IMPL>& vArea,
		const VertexAttribute<ATTR_TYPE, MAP_IMPL>& attr,
440
		unsigned int c
441
	) :	FunctorMap<MAP>(m), indexTable(index), edgeWeight(eWeight), vertexArea(vArea), attrTable(attr), coord(c)
442 443 444 445
	{}

	bool operator()(Dart d)
	{
446 447 448
		std::vector<Coeff<REAL> > coeffs ;
		coeffs.reserve(12) ;

449
		REAL vArea = vertexArea[d] ;
450
		REAL norm2 = 0 ;
451
		REAL aii = 0 ;
Pierre Kraemer's avatar
Pierre Kraemer committed
452
		Traversor2VE<MAP> t(this->m_map, d) ;
453
		for(Dart it = t.begin(); it != t.end(); it = t.next())
454 455 456
		{
			REAL aij = edgeWeight[it] / vArea ;
			aii += aij ;
457 458
			coeffs.push_back(Coeff<REAL>(indexTable[this->m_map.phi1(it)], aij)) ;
			norm2 += aij * aij ;
459
		}
460 461 462 463 464 465 466 467 468
		coeffs.push_back(Coeff<REAL>(indexTable[d], -aii)) ;
		norm2 += aii * aii ;

		nlRowParameterd(NL_RIGHT_HAND_SIDE, (attrTable[d])[coord] * sqrt(norm2)) ;
		nlBegin(NL_ROW);
		for(unsigned int i = 0; i < coeffs.size(); ++i)
			nlCoefficient(coeffs[i].index, coeffs[i].value) ;
		nlEnd(NL_ROW) ;

469 470 471
		return false ;
	}
} ;
Pierre Kraemer's avatar
Pierre Kraemer committed
472

473
} // namespace LinearSolving
Pierre Kraemer's avatar
Pierre Kraemer committed
474

475
} // namespace CGoGN
Pierre Kraemer's avatar
Pierre Kraemer committed
476 477

#endif