Alien  1.3.0
Developer documentation
Loading...
Searching...
No Matches
SYCLInternalLinearAlgebra.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7
8
9#include "arccore/message_passing/ITypeDispatcher.h"
10#include "arccore/message_passing/Request.h"
11#include "arccore/message_passing/IStat.h"
12#include "arccore/message_passing_mpi/MessagePassingMpiGlobal.h"
13#include "arccore/message_passing_mpi/MpiDatatype.h"
14
15#include <alien/utils/Precomp.h>
16
17#include <arccore/base/NotImplementedException.h>
18#include <arccore/base/TraceInfo.h>
19
22
23#include "alien/kernels/sycl/data/SYCLEnv.h"
24#include "alien/kernels/sycl/data/SYCLEnvInternal.h"
25
26#include "alien/kernels/sycl/data/SYCLVectorInternal.h"
27#include "alien/kernels/sycl/data/SYCLVector.h"
28
29#include <alien/kernels/sycl/data/SYCLBEllPackInternal.h>
30#include <alien/kernels/sycl/data/SYCLBEllPackMatrix.h>
31
32#include "alien/kernels/sycl/algebra/SYCLKernelInternal.h"
33#include "alien/kernels/sycl/algebra/SYCLInternalLinearAlgebra.h"
34
35#include "alien/kernels/sycl/algebra/SYCLBEllPackMatrixMult.h"
36
37/*---------------------------------------------------------------------------*/
38
39namespace Alien
40{
41
42using namespace Arccore;
43
44template class ALIEN_EXPORT LinearAlgebra<BackEnd::tag::sycl>;
45template class ALIEN_EXPORT LinearAlgebraExpr<BackEnd::tag::sycl>;
46
48SYCLInternalLinearAlgebraFactory()
49{
50 return new SYCLInternalLinearAlgebra();
51}
52
54SYCLInternalLinearAlgebraExprFactory()
55{
57}
58
59/*---------------------------------------------------------------------------*/
60
61namespace Internal = SYCLInternal;
62
63/*---------------------------------------------------------------------------*/
64
65SYCLInternalLinearAlgebra::SYCLInternalLinearAlgebra()
67{
68 m_internal.reset(new SYCLInternal::KernelInternal());
69}
70
71/*---------------------------------------------------------------------------*/
72
73SYCLInternalLinearAlgebra::~SYCLInternalLinearAlgebra()
74{
75#ifdef ALIEN_USE_PERF_TIMER
76 m_timer.printInfo("SYCL-ALGEBRA");
77#endif
78}
79
80void SYCLInternalLinearAlgebra::setDotAlgo(int dot_algo)
81{
82 m_internal->setDotAlgo(dot_algo);
83}
84
85/*---------------------------------------------------------------------------*/
86/*---------------------------------------------------------------------------*/
87SYCLInternalLinearAlgebra::ResourceType
88SYCLInternalLinearAlgebra::resource(Matrix const& A)
89{
90 return std::make_tuple(&A.distribution().rowDistribution(),A.blockSize());
91}
92
93void SYCLInternalLinearAlgebra::allocate(ResourceType resource, Vector& v)
94{
95 v.init(*std::get<0>(resource),std::get<1>(resource), true);
96}
97
98void SYCLInternalLinearAlgebra::free(Vector& v)
99{
100 v.clear();
101}
102
103Real SYCLInternalLinearAlgebra::norm0(const SYCLVector<Real>& vx ALIEN_UNUSED_PARAM) const
104{
105 // return SYCLBLASKernel::nrm0(x.space().structInfo(),vx);
106 throw NotImplementedException(
107 A_FUNCINFO, "SYCLLinearAlgebra::norm0 not implemented");
108}
109
110/*---------------------------------------------------------------------------*/
111
112Real SYCLInternalLinearAlgebra::norm1(const SYCLVector<Real>& vx ALIEN_UNUSED_PARAM) const
113{
114 // return SYCLBLASKernel::nrm1(x.space().structInfo(),vx);
115 throw NotImplementedException(
116 A_FUNCINFO, "SYCLLinearAlgebra::norm1 not implemented");
117}
118/*---------------------------------------------------------------------------*/
119
120Real SYCLInternalLinearAlgebra::norm2(const SYCLVector<Real>& vx) const
121{
122#ifdef ALIEN_USE_PERF_TIMER
123 SentryType s(m_timer, "SYCL-NORM2");
124#endif
125 return std::sqrt(m_internal->dot(vx.internal()->values(), vx.internal()->values()));
126}
127
128Real SYCLInternalLinearAlgebra::normInf([[maybe_unused]] const SYCLVector<Real>& vx) const
129{
130#ifdef ALIEN_USE_PERF_TIMER
131 SentryType s(m_timer, "SYCL-NORMINF");
132#endif
133 throw NotImplementedException(
134 A_FUNCINFO, "SYCLLinearAlgebra::normInf not implemented");
135}
136/*---------------------------------------------------------------------------*/
137
138void SYCLInternalLinearAlgebra::mult(const SYCLBEllPackMatrix<Real>& ma,
139 const SYCLVector<Real>& vx,
140 SYCLVector<Real>& vr) const
141{
142#ifdef ALIEN_USE_PERF_TIMER
143 SentryType s(m_timer, "SYCL-SPMV");
144#endif
145 Internal::SYCLBEllPackMatrixMultT<Real>(ma).mult(vx, vr);
146}
147
148void SYCLInternalLinearAlgebra::addLMult(Real alpha,
149 const SYCLBEllPackMatrix<Real>& ma,
150 const SYCLVector<Real>& vx,
151 SYCLVector<Real>& vr) const
152{
153#ifdef ALIEN_USE_PERF_TIMER
154 SentryType s(m_timer, "SYCL-ADDLMULT");
155#endif
156 Internal::SYCLBEllPackMatrixMultT<Real>(ma).addLMult(alpha, vx, vr);
157}
158
159void SYCLInternalLinearAlgebra::addUMult(Real alpha,
160 const SYCLBEllPackMatrix<Real>& ma,
161 const SYCLVector<Real>& vx,
162 SYCLVector<Real>& vr) const
163{
164#ifdef ALIEN_USE_PERF_TIMER
165 SentryType s(m_timer, "SYCL-ADDUMULT");
166#endif
167 Internal::SYCLBEllPackMatrixMultT<Real>(ma).addUMult(alpha, vx, vr);
168}
169
170void SYCLInternalLinearAlgebra::
171multDiag(const SYCLBEllPackMatrix<Real>& ma,
172 const SYCLVector<Real>& vy,
173 SYCLVector<Real>& vr) const
174{
175#ifdef ALIEN_USE_PERF_TIMER
176 SentryType s(m_timer, "SYCL-MULTDIAG");
177#endif
178 Internal::SYCLBEllPackMatrixMultT<Real>(ma).multDiag(vy,vr);
179}
180
181void SYCLInternalLinearAlgebra::
182multDiag(const SYCLVector<Real>& diag,
183 const SYCLVector<Real>& vy,
184 SYCLVector<Real>& vr) const
185{
186#ifdef ALIEN_USE_PERF_TIMER
187 SentryType s(m_timer, "SYCL-MULTDIAG");
188#endif
189 diag.pointWiseMult(vy,vr);
190}
191
192
193void SYCLInternalLinearAlgebra::
194multInvDiag(const SYCLBEllPackMatrix<Real>& ma,
195 SYCLVector<Real>& vr) const
196{
197#ifdef ALIEN_USE_PERF_TIMER
198 SentryType s(m_timer, "SYCL-MULTINVDIAG");
199#endif
200 Internal::SYCLBEllPackMatrixMultT<Real>(ma).multInvDiag(vr);
201}
202
203void SYCLInternalLinearAlgebra::
204computeInvDiag(const SYCLBEllPackMatrix<Real>& ma,
205 SYCLVector<Real>& vr) const
206{
207#ifdef ALIEN_USE_PERF_TIMER
208 SentryType s(m_timer, "SYCL-INVDIAG");
209#endif
210 Internal::SYCLBEllPackMatrixMultT<Real>(ma).computeInvDiag(vr);
211}
212
213/*---------------------------------------------------------------------------*/
214
215void SYCLInternalLinearAlgebra::axpy(Real alpha, const SYCLVector<Real>& vx, SYCLVector<Real>& vr) const
216{
217#ifdef ALIEN_USE_PERF_TIMER
218 SentryType s(m_timer, "SYCL-AXPY");
219#endif
220 m_internal->axpy(alpha, vx.internal()->values(), vr.internal()->values());
221}
222
223/*---------------------------------------------------------------------------*/
224
225void SYCLInternalLinearAlgebra::aypx(Real alpha ALIEN_UNUSED_PARAM,
226 SYCLVector<Real>& y ALIEN_UNUSED_PARAM,
227 const SYCLVector<Real>& x ALIEN_UNUSED_PARAM) const
228{
229 throw NotImplementedException(
230 A_FUNCINFO, "SYCLLinearAlgebra::aypx not implemented");
231}
232
233/*---------------------------------------------------------------------------*/
234
235void SYCLInternalLinearAlgebra::copy(const SYCLVector<Real>& vx, SYCLVector<Real>& vr) const
236{
237#ifdef ALIEN_USE_PERF_TIMER
238 SentryType s(m_timer, "SYCL-COPY");
239#endif
240 m_internal->copy(vx.internal()->values(), vr.internal()->values());
241}
242
243
244void SYCLInternalLinearAlgebra::axpy(Real alpha,
245 const SYCLVector<Real>& vx,
246 Integer stride_x,
247 SYCLVector<Real>& vr,
248 Integer stride_r) const
249{
250#ifdef ALIEN_USE_PERF_TIMER
251 SentryType s(m_timer, "SYCL-AXPY");
252#endif
253 m_internal->axpy(alpha, vx.internal()->values(), stride_x, vr.internal()->values(), stride_r);
254}
255
256/*---------------------------------------------------------------------------*/
257
258void SYCLInternalLinearAlgebra::aypx(Real alpha ALIEN_UNUSED_PARAM,
259 SYCLVector<Real>& y ALIEN_UNUSED_PARAM,
260 Integer stride_y ALIEN_UNUSED_PARAM,
261 const SYCLVector<Real>& x ALIEN_UNUSED_PARAM,
262 Integer stride_x ALIEN_UNUSED_PARAM) const
263{
264 throw NotImplementedException(
265 A_FUNCINFO, "SYCLLinearAlgebra::aypx not implemented");
266}
267
268/*---------------------------------------------------------------------------*/
269
270void SYCLInternalLinearAlgebra::copy(const SYCLVector<Real>& vx,
271 Integer stride_x,
272 SYCLVector<Real>& vr,
273 Integer stride_r) const
274{
275#ifdef ALIEN_USE_PERF_TIMER
276 SentryType s(m_timer, "SYCL-COPY");
277#endif
278 m_internal->copy(vx.internal()->values(), stride_x, vr.internal()->values(), stride_r);
279}
280
281/*---------------------------------------------------------------------------*/
282
283Real SYCLInternalLinearAlgebra::dot(const SYCLVector<Real>& vx, const SYCLVector<Real>& vy) const
284{
285#ifdef ALIEN_USE_PERF_TIMER
286 SentryType s(m_timer, "SYCL-DOT");
287#endif
288 auto value = m_internal->dot(vx.internal()->values(), vy.internal()->values());
289 auto& dist = vx.distribution();
290 if (dist.isParallel()) {
291 return Arccore::MessagePassing::mpAllReduce(dist.parallelMng(),
292 Arccore::MessagePassing::ReduceSum,
293 value);
294 }
295 return value;
296}
297
298void SYCLInternalLinearAlgebra::dot(const SYCLVector<Real>& vx,
299 const SYCLVector<Real>& vy,
300 SYCLInternal::Future<Real>& res) const
301{
302#ifdef ALIEN_USE_PERF_TIMER
303 SentryType s(m_timer, "SYCL-DOT-F");
304#endif
305 m_internal->dot(vx.internal()->values(), vy.internal()->values(), res);
306
307 auto& dist = vx.distribution();
308 if (dist.isParallel()) {
309 res.get() ;
310 Real local_value = res() ;
311 Real* x = &res();
312 auto request = mpNonBlockingAllReduce(dist.parallelMng(),
313 Arccore::MessagePassing::ReduceSum,
314 Arccore::ConstArrayView<Real>(1,&local_value),
315 Arccore::ArrayView<Real>(1,x)) ;
316 res.addRequest(dist.parallelMng(), request);
317 }
318}
319
320/*---------------------------------------------------------------------------*/
321
322void SYCLInternalLinearAlgebra::scal(Real alpha, SYCLVector<Real>& vx) const
323{
324#ifdef ALIEN_USE_PERF_TIMER
325 SentryType s(m_timer, "SYCL-SCAL");
326#endif
327 return m_internal->scal(alpha, vx.internal()->values());
328}
329
330
331void SYCLInternalLinearAlgebra::scal(SYCLVector<Real> const& vx, SYCLBEllPackMatrix<Real>& ma) const
332{
333#ifdef ALIEN_USE_PERF_TIMER
334 SentryType s(m_timer, "SYCL-SCAL");
335#endif
336 return ma.scal(vx);
337}
338
339void SYCLInternalLinearAlgebra::pointwiseMult(const SYCLVector<Real>& vx,
340 const SYCLVector<Real>& vy,
341 SYCLVector<Real>& vz) const
342{
343#ifdef ALIEN_USE_PERF_TIMER
344 SentryType s(m_timer, "SYCL-XYZ");
345#endif
346 return m_internal->pointwiseMult(vx.internal()->values(), vy.internal()->values(), vz.internal()->values());
347}
348
349void SYCLInternalLinearAlgebra::assign(SYCLVector<Real>& vx, Real alpha) const
350{
351#ifdef ALIEN_USE_PERF_TIMER
352 SentryType s(m_timer, "SYCL-ASSIGN");
353#endif
354 return m_internal->assign(alpha, vx.internal()->values());
355}
356
357void SYCLInternalLinearAlgebra::diagonal(
358const SYCLBEllPackMatrix<Real>& ma, SYCLVector<Real>& vx) const
359{
360#ifdef ALIEN_USE_PERF_TIMER
361 SentryType s(m_timer, "SYCL-DIAG");
362#endif
363 Internal::SYCLBEllPackMatrixMultT<Real>(ma).computeDiag(vx);
364}
365
366void SYCLInternalLinearAlgebra::reciprocal(SYCLVector<Real>& x ALIEN_UNUSED_PARAM) const
367{
368 throw NotImplementedException(
369 A_FUNCINFO, "SYCLLinearAlgebra::reciprocal not implemented");
370}
371
372
373Integer SYCLInternalLinearAlgebra::computeCxr(const Matrix& a, Matrix& cxr_a) const
374{
375 auto block_size = a.blockSize() ;
376 cxr_a.setBlockSize(1) ;
377 cxr_a.copy(a) ;
378 return block_size ;
379}
380
381Integer SYCLInternalLinearAlgebra::computeCxr(const Matrix& a, const Vector& diag, Matrix& cxr_a) const
382{
383 auto block_size = a.blockSize() ;
384 cxr_a.setBlockSize(1) ;
385 cxr_a.copy(a) ;
386 cxr_a.scal(diag);
387 return block_size ;
388}
389
390
391
392
393SYCLInternalLinearAlgebraExpr::SYCLInternalLinearAlgebraExpr()
394: IInternalLinearAlgebraExpr<SYCLBEllPackMatrix<Real>, SYCLVector<Real>>()
395{
396 m_internal.reset(new SYCLInternal::KernelInternal());
397}
398
399/*---------------------------------------------------------------------------*/
400
401SYCLInternalLinearAlgebraExpr::~SYCLInternalLinearAlgebraExpr() {}
402
403/*---------------------------------------------------------------------------*/
404/*---------------------------------------------------------------------------*/
405
406Real SYCLInternalLinearAlgebraExpr::norm0(const SYCLVector<Real>& vx ALIEN_UNUSED_PARAM) const
407{
408 // return SYCLBLASKernel::nrm0(x.space().structInfo(),vx);
409 throw NotImplementedException(
410 A_FUNCINFO, "SYCLLinearAlgebra::norm0 not implemented");
411}
412
413/*---------------------------------------------------------------------------*/
414
415Real SYCLInternalLinearAlgebraExpr::norm1(const SYCLVector<Real>& vx ALIEN_UNUSED_PARAM) const
416{
417 // return SYCLBLASKernel::nrm1(x.space().structInfo(),vx);
418 throw NotImplementedException(
419 A_FUNCINFO, "SYCLLinearAlgebra::norm1 not implemented");
420}
421
422/*---------------------------------------------------------------------------*/
423
424Real SYCLInternalLinearAlgebraExpr::norm2(const SYCLVector<Real>& vx) const
425{
426 return std::sqrt(m_internal->dot(vx.internal()->values(), vx.internal()->values()));
427}
428
429Real SYCLInternalLinearAlgebraExpr::normInf([[maybe_unused]] const SYCLVector<Real>& vx) const
430{
431#ifdef ALIEN_USE_PERF_TIMER
432 SentryType s(m_timer, "SYCL-NORMINF");
433#endif
434 throw NotImplementedException(
435 A_FUNCINFO, "SYCLLinearAlgebra::normInf not implemented");
436}
437/*---------------------------------------------------------------------------*/
438
439void SYCLInternalLinearAlgebraExpr::mult(
440const SYCLBEllPackMatrix<Real>& ma, const SYCLVector<Real>& vx, SYCLVector<Real>& vr) const
441{
442 Internal::SYCLBEllPackMatrixMultT<Real>(ma).mult(vx, vr);
443}
444
445void SYCLInternalLinearAlgebraExpr::mult(
446const SYCLBEllPackMatrix<Real>& ma, const UniqueArray<Real>& vx, UniqueArray<Real>& vr) const
447{
448 Internal::SYCLBEllPackMatrixMultT<Real>(ma).mult(vx, vr);
449}
450
451/*---------------------------------------------------------------------------*/
452
453void SYCLInternalLinearAlgebraExpr::axpy([[maybe_unused]] Real alpha,
454 [[maybe_unused]] const UniqueArray<Real>& vx,
455 [[maybe_unused]] UniqueArray<Real>& vr) const
456{
457 throw NotImplementedException(
458 A_FUNCINFO, "SYCLLinearAlgebra::axpy not implemented");
459}
460
461void SYCLInternalLinearAlgebraExpr::axpy(Real alpha, const SYCLVector<Real>& vx, SYCLVector<Real>& vy) const
462{
463 m_internal->axpy(alpha, vx.internal()->values(), vy.internal()->values());
464}
465
466/*---------------------------------------------------------------------------*/
467
468void SYCLInternalLinearAlgebraExpr::aypx([[maybe_unused]] Real alpha, [[maybe_unused]] UniqueArray<Real>& vy, [[maybe_unused]] UniqueArray<Real> const& vx) const
469{
470 throw NotImplementedException(
471 A_FUNCINFO, "SYCLLinearAlgebra::aypx not implemented");
472}
473
474void SYCLInternalLinearAlgebraExpr::aypx(Real alpha ALIEN_UNUSED_PARAM,
475 SYCLVector<Real>& y ALIEN_UNUSED_PARAM, const SYCLVector<Real>& x ALIEN_UNUSED_PARAM) const
476{
477 throw NotImplementedException(
478 A_FUNCINFO, "SYCLLinearAlgebra::aypx not implemented");
479}
480
481/*---------------------------------------------------------------------------*/
482
483void SYCLInternalLinearAlgebraExpr::copy([[maybe_unused]] const UniqueArray<Real>& vx,
484 [[maybe_unused]] UniqueArray<Real>& vr) const
485{
486 throw NotImplementedException(
487 A_FUNCINFO, "SYCLLinearAlgebra::copy not implemented");
488}
489
490void SYCLInternalLinearAlgebraExpr::copy(const SYCLVector<Real>& vx, SYCLVector<Real>& vy) const
491{
492 m_internal->copy(vx.internal()->values(), vy.internal()->values());
493}
494
495/*---------------------------------------------------------------------------*/
496
497Real SYCLInternalLinearAlgebraExpr::dot([[maybe_unused]]
498Integer local_size, [[maybe_unused]] const UniqueArray<Real>& vx, [[maybe_unused]] const UniqueArray<Real>& vy) const
499{
500 throw NotImplementedException(
501 A_FUNCINFO, "SYCLLinearAlgebra::dot not implemented");
502}
503
504Real SYCLInternalLinearAlgebraExpr::dot(const SYCLVector<Real>& vx, const SYCLVector<Real>& vy) const
505{
506 return m_internal->dot(vx.internal()->values(), vy.internal()->values());
507}
508
509Real SYCLInternalLinearAlgebraExpr::norm2([[maybe_unused]] const SYCLBEllPackMatrix<Real>& a) const
510{
511 throw NotImplementedException(
512 A_FUNCINFO, "SYCLLinearAlgebra::notm2 not implemented");
513}
514
515void SYCLInternalLinearAlgebraExpr::copy([[maybe_unused]] const SYCLBEllPackMatrix<Real>& a, [[maybe_unused]] SYCLBEllPackMatrix<Real>& r) const
516{
517 throw NotImplementedException(
518 A_FUNCINFO, "SYCLLinearAlgebra::copy not implemented");
519}
520
521void SYCLInternalLinearAlgebraExpr::add([[maybe_unused]] const SYCLBEllPackMatrix<Real>& a, [[maybe_unused]] SYCLBEllPackMatrix<Real>& r) const
522{
523 throw NotImplementedException(
524 A_FUNCINFO, "SYCLLinearAlgebra::add not implemented");
525}
526
527void SYCLInternalLinearAlgebraExpr::scal([[maybe_unused]] Real alpha, [[maybe_unused]] SYCLBEllPackMatrix<Real>& a) const
528{
529 throw NotImplementedException(
530 A_FUNCINFO, "SYCLLinearAlgebra::scal not implemented");
531}
532/*---------------------------------------------------------------------------*/
533void SYCLInternalLinearAlgebraExpr::scal(Real alpha ALIEN_UNUSED_PARAM, UniqueArray<Real>& x ALIEN_UNUSED_PARAM) const
534{
535 throw NotImplementedException(
536 A_FUNCINFO, "SYCLLinearAlgebra::scal not implemented");
537}
538
539void SYCLInternalLinearAlgebraExpr::scal(Real alpha ALIEN_UNUSED_PARAM, SYCLVector<Real>& x ALIEN_UNUSED_PARAM) const
540{
541 throw NotImplementedException(
542 A_FUNCINFO, "SYCLLinearAlgebra::aypx not implemented");
543}
544
545void SYCLInternalLinearAlgebraExpr::diagonal(
546const SYCLBEllPackMatrix<Real>& a ALIEN_UNUSED_PARAM, SYCLVector<Real>& x ALIEN_UNUSED_PARAM) const
547{
548 throw NotImplementedException(
549 A_FUNCINFO, "SYCLLinearAlgebra::aypx not implemented");
550}
551
552void SYCLInternalLinearAlgebraExpr::reciprocal(SYCLVector<Real>& x ALIEN_UNUSED_PARAM) const
553{
554 throw NotImplementedException(
555 A_FUNCINFO, "SYCLLinearAlgebra::aypx not implemented");
556}
557
558void SYCLInternalLinearAlgebraExpr::pointwiseMult(const SYCLVector<Real>& x ALIEN_UNUSED_PARAM,
559 const SYCLVector<Real>& y ALIEN_UNUSED_PARAM, SYCLVector<Real>& w ALIEN_UNUSED_PARAM) const
560{
561 throw NotImplementedException(
562 A_FUNCINFO, "SYCLLinearAlgebra::aypx not implemented");
563}
564
565template class ALIEN_EXPORT SYCLInternal::Future<double>;
566
567namespace SYCLInternal
568{
569template <>
570sycl::buffer<double>& KernelInternal::getWorkBuffer(std::size_t size)
571{
572 if (m_double_work == nullptr) {
573 m_double_work = new sycl::buffer<double>(size);
574 m_double_work->set_final_data(nullptr);
575 }
576 else {
577 if (size > m_double_work->size()) {
578 delete m_double_work;
579 m_double_work = new sycl::buffer<double>(size);
580 m_double_work->set_final_data(nullptr);
581 }
582 }
583 return *m_double_work;
584}
585}
586
587} // namespace Alien
588
589/*---------------------------------------------------------------------------*/
590/*---------------------------------------------------------------------------*/
LinearAlgebraExprT.h.
LinearAlgebraT.h.
Internal linear algebra interface.
Internal linear algebra interface.
Linear algebra interface.
Linear algebra interface.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
Definition BackEnd.h:17