ALP User Documentation 0.7.0
Algebraic Programming User Documentation
blas0.hpp
Go to the documentation of this file.
1
2/*
3 * Copyright 2021 Huawei Technologies Co., Ltd.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
27#ifndef _H_GRB_BLAS0
28#define _H_GRB_BLAS0
29
30#include <functional>
31#include <stdexcept>
32#include <type_traits> //enable_if
33
35#include "graphblas/rc.hpp"
37
38#define NO_CAST_ASSERT( x, y, z ) \
39 static_assert( x, \
40 "\n\n" \
41 "************************************************************************" \
42 "************************************************************************" \
43 "**********************\n" \
44 "* ERROR | " y " " z ".\n" \
45 "************************************************************************" \
46 "************************************************************************" \
47 "**********************\n" \
48 "* Possible fix 1 | Remove no_casting from the template parameters in " \
49 "this call to " y ".\n" \
50 "* Possible fix 2 | Provide a left-hand side input value of the same " \
51 "type as the first domain of the given operator.\n" \
52 "* Possible fix 3 | Provide a right-hand side input value of the same " \
53 "type as the second domain of the given operator.\n" \
54 "* Possible fix 4 | Provide an output value of the same type as the " \
55 "third domain of the given operator.\n" \
56 "* Note that in case of in-place operators the left-hand side input or " \
57 "right-hand side input also play the role of the output value.\n" \
58 "************************************************************************" \
59 "************************************************************************" \
60 "**********************\n" );
61
62
63namespace grb {
64
174 template<
176 class OP,
177 typename InputType1, typename InputType2, typename OutputType
178 >
179 static enum RC apply(
180 OutputType &out,
181 const InputType1 &x,
182 const InputType2 &y,
183 const OP &op = OP(),
184 const typename std::enable_if<
189 void >::type * = nullptr
190 ) {
191 // static sanity check
192 NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || (
193 std::is_same< InputType1, typename OP::D1 >::value &&
194 std::is_same< InputType2, typename OP::D2 >::value &&
195 std::is_same< OutputType, typename OP::D3 >::value
196 ) ),
197 "grb::apply (BLAS level 0)",
198 "Argument value types do not match operator domains while no_casting "
199 "descriptor was set"
200 );
201
202 // call apply
203 const typename OP::D1 left = static_cast< typename OP::D1 >( x );
204 const typename OP::D2 right = static_cast< typename OP::D2 >( y );
205 typename OP::D3 output = static_cast< typename OP::D3 >( out );
206 op.apply( left, right, output );
207 out = static_cast< OutputType >( output );
208
209 // done
210 return SUCCESS;
211 }
212
283 template<
285 class OP, typename InputType, typename IOType
286 >
287 static RC foldr(
288 const InputType &x,
289 IOType &y,
290 const OP &op = OP(),
291 const typename std::enable_if<
295 >::type * = nullptr
296 ) {
297 // static sanity check
298 NO_CAST_ASSERT( ( !(descr & descriptors::no_casting) || (
299 std::is_same< InputType, typename OP::D1 >::value &&
300 std::is_same< IOType, typename OP::D2 >::value &&
301 std::is_same< IOType, typename OP::D3 >::value
302 ) ), "grb::foldr (BLAS level 0)",
303 "Argument value types do not match operator domains while no_casting "
304 "descriptor was set" );
305
306 // call foldr
307 const typename OP::D1 left = static_cast< typename OP::D1 >( x );
308 typename OP::D3 right = static_cast< typename OP::D3 >( y );
309 op.foldr( left, right );
310 y = static_cast< IOType >( right );
311
312 // done
313 return SUCCESS;
314 }
315
386 template<
388 class OP,
389 typename InputType, typename IOType
390 >
391 static RC foldl(
392 IOType &x,
393 const InputType &y,
394 const OP &op = OP(),
395 const typename std::enable_if< grb::is_operator< OP >::value &&
398 >::type * = nullptr
399 ) {
400 // static sanity check
401 NO_CAST_ASSERT( ( !(descr & descriptors::no_casting) || (
402 std::is_same< IOType, typename OP::D1 >::value &&
403 std::is_same< InputType, typename OP::D2 >::value &&
404 std::is_same< IOType, typename OP::D3 >::value
405 ) ), "grb::foldl (BLAS level 0)",
406 "Argument value types do not match operator domains while no_casting "
407 "descriptor was set" );
408
409 // call foldl
410 typename OP::D1 left = static_cast< typename OP::D1 >( x );
411 const typename OP::D3 right = static_cast< typename OP::D3 >( y );
412 op.foldl( left, right );
413 x = static_cast< IOType >( left );
414
415 // done
416 return SUCCESS;
417 }
418
421 namespace internal {
422
437 template<
438 grb::Descriptor descr,
439 typename OutputType, typename D,
440 typename Enabled = void
441 >
442 class ValueOrIndex;
443
444 /* Version where use_index is allowed. */
445 template< grb::Descriptor descr, typename OutputType, typename D >
446 class ValueOrIndex<
447 descr,
448 OutputType, D,
449 typename std::enable_if<
450 std::is_arithmetic< OutputType >::value &&
451 !std::is_same< D, void >::value
452 >::type
453 > {
454
455 private:
456
457 static constexpr const bool use_index = descr & grb::descriptors::use_index;
458
459 static_assert( use_index || std::is_convertible< D, OutputType >::value,
460 "Cannot convert to the requested output type" );
461
462
463 public:
464
465 static OutputType getFromArray(
466 const D * __restrict__ const x,
467 const std::function< size_t( size_t ) > &src_local_to_global,
468 const size_t index
469 ) noexcept {
470 if( use_index ) {
471 return static_cast< OutputType >( src_local_to_global( index ) );
472 } else {
473 return static_cast< OutputType >( x[ index ] );
474 }
475 }
476
477 static OutputType getFromScalar( const D &x, const size_t index ) noexcept {
478 if( use_index ) {
479 return static_cast< OutputType >( index );
480 } else {
481 return static_cast< OutputType >( x );
482 }
483 }
484
485 };
486
487 /* Version where use_index is not allowed. */
488 template< grb::Descriptor descr, typename OutputType, typename D >
489 class ValueOrIndex<
490 descr,
491 OutputType, D,
492 typename std::enable_if<
493 !std::is_arithmetic< OutputType >::value &&
494 !std::is_same< OutputType, void >::value
495 >::type
496 > {
497
498 static_assert( !(descr & descriptors::use_index),
499 "use_index descriptor given while output type is not numeric" );
500
501 static_assert( std::is_convertible< D, OutputType >::value,
502 "Cannot convert input to the given output type" );
503
504 public:
505
506 static OutputType getFromArray(
507 const D * __restrict__ const x,
508 const std::function< size_t( size_t ) > &,
509 const size_t index
510 ) noexcept {
511 return static_cast< OutputType >( x[ index ] );
512 }
513
514 static OutputType getFromScalar(
515 const D &x, const size_t
516 ) noexcept {
517 return static_cast< OutputType >( x );
518 }
519
520 };
521
542 template<
543 bool identity_left,
544 typename OutputType, typename InputType,
545 template< typename > class Identity,
546 typename Enabled = void
547 >
548 class CopyOrApplyWithIdentity;
549
550 /* The cast-and-assign version */
551 template<
552 bool identity_left,
553 typename OutputType, typename InputType,
554 template< typename > class Identity
555 >
556 class CopyOrApplyWithIdentity<
557 identity_left,
558 OutputType, InputType,
559 Identity,
560 typename std::enable_if<
561 std::is_convertible< InputType, OutputType >::value
562 >::type
563 > {
564
565 public:
566
567 template< typename Operator >
568 static void set( OutputType &out, const InputType &in, const Operator & ) {
569 out = static_cast< OutputType >( in );
570 }
571
572 };
573
574 /* The operator with identity version */
575 template<
576 bool identity_left,
577 typename OutputType, typename InputType,
578 template< typename > class Identity
579 >
580 class CopyOrApplyWithIdentity<
581 identity_left,
582 OutputType, InputType,
583 Identity,
584 typename std::enable_if<
585 !std::is_convertible< InputType, OutputType >::value
586 >::type
587 > {
588
589 public:
590
591 template< typename Operator >
592 static void set(
593 OutputType &out, const InputType &in, const Operator &op
594 ) {
595 const auto identity = identity_left ?
596 Identity< typename Operator::D1 >::value() :
597 Identity< typename Operator::D2 >::value();
598 if( identity_left ) {
599 (void) grb::apply( out, identity, in, op );
600 } else {
601 (void) grb::apply( out, in, identity, op );
602 }
603 }
604
605 };
606
607 } // namespace internal
608
609} // namespace grb
610
611#undef NO_CAST_ASSERT
612
613#endif // end ``_H_GRB_BLAS0''
614
Defines all ALP/GraphBLAS descriptors.
static enum RC apply(OutputType &out, const InputType1 &x, const InputType2 &y, const OP &op=OP(), const typename std::enable_if< grb::is_operator< OP >::value &&!grb::is_object< InputType1 >::value &&!grb::is_object< InputType2 >::value &&!grb::is_object< OutputType >::value, void >::type *=nullptr)
Out-of-place application of the operator OP on two data elements.
Definition: blas0.hpp:179
RC foldr(const Vector< InputType, backend, Coords > &x, const Vector< MaskType, backend, Coords > &mask, IOType &y, const Monoid &monoid=Monoid(), const typename std::enable_if< !grb::is_object< IOType >::value &&!grb::is_object< InputType >::value &&!grb::is_object< MaskType >::value &&grb::is_monoid< Monoid >::value, void >::type *const =nullptr)
Folds a vector into a scalar, right-to-left.
Definition: blas1.hpp:3943
RC foldl(IOType &x, const Vector< InputType, backend, Coords > &y, const Vector< MaskType, backend, Coords > &mask, const Monoid &monoid=Monoid(), const typename std::enable_if< !grb::is_object< IOType >::value &&!grb::is_object< InputType >::value &&!grb::is_object< MaskType >::value &&grb::is_monoid< Monoid >::value, void >::type *const =nullptr)
Reduces, or folds, a vector into a scalar.
Definition: blas1.hpp:3840
RC set(Vector< DataType, backend, Coords > &x, const T val, const Phase &phase=EXECUTE, const typename std::enable_if< !grb::is_object< DataType >::value &&!grb::is_object< T >::value, void >::type *const =nullptr) noexcept
Sets all elements of a vector to the given value.
Definition: io.hpp:857
static constexpr Descriptor no_casting
Disallows the standard casting of input parameters to a compatible domain in case they did not match ...
Definition: descriptors.hpp:196
static constexpr Descriptor use_index
Instead of using input vector elements, use the index of those elements.
Definition: descriptors.hpp:167
static constexpr Descriptor no_operation
Indicates no additional pre- or post-processing on any of the GraphBLAS function arguments.
Definition: descriptors.hpp:63
The ALP/GraphBLAS namespace.
Definition: graphblas.hpp:452
RC
Return codes of ALP primitives.
Definition: rc.hpp:47
@ SUCCESS
Indicates the primitive has executed successfully.
Definition: rc.hpp:54
unsigned int Descriptor
Descriptors indicate pre- or post-processing for some or all of the arguments to an ALP/GraphBLAS cal...
Definition: descriptors.hpp:54
Defines the ALP error codes.
Used to inspect whether a given type is an ALP/GraphBLAS object.
Definition: type_traits.hpp:130
Used to inspect whether a given type is an ALP operator.
Definition: type_traits.hpp:104
Specifies the ALP algebraic type traits.