1
+ using System . Runtime . CompilerServices ;
2
+ using System . Runtime . Intrinsics ;
3
+ using System . Runtime . Intrinsics . X86 ;
4
+ using System . Security . Cryptography ;
5
+
6
+ namespace mandelbrot ;
7
+
8
+ public static class MandelBrot
9
+ {
10
+ public static void Main ( string [ ] args )
11
+ {
12
+ int size = args . Length == 0 ? 200 : int . Parse ( args [ 0 ] ) ;
13
+ size = ( size + 7 ) / 8 * 8 ;
14
+ int rowBytes = size / 8 ;
15
+ double inv = 2.0 / size ;
16
+
17
+ Console . WriteLine ( $ "P4\n { size } { size } ") ;
18
+
19
+
20
+ byte [ ] data = new byte [ size * rowBytes ] ;
21
+
22
+ // Constants
23
+ Vector256 < double > idx4 = Vector256 . Create ( 0.0 , 1.0 , 2.0 , 3.0 ) ;
24
+ Vector256 < double > four = Vector256 . Create ( 4.0 ) ;
25
+ Vector256 < double > invV = Vector256 . Create ( inv ) ;
26
+ Vector256 < double > neg1_5 = Vector256 . Create ( - 1.5 ) ;
27
+
28
+ Parallel . For ( 0 , size , y =>
29
+ {
30
+ double ciScalar = y * inv - 1.0 ;
31
+ Vector256 < double > ci = Vector256 . Create ( ciScalar ) ;
32
+
33
+ for ( int xb = 0 ; xb < rowBytes ; xb ++ )
34
+ {
35
+ double baseX = xb * 8.0 ;
36
+
37
+
38
+ Vector256 < double > cr0 = Vector256 . Add (
39
+ Vector256 . Multiply (
40
+ Vector256 . Add ( idx4 , Vector256 . Create ( baseX ) ) , invV ) ,
41
+ neg1_5 ) ;
42
+ Vector256 < double > cr1 = Vector256 . Add (
43
+ Vector256 . Multiply (
44
+ Vector256 . Add ( idx4 , Vector256 . Create ( baseX + 4.0 ) ) , invV ) ,
45
+ neg1_5 ) ;
46
+
47
+ byte hi = MBrot4Block5Mask ( cr0 , ci , four , hiNibble : true ) ;
48
+ byte lo = MBrot4Block5Mask ( cr1 , ci , four , hiNibble : false ) ;
49
+ data [ y * rowBytes + xb ] = ( byte ) ( hi | lo ) ;
50
+ }
51
+ } ) ;
52
+ byte [ ] hash = MD5 . HashData ( data . AsSpan ( ) ) ;
53
+ Console . WriteLine ( Convert . ToHexString ( hash . AsSpan ( ) ) . ToLowerInvariant ( ) ) ;
54
+ }
55
+
56
+
57
+ [ MethodImpl ( MethodImplOptions . AggressiveInlining | MethodImplOptions . AggressiveOptimization ) ]
58
+ private static byte MBrot4Block5Mask ( Vector256 < double > cr , Vector256 < double > ci , Vector256 < double > four , bool hiNibble )
59
+ {
60
+ Vector256 < double > zr = Vector256 < double > . Zero ;
61
+ Vector256 < double > zi = Vector256 < double > . Zero ;
62
+ Vector256 < double > tr = Vector256 < double > . Zero ;
63
+ Vector256 < double > ti = Vector256 < double > . Zero ;
64
+ Vector256 < double > inside = Vector256 < long > . Zero . AsDouble ( ) ;
65
+
66
+ for ( int outer = 0 ; outer < 10 ; outer ++ )
67
+ {
68
+ for ( int j = 0 ; j < 5 ; j ++ )
69
+ {
70
+ // zi = (zr + zr) * zi + ci;
71
+ Vector256 < double > twoZr = Vector256 . Add ( zr , zr ) ;
72
+ zi = Vector256 . Add ( Vector256 . Multiply ( twoZr , zi ) , ci ) ;
73
+
74
+ // zr = tr - ti + cr; (tr, ti from previous sub-iteration)
75
+ zr = Vector256 . Add ( Vector256 . Subtract ( tr , ti ) , cr ) ;
76
+
77
+ // tr = zr*zr; ti = zi*zi;
78
+ tr = Vector256 . Multiply ( zr , zr ) ;
79
+ ti = Vector256 . Multiply ( zi , zi ) ;
80
+ }
81
+
82
+ Vector256 < double > abs2 = Vector256 . Add ( tr , ti ) ;
83
+ inside = Vector256 . LessThanOrEqual ( abs2 , four ) . AsDouble ( ) ;
84
+ }
85
+
86
+ int m = Avx . MoveMask ( inside ) ;
87
+
88
+ if ( hiNibble )
89
+ {
90
+ return ( byte ) (
91
+ ( ( m & 1 ) << 7 ) |
92
+ ( ( m & 2 ) << 5 ) |
93
+ ( ( m & 4 ) << 3 ) |
94
+ ( ( m & 8 ) << 1 )
95
+ ) ;
96
+ }
97
+
98
+ return ( byte ) (
99
+ ( ( m & 1 ) << 3 ) |
100
+ ( ( m & 2 ) << 1 ) |
101
+ ( ( m & 4 ) >> 1 ) |
102
+ ( ( m & 8 ) >> 3 )
103
+ ) ;
104
+ }
105
+ }
0 commit comments