Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
M
mandelbrot-explorer
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Ильин Владимир Александрович
mandelbrot-explorer
Commits
19a46d0f
Commit
19a46d0f
authored
Jun 25, 2025
by
Ильин Владимир Александрович
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
-i arg for max iterations and lots of new bugs fixed!
parent
e00e1adf
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
59 additions
and
48 deletions
+59
-48
Makefile
Makefile
+1
-1
mandelbrot.c
src/mandelbrot.c
+58
-46
mandelbrot.h
src/mandelbrot.h
+0
-1
No files found.
Makefile
View file @
19a46d0f
...
...
@@ -19,7 +19,7 @@ CC = clang
OBJS
=
$(BIULDDIR)
/mouse.o
$(BIULDDIR)
/ui.o
all
:
mandelbrot
all
:
mandelbrot
fast
mandelbrot
:
$(SRCDIR)/mandelbrot.c $(OBJS)
$(CC)
$(CFLAGS)
$(DEBUG_FLAGS)
$(LDLIBS)
$^
-o
$@
...
...
src/mandelbrot.c
View file @
19a46d0f
...
...
@@ -32,7 +32,7 @@
*/
int
mandelbrot_avx
(
Complex
c
)
mandelbrot_avx
(
Complex
c
,
unsigned
max_iterations
)
{
__m256
cr
=
_mm256_set1_pd
(
c
.
real
);
__m256
ci
=
_mm256_set1_pd
(
c
.
imag
);
...
...
@@ -42,11 +42,11 @@ mandelbrot_avx(Complex c)
__m256
threshold
=
_mm256_set1_pd
(
4
);
int
k
=
1
;
unsigned
int
k
=
1
;
__m256
mk
=
_mm256_set1_pd
(
k
);
__m256
one
=
_mm256_set1_pd
(
1
);
while
(
++
k
<
MAX_ITERATIONS
){
while
(
++
k
<
max_iterations
){
/* Compute z1 from z0 */
__m256
zr2
=
_mm256_mul_pd
(
zr
,
zr
);
__m256
zi2
=
_mm256_mul_pd
(
zi
,
zi
);
...
...
@@ -72,11 +72,11 @@ mandelbrot_avx(Complex c)
int
mandelbrot
(
Complex
c
)
{
mandelbrot
(
Complex
c
,
unsigned
int
max_iterations
)
{
Complex
z
=
{
0
.
0
,
0
.
0
};
int
i
;
unsigned
int
i
;
for
(
i
=
0
;
i
<
MAX_ITERATIONS
;
i
++
)
{
for
(
i
=
0
;
i
<
max_iterations
;
i
++
)
{
long
double
temp_real
=
z
.
real
*
z
.
real
-
z
.
imag
*
z
.
imag
+
c
.
real
;
long
double
temp_imag
=
2
*
z
.
real
*
z
.
imag
+
c
.
imag
;
z
.
real
=
temp_real
;
...
...
@@ -85,7 +85,7 @@ mandelbrot(Complex c) {
if
(
__builtin_hypot
(
z
.
real
,
z
.
imag
)
>
2
)
return
i
;
}
return
MAX_ITERATIONS
;
return
max_iterations
;
}
typedef
struct
{
...
...
@@ -101,9 +101,9 @@ typedef struct {
}
Array
;
void
calculate_set
(
Array
*
arr
,
int
height
,
int
width
,
ViewInfo
view
,
short
unsigned
use_avx
)
calculate_set
(
Array
*
arr
,
int
height
,
int
width
,
ViewInfo
view
,
short
unsigned
use_avx
,
unsigned
int
max_iterations
)
{
int
(
*
mandelbrot_func
)(
Complex
C
);
int
(
*
mandelbrot_func
)(
Complex
C
,
unsigned
);
if
(
use_avx
==
0
)
mandelbrot_func
=
mandelbrot
;
...
...
@@ -116,15 +116,15 @@ calculate_set(Array *arr, int height, int width, ViewInfo view, short unsigned u
long
double
imag
=
view
.
y_min
+
(
y
*
(
view
.
y_max
-
view
.
y_min
))
/
height
;
Complex
c
=
{
real
,
imag
};
int
iterations
=
mandelbrot_func
(
c
);
unsigned
int
iterations
=
mandelbrot_func
(
c
,
max_iterations
);
if
(
iterations
==
MAX_ITERATIONS
){
if
(
iterations
==
max_iterations
){
arr
->
pointer
[
y
*
width
+
x
].
r
=
0
;
arr
->
pointer
[
y
*
width
+
x
].
g
=
0
;
arr
->
pointer
[
y
*
width
+
x
].
b
=
0
;
arr
->
pointer
[
y
*
width
+
x
].
a
=
0
;
}
else
{
double
t
=
(
double
)
iterations
/
MAX_ITERATIONS
;
double
t
=
(
double
)
iterations
/
max_iterations
;
t
=
0
.
5
+
0
.
5
*
tan
(
log
(
t
+
0
.
0001
)
*
3
.
0
);
arr
->
pointer
[
y
*
width
+
x
].
r
=
255
*
t
*
0
.
5
;
...
...
@@ -137,9 +137,9 @@ calculate_set(Array *arr, int height, int width, ViewInfo view, short unsigned u
}
void
calculate_set_omp
(
Array
*
arr
,
int
height
,
int
width
,
ViewInfo
view
,
short
unsigned
use_avx
)
calculate_set_omp
(
Array
*
arr
,
int
height
,
int
width
,
ViewInfo
view
,
short
unsigned
use_avx
,
unsigned
int
max_iterations
)
{
int
(
*
mandelbrot_func
)(
Complex
C
);
int
(
*
mandelbrot_func
)(
Complex
,
unsigned
);
if
(
use_avx
==
0
)
mandelbrot_func
=
mandelbrot
;
...
...
@@ -153,15 +153,15 @@ calculate_set_omp(Array *arr, int height, int width, ViewInfo view, short unsign
long
double
imag
=
view
.
y_min
+
(
y
*
(
view
.
y_max
-
view
.
y_min
))
/
height
;
Complex
c
=
{
real
,
imag
};
int
iterations
=
mandelbrot_func
(
c
);
unsigned
int
iterations
=
mandelbrot_func
(
c
,
max_iterations
);
if
(
iterations
==
MAX_ITERATIONS
){
if
(
iterations
==
max_iterations
){
arr
->
pointer
[
y
*
width
+
x
].
r
=
0
;
arr
->
pointer
[
y
*
width
+
x
].
g
=
0
;
arr
->
pointer
[
y
*
width
+
x
].
b
=
0
;
arr
->
pointer
[
y
*
width
+
x
].
a
=
0
;
}
else
{
double
t
=
(
double
)
iterations
/
MAX_ITERATIONS
;
double
t
=
(
double
)
iterations
/
max_iterations
;
t
=
0
.
5
+
0
.
5
*
tan
(
log
(
t
+
0
.
0001
)
*
3
.
0
);
arr
->
pointer
[
y
*
width
+
x
].
r
=
255
*
t
*
0
.
5
;
...
...
@@ -194,9 +194,10 @@ struct arguments
char
*
output_file
;
int
width
;
int
height
;
unsigned
int
max_iterations
;
short
unsigned
use_avx
;
short
unsigned
use_omp
;
int
re
d
calc
;
int
recalc
;
double
x_min
;
double
x_max
;
...
...
@@ -209,12 +210,13 @@ struct arguments
static
struct
argp_option
options
[]
=
{
{
"output file"
,
'o'
,
"FILE"
,
0
,
"Render to image"
},
{
"width"
,
'w'
,
"WIDTH"
,
0
,
"Width of window/image"
},
{
"height"
,
'h'
,
"HEIGHT"
,
0
,
"Height of window/image"
},
{
"dont_use_avx"
,
'x'
,
0
,
0
,
"NOT use avx for calculations"
},
{
"dont_use_omp"
,
't'
,
0
,
0
,
"NOT use openmpfor calculations"
},
{
"recalc"
,
'r'
,
0
,
0
,
"Recalculate set on every frame"
},
{
"output file"
,
'o'
,
"FILE"
,
0
,
"Render to image, default False"
},
{
"width"
,
'w'
,
"WIDTH"
,
0
,
"Width of window/image, default 640"
},
{
"height"
,
'h'
,
"HEIGHT"
,
0
,
"Height of window/image, default 480"
},
{
"iterations"
,
'i'
,
"ITERATIONS"
,
0
,
"Max iterations, default 250."
},
{
"dont_use_avx"
,
'x'
,
0
,
0
,
"NOT use avx for calculations, default False"
},
{
"dont_use_omp"
,
't'
,
0
,
0
,
"NOT use openmpfor calculations, default False"
},
{
"recalc"
,
'r'
,
0
,
0
,
"Recalculate set on every frame, default False"
},
{
"x_min"
,
'a'
,
"VALUE"
,
0
,
"X min"
},
{
"x_max"
,
'b'
,
"VALUE"
,
0
,
"X max"
},
...
...
@@ -231,6 +233,9 @@ parse_opt (int key, char *arg, struct argp_state *state)
struct
arguments
*
arguments
=
state
->
input
;
switch
(
key
)
{
case
'i'
:
arguments
->
max_iterations
=
atoi
(
arg
);
break
;
case
'o'
:
arguments
->
output_file
=
arg
;
break
;
...
...
@@ -247,20 +252,20 @@ parse_opt (int key, char *arg, struct argp_state *state)
arguments
->
use_omp
=
0
;
break
;
case
'r'
:
arguments
->
re
d
calc
=
1
;
arguments
->
recalc
=
1
;
break
;
case
'a'
:
arguments
->
x_m
in
=
atoi
(
arg
);
arguments
->
x_m
ax
=
atoi
(
arg
);
break
;
case
'b'
:
arguments
->
redcalc
=
atoi
(
arg
);
arguments
->
x_min
=
atoi
(
arg
);
break
;
case
'c'
:
arguments
->
redcalc
=
atoi
(
arg
);
arguments
->
y_max
=
atoi
(
arg
);
break
;
case
'd'
:
arguments
->
redcalc
=
atoi
(
arg
);
arguments
->
y_min
=
atoi
(
arg
);
break
;
case
'z'
:
arguments
->
zoom
=
atof
(
arg
);
...
...
@@ -280,10 +285,11 @@ parse_opt (int key, char *arg, struct argp_state *state)
static
struct
argp
argp
=
{
options
,
parse_opt
,
NULL
,
NULL
};
void
render_cl
(
Array
*
arr
,
SDL_Texture
*
texture
,
SDL_Renderer
*
renderer
,
int
width
,
int
height
,
ViewInfo
*
view
,
short
unsigned
use_avx
,
short
unsigned
use_omp
,
short
unsigned
*
needs_recalc
)
{
render_cl
(
Array
*
arr
,
SDL_Texture
*
texture
,
SDL_Renderer
*
renderer
,
int
width
,
int
height
,
ViewInfo
*
view
,
short
unsigned
use_avx
,
short
unsigned
use_omp
,
short
unsigned
*
needs_recalc
,
unsigned
int
max_iterations
)
{
void
(
*
calculate_set_func
)(
Array
*
arr
,
int
height
,
int
width
,
ViewInfo
view
,
short
unsigned
use_avx
);
ViewInfo
view
,
short
unsigned
use_avx
,
unsigned
max_iterations
);
calculate_set_func
=
use_omp
?
calculate_set_omp
:
calculate_set
;
...
...
@@ -294,8 +300,8 @@ render_cl(Array *arr, SDL_Texture *texture, SDL_Renderer *renderer, int width, i
arr
->
pointer
=
realloc
(
arr
->
pointer
,
height
*
width
*
sizeof
(
Color
));
arr
->
size
=
height
*
width
*
sizeof
(
Color
);
}
if
(
needs_recalc
){
calculate_set_func
(
arr
,
height
,
width
,
*
view
,
use_avx
);
if
(
*
needs_recalc
){
calculate_set_func
(
arr
,
height
,
width
,
*
view
,
use_avx
,
max_iterations
);
*
needs_recalc
=
0
;
}
...
...
@@ -306,7 +312,7 @@ render_cl(Array *arr, SDL_Texture *texture, SDL_Renderer *renderer, int width, i
short
unsigned
render_headless
(
ViewInfo
view
,
const
char
*
filename
,
int
width
,
int
height
,
int
width
,
int
height
,
unsigned
int
max_iterations
,
short
unsigned
use_avx
,
short
unsigned
use_omp
)
{
SDL_Surface
*
surface
=
SDL_CreateRGBSurface
(
0
,
width
,
height
,
...
...
@@ -329,12 +335,9 @@ render_headless(ViewInfo view, const char* filename,
width
*
height
*
sizeof
(
Color
)
};
void
(
*
calculate_set_func
)(
Array
*
,
int
,
int
,
ViewInfo
,
short
unsigned
);
calculate_set_func
=
use_omp
?
calculate_set_omp
:
calculate_set
;
short
unsigned
int
plug
;
render_cl
(
&
arr
,
texture
,
renderer
,
width
,
height
,
&
view
,
use_avx
,
use_omp
,
&
plug
);
render_cl
(
&
arr
,
texture
,
renderer
,
width
,
height
,
&
view
,
use_avx
,
use_omp
,
&
plug
,
max_iterations
);
IMG_SavePNG
(
surface
,
filename
);
free
(
arr
.
pointer
);
...
...
@@ -349,8 +352,8 @@ main(int argc, char **argv)
struct
arguments
args
=
{
NULL
,
640
,
480
,
1
,
1
,
0
,
-
2
.
0
,
1
.
0
,
-
1
.
5
,
1
.
5
,
1
.
0
250
,
1
,
0
,
0
,
-
2
.
0
,
1
.
0
,
-
1
.
5
,
1
.
5
,
1
.
0
,
};
argp_parse
(
&
argp
,
argc
,
argv
,
0
,
0
,
&
args
);
...
...
@@ -370,7 +373,8 @@ main(int argc, char **argv)
if
(
args
.
output_file
)
{
render_headless
(
view
,
args
.
output_file
,
args
.
width
,
args
.
height
,
args
.
use_avx
,
args
.
use_omp
);
args
.
use_avx
,
args
.
use_omp
,
args
.
max_iterations
);
SDL_Quit
();
return
0
;
}
...
...
@@ -388,7 +392,7 @@ main(int argc, char **argv)
SDL_TEXTUREACCESS_STREAMING
,
args
.
width
,
args
.
height
),
args
.
height
,
args
.
height
,
args
.
width
,
1
,
0
};
...
...
@@ -478,8 +482,13 @@ main(int argc, char **argv)
}
default:
//returns one if recalc needed
app
.
needs_recalc
=
app
.
needs_recalc
==
0
?
handle_mouse
(
event
,
&
mouse
,
&
view
)
:
1
;
app
.
needs_recalc
=
(
app
.
needs_recalc
||
args
.
redcalc
);
if
(
event
.
type
==
SDL_MOUSEBUTTONDOWN
||
event
.
type
==
SDL_MOUSEBUTTONUP
||
event
.
type
==
SDL_MOUSEWHEEL
||
event
.
type
==
SDL_MOUSEMOTION
)
{
app
.
needs_recalc
=
handle_mouse
(
event
,
&
mouse
,
&
view
);
}
app
.
needs_recalc
=
(
app
.
needs_recalc
||
args
.
recalc
);
break
;
}
...
...
@@ -489,8 +498,11 @@ main(int argc, char **argv)
SDL_SetRenderDrawColor
(
app
.
renderer
,
0xff
,
0xff
,
0xff
,
0xff
);
SDL_RenderClear
(
app
.
renderer
);
render_cl
(
&
screen
,
app
.
texture
,
app
.
renderer
,
app
.
win_width
,
app
.
win_height
,
&
view
,
args
.
use_avx
,
args
.
use_omp
,
&
app
.
needs_recalc
);
printf
(
"needs_recalc: %i
\n
"
,
app
.
needs_recalc
);
render_cl
(
&
screen
,
app
.
texture
,
app
.
renderer
,
app
.
win_width
,
app
.
win_height
,
&
view
,
args
.
use_avx
,
args
.
use_omp
,
&
app
.
needs_recalc
,
args
.
max_iterations
);
int
msec
=
SDL_GetTicks
()
-
frame_start
;
float
fps
=
0
;
if
(
msec
>
0
)
...
...
src/mandelbrot.h
View file @
19a46d0f
...
...
@@ -6,7 +6,6 @@
#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480
#define MAX_ITERATIONS 250
typedef
struct
{
long
double
real
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment