OpenCores
URL https://opencores.org/ocsvn/socgen/socgen/trunk

Subversion Repositories socgen

[/] [socgen/] [trunk/] [tools/] [math/] [test] - Blame information for rev 135

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 134 jt_eaton
eval 'exec `which perl` -S $0 ${1+"$@"}'
2
   if 0;
3
#/**********************************************************************/
4
#/*                                                                    */
5
#/*             -------                                                */
6
#/*            /   SOC  \                                              */
7
#/*           /    GEN   \                                             */
8
#/*          /    TOOL    \                                            */
9
#/*          ==============                                            */
10
#/*          |            |                                            */
11
#/*          |____________|                                            */
12
#/*                                                                    */
13
#/*                                                                    */
14
#/*                                                                    */
15
#/*                                                                    */
16
#/*  Author(s):                                                        */
17
#/*      - John Eaton, jt_eaton@opencores.org                          */
18
#/*                                                                    */
19
#/**********************************************************************/
20
#/*                                                                    */
21
#/*    Copyright (C) <2010-2011>                */
22
#/*                                                                    */
23
#/*  This source file may be used and distributed without              */
24
#/*  restriction provided that this copyright statement is not         */
25
#/*  removed from the file and that any derivative work contains       */
26
#/*  the original copyright notice and the associated disclaimer.      */
27
#/*                                                                    */
28
#/*  This source file is free software; you can redistribute it        */
29
#/*  and/or modify it under the terms of the GNU Lesser General        */
30
#/*  Public License as published by the Free Software Foundation;      */
31
#/*  either version 2.1 of the License, or (at your option) any        */
32
#/*  later version.                                                    */
33
#/*                                                                    */
34
#/*  This source is distributed in the hope that it will be            */
35
#/*  useful, but WITHOUT ANY WARRANTY; without even the implied        */
36
#/*  warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR           */
37
#/*  PURPOSE.  See the GNU Lesser General Public License for more      */
38
#/*  details.                                                          */
39
#/*                                                                    */
40
#/*  You should have received a copy of the GNU Lesser General         */
41
#/*  Public License along with this source; if not, download it        */
42
#/*  from http://www.opencores.org/lgpl.shtml                          */
43
#/*                                                                    */
44
#/**********************************************************************/
45
 
46
 
47
############################################################################
48
# General PERL config
49
############################################################################
50
use Getopt::Long;
51
use English;
52
use File::Basename;
53
use Cwd;
54
use Scalar::Util qw(looks_like_number);
55
use XML::LibXML;
56
use lib './tools';
57
use sys::lib;
58
use yp::lib;
59
use BerkeleyDB;
60
 
61
use strict;
62
use warnings;
63
use Data::Dumper;
64
# this code can be re-written without any regex/eval,their use is purely for shortening the code
65
 
66
 
67
 
68
$OUTPUT_AUTOFLUSH = 1; # set autoflush of stdout to TRUE.
69
my $exp;
70
 
71
 
72
############################################################################
73
### Process the options
74
############################################################################
75
Getopt::Long::config("require_order", "prefix=-");
76
GetOptions("h","help",
77
           "exp=s" => \$exp
78
) || die "(use 'math -h' for help)";
79
 
80
my $opt_h;
81
my $opt_help;
82
 
83
##############################################################################
84
## Help option
85
##############################################################################
86
if ( $opt_h  or $opt_help  )
87
  { print "\n test   -exp 2+2  \n";
88
    exit 1;
89
  }
90
 
91
 
92
 
93
 
94
 
95
 
96
#############################################################################
97
##
98
##
99
#############################################################################
100
 
101
 
102
my $home = cwd();
103
 
104
 
105
 
106
 
107
my $result = solve($exp) ;
108
 
109
print "$exp ---  $result\n";
110
 
111
 
112
 
113
 
114
 
115
 
116
 
117
 
118
 
119
#/*********************************************************************************************/
120
#/                                                                                            */
121
#/  solve routine downloaded from perl monks                                                  */
122
#/                                                                                            */
123
#/  my $exp = "5*(12/(32+4))-10";                                                             */
124
#/  my $exp = "3**(6-1*4)**2";                                                                */
125
#/  my $exp = -3+(-1-2);                                                                      */
126
#/  my $exp = (3-(4+6))/2;                                                                    */
127
#/                                                                                            */
128
#/  my $result = math::lib::solve($exp);                                                      */
129
#/                                                                                            */
130
#/                                                                                            */
131
#/*********************************************************************************************/
132
 
133
 
