ASCII Mandelbrot
up vote
1
down vote
favorite
First of all, let me answer the question that a lot of you may have:
The Mandelbrot set is the set of values of c in the complex plane for which the orbit of 0 under iteration of the quadratic map when f(x) = x2 + c.
The fun thing about the Mandelbrot set is that it's a fractal and you can indefinitely zoom into it. Here's a demonstration.
This code does not zoom into the set, it only shows the first iteration of the fractal. This ASCII image is taken directly from the result of my program:
*
*******
************
***************
*****************
********************
*********************
* * ********************** *
***** *********************** *
******** *****************************
********* *************************
**********************************
***********************************
*************************************
************************************
***********************************
***********************************
***********************************
***********************************
************************************
*************************************
***********************************
**********************************
********* *************************
******** *****************************
***** *********************** *
* * ********************** *
*********************
********************
****************
***************
************
*******
*
The code is simple, it calculates if a character between height and width is placed on the set, if it is, it inserts an asterisk. If it's not, it inserts a space. It then adds a newline char. Here's the code:
#include <iostream>
#include <vector>
#include <string>
#include <cmath>
const int height = 40, width = 80;
typedef std::vector<double> tuple;
tuple coord_to_complex(double i, double j)
{
double real = (4*i) / (width - 1) - 2.0;
double imaginary = (2.2 * j) / (height - 1) - 1.1;
tuple ret = {real, imaginary};
return ret;
}
bool is_in_mandelbrot(tuple re_im)
{
auto cr = re_im[0], ci = re_im[1];
auto zr = cr, zi = ci;
for (int t = 0; t <= 1000; ++t)
{
zr = (std::pow(zr, 2) - std::pow(zi, 2)) + cr;
zi = (2*zi*zr) + ci;
if (std::sqrt(std::pow(zr, 2) + std::pow(zi, 2)) > 2)
return false;
}
return true;
}
std::string print_set()
{
std::string ret = "";
for (int i = 0; i <= height; ++i)
{
for (int j = 0; j <= width; ++j)
{
if (is_in_mandelbrot(coord_to_complex(j, i)))
{
ret += '*';
}
else
{
ret += ' ';
}
}
ret += 'n';
}
return ret;
}
int main() {
std::cout << print_set() << std::endl;
return 0;
}
There's nothing else to say but thanks. So thank you for reading my code.
Credits: Most of the code is based on a codegolfing practice in Python that I found on Github so thanks to the Python programmer who wrote solved that coding challenge.
c++ c++14 ascii-art fractals
New contributor
add a comment |
up vote
1
down vote
favorite
First of all, let me answer the question that a lot of you may have:
The Mandelbrot set is the set of values of c in the complex plane for which the orbit of 0 under iteration of the quadratic map when f(x) = x2 + c.
The fun thing about the Mandelbrot set is that it's a fractal and you can indefinitely zoom into it. Here's a demonstration.
This code does not zoom into the set, it only shows the first iteration of the fractal. This ASCII image is taken directly from the result of my program:
*
*******
************
***************
*****************
********************
*********************
* * ********************** *
***** *********************** *
******** *****************************
********* *************************
**********************************
***********************************
*************************************
************************************
***********************************
***********************************
***********************************
***********************************
************************************
*************************************
***********************************
**********************************
********* *************************
******** *****************************
***** *********************** *
* * ********************** *
*********************
********************
****************
***************
************
*******
*
The code is simple, it calculates if a character between height and width is placed on the set, if it is, it inserts an asterisk. If it's not, it inserts a space. It then adds a newline char. Here's the code:
#include <iostream>
#include <vector>
#include <string>
#include <cmath>
const int height = 40, width = 80;
typedef std::vector<double> tuple;
tuple coord_to_complex(double i, double j)
{
double real = (4*i) / (width - 1) - 2.0;
double imaginary = (2.2 * j) / (height - 1) - 1.1;
tuple ret = {real, imaginary};
return ret;
}
bool is_in_mandelbrot(tuple re_im)
{
auto cr = re_im[0], ci = re_im[1];
auto zr = cr, zi = ci;
for (int t = 0; t <= 1000; ++t)
{
zr = (std::pow(zr, 2) - std::pow(zi, 2)) + cr;
zi = (2*zi*zr) + ci;
if (std::sqrt(std::pow(zr, 2) + std::pow(zi, 2)) > 2)
return false;
}
return true;
}
std::string print_set()
{
std::string ret = "";
for (int i = 0; i <= height; ++i)
{
for (int j = 0; j <= width; ++j)
{
if (is_in_mandelbrot(coord_to_complex(j, i)))
{
ret += '*';
}
else
{
ret += ' ';
}
}
ret += 'n';
}
return ret;
}
int main() {
std::cout << print_set() << std::endl;
return 0;
}
There's nothing else to say but thanks. So thank you for reading my code.
Credits: Most of the code is based on a codegolfing practice in Python that I found on Github so thanks to the Python programmer who wrote solved that coding challenge.
c++ c++14 ascii-art fractals
New contributor
add a comment |
up vote
1
down vote
favorite
up vote
1
down vote
favorite
First of all, let me answer the question that a lot of you may have:
The Mandelbrot set is the set of values of c in the complex plane for which the orbit of 0 under iteration of the quadratic map when f(x) = x2 + c.
The fun thing about the Mandelbrot set is that it's a fractal and you can indefinitely zoom into it. Here's a demonstration.
This code does not zoom into the set, it only shows the first iteration of the fractal. This ASCII image is taken directly from the result of my program:
*
*******
************
***************
*****************
********************
*********************
* * ********************** *
***** *********************** *
******** *****************************
********* *************************
**********************************
***********************************
*************************************
************************************
***********************************
***********************************
***********************************
***********************************
************************************
*************************************
***********************************
**********************************
********* *************************
******** *****************************
***** *********************** *
* * ********************** *
*********************
********************
****************
***************
************
*******
*
The code is simple, it calculates if a character between height and width is placed on the set, if it is, it inserts an asterisk. If it's not, it inserts a space. It then adds a newline char. Here's the code:
#include <iostream>
#include <vector>
#include <string>
#include <cmath>
const int height = 40, width = 80;
typedef std::vector<double> tuple;
tuple coord_to_complex(double i, double j)
{
double real = (4*i) / (width - 1) - 2.0;
double imaginary = (2.2 * j) / (height - 1) - 1.1;
tuple ret = {real, imaginary};
return ret;
}
bool is_in_mandelbrot(tuple re_im)
{
auto cr = re_im[0], ci = re_im[1];
auto zr = cr, zi = ci;
for (int t = 0; t <= 1000; ++t)
{
zr = (std::pow(zr, 2) - std::pow(zi, 2)) + cr;
zi = (2*zi*zr) + ci;
if (std::sqrt(std::pow(zr, 2) + std::pow(zi, 2)) > 2)
return false;
}
return true;
}
std::string print_set()
{
std::string ret = "";
for (int i = 0; i <= height; ++i)
{
for (int j = 0; j <= width; ++j)
{
if (is_in_mandelbrot(coord_to_complex(j, i)))
{
ret += '*';
}
else
{
ret += ' ';
}
}
ret += 'n';
}
return ret;
}
int main() {
std::cout << print_set() << std::endl;
return 0;
}
There's nothing else to say but thanks. So thank you for reading my code.
Credits: Most of the code is based on a codegolfing practice in Python that I found on Github so thanks to the Python programmer who wrote solved that coding challenge.
c++ c++14 ascii-art fractals
New contributor
First of all, let me answer the question that a lot of you may have:
The Mandelbrot set is the set of values of c in the complex plane for which the orbit of 0 under iteration of the quadratic map when f(x) = x2 + c.
The fun thing about the Mandelbrot set is that it's a fractal and you can indefinitely zoom into it. Here's a demonstration.
This code does not zoom into the set, it only shows the first iteration of the fractal. This ASCII image is taken directly from the result of my program:
*
*******
************
***************
*****************
********************
*********************
* * ********************** *
***** *********************** *
******** *****************************
********* *************************
**********************************
***********************************
*************************************
************************************
***********************************
***********************************
***********************************
***********************************
************************************
*************************************
***********************************
**********************************
********* *************************
******** *****************************
***** *********************** *
* * ********************** *
*********************
********************
****************
***************
************
*******
*
The code is simple, it calculates if a character between height and width is placed on the set, if it is, it inserts an asterisk. If it's not, it inserts a space. It then adds a newline char. Here's the code:
#include <iostream>
#include <vector>
#include <string>
#include <cmath>
const int height = 40, width = 80;
typedef std::vector<double> tuple;
tuple coord_to_complex(double i, double j)
{
double real = (4*i) / (width - 1) - 2.0;
double imaginary = (2.2 * j) / (height - 1) - 1.1;
tuple ret = {real, imaginary};
return ret;
}
bool is_in_mandelbrot(tuple re_im)
{
auto cr = re_im[0], ci = re_im[1];
auto zr = cr, zi = ci;
for (int t = 0; t <= 1000; ++t)
{
zr = (std::pow(zr, 2) - std::pow(zi, 2)) + cr;
zi = (2*zi*zr) + ci;
if (std::sqrt(std::pow(zr, 2) + std::pow(zi, 2)) > 2)
return false;
}
return true;
}
std::string print_set()
{
std::string ret = "";
for (int i = 0; i <= height; ++i)
{
for (int j = 0; j <= width; ++j)
{
if (is_in_mandelbrot(coord_to_complex(j, i)))
{
ret += '*';
}
else
{
ret += ' ';
}
}
ret += 'n';
}
return ret;
}
int main() {
std::cout << print_set() << std::endl;
return 0;
}
There's nothing else to say but thanks. So thank you for reading my code.
Credits: Most of the code is based on a codegolfing practice in Python that I found on Github so thanks to the Python programmer who wrote solved that coding challenge.
c++ c++14 ascii-art fractals
c++ c++14 ascii-art fractals
New contributor
New contributor
edited Nov 14 at 0:00
200_success
127k15148410
127k15148410
New contributor
asked Nov 13 at 23:22
ChubakBidpaa
12217
12217
New contributor
New contributor
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
up vote
2
down vote
Good work! I would only like to give you one piece of advice. I see this line in you code:
typedef std::vector<double> tuple;
I don't know if you are aware of this or not, but there is actually a data structure in the C++ standard library called std::tuple
. Click on the text for more information about it. I see that you did not include the std::tuple
, which is good. You also fully qualified all standard C++ library names with std::
instead of using namespace std
, which is also very good.
Just it is generally frowned upon in the C++ programming community to name your own variables and/or data types with the same name as names defined in the C++ standard library. You could have some name collisions and hidden bugs! If this is just your own project, of course you can do whatever you want. But keep in mind that if you are working on a project with multiple programmers at a large company, someone else might use your tuple intending to use std::tuple
or vice versa. In large source files, such small one line declarations can easily be missed if you are scrolling through the code editor very fast. Someone can unintentionally make the mistake. Or someone who does not like you might put using std::tuple;
somewhere intentionally to make your code fail. So it is best to avoid name collisions. There is a kind of philosophy called defensive programming. People tend to do things by their habits. If they are used to one kind of programming practice in their personal projects, they will do the same things at their job. Strive to work how you would work at your job. Think about what other people will think when they have to manage your code. Good luck!
I understand. I didn't know there's such a thing as std::tuple. Otherwise I would have used it.
– ChubakBidpaa
Nov 14 at 0:28
add a comment |
up vote
2
down vote
It's strange that you're using vectors instead of std::complex
to represent your complex numbers. I think you'll find that using the standard complex-number class will simplify your code.
It's much more efficient and accurate to square a number by simply multiplying rather than going via the much more general std::pow()
. Of course, with std::complex
, you don't need to do this squaring yourself, as the std::abs()
function is provided to do that for you.
It's also more efficient to compare the squared magnitude against the square of the bound, rather than to compute the square root of the magnitude (so use std::norm()
rather than std::abs()
).
These changes make for a much more natural version of the code (it's easier to see how it corresponds to the Mandelbrot algorithm):
#include <complex>
constexpr int height = 40, width = 80;
std::complex<double> coord_to_complex(double i, double j)
{
double real = (4*i) / (width - 1) - 2.0;
double imaginary = (2.2 * j) / (height - 1) - 1.1;
return {real, imaginary};
}
bool is_in_mandelbrot(const std::complex<double> c)
{
auto z = c;
for (int t = 0; t <= 1000; ++t)
{
z = z * z + c;
if (std::norm(z) > 4)
return false;
}
return true;
}
You can save some memory allocations by reserving space for the output:
std::string ret = "";
ret.reserve((width+1) * height);
add a comment |
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
2
down vote
Good work! I would only like to give you one piece of advice. I see this line in you code:
typedef std::vector<double> tuple;
I don't know if you are aware of this or not, but there is actually a data structure in the C++ standard library called std::tuple
. Click on the text for more information about it. I see that you did not include the std::tuple
, which is good. You also fully qualified all standard C++ library names with std::
instead of using namespace std
, which is also very good.
Just it is generally frowned upon in the C++ programming community to name your own variables and/or data types with the same name as names defined in the C++ standard library. You could have some name collisions and hidden bugs! If this is just your own project, of course you can do whatever you want. But keep in mind that if you are working on a project with multiple programmers at a large company, someone else might use your tuple intending to use std::tuple
or vice versa. In large source files, such small one line declarations can easily be missed if you are scrolling through the code editor very fast. Someone can unintentionally make the mistake. Or someone who does not like you might put using std::tuple;
somewhere intentionally to make your code fail. So it is best to avoid name collisions. There is a kind of philosophy called defensive programming. People tend to do things by their habits. If they are used to one kind of programming practice in their personal projects, they will do the same things at their job. Strive to work how you would work at your job. Think about what other people will think when they have to manage your code. Good luck!
I understand. I didn't know there's such a thing as std::tuple. Otherwise I would have used it.
– ChubakBidpaa
Nov 14 at 0:28
add a comment |
up vote
2
down vote
Good work! I would only like to give you one piece of advice. I see this line in you code:
typedef std::vector<double> tuple;
I don't know if you are aware of this or not, but there is actually a data structure in the C++ standard library called std::tuple
. Click on the text for more information about it. I see that you did not include the std::tuple
, which is good. You also fully qualified all standard C++ library names with std::
instead of using namespace std
, which is also very good.
Just it is generally frowned upon in the C++ programming community to name your own variables and/or data types with the same name as names defined in the C++ standard library. You could have some name collisions and hidden bugs! If this is just your own project, of course you can do whatever you want. But keep in mind that if you are working on a project with multiple programmers at a large company, someone else might use your tuple intending to use std::tuple
or vice versa. In large source files, such small one line declarations can easily be missed if you are scrolling through the code editor very fast. Someone can unintentionally make the mistake. Or someone who does not like you might put using std::tuple;
somewhere intentionally to make your code fail. So it is best to avoid name collisions. There is a kind of philosophy called defensive programming. People tend to do things by their habits. If they are used to one kind of programming practice in their personal projects, they will do the same things at their job. Strive to work how you would work at your job. Think about what other people will think when they have to manage your code. Good luck!
I understand. I didn't know there's such a thing as std::tuple. Otherwise I would have used it.
– ChubakBidpaa
Nov 14 at 0:28
add a comment |
up vote
2
down vote
up vote
2
down vote
Good work! I would only like to give you one piece of advice. I see this line in you code:
typedef std::vector<double> tuple;
I don't know if you are aware of this or not, but there is actually a data structure in the C++ standard library called std::tuple
. Click on the text for more information about it. I see that you did not include the std::tuple
, which is good. You also fully qualified all standard C++ library names with std::
instead of using namespace std
, which is also very good.
Just it is generally frowned upon in the C++ programming community to name your own variables and/or data types with the same name as names defined in the C++ standard library. You could have some name collisions and hidden bugs! If this is just your own project, of course you can do whatever you want. But keep in mind that if you are working on a project with multiple programmers at a large company, someone else might use your tuple intending to use std::tuple
or vice versa. In large source files, such small one line declarations can easily be missed if you are scrolling through the code editor very fast. Someone can unintentionally make the mistake. Or someone who does not like you might put using std::tuple;
somewhere intentionally to make your code fail. So it is best to avoid name collisions. There is a kind of philosophy called defensive programming. People tend to do things by their habits. If they are used to one kind of programming practice in their personal projects, they will do the same things at their job. Strive to work how you would work at your job. Think about what other people will think when they have to manage your code. Good luck!
Good work! I would only like to give you one piece of advice. I see this line in you code:
typedef std::vector<double> tuple;
I don't know if you are aware of this or not, but there is actually a data structure in the C++ standard library called std::tuple
. Click on the text for more information about it. I see that you did not include the std::tuple
, which is good. You also fully qualified all standard C++ library names with std::
instead of using namespace std
, which is also very good.
Just it is generally frowned upon in the C++ programming community to name your own variables and/or data types with the same name as names defined in the C++ standard library. You could have some name collisions and hidden bugs! If this is just your own project, of course you can do whatever you want. But keep in mind that if you are working on a project with multiple programmers at a large company, someone else might use your tuple intending to use std::tuple
or vice versa. In large source files, such small one line declarations can easily be missed if you are scrolling through the code editor very fast. Someone can unintentionally make the mistake. Or someone who does not like you might put using std::tuple;
somewhere intentionally to make your code fail. So it is best to avoid name collisions. There is a kind of philosophy called defensive programming. People tend to do things by their habits. If they are used to one kind of programming practice in their personal projects, they will do the same things at their job. Strive to work how you would work at your job. Think about what other people will think when they have to manage your code. Good luck!
answered Nov 13 at 23:37
Galaxy
1513
1513
I understand. I didn't know there's such a thing as std::tuple. Otherwise I would have used it.
– ChubakBidpaa
Nov 14 at 0:28
add a comment |
I understand. I didn't know there's such a thing as std::tuple. Otherwise I would have used it.
– ChubakBidpaa
Nov 14 at 0:28
I understand. I didn't know there's such a thing as std::tuple. Otherwise I would have used it.
– ChubakBidpaa
Nov 14 at 0:28
I understand. I didn't know there's such a thing as std::tuple. Otherwise I would have used it.
– ChubakBidpaa
Nov 14 at 0:28
add a comment |
up vote
2
down vote
It's strange that you're using vectors instead of std::complex
to represent your complex numbers. I think you'll find that using the standard complex-number class will simplify your code.
It's much more efficient and accurate to square a number by simply multiplying rather than going via the much more general std::pow()
. Of course, with std::complex
, you don't need to do this squaring yourself, as the std::abs()
function is provided to do that for you.
It's also more efficient to compare the squared magnitude against the square of the bound, rather than to compute the square root of the magnitude (so use std::norm()
rather than std::abs()
).
These changes make for a much more natural version of the code (it's easier to see how it corresponds to the Mandelbrot algorithm):
#include <complex>
constexpr int height = 40, width = 80;
std::complex<double> coord_to_complex(double i, double j)
{
double real = (4*i) / (width - 1) - 2.0;
double imaginary = (2.2 * j) / (height - 1) - 1.1;
return {real, imaginary};
}
bool is_in_mandelbrot(const std::complex<double> c)
{
auto z = c;
for (int t = 0; t <= 1000; ++t)
{
z = z * z + c;
if (std::norm(z) > 4)
return false;
}
return true;
}
You can save some memory allocations by reserving space for the output:
std::string ret = "";
ret.reserve((width+1) * height);
add a comment |
up vote
2
down vote
It's strange that you're using vectors instead of std::complex
to represent your complex numbers. I think you'll find that using the standard complex-number class will simplify your code.
It's much more efficient and accurate to square a number by simply multiplying rather than going via the much more general std::pow()
. Of course, with std::complex
, you don't need to do this squaring yourself, as the std::abs()
function is provided to do that for you.
It's also more efficient to compare the squared magnitude against the square of the bound, rather than to compute the square root of the magnitude (so use std::norm()
rather than std::abs()
).
These changes make for a much more natural version of the code (it's easier to see how it corresponds to the Mandelbrot algorithm):
#include <complex>
constexpr int height = 40, width = 80;
std::complex<double> coord_to_complex(double i, double j)
{
double real = (4*i) / (width - 1) - 2.0;
double imaginary = (2.2 * j) / (height - 1) - 1.1;
return {real, imaginary};
}
bool is_in_mandelbrot(const std::complex<double> c)
{
auto z = c;
for (int t = 0; t <= 1000; ++t)
{
z = z * z + c;
if (std::norm(z) > 4)
return false;
}
return true;
}
You can save some memory allocations by reserving space for the output:
std::string ret = "";
ret.reserve((width+1) * height);
add a comment |
up vote
2
down vote
up vote
2
down vote
It's strange that you're using vectors instead of std::complex
to represent your complex numbers. I think you'll find that using the standard complex-number class will simplify your code.
It's much more efficient and accurate to square a number by simply multiplying rather than going via the much more general std::pow()
. Of course, with std::complex
, you don't need to do this squaring yourself, as the std::abs()
function is provided to do that for you.
It's also more efficient to compare the squared magnitude against the square of the bound, rather than to compute the square root of the magnitude (so use std::norm()
rather than std::abs()
).
These changes make for a much more natural version of the code (it's easier to see how it corresponds to the Mandelbrot algorithm):
#include <complex>
constexpr int height = 40, width = 80;
std::complex<double> coord_to_complex(double i, double j)
{
double real = (4*i) / (width - 1) - 2.0;
double imaginary = (2.2 * j) / (height - 1) - 1.1;
return {real, imaginary};
}
bool is_in_mandelbrot(const std::complex<double> c)
{
auto z = c;
for (int t = 0; t <= 1000; ++t)
{
z = z * z + c;
if (std::norm(z) > 4)
return false;
}
return true;
}
You can save some memory allocations by reserving space for the output:
std::string ret = "";
ret.reserve((width+1) * height);
It's strange that you're using vectors instead of std::complex
to represent your complex numbers. I think you'll find that using the standard complex-number class will simplify your code.
It's much more efficient and accurate to square a number by simply multiplying rather than going via the much more general std::pow()
. Of course, with std::complex
, you don't need to do this squaring yourself, as the std::abs()
function is provided to do that for you.
It's also more efficient to compare the squared magnitude against the square of the bound, rather than to compute the square root of the magnitude (so use std::norm()
rather than std::abs()
).
These changes make for a much more natural version of the code (it's easier to see how it corresponds to the Mandelbrot algorithm):
#include <complex>
constexpr int height = 40, width = 80;
std::complex<double> coord_to_complex(double i, double j)
{
double real = (4*i) / (width - 1) - 2.0;
double imaginary = (2.2 * j) / (height - 1) - 1.1;
return {real, imaginary};
}
bool is_in_mandelbrot(const std::complex<double> c)
{
auto z = c;
for (int t = 0; t <= 1000; ++t)
{
z = z * z + c;
if (std::norm(z) > 4)
return false;
}
return true;
}
You can save some memory allocations by reserving space for the output:
std::string ret = "";
ret.reserve((width+1) * height);
answered Nov 14 at 9:12
Toby Speight
22k536108
22k536108
add a comment |
add a comment |
ChubakBidpaa is a new contributor. Be nice, and check out our Code of Conduct.
ChubakBidpaa is a new contributor. Be nice, and check out our Code of Conduct.
ChubakBidpaa is a new contributor. Be nice, and check out our Code of Conduct.
ChubakBidpaa is a new contributor. Be nice, and check out our Code of Conduct.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f207603%2fascii-mandelbrot%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown