1*8462SApril.Chin@Sun.COM#!/usr/bin/ksh93 2*8462SApril.Chin@Sun.COM 3*8462SApril.Chin@Sun.COM# 4*8462SApril.Chin@Sun.COM# CDDL HEADER START 5*8462SApril.Chin@Sun.COM# 6*8462SApril.Chin@Sun.COM# The contents of this file are subject to the terms of the 7*8462SApril.Chin@Sun.COM# Common Development and Distribution License (the "License"). 8*8462SApril.Chin@Sun.COM# You may not use this file except in compliance with the License. 9*8462SApril.Chin@Sun.COM# 10*8462SApril.Chin@Sun.COM# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 11*8462SApril.Chin@Sun.COM# or http://www.opensolaris.org/os/licensing. 12*8462SApril.Chin@Sun.COM# See the License for the specific language governing permissions 13*8462SApril.Chin@Sun.COM# and limitations under the License. 14*8462SApril.Chin@Sun.COM# 15*8462SApril.Chin@Sun.COM# When distributing Covered Code, include this CDDL HEADER in each 16*8462SApril.Chin@Sun.COM# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 17*8462SApril.Chin@Sun.COM# If applicable, add the following below this CDDL HEADER, with the 18*8462SApril.Chin@Sun.COM# fields enclosed by brackets "[]" replaced with your own identifying 19*8462SApril.Chin@Sun.COM# information: Portions Copyright [yyyy] [name of copyright owner] 20*8462SApril.Chin@Sun.COM# 21*8462SApril.Chin@Sun.COM# CDDL HEADER END 22*8462SApril.Chin@Sun.COM# 23*8462SApril.Chin@Sun.COM 24*8462SApril.Chin@Sun.COM# 25*8462SApril.Chin@Sun.COM# Copyright 2008 Sun Microsystems, Inc. All rights reserved. 26*8462SApril.Chin@Sun.COM# Use is subject to license terms. 27*8462SApril.Chin@Sun.COM# 28*8462SApril.Chin@Sun.COM 29*8462SApril.Chin@Sun.COM# 30*8462SApril.Chin@Sun.COM# mandelbrotset1 - a simple mandelbrot set generation and 31*8462SApril.Chin@Sun.COM# parallel execution demo 32*8462SApril.Chin@Sun.COM# 33*8462SApril.Chin@Sun.COM 34*8462SApril.Chin@Sun.COM# Solaris needs /usr/xpg6/bin:/usr/xpg4/bin because the tools in /usr/bin are not POSIX-conformant 35*8462SApril.Chin@Sun.COMexport PATH=/usr/xpg6/bin:/usr/xpg4/bin:/bin:/usr/bin 36*8462SApril.Chin@Sun.COM 37*8462SApril.Chin@Sun.COM# Make sure all math stuff runs in the "C" locale to avoid problems 38*8462SApril.Chin@Sun.COM# with alternative # radix point representations (e.g. ',' instead of 39*8462SApril.Chin@Sun.COM# '.' in de_DE.*-locales). This needs to be set _before_ any 40*8462SApril.Chin@Sun.COM# floating-point constants are defined in this script). 41*8462SApril.Chin@Sun.COMif [[ "${LC_ALL}" != "" ]] ; then 42*8462SApril.Chin@Sun.COM export \ 43*8462SApril.Chin@Sun.COM LC_MONETARY="${LC_ALL}" \ 44*8462SApril.Chin@Sun.COM LC_MESSAGES="${LC_ALL}" \ 45*8462SApril.Chin@Sun.COM LC_COLLATE="${LC_ALL}" \ 46*8462SApril.Chin@Sun.COM LC_CTYPE="${LC_ALL}" 47*8462SApril.Chin@Sun.COM unset LC_ALL 48*8462SApril.Chin@Sun.COMfi 49*8462SApril.Chin@Sun.COMexport LC_NUMERIC=C 50*8462SApril.Chin@Sun.COM 51*8462SApril.Chin@Sun.COMfunction printmsg 52*8462SApril.Chin@Sun.COM{ 53*8462SApril.Chin@Sun.COM print -u2 "$*" 54*8462SApril.Chin@Sun.COM} 55*8462SApril.Chin@Sun.COM 56*8462SApril.Chin@Sun.COMfunction fatal_error 57*8462SApril.Chin@Sun.COM{ 58*8462SApril.Chin@Sun.COM print -u2 "${progname}: $*" 59*8462SApril.Chin@Sun.COM exit 1 60*8462SApril.Chin@Sun.COM} 61*8462SApril.Chin@Sun.COM 62*8462SApril.Chin@Sun.COM# Get terminal size and put values into a compound variable with the integer 63*8462SApril.Chin@Sun.COM# members "columns" and "lines" 64*8462SApril.Chin@Sun.COMfunction get_term_size 65*8462SApril.Chin@Sun.COM{ 66*8462SApril.Chin@Sun.COM nameref rect=$1 67*8462SApril.Chin@Sun.COM 68*8462SApril.Chin@Sun.COM rect.columns=${ tput cols ; } || return 1 69*8462SApril.Chin@Sun.COM rect.lines=${ tput lines ; } || return 1 70*8462SApril.Chin@Sun.COM 71*8462SApril.Chin@Sun.COM return 0 72*8462SApril.Chin@Sun.COM} 73*8462SApril.Chin@Sun.COM 74*8462SApril.Chin@Sun.COMfunction print_color 75*8462SApril.Chin@Sun.COM{ 76*8462SApril.Chin@Sun.COM print -r -n -- "${symbollist:${1}:1}" 77*8462SApril.Chin@Sun.COM return 0 78*8462SApril.Chin@Sun.COM} 79*8462SApril.Chin@Sun.COM 80*8462SApril.Chin@Sun.COMfunction mandelbrot 81*8462SApril.Chin@Sun.COM{ 82*8462SApril.Chin@Sun.COM nameref result=$1 83*8462SApril.Chin@Sun.COM float x=$2 84*8462SApril.Chin@Sun.COM float y=$3 85*8462SApril.Chin@Sun.COM float xx 86*8462SApril.Chin@Sun.COM float yy 87*8462SApril.Chin@Sun.COM float x1=$4 88*8462SApril.Chin@Sun.COM float y1=$5 89*8462SApril.Chin@Sun.COM integer iteration=$6 90*8462SApril.Chin@Sun.COM integer max_iteration=$7 91*8462SApril.Chin@Sun.COM float mag 92*8462SApril.Chin@Sun.COM 93*8462SApril.Chin@Sun.COM for (( mag=0 ; mag < max_mag && iteration < max_iteration ; iteration++ )) ; do 94*8462SApril.Chin@Sun.COM (( 95*8462SApril.Chin@Sun.COM xx=x*x , 96*8462SApril.Chin@Sun.COM yy=y*y , 97*8462SApril.Chin@Sun.COM mag=xx+yy , 98*8462SApril.Chin@Sun.COM y=x*y*2+y1 , 99*8462SApril.Chin@Sun.COM x=xx-yy+x1 100*8462SApril.Chin@Sun.COM )) 101*8462SApril.Chin@Sun.COM done 102*8462SApril.Chin@Sun.COM 103*8462SApril.Chin@Sun.COM (( result=iteration )) 104*8462SApril.Chin@Sun.COM 105*8462SApril.Chin@Sun.COM return 0 106*8462SApril.Chin@Sun.COM} 107*8462SApril.Chin@Sun.COM 108*8462SApril.Chin@Sun.COM# build mandelbrot image serially 109*8462SApril.Chin@Sun.COMfunction loop_serial 110*8462SApril.Chin@Sun.COM{ 111*8462SApril.Chin@Sun.COM integer value 112*8462SApril.Chin@Sun.COM 113*8462SApril.Chin@Sun.COM for (( y=y_min ; y < y_max ; y+=stepwidth )) ; do 114*8462SApril.Chin@Sun.COM for (( x=x_min ; x < x_max ; x+=stepwidth )) ; do 115*8462SApril.Chin@Sun.COM mandelbrot value ${x} ${y} ${x} ${y} 1 ${symbollistlen} 116*8462SApril.Chin@Sun.COM print_color ${value} 117*8462SApril.Chin@Sun.COM done 118*8462SApril.Chin@Sun.COM 119*8462SApril.Chin@Sun.COM print 120*8462SApril.Chin@Sun.COM done 121*8462SApril.Chin@Sun.COM 122*8462SApril.Chin@Sun.COM return 0 123*8462SApril.Chin@Sun.COM} 124*8462SApril.Chin@Sun.COM 125*8462SApril.Chin@Sun.COM# build mandelbrot image using parallel worker jobs 126*8462SApril.Chin@Sun.COMfunction loop_parallel 127*8462SApril.Chin@Sun.COM{ 128*8462SApril.Chin@Sun.COM integer numjobs=0 129*8462SApril.Chin@Sun.COM # the following calculation suffers from rounding errors 130*8462SApril.Chin@Sun.COM integer lines_per_job=$(( ((m_height+(numcpus-1)) / numcpus) )) 131*8462SApril.Chin@Sun.COM 132*8462SApril.Chin@Sun.COM printmsg $"# lines_per_job=${lines_per_job}" 133*8462SApril.Chin@Sun.COM printmsg $"# numcpus=${numcpus}" 134*8462SApril.Chin@Sun.COM 135*8462SApril.Chin@Sun.COM # "renice" worker jobs 136*8462SApril.Chin@Sun.COM set -o bgnice 137*8462SApril.Chin@Sun.COM 138*8462SApril.Chin@Sun.COM if [[ "${TMPDIR}" == "" ]] ; then 139*8462SApril.Chin@Sun.COM TMPDIR="/tmp" 140*8462SApril.Chin@Sun.COM fi 141*8462SApril.Chin@Sun.COM 142*8462SApril.Chin@Sun.COM # try to generate a job identifer prefix which is unique across multiple hosts 143*8462SApril.Chin@Sun.COM jobident="job_host_$(uname -n)pid_$$_ppid${PPID}" 144*8462SApril.Chin@Sun.COM 145*8462SApril.Chin@Sun.COM printmsg $"## prepare..." 146*8462SApril.Chin@Sun.COM for (( y=y_min ; y < y_max ; y+=(stepwidth*lines_per_job) )) ; do 147*8462SApril.Chin@Sun.COM rm -f "${TMPDIR}/mandelbrot_${jobident}_child_$y.joboutput" 148*8462SApril.Chin@Sun.COM 149*8462SApril.Chin@Sun.COM (( numjobs++ )) 150*8462SApril.Chin@Sun.COM done 151*8462SApril.Chin@Sun.COM 152*8462SApril.Chin@Sun.COM printmsg $"## running ${numjobs} children..." 153*8462SApril.Chin@Sun.COM for (( y=y_min ; y < y_max ; y+=(stepwidth*lines_per_job) )) ; do 154*8462SApril.Chin@Sun.COM ( 155*8462SApril.Chin@Sun.COM integer value 156*8462SApril.Chin@Sun.COM 157*8462SApril.Chin@Sun.COM for (( ; y < y_max && lines_per_job-- > 0 ; y+=stepwidth )) ; do 158*8462SApril.Chin@Sun.COM for (( x=x_min ; x < x_max ; x+=stepwidth )) ; do 159*8462SApril.Chin@Sun.COM mandelbrot value ${x} ${y} ${x} ${y} 1 ${symbollistlen} 160*8462SApril.Chin@Sun.COM print_color ${value} 161*8462SApril.Chin@Sun.COM done 162*8462SApril.Chin@Sun.COM 163*8462SApril.Chin@Sun.COM print 164*8462SApril.Chin@Sun.COM done >"${TMPDIR}/mandelbrot_${jobident}_child_$y.joboutput" 165*8462SApril.Chin@Sun.COM ) & 166*8462SApril.Chin@Sun.COM done 167*8462SApril.Chin@Sun.COM 168*8462SApril.Chin@Sun.COM printmsg $"## waiting for ${numjobs} children..." 169*8462SApril.Chin@Sun.COM wait 170*8462SApril.Chin@Sun.COM 171*8462SApril.Chin@Sun.COM printmsg $"## output:" 172*8462SApril.Chin@Sun.COM for (( y=y_min ; y < y_max ; y+=(stepwidth*lines_per_job) )) ; do 173*8462SApril.Chin@Sun.COM print -- "$( < "${TMPDIR}/mandelbrot_${jobident}_child_$y.joboutput")" 174*8462SApril.Chin@Sun.COM rm "${TMPDIR}/mandelbrot_${jobident}_child_$y.joboutput" 175*8462SApril.Chin@Sun.COM done 176*8462SApril.Chin@Sun.COM 177*8462SApril.Chin@Sun.COM return 0 178*8462SApril.Chin@Sun.COM} 179*8462SApril.Chin@Sun.COM 180*8462SApril.Chin@Sun.COMfunction usage 181*8462SApril.Chin@Sun.COM{ 182*8462SApril.Chin@Sun.COM OPTIND=0 183*8462SApril.Chin@Sun.COM getopts -a "${progname}" "${mandelbrotset1_usage}" OPT '-?' 184*8462SApril.Chin@Sun.COM exit 2 185*8462SApril.Chin@Sun.COM} 186*8462SApril.Chin@Sun.COM 187*8462SApril.Chin@Sun.COM# main 188*8462SApril.Chin@Sun.COMbuiltin basename 189*8462SApril.Chin@Sun.COMbuiltin cat 190*8462SApril.Chin@Sun.COMbuiltin rm 191*8462SApril.Chin@Sun.COMbuiltin uname # loop_parallel needs the ksh93 builtin version to generate unique job file names 192*8462SApril.Chin@Sun.COM 193*8462SApril.Chin@Sun.COMtypeset progname="${ basename "${0}" ; }" 194*8462SApril.Chin@Sun.COM 195*8462SApril.Chin@Sun.COMfloat x_max 196*8462SApril.Chin@Sun.COMfloat x_min 197*8462SApril.Chin@Sun.COMfloat y_max 198*8462SApril.Chin@Sun.COMfloat y_min 199*8462SApril.Chin@Sun.COMfloat m_width 200*8462SApril.Chin@Sun.COMfloat m_height 201*8462SApril.Chin@Sun.COMfloat max_mag 202*8462SApril.Chin@Sun.COMfloat stepwidth 203*8462SApril.Chin@Sun.COMinteger numcpus 204*8462SApril.Chin@Sun.COM 205*8462SApril.Chin@Sun.COM# terminal size rect 206*8462SApril.Chin@Sun.COMtypeset -C termsize=( 207*8462SApril.Chin@Sun.COM integer columns=-1 208*8462SApril.Chin@Sun.COM integer lines=-1 209*8462SApril.Chin@Sun.COM) 210*8462SApril.Chin@Sun.COM 211*8462SApril.Chin@Sun.COMget_term_size termsize || fatal_error $"Could not get terminal size." 212*8462SApril.Chin@Sun.COM 213*8462SApril.Chin@Sun.COMtypeset symbollist=' .:0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ%#' 214*8462SApril.Chin@Sun.COMtypeset symbollistlen=$(( ${#symbollist} - 1)) 215*8462SApril.Chin@Sun.COMtypeset mode="parallel" 216*8462SApril.Chin@Sun.COM 217*8462SApril.Chin@Sun.COMmax_mag=400 218*8462SApril.Chin@Sun.COMstepwidth=0.1 219*8462SApril.Chin@Sun.COMnumcpus=16 220*8462SApril.Chin@Sun.COM 221*8462SApril.Chin@Sun.COM(( m_width=termsize.columns-1 , m_height=termsize.lines-2 )) 222*8462SApril.Chin@Sun.COM 223*8462SApril.Chin@Sun.COMtypeset -r mandelbrotset1_usage=$'+ 224*8462SApril.Chin@Sun.COM[-?\n@(#)\$Id: mandelbrotset1 (Roland Mainz) 2008-11-04 \$\n] 225*8462SApril.Chin@Sun.COM[-author?Roland Mainz <roland.mainz@nrubsig.org>] 226*8462SApril.Chin@Sun.COM[+NAME?mandelbrotset1 - generate mandelbrot set fractals with ksh93] 227*8462SApril.Chin@Sun.COM[+DESCRIPTION?\bmandelbrotset1\b mandelbrot set fractal generator 228*8462SApril.Chin@Sun.COM which runs either in serial or parallel mode (using multiple worker jobs).] 229*8462SApril.Chin@Sun.COM[w:width?Width of fractal.]:[width] 230*8462SApril.Chin@Sun.COM[h:height?Height of fractal.]:[height] 231*8462SApril.Chin@Sun.COM[s:symbols?Symbols to build the fractal from.]:[symbolstring] 232*8462SApril.Chin@Sun.COM[m:mag?Magnification level.]:[magnificationlevel] 233*8462SApril.Chin@Sun.COM[p:stepwidth?Width per step.]:[widthperstep] 234*8462SApril.Chin@Sun.COM[S:serial?Run in serial mode.] 235*8462SApril.Chin@Sun.COM[P:parallel?Run in parallel mode.] 236*8462SApril.Chin@Sun.COM[M:mode?Execution mode.]:[mode] 237*8462SApril.Chin@Sun.COM[C:numcpus?Number of processors used for parallel execution.]:[numcpus] 238*8462SApril.Chin@Sun.COM[+SEE ALSO?\bjuliaset1\b(1), \bksh93\b(1)] 239*8462SApril.Chin@Sun.COM' 240*8462SApril.Chin@Sun.COM 241*8462SApril.Chin@Sun.COMwhile getopts -a "${progname}" "${mandelbrotset1_usage}" OPT ; do 242*8462SApril.Chin@Sun.COM# printmsg "## OPT=|${OPT}|, OPTARG=|${OPTARG}|" 243*8462SApril.Chin@Sun.COM case ${OPT} in 244*8462SApril.Chin@Sun.COM w) m_width="${OPTARG}" ;; 245*8462SApril.Chin@Sun.COM h) m_height="${OPTARG}" ;; 246*8462SApril.Chin@Sun.COM s) symbollist="${OPTARG}" ;; 247*8462SApril.Chin@Sun.COM m) max_mag="${OPTARG}" ;; 248*8462SApril.Chin@Sun.COM p) stepwidth="${OPTARG}" ;; 249*8462SApril.Chin@Sun.COM S) mode="serial" ;; 250*8462SApril.Chin@Sun.COM P) mode="parallel" ;; 251*8462SApril.Chin@Sun.COM M) mode="${OPTARG}" ;; 252*8462SApril.Chin@Sun.COM C) numcpus="${OPTARG}" ;; 253*8462SApril.Chin@Sun.COM *) usage ;; 254*8462SApril.Chin@Sun.COM esac 255*8462SApril.Chin@Sun.COMdone 256*8462SApril.Chin@Sun.COMshift $((OPTIND-1)) 257*8462SApril.Chin@Sun.COM 258*8462SApril.Chin@Sun.COMprintmsg "# width=${m_width}" 259*8462SApril.Chin@Sun.COMprintmsg "# height=${m_height}" 260*8462SApril.Chin@Sun.COMprintmsg "# max_mag=${max_mag}" 261*8462SApril.Chin@Sun.COMprintmsg "# stepwidth=${stepwidth}" 262*8462SApril.Chin@Sun.COMprintmsg "# symbollist='${symbollist}'" 263*8462SApril.Chin@Sun.COMprintmsg "# mode=${mode}" 264*8462SApril.Chin@Sun.COM 265*8462SApril.Chin@Sun.COM(( symbollistlen=${#symbollist}-1 )) 266*8462SApril.Chin@Sun.COM 267*8462SApril.Chin@Sun.COM(( 268*8462SApril.Chin@Sun.COM x_max=m_width*stepwidth/2. , 269*8462SApril.Chin@Sun.COM x_min=-x_max , 270*8462SApril.Chin@Sun.COM y_max=m_height*stepwidth/2. , 271*8462SApril.Chin@Sun.COM y_min=-y_max 272*8462SApril.Chin@Sun.COM)) 273*8462SApril.Chin@Sun.COM 274*8462SApril.Chin@Sun.COMcase "${mode}" in 275*8462SApril.Chin@Sun.COM parallel) loop_parallel ; exit $? ;; 276*8462SApril.Chin@Sun.COM serial) loop_serial ; exit $? ;; 277*8462SApril.Chin@Sun.COM *) fatal_error $"Unknown mode \"${mode}\"." ;; 278*8462SApril.Chin@Sun.COMesac 279*8462SApril.Chin@Sun.COM 280*8462SApril.Chin@Sun.COMfatal_error "not reached." 281*8462SApril.Chin@Sun.COM# EOF. 282