Skip to content

Commit e4816ac

Browse files
committed
Handling double-negated operators associativity
1 parent f8a2e7f commit e4816ac

File tree

4 files changed

+46
-20
lines changed

4 files changed

+46
-20
lines changed

include/graphblas/base/internalops.hpp

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,6 @@ namespace grb {
3939

4040
namespace operators {
4141

42-
43-
4442
/** Core implementations of the standard operators in #grb::operators. */
4543
namespace internal {
4644

@@ -55,13 +53,14 @@ namespace grb {
5553
* - \b D1: The left-hand input domain.
5654
* - \b D2: The right-hand input domain.
5755
* - \b D3: The output domain, must be convertible to bool.
58-
* - \b operator_type: The internal::operator type to negate.
56+
* - \b OperatorType: The internal::operator type to negate.
5957
*/
6058
template<
6159
class Op,
6260
enum Backend implementation = config::default_backend
6361
>
6462
class logical_not {
63+
6564
public:
6665

6766
/** Alias to the left-hand input data type. */
@@ -74,24 +73,26 @@ namespace grb {
7473
typedef typename Op::D3 result_type;
7574

7675
/** Whether this operator has an inplace foldl. */
77-
static constexpr bool has_foldl = Op::operator_type::has_foldl;
76+
static constexpr bool has_foldl = Op::OperatorType::has_foldl;
7877

7978
/** Whether this operator has an inplace foldr. */
80-
static constexpr bool has_foldr = Op::operator_type::has_foldr;
79+
static constexpr bool has_foldr = Op::OperatorType::has_foldr;
8180

8281
/**
8382
* Whether this operator is \em mathematically associative; that is,
8483
* associative when assuming equivalent data types for \a IN1, \a IN2,
8584
* and \a OUT, as well as assuming exact arithmetic, no overflows, etc.
8685
*/
87-
static constexpr bool is_associative = Op::operator_type::is_associative;
86+
static constexpr bool is_associative = is_lnegated< Op >::value
87+
? Op::OperatorType::is_associative
88+
: false;
8889

8990
/**
9091
* Whether this operator is \em mathematically commutative; that is,
9192
* commutative when assuming equivalent data types for \a IN1, \a IN2,
9293
* and \a OUT, as well as assuming exact arithmetic, no overflows, etc.
9394
*/
94-
static constexpr bool is_commutative = Op::operator_type::is_commutative;
95+
static constexpr bool is_commutative = Op::OperatorType::is_commutative;
9596

9697
/**
9798
* Out-of-place application of the operator.
@@ -111,10 +112,8 @@ namespace grb {
111112
void
112113
>::type * = nullptr
113114
) {
114-
115-
Op::operator_type::apply( a, b, c );
115+
Op::OperatorType::apply( a, b, c );
116116
*c = !*c;
117-
118117
}
119118

120119
/**
@@ -132,10 +131,8 @@ namespace grb {
132131
void
133132
>::type * = nullptr
134133
) {
135-
136-
Op::operator_type::foldr( a, c );
134+
Op::OperatorType::foldr( a, c );
137135
*c = !*c;
138-
139136
}
140137

141138
/**
@@ -153,10 +150,8 @@ namespace grb {
153150
void
154151
>::type * = nullptr
155152
) {
156-
157-
Op::operator_type::foldl( c, b );
153+
Op::OperatorType::foldl( c, b );
158154
*c = !*c;
159-
160155
}
161156
};
162157

@@ -4298,7 +4293,7 @@ namespace grb {
42984293
typedef typename OperatorBase< OP >::D3 D3;
42994294

43004295
/** The type of the operator OP. */
4301-
typedef OP operator_type;
4296+
typedef OP OperatorType;
43024297

43034298
/**
43044299
* Reduces a vector of type \a InputType into a value in \a IOType

include/graphblas/ops.hpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1237,6 +1237,15 @@ namespace grb {
12371237
static constexpr const bool value = OP::is_commutative();
12381238
};
12391239

1240+
template< typename OP >
1241+
struct is_lnegated<
1242+
operators::logical_not< OP >,
1243+
typename std::enable_if< is_operator< OP >::value, void >::type
1244+
> {
1245+
static constexpr const bool value = true;
1246+
};
1247+
1248+
12401249
// internal type traits follow
12411250

12421251
namespace internal {

include/graphblas/type_traits.hpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,27 @@ namespace grb {
226226
static const constexpr bool value = true;
227227
};
228228

229+
/**
230+
* Used to inspect whether a given operator is logically negated.
231+
*
232+
* @tparam T The operator to inspect.
233+
*
234+
* An example of a commutative operator is numerical addition,
235+
* #grb::operators::add.
236+
*
237+
* \ingroup typeTraits
238+
*/
239+
template< typename T, typename = void >
240+
struct is_lnegated {
241+
242+
static_assert( is_operator< T >::value,
243+
"Template argument should be an ALP binary operator." );
244+
245+
/** Whether \a T is logically negated. */
246+
static const constexpr bool value = false;
247+
248+
};
249+
229250
/**
230251
* Used to inspect whether a given operator or monoid is commutative.
231252
*

tests/unit/operator_logical_not.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
using namespace grb;
2424

25-
void grb_program( const size_t & n, grb::RC & rc ) {
25+
void grb_program( const size_t &n, grb::RC &rc ) {
2626
(void)n;
2727

2828
{ // Test: logical_and< bool > just to make sure it works
@@ -75,9 +75,10 @@ int main( int argc, char ** argv ) {
7575
return 255;
7676
}
7777
if( out != SUCCESS ) {
78-
std::cerr << "Test FAILED (" << grb::toString( out ) << ")" << std::endl;
78+
std::cerr << std::flush;
79+
std::cout << "Test FAILED (" << grb::toString( out ) << ")\n" << std::flush;
7980
} else {
80-
std::cout << "Test OK" << std::endl;
81+
std::cout << "Test OK\n" << std::flush;
8182
}
8283
return 0;
8384
}

0 commit comments

Comments
 (0)