Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/hotspot/jtreg/vmTestbase/nsk/stress/numeric/numeric010.java
41159 views
1
/*
2
* Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*/
23
24
/*
25
* @test
26
* @key stress randomness
27
*
28
* @summary converted from VM testbase nsk/stress/numeric/numeric010.
29
* VM testbase keywords: [stress, slow, nonconcurrent, quick]
30
* VM testbase readme:
31
* DESCRIPTION
32
* This test calculates the product A*A for a square matrix A, and checks
33
* if such product is calculated correctly. Elements of the matrix A are
34
* initiated with integer numbers, so that A*A must be the same if calculated
35
* with double, float, long, or int precision. The test just checks, if
36
* double, float, long, and int variants of the product calculation result
37
* in the same A*A matrix.
38
* The product A*A is calculated twice: in a single thread, and in N separate
39
* threads, where NxN is the size of square matrix A. When executing in N
40
* threads, each thread calculate distinct row of the resulting matrix.
41
* HotSpot releases 1.0 and 1.3 seem to do not adjust JVM for better
42
* performance in single-thread calculation, while milti-threads calculation
43
* usually runs much faster. I guess, that the 1-thread calculation is probably
44
* executed by HotSpot interpreter, and HotSpot compiler is probably involved
45
* to execute N-threads calculation. So, the test apparently checks accuracy
46
* of A*A calculation in both compilation and interpretation modes.
47
* By the way, the test checks JVM performance. The test is treated failed
48
* due to poor performance, if single-thread calculation is essentially
49
* slower than N-threads calculation (surely, the number of CPUs installed
50
* on the platform executing the test is taken into account for performance
51
* testing). The calculation algorithm is encoded with 3-levels cycle like:
52
* for (int line=0; line<N; line++)
53
* for (int column=0; column<N; column++) {
54
* float sum = 0;
55
* for (int k=0; k<N; k++)
56
* sum += A[line][k] A[k][column];
57
* AA[line][column] = sum;
58
* }
59
* In this test, N=200, so that A is 200x200 matrix; and multiplication
60
* A[line][k]*A[k][column] is executed 200**3=8 millions times in this
61
* cycle. I believe, that this is HotSpot bug to do not adjust JVM for
62
* best performance during such a huge series of executions of the rather
63
* compact portion of program code.
64
* COMMENTS
65
* The bug was filed referencing to the same numeric algorithm,
66
* which is used by this test:
67
* 4242172 (P3/S5) 2.0: poor performance in matrix calculations
68
* Note, that despite HotSpot works faster in milti-thread calculations,
69
* it still remains essentially slower than classic VM with JIT on.
70
*
71
* @library /test/lib
72
* @run main/othervm nsk.stress.numeric.numeric010.numeric010 200 200
73
*/
74
75
package nsk.stress.numeric.numeric010;
76
77
import java.io.PrintStream;
78
import java.util.Random;
79
import jdk.test.lib.Utils;
80
81
/**
82
* This test calculates the product <code>A<sup>.</sup>A</code> for a square
83
* matrix <code>A</code>, and checks if such product is calculated correctly.
84
* Elements of the matrix <code>A</code> are initiated with integer numbers,
85
* so that <code>A<sup>.</sup>A</code> must be the same if calculated with
86
* <code>double</code>, <code>float</code>, <code>long</code>, or
87
* <code>int</code> precision. The test just checks, if <code>double</code>,
88
* <code>float</code>, <code>long</code>, and <code>int</code> variants of
89
* the product calculation result in the same <code>A<sup>.</sup>A</code>
90
* matrix.
91
* <p>
92
* <p>The product <code>A<sup>.</sup>A</code> is calculated twice: in a single
93
* thread, and in <code>N</code> separate threads, where <code>NxN</code> is
94
* the size of square matrix <code>A</code>. When executing in <code>N</code>
95
* threads, each thread calculate distinct row of the resulting matrix. HotSpot
96
* releases 1.0 and 1.3 seem to do not adjust JVM for better performance in
97
* single-thread calculation, while milti-threads calculation usually runs much
98
* faster. I guess, that the 1-thread calculation is probably executed by HotSpot
99
* interpreter, and HotSpot compiler is probably involved to execute
100
* <code>N</code>-threads calculation. So, the test apparently checks accuracy
101
* of <code>A<sup>.</sup>A</code> calculation in both compilation and
102
* interpretation modes.
103
* <p>
104
* <p>By the way, the test checks JVM performance. The test is treated failed
105
* due to poor performance, if single-thread calculation is essentially
106
* slower than <code>N</code>-threads calculation (surely, the number of CPUs
107
* installed on the platform executing the test is taken into account for
108
* performance testing). The calculation algorithm is encoded with 3-levels
109
* cycle like:
110
* <pre>
111
* for (int line=0; line&lt;N; line++)
112
* for (int column=0; column&lt;N; column++) {
113
* float sum = 0;
114
* for (int k=0; k&lt;N; k++)
115
* sum += A[line][k] * A[k][column];
116
* AA[line][column] = sum;
117
* }
118
* </pre>
119
* <p>
120
* In this test, <code>N</code>=200, so that <code>A</code> is 200x200 matrix;
121
* and multiplication <code>A[line][k]*A[k][column]</code> is executed
122
* 200<sup>3</sup>=8 millions times in this cycle. I believe, that this is HotSpot
123
* bug to do not adjust JVM for best performance during such a huge series of
124
* executions of the rather compact portion of program code.
125
* <p>
126
* <p>See the bug-report:
127
* <br>&nbsp;&nbsp;
128
* 4242172 (P3/S5) 2.0: poor performance in matrix calculations
129
*/
130
public class numeric010 {
131
private static final Random RNG = Utils.getRandomInstance();
132
/**
133
* When testing performance, 1-thread calculation is allowed to be 10%
134
* slower than multi-thread calculation (<code>tolerance</code> is
135
* assigned to 10 now).
136
*/
137
public static double tolerance = 100; // 10;
138
139
/**
140
* Re-assign this value to <code>true</code> for better diagnostics.
141
*
142
* @see #print(Object)
143
* @see #println(Object)
144
*/
145
private static boolean verbose = false;
146
147
/**
148
* Stream to print execution trace and/or error messages.
149
* This stream usually equals to <code>System.out</code>
150
*/
151
private static PrintStream out = null;
152
153
/**
154
* Print error-message.
155
*
156
* @see #out
157
*/
158
private static void complain(Object x) {
159
out.println("# " + x);
160
}
161
162
/**
163
* Print to execution trace, if mode is <code>verbose</code>.
164
*
165
* @see #verbose
166
* @see #out
167
*/
168
private static void print(Object x) {
169
if (verbose)
170
out.print(x);
171
}
172
173
/**
174
* Print line to execution trace, if mode is <code>verbose</code>.
175
*
176
* @see #verbose
177
* @see #out
178
*/
179
private static void println(Object x) {
180
print(x + "\n");
181
}
182
183
/**
184
* Re-invoke <code>run(args,out)</code> in order to simulate
185
* JCK-like test interface.
186
*/
187
public static void main(String args[]) {
188
int exitCode = run(args, System.out);
189
System.exit(exitCode + 95);
190
// JCK-like exit status
191
}
192
193
/**
194
* Parse command-line parameters stored in <code>args[]</code> and run
195
* the test.
196
* <p>
197
* <p>Command-line parameters are:
198
* <br>&nbsp;&nbsp;
199
* <code>java numeric010 [-verbose] [-performance]
200
* [-tolerance:<i>percents</i>] [-CPU:<i>number</i>]
201
* <i>matrixSize</i> [<i>threads</i>]</code>
202
* <p>
203
* <p>Here:
204
* <br>&nbsp;&nbsp;<code>-verbose</code> -
205
* keyword, which alows to print execution trace
206
* <br>&nbsp;&nbsp;<code>-performance</code> -
207
* keyword, which alows performance testing
208
* <br>&nbsp;&nbsp;<code>-tolerance</code> -
209
* setup tolerance of performance checking
210
* <br>&nbsp;&nbsp;<code><i>percents</i></code> -
211
* 1-thread calculation is allowed to be
212
* <code><i>percents</i></code>% slower
213
* <br>&nbsp;&nbsp;<code><i>number</i></code> -
214
* number of CPU installed on the computer just executing the test
215
* <br>&nbsp;&nbsp;<code><i>matrixSize</i></code> -
216
* number of rows (and columns) in square matrix to be tested
217
* <br>&nbsp;&nbsp;<code><i>threads</i></code> -
218
* for multi-thread calculation
219
* (default: <code><i>matrixSize</i></code>)
220
*
221
* @param args strings array containing command-line parameters
222
* @param out the test log, usually <code>System.out</code>
223
*/
224
public static int run(String args[], PrintStream out) {
225
numeric010.out = out;
226
227
boolean testPerformance = false;
228
int numberOfCPU = 1;
229
230
int argsShift = 0;
231
for (; argsShift < args.length; argsShift++) {
232
String argument = args[argsShift];
233
234
if (!argument.startsWith("-"))
235
break;
236
237
if (argument.equals("-performance")) {
238
testPerformance = true;
239
continue;
240
}
241
242
if (argument.equals("-verbose")) {
243
verbose = true;
244
continue;
245
}
246
247
if (argument.startsWith("-tolerance:")) {
248
String percents =
249
argument.substring("-tolerance:".length(), argument.length());
250
tolerance = Integer.parseInt(percents);
251
252
if ((tolerance < 0) || (tolerance > 100)) {
253
complain("Tolerance should be 0 to 100%: " + argument);
254
return 2; // failure
255
}
256
continue;
257
}
258
259
if (argument.startsWith("-CPU:")) {
260
String value =
261
argument.substring("-CPU:".length(), argument.length());
262
numberOfCPU = Integer.parseInt(value);
263
264
if (numberOfCPU < 1) {
265
complain("Illegal number of CPU: " + argument);
266
return 2; // failure
267
}
268
continue;
269
}
270
271
complain("Cannot recognize argument: args[" + argsShift + "]: " + argument);
272
return 2; // failure
273
}
274
275
if ((args.length < argsShift + 1) || (args.length > argsShift + 2)) {
276
complain("Illegal argument(s). Execute:");
277
complain(
278
" java numeric010 [-verbose] [-performance] " +
279
"[-tolerance:percents] [-CPU:number] matrixSize [threads]");
280
return 2; // failure
281
}
282
283
int size = Integer.parseInt(args[argsShift]);
284
if ((size < 100) || (size > 10000)) {
285
complain("Matrix size should be 100 to 1000 lines & columns.");
286
return 2; // failure
287
}
288
289
int threads = size;
290
if (args.length >= argsShift + 2)
291
threads = Integer.parseInt(args[argsShift + 1]);
292
if ((threads < 1) || (threads > size)) {
293
complain("Threads number should be 1 to matrix size.");
294
return 2; // failure
295
}
296
if ((size % threads) != 0) {
297
complain("Threads number should evenly divide matrix size.");
298
return 2; // failure
299
}
300
301
print("Preparing A[" + size + "," + size + "]:");
302
IntegerMatrix intA = new IntegerMatrix(size);
303
IntegerMatrix intAA = new IntegerMatrix(size);
304
LongMatrix longA = new LongMatrix(intA);
305
LongMatrix longAA = new LongMatrix(intA);
306
FloatMatrix floatA = new FloatMatrix(intA);
307
FloatMatrix floatAA = new FloatMatrix(intA);
308
DoubleMatrix doubleA = new DoubleMatrix(intA);
309
DoubleMatrix doubleAA = new DoubleMatrix(intA);
310
println(" done.");
311
312
double elapsed[] = {0, 0};
313
314
for (int i = 0; i < 2; i++) {
315
double seconds =
316
elapsedTime((i == 0 ? 1 : threads),
317
intA, intAA,
318
longA, longAA,
319
floatA, floatAA,
320
doubleA, doubleAA);
321
elapsed[i] = seconds;
322
323
print("Checking accuracy:");
324
for (int line = 0; line < size; line++)
325
for (int column = 0; column < size; column++) {
326
if (intAA.value[line][column] != longAA.value[line][column]) {
327
println("");
328
complain("Test failed:");
329
complain("Integer and Long results differ at:");
330
complain(" line=" + line + ", column=" + column);
331
complain(" intAA.value[line][column]=" + intAA.value[line][column]);
332
complain("longAA.value[line][column]=" + longAA.value[line][column]);
333
return 2; // FAILED
334
}
335
if (intAA.value[line][column] != floatAA.value[line][column]) {
336
println("");
337
complain("Test failed:");
338
complain("Integer and Float results differ at:");
339
complain(" line=" + line + ", column=" + column);
340
complain(" intAA.value[line][column]=" + intAA.value[line][column]);
341
complain("floatAA.value[line][column]=" + floatAA.value[line][column]);
342
return 2; // FAILED
343
}
344
if (intAA.value[line][column] != doubleAA.value[line][column]) {
345
println("");
346
complain("Test failed:");
347
complain("Integer and Double results differ at:");
348
complain(" line=" + line + ", column=" + column);
349
complain(" intAA.value[line][column]=" + intAA.value[line][column]);
350
complain("doubleAA.value[line][column]=" + doubleAA.value[line][column]);
351
return 2; // FAILED
352
}
353
}
354
println(" done.");
355
}
356
357
double overallTime = elapsed[0] + elapsed[1];
358
double averageTime = overallTime / 2; // 2 excutions
359
double averagePerformance = 4 * size * size * (size + size) / averageTime / 1e6;
360
println("");
361
println("Overall elapsed time: " + overallTime + " seconds.");
362
println("Average elapsed time: " + averageTime + " seconds.");
363
println("Average performance: " + averagePerformance + " MOPS");
364
365
if (testPerformance) {
366
println("");
367
print("Checking performance: ");
368
double elapsed1 = elapsed[0];
369
double elapsedM = elapsed[1] * numberOfCPU;
370
if (elapsed1 > elapsedM * (1 + tolerance / 100)) {
371
println("");
372
complain("Test failed:");
373
complain("Single-thread calculation is essentially slower:");
374
complain("Calculation time elapsed (seconds):");
375
complain(" single thread: " + elapsed[0]);
376
complain(" multi-threads: " + elapsed[1]);
377
complain(" number of CPU: " + numberOfCPU);
378
complain(" tolerance: " + tolerance + "%");
379
return 2; // FAILED
380
}
381
println("done.");
382
}
383
384
println("Test passed.");
385
return 0; // PASSED
386
}
387
388
/**
389
* Return time (in seconds) elapsed for calculation of matrix
390
* product <code>A*A</code> with <code>int</code>, <code>long</code>,
391
* <code>float</code>, and <code>double</code> representations.
392
*/
393
private static double elapsedTime(int threads,
394
IntegerMatrix intA, IntegerMatrix intAA,
395
LongMatrix longA, LongMatrix longAA,
396
FloatMatrix floatA, FloatMatrix floatAA,
397
DoubleMatrix doubleA, DoubleMatrix doubleAA) {
398
399
println("");
400
print("Computing A*A with " + threads + " thread(s):");
401
long mark1 = System.currentTimeMillis();
402
intAA.setSquareOf(intA, threads);
403
longAA.setSquareOf(longA, threads);
404
floatAA.setSquareOf(floatA, threads);
405
doubleAA.setSquareOf(doubleA, threads);
406
long mark2 = System.currentTimeMillis();
407
println(" done.");
408
409
int size = intA.size();
410
double sec = (mark2 - mark1) / 1000.0;
411
double perf = 4 * size * size * (size + size) / sec;
412
println("Elapsed time: " + sec + " seconds");
413
println("Performance: " + perf / 1e6 + " MOPS");
414
415
return sec;
416
}
417
418
/**
419
* Compute <code>A*A</code> for <code>int</code> matrix <code>A</code>.
420
*/
421
private static class IntegerMatrix {
422
volatile int value[][];
423
424
/**
425
* Number of lines and columns in <code>this</code> square matrix.
426
*/
427
public int size() {
428
return value.length;
429
}
430
431
/**
432
* New square matrix with random elements.
433
*/
434
public IntegerMatrix(int size) {
435
value = new int[size][size];
436
for (int line = 0; line < size; line++)
437
for (int column = 0; column < size; column++)
438
value[line][column] =
439
Math.round((float) ((1 - 2 * RNG.nextDouble()) * size));
440
}
441
442
/**
443
* Assign <code>this</code> matrix with <code>A*A</code>.
444
*
445
* @param threads Split computation into the given number of threads.
446
*/
447
public void setSquareOf(IntegerMatrix A, int threads) {
448
if (this.size() != A.size())
449
throw new IllegalArgumentException(
450
"this.size() != A.size()");
451
452
if ((size() % threads) != 0)
453
throw new IllegalArgumentException("size()%threads != 0");
454
int bunch = size() / threads;
455
456
Thread task[] = new Thread[threads];
457
for (int t = 0; t < threads; t++) {
458
int line0 = bunch * t;
459
MatrixComputer computer =
460
new MatrixComputer(value, A.value, line0, bunch);
461
task[t] = new Thread(computer);
462
}
463
464
for (int t = 0; t < threads; t++)
465
task[t].start();
466
467
for (int t = 0; t < threads; t++)
468
if (task[t].isAlive())
469
try {
470
task[t].join();
471
} catch (InterruptedException exception) {
472
throw new RuntimeException(exception.toString());
473
}
474
}
475
476
/**
477
* Thread to compute a bunch of lines of matrix square.
478
*/
479
private static class MatrixComputer implements Runnable {
480
private int result[][];
481
private int source[][];
482
private int line0;
483
private int bunch;
484
485
/**
486
* Register a task for matrix multiplication.
487
*/
488
public MatrixComputer(
489
int result[][], int source[][], int line0, int bunch) {
490
491
this.result = result; // reference to resulting matrix value
492
this.source = source; // reference to matrix to be squared
493
this.line0 = line0; // compute lines from line0 to ...
494
this.bunch = bunch; // number of resulting lines to compute
495
}
496
497
/**
498
* Do execute the task just registered for <code>this</code> thread.
499
*/
500
public void run() {
501
int line1 = line0 + bunch;
502
int size = result.length;
503
for (int line = line0; line < line1; line++)
504
for (int column = 0; column < size; column++) {
505
int sum = 0;
506
for (int i = 0; i < size; i++)
507
sum += source[line][i] * source[i][column];
508
result[line][column] = sum;
509
}
510
}
511
512
}
513
514
}
515
516
/**
517
* Compute <code>A*A</code> for <code>long</code> matrix <code>A</code>.
518
*/
519
private static class LongMatrix {
520
volatile long value[][];
521
522
/**
523
* Number of lines and columns in <code>this</code> square matrix.
524
*/
525
public int size() {
526
return value.length;
527
}
528
529
530
/**
531
* New square matrix with the given integer elements.
532
*/
533
public LongMatrix(IntegerMatrix A) {
534
int size = A.size();
535
value = new long[size][size];
536
for (int line = 0; line < size; line++)
537
for (int column = 0; column < size; column++)
538
value[line][column] = A.value[line][column];
539
}
540
541
/**
542
* Assign <code>this</code> matrix with <code>A*A</code>.
543
*
544
* @param threads Split computation into the given number of threads.
545
*/
546
public void setSquareOf(LongMatrix A, int threads) {
547
if (this.size() != A.size())
548
throw new IllegalArgumentException(
549
"this.size() != A.size()");
550
551
if ((size() % threads) != 0)
552
throw new IllegalArgumentException("size()%threads != 0");
553
int bunch = size() / threads;
554
555
Thread task[] = new Thread[threads];
556
for (int t = 0; t < threads; t++) {
557
int line0 = bunch * t;
558
MatrixComputer computer =
559
new MatrixComputer(value, A.value, line0, bunch);
560
task[t] = new Thread(computer);
561
}
562
563
for (int t = 0; t < threads; t++)
564
task[t].start();
565
566
for (int t = 0; t < threads; t++)
567
if (task[t].isAlive())
568
try {
569
task[t].join();
570
} catch (InterruptedException exception) {
571
throw new RuntimeException(exception.toString());
572
}
573
}
574
575
/**
576
* Thread to compute a bunch of lines of matrix square.
577
*/
578
private static class MatrixComputer implements Runnable {
579
private long result[][];
580
private long source[][];
581
private int line0;
582
private int bunch;
583
584
/**
585
* Register a task for matrix multiplication.
586
*/
587
public MatrixComputer(
588
long result[][], long source[][], int line0, int bunch) {
589
590
this.result = result; // reference to resulting matrix value
591
this.source = source; // reference to matrix to be squared
592
this.line0 = line0; // compute lines from line0 to ...
593
this.bunch = bunch; // number of resulting lines to compute
594
}
595
596
/**
597
* Do execute the task just registered for <code>this</code> thread.
598
*/
599
public void run() {
600
int line1 = line0 + bunch;
601
int size = result.length;
602
for (int line = line0; line < line1; line++)
603
for (int column = 0; column < size; column++) {
604
long sum = 0;
605
for (int i = 0; i < size; i++)
606
sum += source[line][i] * source[i][column];
607
result[line][column] = sum;
608
}
609
}
610
611
}
612
613
}
614
615
/**
616
* Compute <code>A*A</code> for <code>float</code> matrix <code>A</code>.
617
*/
618
private static class FloatMatrix {
619
volatile float value[][];
620
621
/**
622
* Number of lines and columns in <code>this</code> square matrix.
623
*/
624
public int size() {
625
return value.length;
626
}
627
628
629
/**
630
* New square matrix with the given integer elements.
631
*/
632
public FloatMatrix(IntegerMatrix A) {
633
int size = A.size();
634
value = new float[size][size];
635
for (int line = 0; line < size; line++)
636
for (int column = 0; column < size; column++)
637
value[line][column] = A.value[line][column];
638
}
639
640
/**
641
* Assign <code>this</code> matrix with <code>A*A</code>.
642
*
643
* @param threads Split computation into the given number of threads.
644
*/
645
public void setSquareOf(FloatMatrix A, int threads) {
646
if (this.size() != A.size())
647
throw new IllegalArgumentException(
648
"this.size() != A.size()");
649
650
if ((size() % threads) != 0)
651
throw new IllegalArgumentException("size()%threads != 0");
652
int bunch = size() / threads;
653
654
Thread task[] = new Thread[threads];
655
for (int t = 0; t < threads; t++) {
656
int line0 = bunch * t;
657
MatrixComputer computer =
658
new MatrixComputer(value, A.value, line0, bunch);
659
task[t] = new Thread(computer);
660
}
661
662
for (int t = 0; t < threads; t++)
663
task[t].start();
664
665
for (int t = 0; t < threads; t++)
666
if (task[t].isAlive())
667
try {
668
task[t].join();
669
} catch (InterruptedException exception) {
670
throw new RuntimeException(exception.toString());
671
}
672
}
673
674
/**
675
* Thread to compute a bunch of lines of matrix square.
676
*/
677
private static class MatrixComputer implements Runnable {
678
private float result[][];
679
private float source[][];
680
private int line0;
681
private int bunch;
682
683
/**
684
* Register a task for matrix multiplication.
685
*/
686
public MatrixComputer(
687
float result[][], float source[][], int line0, int bunch) {
688
689
this.result = result; // reference to resulting matrix value
690
this.source = source; // reference to matrix to be squared
691
this.line0 = line0; // compute lines from line0 to ...
692
this.bunch = bunch; // number of resulting lines to compute
693
}
694
695
/**
696
* Do execute the task just registered for <code>this</code> thread.
697
*/
698
public void run() {
699
int line1 = line0 + bunch;
700
int size = result.length;
701
for (int line = line0; line < line1; line++)
702
for (int column = 0; column < size; column++) {
703
float sum = 0;
704
for (int i = 0; i < size; i++)
705
sum += source[line][i] * source[i][column];
706
result[line][column] = sum;
707
}
708
}
709
710
}
711
712
}
713
714
/**
715
* Compute <code>A*A</code> for <code>float</code> matrix <code>A</code>.
716
*/
717
private static class DoubleMatrix {
718
volatile double value[][];
719
720
/**
721
* Number of lines and columns in <code>this</code> square matrix.
722
*/
723
public int size() {
724
return value.length;
725
}
726
727
728
/**
729
* New square matrix with the given integer elements.
730
*/
731
public DoubleMatrix(IntegerMatrix A) {
732
int size = A.size();
733
value = new double[size][size];
734
for (int line = 0; line < size; line++)
735
for (int column = 0; column < size; column++)
736
value[line][column] = A.value[line][column];
737
}
738
739
/**
740
* Assign <code>this</code> matrix with <code>A*A</code>.
741
*
742
* @param threads Split computation into the given number of threads.
743
*/
744
public void setSquareOf(DoubleMatrix A, int threads) {
745
if (this.size() != A.size())
746
throw new IllegalArgumentException(
747
"this.size() != A.size()");
748
749
if ((size() % threads) != 0)
750
throw new IllegalArgumentException("size()%threads != 0");
751
int bunch = size() / threads;
752
753
Thread task[] = new Thread[threads];
754
for (int t = 0; t < threads; t++) {
755
int line0 = bunch * t;
756
MatrixComputer computer =
757
new MatrixComputer(value, A.value, line0, bunch);
758
task[t] = new Thread(computer);
759
}
760
761
for (int t = 0; t < threads; t++)
762
task[t].start();
763
764
for (int t = 0; t < threads; t++)
765
if (task[t].isAlive())
766
try {
767
task[t].join();
768
} catch (InterruptedException exception) {
769
throw new RuntimeException(exception.toString());
770
}
771
}
772
773
/**
774
* Thread to compute a bunch of lines of matrix square.
775
*/
776
private static class MatrixComputer implements Runnable {
777
private double result[][];
778
private double source[][];
779
private int line0;
780
private int bunch;
781
782
/**
783
* Register a task for matrix multiplication.
784
*/
785
public MatrixComputer(
786
double result[][], double source[][], int line0, int bunch) {
787
788
this.result = result; // reference to resulting matrix value
789
this.source = source; // reference to matrix to be squared
790
this.line0 = line0; // compute lines from line0 to ...
791
this.bunch = bunch; // number of resulting lines to compute
792
}
793
794
/**
795
* Do execute the task just registered for <code>this</code> thread.
796
*/
797
public void run() {
798
int line1 = line0 + bunch;
799
int size = result.length;
800
for (int line = line0; line < line1; line++)
801
for (int column = 0; column < size; column++) {
802
double sum = 0;
803
for (int i = 0; i < size; i++)
804
sum += source[line][i] * source[i][column];
805
result[line][column] = sum;
806
}
807
}
808
809
}
810
811
}
812
813
}
814
815