1

I want to see the implementation of the Mandelbrot Set working (script provided by BruXy.regnet.cz), but one line of code is giving me problems to resolve.

In the While-loop, a logic AND comparison is made between two tests;

while [ $B -le 32 -a $V -eq 0 ]

produces unary operator expected

Other variations:

while [[ $B -le 32 ]] && [[ $V -eq 0 ]]

produces (standard_in) 1: syntax error;

[ $B -le 32 ] -a [ $V -eq 0 ]

produces [: too many arguments;

[ "$B" -le 32 -a "$V" -eq 0 ]

produces integer expression expected

If you attempt to run this script, I have commented-out the offending line of code.

  4 #!/usr/bin/bash
  5 S0=S
  6 S1=H
  7 S2=E
  8 S3=L
  9 S4=L
 10 e=echo
 11 b=bc
 12 I=-1
 13 t=~/bash-scripts/temp/m$$
 14 for x in {1..13};do
 15    R=-2
 16    for y in {1..80}; do                    
 17       B=0
 18       r=0
 19       i=0
 20       V=0
 21       #while [[ "$B" -le 32 ]] && [[ "$V" -eq 0 ]]; do
 22          read rt i V<<<`$b<<<"r2=$r^2;i2=$i^2;r2-i2+($R);2*($r*$i)+($I);(r2+i2)>4"`
 23          r=$rt
 24          : $((B+=1))
 25       done
 26       if [ $B -ge 32 ]; then
27          $e -n " "
 28       else
 29          $e -en "\E[01;$(((B*4)/15+30))""m"
 30          eval $e -en "\$E\$S$((C++%5))"
 31       fi
 32       R=`$b<<<"$R+0.03125"`
 33    done
 34    $e -e "\E[m\E(\r"
 35    I=`$b<<<"$I+0.08333"`
 36 done|tee $t
 37 head -n 12 $t|tac
 38
 39 #(c)BruXy

What is the problem?

I do not know how to resolve this issue, though I've been on it for quite some time.

Den
  • 173
  • 11
  • If you like Mandelbrot in Bash/Shell: see: https://stackoverflow.com/a/63749612/1765658 or my improved version: https://gist.github.com/leagris/59e1b7e72462024b278652696f375e71 – Léa Gris Jan 05 '23 at 09:32
  • @LéaGris: Thanks for sharing. It's fascinating what can be acheived with BASH scripting. My intent is to improve my understanding of BASH scripting, so I challenged myself with the Mandelbrot Set (way too big a challenge - I am not a mathematician). I wish I could ask you pertinent, intelligent questions about how you went about scripting the Mandelbrot Set... – Den Jan 05 '23 at 10:56
  • 1
    I did not write the Mandelbrot math part. Though getting inspiration from @FHauri speed improvements; I challenged myself to improve it even more and make it POSIX-shell compatible, add colour gradients and semi-graphic console square pixels. There are still possible improvements if you like challenges. Head to the Mandelbrot algorithm itself. The one used here is the slowest. – Léa Gris Jan 05 '23 at 11:27
  • 1
    @LéaGris have you looked at a degree of parallel processing? fwiw, I modified your code to split processing vertically, first 4-ways, then 8-ways, with each stripe running a single `bc` process (w/ separate stdin/stdout); all output sent to files then `paste outfile{1..n}`; running cygwin in a virtual Win10 env so not lightening fast; w/ hardcoded 80x24 (w/ 12 virtual processors) ... as is: 1m26s ... 4-way/parallel: 0m28s ... 8-way/parallel: 0m14s; a 2nd `bc` may help; more processors would support horizontal splitting; anyhoo ... nice work on the colors/gradients! – markp-fuso Jan 06 '23 at 01:20
  • @markp-fuso Did you make a fork or something you may share with the community? – Léa Gris Jan 06 '23 at 10:40

1 Answers1

2

Run the following at the command line:

$ r=0; i=1; R=-2; I=-1
$ bc<<<"r2=$r^2;i2=$i^2;r2-i2+($R);2*($r*$i)+($I);(r2+i2)>4" 
-3
-1
0

Notice the output is spread across 3 lines.

Where a problem occurs is with this command:

read rt i V <<< `bc<<< ...`

Which is expecting to read the 3 values from a single line of input with the net result being that i and V are left empty which in turn wreaks havoc with follow-on code, eg, [[ "$V" -eq 0 ]] evaluates as [[ '' -eq 0 ]] which generates an error ... and on and on ...

A few quick fixes:

Tell bc to print all 3 values on a single line separated by spaces:

$ bc<<<"r2=$r^2;i2=$i^2;print r2-i2+($R),\" \",2*($r*$i)+($I),\" \",(r2+i2)>4"
-3 -1 0

# so your code becomes

read rt i V <<< $( $b<<<"r2=$r^2;i2=$i^2;print r2-i2+($R),\" \",2*($r*$i)+($I),\" \",(r2+i2)>4" )

Use tr to replace newlines (\n) with spaces:

$ bc<<<"r2=$r^2;i2=$i^2;r2-i2+($R);2*($r*$i)+($I);(r2+i2)>4" | tr '\n' ' '
-3 -1 0

# so your code becomes:

read rt i V <<< $( $b<<<"r2=$r^2;i2=$i^2;r2-i2+($R);2*($r*$i)+($I);(r2+i2)>4" | tr '\n' ' ' )

Tell read to read across the 3 lines:

read -d ' ' rt i V <<< $( $b<<<"r2=$r^2;i2=$i^2;r2-i2+($R);2*($r*$i)+($I);(r2+i2)>4" )

NOTES:

  • this (plus uncommenting the while) should get you past the current batch of issues
  • I'll let you determine if there are any follow-on issues
  • in general, consider enabling debug mode (add set -xv before the first for; set +xv to disable) and review the output to determine if variables are getting set as expected; with the current code you'll see in the first pass through the loop that i and V are blanked out ... which should show follow-on tests/commands missing some values ... which in turn causes an assortment of issues/errors, etc; from there it's just a case of debugging the line that populates i and V ...
markp-fuso
  • 28,790
  • 4
  • 16
  • 36
  • Thank you for your help. I had used ```set -x``` to debug the code, which is why I found the general area of the problem; but my mathematical and syntactical knowledge is evidently limited to make further progress in finding and remedying the issue. – Den Jan 05 '23 at 05:25
  • How did you come to the conclusion that the ```read``` output was spread over three lines? – Den Jan 05 '23 at 05:27
  • Thank you, also, for the ```set -x[v]``` flag; very useful to know. I'll continue running the script and see if anything else needs attention. – Den Jan 05 '23 at 05:29
  • 1
    @Den reviewing the debug (`set -x`) output the first thing that jumped out at me was the test `[[ "" -eq 0 ]]` which indicates `V` was blank; there are only 2 statements that populate V ... `V=0` (not a problem) and read `rt i V <<< ...` (obviously the problem); from here it was a case of reproducing the `bc` command on the command line and confirming the `bc` output covers 3 lines; then it was just a question of coming up with some ideas on how to get those 3 values into the 3 variables – markp-fuso Jan 05 '23 at 16:38
  • Thanks for elaborating. I'm not that familiar with ```bc```, nor the workings of the maths in the script, so I have some distance to go in comprehension. – Den Jan 05 '23 at 18:15
  • @Den while I'm familiar with `bc` I don't actually use it that much except for some very basic (usually real/float) math; after reviewing the man pages and playing with the `print` statement I came up with a 3rd option ... answer has been updated – markp-fuso Jan 05 '23 at 18:27
  • markp-fuso: I need a manual to understand the manual. You got me. Great that you found another way of acheiving the same outcome, which proves that there are many ways to do one thing in BASH. It works as the script should (though, the issue with the reversed colours remains). – Den Jan 06 '23 at 06:51