PPL  1.2
OR_Matrix_inlines.hh
Go to the documentation of this file.
1 /* OR_Matrix class implementation: inline functions.
2  Copyright (C) 2001-2010 Roberto Bagnara <bagnara@cs.unipr.it>
3  Copyright (C) 2010-2016 BUGSENG srl (http://bugseng.com)
4 
5 This file is part of the Parma Polyhedra Library (PPL).
6 
7 The PPL is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 The PPL is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software Foundation,
19 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307, USA.
20 
21 For the most up-to-date information see the Parma Polyhedra Library
22 site: http://bugseng.com/products/ppl/ . */
23 
24 #ifndef PPL_OR_Matrix_inlines_hh
25 #define PPL_OR_Matrix_inlines_hh 1
26 
27 #include "globals_defs.hh"
28 #include "Checked_Number_defs.hh"
29 #include "C_Polyhedron_defs.hh"
30 #include "distances_defs.hh"
31 #include "assertions.hh"
32 #include "checked_defs.hh"
33 #include <algorithm>
34 
35 namespace Parma_Polyhedra_Library {
36 
37 template <typename T>
38 inline dimension_type
40  return ((k + 1)*(k + 1))/2;
41 }
42 
43 template <typename T>
44 inline dimension_type
46  return k + 2 - k % 2;
47 }
48 
49 #if PPL_OR_MATRIX_EXTRA_DEBUG
50 
51 template <typename T>
52 template <typename U>
53 inline dimension_type
55  return size_;
56 }
57 
58 #endif // PPL_OR_MATRIX_EXTRA_DEBUG
59 
60 template <typename T>
61 template <typename U>
62 inline
64  : first(0)
66  , size_(0)
67 #endif
68 {
69 }
70 
71 template <typename T>
72 template <typename U>
73 inline
76  , dimension_type s
77 #endif
78  )
79  : first(&y)
80 #if PPL_OR_MATRIX_EXTRA_DEBUG
81  , size_(s)
82 #endif
83 {
84 }
85 
86 template <typename T>
87 template <typename U>
88 template <typename V>
89 inline
91  : first(y.first)
93  , size_(y.size_)
94 #endif
95 {
96 }
97 
98 template <typename T>
99 template <typename U>
100 inline OR_Matrix<T>::Pseudo_Row<U>&
102  first = y.first;
103 #if PPL_OR_MATRIX_EXTRA_DEBUG
104  size_ = y.size_;
105 #endif
106  return *this;
107 }
108 
109 template <typename T>
110 template <typename U>
111 inline
113 }
114 
115 template <typename T>
116 template <typename U>
117 inline U&
119 #if PPL_OR_MATRIX_EXTRA_DEBUG
120  PPL_ASSERT(k < size_);
121 #endif
122  return *(first + k);
123 }
124 
125 template <typename T>
126 template <typename U>
127 inline
130  : value(),
131  e(n_rows)
132  // Field `i' is intentionally not initialized here.
133 {
134 #if PPL_OR_MATRIX_EXTRA_DEBUG
135  // Turn `value' into a valid object.
136  value.size_ = OR_Matrix::row_size(e);
137 #endif
138 }
139 
140 template <typename T>
141 template <typename U>
142 inline
144  : value(base
146  , OR_Matrix<T>::row_size(0)
147 #endif
148  ),
149  e(0),
150  i(0) {
151 }
152 
153 template <typename T>
154 template <typename U>
155 template <typename V>
156 inline
159  : value(y.value),
160  e(y.e),
161  i(y.i) {
162 }
163 
164 template <typename T>
165 template <typename U>
166 template <typename V>
169  value = y.value;
170  e = y.e;
171  i = y.i;
172  return *this;
173 }
174 
175 template <typename T>
176 template <typename U>
179  return value;
180 }
181 
182 template <typename T>
183 template <typename U>
186  return &value;
187 }
188 
189 template <typename T>
190 template <typename U>
193  ++e;
194  dimension_type increment = e;
195  if (e % 2 != 0) {
196  ++increment;
197  }
198 #if PPL_OR_MATRIX_EXTRA_DEBUG
199  else {
200  value.size_ += 2;
201  }
202 #endif
203  i += increment;
204  value.first += increment;
205  return *this;
206 }
207 
208 template <typename T>
209 template <typename U>
212  any_row_iterator old = *this;
213  ++(*this);
214  return old;
215 }
216 
217 template <typename T>
218 template <typename U>
221  dimension_type decrement = e + 1;
222  --e;
223  if (e % 2 != 0) {
224  ++decrement;
225 #if PPL_OR_MATRIX_EXTRA_DEBUG
226  value.size_ -= 2;
227 #endif
228  }
229  i -= decrement;
230  value.first -= decrement;
231  return *this;
232 }
233 
234 template <typename T>
235 template <typename U>
238  any_row_iterator old = *this;
239  --(*this);
240  return old;
241 }
242 
243 template <typename T>
244 template <typename U>
247  difference_type e_dt = static_cast<difference_type>(e);
248  difference_type i_dt = static_cast<difference_type>(i);
249  difference_type increment = m + (m * m) / 2 + m * e_dt;
250  if (e_dt % 2 == 0 && m % 2 != 0) {
251  ++increment;
252  }
253  e_dt += m;
254  i_dt += increment;
255  e = static_cast<dimension_type>(e_dt);
256  i = static_cast<dimension_type>(i_dt);
257  value.first += increment;
258 #if PPL_OR_MATRIX_EXTRA_DEBUG
259  difference_type value_size_dt = static_cast<difference_type>(value.size_);
260  value_size_dt += (m - m % 2);
261  value.size_ = static_cast<dimension_type>(value_size_dt);
262 #endif
263  return *this;
264 }
265 
266 template <typename T>
267 template <typename U>
268 template <typename Unsigned>
269 inline typename
271  typename OR_Matrix<T>::template any_row_iterator<U>& >::type
273  dimension_type n = m;
274  dimension_type increment = n + (n*n)/2 + n*e;
275  if (e % 2 == 0 && n % 2 != 0) {
276  ++increment;
277  }
278  e += n;
279  i += increment;
280  value.first += increment;
281 #if PPL_OR_MATRIX_EXTRA_DEBUG
282  value.size_ = value.size_ + n - n % 2;
283 #endif
284  return *this;
285 }
286 
287 template <typename T>
288 template <typename U>
291  return *this += -m;
292 }
293 
294 template <typename T>
295 template <typename U>
298  return e - y.e;
299 }
300 
301 template <typename T>
302 template <typename U>
305  any_row_iterator r = *this;
306  r += m;
307  return r;
308 }
309 
310 template <typename T>
311 template <typename U>
312 template <typename Unsigned>
313 inline typename
317  any_row_iterator r = *this;
318  r += m;
319  return r;
320 }
321 
322 template <typename T>
323 template <typename U>
326  any_row_iterator r = *this;
327  r -= m;
328  return r;
329 }
330 
331 template <typename T>
332 template <typename U>
333 inline bool
336  return e == y.e;
337 }
338 
339 template <typename T>
340 template <typename U>
341 inline bool
344  return e != y.e;
345 }
346 
347 template <typename T>
348 template <typename U>
349 inline bool
351  return e < y.e;
352 }
353 
354 template <typename T>
355 template <typename U>
356 inline bool
359  return e <= y.e;
360 }
361 
362 template <typename T>
363 template <typename U>
364 inline bool
366  return e > y.e;
367 }
368 
369 template <typename T>
370 template <typename U>
371 inline bool
374  return e >= y.e;
375 }
376 
377 template <typename T>
378 template <typename U>
379 inline dimension_type
381  return OR_Matrix::row_size(e);
382 }
383 
384 template <typename T>
385 template <typename U>
386 inline dimension_type
388  return e;
389 }
390 
391 template <typename T>
392 inline typename OR_Matrix<T>::row_iterator
394  return num_rows() == 0 ? row_iterator(0) : row_iterator(vec[0]);
395 }
396 
397 template <typename T>
398 inline typename OR_Matrix<T>::row_iterator
400  return row_iterator(num_rows());
401 }
402 
403 template <typename T>
404 inline typename OR_Matrix<T>::const_row_iterator
406  return num_rows() == 0 ? const_row_iterator(0) : const_row_iterator(vec[0]);
407 }
408 
409 template <typename T>
410 inline typename OR_Matrix<T>::const_row_iterator
412  return const_row_iterator(num_rows());
413 }
414 
415 template <typename T>
416 inline typename OR_Matrix<T>::element_iterator
418  return vec.begin();
419 }
420 
421 template <typename T>
422 inline typename OR_Matrix<T>::element_iterator
424  return vec.end();
425 }
426 
427 template <typename T>
430  return vec.begin();
431 }
432 
433 template <typename T>
436  return vec.end();
437 }
438 
439 template <typename T>
440 inline void
442  using std::swap;
443  swap(vec, y.vec);
446 }
447 
448 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
449 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
451 inline dimension_type
453  dimension_type r = 0;
454  const dimension_type FIRST_BIT_MASK = 0x40000000U;
455  for (dimension_type t = FIRST_BIT_MASK; t != 0; t >>= 2) {
456  const dimension_type s = r + t;
457  if (s <= x) {
458  x -= s;
459  r = s + t;
460  }
461  r >>= 1;
462  }
463  return r;
464 }
465 
466 template <typename T>
467 inline dimension_type
469  // Compute the maximum number of rows that are contained in a DB_Row
470  // that allocates a pseudo-triangular matrix.
471  const dimension_type k = isqrt(2*DB_Row<T>::max_size() + 1);
472  return (k - 1) - (k - 1) % 2;
473 }
474 
475 template <typename T>
476 inline memory_size_type
478  return sizeof(*this) + external_memory_in_bytes();
479 }
480 
481 template <typename T>
482 inline
484  : vec(2*num_dimensions*(num_dimensions + 1)),
485  space_dim(num_dimensions),
486  vec_capacity(vec.size()) {
487 }
488 
489 template <typename T>
490 inline
492 }
493 
494 template <typename T>
495 inline typename OR_Matrix<T>::row_reference_type
497  return row_reference_type(vec[row_first_element_index(k)]
499  , row_size(k)
500 #endif
501  );
502 }
503 
504 template <typename T>
507  return const_row_reference_type(vec[row_first_element_index(k)]
509  , row_size(k)
510 #endif
511  );
512 }
513 
514 template <typename T>
515 inline dimension_type
517  return space_dim;
518 }
519 
520 template <typename T>
521 inline dimension_type
523  return 2*space_dimension();
524 }
525 
526 template <typename T>
527 inline void
529  OR_Matrix<T>(0).m_swap(*this);
530 }
531 
532 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
533 
534 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
535 template <typename T>
536 inline bool
537 operator==(const OR_Matrix<T>& x, const OR_Matrix<T>& y) {
538  return x.space_dim == y.space_dim && x.vec == y.vec;
539 }
540 
541 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
542 
543 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
544 template <typename T>
545 inline bool
546 operator!=(const OR_Matrix<T>& x, const OR_Matrix<T>& y) {
547  return !(x == y);
548 }
549 
550 template <typename T>
551 inline
553  : vec(y.vec),
554  space_dim(y.space_dim),
555  vec_capacity(compute_capacity(y.vec.size(),
556  DB_Row<T>::max_size())) {
557 }
558 
559 template <typename T>
560 template <typename U>
561 inline
563  : vec(),
564  space_dim(y.space_dim),
565  vec_capacity(compute_capacity(y.vec.size(),
566  DB_Row<T>::max_size())) {
567  vec.construct_upward_approximation(y.vec, vec_capacity);
568  PPL_ASSERT(OK());
569 }
570 
571 template <typename T>
572 inline OR_Matrix<T>&
574  vec = y.vec;
575  space_dim = y.space_dim;
576  vec_capacity = compute_capacity(y.vec.size(), DB_Row<T>::max_size());
577  return *this;
578 }
579 
580 template <typename T>
581 inline void
583  PPL_ASSERT(new_dim >= space_dim);
584  if (new_dim > space_dim) {
585  const dimension_type new_size = 2*new_dim*(new_dim + 1);
586  if (new_size <= vec_capacity) {
587  // We can recycle the old vec.
588  vec.expand_within_capacity(new_size);
589  space_dim = new_dim;
590  }
591  else {
592  // We cannot recycle the old vec.
593  OR_Matrix<T> new_matrix(new_dim);
594  element_iterator j = new_matrix.element_begin();
595  for (element_iterator i = element_begin(),
596  mend = element_end(); i != mend; ++i, ++j) {
597  assign_or_swap(*j, *i);
598  }
599  m_swap(new_matrix);
600  }
601  }
602 }
603 
604 template <typename T>
605 inline void
607  PPL_ASSERT(new_dim <= space_dim);
608  const dimension_type new_size = 2*new_dim*(new_dim + 1);
609  vec.shrink(new_size);
610  space_dim = new_dim;
611 }
612 
613 template <typename T>
614 inline void
616  if (new_dim > space_dim) {
617  const dimension_type new_size = 2*new_dim*(new_dim + 1);
618  if (new_size <= vec_capacity) {
619  // We can recycle the old vec.
620  vec.expand_within_capacity(new_size);
621  space_dim = new_dim;
622  }
623  else {
624  // We cannot recycle the old vec.
625  OR_Matrix<T> new_matrix(new_dim);
626  m_swap(new_matrix);
627  }
628  }
629  else if (new_dim < space_dim) {
630  shrink(new_dim);
631  }
632 }
633 
634 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
635 
636 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
637 template <typename Specialization, typename Temp, typename To, typename T>
638 inline bool
640  const OR_Matrix<T>& x,
641  const OR_Matrix<T>& y,
642  const Rounding_Dir dir,
643  Temp& tmp0,
644  Temp& tmp1,
645  Temp& tmp2) {
646  if (x.num_rows() != y.num_rows()) {
647  return false;
648  }
649  assign_r(tmp0, 0, ROUND_NOT_NEEDED);
651  i = x.element_begin(), j = y.element_begin(),
652  mat_end = x.element_end(); i != mat_end; ++i, ++j) {
653  const T& x_i = *i;
654  const T& y_i = *j;
655  if (is_plus_infinity(x_i)) {
656  if (is_plus_infinity(y_i)) {
657  continue;
658  }
659  else {
660  pinf:
662  return true;
663  }
664  }
665  else if (is_plus_infinity(y_i)) {
666  goto pinf;
667  }
668  const Temp* tmp1p;
669  const Temp* tmp2p;
670  if (x_i > y_i) {
671  maybe_assign(tmp1p, tmp1, x_i, dir);
672  maybe_assign(tmp2p, tmp2, y_i, inverse(dir));
673  }
674  else {
675  maybe_assign(tmp1p, tmp1, y_i, dir);
676  maybe_assign(tmp2p, tmp2, x_i, inverse(dir));
677  }
678  sub_assign_r(tmp1, *tmp1p, *tmp2p, dir);
679  PPL_ASSERT(sgn(tmp1) >= 0);
680  Specialization::combine(tmp0, tmp1, dir);
681  }
682 
683  Specialization::finalize(tmp0, dir);
684  assign_r(r, tmp0, dir);
685  return true;
686 }
687 
688 
689 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
690 
691 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
692 template <typename Temp, typename To, typename T>
693 inline bool
695  const OR_Matrix<T>& x,
696  const OR_Matrix<T>& y,
697  const Rounding_Dir dir,
698  Temp& tmp0,
699  Temp& tmp1,
700  Temp& tmp2) {
701  return
702  l_m_distance_assign<Rectilinear_Distance_Specialization<Temp> >(r, x, y,
703  dir,
704  tmp0,
705  tmp1,
706  tmp2);
707 }
708 
709 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
710 
711 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
712 template <typename Temp, typename To, typename T>
713 inline bool
715  const OR_Matrix<T>& x,
716  const OR_Matrix<T>& y,
717  const Rounding_Dir dir,
718  Temp& tmp0,
719  Temp& tmp1,
720  Temp& tmp2) {
721  return
722  l_m_distance_assign<Euclidean_Distance_Specialization<Temp> >(r, x, y,
723  dir,
724  tmp0,
725  tmp1,
726  tmp2);
727 }
728 
729 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
730 
731 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
732 template <typename Temp, typename To, typename T>
733 inline bool
735  const OR_Matrix<T>& x,
736  const OR_Matrix<T>& y,
737  const Rounding_Dir dir,
738  Temp& tmp0,
739  Temp& tmp1,
740  Temp& tmp2) {
741  return
742  l_m_distance_assign<L_Infinity_Distance_Specialization<Temp> >(r, x, y,
743  dir,
744  tmp0,
745  tmp1,
746  tmp2);
747 }
748 
750 template <typename T>
751 inline void
753  x.m_swap(y);
754 }
755 
756 } // namespace Parma_Polyhedra_Library
757 
758 #endif // !defined(PPL_OR_Matrix_inlines_hh)
void swap(OR_Matrix< T > &x, OR_Matrix< T > &y)
Swaps x with y.
friend bool operator==(const OR_Matrix< T > &x, const OR_Matrix< T > &y)
memory_size_type external_memory_in_bytes() const
Returns the size in bytes of the memory managed by *this.
Enable_If< Is_Singleton< T >::value, Interval< B, Info > >::type operator*(const Interval< B, Info > &x, const T &y)
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
bool operator!=(const OR_Matrix< T > &x, const OR_Matrix< T > &y)
Returns true if and only if x and y are different.
bool l_m_distance_assign(Checked_Number< To, Extended_Number_Policy > &r, const OR_Matrix< T > &x, const OR_Matrix< T > &y, const Rounding_Dir dir, Temp &tmp0, Temp &tmp1, Temp &tmp2)
dimension_type num_rows() const
Returns the number of rows in the matrix.
bool operator>(const Ptr_Iterator< P > &x, const Ptr_Iterator< Q > &y)
row_iterator row_end()
Returns the past-the-end const_iterator.
void swap(CO_Tree &x, CO_Tree &y)
void shrink(dimension_type new_dim)
Makes the matrix shrink by removing the last space dimensions.
bool rectilinear_distance_assign(Checked_Number< To, Extended_Number_Policy > &r, const OR_Matrix< T > &x, const OR_Matrix< T > &y, const Rounding_Dir dir, Temp &tmp0, Temp &tmp1, Temp &tmp2)
bool euclidean_distance_assign(Checked_Number< To, Extended_Number_Policy > &r, const OR_Matrix< T > &x, const OR_Matrix< T > &y, const Rounding_Dir dir, Temp &tmp0, Temp &tmp1, Temp &tmp2)
size_t dimension_type
An unsigned integral type for representing space dimensions.
OR_Matrix()
Private and not implemented: default construction is not allowed.
A class to define STL const and non-const iterators from pointer types.
any_row_iterator< T > row_iterator
A (non const) row iterator.
Rounding_Dir
Rounding directions for arithmetic computations.
bool operator>=(const Ptr_Iterator< P > &x, const Ptr_Iterator< Q > &y)
Enable_If< Has_Assign_Or_Swap< T >::value, void >::type assign_or_swap(T &to, T &from)
dimension_type isqrt(dimension_type x)
Returns the integer square root of x.
A template class to derive both OR_Matrix::iterator and OR_Matrix::const_iterator.
bool operator==(const OR_Matrix< T > &x, const OR_Matrix< T > &y)
memory_size_type total_memory_in_bytes() const
Returns the total size in bytes of the memory occupied by *this.
dimension_type space_dimension() const
Returns the space-dimension of the matrix.
void resize_no_copy(dimension_type new_dim)
Resizes the matrix without worrying about the old contents.
bool OK() const
Checks if all the invariants are satisfied.
void m_swap(OR_Matrix &y)
Swaps *this with y.
An object that behaves like a matrix's row with respect to the subscript operators.
dimension_type i
Internal index: i = (e+1)*(e+1)/2.
U * first
Holds a reference to the beginning of this row.
Rounding_Dir inverse(Rounding_Dir dir)
dimension_type compute_capacity(dimension_type requested_size, dimension_type maximum_size)
Speculative allocation function.
The base class for the single rows of matrices.
Definition: DB_Row_defs.hh:120
A wrapper for numeric types implementing a given policy.
element_iterator element_begin()
Returns an iterator pointing to the first element, if *this is not empty; otherwise, returns the past-the-end const_iterator.
#define PPL_OR_MATRIX_EXTRA_DEBUG
static dimension_type row_first_element_index(dimension_type k)
Returns the index into vec of the first element of the row of index k.
void finalize()
Finalizes the library.
Definition: initializer.hh:60
any_row_iterator< const T > const_row_iterator
A const row iterator.
bool operator<(const Ptr_Iterator< P > &x, const Ptr_Iterator< Q > &y)
static dimension_type row_size(dimension_type k)
Returns the size of the row of index k.
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_plus_infinity(const T &x)
Coefficient value
Definition: PIP_Tree.cc:618
void grow(dimension_type new_dim)
Makes the matrix grow by adding more space dimensions.
OR_Matrix & operator=(const OR_Matrix &y)
Assignment operator.
Pseudo_Row< U > value
Represents the beginning of a row.
DB_Row< T > vec
Contains the rows of the matrix.
dimension_type space_dim
Contains the dimension of the space of the matrix.
Plus_Infinity PLUS_INFINITY
Definition: checked.cc:31
The entire library is confined to this namespace.
Definition: version.hh:61
Enable_If< Is_Singleton< T >::value, Interval< B, Info > >::type operator+(const Interval< B, Info > &x, const T &y)
row_reference_type operator[](dimension_type k)
Returns a reference to the k-th row of the matrix.
static dimension_type max_num_rows()
Returns the maximum number of rows of a OR_Matrix.
dimension_type vec_capacity
Contains the capacity of vec.
bool operator<=(const Ptr_Iterator< P > &x, const Ptr_Iterator< Q > &y)
I_Result combine(Result l, Result u)
int sgn(Boundary_Type type, const T &x, const Info &info)
A matrix representing octagonal constraints.
static dimension_type max_size()
Returns the size() of the largest possible DB_Row.
Enable_If< Is_Singleton< T >::value, Interval< B, Info > >::type operator-(const Interval< B, Info > &x, const T &y)
size_t memory_size_type
An unsigned integral type for representing memory size in bytes.
void clear()
Clears the matrix deallocating all its rows.
A class that provides a type member called type equivalent to T if and only if b is true...
row_iterator row_begin()
Returns an iterator pointing to the first row, if *this is not empty; otherwise, returns the past-the...
Result maybe_assign(const To *&top, To &tmp, const From &from, Rounding_Dir dir)
Assigns to top a pointer to a location that holds the conversion, according to dir, of from to type To. When necessary, and only when necessary, the variable tmp is used to hold the result of conversion.
element_iterator element_end()
Returns the past-the-end const_iterator.
bool l_infinity_distance_assign(Checked_Number< To, Extended_Number_Policy > &r, const OR_Matrix< T > &x, const OR_Matrix< T > &y, const Rounding_Dir dir, Temp &tmp0, Temp &tmp1, Temp &tmp2)