procedure tcolarit(tabfil,oper1,operat,oper2,outcol) char tabfil ="" {prompt="free format ASCII file"} char oper1 ="" {prompt="operand1 (real | other_colnr: prepend #)"} char operat ="" {prompt="operator",enum="+|-|*|/|=|ln|log|exp|dexp|sqrt|sin|cos|tan|abs|nint|del"} char oper2 ="" {prompt="operand2 (real | other_colnr: prepend #)"} char outcol ="new" {prompt="output column to store result (new|1-15)"} char delim =" " {prompt="column separation character"} bool skiperr =yes {prompt="skip lines causing errors; print message only?"} int ndecim =4 {prompt="number of decimals to print in result"} # @(#) task tcolarit Author: R.A. Jansen -- Nov 23 1996 # @(#) # @(#) task for simple arithmetic operations on entries in ASCII table # @(#) columns. At this time single operators +,-,*,/,=, as well as func # @(#) tions are implemented. Operations either should be of the form: # @(#) = , where operands # @(#) can be a real number or column entries from the table (columns # @(#) should be denoted by a '#'-sign followed by the column number), # @(#) or of the form: = , where # @(#) operator is one of the functions: ln, log, exp, dexp, sqrt, sin, # @(#) cos, tan, abs, nint. In the latter case, 'oper2' has to be an # @(#) empty string. The output numbers can either be direc- # @(#) ted to overwrite an existing column, or to a new column (column # @(#) number will be (ncolumns+1) ), the latter being the default. # @(#) The special operator '=' is used to copy the values of one column # @(#) to another or initialize all elements of a column to a constant. # @(#) The special operator 'del' is used to delete a column. # @(#) This task supplements task 'ctio.filecalc', which may be more # @(#) convenient for complicated arithmetic expressions. # @(#) # @(#) EXAMPLES: # @(#) Assume we have a table with 5 columns of real numbers: # @(#) usr> tcolarit test.fil "#1" "+" "#2" new # @(#) TCOLARIT: table=test.fil [#6] = [#1] + [#2] ncols=5 # @(#) usr> tcolarit test.fil "#6" "log" "" new # @(#) TCOLARIT: table=test.fil [#7] = log( [#6] ) ncols=6 # @(#) usr> tcolarit test.fil "#7" "-" 1.00 7 # @(#) TCOLARIT: table=test.fil [#7] = [#7] - 1. ncols=7 # @(#) # @(#) BUGS: # @(#) Currently, due to the use of task 'cparse', a limit of 15 columns # @(#) is enforced. Output can be up to 16 columns if 'outcol="new"'. # @(#) # @(#) Jan 21 1998 -- Added aditional operators 'nint','=' and 'del' and # @(#) added header parameter 'ndecim' for semi-formatted # @(#) output. begin string infile, sep, cstr, cop1, opt, cop2, ocol, newstr, cval struct line int ncol1, ncol2, NN, NF, pow, nw real newval, val1, val2 bool isfnc, goskip, hundred infile = tabfil cop1 = oper1 opt = operat cop2 = oper2 ocol = outcol sep = delim if ( sep == "" ) { sep = " " } pow = ndecim # Test input task parameters ... ncol1 = 0 if ( substr(cop1,1,1) == "#" ) { ncol1 = int(substr(cop1,2,strlen(cop1))) cop1 = "["//cop1//"]" if ( ncol1 > 15 ) { print ("ERROR NCOL1 > 15: Current limit on column number is 15. Sorry.") return } } else { val1 = real(cop1) } isfnc = no if (opt=="ln"||opt=="log"||opt=="exp"||opt=="dexp"||opt=="sqrt"||opt=="sin"||opt=="cos"||opt=="tan"||opt=="abs"||opt=="nint"||opt=="del") { if ( ncol1 == 0 ) { print("ERROR: 'oper1' is not a column, while 'operat' is a function! Exit...") return } if ( oper2 != "" ) { print("ERROR: 'oper2' not empty string, while 'operat' is a function! Exit...") return } isfnc = yes } ncol2 = 0 if ( !isfnc && substr(cop2,1,1)=="#" ) { ncol2 = int(substr(cop2,2,strlen(cop2))) cop2 = "["//cop2//"]" if ( ncol2 > 15 ) { print ("Current limit on column number is 15. Sorry.") return } } else if ( !isfnc ) { val2 = real(cop2) } # Check whether input file exist if ( !access(infile) ) { print ("File "//infile//" not found! Exit...") return } # Check whether tcolarit crashed before if ( access("tmprtcl.newtab") ) { delete ("tmprtcl.newtab", yes, verify=no) } # Determine number of columns in file in case outcol="new" rdlist (infile, 1) if ( substr(rdlist.cline,1,1) == "#" ) { NN = 1 while ( substr(rdlist.cline,1,1) == "#" ) { NN += 1 rdlist (infile, NN) } } cparse (rdlist.cline, delim=sep) NF = cparse.nfields if ( ncol1 > NF ) { print("ERROR: column number operand1 > total number of columns! Exit ...") return } if ( ncol2 > NF ) { print("ERROR: column number operand2 > total number of columns! Exit ...") return } if (opt == "=" || opt == "del" ) { if ( opt == "=" ) { if ( substr(cop1,2,2)=="#" ) { ocol = substr(cop1,3,strlen(cop1)-1) } else { ocol = substr(cop2,3,strlen(cop2)-1) } } else { ocol = substr(cop1,3,strlen(cop1)-1) } } else { if ( ocol == "new" ) { ocol = str(NF+1) } else { if ( substr(ocol,1,1) == "#" ) { ocol = substr(ocol,2,strlen(ocol)) } } if ( int(ocol) > (NF+1) ) { print("ERROR: requested output column number > input number of columns + 1 ! Exit ...") return } } # Input OK. Opening message... if ( isfnc ) { if ( opt == "del" ) { print ("TCOLARIT: table="//infile//" delete( [#"//str(ncol1)//"] ) ncols="//str(NF)) } else { print ("TCOLARIT: table="//infile//" [#"//ocol//"] = "//opt//"( [#"//str(ncol1)//"] ) ncols="//str(NF)) } } else { if ( opt == "=" ) { print ("TCOLARIT: table="//infile//" "//cop1//" = "//cop2//" ncols="//str(NF)) } else { print ("TCOLARIT: table="//infile//" [#"//ocol//"] = "//cop1//" "//opt//" "//cop2//" ncols="//str(NF)) } } # Loop over table lines and get table column values ... NN = 0 goskip = no list = infile while ( fscan(list,line) != EOF ) { newval = 0.00 newstr = "" cstr = line if ( substr(cstr,1,1) != "#" ) { NN += 1 cparse (cstr, delim=sep) # check number of fields versus column number if ( cparse.nfields < NF ) { if (skiperr) { print ("WARNING: nfields < "//str(NF)//" in line "//str(NN)//"! Skipping line...") goskip = yes } else { print ("ERROR: nfields < "//str(NF)//" in line "//str(NN)//"! Exit...") return } } if ( cparse.nfields > NF ) { if (skiperr) { print ("WARNING: nfields > "//str(NF)//" in line "//str(NN)//"! Skipping line...") goskip = yes } else { print ("ERROR: nfields > "//str(NF)//" in line "//str(NN)//"! Exit...") return } } if (!goskip) { # Number of columns OK, continue if ( ncol1 != 0 ) { if ( ncol1 == 1 ) { if ( cparse.field1 == "INDEF" ) { val1 = -9.999999e9 } else { val1 = real(cparse.field1) } } if ( ncol1 == 2 ) { if ( cparse.field2 == "INDEF" ) { val1 = -9.999999e9 } else { val1 = real(cparse.field2) } } if ( ncol1 == 3 ) { if ( cparse.field3 == "INDEF" ) { val1 = -9.999999e9 } else { val1 = real(cparse.field3) } } if ( ncol1 == 4 ) { if ( cparse.field4 == "INDEF" ) { val1 = -9.999999e9 } else { val1 = real(cparse.field4) } } if ( ncol1 == 5 ) { if ( cparse.field5 == "INDEF" ) { val1 = -9.999999e9 } else { val1 = real(cparse.field5) } } if ( ncol1 == 6 ) { if ( cparse.field6 == "INDEF" ) { val1 = -9.999999e9 } else { val1 = real(cparse.field6) } } if ( ncol1 == 7 ) { if ( cparse.field7 == "INDEF" ) { val1 = -9.999999e9 } else { val1 = real(cparse.field7) } } if ( ncol1 == 8 ) { if ( cparse.field8 == "INDEF" ) { val1 = -9.999999e9 } else { val1 = real(cparse.field8) } } if ( ncol1 == 9 ) { if ( cparse.field9 == "INDEF" ) { val1 = -9.999999e9 } else { val1 = real(cparse.field9) } } if ( ncol1 == 10 ) { if ( cparse.field10 == "INDEF" ) { val1 = -9.999999e9 } else { val1 = real(cparse.field10) } } if ( ncol1 == 11 ) { if ( cparse.field11 == "INDEF" ) { val1 = -9.999999e9 } else { val1 = real(cparse.field11) } } if ( ncol1 == 12 ) { if ( cparse.field12 == "INDEF" ) { val1 = -9.999999e9 } else { val1 = real(cparse.field12) } } if ( ncol1 == 13 ) { if ( cparse.field13 == "INDEF" ) { val1 = -9.999999e9 } else { val1 = real(cparse.field13) } } if ( ncol1 == 14 ) { if ( cparse.field14 == "INDEF" ) { val1 = -9.999999e9 } else { val1 = real(cparse.field14) } } if ( ncol1 == 15 ) { if ( cparse.field15 == "INDEF" ) { val1 = -9.999999e9 } else { val1 = real(cparse.field15) } } } if ( ncol2 != 0 ) { if ( ncol2 == 1 ) { val2 = real(cparse.field1) } if ( ncol2 == 2 ) { val2 = real(cparse.field2) } if ( ncol2 == 3 ) { val2 = real(cparse.field3) } if ( ncol2 == 4 ) { val2 = real(cparse.field4) } if ( ncol2 == 5 ) { val2 = real(cparse.field5) } if ( ncol2 == 6 ) { val2 = real(cparse.field6) } if ( ncol2 == 7 ) { val2 = real(cparse.field7) } if ( ncol2 == 8 ) { val2 = real(cparse.field8) } if ( ncol2 == 9 ) { val2 = real(cparse.field9) } if ( ncol2 == 10 ) { val2 = real(cparse.field10) } if ( ncol2 == 11 ) { val2 = real(cparse.field11) } if ( ncol2 == 12 ) { val2 = real(cparse.field12) } if ( ncol2 == 13 ) { val2 = real(cparse.field13) } if ( ncol2 == 14 ) { val2 = real(cparse.field14) } if ( ncol2 == 15 ) { val2 = real(cparse.field15) } } # Execute operation ... if ( isfnc ) { if ( opt == "ln" ) { if ( val1 > 0.00 ) { newval = log(val1) } else { newval = -9.999999e9 } } if ( opt == "log" ) { if ( val1 > 0.00 ) { newval = log10(val1) } else { newval = -9.999999e9 } } if ( opt == "sqrt" ) { if ( val1 >= 0.00 ) { newval = sqrt(val1) } else { newval = -9.999999e9 } } if ( opt == "exp" ) { newval = exp(val1) } if ( opt == "dexp") { newval = 10**(val1) } if ( opt == "sin" ) { newval = sin(val1) } if ( opt == "cos" ) { newval = cos(val1) } if ( opt == "tan" ) { newval = tan(val1) } if ( opt == "abs" ) { newval = abs(val1) } if ( opt == "nint") { newval = nint(val1) } if ( opt == "del" ) { newval = -9.999999e19 } } else { if ( opt == "+" ) { newval = val1 + val2 } if ( opt == "-" ) { newval = val1 - val2 } if ( opt == "*" ) { newval = val1 * val2 } if ( opt == "/" ) { if ( val2 != 0.00 ) { newval = val1 / val2 } else { newval = -9.999999e9 } } if ( opt == "=" ) { if ( substr(cop1,2,2)=="#" ) { newval = val2 } else { newval = val1 } } } if ( newval == -9.999999e19 ) { cval = "" } else { cval = str((10**(-1.0*pow))*nint(newval*(10**pow))) nw = (pow + stridx(".",cval)) cval = " "//substr(cval//"000000000000",1,nw) } # Construct new table line ... if ( ocol != "1" ) { newstr = newstr//" "//cparse.field1 } else { if ( newval == -9.999999e9 ) { newstr = newstr//" INDEF" } else { newstr = newstr//cval } } if ( NF >= 1 ) { if ( ocol != "2" ) { newstr = newstr//" "//cparse.field2 } else { if ( newval == -9.999999e9 ) { newstr = newstr//" INDEF" } else { newstr = newstr//cval } } } if ( NF >= 2 ) { if ( ocol != "3" ) { newstr = newstr//" "//cparse.field3 } else { if ( newval == -9.999999e9 ) { newstr = newstr//" INDEF" } else { newstr = newstr//cval } } } if ( NF >= 3 ) { if ( ocol != "4" ) { newstr = newstr//" "//cparse.field4 } else { if ( newval == -9.999999e9 ) { newstr = newstr//" INDEF" } else { newstr = newstr//cval } } } if ( NF >= 4 ) { if ( ocol != "5" ) { newstr = newstr//" "//cparse.field5 } else { if ( newval == -9.999999e9 ) { newstr = newstr//" INDEF" } else { newstr = newstr//cval } } } if ( NF >= 5 ) { if ( ocol != "6" ) { newstr = newstr//" "//cparse.field6 } else { if ( newval == -9.999999e9 ) { newstr = newstr//" INDEF" } else { newstr = newstr//cval } } } if ( NF >= 6 ) { if ( ocol != "7" ) { newstr = newstr//" "//cparse.field7 } else { if ( newval == -9.999999e9 ) { newstr = newstr//" INDEF" } else { newstr = newstr//cval } } } if ( NF >= 7 ) { if ( ocol != "8" ) { newstr = newstr//" "//cparse.field8 } else { if ( newval == -9.999999e9 ) { newstr = newstr//" INDEF" } else { newstr = newstr//cval } } } if ( NF >= 8 ) { if ( ocol != "9" ) { newstr = newstr//" "//cparse.field9 } else { if ( newval == -9.999999e9 ) { newstr = newstr//" INDEF" } else { newstr = newstr//cval } } } if ( NF >= 9 ) { if ( ocol != "10" ) { newstr = newstr//" "//cparse.field10 } else { if ( newval == -9.999999e9 ) { newstr = newstr//" INDEF" } else { newstr = newstr//cval } } } if ( NF >= 10 ) { if ( ocol != "11" ) { newstr = newstr//" "//cparse.field11 } else { if ( newval == -9.999999e9 ) { newstr = newstr//" INDEF" } else { newstr = newstr//cval } } } if ( NF >= 11 ) { if ( ocol != "12" ) { newstr = newstr//" "//cparse.field12 } else { if ( newval == -9.999999e9 ) { newstr = newstr//" INDEF" } else { newstr = newstr//cval } } } if ( NF >= 12 ) { if ( ocol != "13" ) { newstr = newstr//" "//cparse.field13 } else { if ( newval == -9.999999e9 ) { newstr = newstr//" INDEF" } else { newstr = newstr//cval } } } if ( NF >= 13 ) { if ( ocol != "14" ) { newstr = newstr//" "//cparse.field14 } else { if ( newval == -9.999999e9 ) { newstr = newstr//" INDEF" } else { newstr = newstr//cval } } } if ( NF >= 14 ) { if ( ocol != "15" ) { newstr = newstr//" "//cparse.field15 } else { if ( newval == -9.999999e9 ) { newstr = newstr//" INDEF" } else { newstr = newstr//cval } } } if ( NF == 15 ) { if ( ocol == "16" ) { if ( newval == -9.999999e9 ) { newstr = newstr//" INDEF" } else { newstr = newstr//cval } } } } else { # End of 'goskip=no' block newstr = cstr goskip = no } } else { # End of 'substr(cstr,1,1)!="#" block newstr = cstr goskip = no } # Write out new table line ... print (newstr, >> "tmprtcl.newtab") # Show where we are in the file (for long files) printf ("%1s", "\r processing line: "//str(NN)//"\r ", ) } # Delete old table file and rename new table file ... delete (infile, yes, verify=no) copy ("tmprtcl.newtab", infile, verbose=no) delete ("tmprtcl.newtab", yes, verify=no) printf("\n%1s\n", "TCOLARIT: Done.") end