134
sub solve {
135
    my $exp  = shift;
136
 
137
 
138
 
139
 
140
 
141
 
142
 
143
 
144
 
145
use constant BASE_PRIORITY =>
146
{
147
        NUMBER          => 2,
148
        OPEN_PARA       => 8,
149
        CLOSED_PARA => 8,
150
        ADD                     => 4,
151
        SUB                     => 4,
152
        MUL                     => 7,
153
        DIV                     => 7,
154
        POW                     => 9,
155
};
156
 
157
use constant DEPTH_BONUS => 10;
158
 
159
 
160
 
161
 
162
my $depth = 0;
163
my @terms;
164
 
165
 
166
 
167
sub delete_at { # delete the term at the index equal to the parameter given to this function
168
        return shift @terms if $_[0] == 0;
169
        return pop @terms if $_[0] == (@terms-1);
170
        my $ret = $terms[ $_[0] ];
171
        @terms = (
172
                @terms[0..$_[0]-1],
173
                @terms[$_[0]+1..@terms-1],
174
        );
175
        return $ret;
176
}
177
 
178
sub insert_at { # inserts a term exactly before the index given as parameter
179
        @terms = (
180
                @terms[0..$_[0]-1],
181
                $_[1],
182
                @terms[$_[0]..@terms-1],
183
        );
184
 
185
}
186
 
187
 
188
sub firstPass {# this builds up the @terms for later use
189
        while( $exp =~ s/^(\-?\d+|\*\*|\*|\/|\+|\-|\(|\))// ) {
190
                my $type=$1;
191
                my $term=$1;
192
                if( @terms>0 &&  $terms[@terms - 1 ]->{type} eq 'NUMBER' && $term =~ /\-\d+/ ) {
193
                        #see if we currently have a negative number,see if before we had a number
194
                        #this means that we're on the wrong track and that - is actually an operator here
195
                        #and not the sign for a negative number
196
                        $exp=$term.$exp;
197
                        $exp=~s/^-//;
198
                        $type = "SUB";
199
                        $term = '-';
200
                        print "EXP $exp \n";
201
                } else {
202
                        $type =~ s/\-?\d+/NUMBER/;
203
                };
204
                $type =~ s/\(/OPEN_PARA/;
205
                $type =~ s/\)/CLOSED_PARA/;
206
                $type =~ s/\+/ADD/;
207
                $type =~ s/\*\*/POW/;
208
                $type =~ s/\*/MUL/;
209
                $type =~ s/\//DIV/;
210
                $type =~ s/\-$/SUB/;
211
                my ($is_term_para) = $type =~ /OPEN_PARA|CLOSED_PARA/; # this flag will tell us wether the term is or is not a paranthesis
212
                $depth++ if $type eq 'OPEN_PARA';  # if we encounter an open paranthesis we increase depth
213
                $depth-- if $type eq 'CLOSED_PARA';# closed paranthesis we decrease it
214
                push @terms,
215
                {
216
                        type            => $type,
217
                        term            => $term,
218
                        priority        => BASE_PRIORITY->{$type} + $depth*DEPTH_BONUS
219
                }
220
                unless $is_term_para; # we leave out the paranthesis because we no longer need them(their purpose
221
                                                          # was to provide priority information for us)
222
        };
223
}
224
 
225
 
226
sub getPrioritary { # gets most prioritary 3 elements in the current expression
227
 
228
        my @sIndexes = sort { -1 * ( $terms[$a]->{priority} <=> $terms[$b]->{priority} ); } 0..(@terms-1) ;
229
 
230
        my $i = 0; # the index in @sIndexes
231
        my $middleMaxPrio = $sIndexes[$i];
232
 
233
        while( $terms[$middleMaxPrio]->{type} eq 'NUMBER' ) { # if our selected maximum priority element is not a number search for the next most prioritized that is a number
234
                print "[DEBUG] $terms[$middleMaxPrio]->{type}";
235
                $middleMaxPrio = $sIndexes[++$i];
236
        };
237
 
238
        my $leftNearMax   = $middleMaxPrio -1; # we take the left of $middleMaxPrio
239
        my $rightNearMax  = $middleMaxPrio +1; # and the right of it , becuase these two are surely operands
240
 
241
        my @selectedTerms = map { delete_at $_  } ( $rightNearMax , $middleMaxPrio , $leftNearMax ); # we delete them in inverse order to not alter the stack badly
242
 
243
        return {
244
                selected        => [ @selectedTerms ],
245
                insertIndex     => $leftNearMax,
246
                maxPriority     => $selectedTerms[1]->{priority}, # the middle element will be surely an operator so it will have maximum priority
247
        };
248
}
249
 
250
 
251
#---------------------------------------------------------------------------------------------------------------------
252
 
253
firstPass;
254
 
255
while( @terms > 1 ) {
256
        print "DEBUG ".Dumper [@terms];
257
 
258
        my $data = getPrioritary;
259
        my @elems = map { $_->{term} } @{ $data->{selected} };
260
        my $expr = sprintf "%s %s %s", reverse @elems;
261
        my $result = eval($expr); # the eval here has just been used for shortening the code,it could have very well been a simple switch on $elems[1]
262
 
263
        print "DEBUG [$expr]\n";
264
 
265
        insert_at
266
        $data->{insertIndex},
267
        {
268
                type    => 'NUMBER',
269
                term    => $result,
270
                priority=> $data->{maxPriority} - DEPTH_BONUS #we have calculated what was probably a paranthesis therefore we substrac a depth_bonus
271
        };
272
        <>;
273
};
274
 
275
 
276
my $result_out =$terms[0]->{term};
277
 
278
print "RESULT : $result_out \n";
279
 
280
 
281
 
282
    return($result_out);
283
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.