134f9b3eeSRoland Mainz#!/usr/bin/ksh93 234f9b3eeSRoland Mainz 334f9b3eeSRoland Mainz# 434f9b3eeSRoland Mainz# CDDL HEADER START 534f9b3eeSRoland Mainz# 634f9b3eeSRoland Mainz# The contents of this file are subject to the terms of the 734f9b3eeSRoland Mainz# Common Development and Distribution License (the "License"). 834f9b3eeSRoland Mainz# You may not use this file except in compliance with the License. 934f9b3eeSRoland Mainz# 1034f9b3eeSRoland Mainz# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 1134f9b3eeSRoland Mainz# or http://www.opensolaris.org/os/licensing. 1234f9b3eeSRoland Mainz# See the License for the specific language governing permissions 1334f9b3eeSRoland Mainz# and limitations under the License. 1434f9b3eeSRoland Mainz# 1534f9b3eeSRoland Mainz# When distributing Covered Code, include this CDDL HEADER in each 1634f9b3eeSRoland Mainz# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1734f9b3eeSRoland Mainz# If applicable, add the following below this CDDL HEADER, with the 1834f9b3eeSRoland Mainz# fields enclosed by brackets "[]" replaced with your own identifying 1934f9b3eeSRoland Mainz# information: Portions Copyright [yyyy] [name of copyright owner] 2034f9b3eeSRoland Mainz# 2134f9b3eeSRoland Mainz# CDDL HEADER END 2234f9b3eeSRoland Mainz# 2334f9b3eeSRoland Mainz 2434f9b3eeSRoland Mainz# 25*3e14f97fSRoger A. Faulkner# Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 2634f9b3eeSRoland Mainz# 2734f9b3eeSRoland Mainz 2834f9b3eeSRoland Mainz# 2934f9b3eeSRoland Mainz# numtree1 - basic compound variable tree demo+benchmark 3034f9b3eeSRoland Mainz# 3134f9b3eeSRoland Mainz 3234f9b3eeSRoland Mainz# Solaris needs /usr/xpg6/bin:/usr/xpg4/bin because the tools in /usr/bin are not POSIX-conformant 3334f9b3eeSRoland Mainzexport PATH=/usr/xpg6/bin:/usr/xpg4/bin:/bin:/usr/bin 3434f9b3eeSRoland Mainz 3534f9b3eeSRoland Mainz# Make sure all math stuff runs in the "C" locale to avoid problems 3634f9b3eeSRoland Mainz# with alternative # radix point representations (e.g. ',' instead of 3734f9b3eeSRoland Mainz# '.' in de_DE.*-locales). This needs to be set _before_ any 3834f9b3eeSRoland Mainz# floating-point constants are defined in this script). 3934f9b3eeSRoland Mainzif [[ "${LC_ALL}" != "" ]] ; then 4034f9b3eeSRoland Mainz export \ 4134f9b3eeSRoland Mainz LC_MONETARY="${LC_ALL}" \ 4234f9b3eeSRoland Mainz LC_MESSAGES="${LC_ALL}" \ 4334f9b3eeSRoland Mainz LC_COLLATE="${LC_ALL}" \ 4434f9b3eeSRoland Mainz LC_CTYPE="${LC_ALL}" 4534f9b3eeSRoland Mainz unset LC_ALL 4634f9b3eeSRoland Mainzfi 4734f9b3eeSRoland Mainzexport LC_NUMERIC=C 4834f9b3eeSRoland Mainz 4934f9b3eeSRoland Mainzfunction fatal_error 5034f9b3eeSRoland Mainz{ 5134f9b3eeSRoland Mainz print -u2 "${progname}: $*" 5234f9b3eeSRoland Mainz exit 1 5334f9b3eeSRoland Mainz} 5434f9b3eeSRoland Mainz 5534f9b3eeSRoland Mainzfunction add_number_to_tree 5634f9b3eeSRoland Mainz{ 5734f9b3eeSRoland Mainz typeset treename=$1 5834f9b3eeSRoland Mainz integer num=$2 5934f9b3eeSRoland Mainz integer i 6034f9b3eeSRoland Mainz typeset nodepath # full name of compound variable 6134f9b3eeSRoland Mainz integer -a pe # path elements 62*3e14f97fSRoger A. Faulkner integer len 63*3e14f97fSRoger A. Faulkner typeset revnums="$(rev <<<"${num}")" 6434f9b3eeSRoland Mainz 6534f9b3eeSRoland Mainz # first built an array containing the names of each path element 6634f9b3eeSRoland Mainz # (e.g. "135" results in an array containing "( 1 3 5 )") 67*3e14f97fSRoger A. Faulkner # 10#<number> is used to prevent leading zeros being interpreted 68*3e14f97fSRoger A. Faulkner # as octals 69*3e14f97fSRoger A. Faulkner for (( len=${#revnums} , i=$( printf "10#%s\n" "${revnums}" ) ; len > 0 ; len--, i=i/10 )) ; do 7034f9b3eeSRoland Mainz pe+=( $((i % 10)) ) 7134f9b3eeSRoland Mainz done 7234f9b3eeSRoland Mainz 7334f9b3eeSRoland Mainz # walk path described via the "pe" array and build nodes if 7434f9b3eeSRoland Mainz # there aren't any nodes yet 7534f9b3eeSRoland Mainz nodepath="${treename}" 7634f9b3eeSRoland Mainz for (( i=0 ; i < ${#pe[@]} ; i++ )) ; do 7734f9b3eeSRoland Mainz nameref x="${nodepath}" 78*3e14f97fSRoger A. Faulkner 79*3e14f97fSRoger A. Faulkner # [[ -v ]] does not work for arrays because [[ -v ar ]] 80*3e14f97fSRoger A. Faulkner # is equal to [[ -v ar[0] ]]. In this case we can 81*3e14f97fSRoger A. Faulkner # use the output of typeset +p x.nodes 82*3e14f97fSRoger A. Faulkner [[ "${ typeset +p x.nodes ;}" == "" ]] && compound -a x.nodes 8334f9b3eeSRoland Mainz 8434f9b3eeSRoland Mainz nodepath+=".nodes[${pe[i]}]" 8534f9b3eeSRoland Mainz done 8634f9b3eeSRoland Mainz 87*3e14f97fSRoger A. Faulkner # insert element (leaf) 8834f9b3eeSRoland Mainz nameref node="${nodepath}" 89*3e14f97fSRoger A. Faulkner [[ "${ typeset +p node.elements ;}" == "" ]] && integer -a node.elements 9034f9b3eeSRoland Mainz node.elements+=( ${num} ) 9134f9b3eeSRoland Mainz 92*3e14f97fSRoger A. Faulkner # DEBUG only 93*3e14f97fSRoger A. Faulkner [[ "${!node.elements[*]}" != "" ]] || fatal_error "assertion $LINENO FAILED" 94*3e14f97fSRoger A. Faulkner [[ "${ typeset +p node.elements ;}" == *-a* ]] || fatal_error "assertion $LINENO FAILED" 95*3e14f97fSRoger A. Faulkner [[ "${ typeset +p node.elements ;}" == *-i* ]] || fatal_error "assertion $LINENO FAILED" 96*3e14f97fSRoger A. Faulkner [[ -v node ]] || fatal_error "assertion $LINENO FAILED" 97*3e14f97fSRoger A. Faulkner [[ -R node ]] || fatal_error "assertion $LINENO FAILED" 98*3e14f97fSRoger A. Faulkner [[ "${ typeset +p ${!node} ;}" == *-C* ]] || fatal_error "assertion $LINENO FAILED" 99*3e14f97fSRoger A. Faulkner [[ "${!x.nodes[*]}" != "" ]] || fatal_error "assertion $LINENO FAILED" 100*3e14f97fSRoger A. Faulkner [[ "${ typeset +p x.nodes ;}" == *-a* ]] || fatal_error "assertion $LINENO FAILED" 101*3e14f97fSRoger A. Faulkner [[ "${ typeset +p x.nodes ;}" == *-C* ]] || fatal_error "assertion $LINENO FAILED" 102*3e14f97fSRoger A. Faulkner 10334f9b3eeSRoland Mainz return 0 10434f9b3eeSRoland Mainz} 10534f9b3eeSRoland Mainz 10634f9b3eeSRoland Mainz 10734f9b3eeSRoland Mainz# floating-point version of "seq" 10834f9b3eeSRoland Mainzfunction floatseq 10934f9b3eeSRoland Mainz{ 11034f9b3eeSRoland Mainz float i 11134f9b3eeSRoland Mainz float arg1=$1 11234f9b3eeSRoland Mainz float arg2=$2 11334f9b3eeSRoland Mainz float arg3=$3 11434f9b3eeSRoland Mainz 11534f9b3eeSRoland Mainz case $# in 11634f9b3eeSRoland Mainz 1) 11734f9b3eeSRoland Mainz for (( i=1. ; i <= arg1 ; i=i+1. )) ; do 11834f9b3eeSRoland Mainz printf "%a\n" i 11934f9b3eeSRoland Mainz done 12034f9b3eeSRoland Mainz ;; 12134f9b3eeSRoland Mainz 2) 12234f9b3eeSRoland Mainz for (( i=arg1 ; i <= arg2 ; i=i+1. )) ; do 12334f9b3eeSRoland Mainz printf "%a\n" i 12434f9b3eeSRoland Mainz done 12534f9b3eeSRoland Mainz ;; 12634f9b3eeSRoland Mainz 3) 12734f9b3eeSRoland Mainz for (( i=arg1 ; i <= arg3 ; i+=arg2 )) ; do 12834f9b3eeSRoland Mainz printf "%a\n" i 12934f9b3eeSRoland Mainz done 13034f9b3eeSRoland Mainz ;; 13134f9b3eeSRoland Mainz *) 13234f9b3eeSRoland Mainz print -u2 -f "%s: Illegal number of arguments %d\n" "$0" $# 13334f9b3eeSRoland Mainz return 1 13434f9b3eeSRoland Mainz ;; 13534f9b3eeSRoland Mainz esac 13634f9b3eeSRoland Mainz 13734f9b3eeSRoland Mainz return 0 13834f9b3eeSRoland Mainz} 13934f9b3eeSRoland Mainz 14034f9b3eeSRoland Mainz 14134f9b3eeSRoland Mainzfunction usage 14234f9b3eeSRoland Mainz{ 14334f9b3eeSRoland Mainz OPTIND=0 14434f9b3eeSRoland Mainz getopts -a "${progname}" "${numtree1_usage}" OPT '-?' 14534f9b3eeSRoland Mainz exit 2 14634f9b3eeSRoland Mainz} 14734f9b3eeSRoland Mainz 14834f9b3eeSRoland Mainz# main 14934f9b3eeSRoland Mainzbuiltin basename 15034f9b3eeSRoland Mainzbuiltin rev 15134f9b3eeSRoland Mainz 15234f9b3eeSRoland Mainzset -o noglob 15334f9b3eeSRoland Mainzset -o errexit 15434f9b3eeSRoland Mainzset -o nounset 15534f9b3eeSRoland Mainz 15634f9b3eeSRoland Mainzcompound base 15734f9b3eeSRoland Mainz 15834f9b3eeSRoland Mainzcompound bench=( 15934f9b3eeSRoland Mainz float start 16034f9b3eeSRoland Mainz float stop 16134f9b3eeSRoland Mainz) 16234f9b3eeSRoland Mainz 16334f9b3eeSRoland Mainzinteger i 16434f9b3eeSRoland Mainz 16534f9b3eeSRoland Mainztypeset progname="${ basename "${0}" ; }" 16634f9b3eeSRoland Mainz 16734f9b3eeSRoland Mainztypeset -r numtree1_usage=$'+ 168*3e14f97fSRoger A. Faulkner[-?\n@(#)\$Id: numtree1 (Roland Mainz) 2010-03-27 \$\n] 16934f9b3eeSRoland Mainz[-author?Roland Mainz <roland.mainz@nrubsig.org>] 17034f9b3eeSRoland Mainz[+NAME?numtree1 - generate sorted variable tree containing numbers] 17134f9b3eeSRoland Mainz[+DESCRIPTION?\bnumtree1\b is a simple variable tree generator 17234f9b3eeSRoland Mainz sorts a given set of numbers into a ksh compound variable tree). 17334f9b3eeSRoland Mainz the application supports two different modes: \'seq\' takes 17434f9b3eeSRoland Mainz 1-3 arguments to specify the set of numbers via seq(1) and 17534f9b3eeSRoland Mainz \'stdin\' reads the numbers from stdin (one per line)] 17634f9b3eeSRoland Mainz 17734f9b3eeSRoland Mainzmethod [ arguments ] 17834f9b3eeSRoland Mainz 17934f9b3eeSRoland Mainz[+SEE ALSO?\bksh93\b(1), \bseq\b(1)] 18034f9b3eeSRoland Mainz' 18134f9b3eeSRoland Mainz 18234f9b3eeSRoland Mainzwhile getopts -a "${progname}" "${numtree1_usage}" OPT ; do 18334f9b3eeSRoland Mainz# printmsg "## OPT=|${OPT}|, OPTARG=|${OPTARG}|" 18434f9b3eeSRoland Mainz case ${OPT} in 18534f9b3eeSRoland Mainz *) usage ;; 18634f9b3eeSRoland Mainz esac 18734f9b3eeSRoland Mainzdone 18834f9b3eeSRoland Mainzshift $((OPTIND-1)) 18934f9b3eeSRoland Mainz 19034f9b3eeSRoland Mainz# prechecks 19134f9b3eeSRoland Mainz(( $# > 0 )) || usage 19234f9b3eeSRoland Mainz 19334f9b3eeSRoland Mainzcmd=$1 19434f9b3eeSRoland Mainzshift 19534f9b3eeSRoland Mainz 19634f9b3eeSRoland Mainz# Read numbers from stdin outside benchmark loop 19734f9b3eeSRoland Mainzif [[ ${cmd} == 'stdin' ]] ; then 19834f9b3eeSRoland Mainz stdin_numbers="$( cat /dev/stdin )" || fatal_error "stdin read error" 19934f9b3eeSRoland Mainzfi 20034f9b3eeSRoland Mainz 20134f9b3eeSRoland Mainz(( bench.start=SECONDS )) 20234f9b3eeSRoland Mainz 20334f9b3eeSRoland Mainzcase ${cmd} in 20434f9b3eeSRoland Mainz "seq") 20534f9b3eeSRoland Mainz for i in ${ floatseq "$@" ; } ; do 20634f9b3eeSRoland Mainz add_number_to_tree base "${i}" 20734f9b3eeSRoland Mainz done 20834f9b3eeSRoland Mainz ;; 20934f9b3eeSRoland Mainz "stdin") 21034f9b3eeSRoland Mainz for i in ${stdin_numbers} ; do 21134f9b3eeSRoland Mainz add_number_to_tree base "${i}" 21234f9b3eeSRoland Mainz done 21334f9b3eeSRoland Mainz ;; 21434f9b3eeSRoland Mainz "demo1") 21534f9b3eeSRoland Mainz for i in 1 32 33 34 34 38 90 ; do 21634f9b3eeSRoland Mainz add_number_to_tree base "${i}" 21734f9b3eeSRoland Mainz done 21834f9b3eeSRoland Mainz ;; 21934f9b3eeSRoland Mainz "demo2") 22034f9b3eeSRoland Mainz for (( i=1000000000 ; i < 1000000000+10 ; i++ )) ; do 22134f9b3eeSRoland Mainz add_number_to_tree base "$i" 22234f9b3eeSRoland Mainz done 22334f9b3eeSRoland Mainz ;; 22434f9b3eeSRoland Mainz *) 22534f9b3eeSRoland Mainz fatal_error "Invalid command ${cmd}." 22634f9b3eeSRoland Mainz ;; 22734f9b3eeSRoland Mainzesac 22834f9b3eeSRoland Mainz 22934f9b3eeSRoland Mainz(( bench.stop=SECONDS )) 23034f9b3eeSRoland Mainz 23134f9b3eeSRoland Mainzprint -u2 -f "# time used: %f\n" $((bench.stop - bench.start)) 23234f9b3eeSRoland Mainz 23334f9b3eeSRoland Mainz# print tree 23434f9b3eeSRoland Mainzprint -v base 23534f9b3eeSRoland Mainz 23634f9b3eeSRoland Mainzexit 0 23734f9b3eeSRoland Mainz# EOF. 238