source: CIVL/examples/verifyThis/strassen.cvl

main
Last change on this file was ea777aa, checked in by Alex Wilton <awilton@…>, 3 years ago

Moved examples, include, build_default.properties, common.xml, and README out from dev.civl.com into the root of the repo.

git-svn-id: svn://vsl.cis.udel.edu/civl/trunk@5704 fb995dde-84ed-4084-dfe6-e5aef3e2452c

  • Property mode set to 100644
File size: 5.2 KB
RevLine 
[f220611]1/* Post-commit solution to matrixMultiplication, using CIVL.
2 * Stephen Siegel
3 */
4
5#include <stdio.h>
6#include <pointer.cvh>
7
8// upper bound on N, the size of the matrices
9$input int BOUND = 8; // can go up to 16 if you have a few minutes
10$assume(BOUND >= 1);
11$input int N; // the size of the matrices
12$assume(1<=N && N<=BOUND);
13// some arbitrary input matrices...
14$input float A0[N][N];
15$input float B0[N][N];
16
17// the "leaf size" for Strassen...
18$input int LEAF_SIZE;
19$assume (1 <= LEAF_SIZE && LEAF_SIZE <= N);
20
21// impl: C is "out" variable
22void matrixMultiply(int n, float C[][], float A[][], float B[][]) {
23 for (int i=0; i<n; i++)
24 for (int j=0; j<n; j++)
25 C[i][j] = 0.0;
26
27 for (int i = 0; i < n; i++) {
28 for (int k = 0; k < n; k++) {
29 for (int j = 0; j < n; j++) {
30 C[i][j] += A[i][k] * B[k][j];
31 }
32 }
33 }
34}
35
36/* Part 3 : Strassen */
37
38// adds two nxn matrices. C is "out" variable.
39void add(int n, float C[][], float A[][], float B[][]) {
40 for (int i = 0; i < n; i++)
41 for (int j = 0; j < n; j++)
42 C[i][j] = A[i][j] + B[i][j];
43}
44
45// subtracts two nxn matrices. C is "out" variable.
46void subtract(int n, float C[][], float A[][], float B[][]) {
47 for (int i = 0; i < n; i++)
48 for (int j = 0; j < n; j++)
49 C[i][j] = A[i][j] - B[i][j];
50}
51
52
53// Strassen algorithm from
54// https://martin-thoma.com/strassen-algorithm-in-python-java-cpp/
55// I'm just going to assume n is a power of 2.
56// There is no problem dealing with the general case but need more
57// time!
58
59// multiplies two nxn matrices, storing result in C
60void strassenR(int n, float C[][], float A[][], float B[][]) {
61 if (n <= LEAF_SIZE) {
62 matrixMultiply(n, C, A, B);
63 } else {
64 // initializing the new sub-matrices
65 int newSize = n / 2;
66 float a11[newSize][newSize];
67 float a12[newSize][newSize];
68 float a21[newSize][newSize];
69 float a22[newSize][newSize];
70
71 float b11[newSize][newSize];
72 float b12[newSize][newSize];
73 float b21[newSize][newSize];
74 float b22[newSize][newSize];
75
76 float aResult[newSize][newSize];
77 float bResult[newSize][newSize];
78
79 // dividing the matrices in 4 sub-matrices:
80 for (int i = 0; i < newSize; i++) {
81 for (int j = 0; j < newSize; j++) {
82 a11[i][j] = A[i][j]; // top left
83 a12[i][j] = A[i][j + newSize]; // top right
84 a21[i][j] = A[i + newSize][j]; // bottom left
85 a22[i][j] = A[i + newSize][j + newSize]; // bottom right
86
87 b11[i][j] = B[i][j]; // top left
88 b12[i][j] = B[i][j + newSize]; // top right
89 b21[i][j] = B[i + newSize][j]; // bottom left
90 b22[i][j] = B[i + newSize][j + newSize]; // bottom right
91 }
92 }
93 // Calculating p1 to p7:
94 add(newSize, aResult, a11, a22);
95 add(newSize, bResult, b11, b22);
96 float p1[newSize][newSize];
97 strassenR(newSize, p1, aResult, bResult);
98 // p1 = (a11+a22) * (b11+b22)
99
100 add(newSize, aResult, a21, a22); // a21 + a22
101 float p2[newSize][newSize];
102 strassenR(newSize, p2, aResult, b11); // p2 = (a21+a22) * (b11)
103
104 subtract(newSize, bResult, b12, b22); // b12 - b22
105 float p3[newSize][newSize];
106 strassenR(newSize, p3, a11, bResult);
107 // p3 = (a11) * (b12 - b22)
108
109 subtract(newSize, bResult, b21, b11); // b21 - b11
110 float p4[newSize][newSize];
111 strassenR(newSize, p4, a22, bResult);
112 // p4 = (a22) * (b21 - b11)
113
114 add(newSize, aResult, a11, a12); // a11 + a12
115 float p5[newSize][newSize];
116 strassenR(newSize, p5, aResult, b22);
117 // p5 = (a11+a12) * (b22)
118
119 subtract(newSize, aResult, a21, a11); // a21 - a11
120 add(newSize, bResult, b11, b12); // b11 + b12
121 float p6[newSize][newSize];
122 strassenR(newSize, p6, aResult, bResult);
123 // p6 = (a21-a11) * (b11+b12)
124
125 subtract(newSize, aResult, a12, a22); // a12 - a22
126 add(newSize, bResult, b21, b22); // b21 + b22
127 float p7[newSize][newSize];
128 strassenR(newSize, p7, aResult, bResult);
129 // p7 = (a12-a22) * (b21+b22)
130
131 // calculating c21, c21, c11 e c22:
132 float c12[newSize][newSize];
133 add(newSize, c12, p3, p5); // c12 = p3 + p5
134 float c21[newSize][newSize];
135 add(newSize, c21, p2, p4); // c21 = p2 + p4
136
137 add(newSize, aResult, p1, p4); // p1 + p4
138 add(newSize, bResult, aResult, p7); // p1 + p4 + p7
139 float c11[newSize][newSize];
140 subtract(newSize, c11, bResult, p5);
141 // c11 = p1 + p4 - p5 + p7
142
143 add(newSize, aResult, p1, p3); // p1 + p3
144 add(newSize, bResult, aResult, p6); // p1 + p3 + p6
145 float c22[newSize][newSize];
146 subtract(newSize, c22, bResult, p2);
147 // c22 = p1 + p3 - p2 + p6
148
149 // Grouping the results obtained in a single matrix:
150 for (int i = 0; i < newSize; i++) {
151 for (int j = 0; j < newSize; j++) {
152 C[i][j] = c11[i][j];
153 C[i][j + newSize] = c12[i][j];
154 C[i + newSize][j] = c21[i][j];
155 C[i + newSize][j + newSize] = c22[i][j];
156 }
157 }
158 }
159}
160
161// determines whether n is a power of 2
162_Bool isPowerOf2(int n) {
163 while (n>1) {
164 if (n%2 != 0)
165 return $false;
166 n = n/2;
167 }
168 return $true;
169}
170
171/* main: runs the three tests */
172int main() {
173 $elaborate(N); // hint to verifier
174 printf("N=%d\n", N);
175 $assume(isPowerOf2(N));
176 float R1[N][N], R2[N][N];
177 matrixMultiply(N, R1, A0, B0);
178 strassenR(N, R2, A0, B0);
179 $assert($equals(&R1, &R2));
180}
Note: See TracBrowser for help on using the repository browser.