Add GMRES example
This commit is contained in:
@@ -73,6 +73,14 @@ This directory includes three implementations of the algorithm:
|
|||||||
light culling and shading.
|
light culling and shading.
|
||||||
|
|
||||||
|
|
||||||
|
GMRES
|
||||||
|
=====
|
||||||
|
|
||||||
|
An implementation of the generalized minimal residual method for solving
|
||||||
|
sparse matrix equations.
|
||||||
|
(http://en.wikipedia.org/wiki/Generalized_minimal_residual_method)
|
||||||
|
|
||||||
|
|
||||||
Mandelbrot
|
Mandelbrot
|
||||||
==========
|
==========
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,22 @@
|
|||||||
|
|
||||||
TASK_CXX=../tasksys.cpp
|
TASK_CXX=../tasksys.cpp
|
||||||
TASK_LIB=-lpthread
|
TASK_LIB=-lpthread
|
||||||
TASK_OBJ=tasksys.o
|
TASK_OBJ=objs/tasksys.o
|
||||||
|
|
||||||
CXX=g++
|
CXX=g++
|
||||||
CXXFLAGS=-Iobjs/ -O2 -m64
|
CXXFLAGS=-Iobjs/ -O2 -m64
|
||||||
|
CC=gcc
|
||||||
|
CCFLAGS=-Iobjs/ -O2 -m64
|
||||||
|
|
||||||
LIBS=-lm $(TASK_LIB) -lstdc++
|
LIBS=-lm $(TASK_LIB) -lstdc++
|
||||||
ISPC=ispc -O2 --arch=x86-64 $(ISPC_FLAGS)
|
ISPC=ispc -O2 --arch=x86-64 $(ISPC_FLAGS)
|
||||||
ISPC_OBJS=$(addprefix objs/, $(ISPC_SRC:.ispc=)_ispc.o $(ISPC_SRC:.ispc=)_ispc_sse2.o \
|
ISPC_OBJS=$(addprefix objs/, $(ISPC_SRC:.ispc=)_ispc.o $(ISPC_SRC:.ispc=)_ispc_sse2.o \
|
||||||
$(ISPC_SRC:.ispc=)_ispc_sse4.o $(ISPC_SRC:.ispc=)_ispc_avx.o)
|
$(ISPC_SRC:.ispc=)_ispc_sse4.o $(ISPC_SRC:.ispc=)_ispc_avx.o)
|
||||||
ISPC_HEADER=objs/$(ISPC_SRC:.ispc=_ispc.h)
|
ISPC_HEADER=objs/$(ISPC_SRC:.ispc=_ispc.h)
|
||||||
CPP_OBJS=$(addprefix objs/, $(CPP_SRC:.cpp=.o) $(TASK_OBJ))
|
|
||||||
|
CPP_OBJS=$(addprefix objs/, $(CPP_SRC:.cpp=.o))
|
||||||
|
CC_OBJS=$(addprefix objs/, $(CC_SRC:.c=.o))
|
||||||
|
OBJS=$(CPP_OBJS) $(CC_OBJS) $(TASK_OBJ) $(ISPC_OBJS)
|
||||||
|
|
||||||
default: $(EXAMPLE)
|
default: $(EXAMPLE)
|
||||||
|
|
||||||
@@ -26,12 +32,15 @@ objs/%.cpp objs/%.o objs/%.h: dirs
|
|||||||
clean:
|
clean:
|
||||||
/bin/rm -rf objs *~ $(EXAMPLE) $(EXAMPLE)-sse4 $(EXAMPLE)-generic16
|
/bin/rm -rf objs *~ $(EXAMPLE) $(EXAMPLE)-sse4 $(EXAMPLE)-generic16
|
||||||
|
|
||||||
$(EXAMPLE): $(CPP_OBJS) $(ISPC_OBJS)
|
$(EXAMPLE): $(OBJS)
|
||||||
$(CXX) $(CXXFLAGS) -o $@ $^ $(LIBS)
|
$(CXX) $(CXXFLAGS) -o $@ $^ $(LIBS)
|
||||||
|
|
||||||
objs/%.o: %.cpp dirs $(ISPC_HEADER)
|
objs/%.o: %.cpp dirs $(ISPC_HEADER)
|
||||||
$(CXX) $< $(CXXFLAGS) -c -o $@
|
$(CXX) $< $(CXXFLAGS) -c -o $@
|
||||||
|
|
||||||
|
objs/%.o: %.c dirs $(ISPC_HEADER)
|
||||||
|
$(CC) $< $(CCFLAGS) -c -o $@
|
||||||
|
|
||||||
objs/%.o: ../%.cpp dirs
|
objs/%.o: ../%.cpp dirs
|
||||||
$(CXX) $< $(CXXFLAGS) -c -o $@
|
$(CXX) $< $(CXXFLAGS) -c -o $@
|
||||||
|
|
||||||
|
|||||||
8
examples/gmres/Makefile
Normal file
8
examples/gmres/Makefile
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
|
||||||
|
EXAMPLE=gmres
|
||||||
|
CPP_SRC=algorithm.cpp main.cpp matrix.cpp
|
||||||
|
CC_SRC=mmio.c
|
||||||
|
ISPC_SRC=matrix.ispc
|
||||||
|
ISPC_TARGETS=sse2,sse4-x2,avx-x2
|
||||||
|
|
||||||
|
include ../common.mk
|
||||||
231
examples/gmres/algorithm.cpp
Normal file
231
examples/gmres/algorithm.cpp
Normal file
@@ -0,0 +1,231 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2012, Intel Corporation
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of Intel Corporation nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||||
|
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||||
|
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*===========================================================================*\
|
||||||
|
|* Includes
|
||||||
|
\*===========================================================================*/
|
||||||
|
#include "algorithm.h"
|
||||||
|
#include "stdio.h"
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*===========================================================================*\
|
||||||
|
|* GMRES
|
||||||
|
\*===========================================================================*/
|
||||||
|
/* upper_triangular_right_solve:
|
||||||
|
* ----------------------------
|
||||||
|
* Given upper triangular matrix R and rhs vector b, solve for
|
||||||
|
* x. This "solve" ignores the rows, columns of R that are greater than the
|
||||||
|
* dimensions of x.
|
||||||
|
*/
|
||||||
|
void upper_triangular_right_solve (const DenseMatrix &R, const Vector &b, Vector &x)
|
||||||
|
{
|
||||||
|
// Dimensionality check
|
||||||
|
ASSERT(R.rows() >= b.size());
|
||||||
|
ASSERT(R.cols() >= x.size());
|
||||||
|
ASSERT(b.size() >= x.size());
|
||||||
|
|
||||||
|
int max_row = x.size() - 1;
|
||||||
|
|
||||||
|
// first solve step:
|
||||||
|
x[max_row] = b[max_row] / R(max_row, max_row);
|
||||||
|
|
||||||
|
for (int row = max_row - 1; row >= 0; row--) {
|
||||||
|
double xi = b[row];
|
||||||
|
for (int col = max_row; col > row; col--)
|
||||||
|
xi -= x[col] * R(row, col);
|
||||||
|
x[row] = xi / R(row, row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create_rotation (used in gmres):
|
||||||
|
* -------------------------------
|
||||||
|
* Construct a Givens rotation to zero out the lowest non-zero entry in a partially
|
||||||
|
* factored Hessenburg matrix. Note that the previous Givens rotations should be
|
||||||
|
* applied to this column before creating a new rotation.
|
||||||
|
*/
|
||||||
|
void create_rotation (const DenseMatrix &H, size_t col, Vector &Cn, Vector &Sn)
|
||||||
|
{
|
||||||
|
double a = H(col, col);
|
||||||
|
double b = H(col + 1, col);
|
||||||
|
double r;
|
||||||
|
|
||||||
|
if (b == 0) {
|
||||||
|
Cn[col] = copysign(1, a);
|
||||||
|
Sn[col] = 0;
|
||||||
|
}
|
||||||
|
else if (a == 0) {
|
||||||
|
Cn[col] = 0;
|
||||||
|
Sn[col] = copysign(1, b);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
r = sqrt(a*a + b*b);
|
||||||
|
Sn[col] = -b / r;
|
||||||
|
Cn[col] = a / r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Applies the 'col'th Givens rotation stored in vectors Sn and Cn to the 'col'th
|
||||||
|
* column of the DenseMatrix M. (Previous columns don't need the rotation applied b/c
|
||||||
|
* presumeably, the first col-1 columns are already upper triangular, and so their
|
||||||
|
* entries in the col and col+1 rows are 0.)
|
||||||
|
*/
|
||||||
|
void apply_rotation (DenseMatrix &H, size_t col, Vector &Cn, Vector &Sn)
|
||||||
|
{
|
||||||
|
double c = Cn[col];
|
||||||
|
double s = Sn[col];
|
||||||
|
double tmp = c * H(col, col) - s * H(col+1, col);
|
||||||
|
H(col+1, col) = s * H(col, col) + c * H(col+1, col);
|
||||||
|
H(col, col) = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Applies the 'col'th Givens rotation to the vector.
|
||||||
|
*/
|
||||||
|
void apply_rotation (Vector &v, size_t col, Vector &Cn, Vector &Sn)
|
||||||
|
{
|
||||||
|
double a = v[col];
|
||||||
|
double b = v[col + 1];
|
||||||
|
|
||||||
|
double c = Cn[col];
|
||||||
|
double s = Sn[col];
|
||||||
|
|
||||||
|
v[col] = c * a - s * b;
|
||||||
|
v[col + 1] = s * a + c * b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Applies the first 'col' Givens rotations to the newly-created column
|
||||||
|
* of H. (Leaves other columns alone.)
|
||||||
|
*/
|
||||||
|
void update_column (DenseMatrix &H, size_t col, Vector &Cn, Vector &Sn)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < col; i++) {
|
||||||
|
double c = Cn[i];
|
||||||
|
double s = Sn[i];
|
||||||
|
double t = c * H(i,col) - s * H(i+1,col);
|
||||||
|
H(i+1, col) = s * H(i,col) + c * H(i+1,col);
|
||||||
|
H(i, col) = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* After a new column has been added to the hessenburg matrix, factor it back into
|
||||||
|
* an upper-triangular matrix by:
|
||||||
|
* - applying the previous Givens rotations to the new column
|
||||||
|
* - computing the new Givens rotation to make the column upper triangluar
|
||||||
|
* - applying the new Givens rotation to the column, and
|
||||||
|
* - applying the new Givens rotation to the solution vector
|
||||||
|
*/
|
||||||
|
void update_qr_decomp (DenseMatrix &H, Vector &s, size_t col, Vector &Cn, Vector &Sn)
|
||||||
|
{
|
||||||
|
update_column( H, col, Cn, Sn);
|
||||||
|
create_rotation(H, col, Cn, Sn);
|
||||||
|
apply_rotation( H, col, Cn, Sn);
|
||||||
|
apply_rotation( s, col, Cn, Sn);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gmres (const Matrix &A, const Vector &b, Vector &x, int num_iters, double max_err)
|
||||||
|
{
|
||||||
|
DEBUG_PRINT("gmres starting!\n");
|
||||||
|
x.zero();
|
||||||
|
|
||||||
|
ASSERT(A.rows() == A.cols());
|
||||||
|
DenseMatrix Qstar(num_iters + 1, A.rows());
|
||||||
|
DenseMatrix H(num_iters + 1, num_iters);
|
||||||
|
|
||||||
|
// arrays for storing parameters of givens rotations
|
||||||
|
Vector Sn(num_iters);
|
||||||
|
Vector Cn(num_iters);
|
||||||
|
|
||||||
|
// array for storing the rhs projected onto the hessenburg's column space
|
||||||
|
Vector G(num_iters+1);
|
||||||
|
G.zero();
|
||||||
|
|
||||||
|
double beta = b.norm();
|
||||||
|
G[0] = beta;
|
||||||
|
|
||||||
|
// temp vector, stores Aqi
|
||||||
|
Vector w(A.rows());
|
||||||
|
|
||||||
|
w.copy(b);
|
||||||
|
w.normalize();
|
||||||
|
Qstar.set_row(0, w);
|
||||||
|
|
||||||
|
int iter = 0;
|
||||||
|
Vector temp(A.rows(), false);
|
||||||
|
double rel_err;
|
||||||
|
|
||||||
|
while (iter < num_iters)
|
||||||
|
{
|
||||||
|
// w = Aqi
|
||||||
|
Qstar.row(iter, temp);
|
||||||
|
A.multiply(temp, w);
|
||||||
|
|
||||||
|
// construct ith column of H, i+1th row of Qstar:
|
||||||
|
for (int row = 0; row <= iter; row++) {
|
||||||
|
Qstar.row(row, temp);
|
||||||
|
H(row, iter) = temp.dot(w);
|
||||||
|
w.add_ax(-H(row, iter), temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
H(iter+1, iter) = w.norm();
|
||||||
|
w.divide(H(iter+1, iter));
|
||||||
|
Qstar.set_row(iter+1, w);
|
||||||
|
|
||||||
|
update_qr_decomp (H, G, iter, Cn, Sn);
|
||||||
|
|
||||||
|
rel_err = fabs(G[iter+1] / beta);
|
||||||
|
|
||||||
|
if (rel_err < max_err)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (iter % 100 == 0)
|
||||||
|
DEBUG_PRINT("Iter %d: %f err\n", iter, rel_err);
|
||||||
|
|
||||||
|
iter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iter == num_iters) {
|
||||||
|
fprintf(stderr, "Error: gmres failed to converge in %d iterations (relative err: %f)\n", num_iters, rel_err);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We've reached an acceptable solution (?):
|
||||||
|
|
||||||
|
DEBUG_PRINT("gmres completed in %d iterations (rel. resid. %f, max %f)\n", num_iters, rel_err, max_err);
|
||||||
|
Vector y(iter+1);
|
||||||
|
upper_triangular_right_solve(H, G, y);
|
||||||
|
for (int i = 0; i < iter + 1; i++) {
|
||||||
|
Qstar.row(i, temp);
|
||||||
|
x.add_ax(y[i], temp);
|
||||||
|
}
|
||||||
|
}
|
||||||
50
examples/gmres/algorithm.h
Normal file
50
examples/gmres/algorithm.h
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2012, Intel Corporation
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of Intel Corporation nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||||
|
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||||
|
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __ALGORITHM_H__
|
||||||
|
#define __ALGORITHM_H__
|
||||||
|
|
||||||
|
#include "matrix.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* Generalized Minimal Residual Method:
|
||||||
|
* -----------------------------------
|
||||||
|
* Takes a square matrix and an rhs and uses GMRES to find an estimate for x.
|
||||||
|
* The specified error is relative.
|
||||||
|
*/
|
||||||
|
void gmres (const Matrix &A, const Vector &b, Vector &x, int num_iters, double err);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
8671
examples/gmres/data/c-18/c-18.mtx
Normal file
8671
examples/gmres/data/c-18/c-18.mtx
Normal file
File diff suppressed because it is too large
Load Diff
2176
examples/gmres/data/c-18/c-18_b.mtx
Normal file
2176
examples/gmres/data/c-18/c-18_b.mtx
Normal file
File diff suppressed because it is too large
Load Diff
17847
examples/gmres/data/c-21/c-21.mtx
Normal file
17847
examples/gmres/data/c-21/c-21.mtx
Normal file
File diff suppressed because it is too large
Load Diff
3516
examples/gmres/data/c-21/c-21_b.mtx
Normal file
3516
examples/gmres/data/c-21/c-21_b.mtx
Normal file
File diff suppressed because it is too large
Load Diff
16346
examples/gmres/data/c-22/c-22.mtx
Normal file
16346
examples/gmres/data/c-22/c-22.mtx
Normal file
File diff suppressed because it is too large
Load Diff
3799
examples/gmres/data/c-22/c-22_b.mtx
Normal file
3799
examples/gmres/data/c-22/c-22_b.mtx
Normal file
File diff suppressed because it is too large
Load Diff
26730
examples/gmres/data/c-25/c-25.mtx
Normal file
26730
examples/gmres/data/c-25/c-25.mtx
Normal file
File diff suppressed because it is too large
Load Diff
3804
examples/gmres/data/c-25/c-25_b.mtx
Normal file
3804
examples/gmres/data/c-25/c-25_b.mtx
Normal file
File diff suppressed because it is too large
Load Diff
55
examples/gmres/debug.h
Normal file
55
examples/gmres/debug.h
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2012, Intel Corporation
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of Intel Corporation nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||||
|
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||||
|
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __DEBUG_H__
|
||||||
|
#define __DEBUG_H__
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************\
|
||||||
|
| Macros
|
||||||
|
\**************************************************************/
|
||||||
|
#define DEBUG
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
#define ASSERT(expr) assert(expr)
|
||||||
|
#define DEBUG_PRINT(...) printf(__VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define ASSERT(expr)
|
||||||
|
#define DEBUG_PRINT(...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
79
examples/gmres/main.cpp
Normal file
79
examples/gmres/main.cpp
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2012, Intel Corporation
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of Intel Corporation nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||||
|
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||||
|
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "matrix.h"
|
||||||
|
#include "algorithm.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include <cmath>
|
||||||
|
#include "../timing.h"
|
||||||
|
|
||||||
|
|
||||||
|
int main (int argc, char **argv)
|
||||||
|
{
|
||||||
|
if (argc < 4) {
|
||||||
|
printf("usage: %s <input-matrix> <input-rhs> <output-file>\n", argv[0]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
double gmres_cycles;
|
||||||
|
|
||||||
|
DEBUG_PRINT("Loading A...\n");
|
||||||
|
Matrix *A = CRSMatrix::matrix_from_mtf(argv[1]);
|
||||||
|
if (A == NULL)
|
||||||
|
return -1;
|
||||||
|
DEBUG_PRINT("... size: %lu\n", A->cols());
|
||||||
|
|
||||||
|
DEBUG_PRINT("Loading b...\n");
|
||||||
|
Vector *b = Vector::vector_from_mtf(argv[2]);
|
||||||
|
if (b == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
Vector x(A->cols());
|
||||||
|
DEBUG_PRINT("Beginning gmres...\n");
|
||||||
|
gmres(*A, *b, x, A->cols() / 2, .01);
|
||||||
|
|
||||||
|
// Write result out to file
|
||||||
|
x.to_mtf(argv[argc-1]);
|
||||||
|
|
||||||
|
// Compute residual (double-check)
|
||||||
|
#ifdef DEBUG
|
||||||
|
Vector bprime(b->size());
|
||||||
|
A->multiply(x, bprime);
|
||||||
|
Vector resid(bprime.size(), &(bprime[0]));
|
||||||
|
resid.subtract(*b);
|
||||||
|
DEBUG_PRINT("residual error check: %lg\n", resid.norm() / b->norm());
|
||||||
|
#endif
|
||||||
|
// Print profiling results
|
||||||
|
DEBUG_PRINT("-- Total mcycles to solve : %.03f --\n", gmres_cycles);
|
||||||
|
}
|
||||||
246
examples/gmres/matrix.cpp
Normal file
246
examples/gmres/matrix.cpp
Normal file
@@ -0,0 +1,246 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2012, Intel Corporation
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of Intel Corporation nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||||
|
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||||
|
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************\
|
||||||
|
| Includes
|
||||||
|
\**************************************************************/
|
||||||
|
#include "matrix.h"
|
||||||
|
#include "matrix_ispc.h"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "mmio.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************\
|
||||||
|
| DenseMatrix methods
|
||||||
|
\**************************************************************/
|
||||||
|
void DenseMatrix::multiply (const Vector &v, Vector &r) const
|
||||||
|
{
|
||||||
|
// Dimensionality check
|
||||||
|
ASSERT(v.size() == cols());
|
||||||
|
ASSERT(r.size() == rows());
|
||||||
|
|
||||||
|
for (int i = 0; i < rows(); i++)
|
||||||
|
r[i] = v.dot(entries + i * num_cols);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Vector *DenseMatrix::row (size_t row) const {
|
||||||
|
return new Vector(num_cols, entries + row * num_cols, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DenseMatrix::row (size_t row, Vector &r) {
|
||||||
|
r.entries = entries + row * cols();
|
||||||
|
r._size = cols();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DenseMatrix::set_row(size_t row, const Vector &v)
|
||||||
|
{
|
||||||
|
ASSERT(v.size() == num_cols);
|
||||||
|
memcpy(entries + row * num_cols, v.entries, num_cols * sizeof(double));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************\
|
||||||
|
| CRSMatrix Methods
|
||||||
|
\**************************************************************/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <vector>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
|
||||||
|
struct entry {
|
||||||
|
int row;
|
||||||
|
int col;
|
||||||
|
double val;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool compare_entries(struct entry i, struct entry j) {
|
||||||
|
if (i.row < j.row)
|
||||||
|
return true;
|
||||||
|
if (i.row > j.row)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return i.col < j.col;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ERR_OUT(...) { fprintf(stderr, __VA_ARGS__); return NULL; }
|
||||||
|
|
||||||
|
CRSMatrix *CRSMatrix::matrix_from_mtf (char *path) {
|
||||||
|
FILE *f;
|
||||||
|
MM_typecode matcode;
|
||||||
|
|
||||||
|
int m, n, nz;
|
||||||
|
|
||||||
|
if ((f = fopen(path, "r")) == NULL)
|
||||||
|
ERR_OUT("Error: %s does not name a valid/readable file.\n", path);
|
||||||
|
|
||||||
|
if (mm_read_banner(f, &matcode) != 0)
|
||||||
|
ERR_OUT("Error: Could not process Matrix Market banner.\n");
|
||||||
|
|
||||||
|
if (mm_is_complex(matcode))
|
||||||
|
ERR_OUT("Error: Application does not support complex numbers.\n")
|
||||||
|
|
||||||
|
if (mm_is_dense(matcode))
|
||||||
|
ERR_OUT("Error: supplied matrix is dense (should be sparse.)\n");
|
||||||
|
|
||||||
|
if (!mm_is_matrix(matcode))
|
||||||
|
ERR_OUT("Error: %s does not encode a matrix.\n", path)
|
||||||
|
|
||||||
|
if (mm_read_mtx_crd_size(f, &m, &n, &nz) != 0)
|
||||||
|
ERR_OUT("Error: could not read matrix size from file.\n");
|
||||||
|
|
||||||
|
if (m != n)
|
||||||
|
ERR_OUT("Error: Application does not support non-square matrices.");
|
||||||
|
|
||||||
|
std::vector<struct entry> entries;
|
||||||
|
entries.resize(nz);
|
||||||
|
|
||||||
|
for (int i = 0; i < nz; i++) {
|
||||||
|
fscanf(f, "%d %d %lg\n", &entries[i].row, &entries[i].col, &entries[i].val);
|
||||||
|
// Adjust from 1-based to 0-based
|
||||||
|
entries[i].row--;
|
||||||
|
entries[i].col--;
|
||||||
|
}
|
||||||
|
|
||||||
|
sort(entries.begin(), entries.end(), compare_entries);
|
||||||
|
|
||||||
|
CRSMatrix *M = new CRSMatrix(m, n, nz);
|
||||||
|
int cur_row = -1;
|
||||||
|
for (int i = 0; i < nz; i++) {
|
||||||
|
while (entries[i].row > cur_row)
|
||||||
|
M->row_offsets[++cur_row] = i;
|
||||||
|
M->entries[i] = entries[i].val;
|
||||||
|
M->columns[i] = entries[i].col;
|
||||||
|
}
|
||||||
|
|
||||||
|
return M;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector *Vector::vector_from_mtf (char *path) {
|
||||||
|
FILE *f;
|
||||||
|
MM_typecode matcode;
|
||||||
|
|
||||||
|
int m, n, nz;
|
||||||
|
|
||||||
|
if ((f = fopen(path, "r")) == NULL)
|
||||||
|
ERR_OUT("Error: %s does not name a valid/readable file.\n", path);
|
||||||
|
|
||||||
|
if (mm_read_banner(f, &matcode) != 0)
|
||||||
|
ERR_OUT("Error: Could not process Matrix Market banner.\n");
|
||||||
|
|
||||||
|
if (mm_is_complex(matcode))
|
||||||
|
ERR_OUT("Error: Application does not support complex numbers.\n")
|
||||||
|
|
||||||
|
if (mm_is_dense(matcode)) {
|
||||||
|
if (mm_read_mtx_array_size(f, &m, &n) != 0)
|
||||||
|
ERR_OUT("Error: could not read matrix size from file.\n");
|
||||||
|
} else {
|
||||||
|
if (mm_read_mtx_crd_size(f, &m, &n, &nz) != 0)
|
||||||
|
ERR_OUT("Error: could not read matrix size from file.\n");
|
||||||
|
}
|
||||||
|
if (n != 1)
|
||||||
|
ERR_OUT("Error: %s does not describe a vector.\n", path);
|
||||||
|
|
||||||
|
Vector *x = new Vector(m);
|
||||||
|
|
||||||
|
if (mm_is_dense(matcode)) {
|
||||||
|
double val;
|
||||||
|
for (int i = 0; i < m; i++) {
|
||||||
|
fscanf(f, "%lg\n", &val);
|
||||||
|
(*x)[i] = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
x->zero();
|
||||||
|
double val;
|
||||||
|
int row;
|
||||||
|
int col;
|
||||||
|
for (int i = 0; i < nz; i++) {
|
||||||
|
fscanf(f, "%d %d %lg\n", &row, &col, &val);
|
||||||
|
(*x)[row-1] = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ERR(...) { fprintf(stderr, __VA_ARGS__); exit(-1); }
|
||||||
|
|
||||||
|
void Vector::to_mtf (char *path) {
|
||||||
|
FILE *f;
|
||||||
|
MM_typecode matcode;
|
||||||
|
|
||||||
|
mm_initialize_typecode(&matcode);
|
||||||
|
mm_set_matrix(&matcode);
|
||||||
|
mm_set_real(&matcode);
|
||||||
|
mm_set_dense(&matcode);
|
||||||
|
mm_set_general(&matcode);
|
||||||
|
|
||||||
|
if ((f = fopen(path, "w")) == NULL)
|
||||||
|
ERR("Error: cannot open/write to %s\n", path);
|
||||||
|
|
||||||
|
mm_write_banner(f, matcode);
|
||||||
|
mm_write_mtx_array_size(f, size(), 1);
|
||||||
|
for (int i = 0; i < size(); i++)
|
||||||
|
fprintf(f, "%lg\n", entries[i]);
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CRSMatrix::multiply (const Vector &v, Vector &r) const
|
||||||
|
{
|
||||||
|
ASSERT(v.size() == cols());
|
||||||
|
ASSERT(r.size() == rows());
|
||||||
|
|
||||||
|
for (int row = 0; row < rows(); row++)
|
||||||
|
{
|
||||||
|
int row_offset = row_offsets[row];
|
||||||
|
int next_offset = ((row + 1 == rows()) ? _nonzeroes : row_offsets[row + 1]);
|
||||||
|
|
||||||
|
double sum = 0;
|
||||||
|
for (int i = row_offset; i < next_offset; i++)
|
||||||
|
{
|
||||||
|
sum += v[columns[i]] * entries[i];
|
||||||
|
}
|
||||||
|
r[row] = sum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CRSMatrix::zero ( )
|
||||||
|
{
|
||||||
|
entries.clear();
|
||||||
|
row_offsets.clear();
|
||||||
|
columns.clear();
|
||||||
|
_nonzeroes = 0;
|
||||||
|
}
|
||||||
279
examples/gmres/matrix.h
Normal file
279
examples/gmres/matrix.h
Normal file
@@ -0,0 +1,279 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2012, Intel Corporation
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of Intel Corporation nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||||
|
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||||
|
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __MATRIX_H__
|
||||||
|
#define __MATRIX_H__
|
||||||
|
|
||||||
|
/**************************************************************\
|
||||||
|
| Includes
|
||||||
|
\**************************************************************/
|
||||||
|
#include <cstring> // size_t
|
||||||
|
#include <cstdlib> // malloc, memcpy, etc.
|
||||||
|
#include <cmath> // sqrt
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "debug.h"
|
||||||
|
#include "matrix_ispc.h"
|
||||||
|
|
||||||
|
|
||||||
|
class DenseMatrix;
|
||||||
|
/**************************************************************\
|
||||||
|
| Vector class
|
||||||
|
\**************************************************************/
|
||||||
|
class Vector {
|
||||||
|
public:
|
||||||
|
static Vector *vector_from_mtf(char *path);
|
||||||
|
void to_mtf (char *path);
|
||||||
|
|
||||||
|
Vector(size_t size, bool alloc_mem=true)
|
||||||
|
{
|
||||||
|
shared_ptr = false;
|
||||||
|
_size = size;
|
||||||
|
|
||||||
|
if (alloc_mem)
|
||||||
|
entries = (double *) malloc(sizeof(double) * _size);
|
||||||
|
else {
|
||||||
|
shared_ptr = true;
|
||||||
|
entries = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector(size_t size, double *content, bool share_ptr=false)
|
||||||
|
{
|
||||||
|
_size = size;
|
||||||
|
if (share_ptr) {
|
||||||
|
entries = content;
|
||||||
|
shared_ptr = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
shared_ptr = false;
|
||||||
|
entries = (double *) malloc(sizeof(double) * _size);
|
||||||
|
memcpy(entries, content, sizeof(double) * _size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~Vector() { if (!shared_ptr) free(entries); }
|
||||||
|
|
||||||
|
const double & operator [] (size_t index) const
|
||||||
|
{
|
||||||
|
ASSERT(index < _size);
|
||||||
|
return *(entries + index);
|
||||||
|
}
|
||||||
|
|
||||||
|
double &operator [] (size_t index)
|
||||||
|
{
|
||||||
|
ASSERT(index < _size);
|
||||||
|
return *(entries + index);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator == (const Vector &v) const
|
||||||
|
{
|
||||||
|
if (v.size() != _size)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (int i = 0; i < _size; i++)
|
||||||
|
if (entries[i] != v[i])
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size() const {return _size; }
|
||||||
|
|
||||||
|
double dot (const Vector &b) const
|
||||||
|
{
|
||||||
|
ASSERT(b.size() == this->size());
|
||||||
|
return ispc::vector_dot(entries, b.entries, size());
|
||||||
|
}
|
||||||
|
|
||||||
|
double dot (const double * const b) const
|
||||||
|
{
|
||||||
|
return ispc::vector_dot(entries, b, size());
|
||||||
|
}
|
||||||
|
|
||||||
|
void zero ()
|
||||||
|
{
|
||||||
|
ispc::zero(entries, size());
|
||||||
|
}
|
||||||
|
|
||||||
|
double norm () const { return sqrtf(dot(entries)); }
|
||||||
|
|
||||||
|
void normalize () { this->divide(this->norm()); }
|
||||||
|
|
||||||
|
void add (const Vector &a)
|
||||||
|
{
|
||||||
|
ASSERT(size() == a.size());
|
||||||
|
ispc::vector_add(entries, a.entries, size());
|
||||||
|
}
|
||||||
|
|
||||||
|
void subtract (const Vector &s)
|
||||||
|
{
|
||||||
|
ASSERT(size() == s.size());
|
||||||
|
ispc::vector_sub(entries, s.entries, size());
|
||||||
|
}
|
||||||
|
|
||||||
|
void multiply (double scalar)
|
||||||
|
{
|
||||||
|
ispc::vector_mult(entries, scalar, size());
|
||||||
|
}
|
||||||
|
|
||||||
|
void divide (double scalar)
|
||||||
|
{
|
||||||
|
ispc::vector_div(entries, scalar, size());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: x may be longer than *(this)
|
||||||
|
void add_ax (double a, const Vector &x) {
|
||||||
|
ASSERT(x.size() >= size());
|
||||||
|
ispc::vector_add_ax(entries, a, x.entries, size());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note that copy only copies the first size() elements of the
|
||||||
|
// supplied vector, i.e. the supplied vector can be longer than
|
||||||
|
// this one. This is useful in least squares calculations.
|
||||||
|
void copy (const Vector &other) {
|
||||||
|
ASSERT(other.size() >= size());
|
||||||
|
memcpy(entries, other.entries, size() * sizeof(double));
|
||||||
|
}
|
||||||
|
|
||||||
|
friend class DenseMatrix;
|
||||||
|
|
||||||
|
private:
|
||||||
|
size_t _size;
|
||||||
|
bool shared_ptr;
|
||||||
|
double *entries;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************\
|
||||||
|
| Matrix base class
|
||||||
|
\**************************************************************/
|
||||||
|
class Matrix {
|
||||||
|
friend class Vector;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Matrix(size_t size_r, size_t size_c)
|
||||||
|
{
|
||||||
|
num_rows = size_r;
|
||||||
|
num_cols = size_c;
|
||||||
|
}
|
||||||
|
~Matrix(){}
|
||||||
|
|
||||||
|
size_t rows() const { return num_rows; }
|
||||||
|
size_t cols() const { return num_cols; }
|
||||||
|
|
||||||
|
virtual void multiply (const Vector &v, Vector &r) const = 0;
|
||||||
|
virtual void zero () = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
size_t num_rows;
|
||||||
|
size_t num_cols;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**************************************************************\
|
||||||
|
| DenseMatrix class
|
||||||
|
\**************************************************************/
|
||||||
|
class DenseMatrix : public Matrix {
|
||||||
|
friend class Vector;
|
||||||
|
|
||||||
|
public:
|
||||||
|
DenseMatrix(size_t size_r, size_t size_c) : Matrix(size_r, size_c)
|
||||||
|
{
|
||||||
|
entries = (double *) malloc(size_r * size_c * sizeof(double));
|
||||||
|
}
|
||||||
|
|
||||||
|
DenseMatrix(size_t size_r, size_t size_c, const double *content) : Matrix (size_r, size_c)
|
||||||
|
{
|
||||||
|
entries = (double *) malloc(size_r * size_c * sizeof(double));
|
||||||
|
memcpy(entries, content, size_r * size_c * sizeof(double));
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void multiply (const Vector &v, Vector &r) const;
|
||||||
|
|
||||||
|
double &operator () (unsigned int r, unsigned int c)
|
||||||
|
{
|
||||||
|
return *(entries + r * num_cols + c);
|
||||||
|
}
|
||||||
|
|
||||||
|
const double &operator () (unsigned int r, unsigned int c) const
|
||||||
|
{
|
||||||
|
return *(entries + r * num_cols + c);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Vector *row(size_t row) const;
|
||||||
|
void row(size_t row, Vector &r);
|
||||||
|
void set_row(size_t row, const Vector &v);
|
||||||
|
|
||||||
|
virtual void zero() { ispc::zero(entries, rows() * cols()); }
|
||||||
|
|
||||||
|
void copy (const DenseMatrix &other)
|
||||||
|
{
|
||||||
|
ASSERT(rows() == other.rows());
|
||||||
|
ASSERT(cols() == other.cols());
|
||||||
|
memcpy(entries, other.entries, rows() * cols() * sizeof(double));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
double *entries;
|
||||||
|
bool shared_ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**************************************************************\
|
||||||
|
| CSRMatrix (compressed row storage, a sparse matrix format)
|
||||||
|
\**************************************************************/
|
||||||
|
class CRSMatrix : public Matrix {
|
||||||
|
public:
|
||||||
|
CRSMatrix (size_t size_r, size_t size_c, size_t nonzeroes) :
|
||||||
|
Matrix(size_r, size_c)
|
||||||
|
{
|
||||||
|
_nonzeroes = nonzeroes;
|
||||||
|
entries.resize(nonzeroes);
|
||||||
|
columns.resize(nonzeroes);
|
||||||
|
row_offsets.resize(size_r);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void multiply(const Vector &v, Vector &r) const;
|
||||||
|
|
||||||
|
virtual void zero();
|
||||||
|
|
||||||
|
static CRSMatrix *matrix_from_mtf (char *path);
|
||||||
|
|
||||||
|
private:
|
||||||
|
unsigned int _nonzeroes;
|
||||||
|
std::vector<double> entries;
|
||||||
|
std::vector<int> row_offsets;
|
||||||
|
std::vector<int> columns;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
122
examples/gmres/matrix.ispc
Normal file
122
examples/gmres/matrix.ispc
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2012, Intel Corporation
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of Intel Corporation nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||||
|
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||||
|
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************\
|
||||||
|
| General
|
||||||
|
\**************************************************************/
|
||||||
|
export void zero (uniform double data[],
|
||||||
|
uniform int size)
|
||||||
|
{
|
||||||
|
foreach (i = 0 ... size)
|
||||||
|
data[i] = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************\
|
||||||
|
| Vector helpers
|
||||||
|
\**************************************************************/
|
||||||
|
export void vector_add (uniform double a[],
|
||||||
|
const uniform double b[],
|
||||||
|
const uniform int size)
|
||||||
|
{
|
||||||
|
foreach (i = 0 ... size)
|
||||||
|
a[i] += b[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
export void vector_sub (uniform double a[],
|
||||||
|
const uniform double b[],
|
||||||
|
const uniform int size)
|
||||||
|
{
|
||||||
|
foreach (i = 0 ... size)
|
||||||
|
a[i] -= b[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
export void vector_mult (uniform double a[],
|
||||||
|
const uniform double b,
|
||||||
|
const uniform int size)
|
||||||
|
{
|
||||||
|
foreach (i = 0 ... size)
|
||||||
|
a[i] *= b;
|
||||||
|
}
|
||||||
|
|
||||||
|
export void vector_div (uniform double a[],
|
||||||
|
const uniform double b,
|
||||||
|
const uniform int size)
|
||||||
|
{
|
||||||
|
foreach (i = 0 ... size)
|
||||||
|
a[i] /= b;
|
||||||
|
}
|
||||||
|
|
||||||
|
export void vector_add_ax (uniform double r[],
|
||||||
|
const uniform double a,
|
||||||
|
const uniform double x[],
|
||||||
|
const uniform int size)
|
||||||
|
{
|
||||||
|
foreach (i = 0 ... size)
|
||||||
|
r[i] += a * x[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
export uniform double vector_dot (const uniform double a[],
|
||||||
|
const uniform double b[],
|
||||||
|
const uniform int size)
|
||||||
|
{
|
||||||
|
varying double sum = 0.0;
|
||||||
|
foreach (i = 0 ... size)
|
||||||
|
sum += a[i] * b[i];
|
||||||
|
return reduce_add(sum);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************\
|
||||||
|
| Matrix helpers
|
||||||
|
\**************************************************************/
|
||||||
|
export void sparse_multiply (const uniform double entries[],
|
||||||
|
const uniform double columns[],
|
||||||
|
const uniform double row_offsets[],
|
||||||
|
const uniform int rows,
|
||||||
|
const uniform int cols,
|
||||||
|
const uniform int nonzeroes,
|
||||||
|
const uniform double v[],
|
||||||
|
uniform double r[])
|
||||||
|
{
|
||||||
|
foreach (row = 0 ... rows) {
|
||||||
|
int row_offset = row_offsets[row];
|
||||||
|
int next_offset = ((row + 1 == rows) ? nonzeroes : row_offsets[row+1]);
|
||||||
|
|
||||||
|
double sum = 0;
|
||||||
|
for (int j = row_offset; j < next_offset; j++)
|
||||||
|
sum += v[columns[j]] * entries[j];
|
||||||
|
r[row] = sum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
511
examples/gmres/mmio.c
Normal file
511
examples/gmres/mmio.c
Normal file
@@ -0,0 +1,511 @@
|
|||||||
|
/*
|
||||||
|
* Matrix Market I/O library for ANSI C
|
||||||
|
*
|
||||||
|
* See http://math.nist.gov/MatrixMarket for details.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include "mmio.h"
|
||||||
|
|
||||||
|
int mm_read_unsymmetric_sparse(const char *fname, int *M_, int *N_, int *nz_,
|
||||||
|
double **val_, int **I_, int **J_)
|
||||||
|
{
|
||||||
|
FILE *f;
|
||||||
|
MM_typecode matcode;
|
||||||
|
int M, N, nz;
|
||||||
|
int i;
|
||||||
|
double *val;
|
||||||
|
int *I, *J;
|
||||||
|
|
||||||
|
if ((f = fopen(fname, "r")) == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
|
||||||
|
if (mm_read_banner(f, &matcode) != 0)
|
||||||
|
{
|
||||||
|
printf("mm_read_unsymetric: Could not process Matrix Market banner ");
|
||||||
|
printf(" in file [%s]\n", fname);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if ( !(mm_is_real(matcode) && mm_is_matrix(matcode) &&
|
||||||
|
mm_is_sparse(matcode)))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Sorry, this application does not support ");
|
||||||
|
fprintf(stderr, "Market Market type: [%s]\n",
|
||||||
|
mm_typecode_to_str(matcode));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* find out size of sparse matrix: M, N, nz .... */
|
||||||
|
|
||||||
|
if (mm_read_mtx_crd_size(f, &M, &N, &nz) !=0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "read_unsymmetric_sparse(): could not parse matrix size.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*M_ = M;
|
||||||
|
*N_ = N;
|
||||||
|
*nz_ = nz;
|
||||||
|
|
||||||
|
/* reseve memory for matrices */
|
||||||
|
|
||||||
|
I = (int *) malloc(nz * sizeof(int));
|
||||||
|
J = (int *) malloc(nz * sizeof(int));
|
||||||
|
val = (double *) malloc(nz * sizeof(double));
|
||||||
|
|
||||||
|
*val_ = val;
|
||||||
|
*I_ = I;
|
||||||
|
*J_ = J;
|
||||||
|
|
||||||
|
/* NOTE: when reading in doubles, ANSI C requires the use of the "l" */
|
||||||
|
/* specifier as in "%lg", "%lf", "%le", otherwise errors will occur */
|
||||||
|
/* (ANSI C X3.159-1989, Sec. 4.9.6.2, p. 136 lines 13-15) */
|
||||||
|
|
||||||
|
for (i=0; i<nz; i++)
|
||||||
|
{
|
||||||
|
fscanf(f, "%d %d %lg\n", &I[i], &J[i], &val[i]);
|
||||||
|
I[i]--; /* adjust from 1-based to 0-based */
|
||||||
|
J[i]--;
|
||||||
|
}
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mm_is_valid(MM_typecode matcode)
|
||||||
|
{
|
||||||
|
if (!mm_is_matrix(matcode)) return 0;
|
||||||
|
if (mm_is_dense(matcode) && mm_is_pattern(matcode)) return 0;
|
||||||
|
if (mm_is_real(matcode) && mm_is_hermitian(matcode)) return 0;
|
||||||
|
if (mm_is_pattern(matcode) && (mm_is_hermitian(matcode) ||
|
||||||
|
mm_is_skew(matcode))) return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mm_read_banner(FILE *f, MM_typecode *matcode)
|
||||||
|
{
|
||||||
|
char line[MM_MAX_LINE_LENGTH];
|
||||||
|
char banner[MM_MAX_TOKEN_LENGTH];
|
||||||
|
char mtx[MM_MAX_TOKEN_LENGTH];
|
||||||
|
char crd[MM_MAX_TOKEN_LENGTH];
|
||||||
|
char data_type[MM_MAX_TOKEN_LENGTH];
|
||||||
|
char storage_scheme[MM_MAX_TOKEN_LENGTH];
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
|
||||||
|
mm_clear_typecode(matcode);
|
||||||
|
|
||||||
|
if (fgets(line, MM_MAX_LINE_LENGTH, f) == NULL)
|
||||||
|
return MM_PREMATURE_EOF;
|
||||||
|
|
||||||
|
if (sscanf(line, "%s %s %s %s %s", banner, mtx, crd, data_type,
|
||||||
|
storage_scheme) != 5)
|
||||||
|
return MM_PREMATURE_EOF;
|
||||||
|
|
||||||
|
for (p=mtx; *p!='\0'; *p=tolower(*p),p++); /* convert to lower case */
|
||||||
|
for (p=crd; *p!='\0'; *p=tolower(*p),p++);
|
||||||
|
for (p=data_type; *p!='\0'; *p=tolower(*p),p++);
|
||||||
|
for (p=storage_scheme; *p!='\0'; *p=tolower(*p),p++);
|
||||||
|
|
||||||
|
/* check for banner */
|
||||||
|
if (strncmp(banner, MatrixMarketBanner, strlen(MatrixMarketBanner)) != 0)
|
||||||
|
return MM_NO_HEADER;
|
||||||
|
|
||||||
|
/* first field should be "mtx" */
|
||||||
|
if (strcmp(mtx, MM_MTX_STR) != 0)
|
||||||
|
return MM_UNSUPPORTED_TYPE;
|
||||||
|
mm_set_matrix(matcode);
|
||||||
|
|
||||||
|
|
||||||
|
/* second field describes whether this is a sparse matrix (in coordinate
|
||||||
|
storgae) or a dense array */
|
||||||
|
|
||||||
|
|
||||||
|
if (strcmp(crd, MM_SPARSE_STR) == 0)
|
||||||
|
mm_set_sparse(matcode);
|
||||||
|
else
|
||||||
|
if (strcmp(crd, MM_DENSE_STR) == 0)
|
||||||
|
mm_set_dense(matcode);
|
||||||
|
else
|
||||||
|
return MM_UNSUPPORTED_TYPE;
|
||||||
|
|
||||||
|
|
||||||
|
/* third field */
|
||||||
|
|
||||||
|
if (strcmp(data_type, MM_REAL_STR) == 0)
|
||||||
|
mm_set_real(matcode);
|
||||||
|
else
|
||||||
|
if (strcmp(data_type, MM_COMPLEX_STR) == 0)
|
||||||
|
mm_set_complex(matcode);
|
||||||
|
else
|
||||||
|
if (strcmp(data_type, MM_PATTERN_STR) == 0)
|
||||||
|
mm_set_pattern(matcode);
|
||||||
|
else
|
||||||
|
if (strcmp(data_type, MM_INT_STR) == 0)
|
||||||
|
mm_set_integer(matcode);
|
||||||
|
else
|
||||||
|
return MM_UNSUPPORTED_TYPE;
|
||||||
|
|
||||||
|
|
||||||
|
/* fourth field */
|
||||||
|
|
||||||
|
if (strcmp(storage_scheme, MM_GENERAL_STR) == 0)
|
||||||
|
mm_set_general(matcode);
|
||||||
|
else
|
||||||
|
if (strcmp(storage_scheme, MM_SYMM_STR) == 0)
|
||||||
|
mm_set_symmetric(matcode);
|
||||||
|
else
|
||||||
|
if (strcmp(storage_scheme, MM_HERM_STR) == 0)
|
||||||
|
mm_set_hermitian(matcode);
|
||||||
|
else
|
||||||
|
if (strcmp(storage_scheme, MM_SKEW_STR) == 0)
|
||||||
|
mm_set_skew(matcode);
|
||||||
|
else
|
||||||
|
return MM_UNSUPPORTED_TYPE;
|
||||||
|
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mm_write_mtx_crd_size(FILE *f, int M, int N, int nz)
|
||||||
|
{
|
||||||
|
if (fprintf(f, "%d %d %d\n", M, N, nz) != 3)
|
||||||
|
return MM_COULD_NOT_WRITE_FILE;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mm_read_mtx_crd_size(FILE *f, int *M, int *N, int *nz )
|
||||||
|
{
|
||||||
|
char line[MM_MAX_LINE_LENGTH];
|
||||||
|
int num_items_read;
|
||||||
|
|
||||||
|
/* set return null parameter values, in case we exit with errors */
|
||||||
|
*M = *N = *nz = 0;
|
||||||
|
|
||||||
|
/* now continue scanning until you reach the end-of-comments */
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (fgets(line,MM_MAX_LINE_LENGTH,f) == NULL)
|
||||||
|
return MM_PREMATURE_EOF;
|
||||||
|
}while (line[0] == '%');
|
||||||
|
|
||||||
|
/* line[] is either blank or has M,N, nz */
|
||||||
|
if (sscanf(line, "%d %d %d", M, N, nz) == 3)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
else
|
||||||
|
do
|
||||||
|
{
|
||||||
|
num_items_read = fscanf(f, "%d %d %d", M, N, nz);
|
||||||
|
if (num_items_read == EOF) return MM_PREMATURE_EOF;
|
||||||
|
}
|
||||||
|
while (num_items_read != 3);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int mm_read_mtx_array_size(FILE *f, int *M, int *N)
|
||||||
|
{
|
||||||
|
char line[MM_MAX_LINE_LENGTH];
|
||||||
|
int num_items_read;
|
||||||
|
/* set return null parameter values, in case we exit with errors */
|
||||||
|
*M = *N = 0;
|
||||||
|
|
||||||
|
/* now continue scanning until you reach the end-of-comments */
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (fgets(line,MM_MAX_LINE_LENGTH,f) == NULL)
|
||||||
|
return MM_PREMATURE_EOF;
|
||||||
|
}while (line[0] == '%');
|
||||||
|
|
||||||
|
/* line[] is either blank or has M,N, nz */
|
||||||
|
if (sscanf(line, "%d %d", M, N) == 2)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
else /* we have a blank line */
|
||||||
|
do
|
||||||
|
{
|
||||||
|
num_items_read = fscanf(f, "%d %d", M, N);
|
||||||
|
if (num_items_read == EOF) return MM_PREMATURE_EOF;
|
||||||
|
}
|
||||||
|
while (num_items_read != 2);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mm_write_mtx_array_size(FILE *f, int M, int N)
|
||||||
|
{
|
||||||
|
if (fprintf(f, "%d %d\n", M, N) != 2)
|
||||||
|
return MM_COULD_NOT_WRITE_FILE;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
/* use when I[], J[], and val[]J, and val[] are already allocated */
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
int mm_read_mtx_crd_data(FILE *f, int M, int N, int nz, int I[], int J[],
|
||||||
|
double val[], MM_typecode matcode)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
if (mm_is_complex(matcode))
|
||||||
|
{
|
||||||
|
for (i=0; i<nz; i++)
|
||||||
|
if (fscanf(f, "%d %d %lg %lg", &I[i], &J[i], &val[2*i], &val[2*i+1])
|
||||||
|
!= 4) return MM_PREMATURE_EOF;
|
||||||
|
}
|
||||||
|
else if (mm_is_real(matcode))
|
||||||
|
{
|
||||||
|
for (i=0; i<nz; i++)
|
||||||
|
{
|
||||||
|
if (fscanf(f, "%d %d %lg\n", &I[i], &J[i], &val[i])
|
||||||
|
!= 3) return MM_PREMATURE_EOF;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (mm_is_pattern(matcode))
|
||||||
|
{
|
||||||
|
for (i=0; i<nz; i++)
|
||||||
|
if (fscanf(f, "%d %d", &I[i], &J[i])
|
||||||
|
!= 2) return MM_PREMATURE_EOF;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return MM_UNSUPPORTED_TYPE;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int mm_read_mtx_crd_entry(FILE *f, int *I, int *J,
|
||||||
|
double *real, double *imag, MM_typecode matcode)
|
||||||
|
{
|
||||||
|
if (mm_is_complex(matcode))
|
||||||
|
{
|
||||||
|
if (fscanf(f, "%d %d %lg %lg", I, J, real, imag)
|
||||||
|
!= 4) return MM_PREMATURE_EOF;
|
||||||
|
}
|
||||||
|
else if (mm_is_real(matcode))
|
||||||
|
{
|
||||||
|
if (fscanf(f, "%d %d %lg\n", I, J, real)
|
||||||
|
!= 3) return MM_PREMATURE_EOF;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (mm_is_pattern(matcode))
|
||||||
|
{
|
||||||
|
if (fscanf(f, "%d %d", I, J) != 2) return MM_PREMATURE_EOF;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return MM_UNSUPPORTED_TYPE;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
mm_read_mtx_crd() fills M, N, nz, array of values, and return
|
||||||
|
type code, e.g. 'MCRS'
|
||||||
|
|
||||||
|
if matrix is complex, values[] is of size 2*nz,
|
||||||
|
(nz pairs of real/imaginary values)
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
int mm_read_mtx_crd(char *fname, int *M, int *N, int *nz, int **I, int **J,
|
||||||
|
double **val, MM_typecode *matcode)
|
||||||
|
{
|
||||||
|
int ret_code;
|
||||||
|
FILE *f;
|
||||||
|
|
||||||
|
if (strcmp(fname, "stdin") == 0) f=stdin;
|
||||||
|
else
|
||||||
|
if ((f = fopen(fname, "r")) == NULL)
|
||||||
|
return MM_COULD_NOT_READ_FILE;
|
||||||
|
|
||||||
|
|
||||||
|
if ((ret_code = mm_read_banner(f, matcode)) != 0)
|
||||||
|
return ret_code;
|
||||||
|
|
||||||
|
if (!(mm_is_valid(*matcode) && mm_is_sparse(*matcode) &&
|
||||||
|
mm_is_matrix(*matcode)))
|
||||||
|
return MM_UNSUPPORTED_TYPE;
|
||||||
|
|
||||||
|
if ((ret_code = mm_read_mtx_crd_size(f, M, N, nz)) != 0)
|
||||||
|
return ret_code;
|
||||||
|
|
||||||
|
|
||||||
|
*I = (int *) malloc(*nz * sizeof(int));
|
||||||
|
*J = (int *) malloc(*nz * sizeof(int));
|
||||||
|
*val = NULL;
|
||||||
|
|
||||||
|
if (mm_is_complex(*matcode))
|
||||||
|
{
|
||||||
|
*val = (double *) malloc(*nz * 2 * sizeof(double));
|
||||||
|
ret_code = mm_read_mtx_crd_data(f, *M, *N, *nz, *I, *J, *val,
|
||||||
|
*matcode);
|
||||||
|
if (ret_code != 0) return ret_code;
|
||||||
|
}
|
||||||
|
else if (mm_is_real(*matcode))
|
||||||
|
{
|
||||||
|
*val = (double *) malloc(*nz * sizeof(double));
|
||||||
|
ret_code = mm_read_mtx_crd_data(f, *M, *N, *nz, *I, *J, *val,
|
||||||
|
*matcode);
|
||||||
|
if (ret_code != 0) return ret_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (mm_is_pattern(*matcode))
|
||||||
|
{
|
||||||
|
ret_code = mm_read_mtx_crd_data(f, *M, *N, *nz, *I, *J, *val,
|
||||||
|
*matcode);
|
||||||
|
if (ret_code != 0) return ret_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (f != stdin) fclose(f);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mm_write_banner(FILE *f, MM_typecode matcode)
|
||||||
|
{
|
||||||
|
char *str = mm_typecode_to_str(matcode);
|
||||||
|
int ret_code;
|
||||||
|
|
||||||
|
ret_code = fprintf(f, "%s %s\n", MatrixMarketBanner, str);
|
||||||
|
free(str);
|
||||||
|
if (ret_code !=2 )
|
||||||
|
return MM_COULD_NOT_WRITE_FILE;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mm_write_mtx_crd(char fname[], int M, int N, int nz, int I[], int J[],
|
||||||
|
double val[], MM_typecode matcode)
|
||||||
|
{
|
||||||
|
FILE *f;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (strcmp(fname, "stdout") == 0)
|
||||||
|
f = stdout;
|
||||||
|
else
|
||||||
|
if ((f = fopen(fname, "w")) == NULL)
|
||||||
|
return MM_COULD_NOT_WRITE_FILE;
|
||||||
|
|
||||||
|
/* print banner followed by typecode */
|
||||||
|
fprintf(f, "%s ", MatrixMarketBanner);
|
||||||
|
fprintf(f, "%s\n", mm_typecode_to_str(matcode));
|
||||||
|
|
||||||
|
/* print matrix sizes and nonzeros */
|
||||||
|
fprintf(f, "%d %d %d\n", M, N, nz);
|
||||||
|
|
||||||
|
/* print values */
|
||||||
|
if (mm_is_pattern(matcode))
|
||||||
|
for (i=0; i<nz; i++)
|
||||||
|
fprintf(f, "%d %d\n", I[i], J[i]);
|
||||||
|
else
|
||||||
|
if (mm_is_real(matcode))
|
||||||
|
for (i=0; i<nz; i++)
|
||||||
|
fprintf(f, "%d %d %20.16g\n", I[i], J[i], val[i]);
|
||||||
|
else
|
||||||
|
if (mm_is_complex(matcode))
|
||||||
|
for (i=0; i<nz; i++)
|
||||||
|
fprintf(f, "%d %d %20.16g %20.16g\n", I[i], J[i], val[2*i],
|
||||||
|
val[2*i+1]);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (f != stdout) fclose(f);
|
||||||
|
return MM_UNSUPPORTED_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (f !=stdout) fclose(f);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new copy of a string s. mm_strdup() is a common routine, but
|
||||||
|
* not part of ANSI C, so it is included here. Used by mm_typecode_to_str().
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
char *mm_strdup(const char *s)
|
||||||
|
{
|
||||||
|
int len = strlen(s);
|
||||||
|
char *s2 = (char *) malloc((len+1)*sizeof(char));
|
||||||
|
return strcpy(s2, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *mm_typecode_to_str(MM_typecode matcode)
|
||||||
|
{
|
||||||
|
char buffer[MM_MAX_LINE_LENGTH];
|
||||||
|
char *types[4];
|
||||||
|
char *mm_strdup(const char *);
|
||||||
|
int error =0;
|
||||||
|
|
||||||
|
/* check for MTX type */
|
||||||
|
if (mm_is_matrix(matcode))
|
||||||
|
types[0] = MM_MTX_STR;
|
||||||
|
else
|
||||||
|
error=1;
|
||||||
|
|
||||||
|
/* check for CRD or ARR matrix */
|
||||||
|
if (mm_is_sparse(matcode))
|
||||||
|
types[1] = MM_SPARSE_STR;
|
||||||
|
else
|
||||||
|
if (mm_is_dense(matcode))
|
||||||
|
types[1] = MM_DENSE_STR;
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* check for element data type */
|
||||||
|
if (mm_is_real(matcode))
|
||||||
|
types[2] = MM_REAL_STR;
|
||||||
|
else
|
||||||
|
if (mm_is_complex(matcode))
|
||||||
|
types[2] = MM_COMPLEX_STR;
|
||||||
|
else
|
||||||
|
if (mm_is_pattern(matcode))
|
||||||
|
types[2] = MM_PATTERN_STR;
|
||||||
|
else
|
||||||
|
if (mm_is_integer(matcode))
|
||||||
|
types[2] = MM_INT_STR;
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
|
||||||
|
/* check for symmetry type */
|
||||||
|
if (mm_is_general(matcode))
|
||||||
|
types[3] = MM_GENERAL_STR;
|
||||||
|
else
|
||||||
|
if (mm_is_symmetric(matcode))
|
||||||
|
types[3] = MM_SYMM_STR;
|
||||||
|
else
|
||||||
|
if (mm_is_hermitian(matcode))
|
||||||
|
types[3] = MM_HERM_STR;
|
||||||
|
else
|
||||||
|
if (mm_is_skew(matcode))
|
||||||
|
types[3] = MM_SKEW_STR;
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
sprintf(buffer,"%s %s %s %s", types[0], types[1], types[2], types[3]);
|
||||||
|
return mm_strdup(buffer);
|
||||||
|
|
||||||
|
}
|
||||||
135
examples/gmres/mmio.h
Normal file
135
examples/gmres/mmio.h
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
/*
|
||||||
|
* Matrix Market I/O library for ANSI C
|
||||||
|
*
|
||||||
|
* See http://math.nist.gov/MatrixMarket for details.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MM_IO_H
|
||||||
|
#define MM_IO_H
|
||||||
|
|
||||||
|
#define MM_MAX_LINE_LENGTH 1025
|
||||||
|
#define MatrixMarketBanner "%%MatrixMarket"
|
||||||
|
#define MM_MAX_TOKEN_LENGTH 64
|
||||||
|
|
||||||
|
typedef char MM_typecode[4];
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
char *mm_typecode_to_str(MM_typecode matcode);
|
||||||
|
|
||||||
|
int mm_read_banner(FILE *f, MM_typecode *matcode);
|
||||||
|
int mm_read_mtx_crd_size(FILE *f, int *M, int *N, int *nz);
|
||||||
|
int mm_read_mtx_array_size(FILE *f, int *M, int *N);
|
||||||
|
|
||||||
|
int mm_write_banner(FILE *f, MM_typecode matcode);
|
||||||
|
int mm_write_mtx_crd_size(FILE *f, int M, int N, int nz);
|
||||||
|
int mm_write_mtx_array_size(FILE *f, int M, int N);
|
||||||
|
|
||||||
|
|
||||||
|
/********************* MM_typecode query fucntions ***************************/
|
||||||
|
|
||||||
|
#define mm_is_matrix(typecode) ((typecode)[0]=='M')
|
||||||
|
|
||||||
|
#define mm_is_sparse(typecode) ((typecode)[1]=='C')
|
||||||
|
#define mm_is_coordinate(typecode)((typecode)[1]=='C')
|
||||||
|
#define mm_is_dense(typecode) ((typecode)[1]=='A')
|
||||||
|
#define mm_is_array(typecode) ((typecode)[1]=='A')
|
||||||
|
|
||||||
|
#define mm_is_complex(typecode) ((typecode)[2]=='C')
|
||||||
|
#define mm_is_real(typecode) ((typecode)[2]=='R')
|
||||||
|
#define mm_is_pattern(typecode) ((typecode)[2]=='P')
|
||||||
|
#define mm_is_integer(typecode) ((typecode)[2]=='I')
|
||||||
|
|
||||||
|
#define mm_is_symmetric(typecode)((typecode)[3]=='S')
|
||||||
|
#define mm_is_general(typecode) ((typecode)[3]=='G')
|
||||||
|
#define mm_is_skew(typecode) ((typecode)[3]=='K')
|
||||||
|
#define mm_is_hermitian(typecode)((typecode)[3]=='H')
|
||||||
|
|
||||||
|
int mm_is_valid(MM_typecode matcode); /* too complex for a macro */
|
||||||
|
|
||||||
|
|
||||||
|
/********************* MM_typecode modify fucntions ***************************/
|
||||||
|
|
||||||
|
#define mm_set_matrix(typecode) ((*typecode)[0]='M')
|
||||||
|
#define mm_set_coordinate(typecode) ((*typecode)[1]='C')
|
||||||
|
#define mm_set_array(typecode) ((*typecode)[1]='A')
|
||||||
|
#define mm_set_dense(typecode) mm_set_array(typecode)
|
||||||
|
#define mm_set_sparse(typecode) mm_set_coordinate(typecode)
|
||||||
|
|
||||||
|
#define mm_set_complex(typecode)((*typecode)[2]='C')
|
||||||
|
#define mm_set_real(typecode) ((*typecode)[2]='R')
|
||||||
|
#define mm_set_pattern(typecode)((*typecode)[2]='P')
|
||||||
|
#define mm_set_integer(typecode)((*typecode)[2]='I')
|
||||||
|
|
||||||
|
|
||||||
|
#define mm_set_symmetric(typecode)((*typecode)[3]='S')
|
||||||
|
#define mm_set_general(typecode)((*typecode)[3]='G')
|
||||||
|
#define mm_set_skew(typecode) ((*typecode)[3]='K')
|
||||||
|
#define mm_set_hermitian(typecode)((*typecode)[3]='H')
|
||||||
|
|
||||||
|
#define mm_clear_typecode(typecode) ((*typecode)[0]=(*typecode)[1]= \
|
||||||
|
(*typecode)[2]=' ',(*typecode)[3]='G')
|
||||||
|
|
||||||
|
#define mm_initialize_typecode(typecode) mm_clear_typecode(typecode)
|
||||||
|
|
||||||
|
|
||||||
|
/********************* Matrix Market error codes ***************************/
|
||||||
|
|
||||||
|
|
||||||
|
#define MM_COULD_NOT_READ_FILE 11
|
||||||
|
#define MM_PREMATURE_EOF 12
|
||||||
|
#define MM_NOT_MTX 13
|
||||||
|
#define MM_NO_HEADER 14
|
||||||
|
#define MM_UNSUPPORTED_TYPE 15
|
||||||
|
#define MM_LINE_TOO_LONG 16
|
||||||
|
#define MM_COULD_NOT_WRITE_FILE 17
|
||||||
|
|
||||||
|
|
||||||
|
/******************** Matrix Market internal definitions ********************
|
||||||
|
|
||||||
|
MM_matrix_typecode: 4-character sequence
|
||||||
|
|
||||||
|
ojbect sparse/ data storage
|
||||||
|
dense type scheme
|
||||||
|
|
||||||
|
string position: [0] [1] [2] [3]
|
||||||
|
|
||||||
|
Matrix typecode: M(atrix) C(oord) R(eal) G(eneral)
|
||||||
|
A(array) C(omplex) H(ermitian)
|
||||||
|
P(attern) S(ymmetric)
|
||||||
|
I(nteger) K(kew)
|
||||||
|
|
||||||
|
***********************************************************************/
|
||||||
|
|
||||||
|
#define MM_MTX_STR "matrix"
|
||||||
|
#define MM_ARRAY_STR "array"
|
||||||
|
#define MM_DENSE_STR "array"
|
||||||
|
#define MM_COORDINATE_STR "coordinate"
|
||||||
|
#define MM_SPARSE_STR "coordinate"
|
||||||
|
#define MM_COMPLEX_STR "complex"
|
||||||
|
#define MM_REAL_STR "real"
|
||||||
|
#define MM_INT_STR "integer"
|
||||||
|
#define MM_GENERAL_STR "general"
|
||||||
|
#define MM_SYMM_STR "symmetric"
|
||||||
|
#define MM_HERM_STR "hermitian"
|
||||||
|
#define MM_SKEW_STR "skew-symmetric"
|
||||||
|
#define MM_PATTERN_STR "pattern"
|
||||||
|
|
||||||
|
|
||||||
|
/* high level routines */
|
||||||
|
|
||||||
|
int mm_write_mtx_crd(char fname[], int M, int N, int nz, int I[], int J[],
|
||||||
|
double val[], MM_typecode matcode);
|
||||||
|
int mm_read_mtx_crd_data(FILE *f, int M, int N, int nz, int I[], int J[],
|
||||||
|
double val[], MM_typecode matcode);
|
||||||
|
int mm_read_mtx_crd_entry(FILE *f, int *I, int *J, double *real, double *img,
|
||||||
|
MM_typecode matcode);
|
||||||
|
|
||||||
|
int mm_read_unsymmetric_sparse(const char *fname, int *M_, int *N_, int *nz_,
|
||||||
|
double **val_, int **I_, int **J_);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
53
examples/gmres/util.h
Normal file
53
examples/gmres/util.h
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2012, Intel Corporation
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of Intel Corporation nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||||
|
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||||
|
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __UTIL_H__
|
||||||
|
#define __UTIL_H__
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "matrix.h"
|
||||||
|
|
||||||
|
|
||||||
|
inline void printMatrix (DenseMatrix &M, const char *name) {
|
||||||
|
printf("Matrix %s:\n", name);
|
||||||
|
for (int row = 0; row < M.rows(); row++) {
|
||||||
|
printf("row %2d: ", row + 1);
|
||||||
|
for (int col = 0; col < M.cols(); col++)
|
||||||
|
printf("%6f ", M(row, col));
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user