1*b4dd7d09SAndy Fiddaman#!/usr/bin/ksh93 2*b4dd7d09SAndy Fiddaman 3*b4dd7d09SAndy Fiddaman# 4*b4dd7d09SAndy Fiddaman# CDDL HEADER START 5*b4dd7d09SAndy Fiddaman# 6*b4dd7d09SAndy Fiddaman# The contents of this file are subject to the terms of the 7*b4dd7d09SAndy Fiddaman# Common Development and Distribution License (the "License"). 8*b4dd7d09SAndy Fiddaman# You may not use this file except in compliance with the License. 9*b4dd7d09SAndy Fiddaman# 10*b4dd7d09SAndy Fiddaman# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 11*b4dd7d09SAndy Fiddaman# or http://www.opensolaris.org/os/licensing. 12*b4dd7d09SAndy Fiddaman# See the License for the specific language governing permissions 13*b4dd7d09SAndy Fiddaman# and limitations under the License. 14*b4dd7d09SAndy Fiddaman# 15*b4dd7d09SAndy Fiddaman# When distributing Covered Code, include this CDDL HEADER in each 16*b4dd7d09SAndy Fiddaman# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 17*b4dd7d09SAndy Fiddaman# If applicable, add the following below this CDDL HEADER, with the 18*b4dd7d09SAndy Fiddaman# fields enclosed by brackets "[]" replaced with your own identifying 19*b4dd7d09SAndy Fiddaman# information: Portions Copyright [yyyy] [name of copyright owner] 20*b4dd7d09SAndy Fiddaman# 21*b4dd7d09SAndy Fiddaman# CDDL HEADER END 22*b4dd7d09SAndy Fiddaman# 23*b4dd7d09SAndy Fiddaman 24*b4dd7d09SAndy Fiddaman# 25*b4dd7d09SAndy Fiddaman# Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 26*b4dd7d09SAndy Fiddaman# 27*b4dd7d09SAndy Fiddaman 28*b4dd7d09SAndy Fiddaman# 29*b4dd7d09SAndy Fiddaman# numtree1 - basic compound variable tree demo+benchmark 30*b4dd7d09SAndy Fiddaman# 31*b4dd7d09SAndy Fiddaman 32*b4dd7d09SAndy Fiddaman# Solaris needs /usr/xpg6/bin:/usr/xpg4/bin because the tools in /usr/bin are not POSIX-conformant 33*b4dd7d09SAndy Fiddamanexport PATH=/usr/xpg6/bin:/usr/xpg4/bin:/bin:/usr/bin 34*b4dd7d09SAndy Fiddaman 35*b4dd7d09SAndy Fiddaman# Make sure all math stuff runs in the "C" locale to avoid problems 36*b4dd7d09SAndy Fiddaman# with alternative # radix point representations (e.g. ',' instead of 37*b4dd7d09SAndy Fiddaman# '.' in de_DE.*-locales). This needs to be set _before_ any 38*b4dd7d09SAndy Fiddaman# floating-point constants are defined in this script). 39*b4dd7d09SAndy Fiddamanif [[ "${LC_ALL}" != "" ]] ; then 40*b4dd7d09SAndy Fiddaman export \ 41*b4dd7d09SAndy Fiddaman LC_MONETARY="${LC_ALL}" \ 42*b4dd7d09SAndy Fiddaman LC_MESSAGES="${LC_ALL}" \ 43*b4dd7d09SAndy Fiddaman LC_COLLATE="${LC_ALL}" \ 44*b4dd7d09SAndy Fiddaman LC_CTYPE="${LC_ALL}" 45*b4dd7d09SAndy Fiddaman unset LC_ALL 46*b4dd7d09SAndy Fiddamanfi 47*b4dd7d09SAndy Fiddamanexport LC_NUMERIC=C 48*b4dd7d09SAndy Fiddaman 49*b4dd7d09SAndy Fiddamanfunction fatal_error 50*b4dd7d09SAndy Fiddaman{ 51*b4dd7d09SAndy Fiddaman print -u2 "${progname}: $*" 52*b4dd7d09SAndy Fiddaman exit 1 53*b4dd7d09SAndy Fiddaman} 54*b4dd7d09SAndy Fiddaman 55*b4dd7d09SAndy Fiddamanfunction add_number_to_tree 56*b4dd7d09SAndy Fiddaman{ 57*b4dd7d09SAndy Fiddaman typeset treename=$1 58*b4dd7d09SAndy Fiddaman integer num=$2 59*b4dd7d09SAndy Fiddaman integer i 60*b4dd7d09SAndy Fiddaman typeset nodepath # full name of compound variable 61*b4dd7d09SAndy Fiddaman integer -a pe # path elements 62*b4dd7d09SAndy Fiddaman integer len 63*b4dd7d09SAndy Fiddaman typeset revnums="$(rev <<<"${num}")" 64*b4dd7d09SAndy Fiddaman 65*b4dd7d09SAndy Fiddaman # first built an array containing the names of each path element 66*b4dd7d09SAndy Fiddaman # (e.g. "135" results in an array containing "( 1 3 5 )") 67*b4dd7d09SAndy Fiddaman # 10#<number> is used to prevent leading zeros being interpreted 68*b4dd7d09SAndy Fiddaman # as octals 69*b4dd7d09SAndy Fiddaman for (( len=${#revnums} , i=$( printf "10#%s\n" "${revnums}" ) ; len > 0 ; len--, i=i/10 )) ; do 70*b4dd7d09SAndy Fiddaman pe+=( $((i % 10)) ) 71*b4dd7d09SAndy Fiddaman done 72*b4dd7d09SAndy Fiddaman 73*b4dd7d09SAndy Fiddaman # walk path described via the "pe" array and build nodes if 74*b4dd7d09SAndy Fiddaman # there aren't any nodes yet 75*b4dd7d09SAndy Fiddaman nodepath="${treename}" 76*b4dd7d09SAndy Fiddaman for (( i=0 ; i < ${#pe[@]} ; i++ )) ; do 77*b4dd7d09SAndy Fiddaman nameref x="${nodepath}" 78*b4dd7d09SAndy Fiddaman 79*b4dd7d09SAndy Fiddaman # [[ -v ]] does not work for arrays because [[ -v ar ]] 80*b4dd7d09SAndy Fiddaman # is equal to [[ -v ar[0] ]]. In this case we can 81*b4dd7d09SAndy Fiddaman # use the output of typeset +p x.nodes 82*b4dd7d09SAndy Fiddaman [[ "${ typeset +p x.nodes ;}" == "" ]] && compound -a x.nodes 83*b4dd7d09SAndy Fiddaman 84*b4dd7d09SAndy Fiddaman nodepath+=".nodes[${pe[i]}]" 85*b4dd7d09SAndy Fiddaman done 86*b4dd7d09SAndy Fiddaman 87*b4dd7d09SAndy Fiddaman # insert element (leaf) 88*b4dd7d09SAndy Fiddaman nameref node="${nodepath}" 89*b4dd7d09SAndy Fiddaman [[ "${ typeset +p node.elements ;}" == "" ]] && integer -a node.elements 90*b4dd7d09SAndy Fiddaman node.elements+=( ${num} ) 91*b4dd7d09SAndy Fiddaman 92*b4dd7d09SAndy Fiddaman # DEBUG only 93*b4dd7d09SAndy Fiddaman [[ "${!node.elements[*]}" != "" ]] || fatal_error "assertion $LINENO FAILED" 94*b4dd7d09SAndy Fiddaman [[ "${ typeset +p node.elements ;}" == *-a* ]] || fatal_error "assertion $LINENO FAILED" 95*b4dd7d09SAndy Fiddaman [[ "${ typeset +p node.elements ;}" == *-i* ]] || fatal_error "assertion $LINENO FAILED" 96*b4dd7d09SAndy Fiddaman [[ -v node ]] || fatal_error "assertion $LINENO FAILED" 97*b4dd7d09SAndy Fiddaman [[ -R node ]] || fatal_error "assertion $LINENO FAILED" 98*b4dd7d09SAndy Fiddaman [[ "${ typeset +p ${!node} ;}" == *-C* ]] || fatal_error "assertion $LINENO FAILED" 99*b4dd7d09SAndy Fiddaman [[ "${!x.nodes[*]}" != "" ]] || fatal_error "assertion $LINENO FAILED" 100*b4dd7d09SAndy Fiddaman [[ "${ typeset +p x.nodes ;}" == *-a* ]] || fatal_error "assertion $LINENO FAILED" 101*b4dd7d09SAndy Fiddaman [[ "${ typeset +p x.nodes ;}" == *-C* ]] || fatal_error "assertion $LINENO FAILED" 102*b4dd7d09SAndy Fiddaman 103*b4dd7d09SAndy Fiddaman return 0 104*b4dd7d09SAndy Fiddaman} 105*b4dd7d09SAndy Fiddaman 106*b4dd7d09SAndy Fiddaman 107*b4dd7d09SAndy Fiddaman# floating-point version of "seq" 108*b4dd7d09SAndy Fiddamanfunction floatseq 109*b4dd7d09SAndy Fiddaman{ 110*b4dd7d09SAndy Fiddaman float i 111*b4dd7d09SAndy Fiddaman float arg1=$1 112*b4dd7d09SAndy Fiddaman float arg2=$2 113*b4dd7d09SAndy Fiddaman float arg3=$3 114*b4dd7d09SAndy Fiddaman 115*b4dd7d09SAndy Fiddaman case $# in 116*b4dd7d09SAndy Fiddaman 1) 117*b4dd7d09SAndy Fiddaman for (( i=1. ; i <= arg1 ; i=i+1. )) ; do 118*b4dd7d09SAndy Fiddaman printf "%a\n" i 119*b4dd7d09SAndy Fiddaman done 120*b4dd7d09SAndy Fiddaman ;; 121*b4dd7d09SAndy Fiddaman 2) 122*b4dd7d09SAndy Fiddaman for (( i=arg1 ; i <= arg2 ; i=i+1. )) ; do 123*b4dd7d09SAndy Fiddaman printf "%a\n" i 124*b4dd7d09SAndy Fiddaman done 125*b4dd7d09SAndy Fiddaman ;; 126*b4dd7d09SAndy Fiddaman 3) 127*b4dd7d09SAndy Fiddaman for (( i=arg1 ; i <= arg3 ; i+=arg2 )) ; do 128*b4dd7d09SAndy Fiddaman printf "%a\n" i 129*b4dd7d09SAndy Fiddaman done 130*b4dd7d09SAndy Fiddaman ;; 131*b4dd7d09SAndy Fiddaman *) 132*b4dd7d09SAndy Fiddaman print -u2 -f "%s: Illegal number of arguments %d\n" "$0" $# 133*b4dd7d09SAndy Fiddaman return 1 134*b4dd7d09SAndy Fiddaman ;; 135*b4dd7d09SAndy Fiddaman esac 136*b4dd7d09SAndy Fiddaman 137*b4dd7d09SAndy Fiddaman return 0 138*b4dd7d09SAndy Fiddaman} 139*b4dd7d09SAndy Fiddaman 140*b4dd7d09SAndy Fiddaman 141*b4dd7d09SAndy Fiddamanfunction usage 142*b4dd7d09SAndy Fiddaman{ 143*b4dd7d09SAndy Fiddaman OPTIND=0 144*b4dd7d09SAndy Fiddaman getopts -a "${progname}" "${numtree1_usage}" OPT '-?' 145*b4dd7d09SAndy Fiddaman exit 2 146*b4dd7d09SAndy Fiddaman} 147*b4dd7d09SAndy Fiddaman 148*b4dd7d09SAndy Fiddaman# main 149*b4dd7d09SAndy Fiddamanbuiltin basename 150*b4dd7d09SAndy Fiddamanbuiltin rev 151*b4dd7d09SAndy Fiddaman 152*b4dd7d09SAndy Fiddamanset -o noglob 153*b4dd7d09SAndy Fiddamanset -o errexit 154*b4dd7d09SAndy Fiddamanset -o nounset 155*b4dd7d09SAndy Fiddaman 156*b4dd7d09SAndy Fiddamancompound base 157*b4dd7d09SAndy Fiddaman 158*b4dd7d09SAndy Fiddamancompound bench=( 159*b4dd7d09SAndy Fiddaman float start 160*b4dd7d09SAndy Fiddaman float stop 161*b4dd7d09SAndy Fiddaman) 162*b4dd7d09SAndy Fiddaman 163*b4dd7d09SAndy Fiddamaninteger i 164*b4dd7d09SAndy Fiddaman 165*b4dd7d09SAndy Fiddamantypeset progname="${ basename "${0}" ; }" 166*b4dd7d09SAndy Fiddaman 167*b4dd7d09SAndy Fiddamantypeset -r numtree1_usage=$'+ 168*b4dd7d09SAndy Fiddaman[-?\n@(#)\$Id: numtree1 (Roland Mainz) 2010-03-27 \$\n] 169*b4dd7d09SAndy Fiddaman[-author?Roland Mainz <roland.mainz@nrubsig.org>] 170*b4dd7d09SAndy Fiddaman[+NAME?numtree1 - generate sorted variable tree containing numbers] 171*b4dd7d09SAndy Fiddaman[+DESCRIPTION?\bnumtree1\b is a simple variable tree generator 172*b4dd7d09SAndy Fiddaman sorts a given set of numbers into a ksh compound variable tree). 173*b4dd7d09SAndy Fiddaman the application supports two different modes: \'seq\' takes 174*b4dd7d09SAndy Fiddaman 1-3 arguments to specify the set of numbers via seq(1) and 175*b4dd7d09SAndy Fiddaman \'stdin\' reads the numbers from stdin (one per line)] 176*b4dd7d09SAndy Fiddaman 177*b4dd7d09SAndy Fiddamanmethod [ arguments ] 178*b4dd7d09SAndy Fiddaman 179*b4dd7d09SAndy Fiddaman[+SEE ALSO?\bksh93\b(1), \bseq\b(1)] 180*b4dd7d09SAndy Fiddaman' 181*b4dd7d09SAndy Fiddaman 182*b4dd7d09SAndy Fiddamanwhile getopts -a "${progname}" "${numtree1_usage}" OPT ; do 183*b4dd7d09SAndy Fiddaman# printmsg "## OPT=|${OPT}|, OPTARG=|${OPTARG}|" 184*b4dd7d09SAndy Fiddaman case ${OPT} in 185*b4dd7d09SAndy Fiddaman *) usage ;; 186*b4dd7d09SAndy Fiddaman esac 187*b4dd7d09SAndy Fiddamandone 188*b4dd7d09SAndy Fiddamanshift $((OPTIND-1)) 189*b4dd7d09SAndy Fiddaman 190*b4dd7d09SAndy Fiddaman# prechecks 191*b4dd7d09SAndy Fiddaman(( $# > 0 )) || usage 192*b4dd7d09SAndy Fiddaman 193*b4dd7d09SAndy Fiddamancmd=$1 194*b4dd7d09SAndy Fiddamanshift 195*b4dd7d09SAndy Fiddaman 196*b4dd7d09SAndy Fiddaman# Read numbers from stdin outside benchmark loop 197*b4dd7d09SAndy Fiddamanif [[ ${cmd} == 'stdin' ]] ; then 198*b4dd7d09SAndy Fiddaman stdin_numbers="$( cat /dev/stdin )" || fatal_error "stdin read error" 199*b4dd7d09SAndy Fiddamanfi 200*b4dd7d09SAndy Fiddaman 201*b4dd7d09SAndy Fiddaman(( bench.start=SECONDS )) 202*b4dd7d09SAndy Fiddaman 203*b4dd7d09SAndy Fiddamancase ${cmd} in 204*b4dd7d09SAndy Fiddaman "seq") 205*b4dd7d09SAndy Fiddaman for i in ${ floatseq "$@" ; } ; do 206*b4dd7d09SAndy Fiddaman add_number_to_tree base "${i}" 207*b4dd7d09SAndy Fiddaman done 208*b4dd7d09SAndy Fiddaman ;; 209*b4dd7d09SAndy Fiddaman "stdin") 210*b4dd7d09SAndy Fiddaman for i in ${stdin_numbers} ; do 211*b4dd7d09SAndy Fiddaman add_number_to_tree base "${i}" 212*b4dd7d09SAndy Fiddaman done 213*b4dd7d09SAndy Fiddaman ;; 214*b4dd7d09SAndy Fiddaman "demo1") 215*b4dd7d09SAndy Fiddaman for i in 1 32 33 34 34 38 90 ; do 216*b4dd7d09SAndy Fiddaman add_number_to_tree base "${i}" 217*b4dd7d09SAndy Fiddaman done 218*b4dd7d09SAndy Fiddaman ;; 219*b4dd7d09SAndy Fiddaman "demo2") 220*b4dd7d09SAndy Fiddaman for (( i=1000000000 ; i < 1000000000+10 ; i++ )) ; do 221*b4dd7d09SAndy Fiddaman add_number_to_tree base "$i" 222*b4dd7d09SAndy Fiddaman done 223*b4dd7d09SAndy Fiddaman ;; 224*b4dd7d09SAndy Fiddaman *) 225*b4dd7d09SAndy Fiddaman fatal_error "Invalid command ${cmd}." 226*b4dd7d09SAndy Fiddaman ;; 227*b4dd7d09SAndy Fiddamanesac 228*b4dd7d09SAndy Fiddaman 229*b4dd7d09SAndy Fiddaman(( bench.stop=SECONDS )) 230*b4dd7d09SAndy Fiddaman 231*b4dd7d09SAndy Fiddamanprint -u2 -f "# time used: %f\n" $((bench.stop - bench.start)) 232*b4dd7d09SAndy Fiddaman 233*b4dd7d09SAndy Fiddaman# print tree 234*b4dd7d09SAndy Fiddamanprint -v base 235*b4dd7d09SAndy Fiddaman 236*b4dd7d09SAndy Fiddamanexit 0 237*b4dd7d09SAndy Fiddaman# EOF. 238