Search code examples
bashlogiccomparison-operatorsmandelbrot

A Mandelbrot Comparison Logic issue that refuses to be resolved


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.


Solution

  • 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 ...