1// RUN: mlir-opt %s --sparse-compiler | \
2// RUN: mlir-cpu-runner \
3// RUN:  -e entry -entry-point-result=void  \
4// RUN:  -shared-libs=%mlir_integration_test_dir/libmlir_c_runner_utils%shlibext | \
5// RUN: FileCheck %s
6
7#SparseVector = #sparse_tensor.encoding<{ dimLevelType = [ "compressed" ] }>
8
9#trait_op = {
10  indexing_maps = [
11    affine_map<(i) -> (i)>, // a
12    affine_map<(i) -> (i)>  // x (out)
13  ],
14  iterator_types = ["parallel"],
15  doc = "x(i) = OP a(i)"
16}
17
18module {
19  // Performs sign operation (using semi-ring unary op)
20  // with semantics that
21  // > 0 : +1.0
22  // < 0 : -1.0
23  // +Inf: +1.0
24  // -Inf: -1.0
25  // +NaN: +NaN
26  // -NaN: -NaN
27  // +0.0: +0.0
28  // -0.0: -0.0
29  func.func @sparse_sign(%arg0: tensor<?xf64, #SparseVector>)
30                             -> tensor<?xf64, #SparseVector> {
31    %c0 = arith.constant 0 : index
32    %d = tensor.dim %arg0, %c0 : tensor<?xf64, #SparseVector>
33    %xin = bufferization.alloc_tensor(%d) : tensor<?xf64, #SparseVector>
34    %0 = linalg.generic #trait_op
35      ins(%arg0: tensor<?xf64, #SparseVector>)
36      outs(%xin: tensor<?xf64, #SparseVector>) {
37      ^bb0(%a: f64, %x: f64) :
38        %result = sparse_tensor.unary %a : f64 to f64
39          present={
40            ^bb1(%s: f64):
41              %z = arith.constant 0.0 : f64
42              %1 = arith.cmpf one, %s, %z : f64
43              %2 = arith.uitofp %1 : i1 to f64
44              %3 = math.copysign %2, %s : f64
45              %4 = arith.cmpf uno, %s, %s : f64
46              %5 = arith.select %4, %s, %3 : f64
47              sparse_tensor.yield %5 : f64
48          }
49          absent={}
50        linalg.yield %result : f64
51    } -> tensor<?xf64, #SparseVector>
52    return %0 : tensor<?xf64, #SparseVector>
53  }
54
55  // Driver method to call and verify sign kernel.
56  func.func @entry() {
57    %c0 = arith.constant 0 : index
58    %du = arith.constant 99.99 : f64
59
60    %pnan = arith.constant 0x7FF0000001000000 : f64
61    %nnan = arith.constant 0xFFF0000001000000 : f64
62    %pinf = arith.constant 0x7FF0000000000000 : f64
63    %ninf = arith.constant 0xFFF0000000000000 : f64
64
65    // Setup sparse vector.
66    %v1 = arith.constant sparse<
67       [ [0], [3], [5], [11], [13], [17], [18], [20], [21], [28], [29], [31] ],
68         [ -1.5, 1.5, -10.2, 11.3, 1.0, -1.0,
69           0x7FF0000001000000, // +NaN
70           0xFFF0000001000000, // -NaN
71           0x7FF0000000000000, // +Inf
72           0xFFF0000000000000, // -Inf
73           -0.0,               // -Zero
74           0.0                 // +Zero
75        ]
76    > : tensor<32xf64>
77    %sv1 = sparse_tensor.convert %v1
78         : tensor<32xf64> to tensor<?xf64, #SparseVector>
79
80    // Call sign kernel.
81    %0 = call @sparse_sign(%sv1) : (tensor<?xf64, #SparseVector>)
82                                 -> tensor<?xf64, #SparseVector>
83
84    //
85    // Verify the results.
86    //
87    // CHECK: ( -1, 1, -1, 1, 1, -1, nan, -nan, 1, -1, -0, 0, 99.99 )
88    //
89    %1 = sparse_tensor.values %0 : tensor<?xf64, #SparseVector> to memref<?xf64>
90    %2 = vector.transfer_read %1[%c0], %du: memref<?xf64>, vector<13xf64>
91    vector.print %2 : vector<13xf64>
92
93    // Release the resources.
94    bufferization.dealloc_tensor %sv1 : tensor<?xf64, #SparseVector>
95    bufferization.dealloc_tensor %0 : tensor<?xf64, #SparseVector>
96    return
97  }
98}
99
100
101