#!/usr/bin/perl 1; ################################################################## ### arithmetic model (table or equation or trivial) evaluation ### ################################################################## sub ALF_EvaluateArithmeticModel { local($model,%arg) = @_; print("# ALF Math Info:\tevaluating arithmetic model $model\t",&ALF_ObjectInfoText($model),"\n") if ($ALF_Debug > 1); local $header = &ALF_FindMatchingObject($model,'HEADER'); local $equation = &ALF_FindMatchingObject($model,'EQUATION'); local $table = &ALF_FindMatchingObject($model,'TABLE'); local $value = $ALF_Value{$model}; local $result; ### trivial arithmetic model if (defined($value)) { $result = $value; ### equation or table } elsif ($header) { local %val = (); local $valid = 1; local @keys = keys %arg; foreach $key (@keys) { local $namematch = &ALF_FindMatchingObject($header,undef,$key); local $typematch = &ALF_FindMatchingObject($header,$key,0); local $match = $namematch || $typematch; if ($match) { local $val = $arg{$key}; print("# ALF Math Info:\tidentified argument $match with value $val for model $model\t",&ALF_ObjectInfoText($match),"\n") if ($ALF_Debug > 1); $val{&UpperCase($key)} = $val if $equation; $val{$match} = $val if $table; } else { $valid = 0; } } local @val = keys %val; $result = &ALF_EvaluateArithmeticExpression($ALF_Value{$equation},%val) if $equation; $result = &ALF_EvaluateTable($ALF_Value{$table},0,$#val,%val) if $table; } else { } print("# ALF Math Info:\tevaluation result for arithmetic model $model(",join(' ',%arg),") = $result\n") if ($ALF_Debug > 1); $result; } ######################################## ### arithmetic expression processing ### ######################################## sub ALF_EvaluateArithmeticExpression { local($expression,%arg) = @_; local @result = (); foreach $item (&Array($expression)) { $result[$#result+1] = &ALF_ReplaceItem($item,%arg); } local $result = eval(join(' ',@result)); print("# ALF Math Info:\t$result = ",join(' ',@result),"\n") if ($ALF_Debug > 1); $result; } ############################### ### lookup table processing ### ############################### sub ALF_FindMatchingIndex { local ($match,*table) = @_; local $found; foreach $index (0..$#table) { $found = $index if &StringMatch($table[$index],$match); last if defined($found); } $found; } sub ALF_FindFloorIndex { local ($match,*table) = @_; local $found; foreach $index (reverse 0..$#table) { $found = $index unless ($table[$index] > $match); last if defined($found); } defined($found)? $found : 0; } sub ALF_FindCeilingIndex { local ($match,*table) = @_; local $found; foreach $index (0..$#table) { $found = $index unless ($table[$index] < $match); last if defined($found); } defined($found)? $found : $#table; } sub ALF_FindInterpolationIndices { local ($match,*table) = @_; local $lower = &ALF_FindFloorIndex($match,*table); local $upper = &ALF_FindCeilingIndex($match,*table); if ($lower == $upper) { if ($upper > 0) { $lower = $lower - 1; } else { $upper = 1; } } ($lower,$upper); } sub ALF_EvaluateTable { local($table,$tableoffset,$count,%arg) = @_; # local @key = sort(keys %arg); local @key = keys %arg; if ($ALF_Debug > 1) { print("# ALF Math Info:\tstarted evaluation of ",$count+1,"D table $table\ttableoffset[$table]=$tableoffset\t%x=(",join(' ',%arg),")\n") if ($count==$#key); print("# ALF Math Info:\t\ttableoffset[$table]=$tableoffset\t%x=(",join(' ',%arg),")\n") unless ($count==$#key); } local $key = $key[$count]; local $keytable = &AssocVal($ALF_KeyTable{$table}, $key); local $keyoffset = &AssocVal($ALF_KeyOffset{$table},$key); local $x = $arg{$key}; local ($lower,$upper) = &ALF_FindInterpolationIndices($x,$keytable); local $x0 = &ArrayVal($keytable,$lower); local $x1 = &ArrayVal($keytable,$upper); local $lowerindex = $tableoffset+$keyoffset*$lower; local $upperindex = $tableoffset+$keyoffset*$upper; if ($ALF_Debug > 1) { print("# ALF Math Info:\t\tkey[$count]=$key\n"); print("# ALF Math Info:\t\tkeyoffset{$key}=$keyoffset\tkeytable{$key}=$keytable=(",join(' ',&Array($keytable)),")\n"); print("# ALF Math Info:\t\tx{$key}=$x\tx0=$keytable\[$lower\]=$x0\tx1=$keytable\[$upper\]=$x1\n"); } local ($y0,$y1); if ($count > 0) { $y0 = &ALF_EvaluateTable($table,$lowerindex,$count-1,%arg); $y1 = &ALF_EvaluateTable($table,$upperindex,$count-1,%arg); } else { $y0 = &ArrayVal($table,$lowerindex); $y1 = &ArrayVal($table,$upperindex); } local $y = $y0 + ($y1-$y0)*($x-$x0)/($x1-$x0); if ($ALF_Debug > 1) { print("# ALF Math Info:\t\ty($x)=$y\ty0=$table\[$lowerindex\]=$y0\ty1=$table\[$upperindex\]=$y1\n"); print("# ALF Math Info:\tfinished evaluation of ",$count+1,"D table $table\ttableoffset[$table]=$tableoffset\ty(",join(' ',%arg),")=$y\n") if ($count==$#key); } $y; }