1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
|
//==============================================================================
//=== sfmult_vector_1 ==========================================================
//==============================================================================
// SFMULT, Copyright (c) 2009, Timothy A Davis. All Rights Reserved.
// SPDX-License-Identifier: BSD-3-clause
// y = A*x or A'*x where x is a vector
// sfmult_AN_x_1 y = A*x x is n-by-1, y is m-by-1
// sfmult_AT_x_1 y = A'*x x is m-by-1, y is n-by-1
#include "sfmult.h"
//==============================================================================
//=== sfmult_AN_x_1 ============================================================
//==============================================================================
void sfmult_AN_x_1 // y = A*x x is n-by-1 unit stride, y is m-by-1
(
// --- outputs, not initialized on input
double *Yx, // m-by-1
double *Yz, // m-by-1 if Y is complex (TO DO)
// --- inputs, not modified
const Int *Ap, // size n+1 column pointers
const Int *Ai, // size nz = Ap[n] row indices
const double *Ax, // size nz values
const double *Az, // size nz imaginary values if A is complex (TO DO)
Int m, // A is m-by-n
Int n,
const double *Xx, // n-by-1
const double *Xz, // n-by-1 if X complex
int ac, // true: use conj(A), otherwise use A (TO DO)
int xc, // true: use conj(X), otherwise use X (TO DO)
int yc // true: compute conj(Y), otherwise compute Y (TO DO)
)
{
double y [4], x ;
Int p, pend, i, j, i0, i1, i2, i3 ;
for (i = 0 ; i < m ; i++)
{
Yx [i] = 0 ;
}
p = 0 ;
for (j = 0 ; j < n ; j++)
{
pend = Ap [j+1] ;
x = Xx [j] ;
switch ((pend - p) % 4)
{
case 3: Yx [Ai [p]] += Ax [p] * x ; p++ ;
case 2: Yx [Ai [p]] += Ax [p] * x ; p++ ;
case 1: Yx [Ai [p]] += Ax [p] * x ; p++ ;
case 0: ;
}
for ( ; p < pend ; p += 4)
{
i0 = Ai [p ] ;
i1 = Ai [p+1] ;
i2 = Ai [p+2] ;
i3 = Ai [p+3] ;
y [0] = Yx [i0] + Ax [p ] * x ;
y [1] = Yx [i1] + Ax [p+1] * x ;
y [2] = Yx [i2] + Ax [p+2] * x ;
y [3] = Yx [i3] + Ax [p+3] * x ;
Yx [i0] = y [0] ;
Yx [i1] = y [1] ;
Yx [i2] = y [2] ;
Yx [i3] = y [3] ;
}
}
}
//==============================================================================
//=== sfmult_AT_x_1 ============================================================
//==============================================================================
void sfmult_AT_x_1 // y = A'*x x is m-by-1 unit stride, y is n-by-1
(
// --- outputs, not initialized on input
double *Yx, // n-by-1
double *Yz, // n-by-1 if Y is complex (TO DO)
// --- inputs, not modified
const Int *Ap, // size n+1 column pointers
const Int *Ai, // size nz = Ap[n] row indices
const double *Ax, // size nz values
const double *Az, // size nz imaginary values if A is complex (TO DO)
Int m, // A is m-by-n
Int n,
const double *Xx, // m-by-1
const double *Xz, // m-by-1 if X complex
int ac, // true: use conj(A), otherwise use A (TO DO)
int xc, // true: use conj(X), otherwise use X (TO DO)
int yc // true: compute conj(Y), otherwise compute Y (TO DO)
)
{
double y ;
Int p, pend, j ;
p = 0 ;
for (j = 0 ; j < n ; j++)
{
pend = Ap [j+1] ;
y = 0 ;
switch ((pend - p) % 4)
{
case 3: y += Ax [p] * Xx [Ai [p]] ; p++ ;
case 2: y += Ax [p] * Xx [Ai [p]] ; p++ ;
case 1: y += Ax [p] * Xx [Ai [p]] ; p++ ;
case 0: ;
}
for ( ; p < pend ; p += 4)
{
y += Ax [p ] * Xx [Ai [p ]] ;
y += Ax [p+1] * Xx [Ai [p+1]] ;
y += Ax [p+2] * Xx [Ai [p+2]] ;
y += Ax [p+3] * Xx [Ai [p+3]] ;
}
Yx [j] = y ;
}
}
|